From 143166ce759ce2cb0133b7438db36b844a9db1a7 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 18 Jan 2026 14:06:26 -1000 Subject: Implement Trello task heuristics for Tasks tab (Phase 3 Step 6) Add filtering logic to show Trello cards as actionable tasks when they have due dates OR are in lists named like "todo", "doing", "in progress", "tasks", "next", or "today". This makes the Tasks tab more useful by surfacing cards that represent work items even without explicit due dates. Co-Authored-By: Claude Opus 4.5 --- internal/handlers/heuristic_test.go | 97 +++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 internal/handlers/heuristic_test.go (limited to 'internal/handlers/heuristic_test.go') diff --git a/internal/handlers/heuristic_test.go b/internal/handlers/heuristic_test.go new file mode 100644 index 0000000..f76fdc0 --- /dev/null +++ b/internal/handlers/heuristic_test.go @@ -0,0 +1,97 @@ +package handlers + +import ( + "net/http/httptest" + "os" + "strings" + "testing" + "time" + + "task-dashboard/internal/models" + "task-dashboard/internal/store" +) + +func TestHandleTasks_Heuristic(t *testing.T) { + // Create temp database file + tmpFile, err := os.CreateTemp("", "test_heuristic_*.db") + if err != nil { + t.Fatalf("Failed to create temp db: %v", err) + } + tmpFile.Close() + defer os.Remove(tmpFile.Name()) + + // Save current directory and change to project root + originalDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get working directory: %v", err) + } + + // Change to project root (2 levels up from internal/handlers) + if err := os.Chdir("../../"); err != nil { + t.Fatalf("Failed to change to project root: %v", err) + } + defer os.Chdir(originalDir) + + // Initialize store (this runs migrations) + db, err := store.New(tmpFile.Name()) + if err != nil { + t.Fatalf("Failed to initialize store: %v", err) + } + defer db.Close() + + // Seed Data + // Board 1: Has actionable lists + board1 := models.Board{ID: "b1", Name: "Work Board"} + + // Card 1: Has Due Date (Should appear) + due := time.Now() + card1 := models.Card{ID: "c1", Name: "Due Task", ListID: "l1", ListName: "Backlog", DueDate: &due, BoardName: "Work Board"} + + // Card 2: No Due Date, Actionable List (Should appear) + card2 := models.Card{ID: "c2", Name: "Doing Task", ListID: "l2", ListName: "Doing", BoardName: "Work Board"} + + // Card 3: No Due Date, Non-Actionable List (Should NOT appear) + card3 := models.Card{ID: "c3", Name: "Backlog Task", ListID: "l1", ListName: "Backlog", BoardName: "Work Board"} + + // Card 4: No Due Date, "To Do" List (Should appear) + card4 := models.Card{ID: "c4", Name: "Todo Task", ListID: "l3", ListName: "To Do", BoardName: "Work Board"} + + board1.Cards = []models.Card{card1, card2, card3, card4} + + if err := db.SaveBoards([]models.Board{board1}); err != nil { + t.Fatalf("Failed to save boards: %v", err) + } + + // Create Handler + h := NewTabsHandler(db) + + // Skip if templates are not loaded + if h.templates == nil { + t.Skip("Templates not available in test environment") + } + + req := httptest.NewRequest("GET", "/tabs/tasks", nil) + w := httptest.NewRecorder() + + // Execute + h.HandleTasks(w, req) + + // Verify + resp := w.Body.String() + + // Check for presence of expected tasks + if !strings.Contains(resp, "Due Task") { + t.Errorf("Expected 'Due Task' to be present") + } + if !strings.Contains(resp, "Doing Task") { + t.Errorf("Expected 'Doing Task' to be present") + } + if !strings.Contains(resp, "Todo Task") { + t.Errorf("Expected 'Todo Task' to be present") + } + + // Check for absence of non-expected tasks + if strings.Contains(resp, "Backlog Task") { + t.Errorf("Expected 'Backlog Task' to be ABSENT") + } +} -- cgit v1.2.3