Skip to content

Flaky test teardown: Mantine Transition timer fires after happy-dom window teardown (window is not defined) #1760

Description

@cliffhall

Problem

An npm run coverage / CI build job can fail even when all tests pass, because Vitest exits non-zero on 1 unhandled error:

⎯⎯ Uncaught Exception ⎯⎯
ReferenceError: window is not defined
 ❯ resolveUpdatePriority node_modules/react-dom/cjs/react-dom-client.development.js:1308:7
 ❯ requestUpdateLane   react-dom-client.development.js:16345:11
 ❯ dispatchSetState    react-dom-client.development.js:9126:14
 ❯ Timeout._onTimeout  @mantine/core/esm/components/Transition/use-transition.mjs:61:13
 ❯ listOnTimeout       node:internal/timers:585:17
This error originated in "src/components/groups/ServerRemoveConfirmModal/ServerRemoveConfirmModal.test.tsx"

Observed on PR #1759's CI (build run 30098049855) — 298 passed / 4426 tests passed, but Errors: 1 error → exit 1.

Root cause

ServerRemoveConfirmModal renders a Mantine Modal, which drives an open/close Transition via a setTimeout. The test doesn't wait for the transition to settle / unmount cleanly, so a pending Transition timer can fire after the happy-dom environment (and its window) has been torn down at the end of the run. The timer's dispatchSetState then hits resolveUpdatePriority, which reads windowReferenceError. It's timing-dependent, so it only trips occasionally (it did not reproduce under a local npm run ci).

This is a general class issue — any component test rendering a Mantine Transition/Modal/Menu/Popover through renderWithMantine is exposed, not just this one modal.

Recommended fix

clients/web/src/test/renderWithMantine.tsx wraps in <MantineProvider theme={theme} defaultColorScheme="light"> without env="test". Setting env="test" makes Mantine render transitions synchronously (no setTimeout), which eliminates the whole class of post-teardown timer races in one place:

<MantineProvider theme={theme} defaultColorScheme="light" env="test">

Validate that no test relies on transition timing after the switch (a few may need a waitFor/findBy adjustment). Alternative/narrower options: give the modal transitionProps={{ duration: 0 }} in the test, or vi.useFakeTimers() + flush before unmount — but env="test" on the shared provider is the durable, repo-wide fix.

Impact

Low correctness risk (all assertions pass), but it can red an otherwise-green CI run, so worth making deterministic.

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions