From fe3ee08870fe2bbdd89b424a5033dcc55783da45 Mon Sep 17 00:00:00 2001 From: ZAINAB Date: Fri, 26 Jun 2026 13:17:41 +0000 Subject: [PATCH] test: add Playwright mobile and desktop scenario coverage Closes #591 - playwright.config.ts: add Firefox, WebKit (Desktop Safari), Pixel 5 (mobile Chrome), and iPhone 13 (mobile Safari) projects alongside the existing Desktop Chrome project. - e2e/viewport.spec.ts: three cross-viewport scenarios covering home page horizontal overflow, verify flow usability, and nav accessibility. --- apps/web/e2e/viewport.spec.ts | 81 +++++++++++++++++++++++++++++++++++ apps/web/playwright.config.ts | 18 ++++++++ 2 files changed, 99 insertions(+) create mode 100644 apps/web/e2e/viewport.spec.ts diff --git a/apps/web/e2e/viewport.spec.ts b/apps/web/e2e/viewport.spec.ts new file mode 100644 index 0000000..46dc350 --- /dev/null +++ b/apps/web/e2e/viewport.spec.ts @@ -0,0 +1,81 @@ +/** + * Mobile and desktop viewport scenario coverage — issue #591. + * + * Verifies that key user flows work and render correctly on both mobile and + * desktop viewports. The Playwright project matrix (playwright.config.ts) + * runs these tests on real mobile device emulations (Pixel 5, iPhone 13) as + * well as Desktop Chrome/Firefox/Safari, so individual tests here do not need + * to set a viewport manually. + */ + +import { expect, test } from '@playwright/test' + +const validResponse = { + certificate: { + id: 'cert-viewport-test', + kwh: 10, + issued_at: '2025-06-01T00:00:00.000Z', + retired: false, + retired_at: null, + retired_by: null, + }, + on_chain: { + anchor_tx: 'anchor_tx_viewport', + anchor_explorer: 'https://stellar.explorer/tx/anchor_tx_viewport', + mint_tx: 'mint_tx_viewport', + mint_explorer: 'https://stellar.explorer/tx/mint_tx_viewport', + }, + meter_proof: { + meter_id: 'meter-viewport', + reading_hash: '1234abcd', + signature_hex: 'beefbeefbeefbeef', + kwh: 10, + timestamp: '2025-06-01T00:00:00.000Z', + verified: true, + }, +} + +test.beforeEach(async ({ page }) => { + await page.route('**/api/verify**', async (route) => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(validResponse), + }) + }) +}) + +test('home page renders primary CTA on any viewport', async ({ page }) => { + await page.goto('/') + // The primary call-to-action must be visible without horizontal scroll + const body = page.locator('body') + await expect(body).toBeVisible() + const scrollWidth: number = await page.evaluate(() => document.body.scrollWidth) + const clientWidth: number = await page.evaluate(() => document.body.clientWidth) + expect(scrollWidth).toBeLessThanOrEqual(clientWidth + 1) // no horizontal overflow +}) + +test('verify page is usable and shows result on any viewport', async ({ page }) => { + await page.goto('/verify') + // Form and submit button must be reachable without horizontal scroll + const verifyButton = page.locator('button:has-text("Verify")') + await expect(verifyButton).toBeVisible() + await Promise.all([ + page.waitForResponse('**/api/verify**'), + verifyButton.click(), + ]) + await expect(page.locator('text=Certificate verified successfully.')).toBeVisible() +}) + +test('navigation is accessible on any viewport', async ({ page }) => { + await page.goto('/') + // On mobile, a hamburger / menu toggle may be present instead of a full nav. + // Either the nav links are visible or a menu toggle exists. + const hasVisibleNav = await page.locator('nav a').first().isVisible().catch(() => false) + const hasMenuToggle = await page + .locator('[aria-label*="menu" i], [aria-label*="navigation" i], button[aria-expanded]') + .first() + .isVisible() + .catch(() => false) + expect(hasVisibleNav || hasMenuToggle).toBe(true) +}) diff --git a/apps/web/playwright.config.ts b/apps/web/playwright.config.ts index f8a7825..420f03b 100644 --- a/apps/web/playwright.config.ts +++ b/apps/web/playwright.config.ts @@ -18,10 +18,28 @@ export default defineConfig({ actionTimeout: 10000, }, projects: [ + // Desktop browsers { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + // Mobile browsers + { + name: 'mobile-chrome', + use: { ...devices['Pixel 5'] }, + }, + { + name: 'mobile-safari', + use: { ...devices['iPhone 13'] }, + }, ], webServer: { command: 'pnpm exec next dev --hostname 127.0.0.1 --port 3000',