diff options
Diffstat (limited to 'internal/handlers/heuristic_test.go')
| -rw-r--r-- | internal/handlers/heuristic_test.go | 152 |
1 files changed, 82 insertions, 70 deletions
diff --git a/internal/handlers/heuristic_test.go b/internal/handlers/heuristic_test.go index b03b664..82f4e90 100644 --- a/internal/handlers/heuristic_test.go +++ b/internal/handlers/heuristic_test.go @@ -1,97 +1,109 @@ 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) +func TestIsActionableList(t *testing.T) { + tests := []struct { + name string + listName string + want bool + }{ + {"doing list", "Doing", true}, + {"in progress", "In Progress", true}, + {"to do", "To Do", true}, + {"todo", "todo", true}, + {"tasks", "My Tasks", true}, + {"next", "Next Up", true}, + {"today", "Today", true}, + {"backlog", "Backlog", false}, + {"done", "Done", false}, + {"ideas", "Ideas", false}, } - 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) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isActionableList(tt.listName); got != tt.want { + t.Errorf("isActionableList(%q) = %v, want %v", tt.listName, got, tt.want) + } + }) } +} - // 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(), "migrations") - 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) +func TestFilterAndSortTrelloTasks(t *testing.T) { 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) + boards := []models.Board{ + { + ID: "b1", + Name: "Work Board", + Cards: []models.Card{ + {ID: "c1", Name: "Due Task", ListName: "Backlog", DueDate: &due, BoardName: "Work Board"}, + {ID: "c2", Name: "Doing Task", ListName: "Doing", BoardName: "Work Board"}, + {ID: "c3", Name: "Backlog Task", ListName: "Backlog", BoardName: "Work Board"}, + {ID: "c4", Name: "Todo Task", ListName: "To Do", BoardName: "Work Board"}, + }, + }, } - // Create Handler - h := NewTabsHandler(db, nil, "../../web/templates") + tasks := filterAndSortTrelloTasks(boards) - // Skip if templates are not loaded - if h.templates == nil { - t.Skip("Templates not available in test environment") + // Should have 3 tasks: c1 (has due date), c2 (Doing list), c4 (To Do list) + if len(tasks) != 3 { + t.Errorf("Expected 3 tasks, got %d", len(tasks)) } - req := httptest.NewRequest("GET", "/tabs/tasks", nil) - w := httptest.NewRecorder() - - // Execute - h.HandleTasks(w, req) + // Verify c3 (Backlog without due date) is not included + for _, task := range tasks { + if task.ID == "c3" { + t.Error("Backlog task without due date should not be included") + } + } - // Verify - resp := w.Body.String() + // Verify expected tasks are present + found := map[string]bool{} + for _, task := range tasks { + found[task.ID] = true + } - // Check for presence of expected tasks - if !strings.Contains(resp, "Due Task") { - t.Errorf("Expected 'Due Task' to be present") + if !found["c1"] { + t.Error("Expected c1 (Due Task) to be present") + } + if !found["c2"] { + t.Error("Expected c2 (Doing Task) to be present") } - if !strings.Contains(resp, "Doing Task") { - t.Errorf("Expected 'Doing Task' to be present") + if !found["c4"] { + t.Error("Expected c4 (Todo Task) to be present") } - if !strings.Contains(resp, "Todo Task") { - t.Errorf("Expected 'Todo Task' to be present") +} + +func TestAtomUrgencyTier(t *testing.T) { + now := time.Now() + yesterday := now.AddDate(0, 0, -1) + tomorrow := now.AddDate(0, 0, 1) + todayWithTime := time.Date(now.Year(), now.Month(), now.Day(), 14, 30, 0, 0, now.Location()) + todayMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) + + tests := []struct { + name string + atom models.Atom + want int + }{ + {"no due date", models.Atom{DueDate: nil}, 4}, + {"overdue", models.Atom{DueDate: &yesterday, IsOverdue: true}, 0}, + {"future", models.Atom{DueDate: &tomorrow, IsFuture: true}, 3}, + {"today with time", models.Atom{DueDate: &todayWithTime, HasSetTime: true}, 1}, + {"today all-day", models.Atom{DueDate: &todayMidnight, HasSetTime: false}, 2}, } - // Check for absence of non-expected tasks - if strings.Contains(resp, "Backlog Task") { - t.Errorf("Expected 'Backlog Task' to be ABSENT") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := atomUrgencyTier(tt.atom); got != tt.want { + t.Errorf("atomUrgencyTier() = %v, want %v", got, tt.want) + } + }) } } |
