Skip to content

Build: Move vitest to repo root and upgrade to 4.1.0#34172

Merged
kasperpeulen merged 19 commits into
nextfrom
kasper/vitest-root-migration
Mar 18, 2026
Merged

Build: Move vitest to repo root and upgrade to 4.1.0#34172
kasperpeulen merged 19 commits into
nextfrom
kasper/vitest-root-migration

Conversation

@kasperpeulen
Copy link
Copy Markdown
Member

@kasperpeulen kasperpeulen commented Mar 17, 2026

What I did

Moved the vitest workspace config from code/ to the repo root and upgraded vitest to 4.1.0, so code/ packages and scripts/ tests all run from a single vitest invocation.

Changes:

  • Moved vitest.config.ts from code/ to repo root, updated all project globs with code/ prefix, added scripts/vitest.config.ts as a project
  • Upgraded vitest from 4.0.14 to 4.1.0 (including addon-vitest devDeps to deduplicate)
  • Moved scripts to root package.json: test, test:watch, storybook:vitest, storybook:vitest:inspect
  • Removed from code/package.json: test, test:watch, affected:test, storybook:vitest, storybook:vitest:inspect
  • Moved vite from resolutions to devDependencies
  • Updated CircleCI jobs to run from repo root (removed working_directory: code)
  • Removed scripts/project.json test target (scripts tests now run via root vitest)
  • Fixed BrowserCommands type augmentation by deduplicating vitest across the monorepo
  • Fixed tests that relied on process.cwd() being code/
  • Removed reactDocgenTypescript.test.ts (covered by other tests)
  • Updated AGENTS.md to reflect root-level test commands

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

  1. Run yarn test from repo root — all tests pass (except detect-agent.test.ts which fails in any AI agent environment)
  2. Run yarn storybook:vitest from repo root — storybook browser tests run in watch mode

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Consolidate the two separate vitest setups (code/ and scripts/) into a
single root-level vitest workspace config. This allows running all tests
with a single `yarn test` from the repo root.

Changes:
- Add root vitest.config.ts that includes all projects from code/ and scripts/
- Remove code/vitest.config.ts (replaced by root config)
- Add explicit configDir to storybook vitest plugin (needed for root context)
- Update package.json scripts to run vitest from root
- Merge NX test targets into a single target on the code project
- Add ignoreSourceErrors to pseudo-states typecheck config
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Migrate repository test infrastructure to Vitest: update root Vitest projects to use code/ prefixes, add a scripts Vitest project, move Storybook Vitest config under code/ and point it at .storybook, adjust package scripts and project targets to run Vitest directly (increased Node memory), remove scripts test target, broaden CI test globs to include scripts/**/*, add vite resolution/dependency, and enable ignoreSourceErrors: true in one addon Vitest config.

Changes

Cohort / File(s) Summary
Root Vitest config
vitest.config.ts
Prefixed project paths with code/, added scripts/vitest.config.ts to projects, and moved storybook config reference to code/vitest.config.storybook.ts.
Storybook Vitest config
code/vitest.config.storybook.ts
Added import { resolve } from 'node:path' and set configDir: resolve(__dirname, '.storybook') in the storybook Vitest plugin config.
Addon Vitest tweak
code/addons/pseudo-states/vitest.config.ts
Added ignoreSourceErrors: true under test.typecheck.
Scripts Vitest config
scripts/vitest.config.ts
Added name: 'scripts' to the exported Vitest test configuration.
Package scripts & deps
package.json, code/package.json, scripts/package.json
Switched test/test:watch scripts to invoke Vitest directly with NODE_OPTIONS=--max_old_space_size=4096, added/updated Vitest-related dependencies to ^4.1.0, added vite dependency and resolution; some scripts now cd .. and use --project scripts.
Project/workspace targets
code/project.json, scripts/project.json
code/project.json test target updated to run Vitest and include vitest.config.ts in inputs; scripts/project.json had its test target removed.
CI/job configs
scripts/ci/common-jobs.ts
Removed per-job working_directory for test jobs, broadened test globs to include code/**/* and scripts/**/*, simplified sed filters, and changed test-results paths from code/test-results to test-results.
Ecosystem resolutions
scripts/ecosystem-ci/existing-resolutions.js
Added 'vite' to the EXISTING_RESOLUTIONS set.
Test mock change
code/addons/vitest/src/node/test-manager.test.ts
Simplified Vitest module mock to return a sync factory { createVitest: mockCreateVitest } instead of async importOriginal-based merge.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@kasperpeulen kasperpeulen changed the title Move vitest workspace config from code/ to repo root Build: Move vitest workspace config from code/ to repo root Mar 17, 2026
@kasperpeulen kasperpeulen added build Internal-facing build tooling & test updates ci:normal labels Mar 17, 2026
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Mar 17, 2026

