Commit 15afbc0
authored
fix(test): auto-inline packages that use
## Summary
Fixes `expect.extend()` matchers from third-party packages (e.g.,
`@testing-library/jest-dom`) not being registered on the test runner's
`expect` instance, causing errors like `Invalid Chai property:
toBeInTheDocument`.
resolve #897
## Root Cause
When third-party packages call
`require('vitest').expect.extend(matchers)` internally, the npm override
(`vitest` → `@voidzero-dev/vite-plus-test`) causes Node.js to load a
**separate module instance** with its own `chai` and `expect`.
Matchers are registered on this separate instance, not on the test
runner's `expect`.
The root issue is the **externalization behavior** of vitest's module
runner. By default, third-party packages in `node_modules` are
externalized — loaded via Node.js native `require`/`import`.
When an externalized package calls `require('vitest')`, Node.js resolves
it through the npm override, producing a different module instance with
a separate `chai`.
## Fix
Patch vitest's `ModuleRunnerTransform` plugin during re-packaging
(`build.ts`) to automatically add known affected packages to
`server.deps.inline` in the `configResolved` hook.
This forces the Vite module runner to process these packages through its
transform pipeline instead of externalizing them to Node.js.
### Normal flow (plain vitest — no npm override)
```mermaid
sequenceDiagram
participant Runner as Test Runner
participant JestDOM as @testing-library/jest-dom
participant NodeJS as Node.js require()
participant Vitest as vitest module
Runner->>Vitest: import vitest (cached by Node.js)
Runner->>Runner: createExpect() → globalExpect
Note over JestDOM: setupFiles execution
JestDOM->>NodeJS: require('vitest')
NodeJS-->>JestDOM: Same vitest module (cached)
JestDOM->>Vitest: expect.extend(matchers)
Note over Vitest: OK: Matchers registered on<br/>the same chai instance
Runner->>Runner: expect(el).toBeInTheDocument() OK:
```
### Bug flow (vite-plus — npm override splits module instances)
```mermaid
sequenceDiagram
participant Runner as Test Runner
participant JestDOM as @testing-library/jest-dom
participant NodeJS as Node.js require()
participant VitestA as vitest (runner instance)
participant VitestB as @voidzero-dev/vite-plus-test<br/>(override instance)
Runner->>VitestA: import vitest
Runner->>Runner: createExpect() with chai-A
Note over JestDOM: setupFiles execution (externalized by default)
JestDOM->>NodeJS: require('vitest')
NodeJS->>NodeJS: npm override rewrites to<br/>@voidzero-dev/vite-plus-test
NodeJS-->>JestDOM: Different module instance
JestDOM->>VitestB: expect.extend(matchers)
Note over VitestB: Matchers registered on chai-B
Runner->>Runner: expect(el).toBeInTheDocument()
Note over Runner: NG: chai-A has no matchers<br/>Invalid Chai property
```
### Fix flow (with `server.deps.inline` patch)
```mermaid
sequenceDiagram
participant Runner as Test Runner
participant JestDOM as @testing-library/jest-dom
participant ModRunner as Vite Module Runner
participant Resolve as vitest:resolve-core
participant Vitest as vitest (single instance)
Runner->>Vitest: import vitest (cached)
Runner->>Runner: createExpect() with chai
Note over JestDOM: setupFiles execution (inlined by patch)
JestDOM->>ModRunner: require('vitest')
ModRunner->>ModRunner: Transform to __vite_ssr_import__
ModRunner->>Resolve: resolve 'vitest'
Resolve-->>ModRunner: dist/index.js (same file)
ModRunner-->>JestDOM: Same module instance (cached)
JestDOM->>Vitest: expect.extend(matchers)
Note over Vitest: OK: Matchers registered on<br/>the same chai instance
Runner->>Runner: expect(el).toBeInTheDocument() OK:
```
### Auto-inlined packages
-
[testing-library/jest-dom](https://github.com/testing-library/jest-dom):
17.7M/weekly download, Calls `require('vitest').expect.extend(matchers)`
via `./vitest` subpath
- [storybookjs/storybook](https://github.com/storybookjs/storybook):
2M/weekly download, Uses `@vitest/expect` internally with
`expect.extend()`
-
[jest-community/jest-extended](https://github.com/jest-community/jest-extended):
958K/weekly download, Calls `expect.extend()` on import
These three packages cover **99.5%** of weekly downloads among all
affected packages.
The list was determined by downloading npm tarballs of all known
`expect.extend` using packages and inspecting their source code.expect.extend() to fix module instance splitting (#1113)1 parent 34caff3 commit 15afbc0
4 files changed
Lines changed: 127 additions & 3 deletions
File tree
- .github/workflows
- ecosystem-ci
- packages/test
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
285 | 285 | | |
286 | 286 | | |
287 | 287 | | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
288 | 292 | | |
289 | 293 | | |
290 | 294 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
94 | 100 | | |
95 | 101 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
8 | | - | |
| 6 | + | |
| 7 | + | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
| |||
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
19 | 28 | | |
20 | 29 | | |
21 | 30 | | |
| |||
55 | 64 | | |
56 | 65 | | |
57 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
58 | 94 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
224 | 224 | | |
225 | 225 | | |
226 | 226 | | |
| 227 | + | |
227 | 228 | | |
228 | 229 | | |
229 | 230 | | |
| |||
2360 | 2361 | | |
2361 | 2362 | | |
2362 | 2363 | | |
| 2364 | + | |
| 2365 | + | |
| 2366 | + | |
| 2367 | + | |
| 2368 | + | |
| 2369 | + | |
| 2370 | + | |
| 2371 | + | |
| 2372 | + | |
| 2373 | + | |
| 2374 | + | |
| 2375 | + | |
| 2376 | + | |
| 2377 | + | |
| 2378 | + | |
| 2379 | + | |
| 2380 | + | |
| 2381 | + | |
| 2382 | + | |
| 2383 | + | |
| 2384 | + | |
| 2385 | + | |
| 2386 | + | |
| 2387 | + | |
| 2388 | + | |
| 2389 | + | |
| 2390 | + | |
| 2391 | + | |
| 2392 | + | |
| 2393 | + | |
| 2394 | + | |
| 2395 | + | |
| 2396 | + | |
| 2397 | + | |
| 2398 | + | |
| 2399 | + | |
| 2400 | + | |
| 2401 | + | |
| 2402 | + | |
| 2403 | + | |
| 2404 | + | |
| 2405 | + | |
| 2406 | + | |
| 2407 | + | |
| 2408 | + | |
| 2409 | + | |
| 2410 | + | |
| 2411 | + | |
| 2412 | + | |
| 2413 | + | |
| 2414 | + | |
| 2415 | + | |
| 2416 | + | |
| 2417 | + | |
| 2418 | + | |
| 2419 | + | |
| 2420 | + | |
| 2421 | + | |
| 2422 | + | |
| 2423 | + | |
| 2424 | + | |
| 2425 | + | |
| 2426 | + | |
| 2427 | + | |
| 2428 | + | |
| 2429 | + | |
| 2430 | + | |
| 2431 | + | |
| 2432 | + | |
| 2433 | + | |
| 2434 | + | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
| 2439 | + | |
| 2440 | + | |
2363 | 2441 | | |
2364 | 2442 | | |
2365 | 2443 | | |
| |||
0 commit comments