test: keep jsdom's localStorage under Node 26 - #144
Conversation
- Node 26 ships localStorage as a lazy global; vitest 4 keeps a global it finds over jsdom's - Node 26 failed 40/186 connect, 274/274 dappbooster and 18/155 frontend tests; Node 24 passes - --no-experimental-webstorage in the workers drops Node's global, so jsdom's lands as on Node 24 - Fixed in vitest 5 (vitest-dev/vitest#10293), refused for v4 (#10873); drop the line on that bump
- engines.node has no upper bound, but every job pins .nvmrc, so Node 26 was never exercised - A separate job keeps the `3 - test` name the ruleset requires; add this one there after merge
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
🔵 Needs a closer look
It modifies the CI/CD workflow, which the repository guardrails state must not be changed without team review, and it carries a documented manual follow-up (making the new job a required check via a ruleset edit).
Pull request overview
This PR fixes a test-environment regression that surfaces on Node 26. Node 25+ ships localStorage as a global by default, and under vitest 4 the test runner keeps a global it already finds rather than copying jsdom's, so every suite gets Node's storage (which returns undefined without --localstorage-file) and fails before its first assertion. The fix passes --no-experimental-webstorage to the vitest worker processes so jsdom's localStorage is used, restoring the Node 24 behavior. It also adds a CI job that runs the suites on Node 26 alongside the pinned Node 24, since engines.node has no upper bound and Node 26 was never exercised.
I verified the approach is sound: test.execArgv is a valid top-level option in vitest 4 (poolOptions were flattened to top-level in v4), and --experimental-webstorage has existed since Node 22.4.0, so --no-experimental-webstorage is accepted (and a harmless no-op) on the pinned Node 24.15+ while disabling the shadowing global on Node 25/26. The new CI job mirrors the existing test job exactly, differing only in the Node version.
Changes:
- Add
execArgv: ['--no-experimental-webstorage']to the three jsdom vitest configs (canton-connect,canton-dappbooster,dapp/frontend) with an explanatory comment. - Add a
test-node-26CI job to.github/workflows/pr.ymlrunningpnpm teston Node 26.
File summaries
| File | Description |
|---|---|
canton-connect/vitest.config.ts |
Passes --no-experimental-webstorage to workers so jsdom's localStorage is used under Node 26. |
canton-dappbooster/vitest.config.ts |
Same flag; this suite's afterEach calls localStorage.clear(), which depends on jsdom's storage. |
dapp/frontend/vite.config.ts |
Same flag added to the nested vitest test block (its LedgerBackend tests touch localStorage). |
.github/workflows/pr.yml |
Adds a test-node-26 job that runs the suites on Node 26 beside the pinned Node 24 job. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
Closes #132
On Node 26 every vitest suite in the repo fails before its first assertion. Node now ships
localStorageas a global, and vitest 4 keeps a global it already finds instead of copying jsdom's, so the tests getundefined.engines.nodehas no upper bound, so Node 26 is supported on paper, and CI never ran it.Changes
--no-experimental-webstorage, so jsdom'slocalStoragelands on Node 26 as it does on 24Deviations
Acceptance criteria
engines.nodeTest plan
Automated tests
mainunder Node 26 (nvm use 26), runpnpm test; expect failures in every suite withCannot read properties of undefinedpnpm test; expect every suite greennvm use(Node 24 from.nvmrc) andpnpm testagain; expect the sameManual verification
3 - test (node 26)green beside3 - testBreaking changes
None.
Checklist
Screenshots
None.