Files
waggle-os/playwright.config.ts
Oleg Maslov b20b138fe4 moving
2026-09-02 10:14:22 +02:00

121 lines
4.8 KiB
TypeScript

/**
* Playwright Configuration — Visual Regression + E2E User Journeys
*
* Two test suites:
* 1. Visual regression: screenshot baselines for all 7 views (dark + light) = 14 baselines
* 2. E2E user journeys: browser-automated interaction tests
*
* Usage:
* npx playwright test # Run all tests
* npx playwright test tests/visual # Visual regression only
* npx playwright test tests/e2e # E2E user journeys only
* npx playwright test --update-snapshots # Update visual baselines
*
* The webServer config builds workspace packages plus apps/web, then auto-starts the Waggle server
* (with --skip-litellm for CI). The server serves the freshly-built React
* frontend from <root>/dist/ at localhost:3333 — matching the canonical
* `npm run build:all` target so tests always run against the latest source.
*/
import { defineConfig, devices } from '@playwright/test';
import os from 'node:os';
import path from 'node:path';
// Playwright enables FORCE_COLOR for its workers; remove an inherited
// NO_COLOR flag first so Node does not report the conflicting pair.
delete process.env.FORCE_COLOR;
delete process.env.NO_COLOR;
const e2eDataDir = process.env.WAGGLE_E2E_DATA_DIR
?? path.join(os.tmpdir(), `waggle-os-playwright-${process.pid}`);
const e2eBaseURL = process.env.WAGGLE_E2E_BASE_URL
?? `http://127.0.0.1:${process.env.WAGGLE_E2E_PORT ?? '3333'}`;
const e2eURL = new URL(e2eBaseURL);
const e2ePort = Number.parseInt(
process.env.WAGGLE_E2E_PORT ?? e2eURL.port ?? '3333',
10,
) || 3333;
const e2eSkipLiteLLM = process.env.WAGGLE_E2E_SKIP_LITELLM !== '0';
const e2eReuseExistingServer = process.env.WAGGLE_E2E_REUSE_EXISTING_SERVER !== '0';
const e2eNodeEnvName = 'WAGGLE_E2E_NODE_EXEC';
const e2eNodeCommand = process.platform === 'win32'
? `"%${e2eNodeEnvName}%"`
: `"$${e2eNodeEnvName}"`;
// Playwright merges process.env when it launches the web server. Keep this
// config object limited to explicit safe overrides because JSON reporters
// serialize it verbatim.
const e2eEnv: NodeJS.ProcessEnv = {
[e2eNodeEnvName]: process.execPath,
FORCE_COLOR: undefined,
NO_COLOR: undefined,
NODE_OPTIONS: '--disable-warning=DEP0040',
};
export default defineConfig({
testDir: './tests',
testMatch: '**/*.spec.ts', // Only run .spec.ts files (excludes Vitest .test.ts files)
snapshotDir: './tests/visual/baselines',
snapshotPathTemplate: '{snapshotDir}/{testName}/{arg}{ext}',
timeout: 30_000,
expect: {
toHaveScreenshot: {
maxDiffPixelRatio: 0.003, // 0.3% threshold
animations: 'disabled',
},
},
fullyParallel: false, // Sequential to avoid port conflicts
workers: 1,
retries: 1,
reporter: [['html', { open: 'never' }]],
use: {
baseURL: e2eBaseURL,
screenshot: 'only-on-failure',
trace: 'on-first-retry',
viewport: { width: 1200, height: 800 },
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
/* Auto-start the Waggle server before tests run.
* --skip-litellm ensures tests don't need a real LLM provider.
*
* The command builds workspace packages and apps/web first (`npm run build:all`)
* so Playwright always runs against current package and web source. `reuseExisting-
* Server: true` skips this when a dev server is already running on :3333
* (developer runs `npm run dev` in another terminal + `npx playwright test`;
* the config notices the port is occupied and skips build+start). Set
* WAGGLE_E2E_REUSE_EXISTING_SERVER=0 for isolated acceptance runs.
*
* The server auto-detects <root>/dist per packages/server/src/local/
* index.ts — no WAGGLE_FRONTEND_DIR override needed. */
webServer: {
command: `npm run build:all && ${e2eNodeCommand} node_modules/tsx/dist/cli.mjs packages/server/src/local/start.ts${e2eSkipLiteLLM ? ' --skip-litellm' : ''}`,
url: new URL('/health', e2eBaseURL).toString(),
reuseExistingServer: e2eReuseExistingServer,
timeout: 600_000, // Cold Windows build + scanning + tsx sidecar import can exceed 5 min
stdout: 'pipe',
stderr: 'pipe',
// D1: the e2e suite drives /api/* routes directly (no token bootstrap), so
// trust loopback in the harness — mirrors vitest.setup.ts which defaults
// this ON for the test env. The production default stays SECURE (token
// required); this only affects the locally-spawned test server.
env: {
...e2eEnv,
WAGGLE_PORT: String(e2ePort),
WAGGLE_TRUST_LOCALHOST: '1',
WAGGLE_RATE_LIMIT_MAX_REQUESTS: '2000',
WAGGLE_DISABLE_MARKETPLACE_SYNC: '1',
WAGGLE_SUPPRESS_EMBEDDING_WARNING: '1',
WAGGLE_DATA_DIR: e2eDataDir,
EMBEDDING_PROVIDER: 'mock',
VITE_WAGGLE_E2E: '1',
VITE_CLERK_PUBLISHABLE_KEY: '',
CLERK_SECRET_KEY: '',
},
},
});