View your CI Pipeline Execution ↗ for commit 4e27527

Command Status Duration Result
nx run-many -t compile -c production --parallel=1 ✅ Succeeded 5m 20s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-17 17:05:30 UTC

- Replace redundant scripts/**/* input with vitest.config.ts (root config
  was missing from NX cache inputs; scripts already covered by sharedGlobals)
- Restore storybook:vitest scripts to reference yarn test:watch/test instead
  of duplicating the full command
The CI jobs previously ran `yarn test` from `code/` working directory,
passing test file paths relative to `code/`. After the vitest root
migration, `yarn test` changes CWD to root, so file paths and output
paths need to be relative to root.

- Remove `working_directory: 'code'` from test jobs
- Prefix glob patterns with `code/` (and add `scripts/` for unit tests)
- Update test result persist paths from `code/test-results` to `test-results`
- Upgrade vitest and @vitest/* packages to ^4.1.0
- Add vite resolution to pin ^7.0.4 (vitest 4.1.0 pulls in vite 8.0.0
  which breaks JSX transforms)
- Update EXISTING_RESOLUTIONS for ecosystem-ci

Note: test-manager.test.ts has 14 new failures due to vitest 4.1.0's
module mocking changes (#9774: manual mocks no longer load/transform
original modules). This test mocks vitest/node internals and needs a
separate fix.
Vitest 4.1.0 changed module mocking behavior: importOriginal() in
manual mocks no longer loads/transforms original modules (#9774).

Remove the importOriginal() spread since the test only needs the
createVitest mock — no other exports from vitest/node are used at
runtime.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/addons/vitest/src/node/test-manager.test.ts`:
- Around line 47-49: The current vi.mock call directly returns an object for
createVitest; update it to use spy-mocking by passing { spy: true } to vi.mock
and return the export via vi.mocked(...) so tests use the repository's spy
convention. Specifically, replace the direct mock of createVitest with a
spy-enabled mock of 'vitest/node' and reference the mocked export using
vi.mocked(require('vitest/node')) or vi.mocked(importedModule) to map
createVitest to mockCreateVitest, ensuring mockCreateVitest remains the
implementation used by the spy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fefe9dc1-7f49-4ca8-8b9e-2737b3d40b56

📥 Commits

Reviewing files that changed from the base of the PR and between eed6a37 and 6079fbd.

📒 Files selected for processing (1)
  • code/addons/vitest/src/node/test-manager.test.ts

Comment thread code/addons/vitest/src/node/test-manager.test.ts
@kasperpeulen kasperpeulen marked this pull request as draft March 17, 2026 09:56
Comment thread code/addons/pseudo-states/vitest.config.ts Outdated
Comment thread code/project.json Outdated
Comment thread code/vitest.config.storybook.ts Outdated
Comment thread package.json Outdated
- Remove ignoreSourceErrors from pseudo-states vitest config
- Use yarn test in code/project.json NX target
- Replace __dirname with import.meta.dirname in vitest.config.storybook.ts
- Move vite from resolutions to devDependencies
- Fix BrowserCommands type augmentation for vitest 4.1.0 compatibility
The addon had vitest ^4.0.14 while root had ^4.1.0, causing two
separate copies with distinct BrowserCommands interfaces. Bump
addon devDeps to ^4.1.0 and use the docs-recommended
`declare module 'vitest/browser'` augmentation path.
Vitest now runs from root, so these were just delegating with
`cd ..`. Updated storybook:vitest and ci-tests to call vitest
directly, and updated AGENTS.md to reflect root-level commands.
Vitest runs from root, so these scripts belong there too.
Remove await-serve-storybooks, build, changelog, changelog:next,
danger, github-release, and i scripts that are not referenced
in any CI config or workflow.
@kasperpeulen kasperpeulen marked this pull request as ready for review March 17, 2026 13:46
@kasperpeulen kasperpeulen changed the title Build: Move vitest workspace config from code/ to repo root Build: Move vitest to repo root and upgrade to 4.1.0 Mar 17, 2026
Comment thread scripts/package.json
Comment on lines +40 to +41
"test": "cd .. && NODE_OPTIONS=--max_old_space_size=4096 vitest run --project scripts",
"test:watch": "cd .. && NODE_OPTIONS=--max_old_space_size=4096 vitest watch --project scripts",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can also set these in Vitest config on project level:

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    projects: [
      {
        test: {
          name: "scripts",
          execArgv: ["--max_old_space_size=4096"]
        }
      }
    ]
  },
});

Comment thread scripts/package.json
"task": "jiti ./task.ts",
"test": "NODE_OPTIONS=--max_old_space_size=4096 vitest run",
"test:watch": "NODE_OPTIONS=--max_old_space_size=4096 vitest watch",
"test": "cd .. && NODE_OPTIONS=--max_old_space_size=4096 vitest run --project scripts",
Copy link
Copy Markdown
Member

@AriPerkkio AriPerkkio Mar 18, 2026

Choose a reason for hiding this comment

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

Instead of cd, you could use package manager's workspace commands.

I've set this kind of setup in https://github.com/chromaui/chromatic-e2e.

├── package.json 
├── vitest.config.ts
│
└── packages
    │
    ├── client
    │   ├── package.json
    │   └── vitest.config.ts
    │
    └── server
        ├── package.json
        └── vitest.config.ts

/vitest.config.ts

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    projects: ["./packages"]
  }
});

/package.json

{
  "name": "@scoped/monorepo-root",
  "private": true,
  "test": "vitest run",
}

/packages/client/vitest.config.ts

import { defineProject } from "vitest/config"; // NOTE: defineProject, not defineConfig

export default defineConfig({
  test: {
    name: "Client Stuff",
    environment: "jsdom",
    // ... and so on
  }
});

/packages/client/package.json

{
  "name": "@scoped/client",
  "test": "yarn workspace @scoped/monorepo-root test --project 'Client Stuff'",

  "Or depending on package manager": "",
  "test": "pnpm --filter @scoped/monorepo-root test --project 'Client Stuff'",
  "test": "npm --workspace @scoped/monorepo-root test -- --project 'Client Stuff'"
}

/packages/server/vitest.config.ts

import { defineProject } from "vitest/config";

export default defineConfig({
  test: {
    name: "Server",
    environment: "node",
    // ... and so on
  }
});

/packages/server/package.json

{
  "name": "@scoped/server",
  "test": "yarn workspace @scoped/monorepo-root test --project Server",
}

@kasperpeulen kasperpeulen merged commit fefa2f5 into next Mar 18, 2026
125 of 126 checks passed
@kasperpeulen kasperpeulen deleted the kasper/vitest-root-migration branch March 18, 2026 10:36
@github-actions github-actions Bot mentioned this pull request Mar 18, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Internal-facing build tooling & test updates ci:normal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants