chore(core): run workspace package unit tests with vitest - #36896
Draft
FrozenPandaz wants to merge 8 commits into
Draft
chore(core): run workspace package unit tests with vitest#36896FrozenPandaz wants to merge 8 commits into
FrozenPandaz wants to merge 8 commits into
Conversation
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
|
View your CI Pipeline Execution ↗ for commit bf949c4
☁️ Nx Cloud last updated this comment at |
FrozenPandaz
force-pushed
the
chore/workspace-vitest
branch
from
September 9, 2026 19:37
652dd54 to
857e2b9
Compare
Ports the jest preset's guards (project-graph and workspace-context mocks, workspaceRoot pinned under tmp/unit) and the patched jest resolver's source resolution to vitest, shared under scripts/ for the next package to reuse.
Mechanical jest.* to vi.* rename, async mock factories with vi.importActual, xdescribe to describe.skip, and vitest type imports.
Vitest joins describe and test names with ' > '; the recorded values are byte-identical.
Written from PR #36754 and corrected against the packages/workspace migration.
Vite resolves the shared setup at the workspace root through the root solution tsconfig, reading every referenced project's tsconfig.json, and prettier resolves .editorconfig from the repo. Both affect the result, so declare them rather than exclude.
At the workspace root, vite resolved the setup against the root solution tsconfig and walked its references, reading all 114 project tsconfigs on every run. A leaf tsconfig beside the files cuts that to one, so the workspace:test inputs no longer have to name them.
…igration Paths moved to tools/vitest, and adds what the sandbox reports taught: where the shared setup must live, how to attribute a violation from the report's process tree, and that oxlint is a separate target from lint.
FrozenPandaz
force-pushed
the
chore/workspace-vitest
branch
from
September 9, 2026 21:51
857e2b9 to
bf949c4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Current Behavior
The
@nx/workspacepackage's 420 unit tests run with Jest through the sharedjest.preset.js: pinned tomaxWorkers: 1, on top of a custom resolver (scripts/patched-jest-resolver.js), the workspace-wide guards inscripts/unit-test-setup.js, and CJS shims for ESM-only dependencies. A fullnx test workspacetakes 7m53s.Expected Behavior
nx test workspaceruns the same 420 tests with Vitest 4, inferred through the@nx/vitestplugin, in ~17.5s (~27x faster). Test count, suite count, and every recorded snapshot value are unchanged; the suite is stable over repeated runs. Other packages are unaffected and still infer Jest.Follows #36754, which moved
packages/nx. Two pieces of that migration turned out to be specific tonx— the one package that barely imports its siblings — so this PR adds the shared machinery every other package will need:scripts/vitest-nx-source-resolver.mtsreplacesscripts/patched-jest-resolver.js.resolve.conditions: ['@nx/nx-source']is not sufficient on its own:node_modules/nxandnode_modules/@nx/*are the published tarballs (dist only), and their exports maps advertise@nx/nx-sourceentries pointing at source files the tarball does not ship. The plugin mapsnx/@nx/*through the localpackages/<pkg>/package.jsoninstead, with a file fallback for deep imports no exports entry covers.scripts/vitest-setup.mtsportsscripts/unit-test-setup.js(jest-only,jest.doMock) and adds what vitest's execution model requires:Module._resolveFilename, so node'srequireand vite's module graph agree — without it a lazyrequire('@nx/js')fails outright under--conditions=@nx/nx-source;Module._load. Generators reach graph builders through lazyrequire(), whichvi.mockcannot see; unmocked,createProjectGraphAsynctakesproject-graph.lockand deadlocks the worker with no output and no test timeout;NX_ISOLATE_PLUGINS=false, so plugin isolation does not spawn worker subprocesses that are never torn down (twopackages/nxspecs already carry this note);NX_WORKSPACE_ROOT_PATHundertmp/unit/<pid>, per worker. The jest resolver set a singletmp/unitas a side effect; with parallel workers one shared root makes every worker queue on the same lock.@clack/promptsshim is kept. It is not only ESM interop: the real library drives a synchronous prompt, so a generator that asks a question blocks the worker forever.Spec changes are the usual codemod (
jest.*→vi.*, async mock factories withvi.importActual,xdescribe→describe.skip, vitest type imports) plusvi.mock('child_process', { spy: true })where a frozen ESM namespace was previously spied on directly.Snapshots are rekeyed, not rewritten: vitest joins describe and test names with
' > 'where jest used a space, so every key reads as new. All 176 recorded values were diffed against the jest originals after normalizing the separator and match exactly. The one shape change istoThrowErrorMatchingInlineSnapshot, which vitest records as[Error: msg]rather than"msg".Verification
nx test workspace— 420 tests (417 passed, 3 skipped), matching jest exactly; stable across four consecutive runs.nx run-many -t build,lint -p workspace— green.devkitrun as a canary — 563 tests, unchanged. A fullnx affectedis not meaningful here: a new file underscripts/marks all 94 projects affected, and nothing jest reads was modified (jest.preset.js,scripts/unit-test-setup.js, andscripts/patched-jest-resolver.jsare untouched).Follow-ups, not in this PR
packages/nx/src/internal-testing-utils/mock-project-graph.tslogs a vitest deprecation warning ("vi.mock call is not at the top level ... will become an error in a future version") because of its dual-runnerif (typeof vi !== 'undefined')branch. Pre-existing; thenxsuite hits it too.scripts/jest-mocks/now serves vitest as well and wants renaming toscripts/test-mocks/once a second package migrates.tmp/unit/<pid>directory behind (gitignored).packages/devkit/jest-setup-nx-workspace-data-dir.jshas themkdtemp+rmSync-on-exit pattern if we want them cleaned up.Related Issue(s)
N/A
View Polygraph session ↗