fix(e2e): replace wall-clock waits with product-emitted signals - #271
Merged
Conversation
Structural fix for shard 1/3 flakiness. Stops patching individual tests.
Root cause: tests asserted on async effects (CSS smooth-scroll completion,
cross-device CRDT convergence) that the product emits no readiness signal
for, and compensated with fixed waitForTimeout values tuned for fast local
dev boxes. Under CI xvfb load those values were exceeded and tests read
mid-flight state. Previous stabilizations only widened the wall-clock
windows.
Three layered changes:
1. Product signals (minimal, targeted):
- src/renderer/components/calendar/calendar-week-view.tsx: expose
anchorDate + visibleDayStart as data attributes so tests can observe
state directly instead of reverse-engineering via scrollLeft.
- src/main/test-hooks.ts: add hasNoteOnDevice(noteId) hook returning
recordPresent/crdtPresent/crdtBody for the local device. Lets tests
probe replication with a single main-process roundtrip instead of
polling UI body text through the renderer.
2. Reusable test primitives (new wait-helpers.ts):
- waitForStable<T>: polls a value and returns when it has not changed
for stableFor ms, or throws on timeout. Signal-based, CI-safe.
- waitForNoteReplicated: wraps the new test hook and normalizes the
expected body. Replaces the loop-then-hard-equal pattern.
- getAnchorDate / waitForAnchorDate / getVisibleDayStart helpers.
3. Test rewrites:
- calendar-week-scroll.e2e.ts: assertions shifted from pixel-tolerance
scrollLeft comparisons to user-observable semantics (visible week
moved forward, Today returns to origin within 1-day rounding slack).
Deleted the waitForTimeout-based waitForScrollSettle helper.
- body-crdt-coverage-variants.e2e.ts V6: replaced the syncBothAndWait
inside expect.poll loop with one sync round-trip plus per-device
waitForNoteReplicated in parallel. Removed the orphaned
readReplicatedNoteStatus helper.
Verification: 5 consecutive green local runs under TZ=UTC CI=1 --workers=1
--retries=0 on the three CI-failing tests (~23s per 4-test batch). Full
body-crdt-coverage-variants + calendar + calendar-comprehensive +
calendar-week-scroll suites: 29 passed, 1 skipped, 0 failed (3.7 min).
typecheck:web and typecheck:node clean.
Follow-up (not in this change): migrate ~300 waitForTimeout call sites
across 21 files to waitForStable; shard rebalance; warm-cache fixtures.
This was referenced Apr 18, 2026
h4yfans
added a commit
that referenced
this pull request
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Structural fix for the recurring shard 1/3 failures. Stops patching individual flakes with bigger timeouts.
calendar-week-view.tsxemitsdata-anchor-date+data-visible-day-start;test-hooks.tsexposeshasNoteOnDevice(noteId)for direct main-process replication probing.tests/e2e/utils/wait-helpers.ts):waitForStable,waitForNoteReplicated,waitForAnchorDate,getAnchorDate,getVisibleDayStart.calendar-week-scroll.e2e.ts→ semantic user-observable assertions (visible week moved forward, Today returns to origin within 1-day rounding slack).body-crdt-coverage-variants.e2e.tsV6 → onesyncBothAndWait+ parallelwaitForNoteReplicatedon both devices via the new hook. Removed the orphanedreadReplicatedNoteStatus.Test plan
TZ=UTC CI=1 --workers=1 --retries=0)pnpm typecheck:webandpnpm typecheck:nodecleanFollow-up (not in this PR)
waitForTimeoutcall sites across 21 files towaitForStable(one file per PR)🤖 Generated with Claude Code