vitest-auto-spy 1.9.2 → 1.9.3

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/dist/angular.cjs CHANGED
@@ -1 +1,565 @@
1
- 'use strict';var vitest=require('vitest'),testing=require('@angular/core/testing');var m;function w(e){m=e;}var L="No mock adapter registered. Import a runtime entry once before creating spies \u2014 'vitest-auto-spy' (default, Vitest) or a runtime variant such as 'vitest-auto-spy/bun'.";function u(){if(!m)throw new Error(L);return m}var h={createMockFn(e,t){let n=e?vitest.vi.fn(e):vitest.vi.fn();return t!==void 0&&n.mockName(t),n},spyOnGetter(e,t){return vitest.vi.spyOn(e,t,"get")},spyOnSetter(e,t){return vitest.vi.spyOn(e,t,"set")},getCalls(e){return e.mock.calls},reset(e){e.mockReset();},clear(e){e.mockClear();},restoreImplementation(e,t){e.mockImplementation(t);}};var N=Symbol.for("vitest-auto-spy.mock"),U=Symbol.for("vitest-auto-spy.resetConfig"),q=Symbol.for("vitest-auto-spy.clearHook");function y(e){Object.defineProperty(e,N,{value:true,enumerable:false,configurable:true});}function T(e,t){Object.defineProperty(e,U,{value:t,enumerable:false,configurable:true});}function v(e,t){Object.defineProperty(e,q,{value:t,enumerable:false,configurable:true});}function j(e,t){Object.defineProperty(e,t,{get(){},set(n){},configurable:true});}function M(e,t,n){let r=u(),o=n==="setter"?r.spyOnSetter(e,t):r.spyOnGetter(e,t);return y(o),o}function C(e,t,n){let r={getters:{},setters:{}};e.accessorSpies=r,t.forEach(o=>{j(e,o),r.getters[o]=M(e,o,"getter");}),n.forEach(o=>{Object.prototype.hasOwnProperty.call(e,o)||j(e,o),r.setters[o]=M(e,o,"setter");});}function Y(e){return `'${e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function J(e,t){return Object.entries(e).map(([n,r])=>`${n}:${i(r,t)}`).join(",")}function X(e,t){return `new Map([${[...e.entries()].map(([r,o])=>`[${i(r,t)},${i(o,t)}]`).join(",")}])`}function Q(e,t){if(t.has(e))return "[Circular]";t.add(e);let n;return e instanceof Date?n=`new Date(${e.getTime()})`:e instanceof Map?n=X(e,t):e instanceof Set?n=`new Set([${[...e].map(r=>i(r,t)).join(",")}])`:Array.isArray(e)?n=`[${e.map(r=>i(r,t)).join(",")}]`:n=`{${J(e,t)}}`,t.delete(e),n}function g(e){return typeof e=="string"?Y(e):typeof e=="bigint"?`${e}n`:typeof e=="symbol"?e.toString():typeof e=="function"?`[Function: ${e.name}]`:Object.is(e,-0)?"-0":String(e)}function O(e){return typeof e=="object"&&e!==null}function i(e,t=new WeakSet){return typeof e=="object"&&e!==null?Q(e,t):g(e)}function R(e){return typeof e=="object"&&e!==null&&"asymmetricMatch"in e&&typeof e.asymmetricMatch=="function"}function Z(e){return e.some(R)}var l=class{#t=Object.create(null);#n=[];set(t,n){if(Array.isArray(t)&&Z(t)){this.#n.push({args:t,value:n});return}this.#t[this.#e(t)]=n;}get(t){let n=this.#e(t);return n in this.#t?this.#t[n]:this.#r(t)}#e(t){return Array.isArray(t)&&!t.some(O)?`[${t.map(n=>g(n)).join(",")}]`:i(t)}#r(t){return Array.isArray(t)?this.#n.find(r=>this.#o(r.args,t))?.value:void 0}#o(t,n){return t.length!==n.length?false:t.every((r,o)=>this.#s(r,n[o]))}#s(t,n){return R(t)?t.asymmetricMatch(n):this.#e([t])===this.#e([n])}};var ee=e=>`The function '${e}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `,te="But the function was called without any arguments.",ne=e=>{let t=i(e);return `But the actual arguments were: ${t.substring(1,t.length-1)}`},A={throwArgumentsError(e,t){let n=e.length===0?te:ne(e);throw new Error(ee(t)+n)}};var re="Observable spies require rxjs. Import 'vitest-auto-spy/rxjs' once (e.g. in your test setup) to enable observablePropsToSpyOn / nextWith / nextWithValues / throwWith / complete / returnSubject.";function P(){throw new Error(re);}function p(e,t){return Object.assign(e,t)}function oe(e){return e.map(t=>({wrappedValue:t.delay===void 0?Promise.resolve(t.value):new Promise(n=>setTimeout(()=>n(t.value),t.delay))}))}function F(e,t){p(e,{resolveWith:n=>{t({value:Promise.resolve(n)});},rejectWith:n=>{t({value:n,_isRejectedPromise:true});},resolveWithPerCall:n=>{n.length!==0&&t({value:void 0,valuesPerCalls:oe(n)});}});}function x(e,t){F(e,n=>{t.value=n.value,t._isRejectedPromise=n._isRejectedPromise??false,t.valuesPerCalls=n.valuesPerCalls??[];});}function V(e,t){F(e,n=>{e.argsToValuesMap.set(t,n);});}var se={record:e=>e,clear:()=>{}};function ie(e){return typeof e!="object"&&typeof e!="function"||e===null?false:typeof Reflect.get(e,"then")=="function"}function E(e){let t=Reflect.get(e,"mock");if(typeof t!="object"||t===null||"settledResults"in t)return se;let n=[];return Object.defineProperty(t,"settledResults",{value:n,enumerable:true,configurable:true,writable:true}),{record(r){let o={type:"incomplete",value:void 0};return n.push(o),ie(r)?r.then(s=>{o.type="fulfilled",o.value=s;},s=>{o.type="rejected",o.value=s;}):(o.type="fulfilled",o.value=r),r},clear(){n.length=0;}}}function ce(e){return typeof e=="object"&&e!==null&&"value"in e}function $(e){if(e._isRejectedPromise)return Promise.reject(e.value);let t=e.valuesPerCalls?.shift();return t?t.wrappedValue:e.value}function W(e,t){let n=e.argsToValuesMap.get(t);return ce(n)?{found:true,value:$(n)}:{found:false,value:void 0}}function ue(e,t,n,r,o){if(e.wasConfigured){let s=W(e,r);if(s.found)return s.value}if(t.wasConfigured){let s=W(t,r);if(s.found)return s.value;A.throwArgumentsError(r,o);}return $(n)}function z(e,t){e.wasConfigured=true;let n=r=>{e.argsToValuesMap.set(t,{value:r});};return p(e,{mockReturnValue:n,returnValue:n}),V(e,t),e}function _(){return {wasConfigured:false,argsToValuesMap:new l}}function H(e){e.wasConfigured=false,e.argsToValuesMap=new l;}function S(e){let t=_(),n=_(),r={value:void 0},o=(...a)=>c.record(ue(t,n,r,a,e)),s=u().createMockFn(o,e),c=E(s);x(s,r);let d=p(s,{calledWith:(...a)=>z(t,a),mustBeCalledWith:(...a)=>z(n,a)});return T(d,()=>{H(t),H(n),r.value=void 0,delete r._isRejectedPromise,delete r.valuesPerCalls,u().restoreImplementation(s,o);}),v(d,()=>c.clear()),y(d),d}var K={methodsToSpyOn:[],observablePropsToSpyOn:[],settersToSpyOn:[],gettersToSpyOn:[],autoSpyAccessors:false,lazySpies:false};function ae(e){let t=Object.getOwnPropertyDescriptors(e);return Object.keys(t).filter(n=>n!=="constructor"&&!t[n]?.get)}function B(e,t){let n=e;for(;n;){let r=Object.getPrototypeOf(n);r&&t(n),n=r;}}var I=new WeakMap;function G(e){let t=I.get(e);if(t)return t;let n=new Set;B(e,o=>ae(o).forEach(s=>n.add(s)));let r=[...n];return I.set(e,r),r}function le(e){let t=new Set,n=new Set;return B(e,r=>{let o=Object.getOwnPropertyDescriptors(r);Object.keys(o).forEach(s=>{s!=="constructor"&&(o[s]?.get&&t.add(s),o[s]?.set&&n.add(s));});}),{getters:[...t],setters:[...n]}}function pe(e,t){if(!t.autoSpyAccessors)return {getters:t.gettersToSpyOn,setters:t.settersToSpyOn};let n=le(e);return {getters:[...new Set([...t.gettersToSpyOn,...n.getters])],setters:[...new Set([...t.settersToSpyOn,...n.setters])]}}function de(e,t){let n=new Set(G(e.prototype)),r=t.filter(o=>!n.has(o));r.length!==0&&console.warn(`[vitest-auto-spy] createSpyFromClass(${e.name}): requested method(s) not found on the class prototype: ${r.join(", ")}. A spy was still created, but the real code will never call it \u2014 check for typos.`);}function fe(e,t){Object.defineProperty(e,t,{configurable:true,enumerable:true,get(){let n=S(t);return Object.defineProperty(e,t,{configurable:true,enumerable:true,writable:true,value:n}),n}});}function ye(e){return e?Array.isArray(e)?{...K,methodsToSpyOn:e}:{methodsToSpyOn:e.methodsToSpyOn??[],observablePropsToSpyOn:e.observablePropsToSpyOn??[],settersToSpyOn:e.settersToSpyOn??[],gettersToSpyOn:e.gettersToSpyOn??[],autoSpyAccessors:e.autoSpyAccessors??false,lazySpies:e.lazySpies??false}:{...K}}function D(e,t){let n=ye(t),r=n.methodsToSpyOn.length>0?n.methodsToSpyOn:G(e.prototype);n.methodsToSpyOn.length>0&&de(e,n.methodsToSpyOn);let o={};n.observablePropsToSpyOn.forEach(c=>{o[c]=P().createPropSpy();});let s=pe(e.prototype,n);return C(o,s.getters,s.setters),r.forEach(c=>{n.lazySpies?fe(o,c):o[c]=S(c);}),o}function ge(e){return e?Array.isArray(e)?{methodsToSpyOn:e,lazySpies:true}:{...e,lazySpies:e.lazySpies??true}:{lazySpies:true}}function ke(e,t){return {provide:e,useValue:D(e,ge(t))}}function be(e){return testing.TestBed.inject(e)}function Se(e,t,n){Object.defineProperty(e,t,{get:()=>n,configurable:true});}function we(e,t,n){Object.defineProperty(e,t,{get:n,configurable:true});}function he(e,t){let n=u();Object.defineProperty(e,t,{get:n.createMockFn(),set:n.createMockFn(),configurable:true});}w(h);exports.injectSpy=be;exports.mockAccessorsProp=he;exports.mockReadonlyProp=Se;exports.mockReadonlyPropGetter=we;exports.provideAutoSpy=ke;
1
+ 'use strict';
2
+
3
+ var vitest = require('vitest');
4
+ var testing = require('@angular/core/testing');
5
+
6
+ // src/lib/mock-adapter.ts
7
+ var registeredAdapter;
8
+ function registerMockAdapter(adapter) {
9
+ registeredAdapter = adapter;
10
+ }
11
+ var MISSING_MOCK_ADAPTER = "No mock adapter registered. Import a runtime entry once before creating spies \u2014 'vitest-auto-spy' (default, Vitest) or a runtime variant such as 'vitest-auto-spy/bun'.";
12
+ function getMockAdapter() {
13
+ if (!registeredAdapter) {
14
+ throw new Error(MISSING_MOCK_ADAPTER);
15
+ }
16
+ return registeredAdapter;
17
+ }
18
+ function asVitestMock(mock) {
19
+ return mock;
20
+ }
21
+ var vitestMockAdapter = {
22
+ createMockFn(implementation, name) {
23
+ const mock = implementation ? vitest.vi.fn(implementation) : vitest.vi.fn();
24
+ if (name !== void 0) {
25
+ mock.mockName(name);
26
+ }
27
+ return mock;
28
+ },
29
+ spyOnGetter(target, property) {
30
+ return vitest.vi.spyOn(target, property, "get");
31
+ },
32
+ spyOnSetter(target, property) {
33
+ return vitest.vi.spyOn(target, property, "set");
34
+ },
35
+ getCalls(mock) {
36
+ return asVitestMock(mock).mock.calls;
37
+ },
38
+ reset(mock) {
39
+ asVitestMock(mock).mockReset();
40
+ },
41
+ clear(mock) {
42
+ asVitestMock(mock).mockClear();
43
+ },
44
+ restoreImplementation(mock, implementation) {
45
+ asVitestMock(mock).mockImplementation(implementation);
46
+ }
47
+ };
48
+
49
+ // src/lib/spy-mark.ts
50
+ var AUTO_SPY_MARK = /* @__PURE__ */ Symbol.for("vitest-auto-spy.mock");
51
+ var RESET_CONFIG = /* @__PURE__ */ Symbol.for("vitest-auto-spy.resetConfig");
52
+ var CLEAR_HOOK = /* @__PURE__ */ Symbol.for("vitest-auto-spy.clearHook");
53
+ function markAsMock(mock) {
54
+ Object.defineProperty(mock, AUTO_SPY_MARK, { value: true, enumerable: false, configurable: true });
55
+ }
56
+ function attachConfigReset(spy, reset) {
57
+ Object.defineProperty(spy, RESET_CONFIG, { value: reset, enumerable: false, configurable: true });
58
+ }
59
+ function attachClearHook(spy, clear) {
60
+ Object.defineProperty(spy, CLEAR_HOOK, { value: clear, enumerable: false, configurable: true });
61
+ }
62
+
63
+ // src/lib/accessor-spy.ts
64
+ function defineWithEmptyAccessors(obj, prop) {
65
+ Object.defineProperty(obj, prop, {
66
+ get() {
67
+ return void 0;
68
+ },
69
+ set(_value) {
70
+ },
71
+ configurable: true
72
+ });
73
+ }
74
+ function spyOnAccessor(autoSpy, accessorName, accessorType) {
75
+ const adapter = getMockAdapter();
76
+ const mock = accessorType === "setter" ? adapter.spyOnSetter(autoSpy, accessorName) : adapter.spyOnGetter(autoSpy, accessorName);
77
+ markAsMock(mock);
78
+ return mock;
79
+ }
80
+ function createAccessorsSpies(autoSpy, gettersToSpyOn, settersToSpyOn) {
81
+ const accessorSpies = { getters: {}, setters: {} };
82
+ autoSpy["accessorSpies"] = accessorSpies;
83
+ gettersToSpyOn.forEach((getterName) => {
84
+ defineWithEmptyAccessors(autoSpy, getterName);
85
+ accessorSpies.getters[getterName] = spyOnAccessor(autoSpy, getterName, "getter");
86
+ });
87
+ settersToSpyOn.forEach((setterName) => {
88
+ if (!Object.prototype.hasOwnProperty.call(autoSpy, setterName)) {
89
+ defineWithEmptyAccessors(autoSpy, setterName);
90
+ }
91
+ accessorSpies.setters[setterName] = spyOnAccessor(autoSpy, setterName, "setter");
92
+ });
93
+ }
94
+
95
+ // src/lib/serialize-args.ts
96
+ function quoteString(value) {
97
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
98
+ }
99
+ function serializeEntries(value, seen) {
100
+ return Object.entries(value).map(([key, entryValue]) => `${key}:${serializeValue(entryValue, seen)}`).join(",");
101
+ }
102
+ function serializeMap(value, seen) {
103
+ const pairs = [...value.entries()].map(([key, entryValue]) => `[${serializeValue(key, seen)},${serializeValue(entryValue, seen)}]`);
104
+ return `new Map([${pairs.join(",")}])`;
105
+ }
106
+ function serializeObject(value, seen) {
107
+ if (seen.has(value)) {
108
+ return "[Circular]";
109
+ }
110
+ seen.add(value);
111
+ let result;
112
+ if (value instanceof Date) {
113
+ result = `new Date(${value.getTime()})`;
114
+ } else if (value instanceof Map) {
115
+ result = serializeMap(value, seen);
116
+ } else if (value instanceof Set) {
117
+ result = `new Set([${[...value].map((item) => serializeValue(item, seen)).join(",")}])`;
118
+ } else if (Array.isArray(value)) {
119
+ result = `[${value.map((item) => serializeValue(item, seen)).join(",")}]`;
120
+ } else {
121
+ result = `{${serializeEntries(value, seen)}}`;
122
+ }
123
+ seen.delete(value);
124
+ return result;
125
+ }
126
+ function serializePrimitive(value) {
127
+ if (typeof value === "string") {
128
+ return quoteString(value);
129
+ }
130
+ if (typeof value === "bigint") {
131
+ return `${value}n`;
132
+ }
133
+ if (typeof value === "symbol") {
134
+ return value.toString();
135
+ }
136
+ if (typeof value === "function") {
137
+ return `[Function: ${value.name}]`;
138
+ }
139
+ if (Object.is(value, -0)) {
140
+ return "-0";
141
+ }
142
+ return String(value);
143
+ }
144
+ function isDeepValue(value) {
145
+ return typeof value === "object" && value !== null;
146
+ }
147
+ function serializeValue(value, seen = /* @__PURE__ */ new WeakSet()) {
148
+ if (typeof value === "object" && value !== null) {
149
+ return serializeObject(value, seen);
150
+ }
151
+ return serializePrimitive(value);
152
+ }
153
+
154
+ // src/lib/args-map.ts
155
+ function isAsymmetricMatcher(value) {
156
+ return typeof value === "object" && value !== null && "asymmetricMatch" in value && typeof value.asymmetricMatch === "function";
157
+ }
158
+ function hasAsymmetricMatcher(args) {
159
+ return args.some(isAsymmetricMatcher);
160
+ }
161
+ var ArgsMap = class {
162
+ // Prototype-less so a `'__proto__'` (or `'constructor'`) serialized key is a
163
+ // plain own property, never walking or polluting the object prototype chain.
164
+ #map = /* @__PURE__ */ Object.create(null);
165
+ #matcherConfigs = [];
166
+ set(key, value) {
167
+ if (Array.isArray(key) && hasAsymmetricMatcher(key)) {
168
+ this.#matcherConfigs.push({ args: key, value });
169
+ return;
170
+ }
171
+ this.#map[this.#serialize(key)] = value;
172
+ }
173
+ get(key) {
174
+ const serialized = this.#serialize(key);
175
+ if (serialized in this.#map) {
176
+ return this.#map[serialized];
177
+ }
178
+ return this.#findByMatcher(key);
179
+ }
180
+ // Keys are always argument arrays; `serializeValue` renders them to a stable,
181
+ // total string (single-quoted strings, bracketed arrays, distinct `undefined`
182
+ // / function / symbol / BigInt / Date renderings, circular-ref safe). Arrays of
183
+ // only primitive args take a fast path that skips the circular-ref bookkeeping.
184
+ #serialize(key) {
185
+ if (Array.isArray(key) && !key.some(isDeepValue)) {
186
+ return `[${key.map((arg) => serializePrimitive(arg)).join(",")}]`;
187
+ }
188
+ return serializeValue(key);
189
+ }
190
+ /** Return the value of the first asymmetric config whose predicate matches the actual args. */
191
+ #findByMatcher(actualArgs) {
192
+ if (!Array.isArray(actualArgs)) {
193
+ return void 0;
194
+ }
195
+ const match = this.#matcherConfigs.find((config) => this.#argsMatch(config.args, actualArgs));
196
+ return match?.value;
197
+ }
198
+ /** Whether every configured arg matches the actual arg at the same position (same length). */
199
+ #argsMatch(configArgs, actualArgs) {
200
+ if (configArgs.length !== actualArgs.length) {
201
+ return false;
202
+ }
203
+ return configArgs.every((configArg, index) => this.#valueMatches(configArg, actualArgs[index]));
204
+ }
205
+ /** Match a single arg: asymmetric matchers delegate to `asymmetricMatch`, others compare by serialization. */
206
+ #valueMatches(configArg, actualArg) {
207
+ if (isAsymmetricMatcher(configArg)) {
208
+ return configArg.asymmetricMatch(actualArg);
209
+ }
210
+ return this.#serialize([configArg]) === this.#serialize([actualArg]);
211
+ }
212
+ };
213
+
214
+ // src/lib/error-handler.ts
215
+ var MUST_BE_CALLED_WITH_PREAMBLE = (functionName) => `The function '${functionName}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `;
216
+ var NO_ARGUMENTS_MESSAGE = `But the function was called without any arguments.`;
217
+ var actualArgumentsMessage = (actualArgs) => {
218
+ const formatted = serializeValue(actualArgs);
219
+ return `But the actual arguments were: ${formatted.substring(1, formatted.length - 1)}`;
220
+ };
221
+ var errorHandler = {
222
+ throwArgumentsError(actualArgs, functionName) {
223
+ const detail = actualArgs.length === 0 ? NO_ARGUMENTS_MESSAGE : actualArgumentsMessage(actualArgs);
224
+ throw new Error(MUST_BE_CALLED_WITH_PREAMBLE(functionName) + detail);
225
+ }
226
+ };
227
+ var MISSING_RXJS_SUPPORT = "Observable spies require rxjs. Import 'vitest-auto-spy/rxjs' once (e.g. in your test setup) to enable observablePropsToSpyOn / nextWith / nextWithValues / throwWith / complete / returnSubject.";
228
+ function requireObservableSupport() {
229
+ {
230
+ throw new Error(MISSING_RXJS_SUPPORT);
231
+ }
232
+ }
233
+
234
+ // src/lib/spy-decoration.ts
235
+ function decorate(target, helpers) {
236
+ return Object.assign(target, helpers);
237
+ }
238
+
239
+ // src/lib/promise-spy.ts
240
+ function toResolvedPerCallValues(valueConfigsPerCall) {
241
+ return valueConfigsPerCall.map((config) => ({
242
+ wrappedValue: config.delay === void 0 ? Promise.resolve(config.value) : new Promise((resolve) => setTimeout(() => resolve(config.value), config.delay))
243
+ }));
244
+ }
245
+ function addPromiseHelpers(target, store) {
246
+ decorate(target, {
247
+ resolveWith: (value) => {
248
+ store({ value: Promise.resolve(value) });
249
+ },
250
+ rejectWith: (value) => {
251
+ store({ value, _isRejectedPromise: true });
252
+ },
253
+ resolveWithPerCall: (valueConfigsPerCall) => {
254
+ if (valueConfigsPerCall.length === 0) {
255
+ return;
256
+ }
257
+ store({ value: void 0, valuesPerCalls: toResolvedPerCallValues(valueConfigsPerCall) });
258
+ }
259
+ });
260
+ }
261
+ function addPromiseHelpersToFunctionSpy(spyFunction, valueContainer) {
262
+ addPromiseHelpers(spyFunction, (container) => {
263
+ valueContainer.value = container.value;
264
+ valueContainer._isRejectedPromise = container._isRejectedPromise ?? false;
265
+ valueContainer.valuesPerCalls = container.valuesPerCalls ?? [];
266
+ });
267
+ }
268
+ function addPromiseHelpersToCalledWithObject(calledWithObject, calledWithArgs) {
269
+ addPromiseHelpers(calledWithObject, (container) => {
270
+ calledWithObject.argsToValuesMap.set(calledWithArgs, container);
271
+ });
272
+ }
273
+
274
+ // src/lib/settled-results.ts
275
+ var NATIVE_RECORDER = {
276
+ record: (returned) => returned,
277
+ clear: () => void 0
278
+ };
279
+ function isThenable(value) {
280
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
281
+ return false;
282
+ }
283
+ return typeof Reflect.get(value, "then") === "function";
284
+ }
285
+ function installSettledResultsPolyfill(mockFn) {
286
+ const state = Reflect.get(mockFn, "mock");
287
+ if (typeof state !== "object" || state === null || "settledResults" in state) {
288
+ return NATIVE_RECORDER;
289
+ }
290
+ const settledResults = [];
291
+ Object.defineProperty(state, "settledResults", { value: settledResults, enumerable: true, configurable: true, writable: true });
292
+ return {
293
+ record(returned) {
294
+ const entry = { type: "incomplete", value: void 0 };
295
+ settledResults.push(entry);
296
+ if (isThenable(returned)) {
297
+ returned.then(
298
+ (value) => {
299
+ entry.type = "fulfilled";
300
+ entry.value = value;
301
+ },
302
+ (reason) => {
303
+ entry.type = "rejected";
304
+ entry.value = reason;
305
+ }
306
+ );
307
+ } else {
308
+ entry.type = "fulfilled";
309
+ entry.value = returned;
310
+ }
311
+ return returned;
312
+ },
313
+ clear() {
314
+ settledResults.length = 0;
315
+ }
316
+ };
317
+ }
318
+
319
+ // src/lib/function-spy.ts
320
+ function isReturnValueContainer(value) {
321
+ return typeof value === "object" && value !== null && "value" in value;
322
+ }
323
+ function unwrapContainer(container) {
324
+ if (container._isRejectedPromise) {
325
+ return Promise.reject(container.value);
326
+ }
327
+ const wrapped = container.valuesPerCalls?.shift();
328
+ if (wrapped) {
329
+ return wrapped.wrappedValue;
330
+ }
331
+ return container.value;
332
+ }
333
+ function lookupConfigured(calledWithObject, actualArgs) {
334
+ const configured = calledWithObject.argsToValuesMap.get(actualArgs);
335
+ if (isReturnValueContainer(configured)) {
336
+ return { found: true, value: unwrapContainer(configured) };
337
+ }
338
+ return { found: false, value: void 0 };
339
+ }
340
+ function returnTheCorrectFakeValue(calledWithObject, mustBeCalledWithObject, valueContainer, actualArgs, functionName) {
341
+ if (calledWithObject.wasConfigured) {
342
+ const match = lookupConfigured(calledWithObject, actualArgs);
343
+ if (match.found) {
344
+ return match.value;
345
+ }
346
+ }
347
+ if (mustBeCalledWithObject.wasConfigured) {
348
+ const match = lookupConfigured(mustBeCalledWithObject, actualArgs);
349
+ if (match.found) {
350
+ return match.value;
351
+ }
352
+ errorHandler.throwArgumentsError(actualArgs, functionName);
353
+ }
354
+ return unwrapContainer(valueContainer);
355
+ }
356
+ function addMethodsToCalledWith(calledWith, calledWithArgs) {
357
+ calledWith.wasConfigured = true;
358
+ const setReturnValue = (value) => {
359
+ calledWith.argsToValuesMap.set(calledWithArgs, { value });
360
+ };
361
+ decorate(calledWith, {
362
+ mockReturnValue: setReturnValue,
363
+ // `returnValue` is the `jest-auto-spies` name — aliased so migrating tests need no rewrite.
364
+ returnValue: setReturnValue
365
+ });
366
+ addPromiseHelpersToCalledWithObject(calledWith, calledWithArgs);
367
+ return calledWith;
368
+ }
369
+ function createCalledWithObject() {
370
+ return { wasConfigured: false, argsToValuesMap: new ArgsMap() };
371
+ }
372
+ function resetCalledWithObject(calledWithObject) {
373
+ calledWithObject.wasConfigured = false;
374
+ calledWithObject.argsToValuesMap = new ArgsMap();
375
+ }
376
+ function createFunctionSpy(name) {
377
+ const calledWithObject = createCalledWithObject();
378
+ const mustBeCalledWithObject = createCalledWithObject();
379
+ const valueContainer = { value: void 0 };
380
+ const dispatch = (...actualArgs) => settledResultsRecorder.record(returnTheCorrectFakeValue(calledWithObject, mustBeCalledWithObject, valueContainer, actualArgs, name));
381
+ const functionSpy = getMockAdapter().createMockFn(dispatch, name);
382
+ const settledResultsRecorder = installSettledResultsPolyfill(functionSpy);
383
+ addPromiseHelpersToFunctionSpy(functionSpy, valueContainer);
384
+ const spy = decorate(functionSpy, {
385
+ calledWith: (...calledWithArgs) => addMethodsToCalledWith(calledWithObject, calledWithArgs),
386
+ mustBeCalledWith: (...calledWithArgs) => addMethodsToCalledWith(mustBeCalledWithObject, calledWithArgs)
387
+ });
388
+ attachConfigReset(spy, () => {
389
+ resetCalledWithObject(calledWithObject);
390
+ resetCalledWithObject(mustBeCalledWithObject);
391
+ valueContainer.value = void 0;
392
+ delete valueContainer._isRejectedPromise;
393
+ delete valueContainer.valuesPerCalls;
394
+ getMockAdapter().restoreImplementation(functionSpy, dispatch);
395
+ });
396
+ attachClearHook(spy, () => settledResultsRecorder.clear());
397
+ markAsMock(spy);
398
+ return exposeAsSpy(spy);
399
+ }
400
+ function exposeAsSpy(spy) {
401
+ return spy;
402
+ }
403
+
404
+ // src/lib/create-spy-from-class.ts
405
+ var EMPTY_CONFIGURATION = {
406
+ methodsToSpyOn: [],
407
+ observablePropsToSpyOn: [],
408
+ settersToSpyOn: [],
409
+ gettersToSpyOn: [],
410
+ autoSpyAccessors: false,
411
+ lazySpies: false
412
+ };
413
+ function extractMethodsFromObject(obj) {
414
+ const descriptors = Object.getOwnPropertyDescriptors(obj);
415
+ return Object.keys(descriptors).filter((name) => name !== "constructor" && !descriptors[name]?.get);
416
+ }
417
+ function walkOwnPrototypes(prototype, visit) {
418
+ let current = prototype;
419
+ while (current) {
420
+ const parent = Object.getPrototypeOf(current);
421
+ if (parent) {
422
+ visit(current);
423
+ }
424
+ current = parent;
425
+ }
426
+ }
427
+ var methodNamesCache = /* @__PURE__ */ new WeakMap();
428
+ function getAllMethodNames(prototype) {
429
+ const cached = methodNamesCache.get(prototype);
430
+ if (cached) {
431
+ return cached;
432
+ }
433
+ const methods = /* @__PURE__ */ new Set();
434
+ walkOwnPrototypes(prototype, (obj) => extractMethodsFromObject(obj).forEach((name) => methods.add(name)));
435
+ const result = [...methods];
436
+ methodNamesCache.set(prototype, result);
437
+ return result;
438
+ }
439
+ function getAllAccessorNames(prototype) {
440
+ const getters = /* @__PURE__ */ new Set();
441
+ const setters = /* @__PURE__ */ new Set();
442
+ walkOwnPrototypes(prototype, (obj) => {
443
+ const descriptors = Object.getOwnPropertyDescriptors(obj);
444
+ Object.keys(descriptors).forEach((name) => {
445
+ if (name === "constructor") {
446
+ return;
447
+ }
448
+ if (descriptors[name]?.get) {
449
+ getters.add(name);
450
+ }
451
+ if (descriptors[name]?.set) {
452
+ setters.add(name);
453
+ }
454
+ });
455
+ });
456
+ return { getters: [...getters], setters: [...setters] };
457
+ }
458
+ function resolveAccessors(prototype, config) {
459
+ if (!config.autoSpyAccessors) {
460
+ return { getters: config.gettersToSpyOn, setters: config.settersToSpyOn };
461
+ }
462
+ const discovered = getAllAccessorNames(prototype);
463
+ return {
464
+ getters: [.../* @__PURE__ */ new Set([...config.gettersToSpyOn, ...discovered.getters])],
465
+ setters: [.../* @__PURE__ */ new Set([...config.settersToSpyOn, ...discovered.setters])]
466
+ };
467
+ }
468
+ function warnOnUnknownMethods(ObjectClass, requested) {
469
+ const available = new Set(getAllMethodNames(ObjectClass.prototype));
470
+ const unknown = requested.filter((name) => !available.has(name));
471
+ if (unknown.length === 0) {
472
+ return;
473
+ }
474
+ console.warn(
475
+ `[vitest-auto-spy] createSpyFromClass(${ObjectClass.name}): requested method(s) not found on the class prototype: ${unknown.join(", ")}. A spy was still created, but the real code will never call it \u2014 check for typos.`
476
+ );
477
+ }
478
+ function defineLazyMethodSpy(autoSpy, methodName) {
479
+ Object.defineProperty(autoSpy, methodName, {
480
+ configurable: true,
481
+ enumerable: true,
482
+ get() {
483
+ const spy = createFunctionSpy(methodName);
484
+ Object.defineProperty(autoSpy, methodName, { configurable: true, enumerable: true, writable: true, value: spy });
485
+ return spy;
486
+ }
487
+ });
488
+ }
489
+ function resolveConfiguration(methodsToSpyOnOrConfig) {
490
+ if (!methodsToSpyOnOrConfig) {
491
+ return { ...EMPTY_CONFIGURATION };
492
+ }
493
+ if (Array.isArray(methodsToSpyOnOrConfig)) {
494
+ return { ...EMPTY_CONFIGURATION, methodsToSpyOn: methodsToSpyOnOrConfig };
495
+ }
496
+ return {
497
+ methodsToSpyOn: methodsToSpyOnOrConfig.methodsToSpyOn ?? [],
498
+ observablePropsToSpyOn: methodsToSpyOnOrConfig.observablePropsToSpyOn ?? [],
499
+ settersToSpyOn: methodsToSpyOnOrConfig.settersToSpyOn ?? [],
500
+ gettersToSpyOn: methodsToSpyOnOrConfig.gettersToSpyOn ?? [],
501
+ autoSpyAccessors: methodsToSpyOnOrConfig.autoSpyAccessors ?? false,
502
+ lazySpies: methodsToSpyOnOrConfig.lazySpies ?? false
503
+ };
504
+ }
505
+ function createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig) {
506
+ const config = resolveConfiguration(methodsToSpyOnOrConfig);
507
+ const methodNames = config.methodsToSpyOn.length > 0 ? config.methodsToSpyOn : getAllMethodNames(ObjectClass.prototype);
508
+ if (config.methodsToSpyOn.length > 0) {
509
+ warnOnUnknownMethods(ObjectClass, config.methodsToSpyOn);
510
+ }
511
+ const autoSpy = {};
512
+ config.observablePropsToSpyOn.forEach((observablePropName) => {
513
+ autoSpy[observablePropName] = requireObservableSupport().createPropSpy();
514
+ });
515
+ const accessors = resolveAccessors(ObjectClass.prototype, config);
516
+ createAccessorsSpies(autoSpy, accessors.getters, accessors.setters);
517
+ methodNames.forEach((methodName) => {
518
+ if (config.lazySpies) {
519
+ defineLazyMethodSpy(autoSpy, methodName);
520
+ } else {
521
+ autoSpy[methodName] = createFunctionSpy(methodName);
522
+ }
523
+ });
524
+ return autoSpy;
525
+ }
526
+
527
+ // src/lib/angular.ts
528
+ function withLazyDefault(methodsToSpyOnOrConfig) {
529
+ if (!methodsToSpyOnOrConfig) {
530
+ return { lazySpies: true };
531
+ }
532
+ if (Array.isArray(methodsToSpyOnOrConfig)) {
533
+ return { methodsToSpyOn: methodsToSpyOnOrConfig, lazySpies: true };
534
+ }
535
+ return { ...methodsToSpyOnOrConfig, lazySpies: methodsToSpyOnOrConfig.lazySpies ?? true };
536
+ }
537
+ function provideAutoSpy(ObjectClass, methodsToSpyOnOrConfig) {
538
+ return {
539
+ provide: ObjectClass,
540
+ useValue: createSpyFromClass(ObjectClass, withLazyDefault(methodsToSpyOnOrConfig))
541
+ };
542
+ }
543
+ function injectSpy(token) {
544
+ const injected = testing.TestBed.inject(token);
545
+ return injected;
546
+ }
547
+ function mockReadonlyProp(object, property, value) {
548
+ Object.defineProperty(object, property, { get: () => value, configurable: true });
549
+ }
550
+ function mockReadonlyPropGetter(object, property, getter) {
551
+ Object.defineProperty(object, property, { get: getter, configurable: true });
552
+ }
553
+ function mockAccessorsProp(object, property) {
554
+ const adapter = getMockAdapter();
555
+ Object.defineProperty(object, property, { get: adapter.createMockFn(), set: adapter.createMockFn(), configurable: true });
556
+ }
557
+
558
+ // src/angular.ts
559
+ registerMockAdapter(vitestMockAdapter);
560
+
561
+ exports.injectSpy = injectSpy;
562
+ exports.mockAccessorsProp = mockAccessorsProp;
563
+ exports.mockReadonlyProp = mockReadonlyProp;
564
+ exports.mockReadonlyPropGetter = mockReadonlyPropGetter;
565
+ exports.provideAutoSpy = provideAutoSpy;
package/dist/angular.js CHANGED
@@ -1 +1,40 @@
1
- import {a as a$1}from'./chunk-HDCUMVHT.js';import {a as a$2}from'./chunk-Q4FBVCJO.js';import {a,c as c$1}from'./chunk-RTGT5WHR.js';import'./chunk-7IUYJ6ZW.js';import {TestBed}from'@angular/core/testing';function s(e){return e?Array.isArray(e)?{methodsToSpyOn:e,lazySpies:true}:{...e,lazySpies:e.lazySpies??true}:{lazySpies:true}}function y(e,r){return {provide:e,useValue:a$2(e,s(r))}}function u(e){return TestBed.inject(e)}function c(e,r,t){Object.defineProperty(e,r,{get:()=>t,configurable:true});}function l(e,r,t){Object.defineProperty(e,r,{get:t,configurable:true});}function T(e,r){let t=c$1();Object.defineProperty(e,r,{get:t.createMockFn(),set:t.createMockFn(),configurable:true});}a(a$1);export{u as injectSpy,T as mockAccessorsProp,c as mockReadonlyProp,l as mockReadonlyPropGetter,y as provideAutoSpy};
1
+ import { vitestMockAdapter } from './chunk-OS2QFTIF.js';
2
+ import { createSpyFromClass } from './chunk-JXCO3VHG.js';
3
+ import { registerMockAdapter, getMockAdapter } from './chunk-T4Q3C2PV.js';
4
+ import './chunk-5JKCB5CM.js';
5
+ import { TestBed } from '@angular/core/testing';
6
+
7
+ function withLazyDefault(methodsToSpyOnOrConfig) {
8
+ if (!methodsToSpyOnOrConfig) {
9
+ return { lazySpies: true };
10
+ }
11
+ if (Array.isArray(methodsToSpyOnOrConfig)) {
12
+ return { methodsToSpyOn: methodsToSpyOnOrConfig, lazySpies: true };
13
+ }
14
+ return { ...methodsToSpyOnOrConfig, lazySpies: methodsToSpyOnOrConfig.lazySpies ?? true };
15
+ }
16
+ function provideAutoSpy(ObjectClass, methodsToSpyOnOrConfig) {
17
+ return {
18
+ provide: ObjectClass,
19
+ useValue: createSpyFromClass(ObjectClass, withLazyDefault(methodsToSpyOnOrConfig))
20
+ };
21
+ }
22
+ function injectSpy(token) {
23
+ const injected = TestBed.inject(token);
24
+ return injected;
25
+ }
26
+ function mockReadonlyProp(object, property, value) {
27
+ Object.defineProperty(object, property, { get: () => value, configurable: true });
28
+ }
29
+ function mockReadonlyPropGetter(object, property, getter) {
30
+ Object.defineProperty(object, property, { get: getter, configurable: true });
31
+ }
32
+ function mockAccessorsProp(object, property) {
33
+ const adapter = getMockAdapter();
34
+ Object.defineProperty(object, property, { get: adapter.createMockFn(), set: adapter.createMockFn(), configurable: true });
35
+ }
36
+
37
+ // src/angular.ts
38
+ registerMockAdapter(vitestMockAdapter);
39
+
40
+ export { injectSpy, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, provideAutoSpy };