Skip to content

Decide where the Jotai test settle belongs, then document it #2194

Description

@kmcginnes

Description

PR #2175 bumped jotai to 3 and added an exported flushPendingAtomUpdates() to src/utils/testing/renderHookWithJotai.tsx. Its body is await act(async () => {}) and nothing else. It has one consumer, useSchemaSync.test.ts, with 10 call sites.

The helper works. Where it lives is the open question, and it needs answering before a second test file copies the pattern.

Two things make this worth settling now rather than later. docs/agents/testing.md already tells agents to use renderHookWithState and to avoid renderHookWithJotai, which is the file the helper lives in, so the sanctioned path and the helper's home disagree. And the helper is re-exported through the @/utils/testing barrel, so it reads as general-purpose when exactly one test file needs it.

The decision

Option A: move the settle inside renderHookWithState. Callers get it for free and all 10 call sites plus the barrel export disappear. The cost is that renderHookWithState becomes async, which changes a signature every hook test in the repo uses.

Option B: inline await act(async () => {}) at the few sites that genuinely need it and drop the shared export. No signature change, no shared abstraction for one consumer. The cost is that each future author rediscovers the need.

Whichever wins, the rule needs stating, including when the settle is not needed. waitFor already absorbs it, so a test asserting inside waitFor needs nothing. Without that written down, agents will add the flush to every test by reflex.

Also fold in

useResetState.test.ts has the same un-wrapped post-mount store.set pattern that #2175 wrapped in act() in useSchemaSync.test.ts, left untreated in two places (the search and query-editor reset test, and the previous-session-availability test). They pass today because the atoms they write are not ones the hook under test renders from. Same pattern, one file treated and one not, so pick one treatment and apply it to both.

Background

jotai v2 always re-rendered once right after mount, even without a value change, which absorbed store writes landing before useAtomValue subscribed. v3 drops that extra render and only re-renders on an actual change, so such a write now arrives as its own render after renderHook or store.set returns. jotai's own docs/core/use-atom.mdx documents this as the release's one behavioral caveat.

Expected outcome

  • A decision between A and B, applied
  • useResetState.test.ts consistent with useSchemaSync.test.ts
  • docs/agents/testing.md states the rule and its limit, so the next Jotai-backed hook test does not reinvent a flush

Related Issues

Important

Internal only — this issue is maintained by the core team and is not accepting external contributions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    internalSignals that the team will work on this issue internally.ready-for-humanNeeds human implementationtech debtIssues, typically tasks, that are mainly about cleaning up code that is problematic in some way

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions