Skip to content

fix(tests): resolve flaky fetch count assertions in MiddlewareTest#90724

Closed
ykd007 wants to merge 1 commit into
Expensify:mainfrom
ykd007:fix/flaky-middleware-test-90660
Closed

fix(tests): resolve flaky fetch count assertions in MiddlewareTest#90724
ykd007 wants to merge 1 commit into
Expensify:mainfrom
ykd007:fix/flaky-middleware-test-90660

Conversation

@ykd007

@ykd007 ykd007 commented May 14, 2026

Copy link
Copy Markdown

/claim #90660

Problem

Two tests in tests/unit/MiddlewareTest.ts were intermittently failing on:

expect(global.fetch).toHaveBeenCalledTimes(2)

Failures confirmed in CI run #33684 — attempt 1 failed, attempt 2 passed, classic timing flake.

Root Cause

The HandleUnusedOptimisticID middleware intercepts the first request's response, reads preexistingReportID out of the Onyx update, then patches the second request's data before it fires. This chain runs across multiple async cycles:

  1. First fetch resolves
  2. Onyx processes the merge (1 batch cycle)
  3. Middleware reacts to Onyx change, updates queued request (another batch cycle)
  4. Second fetch fires

waitForNetworkPromises() only covers 2 batch cycles (it's waitForBatchedUpdates().then(waitForBatchedUpdates)). That's enough for step 2 but not steps 3 and 4. On loaded CI runners, the assertion fires before step 4 completes.

The 'OpenReport to a chat' test had the same issue but used only waitForBatchedUpdates() — even less robust.

Fix

Add an extra waitForBatchedUpdates() + waitForNetworkPromises() pass after the initial wait to fully drain the async queue before asserting on call counts.

No logic changes — the tests were conceptually correct, just not waiting long enough.

The two HandleUnusedOptimisticID tests were intermittently failing on
the assertion that global.fetch was called exactly twice. The root cause
is a timing gap between the first request completing, Onyx processing
the preexistingReportID update, the middleware updating the second
request's data, and the second fetch actually firing.

waitForNetworkPromises() alone (which runs 2 batch cycles) was not
enough to flush the full async chain. Adding an extra batched-updates
and network-promises pass ensures all microtasks and macro-tasks settle
before we assert on call counts.

Also fixes the 'OpenReport to a chat' test which used only
waitForBatchedUpdates() — also insufficient for the same reason.

Fixes Expensify#90660
@ykd007 ykd007 requested a review from a team as a code owner May 14, 2026 19:58
@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi @ykd007, thanks for your interest in contributing to Expensify!

This PR has been automatically closed because it doesn't appear to meet our contribution requirements:

  • You are not a member of the Expensify GitHub organization
  • No linked GitHub issue was found in the PR description where you are listed as an assignee
  • No linked GitHub PR was found in the PR description where you are the author or a reviewer

If you'd like to contribute, please make sure to:

  1. Find an open issue you'd like to work on
  2. Get assigned to the issue by following our contribution process
  3. Link the issue in your PR description using the format: $ https://github.com/Expensify/App/issues/<issueID>

Please review our contributing guidelines for more details.

If you believe this was closed in error, please reach out in the #expensify-open-source Slack channel.

@github-actions github-actions Bot closed this May 14, 2026
@github-actions github-actions Bot locked as spam and limited conversation to collaborators May 14, 2026
@melvin-bot melvin-bot Bot requested review from deetergp and removed request for a team May 14, 2026 19:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant