// tests/mobile-admin/stops-visual.spec.ts import { test, expect } from "@playwright/test"; test.use({ viewport: { width: 390, height: 844 } }); // iPhone 13 test.beforeEach(async ({ page }) => { // Sign in as a test admin (requires the seed admin from db/seed.ts). await page.goto("/login"); await page.fill('input[name="email"]', "test-admin@example.com"); await page.fill('input[name="password"]', "test-password"); await page.click('button[type="submit"]'); await page.waitForURL(/\/admin/); }); test("stops list — iPhone 13", async ({ page }) => { await page.goto("/admin/v2/stops"); await page.waitForLoadState("networkidle"); // The page must render the v2 shell scaffolding. A 48pt-tall date // picker sits in the action slot; the stops list is grouped by // time-of-day (Morning / Afternoon / Evening / Anytime). await expect(page.locator('input[type="date"]')).toBeVisible(); await expect(page).toHaveScreenshot("stops-list-iphone13.png", { fullPage: true, maxDiffPixels: 200, }); }); test("stops list — empty state (date with no stops)", async ({ page }) => { // Pick a date deep in the past so no stops are scheduled. await page.goto("/admin/v2/stops?date=2000-01-01"); await page.waitForLoadState("networkidle"); // The empty state copy is the source of truth. await expect( page.getByText("No stops scheduled", { exact: true }), ).toBeVisible(); });