package reporter import ( "bytes" "encoding/json" "strings" "testing" "time" "github.com/claudomator/claudomator/internal/storage" ) func sampleExecutions() []*storage.Execution { now := time.Date(2026, 2, 8, 10, 0, 0, 0, time.UTC) return []*storage.Execution{ { ID: "exec-1", TaskID: "task-1", Status: "COMPLETED", StartTime: now, EndTime: now.Add(2 * time.Minute), ExitCode: 0, CostUSD: 0.25, }, { ID: "exec-2", TaskID: "task-2", Status: "FAILED", StartTime: now, EndTime: now.Add(30 * time.Second), ExitCode: 1, CostUSD: 0.10, ErrorMsg: "something broke", }, } } func TestConsoleReporter_WithExecutions(t *testing.T) { r := &ConsoleReporter{} var buf bytes.Buffer err := r.Generate(&buf, sampleExecutions()) if err != nil { t.Fatalf("unexpected error: %v", err) } output := buf.String() if !strings.Contains(output, "COMPLETED") { t.Error("missing COMPLETED status") } if !strings.Contains(output, "FAILED") { t.Error("missing FAILED status") } if !strings.Contains(output, "1 completed, 1 failed") { t.Errorf("missing summary in output: %s", output) } if !strings.Contains(output, "$0.3500") { t.Errorf("missing total cost in output: %s", output) } } func TestConsoleReporter_Empty(t *testing.T) { r := &ConsoleReporter{} var buf bytes.Buffer r.Generate(&buf, []*storage.Execution{}) if !strings.Contains(buf.String(), "No executions") { t.Error("expected 'No executions' message") } } func TestJSONReporter(t *testing.T) { r := &JSONReporter{Pretty: false} var buf bytes.Buffer err := r.Generate(&buf, sampleExecutions()) if err != nil { t.Fatal(err) } var result []storage.Execution if err := json.Unmarshal(buf.Bytes(), &result); err != nil { t.Fatalf("invalid JSON: %v", err) } if len(result) != 2 { t.Errorf("want 2 results, got %d", len(result)) } if result[0].Status != "COMPLETED" { t.Errorf("want COMPLETED, got %q", result[0].Status) } } func TestJSONReporter_Pretty(t *testing.T) { r := &JSONReporter{Pretty: true} var buf bytes.Buffer r.Generate(&buf, sampleExecutions()) if !strings.Contains(buf.String(), " ") { t.Error("expected indented JSON") } } func TestHTMLReporter(t *testing.T) { r := &HTMLReporter{} var buf bytes.Buffer err := r.Generate(&buf, sampleExecutions()) if err != nil { t.Fatal(err) } html := buf.String() if !strings.Contains(html, "") { t.Error("missing DOCTYPE") } if !strings.Contains(html, "Claudomator Report") { t.Error("missing title") } if !strings.Contains(html, "COMPLETED") { t.Error("missing COMPLETED status") } if !strings.Contains(html, "FAILED") { t.Error("missing FAILED status") } if !strings.Contains(html, "$0.3500") { t.Error("missing total cost") } }