vitest-auto-spy 5.2.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +38 -5
- package/README.md +100 -67
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +224 -142
- package/dist/bun-angular.d.ts +2 -2
- package/dist/bun-angular.js +36 -19
- package/dist/bun.d.ts +49 -3
- package/dist/bun.js +6 -6
- package/dist/{chunk-JJ2JA2E3.js → chunk-5AOJI3BM.js} +3 -2
- package/dist/{chunk-ED4EVQKA.js → chunk-6YI3G3CH.js} +2 -3
- package/dist/{chunk-XRVVZXOM.js → chunk-75GDWUIT.js} +28 -1
- package/dist/{chunk-KE3LEHPW.js → chunk-DBDXQXS3.js} +15 -8
- package/dist/{chunk-XAS66AWX.js → chunk-EGU3YJJN.js} +2 -29
- package/dist/{chunk-J33KX6XT.js → chunk-JOODFKWS.js} +47 -26
- package/dist/{chunk-URZIJ5CL.js → chunk-NLDPCJKC.js} +4 -4
- package/dist/{chunk-GOG2CJOY.js → chunk-OYQ2PHBU.js} +1 -1
- package/dist/{chunk-5TUDM4DS.js → chunk-QY4UO4BB.js} +67 -19
- package/dist/{chunk-NHSUUN3D.js → chunk-WWO6CUEJ.js} +1 -1
- package/dist/cli.js +51 -10
- package/dist/console.js +4 -4
- package/dist/dom-stubs.js +70 -50
- package/dist/eslint-plugin.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +172 -98
- package/dist/jasmine.js +6 -6
- package/dist/nestjs.js +12 -12
- package/dist/node.cjs +118 -87
- package/dist/node.d.ts +1 -1
- package/dist/node.js +8 -7
- package/dist/react.d.ts +1 -1
- package/dist/react.js +7 -7
- package/dist/rstest.d.ts +1 -1
- package/dist/rstest.js +9 -8
- package/dist/rxjs.js +11 -6
- package/dist/setup.js +6 -6
- package/dist/shared-state.js +1 -53
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +7 -7
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +8 -8
- package/dist/{zoneless-BerZbxtu.d.ts → zoneless-DM1AWQV2.d.ts} +6 -1
- package/package.json +3 -2
- package/skills/vitest-auto-spy/SKILL.md +10 -3
package/dist/angular.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerMockAdapter, getMockAdapter, getObservableSupport, getJasmineSupport, emissionTimeout, requireObservableSupport } from './shared-state.js';
|
|
2
2
|
export { setEmissionTimeout } from './shared-state.js';
|
|
3
3
|
import { vi, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
|
4
4
|
import { TestBed, getTestBed } from '@angular/core/testing';
|
|
@@ -23,6 +23,33 @@ function installDisposeSymbol(host) {
|
|
|
23
23
|
}
|
|
24
24
|
var DISPOSE = installDisposeSymbol(Symbol);
|
|
25
25
|
|
|
26
|
+
// src/lib/docs-links.ts
|
|
27
|
+
var DOCS = "https://asdalexey.github.io/vitest-auto-spy";
|
|
28
|
+
var DOCS_LINKS = {
|
|
29
|
+
angular: `${DOCS}/adapters/angular`,
|
|
30
|
+
// Their own pages rather than anchors on `adapters/angular`: a reader who hits one of these arrived
|
|
31
|
+
// from a failure, not from reading, and the page they want is the one about that check — not the
|
|
32
|
+
// one about the adapter that hosts it.
|
|
33
|
+
angularDiagnostics: `${DOCS}/adapters/angular-diagnostics`,
|
|
34
|
+
angularOverrides: `${DOCS}/adapters/angular-overrides`,
|
|
35
|
+
createSpyFromClass: `${DOCS}/core/create-spy-from-class`,
|
|
36
|
+
controlHelpers: `${DOCS}/core/control-helpers`,
|
|
37
|
+
// The recipe for the one failure no spy library can work around: a binding the bundler already
|
|
38
|
+
// inlined. Deep-linked to the section rather than the page, because the page's first half is
|
|
39
|
+
// about the *silent* half of the same problem and the reader arriving here has the loud one.
|
|
40
|
+
realSeam: `${DOCS}/utilities/module-mocks#provide-a-real-seam`,
|
|
41
|
+
setup: `${DOCS}/utilities/setup`,
|
|
42
|
+
// Its own page rather than a section of the factory's: the reader arriving here was thrown at by a
|
|
43
|
+
// double they configured somewhere else entirely, and the question they have is what counts as
|
|
44
|
+
// configured — which is the whole page, not a paragraph of another one.
|
|
45
|
+
strictMode: `${DOCS}/core/strict-mode`,
|
|
46
|
+
trackInjections: `${DOCS}/utilities/track-injections`
|
|
47
|
+
};
|
|
48
|
+
function withDocs(message, link) {
|
|
49
|
+
return `${message}
|
|
50
|
+
Docs: ${link}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
26
53
|
// src/lib/spy-probe.ts
|
|
27
54
|
var FAST_SPY_BRAND = /* @__PURE__ */ Symbol.for("vitest-auto-spy.fastSpy");
|
|
28
55
|
function isFastSpy(value) {
|
|
@@ -35,6 +62,34 @@ function isThenable(value) {
|
|
|
35
62
|
return typeof Reflect.get(value, "then") === "function";
|
|
36
63
|
}
|
|
37
64
|
|
|
65
|
+
// src/lib/spy-decoration.ts
|
|
66
|
+
function detachedHelperError(helper) {
|
|
67
|
+
return new Error(
|
|
68
|
+
withDocs(
|
|
69
|
+
`[vitest-auto-spy] ${helper} was called off its spy: \`const { ${helper} } = spy.method\` loses the spy it configures. Call it as a method \u2014 spy.method.${helper}(\u2026) \u2014 or bind it first.`,
|
|
70
|
+
DOCS_LINKS.controlHelpers
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function decorate(target, helpers) {
|
|
75
|
+
return Object.assign(target, helpers);
|
|
76
|
+
}
|
|
77
|
+
var shareOnPrototype;
|
|
78
|
+
function setSharedHelperSink(share) {
|
|
79
|
+
shareOnPrototype = share;
|
|
80
|
+
}
|
|
81
|
+
var shared = /* @__PURE__ */ new WeakSet();
|
|
82
|
+
function attachHelpers(target, helpers) {
|
|
83
|
+
if (shareOnPrototype === void 0 || !isFastSpy(target)) {
|
|
84
|
+
return decorate(target, helpers);
|
|
85
|
+
}
|
|
86
|
+
if (!shared.has(helpers)) {
|
|
87
|
+
shared.add(helpers);
|
|
88
|
+
shareOnPrototype(helpers);
|
|
89
|
+
}
|
|
90
|
+
return target;
|
|
91
|
+
}
|
|
92
|
+
|
|
38
93
|
// src/lib/fast-spy.ts
|
|
39
94
|
var clearEpoch = 0;
|
|
40
95
|
var resetEpoch = 0;
|
|
@@ -50,51 +105,52 @@ var STATE = /* @__PURE__ */ Symbol("vitest-auto-spy.fastSpy.state");
|
|
|
50
105
|
var invocationCallCounter = 1;
|
|
51
106
|
var FastMockStateImpl = class {
|
|
52
107
|
constructor(owner) {
|
|
53
|
-
this.owner = owner;
|
|
54
108
|
this.recordedCalls = [];
|
|
55
109
|
this.recordedContexts = [];
|
|
56
110
|
this.recordedInstances = [];
|
|
57
111
|
this.recordedOrder = [];
|
|
58
112
|
this.recordedResults = [];
|
|
59
113
|
this.recordedSettledResults = [];
|
|
114
|
+
this.#owner = owner;
|
|
60
115
|
}
|
|
116
|
+
#owner;
|
|
61
117
|
get calls() {
|
|
62
|
-
syncEpochs(this
|
|
118
|
+
syncEpochs(this.#owner);
|
|
63
119
|
return this.recordedCalls;
|
|
64
120
|
}
|
|
65
121
|
set calls(value) {
|
|
66
122
|
this.recordedCalls = value;
|
|
67
123
|
}
|
|
68
124
|
get contexts() {
|
|
69
|
-
syncEpochs(this
|
|
125
|
+
syncEpochs(this.#owner);
|
|
70
126
|
return this.recordedContexts;
|
|
71
127
|
}
|
|
72
128
|
set contexts(value) {
|
|
73
129
|
this.recordedContexts = value;
|
|
74
130
|
}
|
|
75
131
|
get instances() {
|
|
76
|
-
syncEpochs(this
|
|
132
|
+
syncEpochs(this.#owner);
|
|
77
133
|
return this.recordedInstances;
|
|
78
134
|
}
|
|
79
135
|
set instances(value) {
|
|
80
136
|
this.recordedInstances = value;
|
|
81
137
|
}
|
|
82
138
|
get invocationCallOrder() {
|
|
83
|
-
syncEpochs(this
|
|
139
|
+
syncEpochs(this.#owner);
|
|
84
140
|
return this.recordedOrder;
|
|
85
141
|
}
|
|
86
142
|
set invocationCallOrder(value) {
|
|
87
143
|
this.recordedOrder = value;
|
|
88
144
|
}
|
|
89
145
|
get results() {
|
|
90
|
-
syncEpochs(this
|
|
146
|
+
syncEpochs(this.#owner);
|
|
91
147
|
return this.recordedResults;
|
|
92
148
|
}
|
|
93
149
|
set results(value) {
|
|
94
150
|
this.recordedResults = value;
|
|
95
151
|
}
|
|
96
152
|
get settledResults() {
|
|
97
|
-
syncEpochs(this
|
|
153
|
+
syncEpochs(this.#owner);
|
|
98
154
|
return this.recordedSettledResults;
|
|
99
155
|
}
|
|
100
156
|
set settledResults(value) {
|
|
@@ -153,6 +209,12 @@ function definePrototypeMember(key, value) {
|
|
|
153
209
|
}
|
|
154
210
|
definePrototypeMember(FAST_SPY_BRAND, true);
|
|
155
211
|
definePrototypeMember("_isMockFunction", true);
|
|
212
|
+
function shareFastSpyHelpers(helpers) {
|
|
213
|
+
for (const key of Object.keys(helpers)) {
|
|
214
|
+
definePrototypeMember(key, helpers[key]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
setSharedHelperSink(shareFastSpyHelpers);
|
|
156
218
|
Object.defineProperty(FAST_SPY_PROTOTYPE, "mock", {
|
|
157
219
|
get() {
|
|
158
220
|
const spy = self(this);
|
|
@@ -375,6 +437,33 @@ function createFastSpy(implementation, name) {
|
|
|
375
437
|
return spy;
|
|
376
438
|
}
|
|
377
439
|
|
|
440
|
+
// src/lib/redefine-failure.ts
|
|
441
|
+
var CANNOT_REDEFINE = "Cannot redefine property";
|
|
442
|
+
function isCannotRedefine(error) {
|
|
443
|
+
return error instanceof TypeError && error.message.includes(CANNOT_REDEFINE);
|
|
444
|
+
}
|
|
445
|
+
function describeSpyTarget(target) {
|
|
446
|
+
if (Reflect.get(target, Symbol.toStringTag) === "Module") {
|
|
447
|
+
return "an ES module namespace";
|
|
448
|
+
}
|
|
449
|
+
if (Object.isFrozen(target)) {
|
|
450
|
+
return "a frozen object";
|
|
451
|
+
}
|
|
452
|
+
const constructor = Reflect.get(target, "constructor");
|
|
453
|
+
const name = typeof constructor === "function" ? constructor.name : void 0;
|
|
454
|
+
return name === void 0 || name === "Object" ? "a plain object" : `an instance of ${name}`;
|
|
455
|
+
}
|
|
456
|
+
var REDEFINE_ADVICE = "An ES module namespace is what a bundler leaves behind once it has inlined a barrel or a workspace alias (`@angular/build:unit-test`, a pre-bundled `vite-node` entry): the export is a live binding, not a writable property, and no spy library \u2014 this one, `vi.spyOn`, `jest.spyOn` \u2014 can replace it. `vi.mock()` of the same module is the silent version of this failure, not the fix.\nGive the code under test a real seam and spy on that: inject the dependency, pass it in as an argument, or reach it through a class or object your own code owns.";
|
|
457
|
+
function redefineFailure(lead, target, cause) {
|
|
458
|
+
return new Error(
|
|
459
|
+
withDocs(`[vitest-auto-spy] ${lead} The target is ${describeSpyTarget(target)}.
|
|
460
|
+
${REDEFINE_ADVICE}`, DOCS_LINKS.realSeam),
|
|
461
|
+
{
|
|
462
|
+
cause
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
378
467
|
// src/lib/redefine-accessor-spy.ts
|
|
379
468
|
function spyOnAccessorByRedefine(createMockFn, target, property, type) {
|
|
380
469
|
const existing = Object.getOwnPropertyDescriptor(target, property);
|
|
@@ -395,6 +484,27 @@ function spyOnAccessorByRedefine(createMockFn, target, property, type) {
|
|
|
395
484
|
Object.defineProperty(target, property, descriptor);
|
|
396
485
|
return mock;
|
|
397
486
|
}
|
|
487
|
+
function spyOrExplain(spy, target, property, accessor) {
|
|
488
|
+
try {
|
|
489
|
+
return spy();
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (isCannotRedefine(error)) {
|
|
492
|
+
throw redefineFailure(
|
|
493
|
+
`Cannot spy on the '${accessor}' accessor of '${property}': the property is not configurable, so it cannot be redefined.`,
|
|
494
|
+
target,
|
|
495
|
+
error
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function guardAccessorSpies(adapter) {
|
|
502
|
+
return {
|
|
503
|
+
...adapter,
|
|
504
|
+
spyOnGetter: (target, property) => spyOrExplain(() => adapter.spyOnGetter(target, property), target, property, "get"),
|
|
505
|
+
spyOnSetter: (target, property) => spyOrExplain(() => adapter.spyOnSetter(target, property), target, property, "set")
|
|
506
|
+
};
|
|
507
|
+
}
|
|
398
508
|
|
|
399
509
|
// src/lib/vitest-adapter.ts
|
|
400
510
|
function asVitestMock(mock) {
|
|
@@ -462,33 +572,6 @@ function useVitestAdapter() {
|
|
|
462
572
|
registerMockAdapter(vitestMockAdapter);
|
|
463
573
|
}
|
|
464
574
|
|
|
465
|
-
// src/lib/docs-links.ts
|
|
466
|
-
var DOCS = "https://asdalexey.github.io/vitest-auto-spy";
|
|
467
|
-
var DOCS_LINKS = {
|
|
468
|
-
angular: `${DOCS}/adapters/angular`,
|
|
469
|
-
// Their own pages rather than anchors on `adapters/angular`: a reader who hits one of these arrived
|
|
470
|
-
// from a failure, not from reading, and the page they want is the one about that check — not the
|
|
471
|
-
// one about the adapter that hosts it.
|
|
472
|
-
angularDiagnostics: `${DOCS}/adapters/angular-diagnostics`,
|
|
473
|
-
angularOverrides: `${DOCS}/adapters/angular-overrides`,
|
|
474
|
-
createSpyFromClass: `${DOCS}/core/create-spy-from-class`,
|
|
475
|
-
controlHelpers: `${DOCS}/core/control-helpers`,
|
|
476
|
-
// The recipe for the one failure no spy library can work around: a binding the bundler already
|
|
477
|
-
// inlined. Deep-linked to the section rather than the page, because the page's first half is
|
|
478
|
-
// about the *silent* half of the same problem and the reader arriving here has the loud one.
|
|
479
|
-
realSeam: `${DOCS}/utilities/module-mocks#provide-a-real-seam`,
|
|
480
|
-
setup: `${DOCS}/utilities/setup`,
|
|
481
|
-
// Its own page rather than a section of the factory's: the reader arriving here was thrown at by a
|
|
482
|
-
// double they configured somewhere else entirely, and the question they have is what counts as
|
|
483
|
-
// configured — which is the whole page, not a paragraph of another one.
|
|
484
|
-
strictMode: `${DOCS}/core/strict-mode`,
|
|
485
|
-
trackInjections: `${DOCS}/utilities/track-injections`
|
|
486
|
-
};
|
|
487
|
-
function withDocs(message, link) {
|
|
488
|
-
return `${message}
|
|
489
|
-
Docs: ${link}`;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
575
|
// src/lib/serialize-args.ts
|
|
493
576
|
function createContext() {
|
|
494
577
|
return { seen: /* @__PURE__ */ new WeakSet(), cache: /* @__PURE__ */ new Map(), circularHits: 0 };
|
|
@@ -851,19 +934,6 @@ Actual: ${actualCall(functionName, actualArgs)}`;
|
|
|
851
934
|
})
|
|
852
935
|
};
|
|
853
936
|
|
|
854
|
-
// src/lib/spy-decoration.ts
|
|
855
|
-
function detachedHelperError(helper) {
|
|
856
|
-
return new Error(
|
|
857
|
-
withDocs(
|
|
858
|
-
`[vitest-auto-spy] ${helper} was called off its spy: \`const { ${helper} } = spy.method\` loses the spy it configures. Call it as a method \u2014 spy.method.${helper}(\u2026) \u2014 or bind it first.`,
|
|
859
|
-
DOCS_LINKS.controlHelpers
|
|
860
|
-
)
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
function decorate(target, helpers) {
|
|
864
|
-
return Object.assign(target, helpers);
|
|
865
|
-
}
|
|
866
|
-
|
|
867
937
|
// src/lib/promise-spy.ts
|
|
868
938
|
function toResolvedPerCallValues(valueConfigsPerCall) {
|
|
869
939
|
return valueConfigsPerCall.map(
|
|
@@ -1077,13 +1147,25 @@ function ensureCalledWithObject(state, chain) {
|
|
|
1077
1147
|
return created;
|
|
1078
1148
|
}
|
|
1079
1149
|
var FunctionSpyInternals = class {
|
|
1150
|
+
/** Built on the first stream helper, not on every spy — see {@link ObservableSupport.streamForFunctionSpy}. */
|
|
1151
|
+
#observable = void 0;
|
|
1080
1152
|
constructor(state, valueContainer, host, dispatch, recorder) {
|
|
1081
1153
|
this.state = state;
|
|
1082
1154
|
this.valueContainer = valueContainer;
|
|
1083
1155
|
this.host = host;
|
|
1084
1156
|
this.dispatch = dispatch;
|
|
1085
1157
|
this.recorder = recorder;
|
|
1086
|
-
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* The rxjs layer's state for this spy, materialised on first use.
|
|
1161
|
+
*
|
|
1162
|
+
* Reaching it means a stream helper is running, which means the `/rxjs` entry is loaded — so this
|
|
1163
|
+
* requires the support rather than testing for it, and a spy that never sees a stream helper never
|
|
1164
|
+
* pays for the object.
|
|
1165
|
+
*/
|
|
1166
|
+
get observable() {
|
|
1167
|
+
this.#observable ??= requireObservableSupport().streamForFunctionSpy(this.valueContainer);
|
|
1168
|
+
return this.#observable;
|
|
1087
1169
|
}
|
|
1088
1170
|
/**
|
|
1089
1171
|
* `resetAutoSpy` reverts this spy's configuration; the state lives here, where the host runner's
|
|
@@ -1098,7 +1180,7 @@ var FunctionSpyInternals = class {
|
|
|
1098
1180
|
delete valueContainer._isRejectedPromise;
|
|
1099
1181
|
delete valueContainer._isThrown;
|
|
1100
1182
|
delete valueContainer.valuesPerCalls;
|
|
1101
|
-
this
|
|
1183
|
+
this.#observable?.reset();
|
|
1102
1184
|
getMockAdapter().restoreImplementation(this.host, this.dispatch);
|
|
1103
1185
|
}
|
|
1104
1186
|
/** Empties the polyfilled `settledResults` on `clearAutoSpy` / `resetAutoSpy` (a no-op on Vitest, where the host clears its native array). */
|
|
@@ -1150,8 +1232,8 @@ function createFunctionSpy(name, unstubbed) {
|
|
|
1150
1232
|
const recorder = installSettledResultsPolyfill(functionSpy);
|
|
1151
1233
|
settledResultsRecorder = recorder.record;
|
|
1152
1234
|
const internals = new FunctionSpyInternals(state, valueContainer, functionSpy, dispatch, recorder);
|
|
1153
|
-
const spy =
|
|
1154
|
-
|
|
1235
|
+
const spy = attachHelpers(functionSpy, SPY_HELPERS);
|
|
1236
|
+
getObservableSupport()?.addToFunctionSpy(spy);
|
|
1155
1237
|
getJasmineSupport()?.addToFunctionSpy(spy, {
|
|
1156
1238
|
name,
|
|
1157
1239
|
restoreDispatch: () => {
|
|
@@ -1225,18 +1307,6 @@ function readStoredAccessor(store, key, receiver) {
|
|
|
1225
1307
|
}
|
|
1226
1308
|
return accessor.get?.call(receiver);
|
|
1227
1309
|
}
|
|
1228
|
-
function storeWriteTraps(store) {
|
|
1229
|
-
return {
|
|
1230
|
-
set(_target, key, value, receiver) {
|
|
1231
|
-
if (!writeStoredAccessor(store, key, value, receiver)) {
|
|
1232
|
-
writeStoredValue(store, key, value);
|
|
1233
|
-
}
|
|
1234
|
-
return true;
|
|
1235
|
-
},
|
|
1236
|
-
defineProperty: (_target, key, descriptor) => storeDefinedProp(store, key, descriptor),
|
|
1237
|
-
deleteProperty: (_target, key) => dropStoredProp(store, key)
|
|
1238
|
-
};
|
|
1239
|
-
}
|
|
1240
1310
|
var NOT_STORED = /* @__PURE__ */ Symbol("vitest-auto-spy.notStored");
|
|
1241
1311
|
var PROTOCOL_KEYS = /* @__PURE__ */ new Set(["schedule", "lift", "@@observable", "getReader"]);
|
|
1242
1312
|
function isProtocolKey(key) {
|
|
@@ -1301,7 +1371,8 @@ function attachDispose(spy) {
|
|
|
1301
1371
|
// src/lib/auto-mock.ts
|
|
1302
1372
|
function createAutoMock(overrides, config) {
|
|
1303
1373
|
const unstubbed = resolveUnstubbedGuard(void 0, { strict: config?.strict, onUnstubbedCall: config?.onUnstubbedCall });
|
|
1304
|
-
const
|
|
1374
|
+
const target = { [INTERNALS]: { store: createProxyPropStore(overrides ?? {}), unstubbed } };
|
|
1375
|
+
const mock = new Proxy(target, AUTO_MOCK_HANDLER);
|
|
1305
1376
|
applyObservableProps(mock, config?.observablePropsToSpyOn);
|
|
1306
1377
|
applyMockReturns(mock, config?.returns);
|
|
1307
1378
|
return mock;
|
|
@@ -1340,20 +1411,35 @@ function applyMockReturns(mock, returns) {
|
|
|
1340
1411
|
adapter.restoreImplementation(spy, () => value);
|
|
1341
1412
|
}
|
|
1342
1413
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
return
|
|
1346
|
-
get: (_target, key, receiver) => readKey(store, key, receiver, unstubbed),
|
|
1347
|
-
...storeWriteTraps(store),
|
|
1348
|
-
has(_target, key) {
|
|
1349
|
-
return key === AUTO_SPY_MARK || key === DISPOSE || hasStoredProp(store, key);
|
|
1350
|
-
},
|
|
1351
|
-
ownKeys() {
|
|
1352
|
-
return [.../* @__PURE__ */ new Set([...store.values.keys(), ...store.accessors.keys()])];
|
|
1353
|
-
},
|
|
1354
|
-
getOwnPropertyDescriptor: (_target, key) => describeStoredProp(store, key)
|
|
1355
|
-
};
|
|
1414
|
+
var INTERNALS = /* @__PURE__ */ Symbol("vitest-auto-spy.autoMock.internals");
|
|
1415
|
+
function internalsOf2(target) {
|
|
1416
|
+
return Reflect.get(target, INTERNALS);
|
|
1356
1417
|
}
|
|
1418
|
+
var AUTO_MOCK_HANDLER = {
|
|
1419
|
+
get(target, key, receiver) {
|
|
1420
|
+
const { store, unstubbed } = internalsOf2(target);
|
|
1421
|
+
return readKey(store, key, receiver, unstubbed);
|
|
1422
|
+
},
|
|
1423
|
+
// The traps that route every write into the store — see `proxy-props.ts` for why their absence
|
|
1424
|
+
// was silent rather than loud.
|
|
1425
|
+
set(target, key, value, receiver) {
|
|
1426
|
+
const { store } = internalsOf2(target);
|
|
1427
|
+
if (!writeStoredAccessor(store, key, value, receiver)) {
|
|
1428
|
+
writeStoredValue(store, key, value);
|
|
1429
|
+
}
|
|
1430
|
+
return true;
|
|
1431
|
+
},
|
|
1432
|
+
defineProperty: (target, key, descriptor) => storeDefinedProp(internalsOf2(target).store, key, descriptor),
|
|
1433
|
+
deleteProperty: (target, key) => dropStoredProp(internalsOf2(target).store, key),
|
|
1434
|
+
has(target, key) {
|
|
1435
|
+
return key === AUTO_SPY_MARK || key === DISPOSE || hasStoredProp(internalsOf2(target).store, key);
|
|
1436
|
+
},
|
|
1437
|
+
ownKeys(target) {
|
|
1438
|
+
const { store } = internalsOf2(target);
|
|
1439
|
+
return [.../* @__PURE__ */ new Set([...store.values.keys(), ...store.accessors.keys()])];
|
|
1440
|
+
},
|
|
1441
|
+
getOwnPropertyDescriptor: (target, key) => describeStoredProp(internalsOf2(target).store, key)
|
|
1442
|
+
};
|
|
1357
1443
|
function readKey(store, key, receiver, unstubbed) {
|
|
1358
1444
|
const patched = readStoredAccessor(store, key, receiver);
|
|
1359
1445
|
if (patched !== NOT_STORED) {
|
|
@@ -1375,15 +1461,13 @@ function readKey(store, key, receiver, unstubbed) {
|
|
|
1375
1461
|
store.values.set(key, spy);
|
|
1376
1462
|
return spy;
|
|
1377
1463
|
}
|
|
1464
|
+
var NOOP_GETTER = function noopGetter() {
|
|
1465
|
+
return void 0;
|
|
1466
|
+
};
|
|
1467
|
+
var NOOP_SETTER = function noopSetter(_value) {
|
|
1468
|
+
};
|
|
1378
1469
|
function defineWithEmptyAccessors(obj, prop) {
|
|
1379
|
-
Object.defineProperty(obj, prop, {
|
|
1380
|
-
get() {
|
|
1381
|
-
return void 0;
|
|
1382
|
-
},
|
|
1383
|
-
set(_value) {
|
|
1384
|
-
},
|
|
1385
|
-
configurable: true
|
|
1386
|
-
});
|
|
1470
|
+
Object.defineProperty(obj, prop, { get: NOOP_GETTER, set: NOOP_SETTER, configurable: true });
|
|
1387
1471
|
}
|
|
1388
1472
|
function spyOnAccessor(autoSpy, accessorName, accessorType) {
|
|
1389
1473
|
const adapter = getMockAdapter();
|
|
@@ -1781,35 +1865,6 @@ function hasNothingToRead(ObjectClass, accessors, config) {
|
|
|
1781
1865
|
// conflict: they ask for names to be present, which the proxy already guarantees.
|
|
1782
1866
|
config.onlyMethodsToSpyOn.length === 0;
|
|
1783
1867
|
}
|
|
1784
|
-
|
|
1785
|
-
// src/lib/redefine-failure.ts
|
|
1786
|
-
var CANNOT_REDEFINE = "Cannot redefine property";
|
|
1787
|
-
function isCannotRedefine(error) {
|
|
1788
|
-
return error instanceof TypeError && error.message.includes(CANNOT_REDEFINE);
|
|
1789
|
-
}
|
|
1790
|
-
function describeSpyTarget(target) {
|
|
1791
|
-
if (Reflect.get(target, Symbol.toStringTag) === "Module") {
|
|
1792
|
-
return "an ES module namespace";
|
|
1793
|
-
}
|
|
1794
|
-
if (Object.isFrozen(target)) {
|
|
1795
|
-
return "a frozen object";
|
|
1796
|
-
}
|
|
1797
|
-
const constructor = Reflect.get(target, "constructor");
|
|
1798
|
-
const name = typeof constructor === "function" ? constructor.name : void 0;
|
|
1799
|
-
return name === void 0 || name === "Object" ? "a plain object" : `an instance of ${name}`;
|
|
1800
|
-
}
|
|
1801
|
-
var REDEFINE_ADVICE = "An ES module namespace is what a bundler leaves behind once it has inlined a barrel or a workspace alias (`@angular/build:unit-test`, a pre-bundled `vite-node` entry): the export is a live binding, not a writable property, and no spy library \u2014 this one, `vi.spyOn`, `jest.spyOn` \u2014 can replace it. `vi.mock()` of the same module is the silent version of this failure, not the fix.\nGive the code under test a real seam and spy on that: inject the dependency, pass it in as an argument, or reach it through a class or object your own code owns.";
|
|
1802
|
-
function redefineFailure(lead, target, cause) {
|
|
1803
|
-
return new Error(
|
|
1804
|
-
withDocs(`[vitest-auto-spy] ${lead} The target is ${describeSpyTarget(target)}.
|
|
1805
|
-
${REDEFINE_ADVICE}`, DOCS_LINKS.realSeam),
|
|
1806
|
-
{
|
|
1807
|
-
cause
|
|
1808
|
-
}
|
|
1809
|
-
);
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
// src/lib/prop-mock.ts
|
|
1813
1868
|
var sharedEpoch;
|
|
1814
1869
|
function propEpoch() {
|
|
1815
1870
|
return sharedEpoch ??= globalThis.__vitestAutoSpyPropEpoch__ ??= { current: 0 };
|
|
@@ -2262,8 +2317,9 @@ function readProperty(value, key) {
|
|
|
2262
2317
|
return Reflect.get(value, key);
|
|
2263
2318
|
}
|
|
2264
2319
|
function isEmptyList(value) {
|
|
2265
|
-
return value === void 0 || Array.isArray(value) && value.
|
|
2320
|
+
return value === void 0 || Array.isArray(value) && value.every((entry) => Array.isArray(entry) && isEmptyList(entry));
|
|
2266
2321
|
}
|
|
2322
|
+
var deadModuleVerdicts = /* @__PURE__ */ new WeakMap();
|
|
2267
2323
|
function hasEmptyRuntimeScope(module) {
|
|
2268
2324
|
const definition = readProperty(module, "\u0275mod");
|
|
2269
2325
|
if (definition === void 0) {
|
|
@@ -2272,11 +2328,18 @@ function hasEmptyRuntimeScope(module) {
|
|
|
2272
2328
|
return isEmptyList(readProperty(definition, "declarations")) && isEmptyList(readProperty(definition, "exports"));
|
|
2273
2329
|
}
|
|
2274
2330
|
function isDeadNgModuleImport(module) {
|
|
2275
|
-
|
|
2331
|
+
const definition = readProperty(module, "\u0275mod");
|
|
2332
|
+
if (typeof definition !== "object" || definition === null) {
|
|
2276
2333
|
return false;
|
|
2277
2334
|
}
|
|
2335
|
+
const cached = deadModuleVerdicts.get(definition);
|
|
2336
|
+
if (cached !== void 0) {
|
|
2337
|
+
return cached;
|
|
2338
|
+
}
|
|
2278
2339
|
const injector = readProperty(module, "\u0275inj");
|
|
2279
|
-
|
|
2340
|
+
const dead = isEmptyList(readProperty(definition, "declarations")) && isEmptyList(readProperty(definition, "exports")) && isEmptyList(readProperty(injector, "providers")) && isEmptyList(readProperty(injector, "imports"));
|
|
2341
|
+
deadModuleVerdicts.set(definition, dead);
|
|
2342
|
+
return dead;
|
|
2280
2343
|
}
|
|
2281
2344
|
function moduleName(module) {
|
|
2282
2345
|
const name = readProperty(module, "name");
|
|
@@ -2388,17 +2451,20 @@ Drop the \`schemas\` entry, then put the missing directive, component or pipe in
|
|
|
2388
2451
|
);
|
|
2389
2452
|
}
|
|
2390
2453
|
var HTTP_TESTING_CONTROLLER = "HttpTestingController";
|
|
2391
|
-
function
|
|
2454
|
+
function forEachProvider(value, visit) {
|
|
2392
2455
|
if (Array.isArray(value)) {
|
|
2393
|
-
value.forEach((entry) =>
|
|
2456
|
+
value.forEach((entry) => forEachProvider(entry, visit));
|
|
2394
2457
|
return;
|
|
2395
2458
|
}
|
|
2396
2459
|
const wrapped = readProperty(value, "\u0275providers");
|
|
2397
2460
|
if (wrapped === void 0) {
|
|
2398
|
-
|
|
2461
|
+
visit(value);
|
|
2399
2462
|
return;
|
|
2400
2463
|
}
|
|
2401
|
-
|
|
2464
|
+
forEachProvider(wrapped, visit);
|
|
2465
|
+
}
|
|
2466
|
+
function flattenProviders(value, into) {
|
|
2467
|
+
forEachProvider(value, (provider) => into.push(provider));
|
|
2402
2468
|
}
|
|
2403
2469
|
function findControllerToken(providers) {
|
|
2404
2470
|
const flat = [];
|
|
@@ -2472,16 +2538,15 @@ Flush each one (\`controller.expectOne('/url').flush(body)\`), or call \`control
|
|
|
2472
2538
|
);
|
|
2473
2539
|
}
|
|
2474
2540
|
var moduleDoubles = /* @__PURE__ */ new Map();
|
|
2541
|
+
function rememberModuleDouble(provider) {
|
|
2542
|
+
const token = readProperty(provider, "provide");
|
|
2543
|
+
const useValue = readProperty(provider, "useValue");
|
|
2544
|
+
if (token !== void 0 && isAutoSpyLike(useValue) && readProperty(provider, "multi") !== true) {
|
|
2545
|
+
moduleDoubles.set(token, useValue);
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2475
2548
|
function collectModuleDoubles(config) {
|
|
2476
|
-
|
|
2477
|
-
flattenProviders(readProperty(config, "providers"), flat);
|
|
2478
|
-
flat.forEach((provider) => {
|
|
2479
|
-
const token = readProperty(provider, "provide");
|
|
2480
|
-
const useValue = readProperty(provider, "useValue");
|
|
2481
|
-
if (token !== void 0 && isAutoSpyLike(useValue) && readProperty(provider, "multi") !== true) {
|
|
2482
|
-
moduleDoubles.set(token, useValue);
|
|
2483
|
-
}
|
|
2484
|
-
});
|
|
2549
|
+
forEachProvider(readProperty(config, "providers"), rememberModuleDouble);
|
|
2485
2550
|
}
|
|
2486
2551
|
function tokenName(token) {
|
|
2487
2552
|
const name = readProperty(token, "name");
|
|
@@ -2747,27 +2812,44 @@ function createWithAutoSpies(target, options = {}) {
|
|
|
2747
2812
|
}
|
|
2748
2813
|
};
|
|
2749
2814
|
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2815
|
+
var PERMISSIVE_SCHEMAS = [NO_ERRORS_SCHEMA];
|
|
2816
|
+
var NOTHING = [];
|
|
2817
|
+
function isStandalone3(definition) {
|
|
2752
2818
|
return typeof definition === "object" && definition !== null && Reflect.get(definition, "standalone") === true;
|
|
2753
2819
|
}
|
|
2754
|
-
function
|
|
2820
|
+
function importsOf(definition) {
|
|
2821
|
+
const dependencies = Reflect.get(definition, "dependencies");
|
|
2822
|
+
return dependencies();
|
|
2823
|
+
}
|
|
2824
|
+
function isChildComponent(dependency) {
|
|
2825
|
+
return Reflect.get(dependency, "\u0275cmp") !== void 0;
|
|
2826
|
+
}
|
|
2827
|
+
function keptScope(definition, options) {
|
|
2828
|
+
const kept = importsOf(definition).filter((dependency) => !isChildComponent(dependency));
|
|
2829
|
+
kept.push(...options.keepChildren ?? NOTHING);
|
|
2830
|
+
return kept;
|
|
2831
|
+
}
|
|
2832
|
+
function buildOverride(definition, options) {
|
|
2755
2833
|
const override = {};
|
|
2756
|
-
if (isStandalone3(
|
|
2757
|
-
override.imports = options.keepChildren ??
|
|
2758
|
-
override.schemas =
|
|
2834
|
+
if (isStandalone3(definition)) {
|
|
2835
|
+
override.imports = options.keepTemplate ? keptScope(definition, options) : options.keepChildren ?? NOTHING;
|
|
2836
|
+
override.schemas = PERMISSIVE_SCHEMAS;
|
|
2759
2837
|
}
|
|
2760
2838
|
if (!options.keepTemplate) {
|
|
2761
2839
|
override.template = options.template ?? "";
|
|
2762
|
-
override.styles =
|
|
2840
|
+
override.styles = NOTHING;
|
|
2763
2841
|
}
|
|
2764
2842
|
return override;
|
|
2765
2843
|
}
|
|
2766
2844
|
function applyInputs(fixture, inputs) {
|
|
2767
|
-
|
|
2845
|
+
if (inputs === void 0) {
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
Object.entries(inputs).forEach(([name, value]) => fixture.componentRef.setInput(name, value));
|
|
2768
2849
|
}
|
|
2769
2850
|
function renderShallow(component, options = {}) {
|
|
2770
|
-
const
|
|
2851
|
+
const definition = Reflect.get(component, "\u0275cmp");
|
|
2852
|
+
const standalone = isStandalone3(definition);
|
|
2771
2853
|
TestBed.configureTestingModule({
|
|
2772
2854
|
imports: standalone ? [component, ...options.imports ?? []] : options.imports ?? [],
|
|
2773
2855
|
declarations: standalone ? [] : [component],
|
|
@@ -2775,9 +2857,9 @@ function renderShallow(component, options = {}) {
|
|
|
2775
2857
|
// Only where it can do something. A standalone component carries its own dependency scope, so a
|
|
2776
2858
|
// module-level schema never reaches its template — and `enableAngularDiagnostics({ deadSchemas })`
|
|
2777
2859
|
// is right to report one, which made these two features of the same package cancel each other out.
|
|
2778
|
-
...standalone ? {} : { schemas:
|
|
2860
|
+
...standalone ? {} : { schemas: PERMISSIVE_SCHEMAS }
|
|
2779
2861
|
});
|
|
2780
|
-
TestBed.overrideComponent(component, { set: buildOverride(
|
|
2862
|
+
TestBed.overrideComponent(component, { set: buildOverride(definition, options) });
|
|
2781
2863
|
options.beforeCreate?.();
|
|
2782
2864
|
const fixture = TestBed.createComponent(component);
|
|
2783
2865
|
applyInputs(fixture, options.inputs);
|
package/dist/bun-angular.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithObservable, c as AddCalledWithPromise, d as AddCalledWithSpyMethods, e as AddObservableSpyMethods, f as AddPromiseSpyMethods, g as AddSpyMethodsByReturnTypes, h as AddThrowHelper, i as AddVoidReturnHelpers, j as AutoSpyRxjsTypes, k as ClassSpyConfiguration, C as ClassType, l as CompleteValueConfig, D as DeepMockProxy, m as DeepPartial, E as ErrorValueConfig, F as Func, M as MethodReturns, n as Mutable, N as NextValueConfig, O as ObservableLike, o as OnlyMethodKeysOf, p as OnlyObservablePropsOf, q as OnlyPropsOf, r as Overload, s as OverloadChoice, t as Overloads, P as PropStubValue, S as Spy, u as SpyDisposable, v as SpyOptions, w as StrictSpyConfiguration, x as SubjectLike, y as SubjectOf, U as UnstubbedCall, z as UnstubbedCallHandler, V as ValueConfig, B as ValueConfigPerCall, W as WithMockReturnValue } from './types-DTi4dIeN.js';
|
|
2
|
-
export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, clearAutoSpyDefaults, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, createSpyFromInstance, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, registerAutoSpyDefaults, resetAutoSpy, restoreSpiedInstance, settleDynamicImport, stubConstructor, withOverrides } from './bun.js';
|
|
2
|
+
export { ArgCaptor, AsInstances, AssertMockedOptions, AutoSpyDefaultEntry, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, clearAutoSpyDefaults, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, createSpyFromInstance, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, registerAutoSpyDefaults, resetAutoSpy, restoreSpiedInstance, settleDynamicImport, stubConstructor, withOverrides } from './bun.js';
|
|
3
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-DYtyyKM5.js';
|
|
4
4
|
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-DmM-rPcG.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-DM1AWQV2.js';
|
|
7
7
|
import 'vitest';
|
|
8
8
|
import '@angular/core';
|
|
9
9
|
import '@angular/core/testing';
|