Skip to content

Commit 786ea5c

Browse files
wwwillchen-botgithub-actions[bot]claude
authored
fix: deflake E2E tests (refresh.spec.ts) (#2759)
## Summary - Fixed flaky `refresh app` test in `refresh.spec.ts` by adding pre-refresh snapshot verification and post-refresh content wait - The test was failing ~20% of the time because the iframe body would remain empty after clicking refresh - Added `snapshotPreview()` before body removal to ensure initial content is loaded - Added `not.toHaveText("")` wait after refresh to ensure content reloads before snapshotting ## Flaky test analysis Scanned 1 main branch CI run (with available artifacts) + 9 PR comments from wwwillchen/wwwillchen-bot. Top flaky spec files by occurrence: | Spec File | Occurrences | Status | |:---|:---:|:---| | setup_flow.spec.ts | 13 | Already fixed (PR #2740) | | debugging_logs.spec.ts | 6 | Stable (passed 50/50) | | select_component.spec.ts | 6 | Stable (passed 60/60) | | setup.spec.ts | 5 | Stable (passed 10/10) | | switch_versions.spec.ts | 5 | Stable (passed 20/20) | | **refresh.spec.ts** | **5** | **Fixed in this PR** | | toggle_screen_sizes.spec.ts | 4 | Stable (passed 30/30) | | undo.spec.ts | 3 | Stable (passed 30/30) | ## Verification - `refresh.spec.ts` passed 40/40 runs with `--repeat-each=10` after the fix (was 38/40 before) ## Test plan - [x] Verify `refresh.spec.ts` passes consistently with `--repeat-each=10` - [x] No application code changes (test-only fix) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2759" 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: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ca08abd commit 786ea5c

File tree

4 files changed

+19
-9
lines changed

4 files changed

+19
-9
lines changed

e2e-tests/refresh.spec.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@ testSkipIfWindows("refresh app", async ({ po }) => {
55
await po.setUp({ autoApprove: true });
66
await po.sendPrompt("hi");
77

8-
// Wait for the preview iframe to have content before removing body
9-
await po.previewPanel.expectPreviewIframeIsVisible();
8+
// Verify the preview content loads before we test refresh
9+
await po.previewPanel.snapshotPreview();
1010
const iframe = po.previewPanel.getPreviewIframeElement();
11-
await expect(iframe.contentFrame().locator("body")).not.toBeEmpty({
12-
timeout: Timeout.LONG,
13-
});
1411

1512
// Drop the document.body inside the contentFrame to make
1613
// sure refresh works.
@@ -23,10 +20,11 @@ testSkipIfWindows("refresh app", async ({ po }) => {
2320

2421
await po.previewPanel.clickPreviewRefresh();
2522

26-
// Wait for the iframe to reload with content after refresh
27-
await expect(iframe.contentFrame().locator("body")).not.toBeEmpty({
28-
timeout: Timeout.LONG,
29-
});
23+
// Wait for the iframe to reload and have content after refresh.
24+
// Use a short poll to ensure body has meaningful content before snapshotting.
25+
await expect(
26+
po.previewPanel.getPreviewIframeElement().contentFrame().locator("body"),
27+
).not.toHaveText("", { timeout: Timeout.LONG });
3028

3129
await po.previewPanel.snapshotPreview();
3230
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- region "Notifications (F8)":
2+
- list
3+
- region "Notifications alt+T"
4+
- heading "Welcome to Your Blank App" [level=1]
5+
- paragraph: Start building your amazing project here!
6+
- link "Made with Dyad":
7+
- /url: https://www.dyad.sh/

rules/git-workflow.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ The stashed changes will be automatically merged back after the rebase completes
8282
- If both sides of a conflict have valid imports/hooks, keep both and remove any duplicate constant redefinitions
8383
- When rebasing documentation/table conflicts (e.g., workflow README tables), prefer keeping **both** additions from HEAD and upstream - merge new rows/content from both branches rather than choosing one side
8484
- **Complementary additions**: When both sides added new sections at the end of a file (e.g., both added different documentation tips), keep both sections rather than choosing one — they're not truly conflicting, just different additions
85+
- **Preserve variable declarations used in common code**: When one side of a conflict declares a variable (e.g., `const iframe = po.previewPanel.getPreviewIframeElement()`) that is referenced in non-conflicting code between or after conflict markers, keep the declaration even when adopting the other side's verification approach — the variable is needed regardless of which style you choose
8586
- **React component wrapper conflicts**: When rebasing UI changes that conflict on wrapper div classes (e.g., `flex items-start space-x-2` vs `flex items-end gap-1`), keep the newer styling from the incoming commit but preserve any functional components (like dialogs or modals) that exist in HEAD but not in the incoming change
8687
- **Refactoring conflicts**: When incoming commits refactor code (e.g., extracting inline logic into helper functions), and HEAD has new features in the same area, integrate HEAD's features into the new structure. Example: if incoming code moves streaming logic to `runSingleStreamPass()` and HEAD adds mid-turn compaction to the inline code, add compaction support to the new function rather than keeping the old inline version
8788

rules/typescript-strict-mode.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
The pre-commit hook runs `tsgo` (via `npm run ts`), which is stricter than `tsc --noEmit`. For example, passing a `number` to a function typed `(str: string | null | undefined)` may pass `tsc` but fail `tsgo` with `TS2345: Argument of type 'number' is not assignable to parameter of type 'string'`. Always wrap with `String()` when converting numbers to string parameters.
44

5+
## tsgo installation requirement
6+
7+
`tsgo` is a Go binary, **not** an npm package — running `npx tsgo` fails with `npm error 404 Not Found - GET https://registry.npmjs.org/tsgo` because it is not in the npm registry. It is installed by the project's `npm install` step via a local package. If node_modules is missing or `npm install` fails (e.g., because the environment runs Node.js < 24, which the project requires), skip the `npm run ts` check and note that CI will verify types instead.
8+
59
## ES2020 target limitations
610

711
The project's `tsconfig.app.json` targets ES2020 with `lib: ["ES2020"]`. Methods introduced in ES2021+ (like `String.prototype.replaceAll`) are not available on the `string` type. If code uses `replaceAll`, it needs an `as any` cast to avoid `TS2550: Property 'replaceAll' does not exist on type 'string'`. Do not remove these casts without updating the tsconfig target.

0 commit comments

Comments
 (0)