import { expect } from "@playwright/test"; import { test } from "../fixtures"; import { registerAndLogin, createMeal } from "../helpers"; test("meals are grouped under their category on the meals page", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Beef Stew", "", "Beef"); await createMeal(page, "Chicken Curry", "", "Chicken"); await createMeal(page, "Plain Rice", ""); await page.goto("/meals"); // Each category appears as a heading with its meals beneath it. const beef = page.locator(".category-group").filter({ hasText: "Beef" }); await expect(beef.locator(".category-heading")).toContainText("Beef"); await expect(beef.locator(".list-card").filter({ hasText: "Beef Stew" })).toBeVisible(); const chicken = page.locator(".category-group").filter({ hasText: "Chicken" }); await expect(chicken.locator(".list-card").filter({ hasText: "Chicken Curry" })).toBeVisible(); // Uncategorized meals land in their own group. const uncategorized = page.locator(".category-group").filter({ hasText: "Uncategorized" }); await expect(uncategorized.locator(".list-card").filter({ hasText: "Plain Rice" })).toBeVisible(); }); test("a user can create a meal category", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await page.goto("/meals"); await page.fill('form[action="/meals/categories"] input[name="name"]', "Breakfast"); await page.click('form[action="/meals/categories"] button[type="submit"]'); await expect(page).toHaveURL(/\/meals$/); await expect(page.locator(".meal-category-name").filter({ hasText: "Breakfast" })).toBeVisible(); }); test("a user can delete a meal category and its meals become uncategorized", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); // Create a custom category and a meal in it. await page.goto("/meals"); await page.fill('form[action="/meals/categories"] input[name="name"]', "Breakfast"); await page.click('form[action="/meals/categories"] button[type="submit"]'); await expect(page).toHaveURL(/\/meals$/); await createMeal(page, "Pancakes", "", "Breakfast"); // Delete the category. await page.goto("/meals"); const row = page.locator(".meal-category-row").filter({ hasText: "Breakfast" }); await row.locator(".meal-category-delete").click(); await expect(page).toHaveURL(/\/meals$/); // The category is gone and the meal is now uncategorized. await expect(page.locator(".meal-category-name").filter({ hasText: "Breakfast" })).toHaveCount(0); const uncategorized = page.locator(".category-group").filter({ hasText: "Uncategorized" }); await expect(uncategorized.locator(".list-card").filter({ hasText: "Pancakes" })).toBeVisible(); }); test("a user can change a meal's category via the edit modal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Beef Stew", "", "Beef"); await page.click('button:has-text("Edit")'); const dialog = page.locator("dialog#meal-edit-modal"); await expect(dialog).toBeVisible(); await dialog.locator("#meal-edit-category").selectOption({ label: "Chicken" }); await dialog.locator("#meal-edit-save").click(); await expect(page).toHaveURL(/\/meals\/\d+/); await page.goto("/meals"); const chicken = page.locator(".category-group").filter({ has: page.locator(".category-heading", { hasText: "Chicken" }), }); await expect(chicken.locator(".list-card").filter({ hasText: "Beef Stew" })).toBeVisible(); const beef = page.locator(".category-group").filter({ has: page.locator(".category-heading", { hasText: "Beef" }), }); await expect(beef.locator(".list-card").filter({ hasText: "Beef Stew" })).toHaveCount(0); }); test("a meal's category is shown on its page", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Beef Stew", "", "Beef"); await expect(page.locator(".meal-category-label")).toHaveText("(Beef)"); }); test("the add-meal picker groups meals by category", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Beef Stew", "", "Beef"); await createMeal(page, "Chicken Curry", "", "Chicken"); // Go to a list to open the picker. await page.goto("/lists"); await page.fill("#list-name", "Weekly shop"); await page.click('button:has-text("Create list")'); await expect(page).toHaveURL(/\/lists\/\d+/); await page.click(".add-meal-button"); const picker = page.locator(".meal-picker-backdrop"); await expect(picker).toBeVisible(); const beef = picker.locator(".category-group").filter({ hasText: "Beef" }); await expect(beef.locator(".meal-picker-button").filter({ hasText: "Beef Stew" })).toBeVisible(); const chicken = picker.locator(".category-group").filter({ hasText: "Chicken" }); await expect(chicken.locator(".meal-picker-button").filter({ hasText: "Chicken Curry" })).toBeVisible(); });