vitest-auto-spy 3.12.1 → 3.13.1
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 +22 -2
- package/README.md +27 -3
- package/dist/angular.d.ts +5 -5
- package/dist/angular.js +78 -13
- package/dist/bun-angular.d.ts +10 -4
- package/dist/bun-angular.js +36 -8
- package/dist/bun.d.ts +9 -4
- package/dist/bun.js +4 -4
- package/dist/{chunk-ZBVBJFNW.js → chunk-C3IZLTSJ.js} +11 -3
- package/dist/{chunk-JV5XRAS4.js → chunk-CEVEKNJZ.js} +2 -2
- package/dist/{chunk-7YTPHYP7.js → chunk-PCP6A6PD.js} +1 -1
- package/dist/{chunk-R4EWAG7Y.js → chunk-WVW4XRL5.js} +1 -1
- package/dist/{chunk-3AWKPZCE.js → chunk-ZY7KPBJJ.js} +63 -13
- package/dist/console.d.ts +1 -1
- package/dist/console.js +1 -1
- package/dist/{expect-emission-CuGjE0YR.d.ts → expect-emission-DMx5uXie.d.ts} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +71 -13
- package/dist/nestjs.d.ts +2 -2
- package/dist/nestjs.js +3 -3
- package/dist/node.cjs +71 -13
- package/dist/node.d.ts +3 -3
- package/dist/node.js +4 -4
- package/dist/{prop-mock-IgCwv_40.d.ts → prop-mock-DyjtZVoA.d.ts} +1 -1
- package/dist/react.d.ts +3 -3
- package/dist/react.js +4 -4
- package/dist/rxjs.d.ts +2 -2
- package/dist/rxjs.js +9 -2
- package/dist/setup.d.ts +22 -3
- package/dist/setup.js +42 -3
- package/dist/shared-state.js +3 -0
- package/dist/svelte.d.ts +3 -3
- package/dist/svelte.js +4 -4
- package/dist/{track-injections-BAzV5ITq.d.ts → track-injections-BQndbppn.d.ts} +1 -1
- package/dist/{types-it6CnDkI.d.ts → types-Br-Usge9.d.ts} +13 -2
- package/dist/vue.d.ts +4 -4
- package/dist/vue.js +5 -5
- package/dist/{zoneless-BUNSBSIP.d.ts → zoneless-CEhs7o9p.d.ts} +3 -3
- package/package.json +1 -1
- package/skills/vitest-auto-spy/SKILL.md +8 -0
package/AGENTS.md
CHANGED
|
@@ -358,6 +358,8 @@ users.getName.calledWith(1).mockReturnValue('Ada');
|
|
|
358
358
|
users.getName.mustBeCalledWith(1).mockReturnValue('Ada');
|
|
359
359
|
// asymmetric matchers work in both
|
|
360
360
|
users.save.calledWith(expect.objectContaining({ id: 1 })).mockReturnValue(true);
|
|
361
|
+
// re-registering the same arguments replaces the answer — matcher arguments included
|
|
362
|
+
users.save.calledWith(expect.objectContaining({ id: 1 })).mockReturnValue(false);
|
|
361
363
|
|
|
362
364
|
// promises
|
|
363
365
|
users.load.resolveWith({ id: 1 });
|
|
@@ -374,6 +376,13 @@ feed.items$.throwWith('FAKE ERROR');
|
|
|
374
376
|
const subject = feed.items$.returnSubject(); // ReplaySubject, for anything the helpers miss
|
|
375
377
|
```
|
|
376
378
|
|
|
379
|
+
An exact argument list is matched before the asymmetric configs, and those are tried in
|
|
380
|
+
registration order — a narrow config written first keeps its calls. Two matchers count as the same
|
|
381
|
+
argument when they accept the same values (same matcher class, sample and inversion), which is what
|
|
382
|
+
makes a second `calledWith(1, expect.anything())` an override rather than a second config sitting
|
|
383
|
+
behind the first. A hand-rolled `{ asymmetricMatch }` object is compared by identity instead: its
|
|
384
|
+
verdict is a closure, so only re-registering that same instance overrides.
|
|
385
|
+
|
|
377
386
|
`mock.settledResults` is native on Vitest and polyfilled on Bun / `node:test`, so it is identical on
|
|
378
387
|
all three. Entries are `{ type: 'fulfilled' | 'incomplete' | 'rejected', value }`.
|
|
379
388
|
|
|
@@ -958,8 +967,19 @@ by a dynamic `import()` inside a test — and says so explicitly:
|
|
|
958
967
|
export const navigation = { setFocus: keepMockRegistered(vi.fn()) };
|
|
959
968
|
```
|
|
960
969
|
|
|
961
|
-
|
|
962
|
-
|
|
970
|
+
The mocks it keeps, it also guards. Staying registered means `vi.resetAllMocks()` reaches them too —
|
|
971
|
+
it walks the same set and calls `mockReset()`, which puts an implementation back only when it was
|
|
972
|
+
passed to `vi.fn(implementation)`; behaviour chained on with `.mockReturnValue(…)` or
|
|
973
|
+
`.mockReturnThis()` is simply lost. Under `isolate: false` that surfaces in a *different* file later
|
|
974
|
+
in the same worker, inside application code, as `Cannot read properties of undefined` against a
|
|
975
|
+
shared double that spec never touched — and `vi.restoreAllMocks()` does not cause it (Vitest 4 walks
|
|
976
|
+
`MOCK_RESTORE` there, which only `vi.spyOn` writes to), so probing with that one comes back green and
|
|
977
|
+
sends the search the wrong way. The implementation a long-lived mock carried when it was classified
|
|
978
|
+
is therefore remembered and put back, in `beforeEach`, but only when it has gone missing.
|
|
979
|
+
|
|
980
|
+
`trackMockRegistry()` installs the hooks on its own, `pruneMockRegistry()` is the one-shot sweep (it
|
|
981
|
+
returns how many went), `restoreLongLivedImplementations()` is that repair (it returns how many it
|
|
982
|
+
put back) and `getMockRegistrySize()` reports what is left.
|
|
963
983
|
|
|
964
984
|
Two more switches, both about the environment rather than the spies:
|
|
965
985
|
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ identical API, with **RxJS** spies and **Angular / NestJS / React / Vue·Pinia /
|
|
|
16
16
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
17
17
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
18
18
|
[](https://github.com/ASDAlexey/vitest-auto-spy/actions/workflows/ci.yml)
|
|
19
|
-
[](#install)
|
|
20
20
|
[](https://www.npmjs.com/package/vitest-auto-spy)
|
|
21
21
|
[](https://github.com/ASDAlexey/vitest-auto-spy/actions/workflows/ci.yml)
|
|
22
22
|
[](./LICENSE)
|
|
@@ -1231,6 +1231,24 @@ Wanted: getName(1)
|
|
|
1231
1231
|
Actual: getName(2)
|
|
1232
1232
|
```
|
|
1233
1233
|
|
|
1234
|
+
### Matching order, and re-configuring the same arguments
|
|
1235
|
+
|
|
1236
|
+
An exact argument list is matched first; the asymmetric configs (`expect.any(Number)`,
|
|
1237
|
+
`expect.objectContaining({ … })`, …) are then tried in the order they were registered, so a narrow
|
|
1238
|
+
config placed before a wide one keeps its calls. Registering the **same** argument list again
|
|
1239
|
+
replaces the answer it gave before — matcher arguments included:
|
|
1240
|
+
|
|
1241
|
+
```ts
|
|
1242
|
+
myService.getName.calledWith(expect.anything()).mockReturnValue('first');
|
|
1243
|
+
myService.getName.calledWith(expect.anything()).mockReturnValue('second');
|
|
1244
|
+
expect(myService.getName(1)).toBe('second');
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
Each `expect.anything()` is a new object, so the two are compared by what they accept rather than by
|
|
1248
|
+
identity — same matcher class, same sample, same inversion. A hand-rolled `{ asymmetricMatch }`
|
|
1249
|
+
object is the exception: its verdict lives in a closure nothing can read, so two of them are always
|
|
1250
|
+
two configs and only the very same instance, re-registered, overrides.
|
|
1251
|
+
|
|
1234
1252
|
## Promise-returning methods
|
|
1235
1253
|
|
|
1236
1254
|
```ts
|
|
@@ -1901,7 +1919,7 @@ single-purpose utility you can pick up independently — they all ride on the sa
|
|
|
1901
1919
|
| `installPerTest(install)` | `/setup` | Re-install a stub before every test of the block — a `describe`-level stub is restored away after the first |
|
|
1902
1920
|
| `setupAngularTestEnv(opts)` | `/angular` | Zone and zoneless spec files in one worker, switching platforms per file |
|
|
1903
1921
|
| `restoreTimerGlobals()` | `/setup` | Put back timer globals that uninstalling the fakes deleted rather than restored |
|
|
1904
|
-
| `trackMockRegistry()` / `keepMockRegistered(mock)`
|
|
1922
|
+
| `trackMockRegistry()` / `keepMockRegistered(mock)` / `restoreLongLivedImplementations()` | `/setup` | Keep @vitest/spy's mock registry to the mocks that outlive a file; mark one the split would miss; put back an implementation a cross-file `vi.resetAllMocks()` dropped ([details](#test-run-hygiene)) |
|
|
1905
1923
|
| `errorHandler` | core | The `mustBeCalledWith` argument-mismatch reporter — swap it to customize failure output |
|
|
1906
1924
|
|
|
1907
1925
|
A taste of the DI pair — provide the spy, inject it back fully typed:
|
|
@@ -2065,7 +2083,12 @@ expensive to diagnose when it is missing. The first three are on by default:
|
|
|
2065
2083
|
component trees. Pruning it is easy to get wrong in one specific way: drop the module-level
|
|
2066
2084
|
`vi.fn()` that six spec files import from a shared `*.mock.ts` and nothing clears it any more, so
|
|
2067
2085
|
its calls accumulate and the file that happens to run second fails on calls its predecessor made.
|
|
2068
|
-
`pruneMockRegistry` keeps what a file inherited and drops only what it added.
|
|
2086
|
+
`pruneMockRegistry` keeps what a file inherited and drops only what it added. Keeping a mock
|
|
2087
|
+
registered also means `vi.resetAllMocks()` can reach it — `mockReset` drops an implementation
|
|
2088
|
+
that came from a chained `.mockReturnValue(…)`, which under `isolate: false` kills a *later*
|
|
2089
|
+
file's test on a double it never touched — so `trackMockRegistry()` remembers the implementation
|
|
2090
|
+
each long-lived mock carried and puts it back before a test that has lost it
|
|
2091
|
+
(`restoreLongLivedImplementations()` is that repair on its own, and returns how many it put back).
|
|
2069
2092
|
9. **A hook that ran out of a budget nobody meant to give it.** On by default, because it only ever
|
|
2070
2093
|
appends a sentence to a test that has already failed. Jest applies one `testTimeout` to a hook and
|
|
2071
2094
|
to a test body alike; Vitest resolves `hookTimeout` separately and defaults it to 10 000 ms, so a
|
|
@@ -2395,6 +2418,7 @@ names are unfindable from these messages otherwise — no `TS2739` text contains
|
|
|
2395
2418
|
| `TS2345: Argument of type 'Spy<X>' is not assignable to parameter of type 'X'` | the same, in an argument | `asInstance(spy)`, or `asInstances(a, b, c)` |
|
|
2396
2419
|
| `TS2322: Type 'Spy<X>' is not assignable to type 'Mocked<X>' …` | the variable was declared `Mocked<T>` | declare it `Spy<T>` |
|
|
2397
2420
|
| `'AddPromiseSpyMethods<unknown>' is missing … from type 'WithMockReturnValue<…>'` | a generic class inferred as `Service<any>` | `asSpy<Service>(…)` / `injectSpy<Service>(…)` |
|
|
2421
|
+
| `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 |
|
|
2398
2422
|
| `TS2739 … 'Spy<X>' is missing …` **on a line with `injectSpy`** | the provider handed back the real object | `provideAutoSpy(X)`, or an honest `TestBed.inject` |
|
|
2399
2423
|
|
|
2400
2424
|
Two notes that cost real time when they are missing.
|
package/dist/angular.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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-CEhs7o9p.js';
|
|
2
2
|
import { Type, Signal, WritableSignal } from '@angular/core';
|
|
3
|
-
import { S as Spy, C as ClassType, a as ClassSpyConfiguration, O as OnlyMethodKeysOf, j as AddSpyMethodsByReturnTypes } from './types-
|
|
4
|
-
export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-
|
|
5
|
-
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-
|
|
6
|
-
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-
|
|
3
|
+
import { S as Spy, C as ClassType, a as ClassSpyConfiguration, O as OnlyMethodKeysOf, j as AddSpyMethodsByReturnTypes } from './types-Br-Usge9.js';
|
|
4
|
+
export { I as InjectionLog, T as TrackInjectionsOptions, a as TrackedProvider, t as trackInjections } from './track-injections-BQndbppn.js';
|
|
5
|
+
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-DyjtZVoA.js';
|
|
6
|
+
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-DMx5uXie.js';
|
|
7
7
|
import '@angular/core/testing';
|
|
8
8
|
import 'rxjs';
|
|
9
9
|
import 'vitest';
|
package/dist/angular.js
CHANGED
|
@@ -102,6 +102,9 @@ function serializeShape(value, context) {
|
|
|
102
102
|
if (value instanceof Date) {
|
|
103
103
|
return `new Date(${value.getTime()})`;
|
|
104
104
|
}
|
|
105
|
+
if (value instanceof RegExp) {
|
|
106
|
+
return String(value);
|
|
107
|
+
}
|
|
105
108
|
if (value instanceof Map) {
|
|
106
109
|
return serializeMap(value, context);
|
|
107
110
|
}
|
|
@@ -172,6 +175,22 @@ function isAsymmetricMatcher(value) {
|
|
|
172
175
|
function hasAsymmetricMatcher(args) {
|
|
173
176
|
return args.some(isAsymmetricMatcher);
|
|
174
177
|
}
|
|
178
|
+
var ASYMMETRIC_MATCHER_BRAND = /* @__PURE__ */ Symbol.for("jest.asymmetricMatcher");
|
|
179
|
+
function isSameMatcher(configArg, candidateArg) {
|
|
180
|
+
if (configArg === candidateArg) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
if (!isAsymmetricMatcher(candidateArg) || !isBrandedMatcher(configArg) || !isBrandedMatcher(candidateArg)) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
if (Object.getPrototypeOf(configArg) !== Object.getPrototypeOf(candidateArg)) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return serializeValue(configArg) === serializeValue(candidateArg);
|
|
190
|
+
}
|
|
191
|
+
function isBrandedMatcher(matcher) {
|
|
192
|
+
return matcher.$$typeof === ASYMMETRIC_MATCHER_BRAND;
|
|
193
|
+
}
|
|
175
194
|
var ArgsMap = class {
|
|
176
195
|
// Prototype-less so a `'__proto__'` (or `'constructor'`) serialized key is a
|
|
177
196
|
// plain own property, never walking or polluting the object prototype chain.
|
|
@@ -186,19 +205,7 @@ var ArgsMap = class {
|
|
|
186
205
|
#arities = /* @__PURE__ */ new Set();
|
|
187
206
|
set(key, value) {
|
|
188
207
|
if (Array.isArray(key) && hasAsymmetricMatcher(key)) {
|
|
189
|
-
|
|
190
|
-
const described = [];
|
|
191
|
-
for (const arg of key) {
|
|
192
|
-
if (isAsymmetricMatcher(arg)) {
|
|
193
|
-
serialized.push(void 0);
|
|
194
|
-
described.push(arg.toAsymmetricMatcher?.() ?? String(arg));
|
|
195
|
-
} else {
|
|
196
|
-
const rendered = this.#serialize([arg]);
|
|
197
|
-
serialized.push(rendered);
|
|
198
|
-
described.push(rendered.slice(1, -1));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
this.#matcherConfigs.push({ args: key, serialized, described, value });
|
|
208
|
+
this.#setMatcherConfig(this.#buildMatcherConfig(key, value));
|
|
202
209
|
return;
|
|
203
210
|
}
|
|
204
211
|
if (Array.isArray(key)) {
|
|
@@ -228,6 +235,49 @@ var ArgsMap = class {
|
|
|
228
235
|
const asymmetric = this.#matcherConfigs.map((config) => `[${config.described.join(",")}]`);
|
|
229
236
|
return [...Object.keys(this.#map), ...asymmetric];
|
|
230
237
|
}
|
|
238
|
+
/** Render one asymmetric config once, at registration time. See {@link MatcherConfig}. */
|
|
239
|
+
#buildMatcherConfig(key, value) {
|
|
240
|
+
const serialized = [];
|
|
241
|
+
const described = [];
|
|
242
|
+
for (const arg of key) {
|
|
243
|
+
if (isAsymmetricMatcher(arg)) {
|
|
244
|
+
serialized.push(void 0);
|
|
245
|
+
described.push(arg.toAsymmetricMatcher?.() ?? String(arg));
|
|
246
|
+
} else {
|
|
247
|
+
const rendered = this.#serialize([arg]);
|
|
248
|
+
serialized.push(rendered);
|
|
249
|
+
described.push(rendered.slice(1, -1));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { args: key, serialized, described, value };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Register an asymmetric config, replacing an equivalent one in place.
|
|
256
|
+
*
|
|
257
|
+
* Re-registering args is how a test overrides an earlier answer, and on the exact map that falls
|
|
258
|
+
* out for free — the second `set` writes the same key. The matcher list has to do it by hand:
|
|
259
|
+
* lookup takes the first predicate that matches, so an appended duplicate would sit behind the
|
|
260
|
+
* config it was meant to replace and never be reached, and a `beforeEach` that reconfigures the
|
|
261
|
+
* same spy would grow the list on every test. Replacing in place also keeps the registration
|
|
262
|
+
* order that decides which of two *overlapping* configs wins.
|
|
263
|
+
*/
|
|
264
|
+
#setMatcherConfig(config) {
|
|
265
|
+
const index = this.#matcherConfigs.findIndex((existing) => this.#sameConfigArgs(existing, config));
|
|
266
|
+
if (index === -1) {
|
|
267
|
+
this.#matcherConfigs.push(config);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.#matcherConfigs[index] = config;
|
|
271
|
+
}
|
|
272
|
+
/** Whether two configs were registered for the same argument list, matcher positions included. */
|
|
273
|
+
#sameConfigArgs(existing, candidate) {
|
|
274
|
+
if (existing.args.length !== candidate.args.length) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
return existing.args.every(
|
|
278
|
+
(arg, index) => isAsymmetricMatcher(arg) ? isSameMatcher(arg, candidate.args[index]) : existing.serialized[index] === candidate.serialized[index]
|
|
279
|
+
);
|
|
280
|
+
}
|
|
231
281
|
// Keys are always argument arrays; `serializeValue` renders them to a stable,
|
|
232
282
|
// total string (single-quoted strings, bracketed arrays, distinct `undefined`
|
|
233
283
|
// / function / symbol / BigInt / Date renderings, circular-ref safe). Arrays of
|
|
@@ -1796,7 +1846,14 @@ var AutoSpyInjector = class extends Injector {
|
|
|
1796
1846
|
tokens() {
|
|
1797
1847
|
return [...this.#spies.keys()];
|
|
1798
1848
|
}
|
|
1849
|
+
knows(token) {
|
|
1850
|
+
return this.#spies.has(token);
|
|
1851
|
+
}
|
|
1799
1852
|
};
|
|
1853
|
+
function describeToken(token) {
|
|
1854
|
+
const name = Reflect.get(Object(token), "name");
|
|
1855
|
+
return typeof name === "string" ? name : String(token);
|
|
1856
|
+
}
|
|
1800
1857
|
function factoryOf(target) {
|
|
1801
1858
|
const factory = Reflect.get(target, "\u0275fac");
|
|
1802
1859
|
return typeof factory === "function" ? factory : void 0;
|
|
@@ -1811,6 +1868,14 @@ function createWithAutoSpies(target, options = {}) {
|
|
|
1811
1868
|
injector,
|
|
1812
1869
|
spies: {
|
|
1813
1870
|
get: (token) => {
|
|
1871
|
+
if (!autoSpies.knows(token) && injector.get(token, null, { optional: true }) === null) {
|
|
1872
|
+
throw new Error(
|
|
1873
|
+
withDocs(
|
|
1874
|
+
`[vitest-auto-spy] createWithAutoSpies(${describeToken(target)}).spies.get(${describeToken(token)}): the instance never asked for that token, and nothing in \`providers\` supplies it, so the spy you would get back is not the one it uses. Auto-spied tokens: ${autoSpies.tokens().map(describeToken).join(", ") || "(none)"}.`,
|
|
1875
|
+
DOCS_LINKS.angular
|
|
1876
|
+
)
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1814
1879
|
return injector.get(token);
|
|
1815
1880
|
},
|
|
1816
1881
|
autoSpiedTokens: () => autoSpies.tokens()
|
package/dist/bun-angular.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, j as AddSpyMethodsByReturnTypes, k as AddVoidReturnHelpers, a as ClassSpyConfiguration, C as ClassType, b as CompleteValueConfig, D as DeepMockProxy, l as DeepPartial, E as ErrorValueConfig, F as Func, M as MethodReturns, m as Mutable, N as NextValueConfig, O as OnlyMethodKeysOf, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, S as Spy, r as SpyDisposable, s as SpyOptions, t as StrictSpyConfiguration, U as UnstubbedCall, u as UnstubbedCallHandler, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-
|
|
1
|
+
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, j as AddSpyMethodsByReturnTypes, k as AddVoidReturnHelpers, a as ClassSpyConfiguration, C as ClassType, b as CompleteValueConfig, D as DeepMockProxy, l as DeepPartial, E as ErrorValueConfig, F as Func, M as MethodReturns, m as Mutable, N as NextValueConfig, O as OnlyMethodKeysOf, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, S as Spy, r as SpyDisposable, s as SpyOptions, t as StrictSpyConfiguration, U as UnstubbedCall, u as UnstubbedCallHandler, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-Br-Usge9.js';
|
|
2
2
|
export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, IntersectionObserverStubOptions, MediaElementState, MediaElementStub, MediaElementStubOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, MutationRecordInit, ObserverGlobal, ObserverInstance, ObserverStub, ObserverStubOptions, ResizeEntryRect, TestRunComparison, TestRunReport, TestRunSummary, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, compareTestRuns, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, diffByField, errorHandler, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resetAutoSpy, resizeEntry, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './bun.js';
|
|
3
|
-
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
4
|
-
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-
|
|
3
|
+
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-DMx5uXie.js';
|
|
4
|
+
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-DyjtZVoA.js';
|
|
5
5
|
export { d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-B1pqa-Sh.js';
|
|
6
|
-
export { 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, r as renderShallow, j as runEffect, s as settleResource, k as stable } from './zoneless-
|
|
6
|
+
export { 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, r as renderShallow, j as runEffect, s as settleResource, k as stable } from './zoneless-CEhs7o9p.js';
|
|
7
7
|
import 'rxjs';
|
|
8
8
|
import 'vitest';
|
|
9
9
|
import '@angular/core';
|
|
@@ -72,6 +72,12 @@ declare function registerDomGlobals(options?: RegisterDomGlobalsOptions): Promis
|
|
|
72
72
|
* implementation. A property the target refuses to accept is skipped rather than fatal — a locked
|
|
73
73
|
* global is not worth failing a whole test run over.
|
|
74
74
|
*
|
|
75
|
+
* Skipped, but **not** in silence when it is one of {@link FORCED_GLOBALS}: those are the five the
|
|
76
|
+
* DOM is useless without, so a refused `document` means the environment came up half-installed and
|
|
77
|
+
* the first spec that touches it reports `document is not defined` — naming neither this helper nor
|
|
78
|
+
* the property that refused. The rest stay quiet, because a host built-in keeping its own
|
|
79
|
+
* implementation is the documented outcome rather than a problem.
|
|
80
|
+
*
|
|
75
81
|
* @example
|
|
76
82
|
* ```ts
|
|
77
83
|
* copyWindowGlobals(dom.window as unknown as Record<string, unknown>, globalThis as Record<string, unknown>);
|
package/dist/bun-angular.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import './chunk-Y4YG7UOK.js';
|
|
2
|
-
import { createSpyForToken } from './chunk-
|
|
2
|
+
import { createSpyForToken } from './chunk-CEVEKNJZ.js';
|
|
3
3
|
import './chunk-NQXXUJPS.js';
|
|
4
|
-
export { asInstance, asInstances, asSpy, assertMocked, captureArg, compareTestRuns, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, diffByField, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, getPackageCopies, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resizeEntry, setEmissionTimeout, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './chunk-
|
|
5
|
-
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-
|
|
6
|
-
import { createSpyFromClass } from './chunk-
|
|
7
|
-
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-
|
|
8
|
-
import { withDocs, DOCS_LINKS, isAutoSpyLike } from './chunk-
|
|
9
|
-
export { createFunctionSpy, errorHandler } from './chunk-
|
|
4
|
+
export { asInstance, asInstances, asSpy, assertMocked, captureArg, compareTestRuns, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, diffByField, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, getPackageCopies, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resizeEntry, setEmissionTimeout, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './chunk-C3IZLTSJ.js';
|
|
5
|
+
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-WVW4XRL5.js';
|
|
6
|
+
import { createSpyFromClass } from './chunk-PCP6A6PD.js';
|
|
7
|
+
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-PCP6A6PD.js';
|
|
8
|
+
import { withDocs, DOCS_LINKS, isAutoSpyLike } from './chunk-ZY7KPBJJ.js';
|
|
9
|
+
export { createFunctionSpy, errorHandler } from './chunk-ZY7KPBJJ.js';
|
|
10
10
|
import './chunk-J5O72UHX.js';
|
|
11
11
|
import '@angular/compiler';
|
|
12
12
|
import { NgModule, provideZonelessChangeDetection, Injector, runInInjectionContext, NO_ERRORS_SCHEMA, ApplicationRef, ɵSIGNAL as _SIGNAL } from '@angular/core';
|
|
@@ -160,6 +160,7 @@ ${failures.join("\n") || " - (no registrars were configured)"}`,
|
|
|
160
160
|
}
|
|
161
161
|
function copyWindowGlobals(source, target) {
|
|
162
162
|
const keys = [...FORCED_GLOBALS, ...Object.getOwnPropertyNames(source)];
|
|
163
|
+
const refused = [];
|
|
163
164
|
for (const key of keys) {
|
|
164
165
|
if (key.startsWith("_")) {
|
|
165
166
|
continue;
|
|
@@ -170,9 +171,21 @@ function copyWindowGlobals(source, target) {
|
|
|
170
171
|
}
|
|
171
172
|
try {
|
|
172
173
|
Object.defineProperty(target, key, { value, configurable: true, writable: true, enumerable: true });
|
|
173
|
-
} catch {
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (FORCED_GLOBALS.includes(key)) {
|
|
176
|
+
refused.push(`${key} (${describeError(error)})`);
|
|
177
|
+
}
|
|
174
178
|
}
|
|
175
179
|
}
|
|
180
|
+
if (refused.length === 0) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
console.warn(
|
|
184
|
+
withDocs(
|
|
185
|
+
`[vitest-auto-spy] copyWindowGlobals: the host refused to redefine ${refused.join(", ")}. The DOM is only half-installed, and the failure will arrive later as "document is not defined" or an unrelated jsdom assertion, naming neither this helper nor the property. Something sealed that global before the preload ran.`,
|
|
186
|
+
DOCS_LINKS.bunAngular
|
|
187
|
+
)
|
|
188
|
+
);
|
|
176
189
|
}
|
|
177
190
|
function createJsdomRegistrar(options) {
|
|
178
191
|
return {
|
|
@@ -237,7 +250,14 @@ var AutoSpyInjector = class extends Injector {
|
|
|
237
250
|
tokens() {
|
|
238
251
|
return [...this.#spies.keys()];
|
|
239
252
|
}
|
|
253
|
+
knows(token) {
|
|
254
|
+
return this.#spies.has(token);
|
|
255
|
+
}
|
|
240
256
|
};
|
|
257
|
+
function describeToken(token) {
|
|
258
|
+
const name = Reflect.get(Object(token), "name");
|
|
259
|
+
return typeof name === "string" ? name : String(token);
|
|
260
|
+
}
|
|
241
261
|
function factoryOf(target) {
|
|
242
262
|
const factory = Reflect.get(target, "\u0275fac");
|
|
243
263
|
return typeof factory === "function" ? factory : void 0;
|
|
@@ -252,6 +272,14 @@ function createWithAutoSpies(target, options = {}) {
|
|
|
252
272
|
injector,
|
|
253
273
|
spies: {
|
|
254
274
|
get: (token) => {
|
|
275
|
+
if (!autoSpies.knows(token) && injector.get(token, null, { optional: true }) === null) {
|
|
276
|
+
throw new Error(
|
|
277
|
+
withDocs(
|
|
278
|
+
`[vitest-auto-spy] createWithAutoSpies(${describeToken(target)}).spies.get(${describeToken(token)}): the instance never asked for that token, and nothing in \`providers\` supplies it, so the spy you would get back is not the one it uses. Auto-spied tokens: ${autoSpies.tokens().map(describeToken).join(", ") || "(none)"}.`,
|
|
279
|
+
DOCS_LINKS.angular
|
|
280
|
+
)
|
|
281
|
+
);
|
|
282
|
+
}
|
|
255
283
|
return injector.get(token);
|
|
256
284
|
},
|
|
257
285
|
autoSpiedTokens: () => autoSpies.tokens()
|
package/dist/bun.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { s as SpyOptions, C as ClassType, a as ClassSpyConfiguration, O as OnlyMethodKeysOf, S as Spy, l as DeepPartial, D as DeepMockProxy, F as Func, u as UnstubbedCallHandler, j as AddSpyMethodsByReturnTypes } from './types-
|
|
2
|
-
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, k as AddVoidReturnHelpers, b as CompleteValueConfig, E as ErrorValueConfig, M as MethodReturns, m as Mutable, N as NextValueConfig, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, r as SpyDisposable, t as StrictSpyConfiguration, U as UnstubbedCall, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-
|
|
3
|
-
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
4
|
-
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-
|
|
1
|
+
import { s as SpyOptions, C as ClassType, a as ClassSpyConfiguration, O as OnlyMethodKeysOf, S as Spy, l as DeepPartial, D as DeepMockProxy, F as Func, u as UnstubbedCallHandler, j as AddSpyMethodsByReturnTypes } from './types-Br-Usge9.js';
|
|
2
|
+
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, k as AddVoidReturnHelpers, b as CompleteValueConfig, E as ErrorValueConfig, M as MethodReturns, m as Mutable, N as NextValueConfig, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, r as SpyDisposable, t as StrictSpyConfiguration, U as UnstubbedCall, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-Br-Usge9.js';
|
|
3
|
+
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-DMx5uXie.js';
|
|
4
|
+
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-DyjtZVoA.js';
|
|
5
5
|
export { d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-B1pqa-Sh.js';
|
|
6
6
|
import { Mock } from 'vitest';
|
|
7
7
|
import 'rxjs';
|
|
@@ -790,6 +790,11 @@ interface AssertMockedOptions {
|
|
|
790
790
|
*
|
|
791
791
|
* Worth naming when the factory stubs part of a module and re-exports the rest: without a list,
|
|
792
792
|
* a factory that lost the one export the test drives still looks mocked.
|
|
793
|
+
*
|
|
794
|
+
* An **empty** list is rejected rather than accepted: `exports: []` — which is what
|
|
795
|
+
* `Object.keys(stubs)` or a filtered constant produces when it comes out empty — used to take the
|
|
796
|
+
* named-exports branch, find nothing to check and return, so the one call in the file whose job
|
|
797
|
+
* is to prove the mock applied proved nothing.
|
|
793
798
|
*/
|
|
794
799
|
exports?: readonly string[];
|
|
795
800
|
}
|
package/dist/bun.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './chunk-Y4YG7UOK.js';
|
|
2
2
|
import './chunk-NQXXUJPS.js';
|
|
3
|
-
export { asInstance, asInstances, asSpy, assertMocked, captureArg, compareTestRuns, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, diffByField, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, getPackageCopies, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resizeEntry, setEmissionTimeout, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './chunk-
|
|
4
|
-
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-
|
|
5
|
-
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-
|
|
6
|
-
export { createFunctionSpy, errorHandler } from './chunk-
|
|
3
|
+
export { asInstance, asInstances, asSpy, assertMocked, captureArg, compareTestRuns, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, diffByField, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, getPackageCopies, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resizeEntry, setEmissionTimeout, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './chunk-C3IZLTSJ.js';
|
|
4
|
+
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-WVW4XRL5.js';
|
|
5
|
+
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-PCP6A6PD.js';
|
|
6
|
+
export { createFunctionSpy, errorHandler } from './chunk-ZY7KPBJJ.js';
|
|
7
7
|
import './chunk-J5O72UHX.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mockValueProp, mockReadonlyPropGetter } from './chunk-
|
|
2
|
-
import { createSpyFromClass, createProxyPropStore, describeStoredProp, dropStoredProp, storeDefinedProp, writeStoredAccessor, writeStoredValue, readStoredAccessor, NOT_STORED, DISPOSE, disposeAutoSpy, isProtocolKey, isDeletedProp } from './chunk-
|
|
3
|
-
import { defineHelper, withDocs, DOCS_LINKS, serializeValue, createFunctionSpy, DEEP_CHILDREN } from './chunk-
|
|
1
|
+
import { mockValueProp, mockReadonlyPropGetter } from './chunk-WVW4XRL5.js';
|
|
2
|
+
import { createSpyFromClass, createProxyPropStore, describeStoredProp, dropStoredProp, storeDefinedProp, writeStoredAccessor, writeStoredValue, readStoredAccessor, NOT_STORED, DISPOSE, disposeAutoSpy, isProtocolKey, isDeletedProp } from './chunk-PCP6A6PD.js';
|
|
3
|
+
import { defineHelper, withDocs, DOCS_LINKS, serializeValue, createFunctionSpy, DEEP_CHILDREN } from './chunk-ZY7KPBJJ.js';
|
|
4
4
|
import { getMockAdapter } from './shared-state.js';
|
|
5
5
|
export { describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, getPackageCopies, setEmissionTimeout } from './shared-state.js';
|
|
6
6
|
|
|
@@ -442,6 +442,14 @@ var SILENT_NO_OP_CAUSES = "A `vi.mock()` that does not apply reports nothing: un
|
|
|
442
442
|
var assertMocked = defineHelper((namespace, options = {}) => {
|
|
443
443
|
const target = describeTarget(options.specifier);
|
|
444
444
|
const required = options.exports;
|
|
445
|
+
if (required?.length === 0) {
|
|
446
|
+
throw new Error(
|
|
447
|
+
withDocs(
|
|
448
|
+
`[vitest-auto-spy] assertMocked(${target}): the \`exports\` list is empty, so this call cannot fail and proves nothing. Drop the option to check that at least one export is a mock, or name the exports the test drives.`,
|
|
449
|
+
DOCS_LINKS.moduleMocks
|
|
450
|
+
)
|
|
451
|
+
);
|
|
452
|
+
}
|
|
445
453
|
if (required) {
|
|
446
454
|
const real = required.filter((name) => !isRunnerMock(Reflect.get(namespace, name)));
|
|
447
455
|
if (real.length > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createSpyFromClass, createAutoMock } from './chunk-
|
|
2
|
-
import { withDocs, DOCS_LINKS } from './chunk-
|
|
1
|
+
import { createSpyFromClass, createAutoMock } from './chunk-PCP6A6PD.js';
|
|
2
|
+
import { withDocs, DOCS_LINKS } from './chunk-ZY7KPBJJ.js';
|
|
3
3
|
|
|
4
4
|
// src/lib/track-injections.ts
|
|
5
5
|
function createSpyForToken(token) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runClearHook, runConfigReset, resolveUnstubbedGuard, withDocs, DOCS_LINKS, AUTO_SPY_MARK, createFunctionSpy, isMarkedMock, readDeepChildren, markAsMock } from './chunk-
|
|
1
|
+
import { runClearHook, runConfigReset, resolveUnstubbedGuard, withDocs, DOCS_LINKS, AUTO_SPY_MARK, createFunctionSpy, isMarkedMock, readDeepChildren, markAsMock } from './chunk-ZY7KPBJJ.js';
|
|
2
2
|
import { getMockAdapter, requireObservableSupport } from './shared-state.js';
|
|
3
3
|
|
|
4
4
|
// src/lib/dispose-symbol.ts
|
|
@@ -81,6 +81,9 @@ function serializeShape(value, context) {
|
|
|
81
81
|
if (value instanceof Date) {
|
|
82
82
|
return `new Date(${value.getTime()})`;
|
|
83
83
|
}
|
|
84
|
+
if (value instanceof RegExp) {
|
|
85
|
+
return String(value);
|
|
86
|
+
}
|
|
84
87
|
if (value instanceof Map) {
|
|
85
88
|
return serializeMap(value, context);
|
|
86
89
|
}
|
|
@@ -187,6 +190,22 @@ function isAsymmetricMatcher(value) {
|
|
|
187
190
|
function hasAsymmetricMatcher(args) {
|
|
188
191
|
return args.some(isAsymmetricMatcher);
|
|
189
192
|
}
|
|
193
|
+
var ASYMMETRIC_MATCHER_BRAND = /* @__PURE__ */ Symbol.for("jest.asymmetricMatcher");
|
|
194
|
+
function isSameMatcher(configArg, candidateArg) {
|
|
195
|
+
if (configArg === candidateArg) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
if (!isAsymmetricMatcher(candidateArg) || !isBrandedMatcher(configArg) || !isBrandedMatcher(candidateArg)) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
if (Object.getPrototypeOf(configArg) !== Object.getPrototypeOf(candidateArg)) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return serializeValue(configArg) === serializeValue(candidateArg);
|
|
205
|
+
}
|
|
206
|
+
function isBrandedMatcher(matcher) {
|
|
207
|
+
return matcher.$$typeof === ASYMMETRIC_MATCHER_BRAND;
|
|
208
|
+
}
|
|
190
209
|
var ArgsMap = class {
|
|
191
210
|
// Prototype-less so a `'__proto__'` (or `'constructor'`) serialized key is a
|
|
192
211
|
// plain own property, never walking or polluting the object prototype chain.
|
|
@@ -201,19 +220,7 @@ var ArgsMap = class {
|
|
|
201
220
|
#arities = /* @__PURE__ */ new Set();
|
|
202
221
|
set(key, value) {
|
|
203
222
|
if (Array.isArray(key) && hasAsymmetricMatcher(key)) {
|
|
204
|
-
|
|
205
|
-
const described = [];
|
|
206
|
-
for (const arg of key) {
|
|
207
|
-
if (isAsymmetricMatcher(arg)) {
|
|
208
|
-
serialized.push(void 0);
|
|
209
|
-
described.push(arg.toAsymmetricMatcher?.() ?? String(arg));
|
|
210
|
-
} else {
|
|
211
|
-
const rendered = this.#serialize([arg]);
|
|
212
|
-
serialized.push(rendered);
|
|
213
|
-
described.push(rendered.slice(1, -1));
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
this.#matcherConfigs.push({ args: key, serialized, described, value });
|
|
223
|
+
this.#setMatcherConfig(this.#buildMatcherConfig(key, value));
|
|
217
224
|
return;
|
|
218
225
|
}
|
|
219
226
|
if (Array.isArray(key)) {
|
|
@@ -243,6 +250,49 @@ var ArgsMap = class {
|
|
|
243
250
|
const asymmetric = this.#matcherConfigs.map((config) => `[${config.described.join(",")}]`);
|
|
244
251
|
return [...Object.keys(this.#map), ...asymmetric];
|
|
245
252
|
}
|
|
253
|
+
/** Render one asymmetric config once, at registration time. See {@link MatcherConfig}. */
|
|
254
|
+
#buildMatcherConfig(key, value) {
|
|
255
|
+
const serialized = [];
|
|
256
|
+
const described = [];
|
|
257
|
+
for (const arg of key) {
|
|
258
|
+
if (isAsymmetricMatcher(arg)) {
|
|
259
|
+
serialized.push(void 0);
|
|
260
|
+
described.push(arg.toAsymmetricMatcher?.() ?? String(arg));
|
|
261
|
+
} else {
|
|
262
|
+
const rendered = this.#serialize([arg]);
|
|
263
|
+
serialized.push(rendered);
|
|
264
|
+
described.push(rendered.slice(1, -1));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { args: key, serialized, described, value };
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Register an asymmetric config, replacing an equivalent one in place.
|
|
271
|
+
*
|
|
272
|
+
* Re-registering args is how a test overrides an earlier answer, and on the exact map that falls
|
|
273
|
+
* out for free — the second `set` writes the same key. The matcher list has to do it by hand:
|
|
274
|
+
* lookup takes the first predicate that matches, so an appended duplicate would sit behind the
|
|
275
|
+
* config it was meant to replace and never be reached, and a `beforeEach` that reconfigures the
|
|
276
|
+
* same spy would grow the list on every test. Replacing in place also keeps the registration
|
|
277
|
+
* order that decides which of two *overlapping* configs wins.
|
|
278
|
+
*/
|
|
279
|
+
#setMatcherConfig(config) {
|
|
280
|
+
const index = this.#matcherConfigs.findIndex((existing) => this.#sameConfigArgs(existing, config));
|
|
281
|
+
if (index === -1) {
|
|
282
|
+
this.#matcherConfigs.push(config);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this.#matcherConfigs[index] = config;
|
|
286
|
+
}
|
|
287
|
+
/** Whether two configs were registered for the same argument list, matcher positions included. */
|
|
288
|
+
#sameConfigArgs(existing, candidate) {
|
|
289
|
+
if (existing.args.length !== candidate.args.length) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
return existing.args.every(
|
|
293
|
+
(arg, index) => isAsymmetricMatcher(arg) ? isSameMatcher(arg, candidate.args[index]) : existing.serialized[index] === candidate.serialized[index]
|
|
294
|
+
);
|
|
295
|
+
}
|
|
246
296
|
// Keys are always argument arrays; `serializeValue` renders them to a stable,
|
|
247
297
|
// total string (single-quoted strings, bracketed arrays, distinct `undefined`
|
|
248
298
|
// / function / symbol / BigInt / Date renderings, circular-ref safe). Arrays of
|
package/dist/console.d.ts
CHANGED
package/dist/console.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { vitestMockAdapter } from './chunk-MG5EAMZR.js';
|
|
2
|
-
import { createFunctionSpy } from './chunk-
|
|
2
|
+
import { createFunctionSpy } from './chunk-ZY7KPBJJ.js';
|
|
3
3
|
import './chunk-J5O72UHX.js';
|
|
4
4
|
import { hasMockAdapter, registerMockAdapter, getMockAdapter } from './shared-state.js';
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as StrictSpyConfiguration, n as OnlyObservablePropsOf, M as MethodReturns, l as DeepPartial, S as Spy, s as SpyOptions } from './types-
|
|
1
|
+
import { t as StrictSpyConfiguration, n as OnlyObservablePropsOf, M as MethodReturns, l as DeepPartial, S as Spy, s as SpyOptions } from './types-Br-Usge9.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a fully-typed auto-mock of `T` from its type alone (no class).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, j as AddSpyMethodsByReturnTypes, k as AddVoidReturnHelpers, a as ClassSpyConfiguration, C as ClassType, b as CompleteValueConfig, D as DeepMockProxy, l as DeepPartial, E as ErrorValueConfig, F as Func, M as MethodReturns, m as Mutable, N as NextValueConfig, O as OnlyMethodKeysOf, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, S as Spy, r as SpyDisposable, s as SpyOptions, t as StrictSpyConfiguration, U as UnstubbedCall, u as UnstubbedCallHandler, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-
|
|
1
|
+
export { d as AccessorKeysOf, e as AddAccessorsSpies, f as AddCalledWithObservable, g as AddCalledWithPromise, h as AddCalledWithSpyMethods, A as AddObservableSpyMethods, i as AddPromiseSpyMethods, j as AddSpyMethodsByReturnTypes, k as AddVoidReturnHelpers, a as ClassSpyConfiguration, C as ClassType, b as CompleteValueConfig, D as DeepMockProxy, l as DeepPartial, E as ErrorValueConfig, F as Func, M as MethodReturns, m as Mutable, N as NextValueConfig, O as OnlyMethodKeysOf, n as OnlyObservablePropsOf, o as OnlyPropsOf, p as Overload, q as Overloads, P as PropStubValue, S as Spy, r as SpyDisposable, s as SpyOptions, t as StrictSpyConfiguration, U as UnstubbedCall, u as UnstubbedCallHandler, V as ValueConfig, c as ValueConfigPerCall, W as WithMockReturnValue } from './types-Br-Usge9.js';
|
|
2
2
|
export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, IntersectionObserverStubOptions, MediaElementState, MediaElementStub, MediaElementStubOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, MutationRecordInit, ObserverGlobal, ObserverInstance, ObserverStub, ObserverStubOptions, ResizeEntryRect, TestRunComparison, TestRunReport, TestRunSummary, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, compareTestRuns, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, diffByField, errorHandler, flushEventLoop, flushEventLoopUntil, formatTestRunComparison, intersectionEntry, mockConstructor, mockDeep, moduleNamespace, mutationRecord, narrow, resetAutoSpy, resizeEntry, settleDynamicImport, stubAbortController, stubConstructor, stubIntersectionObserver, stubMediaElement, stubMutationObserver, stubObserver, stubResizeObserver, summarizeTestRun, withOverrides } from './bun.js';
|
|
3
|
-
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
4
|
-
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-
|
|
3
|
+
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-DMx5uXie.js';
|
|
4
|
+
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-DyjtZVoA.js';
|
|
5
5
|
export { d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-B1pqa-Sh.js';
|
|
6
6
|
import 'rxjs';
|
|
7
7
|
import 'vitest';
|