diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-08-14 08:12:29 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-08-14 08:12:29 +0000 |
| commit | b55cfbbd433bed6035dfa228ee700e2cca060ca4 (patch) | |
| tree | 53e9575785fdce504fa9ee1184dd057ed3fc7676 /internal/handlers/handlers_test.go | |
| parent | dcfb7204d654c98657b0638a569e8ec69bb5d852 (diff) | |
Fix integration papercuts found in cross-source review
getAtomDetails's gtasks case was a stub returning a hardcoded "Google
Task" title, so every gtask completed via the web Tasks/Timeline tab
or the Agent API logged into completed-tasks history with no real
title or due date -- now calls findGoogleTask like every other gtasks
call site already does. Gtasks completion also skipped cache
invalidation in two call sites (HandleCompleteAtom, the Agent API's
handleAgentTaskToggle) that already had it for trello; both now
invalidate CacheKeyGoogleTasks the same way the widget handlers do.
HandleTaskDetailPage (the widget deep-link fallback page) hand
-duplicated loadTaskDetailData's lookup instead of calling it, so it
never got this session's earlier gtasks-detail fix -- now delegates.
Also deleted PlanToEatAPI.GetRecipes, dead code since its introduction
("for Phase 2," never called).
Adds a running .agent/critiques.md tracking structural/process
critiques surfaced in conversation, separate from a concrete plan.
Diffstat (limited to 'internal/handlers/handlers_test.go')
| -rw-r--r-- | internal/handlers/handlers_test.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go index 8900f66..7b18cf1 100644 --- a/internal/handlers/handlers_test.go +++ b/internal/handlers/handlers_test.go @@ -2475,6 +2475,86 @@ func TestHandleCompleteAtom_DootShowsTitle(t *testing.T) { } } +func TestHandleCompleteAtom_Gtasks_LogsRealTitleAndInvalidatesCache(t *testing.T) { + h, cleanup := setupTestHandler(t) + defer cleanup() + + due := time.Now().Add(24 * time.Hour) + if err := h.store.SaveGoogleTasks([]models.GoogleTask{ + {ID: "g1", Title: "Renew passport", ListID: "list-a", DueDate: &due, UpdatedAt: time.Now()}, + }); err != nil { + t.Fatal(err) + } + if err := h.store.UpdateCacheMetadata(store.CacheKeyGoogleTasks, 60); err != nil { + t.Fatal(err) + } + h.googleTasksClient = &mockGoogleTasksClient{} + + req := httptest.NewRequest("POST", "/complete-atom", nil) + req.Form = map[string][]string{"id": {"g1"}, "source": {"gtasks"}, "listId": {"list-a"}} + w := httptest.NewRecorder() + h.HandleCompleteAtom(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200, body=%s", w.Code, w.Body.String()) + } + + completed, err := h.store.GetCompletedTasks(10) + if err != nil { + t.Fatal(err) + } + if len(completed) != 1 || completed[0].Title != "Renew passport" { + t.Errorf("completed log = %+v, want title %q (was hardcoded \"Google Task\" before the getAtomDetails fix)", completed, "Renew passport") + } + + meta, err := h.store.GetCacheMetadata(store.CacheKeyGoogleTasks) + if err != nil { + t.Fatal(err) + } + if meta != nil { + t.Error("expected gtasks cache metadata to be invalidated after completion, but it still exists") + } +} + +func TestHandleTaskDetailPage_GtasksSource_LoadsRealTaskFields(t *testing.T) { + h, cleanup := setupTestHandler(t) + defer cleanup() + + if err := h.store.SaveGoogleTasks([]models.GoogleTask{ + {ID: "g1", Title: "Renew passport", Notes: "bring photo", ListID: "list-a", UpdatedAt: time.Now()}, + }); err != nil { + t.Fatal(err) + } + + req := httptest.NewRequest("GET", "/task?id=g1&source=gtasks", nil) + w := httptest.NewRecorder() + h.HandleTaskDetailPage(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200, body=%s", w.Code, w.Body.String()) + } + + mock := h.renderer.(*MockRenderer) + if len(mock.Calls) != 1 { + t.Fatalf("expected 1 render call, got %d", len(mock.Calls)) + } + type pageData struct { + Title string + Description string + } + jsonBytes, _ := json.Marshal(mock.Calls[0].Data) + var got pageData + if err := json.Unmarshal(jsonBytes, &got); err != nil { + t.Fatalf("failed to unmarshal render data: %v", err) + } + if got.Title != "Renew passport" { + t.Errorf("Title = %q, want %q", got.Title, "Renew passport") + } + if got.Description != "bring photo" { + t.Errorf("Description = %q, want %q", got.Description, "bring photo") + } +} + func TestHandleTimeline_IncludesBudgetStatusWhenTrackedTaskExists(t *testing.T) { h, cleanup := setupTestHandler(t) defer cleanup() |
