diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-07-12 10:34:34 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-07-12 10:34:34 +0000 |
| commit | dfb06e896b92003d219979cbb1476ed16b7734a3 (patch) | |
| tree | e8ff6a8ad2e73172a6b352dfe9a12094ee2c27ef /internal/handlers | |
| parent | e1e632c1e57c8aa0940e7ff566a1c7ab267625c8 (diff) | |
feat(widget): add POST /api/widget/add for quick-add
Diffstat (limited to 'internal/handlers')
| -rw-r--r-- | internal/handlers/widget.go | 31 | ||||
| -rw-r--r-- | internal/handlers/widget_test.go | 60 |
2 files changed, 91 insertions, 0 deletions
diff --git a/internal/handlers/widget.go b/internal/handlers/widget.go index 3a30fcf..0c88c16 100644 --- a/internal/handlers/widget.go +++ b/internal/handlers/widget.go @@ -124,6 +124,10 @@ type widgetCompleteRequest struct { Source string `json:"source"` } +type widgetAddRequest struct { + Title string `json:"title"` +} + type widgetRescheduleRequest struct { ID string `json:"id"` Source string `json:"source"` @@ -189,3 +193,30 @@ func (h *Handler) HandleWidgetComplete(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } + +// HandleWidgetAdd creates a new undated native task from the widget's quick-add sheet. +func (h *Handler) HandleWidgetAdd(w http.ResponseWriter, r *http.Request) { + var req widgetAddRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + + title := strings.TrimSpace(req.Title) + if title == "" { + http.Error(w, "title is required", http.StatusBadRequest) + return + } + + task := models.Task{ + ID: newID(), + Content: title, + Priority: 1, + } + if err := h.store.CreateNativeTask(task); err != nil { + http.Error(w, "failed to create task", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} diff --git a/internal/handlers/widget_test.go b/internal/handlers/widget_test.go index 14dd396..e4a1d16 100644 --- a/internal/handlers/widget_test.go +++ b/internal/handlers/widget_test.go @@ -313,6 +313,66 @@ func TestHandleWidgetComplete_UnknownID_Returns404(t *testing.T) { } } +// TestHandleWidgetAdd_CreatesTask proves the quick-add feature: POSTing a +// title to /api/widget/add creates an undated native task the same way the +// web UI's HandleUnifiedAdd does, but via the widget's bearer-token JSON +// API instead of a session-authenticated HTML form. +func TestHandleWidgetAdd_CreatesTask(t *testing.T) { + s, cleanup := setupTestDB(t) + defer cleanup() + h := &Handler{store: s} + body := `{"title":"Buy milk"}` + req := httptest.NewRequest("POST", "/api/widget/add", strings.NewReader(body)) + w := httptest.NewRecorder() + http.HandlerFunc(h.HandleWidgetAdd).ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("expected 200, got %d", w.Code) + } + + tasks, err := s.GetUndatedNativeTasks() + if err != nil { + t.Fatalf("failed to read back tasks: %v", err) + } + found := false + for _, task := range tasks { + if task.Content == "Buy milk" { + found = true + } + } + if !found { + t.Error("expected a task with content 'Buy milk' to have been created") + } +} + +func TestHandleWidgetAdd_EmptyTitle_Returns400(t *testing.T) { + s, cleanup := setupTestDB(t) + defer cleanup() + h := &Handler{store: s} + body := `{"title":""}` + req := httptest.NewRequest("POST", "/api/widget/add", strings.NewReader(body)) + w := httptest.NewRecorder() + http.HandlerFunc(h.HandleWidgetAdd).ServeHTTP(w, req) + + if w.Code != http.StatusBadRequest { + t.Fatalf("expected 400, got %d", w.Code) + } +} + +func TestHandleWidgetAdd_WhitespaceOnlyTitle_Returns400(t *testing.T) { + s, cleanup := setupTestDB(t) + defer cleanup() + h := &Handler{store: s} + body := `{"title":" "}` + req := httptest.NewRequest("POST", "/api/widget/add", strings.NewReader(body)) + w := httptest.NewRecorder() + http.HandlerFunc(h.HandleWidgetAdd).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 := WidgetAuthMiddleware("", inner) |
