Skip to content

chore(tests): ratchet real wall-clock waits in unit tests - #8954

Merged
waleedlatif1 merged 9 commits into
stagingfrom
chore/test-sleep-ratchet
Oct 13, 2026
Merged

waleedlatif1 merged 9 commits into
stagingfrom
chore/test-sleep-ratchet

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

sleep( in tests went from 138 to 220 in 30 days, even though sim-testing.md already says "No real timers". use-chat.dom.test.tsx alone waits about 17s for real. This change makes that rule enforced instead of advisory, using the same approach as eslint-plugin-playwright's no-wait-for-timeout.

New real-wait rule in check:test-patterns, applied to *.test.ts(x) only:

Flagged

  • sleep and interruptibleSleep, resolved through their @sim/utils/helpers import (aliases included)
  • setTimeout from node:timers/promises
  • a new Promise resolved by setTimeout

Not flagged

  • zero or missing delays
  • reject-only timers
  • files that mock @sim/utils/helpers
  • *.integration.ts and *.live.test.ts, which wait on real services

Fake timers: a wait passes when an earlier vi.useFakeTimers() fakes setTimeout for it, either in the same function or module, or in a beforeEach/beforeAll of an enclosing describe. toFake: ['Date'] and shouldAdvanceTime: true don't count. Each wait is its own numbered baseline entry, so adding a wait to an already-baselined file still fails.

Initial baseline: 121 existing waits across 46 files. The baseline normally only shrinks, so it gets a one-time --update --init-rule <rule>, which admits entries only for a known rule the baseline doesn't track yet. It refuses unknown rules and rules already tracked. No other rule's entries change.

Tests: 28 table-driven fixture tests in check-test-patterns.test.ts. Each of the 16 guards was reverted in turn and turned at least one test red.

Test plan

  • check:audits (check:test-patterns with 193 baselined entries)
  • Script tests (check-test-patterns.test.ts)

…-patterns real-wait)

New `real-wait` rule in scripts/check-test-patterns.ts flags a unit test that
waits on the wall clock with no fake timers in scope:

- `sleep`/`interruptibleSleep` resolved through their `@sim/utils/helpers`
  import binding (aliases included; skipped when the file mocks that module),
- `setTimeout` from `node:timers/promises`,
- `new Promise((resolve) => setTimeout(resolve, ms))` and variants whose timer
  callback resolves the promise (reject-only timeout guards are not waits).

Zero or omitted delays are macrotask flushes and are not flagged. Fake timers
cover a wait when an earlier `vi.useFakeTimers()` in an enclosing function or
the module, or a `beforeEach`/`beforeAll` of an enclosing describe or the
module, fakes `setTimeout` (`toFake: ['Date']` and `shouldAdvanceTime: true`
do not). Integration and *.live.test.ts files are exempt: their waits are on
real services. Each occurrence is a numbered entry, capping the count per file.

`--update --init-rule <rule>` admits the one-time baseline for a rule the
baseline does not track yet; `--update` stays shrink-only. Baseline: 121
real-wait entries across 46 files (72 -> 193 total).
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Oct 13, 2026 4:34am UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Confidence score: 4/5

  • scripts/check-test-patterns.ts can exempt await sleep(100) that runs before vi.useFakeTimers() in the same hook. Limit the exemption to waits after fake timers are installed.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/check-test-patterns.ts">

<violation number="1" location="scripts/check-test-patterns.ts:383">
P2: This marks a hook-installed clock active across its whole suite, so `await sleep(100)` before `vi.useFakeTimers()` in the same hook is incorrectly exempted. Exclude hook-body waits that occur before installation while retaining the exemption for test callbacks.</violation>
</file>

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts Outdated
… its own hook

A beforeEach/beforeAll that installs fake timers covered its whole suite,
including waits earlier in the same hook body, which run on the real clock.
Only waits after the install in that hook are exempt now; tests and other
hooks in the suite keep the exemption.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@greptile-apps

greptile-apps Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge.

Summary

This PR adds the real-wait check and records existing waits in the baseline.

  • The test-pattern check now catches new real-time waits in unit tests.

Reviews (9) · Last reviewed commit: "fix(tests): recognize module-scope helpe..." · Reviewed by Greptile

Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts
Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Requires human review: Auto-approval blocked because this review re-detected 2 unresolved issues already reported by Cubic.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts
…it-rule

- Remove `--update --init-rule`: it admitted entries for any rule with no
  remaining baseline entries. `--update` is strictly shrink-only again; the
  real-wait entries enter once, in this PR's baseline diff.
- `vi.useRealTimers()` ends the exemption from where it runs, including a
  nested suite restoring real timers after an outer hook faked them.
- A clock installed in `beforeEach` no longer covers `beforeAll`/`afterAll`
  or earlier sibling `beforeEach` hooks; `beforeAll` no longer covers earlier
  sibling `beforeAll` hooks.
- Only `vi.useFakeTimers()` with no config, or a literal config proven to fake
  setTimeout without shouldAdvanceTime, exempts a wait.
- Namespace imports (`helpers.sleep`, `timers.setTimeout`) are flagged.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

…ons declared above it

Functions run only after the module loads, so a module-scope vi.useFakeTimers()
(or vi.useRealTimers()) applies to every function body regardless of source
order; module-scope waits still follow source order.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

Comment thread scripts/check-test-patterns.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

…y when nothing ran before it

A helper called at module scope before vi.useFakeTimers() waits on the real
clock. A module-scope install now reaches function bodies only when every
earlier module-scope statement is load-safe (imports, function/class
declarations, type-only statements, vi.mock/doMock/hoisted, and variables
whose initializers call nothing); otherwise source order applies. A
module-scope vi.useRealTimers() still reaches every function body.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts Outdated
Comment thread scripts/check-test-patterns.ts Outdated
… install

Any unrelated module-scope call (const run = vi.fn()) used to drop the
helper exemption. Now a module-scope vi.useFakeTimers() covers every function
body except a helper (function declaration or variable bound to a function)
that earlier module-scope code calls directly by name; calls through other
helpers are not traced. WAIT_EXPORTS and HOOK_KINDS are as const.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/check-test-patterns.ts
Comment thread scripts/check-test-patterns.ts Outdated
…ed in a type assertion

helperName now unwraps as/satisfies/non-null/parenthesized initializers with
the shared unwrap helper, so a wrapped arrow called before a module-scope
vi.useFakeTimers() stays flagged.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit 18b1750 into staging Oct 13, 2026
50 checks passed
@waleedlatif1
waleedlatif1 deleted the chore/test-sleep-ratchet branch October 13, 2026 05:51

This branch was successfully deployed

1 active deployment
Preview — 9e047468 Deployed Oct 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant