import { expect } from "@playwright/test"; import { test } from "../fixtures"; import { registerAndLogin, createMeal, addIngredient } from "../helpers"; test("a user can add an ingredient to a meal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", ""); await addIngredient(page, "Penne", "500g"); const row = page.locator(".ingredient-list").filter({ hasText: "Penne" }); await expect(row.locator(".item-qty")).toHaveText("(500g)"); await expect(row.locator("strong")).toHaveText("Penne"); }); test("a user can edit a meal name and description via the modal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", "A classic."); await page.click('button:has-text("Edit")'); const dialog = page.locator("dialog#meal-edit-modal"); await expect(dialog).toBeVisible(); await dialog.locator("#meal-edit-name").fill("Pasta al Pomodoro"); await dialog.locator("#meal-edit-description").fill("## Ingredients\n\nA simple tomato sauce."); await dialog.locator("#meal-edit-save").click(); await expect(page.locator("h1")).toContainText("Pasta al Pomodoro"); await expect(page.locator(".markdown h2")).toContainText("Ingredients"); }); test("a user can delete a meal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", ""); page.on("dialog", (dialog) => dialog.accept()); await page.click('button:has-text("Delete")'); await expect(page).toHaveURL(/\/meals$/); await expect(page.locator(".list-card").filter({ hasText: "Spaghetti Bolognese" })).toHaveCount(0); }); test("a user can edit an ingredient via the actions modal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", ""); await addIngredient(page, "Penne", "500g"); const row = page.locator(".ingredient-list").filter({ hasText: "Penne" }); await row.locator(".item-actions-button").click(); const dialog = row.locator("dialog.item-modal"); await expect(dialog).toBeVisible(); await dialog.locator('[id^="ingredient-edit-name"]').fill("Rigatoni"); await dialog.locator('[id^="ingredient-edit-quantity"]').fill("400g"); await dialog.locator('[id^="ingredient-edit-save"]').click(); const updated = page.locator(".ingredient-list").filter({ hasText: "Rigatoni" }); await expect(updated).toBeVisible(); await expect(updated.locator(".item-qty")).toHaveText("(400g)"); }); test("a user can delete an ingredient via the actions modal", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", ""); await addIngredient(page, "Penne"); const row = page.locator(".ingredient-list").filter({ hasText: "Penne" }); await row.locator(".item-actions-button").click(); const dialog = row.locator("dialog.item-modal"); await expect(dialog).toBeVisible(); await dialog.locator('[id^="ingredient-edit-delete"]').click(); await expect(page.locator(".ingredient-list").filter({ hasText: "Penne" })).toHaveCount(0); }); test("ingredients are grouped under their categories", async ({ page }) => { await registerAndLogin(page, "alice@example.com"); await createMeal(page, "Spaghetti Bolognese", ""); // Add an ingredient in the default "Produce" category. await page.fill("#ingredient-name", "Tomato"); await page.selectOption("#ingredient-category", { label: "Produce" }); await page.click("#add-ingredient-button"); // Add one without a category. await addIngredient(page, "Penne"); await expect(page.locator(".category-heading").filter({ hasText: "Produce" })).toBeVisible(); await expect(page.locator(".category-heading").filter({ hasText: "Uncategorized" })).toBeVisible(); });