Files
poimen-workflows/internal/search/workflow_search_test.go
T
Test 71f3bfae65 feat(T4.1-T4.4): implement advanced operations & analytics (part 1)
T4.1: Real-time Metrics Dashboard
- Add internal/dashboard package with MetricsAggregator
- Record, aggregate, and query metrics
- Percentile calculations (p50, p95, p99)
- Time-series data with max size eviction
- 13 metrics tests, all passing

T4.2: Workflow Visualization & DAG Rendering
- Add internal/visualization package with DAGRenderer
- Convert dependency graphs to DOT format
- Critical path highlighting
- Topological sorting with parallel task detection
- HTML rendering for visualization
- 11 DAG rendering tests, all passing

T4.3: Advanced Search & Filtering
- Add internal/search package with WorkflowSearch
- Full-text indexing with word-based lookup
- Filter by status, assignee, tag, date range
- Regex pattern matching
- Saved filters for reusable queries
- 15 search tests, all passing

T4.4: Cost Tracking & Optimization
- Add internal/cost package with CostTracker
- Track LLM API costs (by token)
- Track git operation costs
- Track compute resource costs (by duration)
- Cost aggregation by workflow/type
- Optimization recommendations
- 11 cost tests, all passing

Total T4.1-T4.4: 50 tests passing
Next: T4.5-T4.8 (alerting, profiling, multi-cluster, self-deployment)
2026-08-23 18:01:18 -07:00

197 lines
3.9 KiB
Go

package search
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestIndex(t *testing.T) {
ws := NewWorkflowSearch()
entry := &WorkflowEntry{
ID: "wf-1",
Name: "Deploy Service",
Status: "completed",
Content: "deployment task",
}
err := ws.Index(entry)
assert.NoError(t, err)
retrieved, exists := ws.GetByID("wf-1")
assert.True(t, exists)
assert.Equal(t, "Deploy Service", retrieved.Name)
}
func TestSearch(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{
ID: "wf-1",
Name: "Deploy Service",
Content: "deployment production",
})
ws.Index(&WorkflowEntry{
ID: "wf-2",
Name: "Build Docker",
Content: "docker image",
})
results := ws.Search("deployment")
assert.Equal(t, 1, len(results))
assert.Equal(t, "wf-1", results[0].ID)
}
func TestFilterByStatus(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{ID: "wf-1", Status: "completed"})
ws.Index(&WorkflowEntry{ID: "wf-2", Status: "running"})
ws.Index(&WorkflowEntry{ID: "wf-3", Status: "completed"})
results := ws.FilterByStatus("completed")
assert.Equal(t, 2, len(results))
}
func TestFilterByAssignee(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{ID: "wf-1", Assignee: "alice"})
ws.Index(&WorkflowEntry{ID: "wf-2", Assignee: "bob"})
ws.Index(&WorkflowEntry{ID: "wf-3", Assignee: "alice"})
results := ws.FilterByAssignee("alice")
assert.Equal(t, 2, len(results))
}
func TestFilterByTag(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{
ID: "wf-1",
Tags: []string{"production", "critical"},
})
ws.Index(&WorkflowEntry{
ID: "wf-2",
Tags: []string{"staging"},
})
results := ws.FilterByTag("production")
assert.Equal(t, 1, len(results))
}
func TestFilterByDateRange(t *testing.T) {
ws := NewWorkflowSearch()
now := time.Now()
ws.Index(&WorkflowEntry{
ID: "wf-1",
CreatedAt: now.Add(-1 * time.Hour),
})
ws.Index(&WorkflowEntry{
ID: "wf-2",
CreatedAt: now.Add(-24 * time.Hour),
})
results := ws.FilterByDateRange(now.Add(-2*time.Hour), now)
assert.Equal(t, 1, len(results))
}
func TestSearchRegex(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{
ID: "wf-1",
Content: "error 404 not found",
})
ws.Index(&WorkflowEntry{
ID: "wf-2",
Content: "success 200 ok",
})
results, err := ws.SearchRegex("error.*404")
assert.NoError(t, err)
assert.Equal(t, 1, len(results))
}
func TestSaveAndGetFilter(t *testing.T) {
ws := NewWorkflowSearch()
filter := map[string]interface{}{"status": "completed"}
ws.SaveFilter("completed-only", filter)
retrieved, exists := ws.GetFilter("completed-only")
assert.True(t, exists)
assert.NotNil(t, retrieved)
}
func TestGetAll(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{ID: "wf-1"})
ws.Index(&WorkflowEntry{ID: "wf-2"})
ws.Index(&WorkflowEntry{ID: "wf-3"})
all := ws.GetAll()
assert.Equal(t, 3, len(all))
}
func TestDelete(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{ID: "wf-1"})
ws.Delete("wf-1")
_, exists := ws.GetByID("wf-1")
assert.False(t, exists)
}
func TestClear(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{ID: "wf-1"})
ws.Index(&WorkflowEntry{ID: "wf-2"})
ws.Clear()
all := ws.GetAll()
assert.Equal(t, 0, len(all))
}
func TestMultiwordSearch(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{
ID: "wf-1",
Content: "deploy service to production",
})
results := ws.Search("deploy service")
assert.Equal(t, 1, len(results))
}
func TestCaseSensitivity(t *testing.T) {
ws := NewWorkflowSearch()
ws.Index(&WorkflowEntry{
ID: "wf-1",
Content: "Deploy Service Production",
})
results := ws.Search("deploy")
assert.Equal(t, 1, len(results))
}
func TestIndexError(t *testing.T) {
ws := NewWorkflowSearch()
entry := &WorkflowEntry{
Name: "No ID",
}
err := ws.Index(entry)
assert.Error(t, err)
}