vitest-auto-spy 5.23.0 → 5.24.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 (40) hide show
  1. package/AGENTS.md +14 -12
  2. package/README.md +10 -10
  3. package/dist/angular-diagnostics.d.ts +16 -4
  4. package/dist/angular-diagnostics.js +16 -10
  5. package/dist/angular-doubles.d.ts +1 -1
  6. package/dist/angular-http.js +2 -2
  7. package/dist/angular-router.d.ts +4 -4
  8. package/dist/angular-router.js +27 -4
  9. package/dist/angular.d.ts +6 -6
  10. package/dist/angular.js +29 -27
  11. package/dist/bun-angular.d.ts +5 -5
  12. package/dist/bun-angular.js +1 -1
  13. package/dist/bun.d.ts +5 -5
  14. package/dist/chunk-6UETTNQH.js +16 -0
  15. package/dist/{chunk-KOR5OK4H.js → chunk-RGRZDCM6.js} +30 -2
  16. package/dist/cli.js +2 -1
  17. package/dist/console.d.ts +1 -1
  18. package/dist/dom-stubs.d.ts +1 -1
  19. package/dist/eslint-plugin.cjs +194 -57
  20. package/dist/eslint-plugin.d.ts +2 -0
  21. package/dist/{expect-emission-S5asJaJP.d.ts → expect-emission-CD6thEE8.d.ts} +1 -1
  22. package/dist/index.d.ts +4 -4
  23. package/dist/jasmine-compat.d.ts +1 -1
  24. package/dist/jasmine.d.ts +2 -2
  25. package/dist/nestjs.d.ts +2 -2
  26. package/dist/node.d.ts +4 -4
  27. package/dist/{package-identity-Cn7yncmJ.d.ts → package-identity-CqrrGVDm.d.ts} +1 -1
  28. package/dist/{prop-mock-C--a8rpU.d.ts → prop-mock-yHR11U7R.d.ts} +1 -1
  29. package/dist/react.d.ts +4 -4
  30. package/dist/rstest.d.ts +4 -4
  31. package/dist/rxjs.d.ts +2 -2
  32. package/dist/setup.d.ts +3 -3
  33. package/dist/svelte.d.ts +4 -4
  34. package/dist/{track-injections-Dig5t28T.d.ts → track-injections-L6IgAUL7.d.ts} +1 -1
  35. package/dist/{track-signal-runs-BSVObkds.d.ts → track-signal-runs-DsBgqliM.d.ts} +3 -3
  36. package/dist/{types-BM3BcWj1.d.ts → types-BuQtoidb.d.ts} +5 -1
  37. package/dist/vue.d.ts +5 -5
  38. package/package.json +1 -1
  39. package/skills/vitest-auto-spy/SKILL.md +1 -1
  40. package/dist/chunk-WYYKUPXW.js +0 -44
package/AGENTS.md CHANGED
@@ -2668,21 +2668,21 @@ replace a stack inside `@angular/core` with a line naming what is missing.
2668
2668
  // afterEach hooks in reverse registration order and this one must run before the teardown.
2669
2669
  import { enableAngularDiagnostics } from 'vitest-auto-spy/angular/diagnostics';
2670
2670
 
2671
- enableAngularDiagnostics(); // { ngModuleScopes, deadSchemas, unspiedProviders, pendingRequests }
2671
+ enableAngularDiagnostics(); // { ngModuleScopes, deadSchemas, unspiedProviders, pendingRequests, shadowedProviders }
2672
2672
  ```
2673
2673
 
2674
- | Member | Fails when |
2675
- | ------------------- | -------------------------------------------------------------------------------- |
2676
- | `ngModuleScopes` | a testing module imports an NgModule that contributes nothing at runtime |
2677
- | `deadSchemas` | `schemas` sit next to a standalone component (`declarations` empty) — a no-op |
2678
- | `unspiedProviders` | `injectSpy` got a real instance; a `console.warn` alone, a throw under the group |
2679
- | `pendingRequests` | the test ended with unflushed `HttpTestingController` requests, named one by one |
2680
- | `shadowedProviders` | a double on the testing module loses to the component's own `providers` |
2674
+ | Member | Fails when |
2675
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2676
+ | `ngModuleScopes` | a testing module imports an NgModule that contributes nothing at runtime |
2677
+ | `deadSchemas` | `schemas` sit next to a standalone component (`declarations` empty) — a no-op |
2678
+ | `unspiedProviders` | `injectSpy` got a real instance; a `console.warn` alone, a throw under the group |
2679
+ | `pendingRequests` | the test ended with unflushed `HttpTestingController` requests, named one by one; `{ ignoreCancelled: true }` forgives the ones the code under test cancelled |
2680
+ | `shadowedProviders` | a double on the testing module loses to the component's own `providers` |
2681
2681
 
2682
2682
  Every member defaults to `true`, takes `false` to opt out, and a second call **replaces** the
2683
2683
  selection (safe from anywhere, including inside a test). `disableAngularDiagnostics()` turns the
2684
2684
  group off and leaves the TestBed timing instrumentation alone. `assertNoShadowedProviders(Component, fixture)`
2685
- and `assertNoPendingRequests()` are the same checks on their own, for a spec that renders through a
2685
+ and `assertNoPendingRequests({ ignoreCancelled }?)` are the same checks on their own, for a spec that renders through a
2686
2686
  helper of its own or wants the HTTP one mid-test — reading takes the requests, so the group will not
2687
2687
  re-report what you inspected.
2688
2688
 
@@ -2896,7 +2896,9 @@ router: one provider call, an `injectLocationDouble()` whose errors name the ins
2896
2896
  (`Location` is `providedIn: 'root'`, so the quiet failure is the real `Location` nobody configured).
2897
2897
  `createLocationDouble()` is the same without a `TestBed`. One asymmetry worth knowing: `back()` and
2898
2898
  `forward()` wake the popstate subscribers but do not write `urlChanges` — the journal holds what the
2899
- app asked for, the subscribers carry what the browser did.
2899
+ app asked for, the subscribers carry what the browser did. And one deliberate difference from
2900
+ Angular's `SpyLocation`: `path()` keeps the query of `go(path, query)` / `replaceState(path, query)`
2901
+ (`/reports?tab=7`), as the real `Location.path()` does — `SpyLocation`'s own drops it.
2900
2902
 
2901
2903
  ### Signal forms — `vitest-auto-spy/signal-forms`
2902
2904
 
@@ -3692,7 +3694,7 @@ blanket downgrade so those keep their severity; do not copy the two names into a
3692
3694
  | `no-overridden-provider` | `error` | suggest | two providers for one token in one array, or one a `TestBed.overrideProvider` in the same hook replaces → the earlier one never runs; the exact duplicate can be deleted |
3693
3695
  | `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
3694
3696
  | `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 |
3695
- | `no-reflect-member-access` | `error` | suggest | `Reflect.get(component, 'privateField')` / `Reflect.set(service, 'x', v)` on a subject the test holds — the second door out of `no-private-member-access`, and the one no compiler stands in: the key is an ordinary string argument, so a rename leaves the spec reading a property that is no longer there and `Reflect.set` writing a dead one nothing reads. `window` / `globalThis` and a computed key are never reported; a write onto a double this library built is reported apart and suggests `mockValueProp` |
3697
+ | `no-reflect-member-access` | `error` | on a double | `Reflect.get(component, 'privateField')` / `Reflect.set(service, 'x', v)` on a subject the test holds — the second door out of `no-private-member-access`, and the one no compiler stands in: the key is an ordinary string argument, so a rename leaves the spec reading a property that is no longer there and `Reflect.set` writing a dead one nothing reads. `window` / `globalThis` (or a name declared as `Window` / `typeof globalThis`) and a computed key are never reported; a write onto a double this library built is reported apart and suggests `mockValueProp` |
3696
3698
  | `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 |
3697
3699
  | `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError`, or a silently empty object, while the bundle loads |
3698
3700
  | `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 |
@@ -3716,7 +3718,7 @@ blanket downgrade so those keep their severity; do not copy the two names into a
3716
3718
  | `prefer-settle-dynamic-import` | `error` | suggest | `await import('./thing')` and `import('./thing').then(…)` inside an `it` / `test` body or a `beforeEach` / `beforeAll` / `afterEach` / `afterAll` hook (the `.only`, `.skip` and `.each` spellings included) → `await settleDynamicImport(() => import('./thing'))`, which is the same load plus `flushEventLoop(1)` and returns the namespace, so the destructured form keeps reading the same way. The bare `await` waits for the **module** and not for the continuation of the code that was loading it, so the assertion runs a turn early and the test is green only while that continuation is short. Syntax only. Silent wherever a function of its own sits between the runner's callback and the import — a `vi.mock` factory, a lazy route's `loadComponent` / `loadChildren`, a callback handed to production code, `settleDynamicImport`'s own `() => import(…)` — and, by the same reading, silent on a spec-local `const load = async () => { await import('…') }`, which is written identically whether the spec calls it or the code under test does |
3717
3719
  | `prefer-create-mock` | `warn` | suggest | an object literal under `as SomeType` — `{ id: '1', isOffline: false } as Device`, `<Device>{ … }` too → `createMock<Device>({ … })`. A cast asks whether the two types overlap rather than whether the value is one of them, so it passes a key the type does not declare (the excess-property check is skipped) **and** a required field the fixture never sets; both type gates stay silent, and the same object is then spread into the expected payload of a call assertion. Where the literal already sits in a typed slot the first repair is to delete the cast. Silent on `as const`, `as unknown` / `as any` and the double cast built from them, on a cast of anything but a literal, and on a literal inside one of this library's own factories. `warn`, because accepting the suggestion makes a drifted fixture red on the next type-check — the finding, and a migration taken file by file |
3718
3720
  | `no-mock-cast` | `error` | suggest | a cast to Vitest's `Mock` / `MockInstance` over a **member access** — `TestBed.inject(S).m as Mock` → `injectSpy(S).m`, which the suggestion writes whenever the token is in view (directly, or through a `const` the file settled with a `TestBed.inject`). `Mock` with no parameters is `Mock<any>`: `mockReturnValue` takes anything and `toHaveBeenCalledWith` stops comparing arguments. `(spy.m.mockReturnValue as Mock)(…)` gets its own message — the cast is on the member that installs the answer, so neither the value nor the method's return type is checked. The name must resolve to an import from `vitest` / `@rstest/core` / `bun:test` / `jest`, or to nothing at all, so a domain `Mock` is left alone |
3719
- | `no-redundant-mock-reset` | `error` | `--fix` / suggest | a mock reset in a `beforeEach` / `afterEach` / `beforeAll` / `afterAll` — `vi.clearAllMocks()` / `resetAllMocks()` / `restoreAllMocks()`, `x.mockClear()` / `mockReset()` / `mockRestore()` — the runner already performs between tests → delete it, and the hook with it where that is all it held. **Silent** until the flags are known: options `{ clearMocks, restoreMocks, mockReset }` first, then a `vitest.config.*` / `vite.config.*` searched upwards from the file and read as text. Flag matches call, never family — `restoreMocks` walks only the spies `vi.spyOn` installed. `--fix` only as the first statement of the file's only `beforeEach`; a suggestion otherwise; never inside a test body |
3721
+ | `no-redundant-mock-reset` | `error` | `--fix` / suggest | a mock reset the runner already performs between tests — `vi.clearAllMocks()` / `resetAllMocks()` / `restoreAllMocks()`, `x.mockClear()` / `mockReset()` / `mockRestore()` — standing where nothing the file wrote ran since the runner's own: the first statement of a `beforeEach` no other `beforeEach` precedes, or a clear as the last statement of an `afterEach` → delete it, and the hook with it where that is all it held. A restore or reset in `afterEach` / `afterAll` is never reported: after the last test it is what takes a spy off before the `afterAll` hooks. **Silent** until the flags are known: options `{ clearMocks, restoreMocks, mockReset }` (or `{ configFile }` naming the runner config) first, then a `vitest.config.*` / `vite.config.*` searched upwards from the file and read as text. Flag matches call, never family — `restoreMocks` walks only the spies `vi.spyOn` installed. `--fix` only in a file whose only before-hook it is; a suggestion otherwise; never inside a test body |
3720
3722
  | `no-unasserted-argument` | `warn` | — | a bare `expect(spy).toHaveBeenCalled()` on evidence from the file: the same subject asserted with `toHaveBeenCalledWith(…)` in another test, or a title containing `with` over a body whose every assertion is a bare call → `toHaveBeenCalledWith(…)` / `mustBeCalledWith(…)`. `not.toHaveBeenCalled()` and the counting matchers are never reported |
3721
3723
  | `no-compile-components` | `error` | suggest | `compileComponents()` under a builder that inlines `templateUrl` / `styleUrls` — a promise already settled → delete it, and the `async` of a hook that awaits nothing else. **Silent until** `['error', { builder: 'inline-resources' }]`: under a JIT setup that loads resources at run time the call is load-bearing. **Keep the call for a component whose template holds a `@defer` block** — that ships async class metadata, which `TestBed` resolves in this very call whatever the builder did, and dropping it fails the test with `has unresolved metadata`; the rule cannot see another file's template, so such a call keeps its own `// eslint-disable-next-line vitest-auto-spy/no-compile-components -- @defer: async class metadata` |
3722
3724
  | `no-sync-testbed-await` | `error` | suggest | `await` on a TestBed call that answers the TestBed or a fixture — `configureTestingModule`, `override*`, `resetTestingModule`, `createComponent`, `getLastFixture`, through `TestBed`, `getTestBed()`, a chain of those, or a name holding one → drop the `await`, and the `async` of a hook that then awaits nothing else; the suggestion does both. Reads **no types**, so it reports without `parserOptions.project`, where `@typescript-eslint/await-thenable` cannot. `inject` and `runInInjectionContext` are never reported: each answers whatever the token or the callback holds, which can be a promise |
package/README.md CHANGED
@@ -2858,18 +2858,18 @@ enableAngularDiagnostics(); // all five
2858
2858
  enableAngularDiagnostics({ pendingRequests: false }); // or pick
2859
2859
  ```
2860
2860
 
2861
- | Member | Fails when |
2862
- | ------------------- | ------------------------------------------------------------------------------------------------------ |
2863
- | `ngModuleScopes` | a testing module imports an NgModule that contributes nothing at all at runtime |
2864
- | `deadSchemas` | `schemas` sit next to a standalone component, where they can never apply |
2865
- | `unspiedProviders` | `injectSpy` gets a real instance — a `console.warn` on its own, a throw in the group |
2866
- | `shadowedProviders` | a double on the testing module loses to the component's own `providers` — the test runs the real thing |
2867
- | `pendingRequests` | a test ends with unflushed `HttpTestingController` requests |
2861
+ | Member | Fails when |
2862
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
2863
+ | `ngModuleScopes` | a testing module imports an NgModule that contributes nothing at all at runtime |
2864
+ | `deadSchemas` | `schemas` sit next to a standalone component, where they can never apply |
2865
+ | `unspiedProviders` | `injectSpy` gets a real instance — a `console.warn` on its own, a throw in the group |
2866
+ | `shadowedProviders` | a double on the testing module loses to the component's own `providers` — the test runs the real thing |
2867
+ | `pendingRequests` | a test ends with unflushed `HttpTestingController` requests; `{ ignoreCancelled: true }` forgives the ones the code under test cancelled |
2868
2868
 
2869
2869
  Each has the same shape: something the spec wrote does nothing, nothing says so, and the test passes
2870
2870
  for a reason its author did not intend. Every member defaults to `true`; a second call **replaces**
2871
2871
  the previous selection, and `disableAngularDiagnostics()` turns the group off.
2872
- `assertNoPendingRequests()` is the HTTP check on its own, for use mid-test, and
2872
+ `assertNoPendingRequests(opts?)` is the HTTP check on its own, for use mid-test, and
2873
2873
  `assertNoShadowedProviders(component, fixture)` is the shadow check on its own — a no-op when the
2874
2874
  fixture never rendered that component, and when everything it resolved is a double.
2875
2875
 
@@ -3830,7 +3830,7 @@ export can never be.
3830
3830
  | `no-overridden-provider` | `error` | suggest | two providers for one token in one array → the earlier one never runs; the exact duplicate can be deleted |
3831
3831
  | `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
3832
3832
  | `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` |
3833
- | `no-reflect-member-access` | `error` | suggest | `Reflect.get(component, 'privateField')` / `Reflect.set(service, 'x', v)` on a subject the test holds — the second door out of `no-private-member-access`, and the one no compiler stands in: the key is an ordinary string argument, so a rename leaves the spec reading a property that is no longer there and `Reflect.set` writing a dead one nothing reads. `window` / `globalThis` and a computed key are never reported; a write onto a double this library built is reported apart and suggests `mockValueProp` |
3833
+ | `no-reflect-member-access` | `error` | on a double | `Reflect.get(component, 'privateField')` / `Reflect.set(service, 'x', v)` on a subject the test holds — the second door out of `no-private-member-access`, and the one no compiler stands in: the key is an ordinary string argument, so a rename leaves the spec reading a property that is no longer there and `Reflect.set` writing a dead one nothing reads. `window` / `globalThis` and a computed key are never reported; a write onto a double this library built is reported apart and suggests `mockValueProp` |
3834
3834
  | `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 |
3835
3835
  | `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError`, or a silently empty object, while the bundle loads |
3836
3836
  | `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 |
@@ -3854,7 +3854,7 @@ export can never be.
3854
3854
  | `prefer-settle-dynamic-import` | `error` | suggest | `await import('./thing')` — or `import('./thing').then(…)` — written in a test body or a hook to settle a module the code under test lazy-loads → `await settleDynamicImport(() => import('./thing'))`. Awaiting the specifier waits for the **module**; the handler's own continuation, the lines after _its_ `await`, is still queued behind it, so the assertion reads the state one turn early. The suggestion wraps the `import()` and imports the helper. Reported only where the innermost enclosing function is the runner's own callback, which is what exempts a `vi.mock` factory, a lazy route's `loadComponent` and a callback the spec hands to production code |
3855
3855
  | `prefer-create-mock` | `warn` | suggest | an object literal under `as SomeType` — `{ id: '1', isOffline: false } as Device`, and the `<Device>{ … }` spelling → `createMock<Device>({ … })`, which takes a `DeepPartial<Device>` and answers a `Device`. A cast asks whether the two types overlap, so it passes a key the type does not declare **and** a required field the fixture never sets; both type gates stay silent and the fixture is then spread into an expected payload. Silent on `as const`, on `as unknown` / `as any` and the double cast built from them, on a cast of anything that is not a literal, and on a literal inside one of this library's own factories. `warn`, not `error`: the repair makes a drifted fixture red on the next type-check, which is the finding and also a migration taken file by file |
3856
3856
  | `no-mock-cast` | `error` | suggest | `TestBed.inject(S).m as Mock` — a cast to Vitest's `Mock` / `MockInstance` over a **member access** → `injectSpy(S).m`, which the suggestion writes when the token is in view. `Mock` with no parameters is `Mock<any>`, so `mockReturnValue` takes anything and `toHaveBeenCalledWith` stops comparing arguments; the worse form, `(spy.m.mockReturnValue as Mock)(…)`, gets a message of its own because the cast sits on the member that installs the answer. The name has to resolve to a runner's import, so a domain `Mock` is never reported |
3857
- | `no-redundant-mock-reset` | `error` | `--fix` / suggest | a mock reset **inside a hook** — `vi.clearAllMocks()` / `resetAllMocks()` / `restoreAllMocks()`, `x.mockClear()` / `mockReset()` / `mockRestore()` — that the runner already performs between tests → delete it. **Silent until** the flags are known: `['error', { clearMocks: true, restoreMocks: true, mockReset: true }]`, or a `vitest.config.*` / `vite.config.*` found above the file. The flag has to match the call: `restoreMocks` alone does not make a `clearAllMocks()` dead, since it never reaches a plain `vi.fn()`. `--fix` only where nothing can have run in between — the first statement of the file's only `beforeEach` — a suggestion everywhere else, and **never** in a test body |
3857
+ | `no-redundant-mock-reset` | `error` | `--fix` / suggest | a mock reset **the runner already performs** — `vi.clearAllMocks()` / `resetAllMocks()` / `restoreAllMocks()`, `x.mockClear()` / `mockReset()` / `mockRestore()` — as the first statement of a `beforeEach` no other `beforeEach` precedes, or a clear closing an `afterEach` → delete it. **Silent until** the flags are known: `['error', { clearMocks: true, restoreMocks: true, mockReset: true }]`, `{ configFile }` naming the runner config, or a `vitest.config.*` / `vite.config.*` found above the file. The flag has to match the call: `restoreMocks` alone does not make a `clearAllMocks()` dead, since it never reaches a plain `vi.fn()`. `--fix` only in a file whose only before-hook it is, a suggestion everywhere else, and **never** in a test body |
3858
3858
  | `no-unasserted-argument` | `warn` | — | a bare `expect(spy).toHaveBeenCalled()` where the file itself says the arguments are the point: the same subject is pinned with `toHaveBeenCalledWith(…)` in another test of the file, or the test's title says `with` and its body asserts nothing else → name the arguments. Narrower than `vitest/prefer-called-with` on purpose — 175 findings against its 1941 on the same suite |
3859
3859
  | `no-compile-components` | `error` | suggest | `compileComponents()` under a builder that inlines `templateUrl` / `styleUrls` — a promise already settled; **silent** until `{ builder: 'inline-resources' }` says so, because a JIT setup that loads resources at run time needs the call. One exception the rule cannot see: a component whose template holds a `@defer` block ships async class metadata, so the call stays load-bearing there |
3860
3860
  | `no-sync-testbed-await` | `error` | suggest | `await` on a TestBed call that answers the TestBed or a fixture — `configureTestingModule`, every `override*`, `resetTestingModule`, `createComponent`, `getLastFixture`; none of them is a promise, so the `await` waits for nothing and the `async` it forced on the hook awaits nothing either. The suggestion drops both. Reads no types, so it reports without `parserOptions.project` |
@@ -9,14 +9,25 @@ interface AngularDiagnosticsOptions {
9
9
  deadSchemas?: boolean;
10
10
  /** Fail — rather than warn — when `injectSpy` finds a real instance where a spy was expected. */
11
11
  unspiedProviders?: boolean;
12
- /** Fail a test that ends with unflushed `HttpTestingController` requests. */
13
- pendingRequests?: boolean;
12
+ /**
13
+ * Fail a test that ends with unflushed `HttpTestingController` requests.
14
+ *
15
+ * An object keeps the check on and carries its option to it: `{ ignoreCancelled: true }` is the
16
+ * opt-in `HttpTestingController.verify({ ignoreCancelled })` names — a request the code under test
17
+ * cancelled, by unsubscribing, is taken but no longer fails the test.
18
+ */
19
+ pendingRequests?: PendingRequestsOptions | boolean;
14
20
  /**
15
21
  * Fail when a double registered on the testing module loses to the component's own `providers`,
16
22
  * so the component under test is running against the real service.
17
23
  */
18
24
  shadowedProviders?: boolean;
19
25
  }
26
+ /** What `pendingRequests` and {@link assertNoPendingRequests} accept. */
27
+ interface PendingRequestsOptions {
28
+ /** Skip requests the code under test cancelled. Default `false`, like Angular's own `verify()`. */
29
+ ignoreCancelled?: boolean;
30
+ }
20
31
  /**
21
32
  * Fail when the `HttpTestingController` this test configured is still holding requests.
22
33
  *
@@ -25,6 +36,7 @@ interface AngularDiagnosticsOptions {
25
36
  * reading it takes the requests, so calling it yourself is not paid for twice.
26
37
  *
27
38
  * A no-op when the group is off, or when the test never configured HTTP testing at all.
39
+ * `ignoreCancelled` defaults to what `enableAngularDiagnostics({ pendingRequests })` was given.
28
40
  *
29
41
  * @example
30
42
  * ```ts
@@ -33,7 +45,7 @@ interface AngularDiagnosticsOptions {
33
45
  * assertNoPendingRequests(); // nothing else went out
34
46
  * ```
35
47
  */
36
- declare function assertNoPendingRequests(): void;
48
+ declare function assertNoPendingRequests(options?: PendingRequestsOptions): void;
37
49
  /**
38
50
  * Fail when a double this test registered on the testing module never reached `component`.
39
51
  *
@@ -165,4 +177,4 @@ declare function reportSpecTiming(timing: SpecTiming): void;
165
177
  */
166
178
  declare function enableTestBedDiagnostics(options?: TestBedDiagnosticsOptions): void;
167
179
 
168
- export { type AngularDiagnosticsOptions, type SpecTiming, type TestBedDiagnosticsOptions, assertNoPendingRequests, assertNoShadowedProviders, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, reportSpecTiming };
180
+ export { type AngularDiagnosticsOptions, type PendingRequestsOptions, type SpecTiming, type TestBedDiagnosticsOptions, assertNoPendingRequests, assertNoShadowedProviders, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, reportSpecTiming };
@@ -1,7 +1,7 @@
1
- import { instrumentTestBed, onTestingModuleConfigured, onComponentCreated, beforeTestBedReset, verifyOnTeardown } from './chunk-KOR5OK4H.js';
2
- export { disableTestBedDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, reportSpecTiming } from './chunk-KOR5OK4H.js';
1
+ import { assertAngularInternals, instrumentTestBed, onTestingModuleConfigured, onComponentCreated, beforeTestBedReset, verifyOnTeardown } from './chunk-RGRZDCM6.js';
2
+ export { disableTestBedDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, reportSpecTiming } from './chunk-RGRZDCM6.js';
3
3
  import { failOnUnspiedProvider } from './chunk-45W5LBPY.js';
4
- import { assertAngularInternals } from './chunk-WYYKUPXW.js';
4
+ import './chunk-6UETTNQH.js';
5
5
  import './chunk-MBSPAUUD.js';
6
6
  import './chunk-DQ3SPSCH.js';
7
7
  import './chunk-MG7LKE4R.js';
@@ -170,7 +170,10 @@ function readControllerToken(config) {
170
170
  }
171
171
  function describeRequest(open) {
172
172
  const request = readProperty(open, "request");
173
- return `${String(readProperty(request, "method"))} ${String(readProperty(request, "urlWithParams"))}`;
173
+ return {
174
+ description: `${String(readProperty(request, "method"))} ${String(readProperty(request, "urlWithParams"))}`,
175
+ cancelled: readProperty(open, "cancelled") === true
176
+ };
174
177
  }
175
178
  function takeOpenRequests(controller) {
176
179
  const match = readProperty(controller, "match");
@@ -189,16 +192,18 @@ function injectFromModule(token) {
189
192
  function readOpenRequests() {
190
193
  return controllerToken === void 0 ? [] : takeOpenRequests(injectFromModule(controllerToken));
191
194
  }
192
- function assertNoPendingRequests() {
193
- const open = [...openAtReset.splice(0), ...readOpenRequests()];
195
+ function assertNoPendingRequests(options = {}) {
196
+ const taken = [...openAtReset.splice(0), ...readOpenRequests()];
197
+ const ignoreCancelled = options.ignoreCancelled ?? active?.ignoreCancelled ?? false;
198
+ const open = ignoreCancelled ? taken.filter((request) => !request.cancelled) : taken;
194
199
  if (open.length === 0) {
195
200
  return;
196
201
  }
197
202
  throw new Error(
198
203
  withDocs(
199
- `[vitest-auto-spy] enableAngularDiagnostics({ pendingRequests }): the test ended with ${open.length} unflushed HttpTestingController request(s): ${open.join(", ")}.
204
+ `[vitest-auto-spy] enableAngularDiagnostics({ pendingRequests }): the test ended with ${open.length} unflushed HttpTestingController request(s): ${open.map((request) => request.description).join(", ")}.
200
205
  Nothing answered them and nothing asserted them, so the code under test is still waiting on a response it never received \u2014 everything the spec expected to happen after that call did not happen here.
201
- Flush each one (\`controller.expectOne('/url').flush(body)\`), or call \`controller.verify()\` in the spec where the absence of a request is the thing being asserted.`,
206
+ Flush each one (\`controller.expectOne('/url').flush(body)\`), or call \`controller.verify()\` in the spec where the absence of a request is the thing being asserted. A request the code cancels on purpose is excused by \`enableAngularDiagnostics({ pendingRequests: { ignoreCancelled: true } })\`.`,
202
207
  DOCS_LINKS.angularDiagnostics
203
208
  )
204
209
  );
@@ -271,7 +276,7 @@ function registerPerTestHooks() {
271
276
  }
272
277
  preparedTest = void 0;
273
278
  if (active?.pendingRequests) {
274
- verifyOnTeardown(assertNoPendingRequests);
279
+ verifyOnTeardown(() => assertNoPendingRequests());
275
280
  }
276
281
  });
277
282
  }
@@ -281,7 +286,8 @@ function enableAngularDiagnostics(options = {}) {
281
286
  ngModuleScopes: options.ngModuleScopes ?? true,
282
287
  deadSchemas: options.deadSchemas ?? true,
283
288
  unspiedProviders: options.unspiedProviders ?? true,
284
- pendingRequests: options.pendingRequests ?? true,
289
+ pendingRequests: options.pendingRequests !== false,
290
+ ignoreCancelled: typeof options.pendingRequests === "object" && options.pendingRequests.ignoreCancelled === true,
285
291
  shadowedProviders: options.shadowedProviders ?? true
286
292
  };
287
293
  assertAngularInternals();
@@ -1,5 +1,5 @@
1
1
  import { AbstractType, Injector, InjectionToken, ValueProvider, FactoryProvider, ProviderToken } from '@angular/core';
2
- import { h as AddSpyMethodsByReturnTypes } from './types-BM3BcWj1.js';
2
+ import { h as AddSpyMethodsByReturnTypes } from './types-BuQtoidb.js';
3
3
  import 'vitest';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  import { writeWarning } from './chunk-3VXZRDH3.js';
2
- import { verifyOnTeardown, beforeTestBedReset } from './chunk-KOR5OK4H.js';
2
+ import { assertAngularInternals, verifyOnTeardown, beforeTestBedReset } from './chunk-RGRZDCM6.js';
3
3
  import { flushEffects } from './chunk-JBV35SU3.js';
4
- import { assertAngularInternals } from './chunk-WYYKUPXW.js';
4
+ import './chunk-6UETTNQH.js';
5
5
  import './chunk-SOROJD3W.js';
6
6
  import { DOCS_LINKS } from './chunk-QO4BPR3V.js';
7
7
  import { withDocs } from './chunk-TZ7DRSRD.js';
@@ -1,6 +1,6 @@
1
1
  import { Type, Injector, FactoryProvider, Provider } from '@angular/core';
2
2
  import { Params, Data, UrlSegment, ActivatedRoute, Route, ResolveData, Navigation, Router, Event } from '@angular/router';
3
- import { h as AddSpyMethodsByReturnTypes } from './types-BM3BcWj1.js';
3
+ import { h as AddSpyMethodsByReturnTypes } from './types-BuQtoidb.js';
4
4
  import { SpyLocation } from '@angular/common/testing';
5
5
  import 'vitest';
6
6
 
@@ -251,12 +251,12 @@ type LocationDouble = SpyLocation;
251
251
  *
252
252
  * const location = injectLocationDouble();
253
253
  *
254
- * location.go('/reports/7'); // urlChanges records it; path() reads it back
254
+ * location.go('/reports', 'tab=7'); // urlChanges records it; path() reads '/reports?tab=7' back
255
255
  * location.simulateUrlPop('/'); // the popstate no method call can cause
256
256
  * ```
257
257
  *
258
- * Returns the provider pair Angular ships (`SpyLocation` for `Location`, `MockLocationStrategy` for
259
- * `LocationStrategy`) — a new array every call, so a list hoisted to a module constant still hands
258
+ * Returns the pair `provideLocationMocks()` ships (a `SpyLocation` for `Location`, whose `path()` keeps
259
+ * the query, and `MockLocationStrategy` for `LocationStrategy`) — a new array every call, so a list hoisted to a module constant still hands
260
260
  * each injector a double of its own.
261
261
  */
262
262
  declare function provideLocationDouble(): Provider[];
@@ -1,3 +1,4 @@
1
+ import { angularInternalsError } from './chunk-6UETTNQH.js';
1
2
  import { createFunctionSpy } from './chunk-LZVIH54N.js';
2
3
  import './chunk-BBPYNKGB.js';
3
4
  import { DOCS_LINKS } from './chunk-QO4BPR3V.js';
@@ -7,8 +8,8 @@ import { Router, DefaultUrlSerializer, PRIMARY_OUTLET, ActivatedRoute, RouterSta
7
8
  import { BehaviorSubject, skip } from 'rxjs';
8
9
  import { signal } from '@angular/core';
9
10
  import { onTestFinished, expect } from 'vitest';
10
- import { Location } from '@angular/common';
11
- import { provideLocationMocks, SpyLocation } from '@angular/common/testing';
11
+ import { Location, LocationStrategy } from '@angular/common';
12
+ import { MockLocationStrategy, SpyLocation } from '@angular/common/testing';
12
13
 
13
14
  var doubles = /* @__PURE__ */ new WeakMap();
14
15
  function toSegments(url) {
@@ -436,13 +437,35 @@ function collectRouterEvents(source) {
436
437
  }
437
438
  };
438
439
  }
440
+ function currentQuery(location) {
441
+ const history = Reflect.get(location, "_history");
442
+ const index = Reflect.get(location, "_historyIndex");
443
+ const entry = Array.isArray(history) && typeof index === "number" ? history[index] : void 0;
444
+ const query = Reflect.get(Object(entry), "query");
445
+ if (typeof query !== "string") {
446
+ throw angularInternalsError(
447
+ "SpyLocation#_history[\u2026].query",
448
+ "`provideLocationDouble()` can no longer answer the query in `path()`, as the real `Location` does."
449
+ );
450
+ }
451
+ return query;
452
+ }
453
+ var QueryAwareSpyLocation = class extends SpyLocation {
454
+ path() {
455
+ const query = currentQuery(this);
456
+ return super.path() + Location.normalizeQueryParams(query);
457
+ }
458
+ };
439
459
  function describeInstance(instance) {
440
460
  const prototype = Reflect.getPrototypeOf(instance);
441
461
  const owner = prototype === null || prototype === Object.prototype ? void 0 : Reflect.get(prototype, "constructor");
442
462
  return typeof owner === "function" ? `an instance of ${owner.name}` : "a plain object";
443
463
  }
444
464
  function provideLocationDouble() {
445
- return [...provideLocationMocks()];
465
+ return [
466
+ { provide: Location, useFactory: createLocationDouble },
467
+ { provide: LocationStrategy, useClass: MockLocationStrategy }
468
+ ];
446
469
  }
447
470
  function injectLocationDouble(injector) {
448
471
  const caller = "[vitest-auto-spy] injectLocationDouble()";
@@ -463,7 +486,7 @@ function injectLocationDouble(injector) {
463
486
  return location;
464
487
  }
465
488
  function createLocationDouble() {
466
- return new SpyLocation();
489
+ return new QueryAwareSpyLocation();
467
490
  }
468
491
 
469
492
  export { collectRouterEvents, createActivatedRoute, createLocationDouble, createRouterDouble, injectActivatedRoute, injectLocationDouble, injectRouterDouble, provideActivatedRoute, provideLocationDouble, provideRouterDouble };
package/dist/angular.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export { o as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, q as provideAutoSpyForToken, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-BSVObkds.js';
1
+ export { o as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, q as provideAutoSpyForToken, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-DsBgqliM.js';
2
2
  import { InjectionToken, Provider, Type, WritableSignal, Signal } from '@angular/core';
3
- import { A as AutoMockConfiguration, D as DeepReadonly } from './expect-emission-S5asJaJP.js';
4
- export { C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, s as setEmissionTimeout } from './expect-emission-S5asJaJP.js';
5
- import { o as DeepPartial, C as ClassType, m as ClassSpyConfiguration, S as Spy, q as OnlyMethodKeysOf, h as AddSpyMethodsByReturnTypes } from './types-BM3BcWj1.js';
3
+ import { A as AutoMockConfiguration, D as DeepReadonly } from './expect-emission-CD6thEE8.js';
4
+ export { C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, s as setEmissionTimeout } from './expect-emission-CD6thEE8.js';
5
+ import { o as DeepPartial, C as ClassType, m as ClassSpyConfiguration, S as Spy, q as OnlyMethodKeysOf, h as AddSpyMethodsByReturnTypes } from './types-BuQtoidb.js';
6
6
  import { TestAPI } from 'vitest';
7
- export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-Dig5t28T.js';
8
- 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-C--a8rpU.js';
7
+ export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-L6IgAUL7.js';
8
+ 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-yHR11U7R.js';
9
9
  import '@angular/core/testing';
10
10
 
11
11
  /**
package/dist/angular.js CHANGED
@@ -3196,33 +3196,6 @@ Nothing here is fixable from a spec: report the Angular version above, and pin t
3196
3196
  )
3197
3197
  );
3198
3198
  }
3199
- var PROBES = [
3200
- {
3201
- what: "TestBed#_testModuleRef",
3202
- consequence: "The live testing module can no longer be told from a reset one, so `provideHttpTesting({ verifyOnTeardown })` and `enableAngularDiagnostics({ pendingRequests, shadowedProviders })` would report nothing at all.",
3203
- ok: () => "_testModuleRef" in getTestBed()
3204
- },
3205
- {
3206
- what: "ReactiveNode#consumers / #kind",
3207
- consequence: "`mockSignalProp()` can no longer see whether a signal has been read, nor write through a read-only one, so a patch applied after the first read would be accepted and quietly change nothing.",
3208
- ok: () => {
3209
- const node = Object(Reflect.get(signal(0), _SIGNAL));
3210
- return "consumers" in node && Reflect.get(node, "kind") === "signal";
3211
- }
3212
- }
3213
- ];
3214
- var failure;
3215
- var checked = false;
3216
- function assertAngularInternals() {
3217
- if (!checked) {
3218
- checked = true;
3219
- const broken = PROBES.find((probe) => !probe.ok());
3220
- failure = broken === void 0 ? void 0 : angularInternalsError(broken.what, broken.consequence);
3221
- }
3222
- if (failure) {
3223
- throw failure;
3224
- }
3225
- }
3226
3199
 
3227
3200
  // src/lib/component-stub.ts
3228
3201
  var NOT = 1;
@@ -3885,6 +3858,35 @@ function installResourceDouble(object, property, initialValue, options) {
3885
3858
  resource
3886
3859
  };
3887
3860
  }
3861
+ var PROBES = [
3862
+ {
3863
+ what: "TestBed#_testModuleRef",
3864
+ consequence: "The live testing module can no longer be told from a reset one, so `provideHttpTesting({ verifyOnTeardown })` and `enableAngularDiagnostics({ pendingRequests, shadowedProviders })` would report nothing at all.",
3865
+ ok: () => "_testModuleRef" in getTestBed()
3866
+ },
3867
+ {
3868
+ what: "ReactiveNode#consumers / #kind",
3869
+ consequence: "`mockSignalProp()` can no longer see whether a signal has been read, nor write through a read-only one, so a patch applied after the first read would be accepted and quietly change nothing.",
3870
+ ok: () => {
3871
+ const node = Object(Reflect.get(signal(0), _SIGNAL));
3872
+ return "consumers" in node && Reflect.get(node, "kind") === "signal";
3873
+ }
3874
+ }
3875
+ ];
3876
+ var failure;
3877
+ var checked = false;
3878
+ function assertAngularInternals() {
3879
+ if (!checked) {
3880
+ checked = true;
3881
+ const broken = PROBES.find((probe) => !probe.ok());
3882
+ failure = broken === void 0 ? void 0 : angularInternalsError(broken.what, broken.consequence);
3883
+ }
3884
+ if (failure) {
3885
+ throw failure;
3886
+ }
3887
+ }
3888
+
3889
+ // src/lib/signal-prop.ts
3888
3890
  function isWritableMember(candidate) {
3889
3891
  const maybe = Object(candidate);
3890
3892
  return isSignal(candidate) && typeof maybe.set === "function";
@@ -1,9 +1,9 @@
1
- export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithAny, c as AddCalledWithObservable, d as AddCalledWithPromise, e as AddCalledWithSpyMethods, f as AddObservableSpyMethods, g as AddPromiseSpyMethods, h as AddSpyMethodsByReturnTypes, i as AddThrowHelper, j as AddVoidReturnHelpers, k as AnyReturnHelpers, l as AutoSpyRxjsTypes, m as ClassSpyConfiguration, C as ClassType, n as CompleteValueConfig, D as DeepMockProxy, o as DeepPartial, E as ErrorValueConfig, F as Func, I as InstanceSpyConfiguration, M as MethodReturns, p as Mutable, N as NextValueConfig, O as ObservableLike, q as OnlyMethodKeysOf, r as OnlyObservablePropsOf, s as OnlyPropsOf, t as Overload, u as OverloadChoice, v as Overloads, P as PropStubValue, S as Spy, w as SpyDisposable, x as SpyOptions, y as StrictSpyConfiguration, z as SubjectLike, B as SubjectOf, U as UnstubbedCall, G as UnstubbedCallHandler, H as UnstubbedRead, J as UnstubbedReadHandler, V as ValueConfig, K as ValueConfigPerCall, W as WithMockReturnValue } from './types-BM3BcWj1.js';
1
+ export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithAny, c as AddCalledWithObservable, d as AddCalledWithPromise, e as AddCalledWithSpyMethods, f as AddObservableSpyMethods, g as AddPromiseSpyMethods, h as AddSpyMethodsByReturnTypes, i as AddThrowHelper, j as AddVoidReturnHelpers, k as AnyReturnHelpers, l as AutoSpyRxjsTypes, m as ClassSpyConfiguration, C as ClassType, n as CompleteValueConfig, D as DeepMockProxy, o as DeepPartial, E as ErrorValueConfig, F as Func, I as InstanceSpyConfiguration, M as MethodReturns, p as Mutable, N as NextValueConfig, O as ObservableLike, q as OnlyMethodKeysOf, r as OnlyObservablePropsOf, s as OnlyPropsOf, t as Overload, u as OverloadChoice, v as Overloads, P as PropStubValue, S as Spy, w as SpyDisposable, x as SpyOptions, y as StrictSpyConfiguration, z as SubjectLike, B as SubjectOf, U as UnstubbedCall, G as UnstubbedCallHandler, H as UnstubbedRead, J as UnstubbedReadHandler, V as ValueConfig, K as ValueConfigPerCall, W as WithMockReturnValue } from './types-BuQtoidb.js';
2
2
  export { AdoptMockOptions, AdoptedMock, ArgCaptor, AsInstances, AssertMockedOptions, CallLog, CaptureArgOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, SpyClassOptions, adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromClass, createSpyFromInstance, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, resetAutoSpy, restoreSpiedInstance, settleDynamicImport, stubConstructor, withOverrides } from './bun.js';
3
- export { A as AutoMockConfiguration, a as AutoSpyDefaultEntry, C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, d as autoMocked, e as clearAutoSpyDefaults, f as createAutoMock, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, r as registerAutoSpyDefaults, s as setEmissionTimeout } from './expect-emission-S5asJaJP.js';
4
- export { c as createFunctionSpy, d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-Cn7yncmJ.js';
5
- export { A as AccessorImplementations, O as OutsideHookReaction, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as reportPropsOutsideHooks, e as restoreMockedProps } from './prop-mock-C--a8rpU.js';
6
- export { A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-BSVObkds.js';
3
+ export { A as AutoMockConfiguration, a as AutoSpyDefaultEntry, C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, d as autoMocked, e as clearAutoSpyDefaults, f as createAutoMock, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, r as registerAutoSpyDefaults, s as setEmissionTimeout } from './expect-emission-CD6thEE8.js';
4
+ export { c as createFunctionSpy, d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-CqrrGVDm.js';
5
+ export { A as AccessorImplementations, O as OutsideHookReaction, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as reportPropsOutsideHooks, e as restoreMockedProps } from './prop-mock-yHR11U7R.js';
6
+ export { A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-DsBgqliM.js';
7
7
  import 'vitest';
8
8
  import '@angular/core';
9
9
  import '@angular/core/testing';
@@ -2,7 +2,7 @@ import { createSpyForToken } from './chunk-ZCWAFGHX.js';
2
2
  export { injectSpy, provideAutoSpy } from './chunk-45W5LBPY.js';
3
3
  import { stable, flushEffects } from './chunk-JBV35SU3.js';
4
4
  export { flushEffects, stable } from './chunk-JBV35SU3.js';
5
- import { angularInternalsError } from './chunk-WYYKUPXW.js';
5
+ import { angularInternalsError } from './chunk-6UETTNQH.js';
6
6
  import './chunk-YEQQIKQR.js';
7
7
  export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, stubConstructor, withOverrides } from './chunk-E5M7DBWB.js';
8
8
  import { mockValueProp } from './chunk-MBSPAUUD.js';
package/dist/bun.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { x as SpyOptions, C as ClassType, m as ClassSpyConfiguration, q as OnlyMethodKeysOf, S as Spy, I as InstanceSpyConfiguration, o as DeepPartial, D as DeepMockProxy, F as Func, h as AddSpyMethodsByReturnTypes } from './types-BM3BcWj1.js';
2
- export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithAny, c as AddCalledWithObservable, d as AddCalledWithPromise, e as AddCalledWithSpyMethods, f as AddObservableSpyMethods, g as AddPromiseSpyMethods, i as AddThrowHelper, j as AddVoidReturnHelpers, k as AnyReturnHelpers, l as AutoSpyRxjsTypes, n as CompleteValueConfig, E as ErrorValueConfig, M as MethodReturns, p as Mutable, N as NextValueConfig, O as ObservableLike, r as OnlyObservablePropsOf, s as OnlyPropsOf, t as Overload, u as OverloadChoice, v as Overloads, P as PropStubValue, w as SpyDisposable, y as StrictSpyConfiguration, z as SubjectLike, B as SubjectOf, U as UnstubbedCall, G as UnstubbedCallHandler, H as UnstubbedRead, J as UnstubbedReadHandler, V as ValueConfig, K as ValueConfigPerCall, W as WithMockReturnValue } from './types-BM3BcWj1.js';
3
- export { A as AutoMockConfiguration, a as AutoSpyDefaultEntry, C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, d as autoMocked, e as clearAutoSpyDefaults, f as createAutoMock, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, r as registerAutoSpyDefaults, s as setEmissionTimeout } from './expect-emission-S5asJaJP.js';
4
- export { c as createFunctionSpy, d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-Cn7yncmJ.js';
5
- export { A as AccessorImplementations, O as OutsideHookReaction, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as reportPropsOutsideHooks, e as restoreMockedProps } from './prop-mock-C--a8rpU.js';
1
+ import { x as SpyOptions, C as ClassType, m as ClassSpyConfiguration, q as OnlyMethodKeysOf, S as Spy, I as InstanceSpyConfiguration, o as DeepPartial, D as DeepMockProxy, F as Func, h as AddSpyMethodsByReturnTypes } from './types-BuQtoidb.js';
2
+ export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithAny, c as AddCalledWithObservable, d as AddCalledWithPromise, e as AddCalledWithSpyMethods, f as AddObservableSpyMethods, g as AddPromiseSpyMethods, i as AddThrowHelper, j as AddVoidReturnHelpers, k as AnyReturnHelpers, l as AutoSpyRxjsTypes, n as CompleteValueConfig, E as ErrorValueConfig, M as MethodReturns, p as Mutable, N as NextValueConfig, O as ObservableLike, r as OnlyObservablePropsOf, s as OnlyPropsOf, t as Overload, u as OverloadChoice, v as Overloads, P as PropStubValue, w as SpyDisposable, y as StrictSpyConfiguration, z as SubjectLike, B as SubjectOf, U as UnstubbedCall, G as UnstubbedCallHandler, H as UnstubbedRead, J as UnstubbedReadHandler, V as ValueConfig, K as ValueConfigPerCall, W as WithMockReturnValue } from './types-BuQtoidb.js';
3
+ export { A as AutoMockConfiguration, a as AutoSpyDefaultEntry, C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, d as autoMocked, e as clearAutoSpyDefaults, f as createAutoMock, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, r as registerAutoSpyDefaults, s as setEmissionTimeout } from './expect-emission-CD6thEE8.js';
4
+ export { c as createFunctionSpy, d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-CqrrGVDm.js';
5
+ export { A as AccessorImplementations, O as OutsideHookReaction, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as reportPropsOutsideHooks, e as restoreMockedProps } from './prop-mock-yHR11U7R.js';
6
6
  import { Mock, MockInstance } from 'vitest';
7
7
 
8
8
  /**
@@ -0,0 +1,16 @@
1
+ import { DOCS_LINKS } from './chunk-QO4BPR3V.js';
2
+ import { withDocs } from './chunk-TZ7DRSRD.js';
3
+ import { VERSION } from '@angular/core';
4
+
5
+ function angularInternalsError(what, consequence) {
6
+ return new Error(
7
+ withDocs(
8
+ `[vitest-auto-spy] @angular/core ${VERSION.full} no longer carries ${what}, which this package reads.
9
+ ${consequence}
10
+ Nothing here is fixable from a spec: report the Angular version above, and pin the previous one until a release of this package reads the new shape.`,
11
+ DOCS_LINKS.angular
12
+ )
13
+ );
14
+ }
15
+
16
+ export { angularInternalsError };
@@ -1,7 +1,8 @@
1
+ import { angularInternalsError } from './chunk-6UETTNQH.js';
1
2
  import { TestBed, getTestBed } from '@angular/core/testing';
2
3
  import { expect, beforeAll, afterAll } from 'vitest';
4
+ import { signal, ɵSIGNAL as _SIGNAL } from '@angular/core';
3
5
 
4
- // src/lib/testbed-diagnostics.ts
5
6
  var INSTRUMENTED = [
6
7
  { method: "configureTestingModule", counter: "configurations" },
7
8
  { method: "createComponent", counter: "components" },
@@ -115,6 +116,33 @@ function enableTestBedDiagnostics(options = {}) {
115
116
  }
116
117
  });
117
118
  }
119
+ var PROBES = [
120
+ {
121
+ what: "TestBed#_testModuleRef",
122
+ consequence: "The live testing module can no longer be told from a reset one, so `provideHttpTesting({ verifyOnTeardown })` and `enableAngularDiagnostics({ pendingRequests, shadowedProviders })` would report nothing at all.",
123
+ ok: () => "_testModuleRef" in getTestBed()
124
+ },
125
+ {
126
+ what: "ReactiveNode#consumers / #kind",
127
+ consequence: "`mockSignalProp()` can no longer see whether a signal has been read, nor write through a read-only one, so a patch applied after the first read would be accepted and quietly change nothing.",
128
+ ok: () => {
129
+ const node = Object(Reflect.get(signal(0), _SIGNAL));
130
+ return "consumers" in node && Reflect.get(node, "kind") === "signal";
131
+ }
132
+ }
133
+ ];
134
+ var failure;
135
+ var checked = false;
136
+ function assertAngularInternals() {
137
+ if (!checked) {
138
+ checked = true;
139
+ const broken = PROBES.find((probe) => !probe.ok());
140
+ failure = broken === void 0 ? void 0 : angularInternalsError(broken.what, broken.consequence);
141
+ }
142
+ if (failure) {
143
+ throw failure;
144
+ }
145
+ }
118
146
  function beforeTestBedReset(wrapped, beforeReset) {
119
147
  const testBed = getTestBed();
120
148
  const original = Reflect.get(testBed, "resetTestingModule");
@@ -131,4 +159,4 @@ function beforeTestBedReset(wrapped, beforeReset) {
131
159
  });
132
160
  }
133
161
 
134
- export { beforeTestBedReset, disableTestBedDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, onComponentCreated, onTestingModuleConfigured, reportSpecTiming, verifyOnTeardown };
162
+ export { assertAngularInternals, beforeTestBedReset, disableTestBedDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, onComponentCreated, onTestingModuleConfigured, reportSpecTiming, verifyOnTeardown };