Unverified 提交 49375c8c authored 作者: wwwillchen-bot's avatar wwwillchen-bot 提交者: GitHub

fix: deflake E2E tests (setup_flow.spec.ts) (#2740)

## Summary - Deflake `setup_flow.spec.ts` which was the most flaky test file (20 occurrences across 10 CI runs and 5 PRs) - Wrap initial "Setup Dyad" heading check in `toPass()` with `Timeout.MEDIUM` to handle slow page renders in CI - Wrap `page.reload()` in `toPass()` retry to handle intermittent `ERR_FILE_NOT_FOUND` errors in Electron - Expand Node.js accordion section before checking for install button (section not auto-expanded after reload with mock) - Use `force: true` on "Continue" button click to avoid accordion overlap pointer interception - Replace hardcoded timeouts with `Timeout.MEDIUM` constants for CI/local adaptability ## Test plan - [x] Ran `setup_flow.spec.ts` with `--repeat-each=10` (30 tests total) - all passed - [x] Previously failed 6/10 times on "node.js install flow" test, now passes 10/10 - [x] Other top flaky specs (context_manage, chat_input, edit_code, logs_server, themes_management, fix_error) passed all repeats locally without changes - their CI flakiness is environment-specific - [x] All 819 unit tests pass - [x] Lint and type checks pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2740" 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 --> Co-authored-by: 's avatarclaude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
上级 a0bc7c73
import { testWithConfig } from "./helpers/test_helper"; import { testWithConfig, Timeout } from "./helpers/test_helper";
import { expect } from "@playwright/test"; import { expect } from "@playwright/test";
const testSetup = testWithConfig({ const testSetup = testWithConfig({
...@@ -9,10 +9,15 @@ testSetup.describe("Setup Flow", () => { ...@@ -9,10 +9,15 @@ testSetup.describe("Setup Flow", () => {
testSetup( testSetup(
"setup banner shows correct state when node.js is installed", "setup banner shows correct state when node.js is installed",
async ({ po }) => { async ({ po }) => {
// Verify the "Setup Dyad" heading is visible // Wait for the page to fully render before checking UI elements
await po.page.waitForLoadState("domcontentloaded");
// Verify the "Setup Dyad" heading is visible (use toPass for CI resilience)
await expect(async () => {
await expect( await expect(
po.page.getByText("Setup Dyad", { exact: true }), po.page.getByText("Setup Dyad", { exact: true }),
).toBeVisible(); ).toBeVisible();
}).toPass({ timeout: Timeout.MEDIUM });
// Verify both accordion sections are visible // Verify both accordion sections are visible
await expect( await expect(
...@@ -39,16 +44,25 @@ testSetup.describe("Setup Flow", () => { ...@@ -39,16 +44,25 @@ testSetup.describe("Setup Flow", () => {
testSetup("node.js install flow", async ({ po }) => { testSetup("node.js install flow", async ({ po }) => {
// Start with Node.js not installed // Start with Node.js not installed
await po.setNodeMock(false); await po.setNodeMock(false);
await po.page.reload();
await po.page.waitForLoadState("domcontentloaded");
// Verify setup banner and install button are visible // Reload with retry to handle intermittent ERR_FILE_NOT_FOUND in Electron
await expect(async () => {
await po.page.reload({ waitUntil: "domcontentloaded" });
}).toPass({ timeout: Timeout.MEDIUM });
// Verify setup banner is visible (use toPass for resilience)
await expect(async () => {
await expect( await expect(
po.page.getByText("Setup Dyad", { exact: true }), po.page.getByText("Setup Dyad", { exact: true }),
).toBeVisible(); ).toBeVisible();
}).toPass({ timeout: Timeout.MEDIUM });
// Expand the Node.js section to reveal the install button
await po.page.getByText("1. Install Node.js (App Runtime)").click();
await expect( await expect(
po.page.getByRole("button", { name: "Install Node.js Runtime" }), po.page.getByRole("button", { name: "Install Node.js Runtime" }),
).toBeVisible({ timeout: 10000 }); ).toBeVisible({ timeout: Timeout.MEDIUM });
// Manual configuration link should be visible // Manual configuration link should be visible
await expect( await expect(
...@@ -61,17 +75,16 @@ testSetup.describe("Setup Flow", () => { ...@@ -61,17 +75,16 @@ testSetup.describe("Setup Flow", () => {
.click(); .click();
// After clicking install, the "Continue" button should appear // After clicking install, the "Continue" button should appear
await expect( const continueButton = po.page.getByRole("button", {
po.page.getByRole("button", { name: /Continue.*I installed Node\.js/ }), name: /Continue.*I installed Node\.js/,
).toBeVisible(); });
await expect(continueButton).toBeVisible();
// Simulate user having installed Node.js // Simulate user having installed Node.js
await po.setNodeMock(true); await po.setNodeMock(true);
// Click the continue button // Click the continue button (use force to avoid accordion overlap issues)
await po.page await continueButton.click({ force: true });
.getByRole("button", { name: /Continue.*I installed Node\.js/ })
.click();
// Node.js should now show as installed // Node.js should now show as installed
await expect( await expect(
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论