Skip to content

chore(tooling): modernize test toolchain to node 26 + bun 1.3.14#5393

Merged
norman-abramovitz merged 1 commit into
cloudfoundry:developfrom
nabramovitz:chore/test-tooling-node26
May 29, 2026
Merged

chore(tooling): modernize test toolchain to node 26 + bun 1.3.14#5393
norman-abramovitz merged 1 commit into
cloudfoundry:developfrom
nabramovitz:chore/test-tooling-node26

Conversation

@nabramovitz

Copy link
Copy Markdown
Contributor

Summary

Modernizes the test toolchain to Node 26.2.0 + Bun 1.3.14 and fixes the localStorage test regression that surfaced on Node 25/26.

This started as the "switch the vitest runner to Bun" follow-up (Bun supplies its own localStorage, which made the failing spec pass). That approach turned out to be non-viable: bunx --bun vitest cannot reliably load the vite/vitest project configs that import @analogjs/vite-plugin-angular. So Bun stays the package manager / task runner, vitest runs under Node, and the localStorage issue is fixed at its real root.

Why not run vitest under Bun

bunx --bun vitest fails to load the project configs in two distinct ways, both open/unreleased upstream Bun bugs:

  1. Non-deterministic CJS interop race(0, import_vite_plugin_angular.default) is not a function (a different subset of the 8 configs fails each run). esbuild's __toESM interop + Bun's inconsistent __esModule marking under concurrent require/import. A clean single load is correct, proving it's a race.
  2. TDZ — forcing all configs to ESM removes Integrating helion-ui-framework #1 but yields ReferenceError: Cannot access 'angular' before initialization in Bun's evaluation of the esbuild-bundled config temp module.

Relevant upstream issues:

Bun 1.3.14 is the latest release and is the exact version carrying the TDZ regression — no upgrade path. Revisit the Bun runner when #30656 ships.

Changes

  • .tool-versions: Node 24.11.0 -> 26.2.0, Bun 1.3.2 -> 1.3.14.
  • package.json engines: node "^24 || ^26", bun ">=1.3.14".
  • In-range dependency bumps (no range widening): vitest 4.1.7, @analogjs/* 2.5.2, @angular/cdk 21.2.13, @angular/platform-server 21.2.14, @playwright/test 1.60.0, typescript-eslint 8.60.0, date-fns 4.3.0, plus transitive lockfile updates.
  • Test scripts: run vitest under Node and drop the NODE_OPTIONS=--localstorage-file=... flag. That flag made Node 25/26's native Web Storage file-backed and leak across test files — the original failure.
  • LocalStorageMock.getItem: return null (not '') for missing keys, matching the Storage contract. The '' divergence broke .toBeNull() assertions (e.g. dashboard-preferences "does not persist when the user is not yet known") once the flag was dropped. Fixed in both copies (src/frontend/vitest.workspace.setup.ts and core/src/test-setup.ts).
  • build/check-versions.cjs: corrected stale Node/Bun version docs.

Verification

  • Full make check green on Node 26.2.0: lint, 2407 passed / 3 skipped unit tests, production build, and jetstream Go tests all pass.
  • Browser-verified on a local make dev (Node 26): login works and a healthy CF endpoint loads fully (orgs/spaces/users/app-stats).

Originally planned as a "switch vitest runner to bun" follow-up, but
`bunx --bun vitest` cannot reliably load the vite/vitest project configs:
bun's runtime hits a non-deterministic CJS __toESM interop race
("default is not a function") and, once configs are forced ESM, a TDZ
"Cannot access 'angular' before initialization". Both are open/unreleased
upstream bun bugs (oven-sh/bun#13338, #30634; fix PR #30656 unmerged) and
1.3.14 is the latest release. So bun stays the package manager / task
runner only; vitest runs under node.

Changes:
- .tool-versions: node 24.11.0 -> 26.2.0, bun 1.3.2 -> 1.3.14
- engines: node "^24 || ^26", bun ">=1.3.14"
- in-range dep bumps (vitest 4.1.7, @analogjs 2.5.2, @angular/cdk 21.2.13,
  @playwright/test 1.60.0, typescript-eslint 8.60.0, date-fns 4.3.0, ...)
- test scripts: run `vitest` under node, drop the
  NODE_OPTIONS=--localstorage-file flag (its file-backed store leaked
  across test files on node 25/26 -- the original failure)
- LocalStorageMock.getItem: return null (not '') for missing keys, so it
  matches the Storage contract; the '' divergence broke `.toBeNull()`
  assertions (e.g. dashboard-preferences "does not persist ...") once the
  flag was dropped. Fixed in both copies (workspace + core setup).
- check-versions.cjs: correct stale node/bun version docs

Full `make check` green on node 26: 2407 passed / 3 skipped, prod build +
jetstream go tests pass.

@norman-abramovitz norman-abramovitz 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.

This PR allows the toolchain to use upgraded tools as we wait for Bun to be upgraded

@norman-abramovitz norman-abramovitz merged commit 7231758 into cloudfoundry:develop May 29, 2026
12 checks passed
@nabramovitz nabramovitz deleted the chore/test-tooling-node26 branch May 29, 2026 22:32
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.

2 participants