e9f4cb0178
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 1m10s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m43s
A Playwright spec drives the whole offline flow in the mock build: force the installed-PWA display mode, enter offline via the Settings toggle (its readiness check fetches the dawgs), assert the blue chrome + online-games-hidden + Stats-disabled, then create and play a device-local English vs_ai game with a pinned bag seed (deterministic rack NEWYMAO) -- play the opening WAY across the centre, watch the robot reply with a real move, and reload to confirm the IndexedDB replay. Enabling infra (all e2e-only; nothing enters the production build): - mock/client.ts fetchDict serves the per-variant dawgs from the preview build's /e2edict/ (was: threw 'unsupported in mock'). - scripts/e2e-dict.mjs copies the real dawgs into dist-e2e from E2E_DICT_DIR (the ui CI job fetches the scrabble-dictionary release like the Go jobs; local default: the sibling scrabble-solver/dawg); playwright.config runs it between build and preview. - localgame/id.ts setForcedSeed + gateway.ts window.__mock.setLocalSeed: a mock-only seam to pin a local game's bag seed (tree-shaken from prod). - ci.yaml ui job: fetch the dawgs + pass E2E_DICT_DIR to the e2e step. - docs/TESTING.md: the offline e2e + the mock-dawg wiring. Verified: check 0 / unit 482 / e2e 198 (both engines) / app entry 113.8/114.
45 lines
2.7 KiB
TypeScript
45 lines
2.7 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.
|
|
// After the mock build, copy the real per-variant dawgs into the preview output (dist-e2e) so the
|
|
// offline spec can play a real local vs_ai game; the files are e2e-only (never committed, never in
|
|
// the production build). Source: E2E_DICT_DIR (CI: the fetched release; local: the sibling).
|
|
command:
|
|
'pnpm exec vite build --mode mock --base / --outDir dist-e2e --emptyOutDir && node scripts/e2e-dict.mjs && 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 } } },
|
|
],
|
|
});
|