summaryrefslogtreecommitdiff
path: root/internal/reporter/reporter_test.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-02-08 21:35:45 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-02-08 21:35:45 -1000
commit2e2b2187b957e9af78797a67ec5c6874615fae02 (patch)
tree1181dbb7e43f5d30cb025fa4d50fd4e7a2c893b3 /internal/reporter/reporter_test.go
Initial project: task model, executor, API server, CLI, storage, reporter
Claudomator automation toolkit for Claude Code with: - Task model with YAML parsing, validation, state machine (49 tests, 0 races) - SQLite storage for tasks and executions - Executor pool with bounded concurrency, timeout, cancellation - REST API + WebSocket for mobile PWA integration - Webhook/multi-notifier system - CLI: init, run, serve, list, status commands - Console, JSON, HTML reporters with cost tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/reporter/reporter_test.go')
-rw-r--r--internal/reporter/reporter_test.go114
1 files changed, 114 insertions, 0 deletions
diff --git a/internal/reporter/reporter_test.go b/internal/reporter/reporter_test.go
new file mode 100644
index 0000000..1ddce23
--- /dev/null
+++ b/internal/reporter/reporter_test.go
@@ -0,0 +1,114 @@
+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, "<!DOCTYPE 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")
+ }
+}