Skip to content

chore: migrate tests from mocha/chai to node:test#3044

Draft
bennypowers wants to merge 52 commits into
node24/typescript-upgradefrom
node24/test-migration
Draft

chore: migrate tests from mocha/chai to node:test#3044
bennypowers wants to merge 52 commits into
node24/typescript-upgradefrom
node24/test-migration

Conversation

@bennypowers
Copy link
Copy Markdown
Member

@bennypowers bennypowers commented Mar 16, 2026

Summary

Migrate all test files across ~20 packages from mocha/chai to node:test + node:assert.

  • Update test scripts to use node --test (no flags needed; type stripping is default on Node 22.18+)
  • Add --test-timeout and --test-force-exit for CI reliability
  • Move rollup-plugin-html tests from test/src/ to test/
  • Add new test files for config-loader, parse5-utils, rollup-plugin-copy, rollup-plugin-import-meta-assets
  • Replace mocha .js test files with .mjs equivalents where needed
  • Fix browser-logs stack trace assertions (regex instead of hardcoded column offsets)
  • Tests import from dist/ for packages with CJS source deps

Tests only -- no production source code changes. This is a non-breaking internal change.

Stack

  1. refactor: use import type for type-only imports #3052 -- import type annotations
  2. chore: upgrade TypeScript to 5.9.3 and enable .ts imports #3043 -- TS 5.9, nodenext, .ts imports, drop EOL Node versions
  3. chore: migrate tests from mocha/chai to node:test #3044 -- mocha/chai to node:test migration

Test plan

  • npm run build passes
  • Lint passes
  • Node tests pass on Node 22, 24, and latest
  • Browser tests pass
  • Storybook builder verification passes

- Upgrade TypeScript from 5.0.4 to 5.9.3
- Update eslint, prettier, and related dev dependencies
- Enable `module: nodenext` and `rewriteRelativeImportExtensions` in tsconfigs
- Rewrite all relative imports from .js to .ts extensions
- Add `type` keyword to type-only imports across source files
- Remove TypeScript parameter properties from constructors
  (DevServer, PluginSyntaxError, WebSocketsManager)
- Fix internal-ip CJS interop for nodenext module resolution
- Add @ts-ignore for deprecated puppeteer accessibility API

Zero runtime behavior change — output remains CJS.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 16, 2026

🦋 Changeset detected

Latest commit: 8e0c2aa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@web/browser-logs Major
@web/test-runner-core Patch
@web/test-runner Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

prettier-plugin-package v1.x requires prettier ^2, which conflicts
with our upgrade to prettier ^3.7.1. v2.0.0 supports prettier ^3.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from a38ded7 to 010ef78 Compare March 17, 2026 11:52
@typescript-eslint v8 enables stricter rules by default. Disable rules
that flag pre-existing code patterns:
- no-require-imports: CJS require() in .js files
- no-unused-expressions: chai expect() assertions in tests
- no-empty-object-type: {} type usage
- no-unsafe-function-type: Function type usage
- no-unused-vars: allow unused catch parameters

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 010ef78 to 8bd2017 Compare March 17, 2026 12:53
TS 5.9 with module:nodenext requires explicit return type annotation
when the inferred type references a non-portable path (TS2742).

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 8bd2017 to 268a3ff Compare March 17, 2026 14:57
…Extensions

TypeScript's rewriteRelativeImportExtensions injects a
__rewriteRelativeImportExtension helper into the output. This helper
is not needed in browser bundles and breaks test execution.

Add stripRewriteImportExtensionPlugin to remove the helper from the
rollup output. Also add resolveMochaPlugin for robust monorepo
module resolution.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 268a3ff to 61bf92a Compare March 17, 2026 16:48
Test files were accidentally copied from fix/node24 which included
test migration changes (node:test, import.meta). Those belong in PR2.
Restored to master versions with only .ts import extension rewrites.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from b5e6238 to 32ba55e Compare March 17, 2026 18:02
@bennypowers bennypowers marked this pull request as draft March 17, 2026 18:34
- Restore dev-server-rollup test files to master versions: the sed
  import rewrite incorrectly changed assertion strings like
  "import moduleA from './module-a-stub.js'" to use .ts extensions.
  Only actual import statements should use .ts extensions.
- Add hanbi.d.ts ambient declarations for packages that use hanbi
  in tests (dev-server-core, dev-server-hmr, dev-server-import-maps,
  test-runner-core). With module:nodenext, untyped CJS modules need
  explicit declarations.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 32ba55e to 5abe25a Compare March 17, 2026 19:01
- Remove leaked PR4 files: JSDoc→TS conversions (.ts files in config-loader,
  parse5-utils, rollup-plugin-copy, rollup-plugin-import-meta-assets,
  storybook-utils) belong in PR4, not PR1
- Override JSDoc package tsconfigs to use module:commonjs/moduleResolution:node
  since their .js source files are incompatible with nodenext
- Fix parse5 Token→Attribute type import for parse5 v6 compat
- Fix Object.values(bundle) unknown type with explicit cast
- Add CJS interop for saucelabs and internal-ip (build errors with nodenext)
- Add CJS interop for rollup plugins in storybook-builder
- Restore master test scripts (test migration belongs in PR2)
- Remove tsx devDep from test-runner-core (belongs in PR2)
- Add workaround for @jridgewell/remapping .d.cts TS 5.9 syntax error
- Restore rollup-plugin-html source files from master with .ts imports

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 5abe25a to 4fb3367 Compare March 18, 2026 12:08
With module:nodenext, ts-node fails on untyped CJS modules (like hanbi).
Override moduleResolution to 'node' for test execution via mocha+ts-node.
This is temporary — PR2 migrates all tests to node:test which doesn't
need ts-node.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 4fb3367 to 4926432 Compare March 18, 2026 13:33
ts-node with module:nodenext treats .ts files as ESM, causing
"Cannot require() ES Module" errors. Override both module and
moduleResolution to commonjs/node for test execution.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 4926432 to 6aab5fb Compare March 18, 2026 14:47
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 6aab5fb to 1effc4f Compare March 18, 2026 14:58
koa v3 + @types/koa v3 and ws v8 + @types/ws v8 are required for
module:nodenext compatibility. @types/koa v2 and ws v7 types don't
resolve correctly with nodenext module resolution.

Add build script workaround to remove nested @types/koa and @types/ws
installed by transitive dependencies (@rocket/cli) which conflict
with the workspace package versions.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 1effc4f to 74db169 Compare March 18, 2026 17:03
- Restore parse5 to ^6.0.1 in all packages (v8 migration is in PR4)
- Keep koa v3 / ws v8 in dev-server-core (required for nodenext compat)
- Use WebSocketServer from ws v8 API
- Remove nested @types cleanup for ws (not needed)

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR1 emits CJS output (no "type": "module" yet), so import.meta
is not available. Revert to __dirname in browserScript.ts and
createServer.ts. Remove __esModule export from RollupPluginHTMLOptions.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from c40dc3e to fdff965 Compare March 20, 2026 06:53
- Restore ALL test files to master versions with only .ts import rewrites
  (removes leaked node:test/node:assert imports from PR2)
- Replace @typescript-eslint/ban-types with no-empty-object-type in
  inline disable comments (ban-types removed in v8)
- Fix invalid typeof comparison in rollupAdapter.ts
- Add eslintConfig.root: true to prevent parent config interference
- Add react-dom devDependency for storybook builder tests
- Regenerate package-lock.json from master base

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from fdff965 to 037552b Compare March 20, 2026 12:20
Allow unused function arguments prefixed with underscore.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 037552b to 0c3de8d Compare March 22, 2026 05:41
The previous sed only matched lines starting with import/export,
missing multi-line imports where 'from' is on a continuation line.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
prettier v3 no longer has bin-prettier.js. Use npx prettier instead.
Format files that were changed but not auto-formatted.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Migrate all test files across ~20 packages to Node.js native test runner
- Replace mocha describe/it/before/after with node:test equivalents
- Replace chai expect/assert with node:assert/strict
- Update package.json test scripts to use `node --test`
- Add tsx devDependency to test-runner-core for TypeScript test execution
- Move rollup-plugin-html tests from test/src/ to test/
- Replace mocha-based test files with .mjs equivalents where needed
- Add changeset for browser-logs test migration

Tests only — no production source code changes.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tsx devDependency added to test-runner-core was missing from
the lock file, causing npm ci to fail.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix 48 test files with merge conflict markers from rebase
- Remove unused path imports in test files flagged by eslint
- Regenerate package-lock.json

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix config-loader, parse5-utils test imports to use src/ not dist/
- Fix rollup-plugin-copy, rollup-plugin-import-meta-assets test imports
  to use .js not .ts (JSDoc packages still have .js source on PR2)
- Fix dev-server-core exports map: use "default" condition instead of
  "require"/"import" for Node 24 ESM compatibility
- Resolve merge conflict markers in test files
- Remove unused path imports

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers force-pushed the node24/test-migration branch from 49b4991 to 2cc8e4e Compare March 22, 2026 09:42
- Add --experimental-transform-types flag to all node --test commands
  (needed for .ts import resolution without "type": "module")
- Copy source files from fix/node24 for correct import type keywords
  and CJS interop (browser-compat-data, ua-parser-js, etc.)
- Restore parse5 v6 types and CJS-compatible code for pre-PR3 output
- Fix typeof comparison in rollupAdapter

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace hardcoded column offsets (N:23) with regex patterns (N:\d+)
  in browser-logs error stack trace tests. Column offsets vary by
  browser version and shouldn't be hardcoded.
- Add --test-timeout 120000 to all node --test commands to prevent
  30-minute hangs on Windows when a test server fails to shut down.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Node 24 native type stripping requires explicit `import type` for
type-only parse5 imports (Document, Node, Element, Attribute, etc.).
Without this, named imports fail at runtime because the types are
stripped from the module's exports.

Also fix remaining .js -> .ts import rewrites in multi-line from
clauses that were missed by previous sed runs.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Node 24 runs .ts source files as ESM (native type stripping),
so require.resolve() and __dirname are unavailable. Use
import.meta.resolve() and import.meta.dirname with @ts-ignore
to suppress TS1470 (import.meta not allowed in CJS output).

The CJS output with import.meta is technically invalid but
the dist isn't executed directly until PR3 adds "type": "module".
Tests run source files directly on Node 24 where it works.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert source files that use import.meta back to __dirname and
require.resolve. The import.meta in CJS compiled output causes
Node to reparse as ESM, breaking dist execution.

Source files will be migrated to import.meta in PR3 when
"type": "module" is added.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests for packages whose source uses require.resolve/__dirname
must import from compiled dist/ (CJS) instead of src/ (TS treated
as ESM by Node 24). This avoids "require is not defined" errors.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
node --test doesn't exit when open handles remain (servers, browsers,
sockets). Add --test-force-exit to force process exit after all tests
complete, preventing 30-minute CI job timeouts.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers
Copy link
Copy Markdown
Member Author

Replaced by #3049 (combined with PR3)

All packages now require Node 22+. No enums or namespaces in test
files, so native type stripping (default on 22.18+) handles everything
without needing --experimental-transform-types.

CI workflows updated to test on Node 22/24/latest.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bennypowers bennypowers reopened this May 13, 2026
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