summaryrefslogtreecommitdiff
path: root/internal/handlers/widget_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handlers/widget_test.go')
-rw-r--r--internal/handlers/widget_test.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/internal/handlers/widget_test.go b/internal/handlers/widget_test.go
new file mode 100644
index 0000000..a82a070
--- /dev/null
+++ b/internal/handlers/widget_test.go
@@ -0,0 +1,127 @@
+package handlers_test
+
+import (
+ "encoding/json"
+ "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)
+ }
+}
+
+// Ensure json import is used (WidgetResponse roundtrip sanity check).
+var _ = json.Marshal