[No QA] Fix flaky ContactMethodsPage and UnreadIndicators tests - #92587
Merged
madmax330 merged 3 commits intoJun 4, 2026
Merged
Conversation
Align the post-render Onyx merges in signInAndGetApp() with the UnreadIndicatorsTest pattern: issue merges as a bare Promise.all and let the final waitForBatchedUpdatesWithAct drain them, rather than wrapping them in act() which forces a synchronous React flush that is significantly slower under CI coverage instrumentation. Co-authored-by: Cursor <cursoragent@cursor.com>
ContactMethodsPageTest: after merging only validatedDate the Onyx subscriber notification is queued as a macrotask, so waitFor's act() saw stale state on every retry. Adding waitForBatchedUpdates() before waitFor ensures the notification is delivered to the useOnyx hook and the component re-renders before the assertion runs. UnreadIndicatorsTest: the 'Display bold in the LHN' test ended with waitFor(() => expect(isNewMessagesBadgeVisible()).toBe(true)). Under heavy CI load each waitFor retry wraps its callback in act(), which can stall for many seconds draining scroll-triggered cascading effects, eventually blowing the 120 s Jest timeout. Replacing waitFor+act with waitForBatchedUpdates() + a direct assertion matches the pattern used by every other test in the file and removes the act() overhead that caused the hang. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@marcochavezf Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
madmax330
approved these changes
Jun 4, 2026
Contributor
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
Contributor
|
🚀 Deployed to staging by https://github.com/madmax330 in version: 9.4.0-0 🚀
Bundle Size Analysis (Sentry): |
Contributor
|
🚀 Deployed to production by https://github.com/Julesssss in version: 9.4.0-7 🚀
|
This was referenced Jun 17, 2026
brunovjk
pushed a commit
to brunovjk/Expensify-App
that referenced
this pull request
Jun 17, 2026
Complete the PR Expensify#92587 waitFor pattern, avoid act() stalls during chat navigation, and raise the Jest timeout to 240s for loaded CI runners. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Explanation of Change
Two flaky tests in CI job 7/8 were investigated and fixed:
ContactMethodsPageTest—sets info indicator when login is unvalidated and not defaultAfter
await Onyx.merge(ONYXKEYS.LOGIN_LIST, {validatedDate: '2024-02-02'})the Onyx subscriber notification is delivered on the next macrotask tick, after the merge promise resolves.waitForimmediately wraps its first retry inact(), which only flushes already-queued React state updates — it cannot see the Onyx notification that hasn't fired yet. Addingawait waitForBatchedUpdates()beforewaitForensures the notification reaches theuseOnyxhook and the component re-renders before the assertion runs.The first test in the file (
sets error indicator) passed because mergingerrorFields: nullalongsidevalidatedDateproduces a structurally larger Onyx diff that happens to flush the notification synchronously in practice; the second test merging onlyvalidatedDateexposed a race thatwaitForBatchedUpdates()eliminates.UnreadIndicatorsTest—Display bold in the LHN for unread chat and new line indicator above the chat message when we navigate to itThe test ended with
return waitFor(() => expect(isNewMessagesBadgeVisible()).toBe(true)). Under heavy CI load (5 concurrent test shards on the same 8-vCPU runner) eachwaitForretry wraps its callback inact().act()stalls while draining the cascading scroll-triggered effects (setIsFloatingMessageCounterVisible, Reanimated shared-value updates, etc.), and on a CPU-starved runner each stall can be many seconds long. With the default 1000 mswaitFortimeout split into 50 ms intervals, only ~20 retries are attempted, but each retry'sact()draining exceeds that window, letting the total balloon past the 120 000 ms Jest limit.Replacing
waitFor + actwithawait waitForBatchedUpdates()followed by a direct synchronous assertion matches the pattern used by every other test in the samedescribeblock, avoidsact()overhead entirely, and is sufficient because the badge'stranslateYis already at the expected value by the time the microtask queue is drained.Fixed Issues
$ Internal — no GitHub issue; reproducer: https://github.com/Expensify/App/actions/runs/26909698301/job/79384087487
Tests
npx jest tests/ui/ContactMethodsPageTest.tsx— both tests pass.npx jest tests/ui/UnreadIndicatorsTest.tsx --testNamePattern="Display bold in the LHN"— passes in ~9 s locally.UnreadIndicatorsTestsuite and confirm no regressions.Offline tests
N/A — no offline behavior changed.
QA Steps
N/A — [No QA] test-only change; no production behavior changed.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari