Summary
The frontend Playwright e2e suite is currently unreliable on local runs. The tests are intended to run against dev:web with VITE_NO_ELECTRON=1, so useWorkspaceQuery serves deterministic mockWorkspaces. In practice, local runs can fail before assertions because Playwright targets 127.0.0.1:5173 while Vite can bind only to localhost / IPv6 loopback on macOS. If a different renderer is already listening on 127.0.0.1:5173, Playwright can also reuse that incompatible server because reuseExistingServer is enabled outside CI.
Even when the intended preview server is reachable, several checked-in workbench/history/inspector specs are stale: they still assert old route names and accessible labels that no longer match the current React UI.
Severity
P2 developer workflow / regression coverage bug.
This does not affect production behavior directly, but it makes the browser e2e suite noisy and can hide real UI regressions.
Repro A: fresh local e2e run can fail with connection refused
From frontend:
npm run test:e2e -- --workers=1 e2e/workbench.spec.ts
Observed failure:
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://127.0.0.1:5173/
Manual check showed npm run dev:web -- --port 5173 advertised:
Local: http://localhost:5173/
and the listener was on IPv6 loopback:
node ... TCP [::1]:5173 (LISTEN)
localhost responded, but 127.0.0.1 did not:
curl -I http://localhost:5173/ # 200 OK
curl -I http://127.0.0.1:5173/ # connection refused
Repro B: with a reachable preview server, stale selectors/routes fail
Start preview explicitly:
npm run dev:web -- --host 127.0.0.1 --port 5173 --strictPort
npm run test:e2e -- --workers=1 e2e/workbench.spec.ts
Observed failures:
Locator: getByRole('button', { name: 'Orchestrator', exact: true })
Expected: visible
Error: element(s) not found
Locator: getByText('Changed')
Expected: visible
Error: element(s) not found
waiting for getByRole('button', { name: 'refactor-mux', exact: true })
Expected behavior
npm run test:e2e should start or use the intended deterministic preview renderer and pass against current UI routes/selectors.
Actual behavior
The suite can fail in multiple local modes:
- Playwright tries
127.0.0.1:5173 while Vite is only reachable through localhost.
reuseExistingServer: !process.env.CI can silently attach to an already-running incompatible renderer on port 5173.
- Workbench/history/inspector specs assert stale labels and routes.
Screenshot evidence
Current preview UI with mock data loaded. Notice the UI renders title-based session rows, not a visible refactor-mux button:
Wrong-server scenario: if a daemon-backed renderer is already on 127.0.0.1:5173, Playwright reuses it and tests run against real local daemon state instead of mock fixtures:
Code pointers / likely root cause
frontend/playwright.config.ts
use: {
baseURL: "http://127.0.0.1:5173",
},
webServer: {
command: "npm run dev:web -- --port 5173",
port: 5173,
reuseExistingServer: !process.env.CI,
},
The command does not force --host 127.0.0.1, but the tests use 127.0.0.1.
frontend/package.json
"dev:web": "VITE_NO_ELECTRON=1 vite --config vite.renderer.config.ts"
frontend/src/renderer/hooks/useWorkspaceQuery.ts
const usePreviewData = import.meta.env.VITE_NO_ELECTRON === "1";
The e2e tests rely on this preview mode.
frontend/e2e/workbench.spec.ts
await expect(page.getByRole("button", { name: "Orchestrator", exact: true })).toBeVisible();
await page.goto("/#/workspaces/api-gateway/sessions/refactor-mux");
await page.getByRole("button", { name: "refactor-mux", exact: true }).click();
Current generated routes use /projects/$projectId/sessions/$sessionId, not /workspaces/....
frontend/src/renderer/lib/mock-data.ts
id: "refactor-mux",
title: "Split terminal mux responsibilities",
The current visible session button is title-based, not exact refactor-mux.
frontend/src/renderer/components/Sidebar.tsx
Current accessible names include:
aria-label="Orchestrator board"
aria-label={orchestrator ? `Open ${workspace.name} orchestrator` : `Spawn ${workspace.name} orchestrator`}
There is no exact button[name="Orchestrator"] in the current shell.
Suggested fix shape
- Update
frontend/playwright.config.ts to make the server URL deterministic:
- add
--host 127.0.0.1
- consider
--strictPort
- consider disabling
reuseExistingServer or using a dedicated e2e-only port to avoid attaching to the wrong renderer
- Update stale selectors/routes in:
frontend/e2e/workbench.spec.ts
frontend/e2e/history-nav.spec.ts
frontend/e2e/inspector-toggle.spec.ts
- Prefer selectors that match current accessible names:
Open Split terminal mux responsibilities
/projects/api-gateway/sessions/refactor-mux
Orchestrator board or project-specific orchestrator button labels, depending on intended behavior
- Re-run the full browser suite:
npm --prefix frontend run test:e2e
Duplicate / overlap check
Searched current issues and PRs for:
Playwright e2e VITE_NO_ELECTRON reuseExistingServer
e2e workbench refactor-mux workspaces
test:e2e playwright
refactor-mux
- exact title text
No existing issue matched this exact bug.
Closest related PRs checked:
Contribution value
This is a good focused issue because:
- It is reproducible locally without credentials.
- It stays inside frontend test/config boundaries.
- It improves developer confidence in the e2e suite.
- It should be a small PR: stabilize Playwright server startup and refresh stale selectors/routes.
Summary
The frontend Playwright e2e suite is currently unreliable on local runs. The tests are intended to run against
dev:webwithVITE_NO_ELECTRON=1, souseWorkspaceQueryserves deterministicmockWorkspaces. In practice, local runs can fail before assertions because Playwright targets127.0.0.1:5173while Vite can bind only tolocalhost/ IPv6 loopback on macOS. If a different renderer is already listening on127.0.0.1:5173, Playwright can also reuse that incompatible server becausereuseExistingServeris enabled outside CI.Even when the intended preview server is reachable, several checked-in workbench/history/inspector specs are stale: they still assert old route names and accessible labels that no longer match the current React UI.
Severity
P2 developer workflow / regression coverage bug.
This does not affect production behavior directly, but it makes the browser e2e suite noisy and can hide real UI regressions.
Repro A: fresh local e2e run can fail with connection refused
From
frontend:Observed failure:
Manual check showed
npm run dev:web -- --port 5173advertised:and the listener was on IPv6 loopback:
localhostresponded, but127.0.0.1did not:Repro B: with a reachable preview server, stale selectors/routes fail
Start preview explicitly:
Observed failures:
Expected behavior
npm run test:e2eshould start or use the intended deterministic preview renderer and pass against current UI routes/selectors.Actual behavior
The suite can fail in multiple local modes:
127.0.0.1:5173while Vite is only reachable throughlocalhost.reuseExistingServer: !process.env.CIcan silently attach to an already-running incompatible renderer on port5173.Screenshot evidence
Current preview UI with mock data loaded. Notice the UI renders title-based session rows, not a visible
refactor-muxbutton:Wrong-server scenario: if a daemon-backed renderer is already on
127.0.0.1:5173, Playwright reuses it and tests run against real local daemon state instead of mock fixtures:Code pointers / likely root cause
frontend/playwright.config.tsThe command does not force
--host 127.0.0.1, but the tests use127.0.0.1.frontend/package.jsonfrontend/src/renderer/hooks/useWorkspaceQuery.tsThe e2e tests rely on this preview mode.
frontend/e2e/workbench.spec.tsCurrent generated routes use
/projects/$projectId/sessions/$sessionId, not/workspaces/....frontend/src/renderer/lib/mock-data.tsThe current visible session button is title-based, not exact
refactor-mux.frontend/src/renderer/components/Sidebar.tsxCurrent accessible names include:
There is no exact
button[name="Orchestrator"]in the current shell.Suggested fix shape
frontend/playwright.config.tsto make the server URL deterministic:--host 127.0.0.1--strictPortreuseExistingServeror using a dedicated e2e-only port to avoid attaching to the wrong rendererfrontend/e2e/workbench.spec.tsfrontend/e2e/history-nav.spec.tsfrontend/e2e/inspector-toggle.spec.tsOpen Split terminal mux responsibilities/projects/api-gateway/sessions/refactor-muxOrchestrator boardor project-specific orchestrator button labels, depending on intended behaviorDuplicate / overlap check
Searched current issues and PRs for:
Playwright e2e VITE_NO_ELECTRON reuseExistingServere2e workbench refactor-mux workspacestest:e2e playwrightrefactor-muxNo existing issue matched this exact bug.
Closest related PRs checked:
refactor-muxin terminal work, but is unrelated to the e2e config/selector drift.Contribution value
This is a good focused issue because: