vitest-auto-spy 5.0.1 → 5.2.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.
- package/AGENTS.md +119 -11
- package/README.md +46 -11
- package/dist/angular.d.ts +28 -6
- package/dist/angular.js +203 -15
- package/dist/bun-angular.d.ts +5 -5
- package/dist/bun-angular.js +7 -8
- package/dist/bun.d.ts +81 -5
- package/dist/bun.js +5 -6
- package/dist/{chunk-Q74KQJWG.js → chunk-5TUDM4DS.js} +39 -1
- package/dist/chunk-ED4EVQKA.js +74 -0
- package/dist/{chunk-CWHCYCCQ.js → chunk-GOG2CJOY.js} +1 -1
- package/dist/{chunk-VX5DDHAS.js → chunk-J33KX6XT.js} +48 -3
- package/dist/{chunk-Y4YG7UOK.js → chunk-JJ2JA2E3.js} +1 -1
- package/dist/{chunk-NTJDMRHP.js → chunk-KE3LEHPW.js} +11 -56
- package/dist/{chunk-5LLY42R7.js → chunk-NHSUUN3D.js} +1 -1
- package/dist/{chunk-YZOB2KRF.js → chunk-URZIJ5CL.js} +3 -3
- package/dist/{chunk-ZLF2YBXV.js → chunk-XAS66AWX.js} +50 -2
- package/dist/cli.js +316 -300
- package/dist/console.d.ts +1 -1
- package/dist/console.js +3 -2
- package/dist/dom-stubs.d.ts +1 -1
- package/dist/dom-stubs.js +56 -6
- package/dist/eslint-plugin.cjs +331 -76
- package/dist/eslint-plugin.d.cts +56 -0
- package/dist/eslint-plugin.d.ts +56 -0
- package/dist/{expect-emission-Dy5CvsF2.d.ts → expect-emission-DYtyyKM5.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +145 -8
- package/dist/jasmine-compat.d.ts +1 -1
- package/dist/jasmine.d.ts +2 -2
- package/dist/jasmine.js +5 -4
- package/dist/nestjs.d.ts +2 -2
- package/dist/nestjs.js +6 -5
- package/dist/node.cjs +96 -3
- package/dist/node.d.cts +3 -0
- package/dist/node.d.ts +4 -4
- package/dist/node.js +5 -5
- package/dist/{prop-mock-Dp2ZMFqj.d.ts → prop-mock-DmM-rPcG.d.ts} +44 -2
- package/dist/react.d.ts +4 -4
- package/dist/react.js +6 -5
- package/dist/rstest.d.ts +6 -0
- package/dist/rstest.js +63 -0
- package/dist/rxjs.d.ts +2 -2
- package/dist/setup.d.ts +21 -9
- package/dist/setup.js +7 -4
- package/dist/shared-state.js +1 -1
- package/dist/svelte.d.ts +4 -4
- package/dist/svelte.js +6 -5
- package/dist/{track-injections-CAqxzlhV.d.ts → track-injections-D4TuS8yk.d.ts} +1 -1
- package/dist/{types-CQLPjw8z.d.ts → types-DTi4dIeN.d.ts} +91 -22
- package/dist/vue.d.ts +5 -5
- package/dist/vue.js +7 -6
- package/dist/{zoneless-BFq3ve6Q.d.ts → zoneless-BerZbxtu.d.ts} +36 -4
- package/package.json +14 -3
- package/skills/vitest-auto-spy/SKILL.md +38 -6
- package/dist/chunk-NQXXUJPS.js +0 -39
package/AGENTS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# vitest-auto-spy — instructions for AI coding agents
|
|
2
2
|
|
|
3
3
|
You are looking at the agent-facing reference for **`vitest-auto-spy`**: typed test spies generated
|
|
4
|
-
from a class, a type, or nothing at all, on Vitest / `bun:test` / `node:test
|
|
4
|
+
from a class, a type, or nothing at all, on Vitest / `bun:test` / `node:test` / Rstest.
|
|
5
5
|
|
|
6
6
|
This file is written for an agent **using** the library in someone's test suite. It is shipped
|
|
7
7
|
inside the npm package, so it is readable with no network:
|
|
@@ -43,6 +43,7 @@ adapter installed and spies fail at runtime.
|
|
|
43
43
|
| `bun test` | `vitest-auto-spy/bun` |
|
|
44
44
|
| `bun test` + Angular | `vitest-auto-spy/bun-angular` |
|
|
45
45
|
| `node --test` | `vitest-auto-spy/node` |
|
|
46
|
+
| `rstest run` | `vitest-auto-spy/rstest` |
|
|
46
47
|
| Angular + Vitest | `vitest-auto-spy/angular` |
|
|
47
48
|
| NestJS | `vitest-auto-spy/nestjs` |
|
|
48
49
|
| React | `vitest-auto-spy/react` |
|
|
@@ -633,6 +634,31 @@ Also true, and worth not re-deriving:
|
|
|
633
634
|
mapping = createSpyFromClass(MgwMappingService); // no second type argument here
|
|
634
635
|
```
|
|
635
636
|
|
|
637
|
+
**The symptom that leads here says nothing about overloads**, which is why the option is hard to
|
|
638
|
+
find from the error. A stub of the real response shape is rejected on the spec's own line —
|
|
639
|
+
`TS2345: Argument of type 'Page' is not assignable to parameter of type 'HttpEvent<Page>'` — on
|
|
640
|
+
`nextWith(body)`, `resolveWith(body)`, `calledWith(…).returnValue(body)` or
|
|
641
|
+
`mockReturnValue(of(body))` against a generated `observe` client. Neither the double nor the stub
|
|
642
|
+
is wrong; both are being checked against the signature nobody calls. Reach for `overload`, never
|
|
643
|
+
for `@ts-expect-error`: one migration wrote sixty of those across twenty-five files before anyone
|
|
644
|
+
found this option, and each one stops checking the response shape that line exists to describe.
|
|
645
|
+
|
|
646
|
+
**Name the method rather than the whole double.** `'first'` on the type moves *every* overloaded
|
|
647
|
+
member, and on a wide type that breaks the ones nobody was fixing — `Spy<Response, { overload:
|
|
648
|
+
'first' }>` for one method collected five `TS2769`s on `download`. `overload` also takes a map:
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
let perf: Spy<Performance, { overload: { getEntriesByType: 'first' } }>;
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
A name the type does not have never matches, so a rename leaves a dead entry rather than a red
|
|
655
|
+
build. The default stays `'last'` because "the useful signature" is not decidable from the type: on
|
|
656
|
+
a generated `observe` client it is the first, on a four-overload `api-mgw` client the last, and both
|
|
657
|
+
live in one suite. And **overload order is not always the author's** — `declare global` in a
|
|
658
|
+
third-party package appends to a global interface (`web-vitals` does exactly this to
|
|
659
|
+
`Performance.getEntriesByType`), so which signature is last depends on which packages are in the
|
|
660
|
+
program and can move on a dependency bump.
|
|
661
|
+
|
|
636
662
|
**A getter that returns a `Signal<T>` goes in `instanceMethodsToSpyOn`**, not in `gettersToSpyOn`.
|
|
637
663
|
`get isKidMode(): Signal<boolean> { return this._isKidMode.asReadonly(); }` is read as a property
|
|
638
664
|
and called as a function, and the accessor route makes you write
|
|
@@ -642,6 +668,29 @@ class prototype, so nothing is being shadowed), and
|
|
|
642
668
|
`service.isKidMode.mockReturnValue(false)` reads like every other member. `mockSignalProp` is the
|
|
643
669
|
other answer when the value has to change during the test.
|
|
644
670
|
|
|
671
|
+
### The composition belongs to the class — `registerAutoSpyDefaults`
|
|
672
|
+
|
|
673
|
+
A class is doubled the same way in every file that doubles it, so register that once instead of
|
|
674
|
+
repeating it:
|
|
675
|
+
|
|
676
|
+
```ts
|
|
677
|
+
// vitest.setup.ts, once
|
|
678
|
+
registerAutoSpyDefaults(Router, { observablePropsToSpyOn: ['events'], gettersToSpyOn: ['url'] });
|
|
679
|
+
|
|
680
|
+
// every spec, from then on
|
|
681
|
+
provideAutoSpy(Router);
|
|
682
|
+
provideAutoSpy(Router, { instanceMethodsToSpyOn: ['currentNavigation'] }); // ADDS to the registration
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
The call site is **merged** into the registration, not substituted for it: lists unioned
|
|
686
|
+
(registration first, no repeats), `returns` / `overrides` merged key by key with the call site
|
|
687
|
+
winning, scalars decided by the call site when it names the key. The bare-array form counts as
|
|
688
|
+
`{ methodsToSpyOn: [...] }`. Registration is by class identity, so a subclass inherits nothing —
|
|
689
|
+
walking the prototype chain would let one registration change doubles in files nobody was looking at.
|
|
690
|
+
A second registration for the same class replaces the first, because two of them in one suite is the
|
|
691
|
+
drift this removes rather than a merge to perform. `clearAutoSpyDefaults(Class)` drops one,
|
|
692
|
+
`clearAutoSpyDefaults()` the lot.
|
|
693
|
+
|
|
645
694
|
### `strict` — a method nobody configured throws instead of answering `undefined`
|
|
646
695
|
|
|
647
696
|
```ts
|
|
@@ -751,6 +800,23 @@ const config = asSpy<FeatureFlagService>(TestBed.inject(FeatureFlagService)); //
|
|
|
751
800
|
const config = injectSpy<FeatureFlagService>(FeatureFlagService); // ✅
|
|
752
801
|
```
|
|
753
802
|
|
|
803
|
+
**A declared default now reaches the double, and used not to.** `class RemoteConfigService<T =
|
|
804
|
+
RemoteConfigDefaults>` handed to `createSpyFromClass` / `injectSpy` inferred `T` as `unknown`, so
|
|
805
|
+
every member typed against it read as `unknown` on a class that had said exactly what it should be.
|
|
806
|
+
Two shapes caused it, both fixed: the `& { [key: string]: any }` intersection `ClassType<T>` used to
|
|
807
|
+
carry (an index signature makes inference drop the default) and the union in `injectSpy`'s token
|
|
808
|
+
parameter (a union does too — a class now matches a bare construct-signature overload first).
|
|
809
|
+
Spelling the argument out still works and is still the answer when the class has **no** default.
|
|
810
|
+
|
|
811
|
+
**A generic *method* is a different thing, and it does collapse.** `show<T, U>(component: Type<T>,
|
|
812
|
+
data: U)` on a modal or factory service reaches `Spy<T>` through `Parameters` / `ReturnType`, which
|
|
813
|
+
instantiate the method's own type parameters — so the double types as `show(component: Type<unknown>,
|
|
814
|
+
data: unknown)`. No mapped type in TypeScript can preserve a generic signature, so this is a limit
|
|
815
|
+
rather than a defect, and it is usually harmless: `unknown` accepts every argument and every seeded
|
|
816
|
+
return, so `spy.show.calledWith(MyModal, data).mockReturnValue(ref)` compiles. It bites only where
|
|
817
|
+
the instantiated type appears in a **contravariant** position; there, name the shape on a declaration
|
|
818
|
+
of your own and assign the factory's result to it.
|
|
819
|
+
|
|
754
820
|
---
|
|
755
821
|
|
|
756
822
|
## 7. Resetting
|
|
@@ -1015,6 +1081,12 @@ and a template error about a null profile appeared in a different `describe`. Th
|
|
|
1015
1081
|
properties back and warns with the count and the cause. `countMockedProps()` is exported if you
|
|
1016
1082
|
would rather assert it: `afterEach(() => expect(countMockedProps()).toBe(0))`.
|
|
1017
1083
|
|
|
1084
|
+
**A `mock*Prop` patch written in a `describe` body or a `beforeAll` is reported**, because the sweep
|
|
1085
|
+
undoes it after the test it was applied during and nothing puts it back: the first test passes and
|
|
1086
|
+
every one after it reads the real member. `propsOutsideHooks` grades that — `'warn'` (default),
|
|
1087
|
+
`'throw'`, `'off'` — and `reportPropsOutsideHooks(reaction)` sets the same dial for a suite that
|
|
1088
|
+
wires its own hooks. Move the call into `beforeEach`.
|
|
1089
|
+
|
|
1018
1090
|
**The one that only bites at scale:** with `isolate: false`, a `setTimeout` or
|
|
1019
1091
|
`requestAnimationFrame` a component schedules and never clears keeps running after its file is done,
|
|
1020
1092
|
and fires while the **next** file is mid-test. It is reported against that innocent file, as
|
|
@@ -1139,10 +1211,16 @@ Everything a spec can observe is the same, and the suite pins it by putting the
|
|
|
1139
1211
|
Vitest applies through those two functions.
|
|
1140
1212
|
|
|
1141
1213
|
**The one difference.** `mock.invocationCallOrder` counts on this library's own scale, so
|
|
1142
|
-
`expect(a).toHaveBeenCalledBefore(b)` is exact between two auto-spies and
|
|
1143
|
-
auto-spy and a hand-written `vi.fn()` —
|
|
1144
|
-
|
|
1145
|
-
|
|
1214
|
+
`expect(a).toHaveBeenCalledBefore(b)` is exact between two auto-spies and **wrong** between an
|
|
1215
|
+
auto-spy and a hand-written `vi.fn()` — not an error, an answer, computed from two counters that
|
|
1216
|
+
never met. `@vitest/spy` keeps its own in a module-private variable it neither exports nor lets
|
|
1217
|
+
anything advance, so the scales cannot be reconciled after the fact; they drift apart by however many
|
|
1218
|
+
calls of each kind the run has already made. Measured in a converted suite: a double reporting
|
|
1219
|
+
`[164, 165, 167, 168, 169]` beside a `vi.fn()` reporting `[28]` for its single call in the same test,
|
|
1220
|
+
under an assertion that had been passing — because `jest-auto-spies` built both halves with
|
|
1221
|
+
`jest.fn()`, which did share one counter. Three earlier calls of one family are enough to invert the
|
|
1222
|
+
verdict. Nothing else in the library or in Vitest reads that field. If a suite needs the comparison,
|
|
1223
|
+
compare two doubles of the same family, or switch the whole run back to the runner's factory:
|
|
1146
1224
|
|
|
1147
1225
|
```ts
|
|
1148
1226
|
// vitest.setup.ts
|
|
@@ -1893,11 +1971,13 @@ enableAngularDiagnostics(); // { ngModuleScopes, deadSchemas, unspiedProviders,
|
|
|
1893
1971
|
| `deadSchemas` | `schemas` sit next to a standalone component (`declarations` empty) — a no-op |
|
|
1894
1972
|
| `unspiedProviders` | `injectSpy` got a real instance; a `console.warn` alone, a throw under the group |
|
|
1895
1973
|
| `pendingRequests` | the test ended with unflushed `HttpTestingController` requests, named one by one |
|
|
1974
|
+
| `shadowedProviders` | a double on the testing module loses to the component's own `providers` |
|
|
1896
1975
|
|
|
1897
1976
|
Every member defaults to `true`, takes `false` to opt out, and a second call **replaces** the
|
|
1898
1977
|
selection (safe from anywhere, including inside a test). `disableAngularDiagnostics()` turns the
|
|
1899
|
-
group off and leaves the TestBed timing instrumentation alone. `
|
|
1900
|
-
|
|
1978
|
+
group off and leaves the TestBed timing instrumentation alone. `assertNoShadowedProviders(Component, fixture)`
|
|
1979
|
+
and `assertNoPendingRequests()` are the same checks on their own, for a spec that renders through a
|
|
1980
|
+
helper of its own or wants the HTTP one mid-test — reading takes the requests, so the group will not
|
|
1901
1981
|
re-report what you inspected.
|
|
1902
1982
|
|
|
1903
1983
|
Nothing here imports `@angular/common/http/testing`: the token is read out of the spec's own
|
|
@@ -2273,6 +2353,25 @@ and costs +206 B per mock against +65 B for naming at creation, measured over 20
|
|
|
2273
2353
|
mock in `node:test`'s reporter output on its own. Full account:
|
|
2274
2354
|
<https://asdalexey.github.io/vitest-auto-spy/runtimes/node#spy-names>.
|
|
2275
2355
|
|
|
2356
|
+
### Rstest
|
|
2357
|
+
|
|
2358
|
+
`vitest-auto-spy/rstest` drives the same core through `rstest.fn()` / `rstest.spyOn()`. Rstest
|
|
2359
|
+
implements the Jest/Vitest mock surface, so **none of the `node:test` differences above apply**:
|
|
2360
|
+
`spy.method.mock.calls[0]` is a bare argument array, the `mockReturnValue` family is native, and
|
|
2361
|
+
`gettersToSpyOn` / `settersToSpyOn` go through `rstest.spyOn(obj, 'prop', 'get' | 'set')` rather than
|
|
2362
|
+
the redefinition fallback. `rstest.clearAllMocks()`, `rstest.resetAllMocks()` and the
|
|
2363
|
+
`clearMocks: true` / `resetMocks: true` config keys reach spies built by `createSpyFromClass` — the
|
|
2364
|
+
entry plants one sentinel mock for it, and there is nothing to enable.
|
|
2365
|
+
|
|
2366
|
+
Two things are not there. `vitest-auto-spy/setup` is wired to Vitest's hooks, so `setupAutoSpy()` and
|
|
2367
|
+
the fake-timer helpers are Vitest-only — on Rstest, import `vitest-auto-spy/rstest` once in the setup
|
|
2368
|
+
file, which is the part a setup file is for. `trackNodeMocks()` is `node:test`-only and is not needed:
|
|
2369
|
+
Rstest drops its mock registry between files, like Vitest and Bun.
|
|
2370
|
+
|
|
2371
|
+
Rstest is 0.x. Vitest stays the zero-config default; reach for this entry when the suite already runs
|
|
2372
|
+
on Rstest, which is typically an Rspack project reusing its bundler config for tests. Full account:
|
|
2373
|
+
<https://asdalexey.github.io/vitest-auto-spy/runtimes/rstest>.
|
|
2374
|
+
|
|
2276
2375
|
---
|
|
2277
2376
|
|
|
2278
2377
|
## 14. `fakeAsync` needs `vitest-auto-spy/zone`
|
|
@@ -2363,6 +2462,10 @@ export default [
|
|
|
2363
2462
|
];
|
|
2364
2463
|
```
|
|
2365
2464
|
|
|
2465
|
+
`autoSpy.configs.typeErrors` is a second flat config holding the subset whose findings are compile
|
|
2466
|
+
errors — `prefer-as-spy` (`TS2352`) and `no-mocked-for-spy` (`TS2322`). Spread its `rules` after a
|
|
2467
|
+
blanket downgrade so those keep their severity; do not copy the two names into a consumer's config.
|
|
2468
|
+
|
|
2366
2469
|
| Rule | Level | Fix | Flags |
|
|
2367
2470
|
| --------------------------------- | ------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
2368
2471
|
| `no-expect-in-subscribe` | `error` | suggest | `expect()` inside `subscribe()` → `expectEmission` / `firstValueFrom` |
|
|
@@ -2377,17 +2480,21 @@ export default [
|
|
|
2377
2480
|
| `no-floating-assertion` | `error` | — | `expect()` in a `.then()` nobody awaits → `expect(await promise)` |
|
|
2378
2481
|
| `no-bare-called-with` | `error` | — | `spy.m.calledWith(1);` as a statement — a stub nobody continued, asserting nothing; chai's `expect(fn).to.have.been.calledWith()` exempt |
|
|
2379
2482
|
| `no-overridden-provider` | `error` | suggest | two providers for one token in one array → the earlier one never runs; the exact duplicate can be deleted |
|
|
2380
|
-
| `no-inject-before-override` | `error` | — | `TestBed.inject()` in a hook, in a suite that still calls `override*` |
|
|
2483
|
+
| `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
|
|
2484
|
+
| `no-private-member-access` | `error` | — | `instance['privateMember']`, `(instance as any).privateMember` (and `as unknown as`, and a decoy type), `vi.spyOn(Object.getPrototypeOf(x), 'm')` → drive the member through the public API. **Type-aware**: silent without `parserOptions.project`, and silent on an index signature |
|
|
2485
|
+
| `no-dead-schemas` | `error` | — | `schemas` on a testing module with no `declarations` — the schema applies to nothing; the file decides, so a `declarations` in another `configureTestingModule` call silences it |
|
|
2381
2486
|
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError` while the bundle loads |
|
|
2382
2487
|
| `no-unregistered-inject-spy` | `error` | — | `injectSpy(X)` for a token this file never registered → the real instance, whose spy helpers exist only for the compiler |
|
|
2383
2488
|
| `prefer-render-shallow` | `error` | suggest | `TestBed.createComponent` in a file that never reads the template → `renderShallow(X)`; 0.24× the per-test cycle at 100 children |
|
|
2489
|
+
| `prefer-observer-stub` | `error` | — | a hand-rolled observer global → `stubIntersectionObserver()` / `stubResizeObserver()` / `stubMutationObserver()`; the manual save-and-restore goes too, `restoreMockedProps()` runs the undo |
|
|
2384
2490
|
| `jasmine-namespace-without-entry` | `error` | — | `.and` / `.calls` / `.withArgs` on a library spy in a file that installs the compat layer nowhere — option: `{ setupModules: […] }` |
|
|
2385
2491
|
| `no-jasmine-globals` | `error` | — | `jasmine.*`, bare `spyOn(` / `spyOnProperty(` / `spyOnAllFunctions(` / `fail(` / `pending(`, `.withContext(` |
|
|
2386
2492
|
| `no-save-arguments-by-value` | `error` | — | `spy.calls.saveArgumentsByValue()` — a no-op here, so the spec silently asserts on post-mutation state |
|
|
2387
2493
|
| `prefer-native-spy-api` | `error` | `--fix` / suggest | `.and` / `.calls` where the spy's own API says the same thing — turn it on for the last mile off the jasmine shim |
|
|
2388
2494
|
|
|
2389
|
-
|
|
2390
|
-
suggestions.
|
|
2495
|
+
Twenty-three rules, **every one an `error` since 4.0.0**; three fix on their own, eight offer
|
|
2496
|
+
suggestions. Twenty-two are syntactic; `no-private-member-access` is the one that reads types, and it
|
|
2497
|
+
reports nothing at all without `parserOptions.project` / `projectService` rather than guessing. The config used to be a graded mix of `error` / `warn` / `off`, which decided for the
|
|
2391
2498
|
consumer how much each finding mattered — a `warn` nothing reads is `off` with extra output. Three of
|
|
2392
2499
|
them can report on a _correct_ project, and only one has an option:
|
|
2393
2500
|
`jasmine-namespace-without-entry` takes `['error', { setupModules: ['./test-setup'] }]`, naming the
|
|
@@ -2585,7 +2692,8 @@ packages, which a subpath export can never be.
|
|
|
2585
2692
|
| `TS2540: Cannot assign to 'X' because it is a read-only property` | a `readonly` field of an object under test | `mockValueProp(obj, 'X', value)` — on a class **getter**, `mockReadonlyProp` |
|
|
2586
2693
|
| `TypeError: Cannot read properties of undefined (reading 'mockReturnValue')` | the member is an **instance field**, not on the prototype — `Router.currentNavigation` since Angular 20 | `provideAutoSpy(Router, { instanceMethodsToSpyOn: ['currentNavigation'] })` (§5) |
|
|
2587
2694
|
| `throwWith` reaching the success branch first, with the previous test's value | the spy's `ReplaySubject(1)` outlived the test that filled it | upgrade; and `resetAutoSpy(spy)` in `beforeEach` when the TestBed is built in `beforeAll` |
|
|
2588
|
-
| `TS2540` on a `Spy<T>` / `createAutoMock` member, which the runtime writes fine | `Spy<T>` is homomorphic
|
|
2695
|
+
| `TS2540` on a `Spy<T>` / `createAutoMock` member, which the runtime writes fine | `Spy<T>` is homomorphic and keeps the `readonly` of the source member — deliberately: on a member replaced by a **spied accessor** the assignment reaches the setter spy and the getter still answers `undefined`, so the type error is the loud version of a silent no-op | `mockValueProp(spy, 'X', value)` — it defines rather than assigns, so it works in both cases; `Mutable<Spy<T>>` is the opt-in for plain data members, and `Reflect.set` is **not** a way round it |
|
|
2696
|
+
| `TS2345` from `mockReturnValue` / `mockImplementation` / `mockResolvedValue` on a double that used to compile | the mock surface is `MockInstance<Method>`, so the stub is now checked against the method's own return type | stub with what the method returns; if the double is meant to answer something else, the method's type or the spec's expectation is wrong |
|
|
2589
2697
|
| `delete mock.optionalMethod` leaving the member present and truthy | the Proxy had no `deleteProperty` trap before 3.5.0 | upgrade; before that, `mock.optionalMethod = undefined` |
|
|
2590
2698
|
| half a double's methods reaching the real implementation after `Object.assign` | `ownKeys` on a type-driven Proxy lists only the keys already read | `createSpyFromClass(X)` — a real object, with enumerable method keys |
|
|
2591
2699
|
| `let s: MockInstance<() => unknown>` not matching anything | `MockInstance<F>` is invariant in `F`; Jest's `SpyInstance` was not | `MockInstance<T['method']>`, or better `injectSpy(X).method` |
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ The only auto-spy library that reads a **class** and gives a **fully-typed** spy
|
|
|
8
8
|
with **return-type-aware** helpers — `resolveWith` / `rejectWith` for `Promise`s, `nextWith` /
|
|
9
9
|
`throwWith` for RxJS `Observable`s, and `calledWith` / `mustBeCalledWith` for argument matching. Or
|
|
10
10
|
skip the class entirely and mock straight from a **type or interface** with `createAutoMock<T>()` and
|
|
11
|
-
recursive `mockDeep<T>()`. Runs on **Vitest**, **Bun** (`bun:test`)
|
|
11
|
+
recursive `mockDeep<T>()`. Runs on **Vitest**, **Bun** (`bun:test`), **`node:test`** and **Rstest** behind one
|
|
12
12
|
identical API, with **RxJS** spies and **Angular / NestJS / React / Vue·Pinia / Svelte** recipes
|
|
13
13
|
([availability](#availability)). A drop-in replacement for
|
|
14
14
|
[`jest-auto-spies`](https://www.npmjs.com/package/jest-auto-spies) — same API, and roughly 1.5x
|
|
@@ -23,7 +23,7 @@ faster at suite scale ([benchmarks](#benchmarks)) — and for
|
|
|
23
23
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
24
24
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
25
25
|
[](https://github.com/ASDAlexey/vitest-auto-spy/actions/workflows/ci.yml)
|
|
26
|
-
[](#install)
|
|
27
27
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
28
28
|
[](https://github.com/ASDAlexey/vitest-auto-spy/actions/workflows/ci.yml)
|
|
29
29
|
[](./LICENSE)
|
|
@@ -76,7 +76,7 @@ faster at suite scale ([benchmarks](#benchmarks)) — and for
|
|
|
76
76
|
- 🧩 Module mocks that prove they applied — `assertMocked`, `moduleNamespace`, for a `vi.mock()` a bundler quietly ignored
|
|
77
77
|
- 🧾 Fixtures without casts — deep-partial `createMock`, `createFixture` / `createFixtureFactory`, `narrow()`, `withOverrides()`, `asInstances()`, `captureArg()`
|
|
78
78
|
- 🚚 A migration you can verify — `vitest-auto-spy/diagnostics`: `compareTestRuns` on the two JSON reports, `summarizeTestRun` / `formatTestRunComparison` to read the answer, `diffByField` for the assertion the reporter collapses, `explainSpy` for a double that answered something you did not configure
|
|
79
|
-
- 📏 Lint rules and one-line test-run hygiene — twenty rules in `vitest-auto-spy/eslint-plugin` (three `--fix`, eight suggestions, four of them for a suite mid-migration off jasmine), `setupAutoSpy()`
|
|
79
|
+
- 📏 Lint rules and one-line test-run hygiene — twenty-three rules in `vitest-auto-spy/eslint-plugin` (three `--fix`, eight suggestions, four of them for a suite mid-migration off jasmine), `setupAutoSpy()`
|
|
80
80
|
- 🩺 [Editor diagnostics](#editor-diagnostics--webstorm--vs-code) — the same anti-patterns underlined while you type: native ESLint inspections in **WebStorm** and the other JetBrains IDEs, the ESLint extension in **VS Code**, no extra plugin either way
|
|
81
81
|
- 🔎 [`npx vitest-auto-spy doctor`](#the-cli--doctor-perf-codemod-and-init) — suite-level defects **that never fail a run**: a `tsconfig` `include` matching no file, a production module importing a spec, a `@jest-environment` pragma the runner never reads, config left behind for a runner that is gone. Read-only, no config, exits 1 in CI
|
|
82
82
|
- ⏱️ [`npx vitest-auto-spy perf`](#perf--where-the-cpu-time-actually-goes) — where a suite's CPU time actually goes, phase by phase, and which spec files to act on: the ones that reach no DOM and could run under `node`, the ones that import a barrel. Runs Vitest once with a reporter this package ships, reads `TestModule.diagnostic()`, names files, states the rule behind each finding
|
|
@@ -719,7 +719,7 @@ the time. It works in any client that _is_ Claude Code — the z.ai and Kimi set
|
|
|
719
719
|
|
|
720
720
|
## Availability
|
|
721
721
|
|
|
722
|
-
> **All entry points are published.** The **Vitest / Bun / `node:test
|
|
722
|
+
> **All entry points are published.** The **Vitest / Bun / `node:test` / Rstest** runtimes, the **RxJS** layer,
|
|
723
723
|
> and the **Angular / NestJS / React / Vue·Pinia / Svelte** recipes all ship as importable entry points —
|
|
724
724
|
> one identical API across every runner and framework.
|
|
725
725
|
|
|
@@ -727,6 +727,7 @@ the time. It works in any client that _is_ Claude Code — the z.ai and Kimi set
|
|
|
727
727
|
| ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
728
728
|
| `vitest-auto-spy` · `vitest-auto-spy/rxjs` · `vitest-auto-spy/angular` | ✅ **Published** |
|
|
729
729
|
| `vitest-auto-spy/bun` · `vitest-auto-spy/bun-angular` · `vitest-auto-spy/node` | ✅ **Published** |
|
|
730
|
+
| `vitest-auto-spy/rstest` | ✅ **Published** |
|
|
730
731
|
| `vitest-auto-spy/nestjs` · `/react` · `/vue` · `/svelte` · `/console` | `provideAutoSpy`, `injectSpy` for `Test.createTestingModule`; `createNestUnit` builds the unit from its DI metadata with every unprovided token auto-spied, `expose` for sociable collaborators |
|
|
731
732
|
| `vitest-auto-spy/setup` · `vitest-auto-spy/zone` · `vitest-auto-spy/eslint-plugin` | ✅ **Published** |
|
|
732
733
|
| `vitest-auto-spy/jasmine` · `/jasmine-compat` · `/observer-spy` | ✅ **Published** |
|
|
@@ -1154,6 +1155,7 @@ Node / Bun / React / Vue project pulls **neither rxjs nor Angular into its runti
|
|
|
1154
1155
|
| `vitest-auto-spy/bun` | the same core, driven by Bun's `bun:test` mocks | `bun:test` | ✅ |
|
|
1155
1156
|
| `vitest-auto-spy/bun-angular` | Angular's `TestBed` under `bun test` — DOM, JIT `templateUrl` resolution and a zoneless environment, from one preload | `bun:test`, `@angular/core`, `@angular/platform-browser` | ✅ |
|
|
1156
1157
|
| `vitest-auto-spy/node` | the same core, driven by `node:test`'s `mock.fn()`, plus `trackNodeMocks()` — a private `MockTracker` so dropped spies are actually freed | `node:test` | ✅ |
|
|
1158
|
+
| `vitest-auto-spy/rstest` | the same core, driven by Rstest's `rstest.fn()` / `rstest.spyOn()` | `@rstest/core` | ✅ |
|
|
1157
1159
|
| `vitest-auto-spy/nestjs` | `provideAutoSpy`, `injectSpy` for `Test.createTestingModule` | — (your `@nestjs/*`) | ✅ |
|
|
1158
1160
|
| `vitest-auto-spy/react` | the core, with a natural import for React Testing Library suites | — (your `react`) | ✅ |
|
|
1159
1161
|
| `vitest-auto-spy/vue` | `provideAutoSpy` for `global.provide` + Pinia store spying | — (your `vue`/`pinia`) | ✅ |
|
|
@@ -1202,18 +1204,19 @@ import 'vitest-auto-spy/rxjs';
|
|
|
1202
1204
|
|
|
1203
1205
|
The core is runner-agnostic behind a `MockAdapter`: pick the entry that matches your test
|
|
1204
1206
|
runner — the public API (`createSpyFromClass`, `calledWith`, `resolveWith`, `nextWith`, …) is
|
|
1205
|
-
identical across all
|
|
1207
|
+
identical across all four.
|
|
1206
1208
|
|
|
1207
1209
|
```ts
|
|
1208
1210
|
import { createSpyFromClass } from 'vitest-auto-spy'; // Vitest (default, zero-config)
|
|
1209
1211
|
import { createSpyFromClass } from 'vitest-auto-spy/bun'; // Bun — bun:test
|
|
1210
1212
|
import { createSpyFromClass } from 'vitest-auto-spy/node'; // node:test
|
|
1213
|
+
import { createSpyFromClass } from 'vitest-auto-spy/rstest'; // Rstest
|
|
1211
1214
|
```
|
|
1212
1215
|
|
|
1213
1216
|
Angular's `TestBed` runs on Bun too — see [Angular on Bun](#angular-on-bun-buntest) below.
|
|
1214
1217
|
|
|
1215
1218
|
> Only the auto-spy helpers are normalised across runtimes; **native** mock methods stay the
|
|
1216
|
-
> runner's own — `mockReturnValue` on Vitest/Bun, `spy.method.mock.mockImplementation` on
|
|
1219
|
+
> runner's own — `mockReturnValue` on Vitest/Bun/Rstest, `spy.method.mock.mockImplementation` on
|
|
1217
1220
|
> `node:test`. Each entry registers its adapter on import, so import the one matching your runner.
|
|
1218
1221
|
|
|
1219
1222
|
> Using an observable spy (`observablePropsToSpyOn`, `nextWith`, …) without importing
|
|
@@ -1659,6 +1662,27 @@ createSpyFromClass(MyService, {
|
|
|
1659
1662
|
});
|
|
1660
1663
|
```
|
|
1661
1664
|
|
|
1665
|
+
### The composition belongs to the class — `registerAutoSpyDefaults`
|
|
1666
|
+
|
|
1667
|
+
A spy's composition is a fact about the class rather than about the spec: `Router` needs `events`
|
|
1668
|
+
spied as an Observable property and `url` as a getter wherever it is doubled. Register it once and
|
|
1669
|
+
every call site starts from it.
|
|
1670
|
+
|
|
1671
|
+
```ts
|
|
1672
|
+
// vitest-setup.ts, once
|
|
1673
|
+
registerAutoSpyDefaults(Router, { observablePropsToSpyOn: ['events'], gettersToSpyOn: ['url'] });
|
|
1674
|
+
|
|
1675
|
+
// every spec, from then on
|
|
1676
|
+
provideAutoSpy(Router);
|
|
1677
|
+
provideAutoSpy(Router, { instanceMethodsToSpyOn: ['currentNavigation'] }); // adds, does not replace
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
The call site is **merged** into the registration rather than replacing it: lists unioned,
|
|
1681
|
+
`returns` / `overrides` merged key by key, scalars decided by the call site when it names the key.
|
|
1682
|
+
Registration is by class identity — a subclass inherits nothing — and a second registration for one
|
|
1683
|
+
class replaces the first, because two of them in one suite is the drift this removes.
|
|
1684
|
+
`clearAutoSpyDefaults(Class)` drops one, `clearAutoSpyDefaults()` the lot.
|
|
1685
|
+
|
|
1662
1686
|
### Spying instance-assigned callables (`signal()`, arrow props, `signalStore()`)
|
|
1663
1687
|
|
|
1664
1688
|
`createSpyFromClass` discovers methods by walking the **prototype**, so a callable assigned on the
|
|
@@ -2831,6 +2855,7 @@ not a function` on Node 25, `undefined` on Node 26, under jsdom and happy-dom al
|
|
|
2831
2855
|
| --------------------- | --------- | ------------------------------------------------------------------------------------- |
|
|
2832
2856
|
| `duplicateCopies` | `'throw'` | `'warn'` to report without failing, `'off'` to skip the check |
|
|
2833
2857
|
| `restoreProps` | `true` | `restoreMockedProps()` in a global `afterEach` |
|
|
2858
|
+
| `propsOutsideHooks` | `'warn'` | Name a `mock*Prop` patch made in a `describe` body or `beforeAll` — it survives one test; `'throw'`, `'off'`. `reportPropsOutsideHooks(reaction)` sets the same dial without the setup helper |
|
|
2834
2859
|
| `restoreMocks` | `false` | `vi.restoreAllMocks()` in a global `afterEach` — turn on for `isolate: false` |
|
|
2835
2860
|
| `strayTimers` | `false` | Cancel timeouts, intervals and frames that outlive their file |
|
|
2836
2861
|
| `onStrayTimers` | — | Takes the per-file count the sweep cancelled — see the note on `--detect-async-leaks` |
|
|
@@ -3017,6 +3042,11 @@ export default [
|
|
|
3017
3042
|
];
|
|
3018
3043
|
```
|
|
3019
3044
|
|
|
3045
|
+
A second config, `autoSpy.configs.typeErrors`, holds the subset whose findings are compile errors
|
|
3046
|
+
(`prefer-as-spy` is `TS2352`, `no-mocked-for-spy` is `TS2322`). Spread it **after** a blanket
|
|
3047
|
+
downgrade so those keep their severity — the recipe is a spread rather than rule names copied into
|
|
3048
|
+
your config, where they would go stale silently.
|
|
3049
|
+
|
|
3020
3050
|
The full dial — landing it on a large existing suite without a red CI, the three rules that can
|
|
3021
3051
|
report on correct code, and `setupModules` — is on the docs site:
|
|
3022
3052
|
[ESLint plugin → Tuning it for your project](https://asdalexey.github.io/vitest-auto-spy/utilities/eslint-plugin#tuning-it-for-your-project).
|
|
@@ -3040,10 +3070,13 @@ export can never be.
|
|
|
3040
3070
|
| `no-floating-assertion` | `error` | — | `expect()` in a `.then()` nobody awaits → `expect(await promise)` |
|
|
3041
3071
|
| `no-bare-called-with` | `error` | — | `spy.m.calledWith(1);` as a statement of its own — a stub nobody continued, asserting nothing |
|
|
3042
3072
|
| `no-overridden-provider` | `error` | suggest | two providers for one token in one array → the earlier one never runs; the exact duplicate can be deleted |
|
|
3043
|
-
| `no-inject-before-override` | `error` | — | `TestBed.inject()` in a hook, in a suite that still calls `override*` |
|
|
3073
|
+
| `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
|
|
3074
|
+
| `no-private-member-access` | `error` | — | `instance['privateMember']`, `(instance as any).privateMember` and `vi.spyOn(Object.getPrototypeOf(x), 'm')` — the three spellings that get past `private`; **type-aware**, and silent without `parserOptions.project` |
|
|
3075
|
+
| `no-dead-schemas` | `error` | — | `schemas` on a testing module that declares nothing — a charm protecting nobody, and one that starts working the day `declarations` arrive |
|
|
3044
3076
|
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError` while the bundle loads |
|
|
3045
3077
|
| `no-unregistered-inject-spy` | `error` | — | `injectSpy(X)` for a token this file never registered → the real instance, whose spy helpers exist only for the compiler |
|
|
3046
3078
|
| `prefer-render-shallow` | `error` | suggest | `TestBed.createComponent` in a file that never reads the template → `renderShallow(X)`; 0.24× the per-test cycle at 100 children |
|
|
3079
|
+
| `prefer-observer-stub` | `error` | — | a hand-rolled `IntersectionObserver` / `ResizeObserver` / `MutationObserver` written into a global → `stubIntersectionObserver()` and friends, whose undo `restoreMockedProps()` already runs |
|
|
3047
3080
|
| `jasmine-namespace-without-entry` | `error` | — | `.and` / `.calls` / `.withArgs` on a library spy in a file that installs the compatibility layer nowhere |
|
|
3048
3081
|
| `no-jasmine-globals` | `error` | — | `jasmine.*`, `spyOn(` / `spyOnProperty(` / `spyOnAllFunctions(` / `fail(` / `pending(`, `.withContext(` — none of them exist under Vitest |
|
|
3049
3082
|
| `no-save-arguments-by-value` | `error` | — | `spy.calls.saveArgumentsByValue()`, which is a no-op here → take the copy at call time |
|
|
@@ -3053,7 +3086,7 @@ Every message ends with a link to the matching [recipe](#how-to-mock): a rule th
|
|
|
3053
3086
|
"don't" moves the problem rather than solving it. Rules travel with the API they recommend, so they
|
|
3054
3087
|
are versioned together and stop being re-written in every project that installs the package.
|
|
3055
3088
|
|
|
3056
|
-
**Three of the twenty fix on their own, eight offer suggestions**, and the split is not about how hard
|
|
3089
|
+
**Three of the twenty-three fix on their own, eight offer suggestions**, and the split is not about how hard
|
|
3057
3090
|
the rewrite is. `no-mocked-for-spy` touches a _declaration_: get it wrong and the file stops
|
|
3058
3091
|
compiling, which is the loudest, cheapest failure there is — so `--fix` rewrites the type, adds
|
|
3059
3092
|
`import type { Spy } from 'vitest-auto-spy'` and drops the `Mocked` import once nothing else uses
|
|
@@ -3157,7 +3190,7 @@ package's own — it needs its ESLint integration switched on.
|
|
|
3157
3190
|
### WebStorm and the other JetBrains IDEs
|
|
3158
3191
|
|
|
3159
3192
|
No plugin to install: WebStorm, IntelliJ IDEA Ultimate, PhpStorm, PyCharm Professional and RubyMine
|
|
3160
|
-
all run ESLint natively, so the twenty rules appear inline, in the **Problems** tool window, and
|
|
3193
|
+
all run ESLint natively, so the twenty-three rules appear inline, in the **Problems** tool window, and
|
|
3161
3194
|
under **Code → Inspect Code** for the whole project.
|
|
3162
3195
|
|
|
3163
3196
|
```js
|
|
@@ -3174,7 +3207,7 @@ has supported flat config since 2023.3); scope the block to spec files yourself;
|
|
|
3174
3207
|
the fixes and suggestions live.
|
|
3175
3208
|
|
|
3176
3209
|
A native JetBrains plugin is **not** planned — it would duplicate an integration the IDE already has
|
|
3177
|
-
and then keep a second copy of twenty rules, in Kotlin, in step with the TypeScript ones.
|
|
3210
|
+
and then keep a second copy of twenty-three rules, in Kotlin, in step with the TypeScript ones.
|
|
3178
3211
|
|
|
3179
3212
|
### VS Code, Cursor, Windsurf, VSCodium
|
|
3180
3213
|
|
|
@@ -3218,6 +3251,7 @@ names are unfindable from these messages otherwise — no `TS2739` text contains
|
|
|
3218
3251
|
| `TS2322: Type 'Spy<X>' is not assignable to type 'Mocked<X>' …` | the variable was declared `Mocked<T>` | declare it `Spy<T>` |
|
|
3219
3252
|
| `'AddPromiseSpyMethods<unknown>' is missing … from type 'WithMockReturnValue<…>'` | a generic class inferred as `Service<any>` | `asSpy<Service>(…)` / `injectSpy<Service>(…)` |
|
|
3220
3253
|
| `TS2345` / `TS2554` **on a call to a spied method** (wrong arguments) | the arguments the real method rejects — the double's call signature is the method's own; it used to accept anything | fix the call; don't re-widen the spy |
|
|
3254
|
+
| `TS2345` **inside `mockReturnValue` / `mockImplementation` / `mockResolvedValue`** | the stub is not what the method returns — the mock surface is `MockInstance<Method>`, so it is checked | fix the stub; a deliberate mismatch is a type bug |
|
|
3221
3255
|
| `TS2739 … 'Spy<X>' is missing …` **on a line with `injectSpy`** | the provider handed back the real object | `provideAutoSpy(X)`, or an honest `TestBed.inject` |
|
|
3222
3256
|
|
|
3223
3257
|
Two notes that cost real time when they are missing.
|
|
@@ -3264,9 +3298,10 @@ another, and the next one is in that same file.
|
|
|
3264
3298
|
| `mockSystemTime` / `withSystemTime` / `mockNow` / `useCountingClock` _(`/setup`)_ | Clock control that survives fake timers being re-installed per test |
|
|
3265
3299
|
| `registerFocusMatchers()` _(`/setup`)_ | Adds `expect(el).toHaveFocus()` |
|
|
3266
3300
|
| `overrideAutoSpy` / `overrideComponentProvider` / `assertNgModuleScopes` / `assertComponentDefIntact` _(Angular)_ | Override a component-level provider — and verify on the next fixture that the override applied; diagnose an NgModule with an empty runtime scope |
|
|
3267
|
-
| `enableAngularDiagnostics(opts?)` / `disableAngularDiagnostics()` / `assertNoPendingRequests()` _(Angular)_
|
|
3301
|
+
| `enableAngularDiagnostics(opts?)` / `disableAngularDiagnostics()` / `assertNoPendingRequests()` / `assertNoShadowedProviders()` _(Angular)_ | `ngModuleScopes`, `deadSchemas`, `unspiedProviders`, `shadowedProviders` and `pendingRequests`: a dead NgModule import, `schemas` that can never apply, an unspied provider, a double the component's own `providers` shadow, and unflushed HTTP requests — each as a failure |
|
|
3268
3302
|
| `trackInjections(tokens, opts?)` _(Angular, NestJS)_ | Providers that record which collaborators DI constructed, with an auto-spy behind each token |
|
|
3269
3303
|
| `setupAutoSpy(opts?)` _(`/setup`)_ | Property restore + duplicate-copy detection + mock-registry hygiene, in one call |
|
|
3304
|
+
| `registerAutoSpyDefaults(Class, config)` / `clearAutoSpyDefaults(Class?)` | A class's spy composition registered once, merged into every `createSpyFromClass(X)` / `provideAutoSpy(X)` from then on |
|
|
3270
3305
|
| `setupFakeTimers(config?)` / `advanceTimers(ms?)` _(`/setup`)_ | Paired fake-timer install/restore, and an advance that also settles queued microtasks |
|
|
3271
3306
|
| `describeDuplicateCopies()` / `getPackageCopies()` | The duplicate-install report, and the copies behind it |
|
|
3272
3307
|
| `renderShallow(Component, opts?)` _(Angular)_ | `TestBed` component, minus its children and (by default) its template |
|
package/dist/angular.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { l as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, S as SettleResourceOptions, d as ShallowRender, e as SpyRegistry, f as StableOptions, g as createWithAutoSpies, h as flushEffects, i as injectSpy, p as provideAutoSpy, m as provideAutoSpyForToken, r as renderShallow, j as runEffect, s as settleResource, k as stable } from './zoneless-
|
|
1
|
+
export { l as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, S as SettleResourceOptions, d as ShallowRender, e as SpyRegistry, f as StableOptions, g as createWithAutoSpies, h as flushEffects, i as injectSpy, p as provideAutoSpy, m as provideAutoSpyForToken, r as renderShallow, j as runEffect, s as settleResource, k as stable } from './zoneless-BerZbxtu.js';
|
|
2
2
|
import { InjectionToken, Provider, Type, Signal, WritableSignal } from '@angular/core';
|
|
3
3
|
import { TestAPI } from 'vitest';
|
|
4
|
-
import { C as ClassType, S as Spy, k as ClassSpyConfiguration, o as OnlyMethodKeysOf, g as AddSpyMethodsByReturnTypes } from './types-
|
|
5
|
-
export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-
|
|
6
|
-
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp,
|
|
7
|
-
export { C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
4
|
+
import { C as ClassType, S as Spy, k as ClassSpyConfiguration, o as OnlyMethodKeysOf, g as AddSpyMethodsByReturnTypes } from './types-DTi4dIeN.js';
|
|
5
|
+
export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-D4TuS8yk.js';
|
|
6
|
+
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, e as restoreMockedProps } from './prop-mock-DmM-rPcG.js';
|
|
7
|
+
export { C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-DYtyyKM5.js';
|
|
8
8
|
import '@angular/core/testing';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -245,6 +245,11 @@ interface AngularDiagnosticsOptions {
|
|
|
245
245
|
unspiedProviders?: boolean;
|
|
246
246
|
/** Fail a test that ends with unflushed `HttpTestingController` requests. */
|
|
247
247
|
pendingRequests?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Fail when a double registered on the testing module loses to the component's own `providers`,
|
|
250
|
+
* so the component under test is running against the real service.
|
|
251
|
+
*/
|
|
252
|
+
shadowedProviders?: boolean;
|
|
248
253
|
}
|
|
249
254
|
/**
|
|
250
255
|
* Fail when the `HttpTestingController` this test configured is still holding requests.
|
|
@@ -263,6 +268,23 @@ interface AngularDiagnosticsOptions {
|
|
|
263
268
|
* ```
|
|
264
269
|
*/
|
|
265
270
|
declare function assertNoPendingRequests(): void;
|
|
271
|
+
/**
|
|
272
|
+
* Fail when a double this test registered on the testing module never reached `component`.
|
|
273
|
+
*
|
|
274
|
+
* `shadowedProviders` calls this on every fixture; it is exported for the same reason
|
|
275
|
+
* {@link assertNoPendingRequests} is — a spec that builds its component through a helper of its own
|
|
276
|
+
* can ask directly, and a check that can only be reached through one code path is a check that
|
|
277
|
+
* stops running the day that path changes.
|
|
278
|
+
*
|
|
279
|
+
* A no-op when the fixture never rendered `component`, and when everything it resolved is a double.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* const fixture = renderThroughOurHelper(CartComponent);
|
|
284
|
+
* assertNoShadowedProviders(CartComponent, fixture); // the doubles really are the ones in play
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
declare function assertNoShadowedProviders(component: unknown, fixture: unknown): void;
|
|
266
288
|
/**
|
|
267
289
|
* Turn the group on. Every member defaults to `true`; pass `false` to leave one out.
|
|
268
290
|
*
|
|
@@ -709,4 +731,4 @@ declare function reportSpecTiming(timing: SpecTiming): void;
|
|
|
709
731
|
*/
|
|
710
732
|
declare function enableTestBedDiagnostics(options?: TestBedDiagnosticsOptions): void;
|
|
711
733
|
|
|
712
|
-
export { type AngularDiagnosticsOptions, type AngularTestEnvMode, type AngularTestEnvOptions, type AutoSpyFixture, type AutoSpyOverride, type DirectiveHostOptions, type ExtendWithAutoSpiesOptions, type MockedResource, type ResourceDouble, type ResourceDoubleStatus, type ResourceLike, type SignalLike, type SpecTiming, type SpiedFixtures, type TestBedDiagnosticsOptions, assertComponentDefIntact, assertNgModuleScopes, assertNoPendingRequests, createDirectiveHost, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, extendWithAutoSpies, formatSpecTiming, getTestBedTiming, instrumentTestBed, mockResourceProp, mockSignalProp, overrideAutoSpy, overrideComponentProvider, registerDirectiveMatchers, registerResourceMatchers, registerSignalMatchers, reportSpecTiming, setupAngularTestEnv };
|
|
734
|
+
export { type AngularDiagnosticsOptions, type AngularTestEnvMode, type AngularTestEnvOptions, type AutoSpyFixture, type AutoSpyOverride, type DirectiveHostOptions, type ExtendWithAutoSpiesOptions, type MockedResource, type ResourceDouble, type ResourceDoubleStatus, type ResourceLike, type SignalLike, type SpecTiming, type SpiedFixtures, type TestBedDiagnosticsOptions, assertComponentDefIntact, assertNgModuleScopes, assertNoPendingRequests, assertNoShadowedProviders, createDirectiveHost, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, extendWithAutoSpies, formatSpecTiming, getTestBedTiming, instrumentTestBed, mockResourceProp, mockSignalProp, overrideAutoSpy, overrideComponentProvider, registerDirectiveMatchers, registerResourceMatchers, registerSignalMatchers, reportSpecTiming, setupAngularTestEnv };
|