The chat cut removed the only WebSocket and CI went before it, but comments still leaned on both: `?account=` was justified by the socket, job polling by an in-process WS registry, the e2e flows as "proxy-safe (none use the WebSocket)", and pyrightconfig named a CI container the engine contract test never checked. Each now says what holds today (the wallet gate, no push channel, the two contract test halves, the image build's `npm ci`, the gate).
78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
import { defineConfig, devices } from "@playwright/test";
|
|
|
|
/**
|
|
* E2E characterization (golden-master) net for the Platform refactor.
|
|
*
|
|
* Target (PW_BASE_URL): defaults to the baked localdev stack on :8080 (production-faithful,
|
|
* same-origin, no HMR gaps). Point it at http://localhost:5173 for the fast Vite loop — all
|
|
* five characterization flows are proxy-safe.
|
|
*
|
|
* The stack must already be UP (owned by `siftlode dev`); there is deliberately no `webServer`.
|
|
* `e2e/global.setup.ts` seeds the dedicated test account and logs in once, sharing the resulting
|
|
* session via storageState so the real tests never re-authenticate (auth endpoints are rate-limited).
|
|
*
|
|
* Runs serial / single-worker on purpose: the specs share ONE seeded account, and a couple of
|
|
* them mutate server state (Settings save), so determinism beats parallelism here.
|
|
*/
|
|
|
|
const BASE_URL = process.env.PW_BASE_URL || "http://127.0.0.1:8080";
|
|
const STORAGE_STATE = "e2e/.auth/state.json";
|
|
|
|
export default defineConfig({
|
|
testDir: "./e2e",
|
|
fullyParallel: false,
|
|
workers: 1,
|
|
forbidOnly: !!process.env.CI,
|
|
retries: 0,
|
|
reporter: [["list"], ["html", { open: "never" }]],
|
|
timeout: 30_000,
|
|
expect: { timeout: 7_000 },
|
|
use: {
|
|
baseURL: BASE_URL,
|
|
storageState: STORAGE_STATE,
|
|
locale: "en-US",
|
|
// retain-on-failure (not on-first-retry): with retries:0 a "first retry" never happens, so a
|
|
// trace would never be captured — this keeps a full trace for any failure, discarded on success.
|
|
trace: "retain-on-failure",
|
|
screenshot: "only-on-failure",
|
|
},
|
|
projects: [
|
|
{
|
|
name: "setup",
|
|
testMatch: /global\.setup\.ts/,
|
|
use: { storageState: { cookies: [], origins: [] } },
|
|
},
|
|
{
|
|
name: "chromium",
|
|
use: { ...devices["Desktop Chrome"], storageState: STORAGE_STATE },
|
|
dependencies: ["setup"],
|
|
},
|
|
// WebKit catches engine-level differences (JS, CSS/layout, event order) that every iOS browser
|
|
// inherits. It does NOT reproduce iPad MEDIA refusals: Playwright's WebKit decodes through the
|
|
// host OS (Media Foundation on Windows, GStreamer on Linux), and measured on 2026-09-14 it played
|
|
// an mp3-in-mp4 and an AV1 mp4 that iPad refuses. Media checks need a real iPad.
|
|
{
|
|
name: "webkit",
|
|
use: { ...devices["Desktop Safari"], storageState: STORAGE_STATE },
|
|
dependencies: ["setup"],
|
|
},
|
|
{
|
|
name: "ipad",
|
|
use: { ...devices["iPad (gen 7) landscape"], storageState: STORAGE_STATE },
|
|
dependencies: ["setup"],
|
|
},
|
|
// The speed baseline (e2e/speed.measure.ts): readings, not tests. Only when PW_SPEED is set —
|
|
// `scripts/audit_metrics.py --speed` sets it — so the e2e suite never runs it.
|
|
...(process.env.PW_SPEED
|
|
? [
|
|
{
|
|
name: "speed",
|
|
testMatch: /\.measure\.ts/,
|
|
use: { ...devices["Desktop Chrome"], storageState: STORAGE_STATE },
|
|
dependencies: ["setup"],
|
|
},
|
|
]
|
|
: []),
|
|
],
|
|
});
|