Skip to content

test: shield the web suite from Node's built-in web storage - #416

Merged
kevinswiber merged 1 commit into
mainfrom
chore/webstorage-test-shim
Jul 7, 2026
Merged

test: shield the web suite from Node's built-in web storage#416
kevinswiber merged 1 commit into
mainfrom
chore/webstorage-test-shim

Conversation

@kevinswiber

Copy link
Copy Markdown
Member

Node 25 enabled the Web Storage API by default (nodejs/node#57666): the vitest worker's globals
then carry Node's localStorage/sessionStorage, which shadow happy-dom's and — with no
--localstorage-file backing — throw on every access (vitest-dev/vitest#8757). happy-dom's
window.localStorage delegates to the same broken storage, so re-binding to the window doesn't
help. The state is reachable on Node 22/24 via NODE_OPTIONS=--experimental-webstorage, and any
shell that skips the repo's mise pin resolves a newer node and hits it for real — a login
non-interactive shell (the shape review sandboxes use) resolves Homebrew's node 26 on a typical
setup, which is exactly how the PR #415 review environment failed 48 otherwise-green tests.

The fix is a vitest setup file that probes each storage global with a real write and, only when it
is broken or missing, installs an in-memory implementation. A healthy environment is left
completely untouched.

Verification:

  • pre-shim, NODE_OPTIONS=--experimental-webstorage: 16/16 prefs tests fail (the reported class)
  • post-shim, same flag: 642/642
  • post-shim, plain npm run check (mise node 22.23.1): 642/642
  • post-shim, real Homebrew node 26.0.0: 642/642
  • just check: 2172 passed

Node 25 enabled the Web Storage API by default (nodejs/node#57666): the
vitest worker's globals then carry Node's localStorage/sessionStorage,
which shadow happy-dom's and, with no --localstorage-file backing, throw
on every access (vitest-dev/vitest#8757). happy-dom's window.localStorage
delegates to the same broken storage. The state is reachable on Node
22/24 via NODE_OPTIONS=--experimental-webstorage, and shells that skip
the repo's mise pin (login non-interactive shells resolve Homebrew's
node 26) hit it today — a review environment failed 48 otherwise-green
tests this way.

A vitest setup file probes each storage global with a real write and,
only when it is broken or missing, replaces it with an in-memory
implementation — a healthy environment is left untouched. Verified both
ways: 642 tests pass plain and under the --experimental-webstorage
simulation, which failed 16/16 in prefs.test.ts before the shim.
@kevinswiber
kevinswiber merged commit ebc2ade into main Jul 7, 2026
9 checks passed
@kevinswiber
kevinswiber deleted the chore/webstorage-test-shim branch July 7, 2026 05:56
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