vitest-auto-spy 5.42.0 → 5.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +175 -1
  3. package/README.md +151 -133
  4. package/agent-docs/angular.md +33 -8
  5. package/agent-docs/checklist.md +11 -3
  6. package/agent-docs/configuration.md +3 -2
  7. package/agent-docs/errors.md +1 -0
  8. package/agent-docs/eslint.md +1 -1
  9. package/agent-docs/factories.md +11 -0
  10. package/agent-docs/setup.md +34 -3
  11. package/dist/angular-diagnostics.js +3 -3
  12. package/dist/angular-doubles.d.ts +1 -1
  13. package/dist/angular-doubles.js +3 -3
  14. package/dist/angular-http.d.ts +17 -5
  15. package/dist/angular-http.js +3 -2
  16. package/dist/angular-matchers.d.ts +11 -3
  17. package/dist/angular-matchers.js +16 -9
  18. package/dist/angular-router.d.ts +2 -2
  19. package/dist/angular-router.js +1 -1
  20. package/dist/angular.d.ts +7 -7
  21. package/dist/angular.js +1 -1
  22. package/dist/bun-angular.d.ts +5 -5
  23. package/dist/bun-angular.js +6 -6
  24. package/dist/bun.d.ts +5 -5
  25. package/dist/bun.js +3 -3
  26. package/dist/{chunk-MHN6GMXP.js → chunk-FQ6NT2IN.js} +1 -1
  27. package/dist/{chunk-EYXARTWD.js → chunk-I6CB4CNT.js} +24 -4
  28. package/dist/{chunk-J4IJCTHT.js → chunk-IB72SVKT.js} +1 -1
  29. package/dist/{chunk-RYEBG2KB.js → chunk-M5H32F4Q.js} +2 -2
  30. package/dist/{chunk-25QOHNGU.js → chunk-NGZYYSEA.js} +2 -2
  31. package/dist/{chunk-CENALW7R.js → chunk-PUUSCWDD.js} +1 -1
  32. package/dist/{chunk-J2C3KRTC.js → chunk-QGLUX55Q.js} +1 -1
  33. package/dist/cli.js +365 -209
  34. package/dist/console.d.ts +18 -2
  35. package/dist/console.js +26 -4
  36. package/dist/dom-stubs.d.ts +2 -2
  37. package/dist/eslint-plugin.cjs +112 -2
  38. package/dist/{expect-emission-D273986K.d.ts → expect-emission-DMQZF5QR.d.ts} +1 -1
  39. package/dist/index.d.ts +4 -4
  40. package/dist/index.js +24 -4
  41. package/dist/jasmine-compat.d.ts +1 -1
  42. package/dist/jasmine.d.ts +2 -2
  43. package/dist/jasmine.js +4 -4
  44. package/dist/nestjs.d.ts +2 -2
  45. package/dist/nestjs.js +6 -6
  46. package/dist/node.cjs +24 -4
  47. package/dist/node.d.ts +4 -4
  48. package/dist/node.js +24 -4
  49. package/dist/{package-identity-BnqwTQIn.d.ts → package-identity-5kYzh3ad.d.ts} +3 -1
  50. package/dist/perf-reporter.d.ts +5 -0
  51. package/dist/perf-reporter.js +28 -3
  52. package/dist/{prop-mock-Cz0yKWEP.d.ts → prop-mock-WOpRQPUc.d.ts} +1 -1
  53. package/dist/react.d.ts +4 -4
  54. package/dist/rstest.d.ts +4 -4
  55. package/dist/rstest.js +4 -4
  56. package/dist/rxjs.d.ts +2 -2
  57. package/dist/setup.d.ts +63 -6
  58. package/dist/setup.js +203 -22
  59. package/dist/svelte.d.ts +4 -4
  60. package/dist/{track-injections-BTJKOqWz.d.ts → track-injections-CYQKc3M8.d.ts} +10 -4
  61. package/dist/{track-signal-runs-bs2umXNE.d.ts → track-signal-runs-CyPA-p4I.d.ts} +3 -3
  62. package/dist/{types-CyRUgJVd.d.ts → types-Dxw-oWfr.d.ts} +7 -2
  63. package/dist/vue.d.ts +5 -5
  64. package/package.json +1 -1
  65. package/skills/vitest-auto-spy/SKILL.md +141 -134
package/AGENTS.md CHANGED
@@ -81,7 +81,7 @@ Add-ons, orthogonal to the runner:
81
81
  | --- | --- | --- |
82
82
  | Observable spies | `import 'vitest-auto-spy/rxjs'` | `nextWith` & friends. **Side-effect import, once**, in a setup file, a spec, or a `.d.ts` the `tsconfig` includes (§4) |
83
83
  | observer-spy shim | `vitest-auto-spy/observer-spy` | `subscribeSpyTo` — the `@hirez_io/observer-spy` surface (§20). Its own entry so `/rxjs` does not carry it |
84
- | Console spies | `vitest-auto-spy/console` | silent typed spies over the global `console` — `installConsoleSpies()` per test, `restoreConsole()` after |
84
+ | Console spies | `vitest-auto-spy/console` | silent typed spies over the global `console` — `installConsoleSpies()` per test, `restoreConsole()` after; `consoleOutput()` is everything logged, keyed by channel |
85
85
  | DOM stubs | `vitest-auto-spy/dom-stubs` | `stubIntersectionObserver` / `stubResizeObserver` / `stubMutationObserver` / `stubObserver`, `stubMediaElement`, `stubAbortController`, `stubWebStorage` (§12), `stubAnimationFrame`, `stubElementRect`, `intersectionEntry` / `resizeEntry` / `mutationRecord`. **Moved off the root in 4.0.0** |
86
86
  | Run diagnostics | `vitest-auto-spy/diagnostics` | `compareTestRuns`, `summarizeTestRun`, `formatTestRunComparison`, `diffByField`. **Moved off the root in 4.0.0** |
87
87
  | Angular HTTP | `vitest-auto-spy/angular-http` | `provideHttpTesting`, `expectRequest` — `httpResource()` / `HttpClient` (§13). Optional `@angular/common` peer, this entry only |
