summaryrefslogtreecommitdiff
path: root/internal/handlers/handlers_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handlers/handlers_test.go')
-rw-r--r--internal/handlers/handlers_test.go271
1 files changed, 12 insertions, 259 deletions
diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go
index ca24778..61fb75d 100644
--- a/internal/handlers/handlers_test.go
+++ b/internal/handlers/handlers_test.go
@@ -819,169 +819,6 @@ func TestShoppingComplete_ExternalItemMarkedChecked(t *testing.T) {
}
}
-// TestShoppingToggle_UpdatesItemState verifies toggle correctly updates state
-func TestShoppingToggle_UpdatesItemState(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
- h := &Handler{
- store: db,
- renderer: newTestRenderer(),
- config: &config.Config{},
- }
-
- // Add user item
- _ = db.SaveUserShoppingItem("Toggle Item", "TestStore")
- items, _ := db.GetUserShoppingItems()
- itemID := items[0].ID
-
- // Toggle to checked
- req := httptest.NewRequest("POST", "/shopping/toggle", nil)
- req.Form = map[string][]string{
- "id": {fmt.Sprintf("user-%d", itemID)},
- "source": {"user"},
- "checked": {"true"},
- }
- w := httptest.NewRecorder()
- h.HandleShoppingToggle(w, req)
-
- if w.Code != http.StatusOK {
- t.Errorf("Expected status 200, got %d", w.Code)
- }
-
- // Verify item is checked
- items, _ = db.GetUserShoppingItems()
- if !items[0].Checked {
- t.Error("Expected item to be checked after toggle")
- }
-
- // Toggle back to unchecked
- req = httptest.NewRequest("POST", "/shopping/toggle", nil)
- req.Form = map[string][]string{
- "id": {fmt.Sprintf("user-%d", itemID)},
- "source": {"user"},
- "checked": {"false"},
- }
- w = httptest.NewRecorder()
- h.HandleShoppingToggle(w, req)
-
- items, _ = db.GetUserShoppingItems()
- if items[0].Checked {
- t.Error("Expected item to be unchecked after second toggle")
- }
-}
-
-// TestShoppingToggle_ExternalSources verifies toggle works for external sources
-func TestShoppingToggle_ExternalSources(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
- h := &Handler{
- store: db,
- renderer: newTestRenderer(),
- config: &config.Config{},
- }
-
- tests := []struct {
- source string
- itemID string
- }{
- {"trello", "trello-toggle-123"},
- {"plantoeat", "pte-toggle-456"},
- }
-
- for _, tc := range tests {
- t.Run(tc.source, func(t *testing.T) {
- // Toggle to checked
- req := httptest.NewRequest("POST", "/shopping/toggle", nil)
- req.Form = map[string][]string{
- "id": {tc.itemID},
- "source": {tc.source},
- "checked": {"true"},
- }
- w := httptest.NewRecorder()
- h.HandleShoppingToggle(w, req)
-
- if w.Code != http.StatusOK {
- t.Errorf("Expected status 200, got %d", w.Code)
- }
-
- checks, _ := db.GetShoppingItemChecks(tc.source)
- if !checks[tc.itemID] {
- t.Errorf("Expected %s item to be checked", tc.source)
- }
- })
- }
-}
-
-// TestShoppingToggle_UnknownSource verifies error for unknown source
-func TestShoppingToggle_UnknownSource(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
- h := &Handler{
- store: db,
- config: &config.Config{},
- }
-
- req := httptest.NewRequest("POST", "/shopping/toggle", nil)
- req.Form = map[string][]string{
- "id": {"unknown-123"},
- "source": {"unknown"},
- "checked": {"true"},
- }
- w := httptest.NewRecorder()
- h.HandleShoppingToggle(w, req)
-
- if w.Code != http.StatusBadRequest {
- t.Errorf("Expected status 400 for unknown source, got %d", w.Code)
- }
-}
-
-// TestShoppingModeToggle_ReturnsUpdatedList verifies shopping mode toggle returns items
-func TestShoppingModeToggle_ReturnsUpdatedList(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
- h := &Handler{
- store: db,
- renderer: newTestRenderer(),
- config: &config.Config{},
- }
-
- // Add items
- _ = db.SaveUserShoppingItem("Item 1", "TestStore")
- _ = db.SaveUserShoppingItem("Item 2", "TestStore")
-
- items, _ := db.GetUserShoppingItems()
- itemID := items[0].ID
-
- // Toggle in shopping mode
- req := httptest.NewRequest("POST", "/shopping/mode/TestStore/toggle", nil)
- req.Form = map[string][]string{
- "id": {fmt.Sprintf("user-%d", itemID)},
- "source": {"user"},
- "checked": {"true"},
- }
-
- rctx := chi.NewRouteContext()
- rctx.URLParams.Add("store", "TestStore")
- req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
-
- w := httptest.NewRecorder()
- h.HandleShoppingModeToggle(w, req)
-
- if w.Code != http.StatusOK {
- t.Errorf("Expected status 200, got %d", w.Code)
- }
-
- // Response should be HTML (items list)
- contentType := w.Header().Get("Content-Type")
- if !strings.Contains(contentType, "text/html") {
- t.Errorf("Expected HTML response, got %s", contentType)
- }
-}
-
// TestShoppingTabFiltersCheckedItems verifies checked items excluded from tab
func TestShoppingTabFiltersCheckedItems(t *testing.T) {
db, cleanup := setupTestDB(t)
@@ -1057,26 +894,6 @@ func TestHandleTabTasks(t *testing.T) {
}
}
-func TestHandleTabMeals(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
- h := &Handler{
- store: db,
- renderer: newTestRenderer(),
- config: &config.Config{CacheTTLMinutes: 5},
- }
-
- req := httptest.NewRequest("GET", "/tabs/meals", nil)
- w := httptest.NewRecorder()
-
- h.HandleTabMeals(w, req)
-
- if w.Code != http.StatusOK {
- t.Errorf("Expected status 200, got %d", w.Code)
- }
-}
-
func TestHandleTabPlanning(t *testing.T) {
db, cleanup := setupTestDB(t)
defer cleanup()
@@ -2120,35 +1937,6 @@ func TestHandleSetTaskRecurrence_InvalidFreq_Returns400(t *testing.T) {
}
}
-// =============================================================================
-// HandleGetListsOptions template tests
-// =============================================================================
-
-// TestHandleGetListsOptions_RendersTemplate verifies that HandleGetListsOptions uses
-// the renderer with the "lists-options" template.
-func TestHandleGetListsOptions_RendersTemplate(t *testing.T) {
- h, cleanup := setupTestHandler(t)
- defer cleanup()
-
- h.trelloClient = &mockTrelloClient{boards: []models.Board{}}
-
- req := httptest.NewRequest("GET", "/trello/lists?board_id=board1", nil)
- w := httptest.NewRecorder()
- h.HandleGetListsOptions(w, req)
-
- mr := h.renderer.(*MockRenderer)
- var found bool
- for _, call := range mr.Calls {
- if call.Name == "lists-options" {
- found = true
- break
- }
- }
- if !found {
- t.Error("Expected renderer to be called with 'lists-options' template")
- }
-}
-
// TestHandleSyncSources_AddsLogEntry verifies that syncing sources creates a sync log entry.
func TestHandleSyncSources_AddsLogEntry(t *testing.T) {
h, cleanup := setupTestHandler(t)
@@ -2339,67 +2127,32 @@ func TestHandleTabPlanning_TomorrowBoundary(t *testing.T) {
}
// =============================================================================
-// HandleTabMeals grouping test
+// groupMeals grouping test
// =============================================================================
-// TestHandleTabMeals_GroupingMergesRecipes verifies that multiple meals sharing
-// the same date+mealType are combined into a single CombinedMeal entry whose
-// RecipeNames contains all merged recipe names.
-func TestHandleTabMeals_GroupingMergesRecipes(t *testing.T) {
- db, cleanup := setupTestDB(t)
- defer cleanup()
-
+// TestGroupMeals_MergesRecipes verifies that multiple meals sharing the same
+// date+mealType are combined into a single CombinedMeal entry whose
+// RecipeNames contains all merged recipe names. groupMeals is still live
+// logic used by the timeline (see timeline_logic.go).
+func TestGroupMeals_MergesRecipes(t *testing.T) {
today := config.Today()
meals := []models.Meal{
{ID: "m1", RecipeName: "Pasta", Date: today, MealType: "dinner", RecipeURL: "http://example.com/pasta"},
{ID: "m2", RecipeName: "Salad", Date: today, MealType: "dinner", RecipeURL: "http://example.com/salad"},
{ID: "m3", RecipeName: "Oatmeal", Date: today, MealType: "breakfast", RecipeURL: "http://example.com/oatmeal"},
}
- if err := db.SaveMeals(meals); err != nil {
- t.Fatalf("Failed to save meals: %v", err)
- }
- renderer := NewMockRenderer()
- h := &Handler{
- store: db,
- renderer: renderer,
- config: &config.Config{CacheTTLMinutes: 5},
- }
-
- req := httptest.NewRequest("GET", "/tabs/meals", nil)
- w := httptest.NewRecorder()
- h.HandleTabMeals(w, req)
-
- if w.Code != http.StatusOK {
- t.Errorf("Expected 200, got %d", w.Code)
- }
-
- var mealsCall *RenderCall
- for i, call := range renderer.Calls {
- if call.Name == "meals-tab" {
- c := renderer.Calls[i]
- mealsCall = &c
- break
- }
- }
- if mealsCall == nil {
- t.Fatal("Expected meals-tab to be rendered")
- }
-
- data, ok := mealsCall.Data.(struct{ Meals []CombinedMeal })
- if !ok {
- t.Fatalf("Expected meals data struct, got %T", mealsCall.Data)
- }
+ combined := groupMeals(meals)
// m1 + m2 share date+dinner → 1 CombinedMeal; m3 is breakfast → 1 CombinedMeal
- if len(data.Meals) != 2 {
- t.Errorf("Expected 2 combined meals, got %d", len(data.Meals))
+ if len(combined) != 2 {
+ t.Errorf("Expected 2 combined meals, got %d", len(combined))
}
var dinner *CombinedMeal
- for i := range data.Meals {
- if data.Meals[i].MealType == "dinner" {
- dinner = &data.Meals[i]
+ for i := range combined {
+ if combined[i].MealType == "dinner" {
+ dinner = &combined[i]
break
}
}