Unverified 提交 70c010af authored 作者: wwwillchen-bot's avatar wwwillchen-bot 提交者: GitHub

feat: enable parallel Playwright e2e test execution (#2547)

## Summary - Skip the Electron singleton lock for E2E test builds to allow multiple app instances to run concurrently - Update Playwright config to use 2 workers for parallel test execution ## Performance Impact With parallelism of 2, tests should complete approximately **~1.6-1.8x faster** (not a perfect 2x due to overhead and some sequential test dependencies). The speedup comes from: - Two Electron app instances can now run simultaneously during E2E tests - Previously, the singleton lock (`app.requestSingleInstanceLock()`) would cause second instances to quit immediately ## Implementation Details - Modified `src/main.ts` to check `IS_TEST_BUILD` and skip the singleton lock for e2e test builds - Changed `playwright.config.ts` from `workers: 1` to `workers: 2` ## Test plan - [ ] Run `npm run build` to ensure the e2e build compiles correctly - [ ] Run `npx playwright test` to verify tests pass with parallel execution - [ ] Verify no race conditions occur when multiple app instances run simultaneously 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2547" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Enable parallel Playwright E2E tests by skipping Electron’s single-instance lock in test builds and reading worker count from PLAYWRIGHT_PARALLELISM. CI sets 3 workers on self-hosted macOS (1 elsewhere), keeping single-instance behavior in production. - **Bug Fixes** - Prevent crash in second-instance handler when no deep link URL; clarify deep link handling for test builds. <sup>Written for commit 0f542e189f5b17cc857acc9ad07955c47a0049f1. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWill Chen <willchen90@gmail.com> Co-authored-by: 's avatarClaude Opus 4.5 <noreply@anthropic.com>
上级 5da907b2
...@@ -290,6 +290,8 @@ jobs: ...@@ -290,6 +290,8 @@ jobs:
- name: E2E tests (Shard ${{ matrix.shard }}/${{ matrix.shardTotal }}) - name: E2E tests (Shard ${{ matrix.shard }}/${{ matrix.shardTotal }})
env: env:
FLAKINESS_ACCESS_TOKEN: ${{ secrets.FLAKINESS_ACCESS_TOKEN }} FLAKINESS_ACCESS_TOKEN: ${{ secrets.FLAKINESS_ACCESS_TOKEN }}
# Self-hosted macOS runners can handle more parallelism
PLAYWRIGHT_PARALLELISM: ${{ contains(matrix.os.image, 'self-hosted') && '3' || '1' }}
# You can add debug logging to make it easier to see what's failing # You can add debug logging to make it easier to see what's failing
# by adding "DEBUG=pw:browser" in front. # by adding "DEBUG=pw:browser" in front.
# Use blob reporter for sharding and merge capabilities # Use blob reporter for sharding and merge capabilities
......
...@@ -5,7 +5,9 @@ const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); ...@@ -5,7 +5,9 @@ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
const config: PlaywrightTestConfig = { const config: PlaywrightTestConfig = {
testDir: "./e2e-tests", testDir: "./e2e-tests",
workers: 1, // Enable parallel test execution - E2E test builds skip the singleton lock
// Read parallelism from env var, default to 1 if not set
workers: parseInt(process.env.PLAYWRIGHT_PARALLELISM || "1", 10),
retries: process.env.CI ? 2 : 0, retries: process.env.CI ? 2 : 0,
timeout: process.env.CI ? 180_000 : 75_000, timeout: process.env.CI ? 180_000 : 75_000,
// Use a custom snapshot path template because Playwright's default // Use a custom snapshot path template because Playwright's default
......
...@@ -380,21 +380,31 @@ const createApplicationMenu = () => { ...@@ -380,21 +380,31 @@ const createApplicationMenu = () => {
Menu.setApplicationMenu(appMenu); Menu.setApplicationMenu(appMenu);
}; };
const gotTheLock = app.requestSingleInstanceLock(); // Skip singleton lock for E2E test builds to allow parallel test execution.
// Deep link handling still works via the 'open-url' event registered below.
if (!gotTheLock) { // The 'second-instance' handler is intentionally omitted since it requires the singleton lock.
app.quit(); if (IS_TEST_BUILD) {
} else {
app.on("second-instance", (_event, commandLine, _workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
// the commandLine is array of strings in which last element is deep link url
handleDeepLinkReturn(commandLine.pop()!);
});
app.whenReady().then(onReady); app.whenReady().then(onReady);
} else {
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on("second-instance", (_event, commandLine, _workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
// the commandLine is array of strings in which last element is deep link url
const url = commandLine.at(-1);
if (url) {
handleDeepLinkReturn(url);
}
});
app.whenReady().then(onReady);
}
} }
// Handle the protocol. In this case, we choose to show an Error Box. // Handle the protocol. In this case, we choose to show an Error Box.
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论