diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-25 20:04:03 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-25 20:04:03 -1000 |
| commit | fa95c71494458070b78270e3d9170076028fc974 (patch) | |
| tree | 5cb06c5e6962c9d46ee0e0dad106ff6cbf097730 /internal/handlers | |
| parent | 15ac2c98b554e43d287c136b3223d30b0af72b06 (diff) | |
Refactor: extract helpers and clean up hardcoded HTML
- Extract parseEventTime() and deduplicateEvents() in google_calendar.go
- Add scanTask() and scanTasks() SQL helpers in sqlite.go
- Move completed-atom HTML to partial template
- Add loadTestTemplates() test helper for template-dependent tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers')
| -rw-r--r-- | internal/handlers/handlers.go | 22 | ||||
| -rw-r--r-- | internal/handlers/handlers_test.go | 28 |
2 files changed, 34 insertions, 16 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index ee28a87..e0e185d 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -665,22 +665,12 @@ func (h *Handler) handleAtomToggle(w http.ResponseWriter, r *http.Request, compl } // Return completed task HTML with uncomplete option - completedHTML := fmt.Sprintf(`<div class="bg-white/5 rounded-lg border border-white/5 opacity-60"> - <div class="flex items-start gap-2 sm:gap-3 p-3 sm:p-4"> - <input type="checkbox" checked - hx-post="/uncomplete-atom" - hx-vals='{"id": "%s", "source": "%s"}' - hx-target="closest div.rounded-lg" - hx-swap="outerHTML" - class="mt-1 h-5 w-5 rounded bg-black/40 border-white/30 text-green-600 cursor-pointer flex-shrink-0"> - <span class="text-lg flex-shrink-0">✓</span> - <div class="flex-1 min-w-0"> - <h3 class="text-sm font-medium text-white/40 line-through break-words">%s</h3> - <div class="text-xs text-green-400/70 mt-1">Completed - click to undo</div> - </div> - </div> - </div>`, template.HTMLEscapeString(id), template.HTMLEscapeString(source), template.HTMLEscapeString(title)) - HTMLString(w, completedHTML) + data := struct { + ID string + Source string + Title string + }{id, source, title} + HTMLResponse(w, h.templates, "completed-atom", data) } else { // Invalidate cache to force refresh switch source { diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go index d14f71b..3658e0e 100644 --- a/internal/handlers/handlers_test.go +++ b/internal/handlers/handlers_test.go @@ -3,9 +3,11 @@ package handlers import ( "context" "encoding/json" + "html/template" "net/http" "net/http/httptest" "os" + "path/filepath" "testing" "time" @@ -58,6 +60,30 @@ func setupTestDB(t *testing.T) (*store.Store, func()) { return db, cleanup } +// loadTestTemplates loads templates for testing from project root +func loadTestTemplates(t *testing.T) *template.Template { + t.Helper() + + // Get path relative to project root + tmpl, err := template.ParseGlob(filepath.Join("web", "templates", "*.html")) + if err != nil { + // Try from internal/handlers (2 levels up) + tmpl, err = template.ParseGlob(filepath.Join("..", "..", "web", "templates", "*.html")) + if err != nil { + t.Logf("Warning: failed to parse templates: %v", err) + return nil + } + } + + // Parse partials + tmpl, err = tmpl.ParseGlob(filepath.Join("web", "templates", "partials", "*.html")) + if err != nil { + tmpl, _ = tmpl.ParseGlob(filepath.Join("..", "..", "web", "templates", "partials", "*.html")) + } + + return tmpl +} + // mockTodoistClient creates a mock Todoist client for testing type mockTodoistClient struct { tasks []models.Task @@ -457,6 +483,7 @@ func TestHandleCompleteAtom_Todoist(t *testing.T) { store: db, todoistClient: mockTodoist, config: &config.Config{}, + templates: loadTestTemplates(t), } // Create request @@ -523,6 +550,7 @@ func TestHandleCompleteAtom_Trello(t *testing.T) { store: db, trelloClient: mockTrello, config: &config.Config{}, + templates: loadTestTemplates(t), } // Create request |
