From 2e2b2187b957e9af78797a67ec5c6874615fae02 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 8 Feb 2026 21:35:45 -1000 Subject: 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 --- internal/notify/notify_test.go | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 internal/notify/notify_test.go (limited to 'internal/notify/notify_test.go') diff --git a/internal/notify/notify_test.go b/internal/notify/notify_test.go new file mode 100644 index 0000000..fcb5345 --- /dev/null +++ b/internal/notify/notify_test.go @@ -0,0 +1,86 @@ +package notify + +import ( + "encoding/json" + "io" + "log/slog" + "net/http" + "net/http/httptest" + "os" + "testing" +) + +func TestWebhookNotifier_Success(t *testing.T) { + var received Event + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, _ := io.ReadAll(r.Body) + json.Unmarshal(body, &received) + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})) + notifier := NewWebhookNotifier(server.URL, logger) + + event := Event{ + TaskID: "t-1", + TaskName: "Test", + Status: "COMPLETED", + CostUSD: 0.50, + Duration: "2m30s", + } + + if err := notifier.Notify(event); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if received.TaskID != "t-1" { + t.Errorf("task_id: want 't-1', got %q", received.TaskID) + } + if received.CostUSD != 0.50 { + t.Errorf("cost: want 0.50, got %f", received.CostUSD) + } +} + +func TestWebhookNotifier_ServerError(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + defer server.Close() + + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})) + notifier := NewWebhookNotifier(server.URL, logger) + + err := notifier.Notify(Event{TaskID: "t-1", Status: "COMPLETED"}) + if err == nil { + t.Fatal("expected error for 500 response") + } +} + +func TestMultiNotifier_FansOut(t *testing.T) { + var count int + counter := &countingNotifier{count: &count} + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})) + multi := NewMultiNotifier(logger, counter, counter, counter) + + multi.Notify(Event{TaskID: "t-1"}) + if count != 3 { + t.Errorf("want 3 notifications, got %d", count) + } +} + +func TestLogNotifier_NoError(t *testing.T) { + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})) + notifier := &LogNotifier{Logger: logger} + if err := notifier.Notify(Event{TaskID: "t-1", Status: "COMPLETED"}); err != nil { + t.Errorf("unexpected error: %v", err) + } +} + +type countingNotifier struct { + count *int +} + +func (c *countingNotifier) Notify(_ Event) error { + *c.count++ + return nil +} -- cgit v1.2.3