Skip to content

Commit 090c1b2

Browse files
JohnMcLearclaude
andcommitted
chore(e2e): auto-run under xvfb-run when available
Add scripts/run-e2e.mjs which detects xvfb-run on PATH and wraps playwright under it automatically so E2E tests don't steal focus from the user's display. Falls back to direct invocation if xvfb-run is absent (with an install hint). Set E2E_NO_XVFB=1 to force direct mode. - package.json: test:e2e → node scripts/run-e2e.mjs - ci.yml: drop explicit xvfb-run wrapper (script handles it) - AGENTS.md: document xvfb-run behaviour in Dev loop table Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent df7eb03 commit 090c1b2

4 files changed

Lines changed: 35 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- run: pnpm install --frozen-lockfile
3333
- run: pnpm exec playwright install --with-deps chromium
3434
- run: pnpm build
35-
- run: xvfb-run --auto-servernum pnpm test:e2e
35+
- run: pnpm test:e2e
3636
env:
3737
CI: 'true'
3838
- uses: actions/upload-artifact@v4

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Guidance for AI agents (Claude, Copilot, Cursor, etc.) working in this repo.
2222
| `pnpm format` | Prettier write. |
2323
| `pnpm test` | Vitest unit + component tests (single run). |
2424
| `pnpm test:watch` | Vitest watch mode. |
25-
| `pnpm test:e2e` | Playwright Electron E2E. Requires Etherpad on `:9003` (auto-spun by global setup). |
25+
| `pnpm test:e2e` | Playwright Electron E2E. Requires Etherpad on `:9003` (auto-spun by global setup). Auto-runs under `xvfb-run` when available so no windows steal focus. Set `E2E_NO_XVFB=1` to disable. |
2626
| `pnpm build` | Production build → `out/main`, `out/preload`, `out/renderer`. |
2727
| `pnpm package` | Build + electron-builder → AppImage + .deb under `release/`. |
2828

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"format": "prettier --write src tests",
2222
"test": "vitest run",
2323
"test:watch": "vitest",
24-
"test:e2e": "playwright test",
24+
"test:e2e": "node scripts/run-e2e.mjs",
2525
"package": "electron-vite build && electron-builder --linux --config build/electron-builder.yml",
2626
"start": "electron-vite preview"
2727
},

scripts/run-e2e.mjs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env node
2+
// Run Playwright E2E either under xvfb-run (if available) so the tests don't
3+
// steal focus from the user, or directly otherwise. Pass-through args.
4+
import { spawnSync } from 'node:child_process';
5+
6+
const args = process.argv.slice(2);
7+
8+
function which(bin) {
9+
const r = spawnSync('which', [bin], { stdio: ['ignore', 'pipe', 'ignore'] });
10+
return r.status === 0 ? r.stdout.toString().trim() : null;
11+
}
12+
13+
const xvfb = which('xvfb-run');
14+
const playwrightArgs = ['exec', 'playwright', 'test', ...args];
15+
16+
let cmd;
17+
let argv;
18+
if (xvfb && !process.env.E2E_NO_XVFB) {
19+
cmd = xvfb;
20+
argv = ['--auto-servernum', '--server-args=-screen 0 1280x800x24', 'pnpm', ...playwrightArgs];
21+
console.error('[e2e] running under xvfb-run (set E2E_NO_XVFB=1 to disable)');
22+
} else {
23+
cmd = 'pnpm';
24+
argv = playwrightArgs;
25+
if (!xvfb) {
26+
console.error('[e2e] xvfb-run not found on PATH; tests will run on the visible display.');
27+
console.error('[e2e] install with: sudo apt install xvfb');
28+
}
29+
}
30+
31+
const r = spawnSync(cmd, argv, { stdio: 'inherit' });
32+
process.exit(r.status ?? 1);

0 commit comments

Comments
 (0)