package handlers_test import ( "net/http" "net/http/httptest" "strings" "testing" "time" "task-dashboard/internal/handlers" "task-dashboard/internal/models" ) func TestWidgetAuthMiddleware_NoToken(t *testing.T) { called := false inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true }) h := handlers.WidgetAuthMiddleware("secret", inner) req := httptest.NewRequest("GET", "/api/widget", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected 401, got %d", w.Code) } if called { t.Fatal("inner handler should not have been called") } } func TestWidgetAuthMiddleware_WrongToken(t *testing.T) { inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) h := handlers.WidgetAuthMiddleware("secret", inner) req := httptest.NewRequest("GET", "/api/widget", nil) req.Header.Set("Authorization", "Bearer wrong") w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected 401, got %d", w.Code) } } func TestWidgetAuthMiddleware_CorrectToken(t *testing.T) { called := false inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true }) h := handlers.WidgetAuthMiddleware("secret", inner) req := httptest.NewRequest("GET", "/api/widget", nil) req.Header.Set("Authorization", "Bearer secret") w := httptest.NewRecorder() h.ServeHTTP(w, req) if !called { t.Fatal("inner handler should have been called") } } func TestTimelineItemToWidgetItem_Task(t *testing.T) { now := time.Now() item := models.TimelineItem{ ID: "abc", Title: "Write notes", Source: "todoist", Type: models.TimelineItemTypeTask, Time: now, IsAllDay: true, URL: "https://todoist.com/task/abc", } wi := handlers.TimelineItemToWidgetItem(item) if wi.ID != "abc" { t.Errorf("ID: got %q, want %q", wi.ID, "abc") } if wi.Type != "task" { t.Errorf("Type: got %q, want %q", wi.Type, "task") } if !wi.Completable { t.Error("todoist task should be completable") } if wi.Start != nil { t.Error("all-day item should have nil Start") } } func TestTimelineItemToWidgetItem_Event(t *testing.T) { start := time.Now() end := start.Add(time.Hour) item := models.TimelineItem{ ID: "cal1", Title: "Team sync", Source: "calendar", Type: models.TimelineItemTypeEvent, Time: start, EndTime: &end, } wi := handlers.TimelineItemToWidgetItem(item) if wi.Type != "event" { t.Errorf("Type: got %q, want %q", wi.Type, "event") } if wi.Completable { t.Error("calendar event should not be completable") } if wi.Start == nil { t.Error("timed event should have non-nil Start") } } func TestHandleWidgetComplete_NonTodoist(t *testing.T) { h := handlers.HandleWidgetComplete(nil) body := `{"id":"x","source":"calendar"}` req := httptest.NewRequest("POST", "/api/widget/complete", strings.NewReader(body)) w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("expected 400, got %d", w.Code) } } func TestWidgetAuthMiddleware_EmptyToken(t *testing.T) { inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) h := handlers.WidgetAuthMiddleware("", inner) req := httptest.NewRequest("GET", "/api/widget", nil) req.Header.Set("Authorization", "Bearer ") w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected 401 with empty token, got %d", w.Code) } }