Skip to content

ci: add Node.js 24 to test matrix#13358

Merged
gr2m merged 23 commits intomainfrom
add-node-24-to-ci
Mar 16, 2026
Merged

ci: add Node.js 24 to test matrix#13358
gr2m merged 23 commits intomainfrom
add-node-24-to-ci

Conversation

@gr2m
Copy link
Copy Markdown
Collaborator

@gr2m gr2m commented Mar 12, 2026

Summary

Adds Node.js 24 to the CI test matrix and fixes all build/test incompatibilities.

Closes #13357

Changes

CI & config

  • Adds Node.js 24 to .github/workflows/ci.yml test matrix
  • Adds ^24.0.0 to root package.json engines field

SvelteKit example build fix

  • Updates @sveltejs/adapter-vercel from v5 to v6 and @sveltejs/kit to v2.55+ in examples/sveltekit-openai — adapter-vercel v5 only supported Node 18/20/22, v6 adds Node 24

Vitest v2 → v4 upgrade

Node 24 ships with undici v7, which enforces strict AbortSignal instanceof checks in fetch(). The jsdom environment in vitest v2/v3 replaces the global AbortController/AbortSignal with its own polyfill, and Node 24's native fetch rejects these with "Expected signal to be an instance of AbortSignal". Vitest v4 stops overriding these globals (vitest-dev/vitest#8390), fixing the incompatibility.

Test adaptations required by vitest v4

vi.fn() arrow functions can no longer be used as constructors — vitest v4 wraps mock functions differently, so arrow-function mocks fail with TypeError: is not a constructor when called with new. Fixed by changing arrow functions to function expressions in mock implementations:

  • packages/amazon-bedrock/src/bedrock-event-stream-response-handler.test.ts
  • packages/baseten/src/baseten-provider.unit.test.ts
  • packages/gateway/src/gateway-provider.test.ts
  • packages/google-vertex/src/google-vertex-auth-google-auth-library.test.ts

toStrictEqual(expect.objectContaining(...)) is stricter — vitest v4 now requires that undefined properties on the actual object (e.g. metadata: undefined) also appear in the expected pattern. Since these tests intentionally do partial matching, changed to toEqual(expect.objectContaining(...)):

  • packages/angular/src/lib/chat.ng.test.ts
  • packages/svelte/src/chat.svelte.test.ts

toThrowError with an Error object checks all properties — previously only checked message, now checks every property. The anthropic overloaded-error test compared requestBodyValues: {} against the full request body. Changed to try/catch with individual property assertions:

  • packages/anthropic/src/anthropic-messages-language-model.test.ts

test.workspace renamed to test.projects:

  • packages/svelte/vite.config.ts

Other test fixes

  • packages/openai and packages/elevenlabs: Made File object snapshot tests Node version-agnostic (Node 24 serializes additional Symbol(state) on File objects)
  • packages/mcp: Fixed race condition in SSE reconnect test where server.calls[2] was accessed before the fire-and-forget openInboundSse() completed — added vi.waitFor()
  • Pinned tinyexec to 1.0.2 via pnpm overrides (1.0.3 has broken package exports on npm)

Backports

Closes #13357

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tigent tigent bot added the maintenance CI, internal documentation, automations, etc label Mar 12, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The File object serialization includes Symbol(state) on newer Node
versions (24+), causing inline snapshot mismatches. Extract the file
field separately and only snapshot the non-file form fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same fix as openai — extract the File field separately to avoid
Node 24's additional Symbol(state) in File serialization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@aayush-kapoor aayush-kapoor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local dev setup regression

…port

@sveltejs/adapter-vercel v5 only supports Node 18/20/22. Upgrade to v6
which adds Node 24 to valid_node_versions. Also upgrade @sveltejs/kit to
v2.55+ as required by adapter v6.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
openInboundSse() is fire-and-forget after a 202 response, so the GET
call may not have arrived by the time the assertion runs. Use vi.waitFor
to poll until server.calls[2] exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Upgrade vitest to v4 in @ai-sdk/vue and @ai-sdk/mcp (were still on 2.1.4)
- Fix it() timeout option syntax in e2e tests (vitest v4 takes number, not object)
- Fix MCP oauth test to access URL and Headers properties directly
- Update MCP inline snapshot for vitest v4 formatting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Angular test file used .at(0) and .at(1) which require ES2022 lib,
but the project targets ES2018. This was exposed by the vitest v4 upgrade.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add packageExtensions for @testing-library/jest-dom to declare vitest
as a peer dependency. Without this, pnpm resolves a different vitest
instance for jest-dom, causing "snapshot state not found" errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In vitest v4, spyOn without restore causes stacked spies between tests,
leading to duplicate call counts. Add afterEach with vi.restoreAllMocks().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace `import '@testing-library/jest-dom/vitest'` with manual
`expect.extend(matchers)` using the correct vitest expect. The
jest-dom/vitest entry imports its own vitest instance which in pnpm
monorepos can resolve to a different copy, breaking snapshot state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ations

Move the jest-dom matchers setup from individual test file imports to
vitest setupFiles config. This avoids the duplicate vitest instance
issue while providing proper TypeScript type augmentation via jest-dom.d.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @typescript-eslint/no-empty-object-type rule is not configured in
all packages, causing ESLint to error on the disable comment itself.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The packageExtensions workaround for @testing-library/jest-dom is no
longer needed since the setupFiles approach avoids importing
jest-dom/vitest (which caused the duplicate vitest instance issue).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use `/// <reference types="@testing-library/jest-dom/vitest" />` in
vitest setup files instead of separate jest-dom.d.ts files. The
triple-slash directive is type-only so the duplicate vitest instance
issue doesn't apply at type-check time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tinyexec version pin is not needed — tests and type-check pass
without it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restoring the tinyexec 1.0.2 pin — removing it caused azure tests to
time out on Node 24 CI, likely due to transitive dependency resolution
changes affecting test performance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gr2m gr2m merged commit 265cfb3 into main Mar 16, 2026
18 checks passed
@gr2m gr2m deleted the add-node-24-to-ci branch March 16, 2026 15:00
felixarntz added a commit that referenced this pull request Mar 16, 2026
## Background

The base64 data in question includes a several MB sized image. This can
lead to parsing being slow, leading to intermittent failures completely
unrelated to the changes made (see e.g.
https://github.com/vercel/ai/actions/runs/23155408928/job/67274515942?pr=13482
or
https://github.com/vercel/ai/actions/runs/23155646090/job/67275349940?pr=13481).

## Summary

* Increases timeout for the test to 6s (since it always exceeded 5s only
_slightly_)
* No changeset included because it's a test-only change

## Manual Verification

N/A

## Checklist

- [ ] Tests have been added / updated (for bug fixes / features)
- [ ] Documentation has been added / updated (for bug fixes / features)
- [ ] A _patch_ changeset for relevant packages has been added (for bug
fixes / features - run `pnpm changeset` in the project root)
- [x] I have reviewed this pull request (self-review)

## Future Work

N/A

## Related Issues

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

Labels

maintenance CI, internal documentation, automations, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Node.js 24 to supported versions and CI

3 participants