import { expect, type Page, test } from "@playwright/test"; import { captureScreenshot, completeOnboarding, openUserSettings, signup } from "./helpers"; async function useAppearance(page: Page, appearance: "light" | "dark") { const settings = await openUserSettings(page); await settings.getByTestId(`ui-appearance-${appearance}`).click(); await expect(page.locator("html")).toHaveAttribute("data-theme", appearance); await settings.getByRole("button", { name: "Close user settings" }).click(); await expect(settings).toBeHidden(); } test("a recipe card scales its ingredients and cooks step by step", async ({ page }, testInfo) => { const stamp = Date.now(); await signup(page, `recipe-card-${stamp}@rakazo.test`, "password12", "Recipe Card"); await completeOnboarding(page); await page.getByPlaceholder(/Message/).fill("Give me a pancake recipe."); await page.keyboard.press("Enter"); const card = page.getByTestId("thread-card"); await expect(card).toBeVisible({ timeout: 60_000 }); await expect(card).toContainText("200 g"); await expect(card).toContainText("1 Egg"); await card.getByRole("button", { name: "More Servings" }).click(); await expect(card.getByTestId("card-stepper-value")).toHaveText("3"); await expect(card).toContainText("300 g"); await expect(card).toContainText("1½ Eggs"); await expect(card).toContainText("450 ml"); await useAppearance(page, "light"); await card.scrollIntoViewIfNeeded(); await captureScreenshot(page, testInfo, "recipe-card-light"); await useAppearance(page, "dark"); await card.scrollIntoViewIfNeeded(); await captureScreenshot(page, testInfo, "recipe-card-dark"); await card.getByRole("button", { name: "Cook" }).click(); const cooking = page.getByTestId("cooking-mode"); await expect(cooking).toContainText("Step 1 of 3"); await cooking.getByRole("button", { name: "Next" }).click(); await expect(cooking).toContainText("Step 2 of 3"); await expect(cooking).toContainText("Let the batter rest."); await cooking.getByRole("button", { name: "Start timer" }).click(); await expect(cooking.getByRole("button", { name: "Stop timer" })).toContainText(/9:5\d/, { timeout: 10_000, }); await captureScreenshot(page, testInfo, "cooking-mode-dark"); await closeCookingMode(page); await useAppearance(page, "light"); await card.getByRole("button", { name: "Cook" }).click(); await expect(cooking).toContainText("Step 2 of 3"); await captureScreenshot(page, testInfo, "cooking-mode-light"); await closeCookingMode(page); // Servings, step and timer are stored on the card, so a reload keeps them. await page.reload({ waitUntil: "domcontentloaded" }); const reloaded = page.getByTestId("thread-card"); await expect(reloaded.getByTestId("card-stepper-value")).toHaveText("3", { timeout: 30_000 }); await expect(reloaded).toContainText(/9:[45]\d/); await reloaded.getByRole("button", { name: "Cook" }).click(); await expect(page.getByTestId("cooking-mode")).toContainText("Step 2 of 3"); await expect( page.getByTestId("cooking-mode").getByRole("button", { name: "Stop timer" }), ).toBeVisible(); }); async function closeCookingMode(page: Page) { await page.keyboard.press("Escape"); await expect(page.getByTestId("cooking-mode")).toBeHidden(); }