import { test, expect } from "@playwright/test"; import AxeBuilder from "@axe-core/playwright"; const product = "/product/the-original-salted-egg-cornflakes-clan"; test("bag quantities, subtotal, persistence and removal", async ({ page }) => { await page.goto("/"); await page .getByRole("button", { name: "Quick add The Original Salted Egg Cornflakes 180g", exact: true, }) .click(); let dialog = page.getByRole("dialog"); await expect(dialog).toBeVisible(); await expect(dialog).toContainText("RM 17.90"); await dialog .getByRole("button", { name: "Increase The Original Salted Egg Cornflakes", }) .click(); await expect(dialog).toContainText("RM 35.80"); await page.keyboard.press("Escape"); await page.reload(); await page.getByRole("button", { name: "Open shopping bag (2)" }).click(); await expect(dialog).toContainText("RM 35.80"); await dialog.getByRole("link", { name: "View your bag" }).click(); await expect(page).toHaveURL("/cart"); await page .getByRole("button", { name: "Remove The Original Salted Egg Cornflakes", exact: true, }) .click(); await expect( page.getByRole("heading", { name: "Your cart is empty" }), ).toBeVisible(); }); test("wishlist persists and can be removed", async ({ page }) => { await page.goto("/"); await page .getByRole("button", { name: "Save The Original Salted Egg Cornflakes to wishlist", exact: true, }) .click(); await page.goto("/wishlist"); await expect(page.locator(".product-card")).toHaveCount(1); await page .getByRole("button", { name: "Remove The Original Salted Egg Cornflakes from wishlist", exact: true, }) .click(); await expect( page.getByRole("heading", { name: "A little room for favourites" }), ).toBeVisible(); }); test("filters, sorting, load more and no results", async ({ page }) => { await page.goto("/shop"); await expect(page.locator(".product-card")).toHaveCount(12); await page.getByRole("button", { name: "LOAD MORE" }).click(); await expect(page.locator(".product-card")).toHaveCount(13); await page.getByRole("button", { name: "Tempeh chips", exact: true }).click(); await expect(page.locator(".product-card")).toHaveCount(2); await page.getByRole("button", { name: "All snacks", exact: true }).click(); await page.getByLabel("Sort by").selectOption("low"); await expect(page.locator(".product-card").first()).toContainText("RM 3.50"); await page .getByRole("searchbox", { name: "Search products" }) .fill("nothingmatches"); await expect( page.getByRole("heading", { name: "No snacks found" }), ).toBeVisible(); await page.getByRole("button", { name: "Clear filters" }).click(); await expect(page.locator(".result-count")).toContainText("13 snacks"); }); test("search returns products and journal articles and restores focus", async ({ page, }) => { await page.goto("/"); const trigger = page.getByRole("button", { name: "Search", exact: true }); await trigger.click(); const search = page.getByRole("searchbox", { name: "Search snacks, collections and stories", }); await search.fill("mushroom"); await expect(page.locator(".search-results>a")).toHaveCount(3); await search.fill("Mauritius"); await expect( page.getByRole("link", { name: "Journal: Mauritius, We’ve Arrived" }), ).toBeVisible(); await page.keyboard.press("Escape"); await expect(trigger).toBeFocused(); await trigger.click(); await page.getByRole("searchbox").fill("tempeh"); await page.getByRole("button", { name: "View all search results" }).click(); await expect(page).toHaveURL("/shop?q=tempeh"); await expect(page.locator(".product-card")).toHaveCount(2); }); test("gallery, quantity, alternate packs and checkout preview", async ({ page, }) => { await page.goto(product); await page .getByRole("button", { name: "View product image 2", exact: true }) .click(); await expect(page.locator(".gallery-main img")).toHaveAttribute( "src", "/images/snack-23-1.webp", ); await page.getByRole("button", { name: "Zoom product image" }).click(); await expect(page.getByRole("dialog")).toBeVisible(); await page.keyboard.press("Escape"); await page.getByRole("button", { name: "Increase Quantity" }).click(); await page.getByRole("button", { name: "BUY NOW" }).click(); await expect(page).toHaveURL("/checkout"); await expect(page.locator(".checkout-layout")).toContainText("RM 35.80"); await expect(page.getByRole("radio", { name: /Credit \/ debit card/ })).toBeChecked(); await expect(page.locator(".checkout-order-summary .checkout-subtotal")).toContainText("RM 40.80"); }); test("mobile navigation and filter panel", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto("/"); await page.getByRole("button", { name: "Open menu" }).click(); await page .getByRole("dialog") .getByRole("link", { name: "Shop", exact: true }) .click(); await expect(page).toHaveURL("/shop"); await expect(page.getByRole("dialog")).toHaveCount(0); await page.getByRole("button", { name: "Filters", exact: true }).click(); await page.getByLabel("Pack size").selectOption("Fun pack"); await expect(page.locator(".product-card")).toHaveCount(2); }); test("contact validation and honest email preparation state", async ({ page, }) => { await page.goto("/contact"); await page.getByRole("button", { name: "SEND MESSAGE" }).click(); await expect(page.locator("input[name=name]")).toBeFocused(); await page.getByLabel("Your name").fill("Test Customer"); await page .getByLabel("Email address", { exact: true }) .first() .fill("customer@example.com"); await page .getByLabel("Your message") .fill("I would like to ask about product ingredients."); await page.getByRole("button", { name: "SEND MESSAGE" }).click(); await expect(page.locator(".form-status")).toContainText( "Send it there to reach ADUCKTIVE", ); }); test("newsletter validates email and does not claim a subscription", async ({ page, }) => { await page.goto("/"); await page.locator("#newsletter-email").fill("snacker@example.com"); await page.getByRole("button", { name: "Subscribe to newsletter" }).click(); await expect(page.locator(".newsletter [role=status]")).toContainText( "Send it to ask our team to subscribe you", ); }); test("journal filtering and article navigation", async ({ page }) => { await page.goto("/journal"); await page .getByRole("searchbox", { name: "Search journal" }) .fill("Mauritius"); await expect(page.locator(".featured-article")).toContainText("Mauritius"); await page.locator(".featured-article").click(); await expect(page.getByRole("heading", { level: 1 })).toHaveText( "Mauritius, We’ve Arrived", ); await expect(page.locator(".article-body")).toContainText("official debut"); }); test("major routes render without browser errors and respect every target width", async ({ page, }) => { const errors: string[] = []; page.on("pageerror", (e) => errors.push(e.message)); for (const width of [320, 390, 768, 1024, 1200, 1440]) { await page.setViewportSize({ width, height: 900 }); for (const route of [ "/", "/shop", "/collections", product, "/about", "/contact", "/journal", "/journal/90", "/cart", "/checkout", "/account", "/help/faq", "/help/shipping", "/help/returns", "/help/privacy", "/help/terms", ]) { await page.goto(route); await expect( page .getByRole("heading", { level: 1 }) .or(page.getByRole("heading", { name: "Your cart is empty" })) .first(), ).toBeVisible(); const overflow = await page.evaluate( () => document.documentElement.scrollWidth > innerWidth + 1, ); expect(overflow, `${route} at ${width}px`).toBe(false); } } expect(errors).toEqual([]); }); test("core pages pass automated WCAG checks", async ({ page }) => { await page.emulateMedia({ reducedMotion: "reduce" }); for (const route of ["/", "/shop", product, "/contact", "/cart"]) { await page.goto(route); const result = await new AxeBuilder({ page }) .withTags(["wcag2a", "wcag2aa", "wcag21aa"]) .analyze(); expect( result.violations.map((v) => ({ id: v.id, nodes: v.nodes.map((n) => n.target), })), route, ).toEqual([]); } }); test("scroll reveals appear and respect reduced-motion preferences", async ({ page, }) => { await page.emulateMedia({ reducedMotion: "no-preference" }); await page.goto("/"); const story = page.locator(".story-copy"); await expect(story).toHaveCSS("opacity", "0"); await story.scrollIntoViewIfNeeded(); await expect(story).toHaveCSS("opacity", "1"); await page.emulateMedia({ reducedMotion: "reduce" }); await page.reload(); await expect(story).toHaveCSS("opacity", "1"); await expect(page.locator(".pack-original")).toHaveCSS( "animation-name", "none", ); }); test("shop dropdown supports keyboard dismissal, outside click and category navigation", async ({ page }) => { await page.goto("/"); const trigger = page.getByRole("button", { name: "Shop", exact: true }); await trigger.focus(); await page.keyboard.press("Enter"); await expect(trigger).toHaveAttribute("aria-expanded", "true"); await page.keyboard.press("Tab"); await expect(page.locator("#desktop-shop-links a").first()).toBeFocused(); await page.keyboard.press("Escape"); await expect(trigger).toBeFocused(); await expect(trigger).toHaveAttribute("aria-expanded", "false"); await trigger.click(); await page.locator("h1").click(); await expect(trigger).toHaveAttribute("aria-expanded", "false"); await trigger.click(); await page.locator("#desktop-shop-links").getByRole("link", { name: "Tempeh chips" }).click(); await expect(page).toHaveURL("/shop?category=Tempeh%20chips"); await expect(page.locator(".product-card")).toHaveCount(2); await expect(trigger).toHaveAttribute("aria-expanded", "false"); }); test("mobile shop categories expand and close the drawer on selection", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto("/"); await page.getByRole("button", { name: "Open menu" }).click(); await page.getByRole("button", { name: "Shop categories" }).click(); await page.locator("#mobile-shop-links").getByRole("link", { name: "Cornflakes", exact: true }).click(); await expect(page).toHaveURL("/shop?category=Cornflakes"); await expect(page.getByRole("dialog")).toHaveCount(0); await expect(page.getByLabel("Main navigation")).toBeHidden(); }); test("checkout preview supports delivery, payment, review and completion", async ({ page }) => { await page.goto(product); await page.getByRole("button", { name: "BUY NOW" }).click(); await page.getByRole("button", { name: "REVIEW ORDER", exact: true }).click(); await page.getByRole("button", { name: "SAVE ADDRESS" }).click(); await expect(page.getByLabel("Full name", { exact: true })).toBeFocused(); await page.getByLabel("Full name", { exact: true }).fill("Test Snacker"); await page.getByLabel("Phone number", { exact: true }).fill("0123456789"); await page.getByLabel("Street address", { exact: true }).fill("12 Test Street"); await page.getByLabel("City", { exact: true }).fill("Subang Jaya"); await page.getByLabel("Postcode", { exact: true }).fill("47500"); await page.getByLabel("State / region", { exact: true }).fill("Selangor"); await page.getByRole("button", { name: "SAVE ADDRESS" }).click(); await expect(page.locator(".address-card")).toContainText("Test Snacker"); await page.locator(".address-card button").click(); await page.getByLabel("Full name", { exact: true }).fill("Unsaved edit"); await page.keyboard.press("Escape"); await expect(page.locator(".address-card")).toContainText("Test Snacker"); await page.getByLabel("Voucher code").fill("SNACK10"); await page.getByRole("button", { name: "Check code", exact: true }).click(); await expect(page.locator(".checkout-option-note[role=status]")).toContainText("No discount has been applied"); await page.getByRole("button", { name: "Increase The Original Salted Egg Cornflakes" }).click(); await expect(page.locator(".checkout-order-summary .checkout-subtotal")).toContainText("RM 40.80"); await page.getByRole("radio", { name: /Express delivery/ }).check(); await expect(page.locator(".checkout-order-summary .checkout-subtotal")).toContainText("RM 45.80"); await page.getByRole("radio", { name: /Online banking/ }).check(); await page.getByRole("radio", { name: /E-wallet/ }).check(); await page.getByRole("button", { name: "REVIEW ORDER", exact: true }).click(); await expect(page.getByRole("dialog")).toContainText("Express delivery"); await expect(page.getByRole("dialog")).toContainText("E-wallet"); await expect(page.getByRole("dialog")).toContainText("RM 45.80"); await expect(page.locator('.checkout-page a[href^="https:"]')).toHaveCount(0); await page.getByRole("button", { name: "COMPLETE CHECKOUT PREVIEW" }).click(); await expect(page.getByRole("dialog")).toContainText("No order was placed, no payment was taken"); await expect(page).toHaveURL("/checkout"); await page.keyboard.press("Escape"); await page.reload(); await expect(page.locator(".address-card")).toContainText("Add a delivery address"); await expect(page.locator(".checkout-card-stack")).not.toContainText("SNACK10"); await page.getByRole("button", { name: "Remove The Original Salted Egg Cornflakes", exact: true }).click(); await expect(page.getByRole("heading", { name: "Your cart is empty" })).toBeVisible(); await expect(page.locator(".checkout-paybar")).toHaveCount(0); }); test("local account forms validate and do not simulate authentication", async ({ page }) => { await page.goto("/account"); await page.getByRole("link", { name: "CREATE AN ACCOUNT", exact: true }).click(); await expect(page).toHaveURL("/register"); await page.getByLabel("Full name", { exact: true }).fill("Test Snacker"); await page.getByLabel("Email address", { exact: true }).fill("snacker@example.com"); await page.getByLabel("Password", { exact: true }).fill("sample-password"); await page.getByRole("button", { name: "Show password", exact: true }).click(); await expect(page.locator("#club-password")).toHaveAttribute("type", "text"); await page.getByLabel("Confirm password", { exact: true }).fill("different-password"); await page.getByRole("button", { name: "CREATE AN ACCOUNT", exact: true }).click(); await expect(page.locator("#club-confirm")).toBeFocused(); expect(await page.locator("#club-confirm").evaluate((input: HTMLInputElement) => input.validity.customError)).toBe(true); await page.getByLabel("Confirm password", { exact: true }).fill("sample-password"); await page.getByRole("button", { name: "CREATE AN ACCOUNT", exact: true }).click(); await expect(page.locator(".club-form-status")).toContainText("no account has been created"); await expect(page.locator("#club-password")).toHaveValue(""); await page.getByRole("link", { name: "Log in", exact: true }).click(); await expect(page).toHaveURL("/login"); await page.getByLabel("Email address", { exact: true }).fill("snacker@example.com"); await page.getByLabel("Password", { exact: true }).fill("sample-password"); await page.getByRole("button", { name: "LOG IN", exact: true }).click(); await expect(page.locator(".club-form-status")).toContainText("you haven’t been signed in"); await expect(page.locator("#club-password")).toHaveValue(""); await page.getByRole("link", { name: "Forgot your password?" }).click(); await expect(page).toHaveURL("/forgot-password"); await page.getByLabel("Email address", { exact: true }).fill("snacker@example.com"); await page.getByRole("button", { name: "REQUEST PASSWORD RESET" }).click(); await expect(page.locator(".club-form-status")).toContainText("no reset email has been sent"); expect(await page.evaluate(() => JSON.stringify({...localStorage, ...sessionStorage}))).not.toContain("sample-password"); });