import { test, expect, devices } from '@playwright/test'; // UAT-3: Browser gate (hard stop) — e2e. // Spec (CAPTURE.md §Browsers): // Phone: iOS Safari, Android Chrome. // PC: Chrome, Edge, Firefox. // Other clients get a hard stop. // // Acceptance: opening in an unsupported browser (e.g. Opera, Samsung // Internet) shows a hard-stop message, NOT the app. // // The app itself must not render (no content, no "Milestone 1 // — Capture" text) in an unsupported browser; the hard-stop page lists // the spec browsers instead. const DESKTOP_CHROME_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'; const DESKTOP_OPERA_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 OPR/110.0.0.0'; const DESKTOP_EDGE_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0'; const DESKTOP_FIREFOX_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0'; const IOS_SAFARI_UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/605.1.15'; const ANDROID_CHROME_UA = 'Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6331.115 Mobile Safari/537.36'; const SAMSUNG_INTERNET_UA = 'Mozilla/5.0 (Linux; Android 14; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/24.0 Chrome/124.0.0.0 Mobile Safari/537.36'; async function openApp(page, ua) { await page.setExtraHTTPHeaders({ 'User-Agent': ua }); await page.goto('/'); // The gate runs on client hydration; wait a beat for the DOM to // settle on whichever branch rendered. await page.waitForTimeout(300); } // The app renders when the gate passes: the layout's
is present // and the capture UI (Add Photo heading) is inside it. async function expectApp(page) { await expect(page.locator('main')).toBeVisible(); await expect(page.locator('main')).toContainText('Add Photo'); // No hard-stop page. await expect(page.locator('.gate')).toHaveCount(0); } // The hard stop renders when the gate fails: the .gate box is present, // the app's
is NOT, and the spec browsers are listed. async function expectHardStop(page) { await expect(page.locator('.gate h1')).toHaveText('Unsupported browser'); await expect(page.locator('main')).toHaveCount(0); const gate = page.locator('.gate'); await expect(gate).toContainText('iOS Safari'); await expect(gate).toContainText('Android Chrome'); await expect(gate).toContainText('Chrome'); await expect(gate).toContainText('Edge'); await expect(gate).toContainText('Firefox'); } test('UAT-3: app renders in desktop Chrome (supported)', async ({ page }) => { await openApp(page, DESKTOP_CHROME_UA); await expectApp(page); }); test('UAT-3: app renders in desktop Edge (supported)', async ({ page }) => { await openApp(page, DESKTOP_EDGE_UA); await expectApp(page); }); test('UAT-3: app renders in desktop Firefox (supported)', async ({ page }) => { await openApp(page, DESKTOP_FIREFOX_UA); await expectApp(page); }); test('UAT-3: app renders in iOS Safari (supported)', async ({ page, context }) => { await context.setExtraHTTPHeaders({ 'User-Agent': IOS_SAFARI_UA }); await page.goto('/'); await page.waitForTimeout(300); await expectApp(page); }); test('UAT-3: app renders in Android Chrome (supported)', async ({ page, context }) => { await context.setExtraHTTPHeaders({ 'User-Agent': ANDROID_CHROME_UA }); await page.goto('/'); await page.waitForTimeout(300); await expectApp(page); }); test('UAT-3: hard stop in desktop Opera (unsupported)', async ({ page }) => { await openApp(page, DESKTOP_OPERA_UA); await expect(page.locator('.gate h1')).toHaveText('Unsupported browser'); // The app must NOT render. await expect(page.locator('main')).toHaveCount(0); // The hard-stop page lists the spec browsers. await expect(page.locator('.gate')).toContainText('iOS Safari'); await expect(page.locator('.gate')).toContainText('Android Chrome'); await expect(page.locator('.gate')).toContainText('Chrome'); await expect(page.locator('.gate')).toContainText('Edge'); await expect(page.locator('.gate')).toContainText('Firefox'); }); test('UAT-3: hard stop in Samsung Internet (unsupported)', async ({ page, context }) => { await context.setExtraHTTPHeaders({ 'User-Agent': SAMSUNG_INTERNET_UA }); await page.goto('/'); await page.waitForTimeout(300); await expect(page.locator('.gate h1')).toHaveText('Unsupported browser'); await expect(page.locator('main')).toHaveCount(0); });