Skip to content

Commit 828d74b

Browse files
Enable E2E tests on Linux (#3295)
## Related issues - Related to https://linear.app/a8c/issue/RSM-1856/review-and-fix-e2e-tests-on-linux ## How AI was used in this PR Drafted with Claude Code under interactive review. The author pushed back on overstated claims (e.g. attributing the OOM to PHP WASM workers when only the symptom was verified) and on a speculative selector change that was reverted after confirming it was unnecessary. Each change here was vetted against the actual test runs and existing codebase conventions. ## Proposed Changes - Add `process.env.E2E` guard to `autoInstallLinuxCliIfNeeded` so a packaged Linux build does not write to the host user's `~/.bashrc` or `~/.local/bin/studio` during E2E runs. - Verified by inspecting the bundle from `electron-vite build`: vite statically replaces `process.env.NODE_ENV` with `"production"`, so the existing `NODE_ENV !== 'production'` guard collapses to a dead `false` in the bundle (the same substitution applies to the full `package` flow, which just wraps the vite output). Without the new `process.env.E2E` term, the function would fire during E2E and call `installCli()`, which uses `os.homedir()` directly — and `E2E_HOME_PATH` does not override that. - The Mac/Windows installers use the same NODE_ENV-only guard pattern, but extending the fix to them is out of scope here: the analog has not been verified on those platforms from this Linux box, and shipping a guard on inference alone is the kind of thing this PR is trying to avoid. - Reduce concurrent running sites in `blueprints.test.ts` to one at a time. The shared session previously accumulated 6+ running sites by the end of the file, which crashes memory-constrained hosts (e.g. local Linux VMs). Each blueprint test now runs with only its own site; the default onboarding site is stopped after `beforeAll`, and each newly created site is stopped after the test completes. - Update `getStopAllButton` in `main-sidebar.ts` to match both "Stop" (single running site) and "Stop all" (multiple). The button text is conditional in `running-sites.tsx`; the existing locator only matched "Stop all" exactly, which made the new cleanup logic in blueprints unreliable when one site was running. ## Testing Instructions 1. Build the app: `npm run make`. 2. Install Playwright browsers: `npx playwright install chromium`. 3. Run the full suite: `npm run e2e`. 4. Expected outcome on Linux: 43 pass, 1 skipped (`import.test.ts` is skipped without the optional `e2e/imports/jetpack-backup.tar.gz` fixture). A few editor-iframe tests may flake on the first attempt and pass on Playwright's automatic retry. Verified locally on Linux arm64 (Parallels VM). Mac/Windows behavior should be unchanged: the blueprints cleanup adds ~15-30s to that file's run time, otherwise no functional difference. ## Pre-merge Checklist - [ ] Have you checked for TypeScript, React or other console errors? - [ ] Mac and Windows E2E jobs still pass on CI.
1 parent 3981d90 commit 828d74b

3 files changed

Lines changed: 20 additions & 3 deletions

File tree

apps/studio/e2e/blueprints.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,27 @@ test.describe( 'Blueprints', () => {
1818
await onboarding.closeWhatsNew();
1919

2020
const siteContent = new SiteContent( session.mainWindow, DEFAULT_SITE_NAME );
21-
await expect( siteContent.siteNameHeading ).toBeVisible( { timeout: 120_000 } );
21+
await expect( siteContent.runningButton ).toBeAttached( { timeout: 120_000 } );
22+
23+
// Run one site at a time to keep peak memory low on constrained hosts.
24+
const sidebar = new MainSidebar( session.mainWindow );
25+
await sidebar.getStopAllButton().click();
26+
await expect( sidebar.locator.getByText( 'No sites running' ) ).toBeAttached( {
27+
timeout: 60_000,
28+
} );
2229
} );
2330

2431
test.afterEach( async ( { page: _page }, testInfo ) => {
2532
await session.reportMainProcessLogsOnFailure( testInfo );
33+
34+
const sidebar = new MainSidebar( session.mainWindow );
35+
const stopAllButton = sidebar.getStopAllButton();
36+
if ( await stopAllButton.isVisible().catch( () => false ) ) {
37+
await stopAllButton.click();
38+
await expect( sidebar.locator.getByText( 'No sites running' ) ).toBeAttached( {
39+
timeout: 60_000,
40+
} );
41+
}
2642
} );
2743

2844
test.afterAll( async () => {

apps/studio/e2e/page-objects/main-sidebar.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export default class MainSidebar {
1818
}
1919

2020
getStopAllButton() {
21-
return this.locator.getByRole( 'button', { name: 'Stop all', exact: true } );
21+
// The button is labeled "Stop" with one running site and "Stop all" with multiple.
22+
return this.locator.getByRole( 'button', { name: /^Stop( all)?$/ } );
2223
}
2324

2425
async openAddSiteModal() {

apps/studio/src/modules/cli/lib/linux-installation-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ export class LinuxCliInstallationManager implements StudioCliInstallationManager
229229
}
230230

231231
export async function autoInstallLinuxCliIfNeeded(): Promise< void > {
232-
if ( process.platform !== 'linux' || process.env.NODE_ENV !== 'production' ) {
232+
if ( process.platform !== 'linux' || process.env.NODE_ENV !== 'production' || process.env.E2E ) {
233233
return;
234234
}
235235

0 commit comments

Comments
 (0)