e39ec9a77b
The end-to-end suite had never been run. Its first run failed six ways, all of them the page sitting on the login screen: every browser page load re-obtains an access token, the refresh endpoint allows thirty a minute per address, and a twenty-test run makes about fifty of them from one address. Half came back 429, and a failed refresh is indistinguishable from being logged out. Raising the ceiling would only move it and make a green suite depend on how fast the machine is, so the limiter is switched off for the test backend alone — it measures a client, and the runner is not one. It stays on everywhere else. With that gone, one real failure was left, and it belonged to the commit that claimed to have fixed it: cell widths were held, but a week whose cell carries a holiday name still stood taller than its neighbours, because each week is its own grid and none can see another's height. The weeks now share one grid whose rows are all a single fraction, so the tallest sets the rest and no cell can grow its own row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ei7gCZzdd751uZtPzb1Pep
75 lines
3.1 KiB
TypeScript
75 lines
3.1 KiB
TypeScript
import { defineConfig, devices } from '@playwright/test'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
const authFile = path.join(__dirname, 'e2e/.auth/user.json')
|
|
|
|
// NOTE: the frontend origin is deliberately `http://localhost:5173`, never
|
|
// `127.0.0.1` — Vite's dev server binds IPv6 `::1`, and on macOS
|
|
// `127.0.0.1` can silently miss it (see the matching comment in
|
|
// vite.config.ts's proxy target, which uses 127.0.0.1 for the *backend* for
|
|
// the opposite reason: to dodge a stray IPv6 listener there).
|
|
const FRONTEND_URL = 'http://localhost:5173'
|
|
const BACKEND_HEALTH_URL = 'http://127.0.0.1:8000/health'
|
|
|
|
export default defineConfig({
|
|
testDir: './e2e',
|
|
globalSetup: './e2e/global-setup.ts',
|
|
fullyParallel: true,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: process.env.CI ? 1 : 0,
|
|
// A fresh suite against a single shared demo workspace — keep it to one
|
|
// worker in CI until it's proven flake-free under parallel load. Left
|
|
// unset locally so Playwright picks its usual CPU-based default.
|
|
...(process.env.CI ? { workers: 1 } : {}),
|
|
reporter: process.env.CI ? [['github'], ['html', { open: 'never' }]] : 'list',
|
|
use: {
|
|
baseURL: FRONTEND_URL,
|
|
// Pinned so translated labels/aria-labels used as selectors (e.g.
|
|
// "Välj månad") are deterministic regardless of the host machine's
|
|
// locale — the app defaults to Swedish or English based on
|
|
// `navigator.language` (see LanguageContext.tsx).
|
|
locale: 'sv-SE',
|
|
trace: 'retain-on-failure',
|
|
screenshot: 'only-on-failure',
|
|
},
|
|
webServer: [
|
|
{
|
|
command: 'uv run uvicorn app.main:app --port 8000',
|
|
cwd: path.resolve(__dirname, '../backend'),
|
|
url: BACKEND_HEALTH_URL,
|
|
// The backend rate-limits per remote IP (slowapi's
|
|
// `get_remote_address`), which assumes one IP is one client. This
|
|
// suite breaks that assumption: every page load in the whole run
|
|
// comes from 127.0.0.1. `POST /api/auth/refresh` fires once per page
|
|
// load (AuthProvider re-obtains the access token on mount, see
|
|
// AuthContext.tsx) and is capped at 30/minute, so a ~20-test run's
|
|
// ~50 refreshes start returning 429 partway through — and a failed
|
|
// refresh renders the login screen, which is why unrelated specs
|
|
// failed on `getByTestId('dashboard')`/`('calendar')` not being
|
|
// found. Raising the cap would only move the cliff and make green-ness
|
|
// a function of machine speed; the limiter simply does not apply to a
|
|
// single-IP test runner, so it is switched off here.
|
|
env: { APP_RATE_LIMIT_ENABLED: 'false' },
|
|
reuseExistingServer: !process.env.CI,
|
|
timeout: 60_000,
|
|
},
|
|
{
|
|
command: 'npx vite --port 5173 --strictPort',
|
|
cwd: __dirname,
|
|
url: FRONTEND_URL,
|
|
reuseExistingServer: !process.env.CI,
|
|
timeout: 60_000,
|
|
},
|
|
],
|
|
projects: [
|
|
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
|
|
{
|
|
name: 'chromium',
|
|
use: { ...devices['Desktop Chrome'], storageState: authFile },
|
|
dependencies: ['setup'],
|
|
},
|
|
],
|
|
})
|