Skip to content

fix(vite): support virtual:msw imports in vitest - #2802

Merged
kettanaito merged 1 commit into
mainfrom
fix/vitest-virtual-msw-import
Oct 2, 2026
Merged

kettanaito merged 1 commit into
mainfrom
fix/vitest-virtual-msw-import

Conversation

@kettanaito

@kettanaito kettanaito commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: d23bd731-a543-4182-aa58-f7115d952b65

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6aef1 and 52ce401.

📒 Files selected for processing (8)
  • src/vite/options.d.ts
  • src/vite/plugin.test.ts
  • src/vite/plugin.ts
  • src/vite/runtime.ts
  • src/vite/tsconfig.build.json
  • test/regressions/2799-vite-virtual-module.test.ts
  • tsdown.config.ts
  • vitest.config.ts
💤 Files with no reviewable changes (1)
  • src/vite/options.d.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The Vite runtime replaces its preconfigured network export with an asynchronous network factory. The Vite plugin resolves and loads virtual:msw directly, creating a network with server or browser options. Tests and build configuration are updated for this module flow.

Changes

Vite virtual network creation

Layer / File(s) Summary
Create and manage networks
src/vite/runtime.ts
createNetwork(options) waits for prior disposal, creates a network with the supplied options, and applies the existing serialized operations and HMR lifecycle behavior.
Load the Vite virtual network
src/vite/options.d.ts, src/vite/plugin.ts, src/vite/plugin.test.ts, src/vite/tsconfig.build.json, test/regressions/2799-vite-virtual-module.test.ts, tsdown.config.ts, vitest.config.ts
The plugin resolves and loads virtual:msw directly, using msw/node defaults for server environments and browser defaults with a worker URL otherwise. The obsolete options module is removed. Tests and build configuration are updated, including a regression test for a registered request handler.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant VitePlugin
  participant Runtime
  participant MSWNetwork
  VitePlugin->>Runtime: createNetwork(options)
  Runtime->>MSWNetwork: defineNetwork(options)
  MSWNetwork-->>Runtime: created network
  Runtime-->>VitePlugin: return network
Loading

Merge Risk: ⚪ Minimal · up to 52ce4

The network replacement concern is resolved by the existing lifecycle logic. No actionable merge blocker remains after normal checks.

Architecture Summary

Architecture risk: 🟡 Medium · up to 52ce4

The change affects 4 systems.

Changed systems: src, tsdown.config.ts, vitest.config.ts, test

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 5 changed files map to changed impact.
  • observed — tsdown.config.ts (service) was modified; 1 changed file maps to changed impact.
  • observed — vitest.config.ts (service) was modified; 1 changed file maps to changed impact.
  • observed — test (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in src/vite/options.d.ts: The virtual:msw/options module declaration and its exported defaultNetworkOptions type were removed.
  • observed — Modified behavior in src/vite/plugin.test.ts: The SSR resolution assertion now checks virtual:msw rather than virtual:msw/options.
  • observed — Modified behavior in src/vite/plugin.ts: The virtual:msw/options ID constant was removed.
  • observed — Modified behavior in src/vite/plugin.ts: resolveId now resolves virtual:msw to its own virtual ID instead of resolving the runtime file, and no longer resolves virtual:msw/options. The loader now handles virtual:msw directly: server environments create a network with msw/node defaults, while other environments create one with browser defaults and record the environment for worker emission. The former options-module loader, which exported defaults separately, was removed.

Reliability and maintainability

  • inferred — Risk-relevant change factors for src: blast_radius_1; blast_radius_2; direct_dependents_1; direct_dependents_2
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 6 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: fixing virtual:msw imports in Vitest.
Description check ✅ Passed The description references issue #2799, which matches the regression fix included in the changeset.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 6 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit watched the network start,
With browser or server options in its heart.
It waited while old networks retired,
Then tested handlers as requests transpired.
HMR paused and resumed with care,
The rabbit left a carrot there.

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

@kettanaito
kettanaito merged commit e73c381 into main Oct 2, 2026
12 checks passed
@kettanaito
kettanaito deleted the fix/vitest-virtual-msw-import branch October 2, 2026 21:03
@kettanaito

Copy link
Copy Markdown
Member Author

Released: v3.0.2 🎉

This has been released in v3.0.2.

Get these changes by running the following command:

npm i msw@latest

Predictable release automation by Release.

renovate Bot added a commit to cigaleapp/cigale that referenced this pull request Oct 13, 2026
##### [v3.0.2](https://github.com/mswjs/msw/releases/tag/v3.0.2)

#### v3.0.2 (2026-10-03)

##### Bug Fixes

- **vite:** support `virtual:msw` imports in vitest ([#2802](mswjs/msw#2802)) ([`e73c381`](mswjs/msw@e73c381)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.1](https://github.com/mswjs/msw/releases/tag/v3.0.1)

#### v3.0.1 (2026-09-30)

##### Bug Fixes

- treat `CONNECT` requests as the transport mechanism ([#2796](mswjs/msw#2796)) ([`7cad86a`](mswjs/msw@7cad86a)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.0](https://github.com/mswjs/msw/releases/tag/v3.0.0)

#### v3.0.0 (2026-09-28)

- v3.0.0 ([#2692](mswjs/msw#2692)) ([`2bb4342`](mswjs/msw@2bb4342)) [@kettanaito](https://github.com/kettanaito) [@Andarist](https://github.com/Andarist)

##### ⚠️ BREAKING CHANGES

- **MSW is now ESM-only** ([#2765](mswjs/msw#2765)).
- Deprecate support for Node.js v18 and v20 ([#2729](mswjs/msw#2729)). The minimal supported Node.js version is v22.
- `msw/native` is removed in favor of [`@msw/react-native`](https://github.com/mswjs/react-native).
- Require TypeScript 5.9 as the minimal version.
- Deprecate support for TypeScript 5.1 and 5.2 ([#2730](mswjs/msw#2730))
- `worker.stop()` returns a Promise ([#2724](mswjs/msw#2724)). Awaiting it is relevant only for in-flight critical scenarios.
- `graphql` is now exported as `msw/graphql` ([#2691](mswjs/msw#2691)). GraphQL is now handled as a proper optional peer dependency.
- Removes the `handleRequest()` utility. Please use the `defineNetwork()` API instead.
- `GraphQLLinkHandlers` type has been renamed to `GraphQLLink`.
- The `file://` requests now throw in Node.js as they normally do (not supported by `fetch`).
- The `Content-Length` request header is now removed by `bypass()`.
- HTTP-to-WebSocket upgrade requests performed via `fetch()` now throw in Node.js as they normally do (not supported by `fetch`).
- Cookies are no longer managed in Node.js for better compatibilty. Instead, whatever is the default behavior of your environment that's the cookie behavior you get. This has no effect on the browser.
- WebSocket `connection` life cycle event has been renamed to `websocket:connection` ([#2783](mswjs/msw#2783)).
- `onUnhandledRequest` option has been renamed to `onUnhandledFrame`.
- The library no longer patches `setTimeout` to circumvent fake timers in test runners. You should advance the fake timers normally for delayed mocked responses to resolve.
- The library no longer returns a mocked cookie string on `request.headers.get('cookie')` in the handlers. It returns `null` in all environments. Please use the `cookies` resolver argument to have cookie-based logic.

##### Features

- Supports Node.js v24 and v26.
- Supports TypeScript v6.0 and v7.0.
- You can import individual utilities, like `delay` or `passthrough`, from the new `msw/utils` entrypoint for smaller footprint on your bundle.
- Support GraphQL v17.0.
- Support intercepting page navigations and form submissions ([#2721](mswjs/msw#2721)).
- Support GraphQL subscriptions ([#285](mswjs/msw#285), [#2763](mswjs/msw#2763)).
- Migrate from `path-to-regexp` to `@msw/url` ([#2678](mswjs/msw#2678)).
- Remove the following dependencies:
  - `graphql`
  - `path-to-regexp`
  - `picocolors`
  - `statuses`
  - `strict-event-emitter`
- Adds a Vite plugin for MSW ([#2781](mswjs/msw#2781)).
- Adds a `websocket:error` life cycle event to listen to WebSocket connection errors ([#2784](mswjs/msw#2784)).
- Support modifying the intercepted request headers in passthrough scenarios ([#2786](mswjs/msw#2786)).
- Support a new WebSocket Extension API that allows for better custom experiences ([#2791](mswjs/msw#2791)).

##### Bug fixes

- Fix an issue where preventing a page closure via the `beforeunload` listener would unregister the MSW worker ([#1105](mswjs/msw#1105)).
- Fix an issue that caused intermittent test failures in Vitest Browser Mode and Firefox if using `maxWorkers: 1` ([#2726](mswjs/msw#2726)).
- Fix an issue where in-flight requests were incorrectly passthrough when performed before calling `worker.stop()` ([#2724](mswjs/msw#2724), [#2597](mswjs/msw#2597)).
- Fix an issue where persisting cookies in `localStorage` would cause a maximum quota exceeded errors.
- Fix various issues related to the network interception in Node.js.
renovate Bot added a commit to cigaleapp/cigale that referenced this pull request Oct 17, 2026
##### [v3.0.3](https://github.com/mswjs/msw/releases/tag/v3.0.3)

#### v3.0.3 (2026-10-10)

##### Bug Fixes

- **HandlersController:** dispose of reset handlers ([#2810](mswjs/msw#2810)) ([`3818a81`](mswjs/msw@3818a81)) [@kettanaito](https://github.com/kettanaito)
- expose network context on `enable` in network sources ([#2809](mswjs/msw#2809)) ([`d1fe8e6`](mswjs/msw@d1fe8e6)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.2](https://github.com/mswjs/msw/releases/tag/v3.0.2)

#### v3.0.2 (2026-10-03)

##### Bug Fixes

- **vite:** support `virtual:msw` imports in vitest ([#2802](mswjs/msw#2802)) ([`e73c381`](mswjs/msw@e73c381)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.1](https://github.com/mswjs/msw/releases/tag/v3.0.1)

#### v3.0.1 (2026-09-30)

##### Bug Fixes

- treat `CONNECT` requests as the transport mechanism ([#2796](mswjs/msw#2796)) ([`7cad86a`](mswjs/msw@7cad86a)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.0](https://github.com/mswjs/msw/releases/tag/v3.0.0)

#### v3.0.0 (2026-09-28)

- v3.0.0 ([#2692](mswjs/msw#2692)) ([`2bb4342`](mswjs/msw@2bb4342)) [@kettanaito](https://github.com/kettanaito) [@Andarist](https://github.com/Andarist)

##### ⚠️ BREAKING CHANGES

- **MSW is now ESM-only** ([#2765](mswjs/msw#2765)).
- Deprecate support for Node.js v18 and v20 ([#2729](mswjs/msw#2729)). The minimal supported Node.js version is v22.
- `msw/native` is removed in favor of [`@msw/react-native`](https://github.com/mswjs/react-native).
- Require TypeScript 5.9 as the minimal version.
- Deprecate support for TypeScript 5.1 and 5.2 ([#2730](mswjs/msw#2730))
- `worker.stop()` returns a Promise ([#2724](mswjs/msw#2724)). Awaiting it is relevant only for in-flight critical scenarios.
- `graphql` is now exported as `msw/graphql` ([#2691](mswjs/msw#2691)). GraphQL is now handled as a proper optional peer dependency.
- Removes the `handleRequest()` utility. Please use the `defineNetwork()` API instead.
- `GraphQLLinkHandlers` type has been renamed to `GraphQLLink`.
- The `file://` requests now throw in Node.js as they normally do (not supported by `fetch`).
- The `Content-Length` request header is now removed by `bypass()`.
- HTTP-to-WebSocket upgrade requests performed via `fetch()` now throw in Node.js as they normally do (not supported by `fetch`).
- Cookies are no longer managed in Node.js for better compatibility. Instead, whatever is the default behavior of your environment that's the cookie behavior you get. This has no effect on the browser.
- WebSocket `connection` life cycle event has been renamed to `websocket:connection` ([#2783](mswjs/msw#2783)).
- `onUnhandledRequest` option has been renamed to `onUnhandledFrame`.
- The library no longer patches `setTimeout` to circumvent fake timers in test runners. You should advance the fake timers normally for delayed mocked responses to resolve.
- The library no longer returns a mocked cookie string on `request.headers.get('cookie')` in the handlers. It returns `null` in all environments. Please use the `cookies` resolver argument to have cookie-based logic.

##### Features

- Supports Node.js v24 and v26.
- Supports TypeScript v6.0 and v7.0.
- You can import individual utilities, like `delay` or `passthrough`, from the new `msw/utils` entrypoint for smaller footprint on your bundle.
- Support GraphQL v17.0.
- Support intercepting page navigations and form submissions ([#2721](mswjs/msw#2721)).
- Support GraphQL subscriptions ([#285](mswjs/msw#285), [#2763](mswjs/msw#2763)).
- Migrate from `path-to-regexp` to `@msw/url` ([#2678](mswjs/msw#2678)).
- Remove the following dependencies:
  - `graphql`
  - `path-to-regexp`
  - `picocolors`
  - `statuses`
  - `strict-event-emitter`
- Adds a Vite plugin for MSW ([#2781](mswjs/msw#2781)).
- Adds a `websocket:error` life cycle event to listen to WebSocket connection errors ([#2784](mswjs/msw#2784)).
- Support modifying the intercepted request headers in passthrough scenarios ([#2786](mswjs/msw#2786)).
- Support a new WebSocket Extension API that allows for better custom experiences ([#2791](mswjs/msw#2791)).

##### Bug fixes

- Fix an issue where preventing a page closure via the `beforeunload` listener would unregister the MSW worker ([#1105](mswjs/msw#1105)).
- Fix an issue that caused intermittent test failures in Vitest Browser Mode and Firefox if using `maxWorkers: 1` ([#2726](mswjs/msw#2726)).
- Fix an issue where in-flight requests were incorrectly passthrough when performed before calling `worker.stop()` ([#2724](mswjs/msw#2724), [#2597](mswjs/msw#2597)).
- Fix an issue where persisting cookies in `localStorage` would cause a maximum quota exceeded errors.
- Fix various issues related to the network interception in Node.js.
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.

Can’t import virtual:msw in Vitest

1 participant