package/CHANGELOG.md CHANGED
@@ -10,6 +10,178 @@ The latest released version here must always match the one published on
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [5.44.0] - 2026-09-27
14
+
15
+ ### Added
16
+
17
+ - **`doctor` warns when `vitest run` and the Angular builder test on different DOMs.**
18
+ `runner-dom-differs-from-builder` (warning): a `vitest.config.*` / `vite.config.*` that sets
19
+ `environment: 'jsdom'` beside an `@angular/build:unit-test` / `@nx/angular:unit-test` target that
20
+ runs happy-dom (both installed; the builder picks happy-dom whenever it resolves). `nx test` and the
21
+ IDE then run the same specs on two DOMs, and doctor said nothing — `angular-build-happy-dom` stays
22
+ quiet once happy-dom is installed. The fix aligns on happy-dom; a jsdom-only spec keeps
23
+ `// @vitest-environment jsdom`. On a 48-file Angular suite the switch took Duration from 1.37 s to
24
+ 1.10 s (−20 %).
25
+ - **`doctor` warns when Analog's `setupTestBed()` is laxer than the builder's TestBed.**
26
+ `analog-testbed-laxer-than-builder` (warning): `setupTestBed()` from
27
+ `@analogjs/vitest-angular/setup-testbed` leaves `errorOnUnknownElements` /
28
+ `errorOnUnknownProperties` off, while `@angular/build:unit-test` (20.x and 22.x checked) turns both
29
+ on, so a template typo only logs under `vitest run` and fails under `nx test`. The fix gives the
30
+ call: `setupTestBed({ errorOnUnknownElements: true, errorOnUnknownProperties: true })`. A flag
31
+ written with any value, and options passed as a variable, are left alone.
32
+ - **`consoleOutput()` from `vitest-auto-spy/console`: everything a test logged, as one value.**
33
+ Pinning a CLI's exact output meant asserting every spy at once, so each suite wrote its own
34
+ `logged()` over `consoleErrorSpy` / `consoleWarnSpy` / `consoleInfoSpy`; in one consumer that exact
35
+ form found a `console.warn` a test had passed over with `toHaveBeenCalledWith` for months.
36
+ `consoleOutput()` returns the argument lists of every recorded call keyed by channel (`debug`,
37
+ `error`, `info`, `log`, `trace`, `warn`), only the channels written to, so
38
+ `expect(consoleOutput()).toStrictEqual({ info: [['done']] })` pins the whole output with a full diff
39
+ and `{}` means silence. It throws while no spy is on `console`, rather than report silence it did
40
+ not hear. A function, not a `toHaveLogged` matcher: `toStrictEqual` already gives the diff, and the
41
+ matcher would have doubled the growth and registered `expect.extend` on every import. `/console` is
42
+ +208 B min+gzip (9973 → 10181 B, +2.1 %).
43
+ - **`strayTimers: { ignore: [...] }`.** The object form turns the sweep on and leaves alone every
44
+ timer whose scheduling stack contains one of the substrings or matches one of the RegExps — never
45
+ counted, reported or cancelled, since its owner still holds the handle. `trackStrayTimers(host,
46
+ { ignore })` takes the same list; the latest call's list is in force. The type is exported from
47
+ `/setup` as `StrayTimersOptions`. For a dependency's housekeeping no spec can reach, which until now
48
+ could only be silenced by turning `strayTimers` off for the whole project.
49
+ - **An Observable error nothing handled fails the test that raised it.** rxjs rethrows such an error
50
+ from `setTimeout(() => { throw error })`, which fails no test: it fired after the test, or the sweep
51
+ cancelled it at the end of the file and all that was left was a stray `setTimeout 0 ms, scheduled
52
+ in "<test>" at TestRequest.error` — the real error gone. With `strayTimers` on, the `afterEach` now
53
+ runs that pending rethrow early and fails the test with `Unhandled Observable error in "<test>"`,
54
+ quoting the error and carrying it as `cause`; a rethrow scheduled outside a test fails the file at
55
+ its sweep. It reads the fake clock as well while one is installed (`globalFakeTimers`), and a
56
+ rethrow `config.onUnhandledError` takes reports nothing, as in rxjs. `flushUnhandledObservableErrors()`
57
+ in `/setup` is the same check by hand. On by default with `strayTimers`, because without the sweep
58
+ the rethrow is an uncaught exception that fails the run anyway: the sweep was what hid it. The
59
+ scheduler wrappers' hot path is unchanged: a tracked `setTimeout` + `clearTimeout` pair measured
60
+ 2.13–2.20 µs before and 2.13–2.17 µs after on a stand-in host, 2.50–2.55 µs both ways on Node's real
61
+ timers, interleaved runs.
62
+ - **`provideHttpTesting({ interceptors, features })`.** A suite whose interceptor was under test had
63
+ to write `provideHttpClient(withInterceptors([...]))` + `provideHttpClientTesting()` itself, which
64
+ lost the end-of-test check and meant an `afterEach(() => verifyNoPendingRequests())` by hand.
65
+ `interceptors` takes functional interceptors and `features` any other `provideHttpClient()`
66
+ feature (`withInterceptorsFromDi()`, `withXsrfConfiguration()`); both go into one
67
+ `provideHttpClient()` call, before `provideHttpClientTesting()`, and the teardown check stays armed.
68
+ `interceptors` run in array order, before those `features` brings. `/angular-http` is +52 B
69
+ min+gzip (3652 → 3704 B, +1.4 %).
70
+
71
+ ### Fixed
72
+
73
+ - **`strayConsole` sees what the DOM environment writes — a suite under `'throw'` can newly fail.**
74
+ happy-dom's page console and jsdom's virtual console hold the worker's own console, captured when
75
+ the environment was built, before Vitest swapped `globalThis.console`; so happy-dom's
76
+ `NotSupportedError: Failed to load iframe page … Iframe page loading is disabled` and jsdom's
77
+ `Not implemented: navigation`
78
+ reached stderr of a green run, past the guard and past every console spy. The guard now routes that
79
+ console into the one it watches: the line fails the test that caused it at the spec's frame, a
80
+ `/console` spy or `vi.spyOn(…).mockImplementation` absorbs it (and can assert it), and both lines
81
+ get a `Likely cause:`. A suite under `strayConsole: 'throw'` (the `setupAutoSpy` default) that had
82
+ such lines on stderr now fails on them — that output is what the guard promises to catch. Fix the
83
+ cause (stub the API, mock the navigation, absorb it with a console spy), or let a line through with
84
+ `strayConsole: { allow: ['Not implemented: navigation'] }`. Routing is off when Vitest does not
85
+ intercept the console (`disableConsoleIntercept`).
86
+ - **`no-redundant-mock-reset` no longer calls a reset dead on a flag the Angular unit-test builder
87
+ never reads.** `@angular/build:unit-test` and `@nx/angular:unit-test` hand Vitest `config: false`
88
+ unless the target names a `runnerConfig`, so a `restoreMocks: true` / `mockReset: true` in the
89
+ `vitest.config.ts` the rule read (found or `configFile`) did not apply under `ng test` / `nx test`,
90
+ and deleting the reported line broke that run. The rule now finds the unit-test targets whose
91
+ project root holds the spec (`angular.json` / `workspace.json` / `project.json`, executors from
92
+ `nx.json` `targetDefaults`), resolves each target's and configuration's `runnerConfig` as the
93
+ builder does, and reports a reset only where every run performs it. A clear stays reported on
94
+ Vitest 5, whose default clears under the builder too. Workspaces without such a target, and flags
95
+ passed inline as options, are read as before. `/eslint-plugin` is +825 B min+gzip (42269 →
96
+ 43094 B, +2.0 %): the workspace reader.
97
+ - **A function in `overrides` for a method is a spy now, as `Spy<T>` says.** `provideAutoSpy(DomSanitizer,
98
+ { overrides: { sanitize: (_c, v) => String(v) } })` stored the function as written, so
99
+ `expect(injectSpy(DomSanitizer).sanitize).toHaveBeenCalledOnce()` compiled and threw
100
+ `[Function sanitize] is not a spy`. On `createSpyFromClass` / `provideAutoSpy` a plain function seeded
101
+ on a method (a prototype method, a name in `methodsToSpyOn` / `instanceMethodsToSpyOn` /
102
+ `onlyMethodsToSpyOn`, any member of the abstract-class fallback or a `fillMissing` double) becomes that
103
+ method's spy with the function as its implementation: calls, `mock.calls` and `calledWith` work, the
104
+ function runs with the double as `this` until the test configures the spy, it counts as configured
105
+ under `strict` (framework hooks such as `ngOnDestroy` included), and `resetAutoSpy` brings it back.
106
+ Kept exactly as seeded: values, getter seeds, a function on a non-method field, a class, and any
107
+ callable with its own API — a `vi.fn()`, a library spy, a signal — so a held `vi.fn()` keeps its
108
+ identity. The seed still wins over `returns` / `selfReturning` for the same key. `createAutoMock`,
109
+ `provideAutoSpyForToken` and `createSpyFromInstance` are unchanged. Cost: one spy per seeded method,
110
+ created at build instead of on first read (+0.5 µs per seeded method, `bench` case "createSpyFromClass
111
+ with overrides"); the root entry is +191 B min+gzip (27636 → 27827 B, +0.7 %), and the entries
112
+ built on it +182–216 B each.
113
+ - **`perf-heap` no longer calls the first load of a module a leak.** Under `isolate: false` a worker
114
+ evaluates a module once and keeps it, so the first file in a lane to import `@sentry/angular` or a
115
+ zod-heavy barrel showed its +8–10 MB as heap the spec left behind, and two runs over the same files
116
+ named different files. The reporter now records, per file, the modules the worker evaluated for the
117
+ first time (keys of Vitest's import durations the lane's previous file did not have), and `perf`
118
+ lists growth that comes with a first load of 50 ms or more in a second note, "first load of
119
+ `@sentry/angular` in this worker (+8 MB), not retained by the spec". When several lanes first-loaded
120
+ the same module, a file at more than twice the middle reading keeps the rest in the leak list
121
+ ("+21 MB beyond the first load of …"); a file that loaded nothing new is reported as before. A
122
+ measured run under `isolate: false` asks Vitest for 30 import durations instead of 10, because the
123
+ worker's table keeps every earlier spec. The report gains an optional `firstLoads` per file (format
124
+ version unchanged; an older report reads as before). `/perf-reporter` is +242 B min+gzip (1736 →
125
+ 1978 B, +13.9 %) and +1.4 kB to import (8599 → 9967 B): the lane walk that finds the first loads.
126
+ - **`strayTimers` no longer charges undici's timers to the spec.** Node's global `fetch()` runs on
127
+ undici, which keeps a 499 ms tick and a keep-alive timeout per pooled connection. A file that
128
+ fetched from a server it could not close failed `onStrayTimers: 'throw'` with `setTimeout 499 ms …
129
+ at new Promise (<anonymous>)` and `setTimeout 3000 ms … at Parser.setTimeout (…/undici/lib/…)`,
130
+ nothing a spec could fix. A timer whose scheduling call's nearest frame outside this package and
131
+ zone.js is undici (`node:internal/deps/undici`, or the `undici` package) is now neither counted,
132
+ reported nor cancelled — cancelling it would stall undici's timeouts for the rest of the worker. A
133
+ spec callback undici calls synchronously (a `MockAgent` reply) still has its own timers charged.
134
+
135
+ ### Size
136
+
137
+ `/setup` **27760 → 29187 B** min+gzip (+1427 B, +5.1 %) and +7.7 kB to import (157520 → 165233 B):
138
+ about 1.0 kB of it is the unhandled-Observable check and `strayTimers: { ignore }` with the undici
139
+ filter, about 0.4 kB the environment-console routing and its two `Likely cause:` lines (an esbuild
140
+ bundle of the sources before and after each, 31133 → 31544 → 32607 B).
141
+
142
+ ## [5.43.0] - 2026-09-27
143
+
144
+ ### Added
145
+
146
+ - **`trackInjections(...).names({ clean: true })`.** `names()` returns each token's `Function.name`
147
+ as is, so under esbuild a decorated `FeatureFlagService` came back as `_FeatureFlagService` while
148
+ `get()` and every message printed the clean name. The option takes the rename off (the leading `_`,
149
+ Rollup's `$1`); without it the result is unchanged.
150
+ - **`toHaveSignalValue(expected, { strict: true })`.** The matcher compares the way `toEqual` does, so
151
+ `signal({ color: undefined })` passed against `{}` and a class instance against a plain object; a
152
+ spec on `expect(sig()).toStrictEqual(x)` lost precision by moving to it. `strict` counts
153
+ `undefined` properties, array holes and the object's class, as `toStrictEqual` does. The options
154
+ type is exported from `/angular/matchers` as `SignalValueOptions`. `/angular/matchers` is +137 B
155
+ min+gzip (2662 → 2799 B, +5.1 %) and +0.6 kB to import (22349 → 22906 B): the strict comparison,
156
+ its class tester, and the structural-directive message below.
157
+
158
+ ### Changed
159
+
160
+ - **`angular-build-istanbul-module-cache` puts its −46 % in range.** A second suite, 862 spec files on
161
+ `@angular/build` 22.2 and Vitest 5.0.2, gained −19 % from the cache (48 → 39 s), while switching it
162
+ to v8 ran in 19–22 s, about twice as fast as istanbul with the cache, on 7.5–8 GB RSS against
163
+ 10–11 GB. The finding now gives −46 % as "up to", adds that data point, says the cache pays off on
164
+ CI only when CI keeps `node_modules/.vitest-cache`, and its fix offers `coverage.provider: 'v8'` as
165
+ the alternative. Still an info.
166
+
167
+ ### Fixed
168
+
169
+ - **`toHaveDirectiveApplied(Structural, selector)` no longer sends a structural directive to
170
+ `detectChanges()`.** When the directive rendered nothing the selector names, the failure said no
171
+ element matches and to run `fixture.detectChanges()`, which changes nothing. It now says the
172
+ directive is on a template anchor, that the element exists only in a view the directive chose to
173
+ render, and to assert without a selector.
174
+ - **Docs that disagreed with 5.41–5.42.** The performance table and README called the
175
+ `lazySpies: true` path "the default" (a class of 8+ methods now gets `'proxy'`) and said lazy spies
176
+ change no behaviour; the width is now defined as the methods the double spies, after
177
+ `onlyMethodsToSpyOn` / `methodsToSpyOn`. The Russian Angular page carried the pre-4.1 speed table.
178
+ The strict-mode and control-helper pages now say a delegating `mockImplementation` and `vi.when` are
179
+ not reported, and a `vi.when` over a `mockReturnValue` is. The CLI page counts `ng-test` among the
180
+ commands, says it exits with `ng`'s code, lists its exit-2 cases, that `--related` takes a
181
+ comma-separated list and that the builder compiles only included specs from `@angular/build` 22.2
182
+ (also in `--help`); the Russian CLI page gains the exit-code table. `RouteResources` is `never` up
183
+ to router 22.1, not only on 20 and 21.
184
+
13
185
  ## [5.42.0] - 2026-09-27
14
186
 
15
187
  ### Added
@@ -5692,7 +5864,9 @@ moved under 1 %: `/angular` +192 B (+1.0 %) for the override queue and the HTTP
5692
5864
  This copy ships with the package and carries 5.x only. Releases before 5.0.0 are in the
5693
5865
  [full changelog](https://github.com/ASDAlexey/vitest-auto-spy/blob/master/CHANGELOG.md).
5694
5866
 
5695
- [Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.42.0...HEAD
5867
+ [Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.44.0...HEAD
5868
+ [5.44.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.43.0...v5.44.0
5869
+ [5.43.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.42.0...v5.43.0
5696
5870
  [5.42.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.41.0...v5.42.0
5697
5871
  [5.41.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.40.1...v5.41.0
5698
5872
  [5.40.1]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.40.0...v5.40.1