Files
scrabble-game/ui/playwright.config.ts
T
Ilia Denisov 9ec72c8377
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
feat(ui): landscape two-column game layout, board fitted by height
When the viewport is wider than tall (matchMedia orientation: landscape) the
game screen switches from the portrait stack to a two-column layout: the board
fills the right column as the largest square that fits the height (no zoom,
shrinking by width when cramped — lowest priority), while the left panel stacks
the rack (+ make), the status line, the score plaques, the always-open docked
history and the controls. Board zoom, the history slide-drawer gestures and the
growing nav bar are gated off in landscape; the portrait layout is unchanged and
both render from the same snippets so behaviour stays single-sourced.

The mock e2e now defaults to a portrait viewport (the mobile-first app the
gesture/zoom/history specs are written for); landscape.spec.ts covers the wide
layout in its own viewport.
2026-06-14 19:06:35 +02:00

42 lines
2.3 KiB
TypeScript

import { defineConfig, devices } from '@playwright/test';
// Hermetic e2e: Playwright builds the app in `mock` mode (the in-memory fake transport, so the
// smoke needs no backend/gateway/Postgres) and serves the MINIFIED artifact via `vite preview`,
// rather than the dev server. Running against the production-minified bundle is what the contour
// ships, so the e2e now catches minification-only regressions — e.g. a reactive dependency the
// minifier drops — which the unminified dev server silently hid. The build goes to dist-e2e/ so it
// never clobbers the dist/ the bundle-size gate measures.
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 1 : 0,
reporter: 'list',
use: {
baseURL: 'http://localhost:4173',
trace: 'on-first-retry',
},
webServer: {
// `--base /` overrides the production relative base (`./`, which lets the gateway serve the SPA
// under /app/ and /telegram/): served from the preview root, an absolute base keeps assets at
// /assets/ so the SPA-fallback also boots a subpath like /telegram/. Base only prefixes asset
// URLs, so the minified JS under test is identical to the contour's.
command:
'pnpm exec vite build --mode mock --base / --outDir dist-e2e --emptyOutDir && pnpm exec vite preview --outDir dist-e2e --port 4173 --strictPort',
url: 'http://localhost:4173',
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
// Run the same hermetic specs in Chromium and WebKit (Safari's engine) so the UI is
// exercised in both rendering/JS engines. Note: desktop WebKit on Linux does not
// reproduce iOS Safari's text auto-inflation, so the `text-size-adjust` guard in
// app.css is not regression-covered here — but engine-level CSS/JS differences are.
// The mock e2e exercises the mobile-first app, so it runs in a portrait viewport by default —
// the layout the gesture/zoom/history-drawer specs are written for. The wide landscape layout
// (Game.svelte's two-column branch) has its own spec that overrides the viewport (landscape.spec.ts).
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'], viewport: { width: 390, height: 844 } } },
{ name: 'webkit', use: { ...devices['Desktop Safari'], viewport: { width: 390, height: 844 } } },
],
});