vitest-auto-spy 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -7
- package/dist/angular.cjs +1 -0
- package/dist/angular.d.cts +21 -0
- package/dist/angular.d.ts +21 -0
- package/dist/angular.js +1 -0
- package/dist/chunk-6S2BI3IA.js +1 -0
- package/dist/chunk-7IUYJ6ZW.js +1 -0
- package/dist/index.cjs +1 -400
- package/dist/index.d.cts +5 -146
- package/dist/index.d.ts +5 -146
- package/dist/index.js +1 -390
- package/dist/rxjs.cjs +1 -0
- package/dist/rxjs.d.cts +23 -0
- package/dist/rxjs.d.ts +23 -0
- package/dist/rxjs.js +1 -0
- package/dist/types-Cg9eZmvm.d.cts +114 -0
- package/dist/types-Cg9eZmvm.d.ts +114 -0
- package/package.json +23 -5
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -50,8 +50,33 @@ same API, but spying only on **Vitest** instead of Jest.
|
|
|
50
50
|
npm i -D vitest-auto-spy
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
Peer dependencies
|
|
54
|
-
|
|
53
|
+
Peer dependencies are all **optional** and provided by your project: `vitest` (required),
|
|
54
|
+
plus `rxjs` and `@angular/core` only if you use the matching entry point. The package itself
|
|
55
|
+
has **zero runtime dependencies**.
|
|
56
|
+
|
|
57
|
+
### Entry points
|
|
58
|
+
|
|
59
|
+
The library ships a framework-agnostic core and two opt-in layers, so a plain Node / Bun /
|
|
60
|
+
React / Vue project pulls **neither rxjs nor Angular into its runtime bundle**:
|
|
61
|
+
|
|
62
|
+
| Import | Provides | Pulls in |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| `vitest-auto-spy` | `createSpyFromClass`, `createFunctionSpy`, sync + promise + accessor spies, `errorHandler`, types | `vitest` |
|
|
65
|
+
| `vitest-auto-spy/rxjs` | observable spies (`nextWith`, `nextWithValues`, `observablePropsToSpyOn`, …) + `createObservableWithValues` | `rxjs` |
|
|
66
|
+
| `vitest-auto-spy/angular` | `provideAutoSpy`, `injectSpy`, `mockReadonlyProp*`, `mockAccessorsProp` | `@angular/core` |
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createSpyFromClass } from 'vitest-auto-spy';
|
|
70
|
+
import 'vitest-auto-spy/rxjs'; // once (e.g. in your test setup) — enables observable spies
|
|
71
|
+
import { provideAutoSpy, injectSpy } from 'vitest-auto-spy/angular';
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> Using an observable spy (`observablePropsToSpyOn`, `nextWith`, …) without importing
|
|
75
|
+
> `vitest-auto-spy/rxjs` throws a clear hint telling you to add that import.
|
|
76
|
+
>
|
|
77
|
+
> The decoupling is at the **runtime** level. The core's _type_ surface (`Spy<T>`) still
|
|
78
|
+
> references rxjs types, so keep `rxjs` available for type-checking (it's normally already a
|
|
79
|
+
> devDependency); none of it reaches your runtime bundle.
|
|
55
80
|
|
|
56
81
|
## Why
|
|
57
82
|
|
|
@@ -87,9 +112,14 @@ The public API is intentionally identical. In most projects the migration is a
|
|
|
87
112
|
|
|
88
113
|
```diff
|
|
89
114
|
- import { createSpyFromClass, provideAutoSpy } from 'jest-auto-spies';
|
|
90
|
-
+ import { createSpyFromClass
|
|
115
|
+
+ import { createSpyFromClass } from 'vitest-auto-spy';
|
|
116
|
+
+ import { provideAutoSpy } from 'vitest-auto-spy/angular';
|
|
117
|
+
+ import 'vitest-auto-spy/rxjs'; // once, if you use observable spies
|
|
91
118
|
```
|
|
92
119
|
|
|
120
|
+
The only API-shape change from `jest-auto-spies` is that the Angular helpers and the
|
|
121
|
+
observable layer live behind the `/angular` and `/rxjs` subpaths (see [Entry points](#entry-points)).
|
|
122
|
+
|
|
93
123
|
| jest-auto-spies | vitest-auto-spy | Status |
|
|
94
124
|
| --- | --- | --- |
|
|
95
125
|
| `createSpyFromClass` | `createSpyFromClass` | ✅ identical |
|
|
@@ -155,7 +185,11 @@ myService.getProducts.calledWith(1).resolveWith(['one']);
|
|
|
155
185
|
## Observable-returning methods & Observable properties
|
|
156
186
|
|
|
157
187
|
Both spied **methods** that return an `Observable` and spied **properties** of type
|
|
158
|
-
`Observable` get the same control surface:
|
|
188
|
+
`Observable` get the same control surface. Enable them by importing the rxjs layer once:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import 'vitest-auto-spy/rxjs';
|
|
192
|
+
```
|
|
159
193
|
|
|
160
194
|
```ts
|
|
161
195
|
myService.getProducts$.nextWith([{ name: 'Product 1' }]); // emit, stream stays open
|
|
@@ -187,7 +221,7 @@ myService.getProducts$.calledWith(1).nextWith([{ name: 'Product 1' }]);
|
|
|
187
221
|
### Standalone observable builder
|
|
188
222
|
|
|
189
223
|
```ts
|
|
190
|
-
import { createObservableWithValues } from 'vitest-auto-spy';
|
|
224
|
+
import { createObservableWithValues } from 'vitest-auto-spy/rxjs';
|
|
191
225
|
|
|
192
226
|
const fake$ = createObservableWithValues([{ value: 1 }, { value: 2 }, { complete: true }]);
|
|
193
227
|
|
|
@@ -217,7 +251,7 @@ expect(spy.accessorSpies.setters.userName).toHaveBeenCalledWith('New Name');
|
|
|
217
251
|
`provideAutoSpy` is the shorthand for providing an auto-spy in a `TestBed`:
|
|
218
252
|
|
|
219
253
|
```ts
|
|
220
|
-
import { provideAutoSpy, injectSpy } from 'vitest-auto-spy';
|
|
254
|
+
import { provideAutoSpy, injectSpy } from 'vitest-auto-spy/angular';
|
|
221
255
|
|
|
222
256
|
TestBed.configureTestingModule({
|
|
223
257
|
providers: [
|
|
@@ -243,7 +277,7 @@ beforeEach(() => {
|
|
|
243
277
|
### Signal / readonly property mocking (bonus)
|
|
244
278
|
|
|
245
279
|
```ts
|
|
246
|
-
import { mockReadonlyProp, mockReadonlyPropGetter, mockAccessorsProp } from 'vitest-auto-spy';
|
|
280
|
+
import { mockReadonlyProp, mockReadonlyPropGetter, mockAccessorsProp } from 'vitest-auto-spy/angular';
|
|
247
281
|
|
|
248
282
|
mockReadonlyProp(service, 'isReady', true); // static value (incl. signals)
|
|
249
283
|
mockReadonlyPropGetter(service, 'label', () => 'A'); // dynamic getter
|
package/dist/angular.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var testing=require('@angular/core/testing'),vitest=require('vitest');function g(e,t){Object.defineProperty(e,t,{get(){},set(r){},configurable:true});}function T(e,t,r){let n=t;return r==="setter"?vitest.vi.spyOn(e,n,"set"):vitest.vi.spyOn(e,n,"get")}function b(e,t,r){let n={getters:{},setters:{}};e.accessorSpies=n,t.forEach(o=>{g(e,o),n.getters[o]=T(e,o,"getter");}),r.forEach(o=>{Object.prototype.hasOwnProperty.call(e,o)||g(e,o),n.setters[o]=T(e,o,"setter");});}function A(e){return `'${e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function M(e,t){return Object.entries(e).map(([r,n])=>`${r}:${i(n,t)}`).join(",")}function W(e,t){return `new Map([${[...e.entries()].map(([n,o])=>`[${i(n,t)},${i(o,t)}]`).join(",")}])`}function F(e,t){if(t.has(e))return "[Circular]";t.add(e);let r;return e instanceof Date?r=`new Date(${e.getTime()})`:e instanceof Map?r=W(e,t):e instanceof Set?r=`new Set([${[...e].map(n=>i(n,t)).join(",")}])`:Array.isArray(e)?r=`[${e.map(n=>i(n,t)).join(",")}]`:r=`{${M(e,t)}}`,t.delete(e),r}function i(e,t=new WeakSet){return typeof e=="string"?A(e):typeof e=="bigint"?`${e}n`:typeof e=="symbol"?e.toString():typeof e=="function"?`[Function: ${e.name}]`:typeof e=="object"&&e!==null?F(e,t):Object.is(e,-0)?"-0":String(e)}var l=class{#e={};set(t,r){this.#e[this.#t(t)]=r;}get(t){return this.#e[this.#t(t)]}#t(t){return i(t)}};var E=e=>`The function '${e}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `,_="But the function was called without any arguments.",$=e=>{let t=i(e);return `But the actual arguments were: ${t.substring(1,t.length-1)}`},m={throwArgumentsError(e,t){let r=e.length===0?_:$(e);throw new Error(E(t)+r)}};var H="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 S(){throw new Error(H);}function a(e,t){return Object.assign(e,t)}function K(e){return e.map(t=>({wrappedValue:t.delay===void 0?Promise.resolve(t.value):new Promise(r=>setTimeout(()=>r(t.value),t.delay))}))}function O(e,t){a(e,{resolveWith:r=>{t({value:Promise.resolve(r)});},rejectWith:r=>{t({value:r,_isRejectedPromise:true});},resolveWithPerCall:r=>{r.length!==0&&t({value:void 0,valuesPerCalls:K(r)});}});}function C(e,t){O(e,r=>{t.value=r.value,t._isRejectedPromise=r._isRejectedPromise??false,t.valuesPerCalls=r.valuesPerCalls??[];});}function j(e,t){O(e,r=>{e.argsToValuesMap.set(t,r);});}function B(e){return typeof e=="object"&&e!==null&&"value"in e}function v(e){if(e._isRejectedPromise)return Promise.reject(e.value);let t=e.valuesPerCalls?.shift();return t?t.wrappedValue:e.value}function h(e,t){let r=e.argsToValuesMap.get(t);return B(r)?{found:true,value:v(r)}:{found:false,value:void 0}}function I(e,t,r,n,o){if(e.wasConfigured){let s=h(e,n);if(s.found)return s.value}if(t.wasConfigured){let s=h(t,n);if(s.found)return s.value;m.throwArgumentsError(n,o);}return v(r)}function w(e,t){return e.wasConfigured=true,a(e,{mockReturnValue:r=>{e.argsToValuesMap.set(t,{value:r});}}),j(e,t),e}function k(){return {wasConfigured:false,argsToValuesMap:new l}}function P(e){let t=k(),r=k(),n={value:void 0},o=vitest.vi.fn((...u)=>I(t,r,n,u,e));o.mockName(e),C(o,n);let s=a(o,{calledWith:(...u)=>w(t,u),mustBeCalledWith:(...u)=>w(r,u)});return s}var R={methodsToSpyOn:[],observablePropsToSpyOn:[],settersToSpyOn:[],gettersToSpyOn:[]};function G(e){let t=Object.getOwnPropertyDescriptors(e);return Object.keys(t).filter(r=>r!=="constructor"&&!t[r]?.get)}function q(e){let t=new Set,r=e;for(;r;){let n=Object.getPrototypeOf(r);n&&G(r).forEach(o=>t.add(o)),r=n;}return [...t]}function D(e){return e?Array.isArray(e)?{...R,methodsToSpyOn:e}:{methodsToSpyOn:e.methodsToSpyOn??[],observablePropsToSpyOn:e.observablePropsToSpyOn??[],settersToSpyOn:e.settersToSpyOn??[],gettersToSpyOn:e.gettersToSpyOn??[]}:{...R}}function x(e,t){let{methodsToSpyOn:r,observablePropsToSpyOn:n,settersToSpyOn:o,gettersToSpyOn:s}=D(t),u=r.length>0?r:q(e.prototype),p={};return n.forEach(c=>{p[c]=S().createPropSpy();}),b(p,s,o),u.forEach(c=>{p[c]=P(c);}),p}function L(e,t){return {provide:e,useValue:x(e,t)}}function N(e){return testing.TestBed.inject(e)}function J(e,t,r){Object.defineProperty(e,t,{get:()=>r,configurable:true});}function X(e,t,r){Object.defineProperty(e,t,{get:r,configurable:true});}function Y(e,t){Object.defineProperty(e,t,{get:vitest.vi.fn(),set:vitest.vi.fn(),configurable:true});}exports.injectSpy=N;exports.mockAccessorsProp=Y;exports.mockReadonlyProp=J;exports.mockReadonlyPropGetter=X;exports.provideAutoSpy=L;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { C as ClassType, S as Spy, a as ClassSpyConfiguration, O as OnlyMethodKeysOf } from './types-Cg9eZmvm.cjs';
|
|
2
|
+
import 'rxjs';
|
|
3
|
+
import 'vitest';
|
|
4
|
+
|
|
5
|
+
/** `{ provide, useValue }` shape consumed by Angular's `providers`. */
|
|
6
|
+
type AngularValueProvider<T> = {
|
|
7
|
+
provide: ClassType<T>;
|
|
8
|
+
useValue: Spy<T>;
|
|
9
|
+
};
|
|
10
|
+
/** Shorthand Angular provider: `{ provide, useValue: createSpyFromClass(...) }`. */
|
|
11
|
+
declare function provideAutoSpy<T>(ObjectClass: ClassType<T>, methodsToSpyOnOrConfig?: ClassSpyConfiguration<T> | OnlyMethodKeysOf<T>[]): AngularValueProvider<T>;
|
|
12
|
+
/** Inject a service from Angular's `TestBed`, already typed as `Spy<T>`. */
|
|
13
|
+
declare function injectSpy<T>(token: ClassType<T> | (abstract new (...args: never[]) => T)): Spy<T>;
|
|
14
|
+
/** Override a readonly property (incl. `signal()` / `computed()`) with a static value. */
|
|
15
|
+
declare function mockReadonlyProp<T, K extends keyof T>(object: T, property: K, value: T[K]): void;
|
|
16
|
+
/** Override a readonly property with a dynamic getter. */
|
|
17
|
+
declare function mockReadonlyPropGetter<T, K extends keyof T>(object: T, property: K, getter: () => unknown): void;
|
|
18
|
+
/** Replace a property with spied `get`/`set` accessors (`vi.fn()`). */
|
|
19
|
+
declare function mockAccessorsProp<T, K extends keyof T>(object: T, property: K): void;
|
|
20
|
+
|
|
21
|
+
export { type AngularValueProvider, injectSpy, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, provideAutoSpy };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { C as ClassType, S as Spy, a as ClassSpyConfiguration, O as OnlyMethodKeysOf } from './types-Cg9eZmvm.js';
|
|
2
|
+
import 'rxjs';
|
|
3
|
+
import 'vitest';
|
|
4
|
+
|
|
5
|
+
/** `{ provide, useValue }` shape consumed by Angular's `providers`. */
|
|
6
|
+
type AngularValueProvider<T> = {
|
|
7
|
+
provide: ClassType<T>;
|
|
8
|
+
useValue: Spy<T>;
|
|
9
|
+
};
|
|
10
|
+
/** Shorthand Angular provider: `{ provide, useValue: createSpyFromClass(...) }`. */
|
|
11
|
+
declare function provideAutoSpy<T>(ObjectClass: ClassType<T>, methodsToSpyOnOrConfig?: ClassSpyConfiguration<T> | OnlyMethodKeysOf<T>[]): AngularValueProvider<T>;
|
|
12
|
+
/** Inject a service from Angular's `TestBed`, already typed as `Spy<T>`. */
|
|
13
|
+
declare function injectSpy<T>(token: ClassType<T> | (abstract new (...args: never[]) => T)): Spy<T>;
|
|
14
|
+
/** Override a readonly property (incl. `signal()` / `computed()`) with a static value. */
|
|
15
|
+
declare function mockReadonlyProp<T, K extends keyof T>(object: T, property: K, value: T[K]): void;
|
|
16
|
+
/** Override a readonly property with a dynamic getter. */
|
|
17
|
+
declare function mockReadonlyPropGetter<T, K extends keyof T>(object: T, property: K, getter: () => unknown): void;
|
|
18
|
+
/** Replace a property with spied `get`/`set` accessors (`vi.fn()`). */
|
|
19
|
+
declare function mockAccessorsProp<T, K extends keyof T>(object: T, property: K): void;
|
|
20
|
+
|
|
21
|
+
export { type AngularValueProvider, injectSpy, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, provideAutoSpy };
|
package/dist/angular.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {c as c$1}from'./chunk-6S2BI3IA.js';import'./chunk-7IUYJ6ZW.js';import {TestBed}from'@angular/core/testing';import {vi}from'vitest';function i(e,o){return {provide:e,useValue:c$1(e,o)}}function s(e){return TestBed.inject(e)}function y(e,o,r){Object.defineProperty(e,o,{get:()=>r,configurable:true});}function a(e,o,r){Object.defineProperty(e,o,{get:r,configurable:true});}function c(e,o){Object.defineProperty(e,o,{get:vi.fn(),set:vi.fn(),configurable:true});}export{s as injectSpy,c as mockAccessorsProp,y as mockReadonlyProp,a as mockReadonlyPropGetter,i as provideAutoSpy};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {b as b$1,d,c}from'./chunk-7IUYJ6ZW.js';import {vi}from'vitest';function M(e){return `'${e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function v(e,t){return Object.entries(e).map(([n,r])=>`${n}:${i(r,t)}`).join(",")}function V(e,t){return `new Map([${[...e.entries()].map(([r,o])=>`[${i(r,t)},${i(o,t)}]`).join(",")}])`}function A(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=V(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=`{${v(e,t)}}`,t.delete(e),n}function i(e,t=new WeakSet){return typeof e=="string"?M(e):typeof e=="bigint"?`${e}n`:typeof e=="symbol"?e.toString():typeof e=="function"?`[Function: ${e.name}]`:typeof e=="object"&&e!==null?A(e,t):Object.is(e,-0)?"-0":String(e)}var W=e=>`The function '${e}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `,E="But the function was called without any arguments.",F=e=>{let t=i(e);return `But the actual arguments were: ${t.substring(1,t.length-1)}`},y={throwArgumentsError(e,t){let n=e.length===0?E:F(e);throw new Error(W(t)+n)}};var l=class{#e={};set(t,n){this.#e[this.#t(t)]=n;}get(t){return this.#e[this.#t(t)]}#t(t){return i(t)}};function $(e){return e.map(t=>({wrappedValue:t.delay===void 0?Promise.resolve(t.value):new Promise(n=>setTimeout(()=>n(t.value),t.delay))}))}function g(e,t){d(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:$(n)});}});}function m(e,t){g(e,n=>{t.value=n.value,t._isRejectedPromise=n._isRejectedPromise??false,t.valuesPerCalls=n.valuesPerCalls??[];});}function T(e,t){g(e,n=>{e.argsToValuesMap.set(t,n);});}function _(e){return typeof e=="object"&&e!==null&&"value"in e}function C(e){if(e._isRejectedPromise)return Promise.reject(e.value);let t=e.valuesPerCalls?.shift();return t?t.wrappedValue:e.value}function b(e,t){let n=e.argsToValuesMap.get(t);return _(n)?{found:true,value:C(n)}:{found:false,value:void 0}}function z(e,t,n,r,o){if(e.wasConfigured){let s=b(e,r);if(s.found)return s.value}if(t.wasConfigured){let s=b(t,r);if(s.found)return s.value;y.throwArgumentsError(r,o);}return C(n)}function w(e,t){return e.wasConfigured=true,d(e,{mockReturnValue:n=>{e.argsToValuesMap.set(t,{value:n});}}),T(e,t),b$1()?.addToCalledWithObject(e,t),e}function S(){return {wasConfigured:false,argsToValuesMap:new l}}function h(e){let t=S(),n=S(),r={value:void 0},o=vi.fn((...u)=>z(t,n,r,u,e));o.mockName(e),m(o,r),b$1()?.addToFunctionSpy(o,r);let s=d(o,{calledWith:(...u)=>w(t,u),mustBeCalledWith:(...u)=>w(n,u)});return s}function O(e,t){Object.defineProperty(e,t,{get(){},set(n){},configurable:true});}function k(e,t,n){let r=t;return n==="setter"?vi.spyOn(e,r,"set"):vi.spyOn(e,r,"get")}function P(e,t,n){let r={getters:{},setters:{}};e.accessorSpies=r,t.forEach(o=>{O(e,o),r.getters[o]=k(e,o,"getter");}),n.forEach(o=>{Object.prototype.hasOwnProperty.call(e,o)||O(e,o),r.setters[o]=k(e,o,"setter");});}var R={methodsToSpyOn:[],observablePropsToSpyOn:[],settersToSpyOn:[],gettersToSpyOn:[]};function B(e){let t=Object.getOwnPropertyDescriptors(e);return Object.keys(t).filter(n=>n!=="constructor"&&!t[n]?.get)}function H(e){let t=new Set,n=e;for(;n;){let r=Object.getPrototypeOf(n);r&&B(n).forEach(o=>t.add(o)),n=r;}return [...t]}function I(e){return e?Array.isArray(e)?{...R,methodsToSpyOn:e}:{methodsToSpyOn:e.methodsToSpyOn??[],observablePropsToSpyOn:e.observablePropsToSpyOn??[],settersToSpyOn:e.settersToSpyOn??[],gettersToSpyOn:e.gettersToSpyOn??[]}:{...R}}function ue(e,t){let{methodsToSpyOn:n,observablePropsToSpyOn:r,settersToSpyOn:o,gettersToSpyOn:s}=I(t),u=n.length>0?n:H(e.prototype),c$1={};return r.forEach(p=>{c$1[p]=c().createPropSpy();}),P(c$1,s,o),u.forEach(p=>{c$1[p]=h(p);}),c$1}export{y as a,h as b,ue as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e;function n(t){e=t;}function p(){return e}var o="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 a(){if(!e)throw new Error(o);return e}function u(t,r){return Object.assign(t,r)}export{n as a,p as b,a as c,u as d};
|
package/dist/index.cjs
CHANGED
|
@@ -1,400 +1 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var vitest = require('vitest');
|
|
4
|
-
var javascriptStringify = require('javascript-stringify');
|
|
5
|
-
var rxjs = require('rxjs');
|
|
6
|
-
var operators = require('rxjs/operators');
|
|
7
|
-
var testing = require('@angular/core/testing');
|
|
8
|
-
|
|
9
|
-
// src/lib/accessor-spy.ts
|
|
10
|
-
function defineWithEmptyAccessors(obj, prop) {
|
|
11
|
-
Object.defineProperty(obj, prop, {
|
|
12
|
-
get() {
|
|
13
|
-
return void 0;
|
|
14
|
-
},
|
|
15
|
-
set(_value) {
|
|
16
|
-
},
|
|
17
|
-
configurable: true
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
function spyOnAccessor(autoSpy, accessorName, accessorType) {
|
|
21
|
-
const key = accessorName;
|
|
22
|
-
return accessorType === "setter" ? vitest.vi.spyOn(autoSpy, key, "set") : vitest.vi.spyOn(autoSpy, key, "get");
|
|
23
|
-
}
|
|
24
|
-
function createAccessorsSpies(autoSpy, gettersToSpyOn, settersToSpyOn) {
|
|
25
|
-
const accessorSpies = { getters: {}, setters: {} };
|
|
26
|
-
autoSpy["accessorSpies"] = accessorSpies;
|
|
27
|
-
gettersToSpyOn.forEach((getterName) => {
|
|
28
|
-
defineWithEmptyAccessors(autoSpy, getterName);
|
|
29
|
-
accessorSpies.getters[getterName] = spyOnAccessor(autoSpy, getterName, "getter");
|
|
30
|
-
});
|
|
31
|
-
settersToSpyOn.forEach((setterName) => {
|
|
32
|
-
if (!Object.prototype.hasOwnProperty.call(autoSpy, setterName)) {
|
|
33
|
-
defineWithEmptyAccessors(autoSpy, setterName);
|
|
34
|
-
}
|
|
35
|
-
accessorSpies.setters[setterName] = spyOnAccessor(autoSpy, setterName, "setter");
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
var ArgsMap = class {
|
|
39
|
-
#map = {};
|
|
40
|
-
set(key, value) {
|
|
41
|
-
this.#map[this.#serialize(key)] = value;
|
|
42
|
-
}
|
|
43
|
-
get(key) {
|
|
44
|
-
return this.#map[this.#serialize(key)];
|
|
45
|
-
}
|
|
46
|
-
// Keys are always argument arrays, which `javascript-stringify` always renders
|
|
47
|
-
// to a string. `String(...)` keeps the result total against its `string |
|
|
48
|
-
// undefined` signature without an unreachable fallback branch.
|
|
49
|
-
#serialize(key) {
|
|
50
|
-
return String(javascriptStringify.stringify(key));
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var MUST_BE_CALLED_WITH_PREAMBLE = (functionName) => `The function '${functionName}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `;
|
|
54
|
-
var NO_ARGUMENTS_MESSAGE = `But the function was called without any arguments.`;
|
|
55
|
-
var actualArgumentsMessage = (actualArgs) => {
|
|
56
|
-
const formatted = String(javascriptStringify.stringify(actualArgs));
|
|
57
|
-
return `But the actual arguments were: ${formatted.substring(1, formatted.length - 1)}`;
|
|
58
|
-
};
|
|
59
|
-
var errorHandler = {
|
|
60
|
-
throwArgumentsError(actualArgs, functionName) {
|
|
61
|
-
const detail = actualArgs.length === 0 ? NO_ARGUMENTS_MESSAGE : actualArgumentsMessage(actualArgs);
|
|
62
|
-
throw new Error(MUST_BE_CALLED_WITH_PREAMBLE(functionName) + detail);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/lib/constants.ts
|
|
67
|
-
var REPLAY_BUFFER_SIZE = 1;
|
|
68
|
-
|
|
69
|
-
// src/lib/spy-decoration.ts
|
|
70
|
-
function decorate(target, helpers) {
|
|
71
|
-
return Object.assign(target, helpers);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// src/lib/value-config-guards.ts
|
|
75
|
-
function isCompleteConfig(config) {
|
|
76
|
-
return "complete" in config;
|
|
77
|
-
}
|
|
78
|
-
function isNextValueConfig(config) {
|
|
79
|
-
return "value" in config;
|
|
80
|
-
}
|
|
81
|
-
function isErrorConfig(config) {
|
|
82
|
-
return "errorValue" in config;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// src/lib/observable-spy.ts
|
|
86
|
-
function createReplaySubject() {
|
|
87
|
-
return new rxjs.ReplaySubject(REPLAY_BUFFER_SIZE);
|
|
88
|
-
}
|
|
89
|
-
function mergeSubjectWithDefaultValues(subject, valuesConfigs) {
|
|
90
|
-
const onCompleteSubject = new rxjs.ReplaySubject(REPLAY_BUFFER_SIZE);
|
|
91
|
-
const results$ = rxjs.from(valuesConfigs).pipe(
|
|
92
|
-
// Honor a delay on a completion entry before it stops the stream.
|
|
93
|
-
operators.concatMap(
|
|
94
|
-
(config) => isCompleteConfig(config) && config.complete && config.delay ? rxjs.of(config).pipe(operators.delay(config.delay)) : rxjs.of(config)
|
|
95
|
-
),
|
|
96
|
-
// Stop (and signal completion) as soon as a `{ complete: true }` entry arrives.
|
|
97
|
-
operators.takeWhile((config) => {
|
|
98
|
-
if (!isCompleteConfig(config)) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
if (config.complete) {
|
|
102
|
-
onCompleteSubject.next();
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
return true;
|
|
106
|
-
}),
|
|
107
|
-
// Map each remaining entry to its emission: a value, an error, or nothing.
|
|
108
|
-
operators.concatMap((config) => {
|
|
109
|
-
if (isNextValueConfig(config) && config.value) {
|
|
110
|
-
return config.delay ? rxjs.of(config.value).pipe(operators.delay(config.delay)) : rxjs.of(config.value);
|
|
111
|
-
}
|
|
112
|
-
if (isErrorConfig(config) && config.errorValue) {
|
|
113
|
-
return config.delay ? rxjs.timer(config.delay).pipe(operators.switchMap(() => rxjs.throwError(() => config.errorValue))) : rxjs.throwError(() => config.errorValue);
|
|
114
|
-
}
|
|
115
|
-
return rxjs.EMPTY;
|
|
116
|
-
})
|
|
117
|
-
);
|
|
118
|
-
return rxjs.merge(results$, subject.pipe(operators.takeUntil(onCompleteSubject)));
|
|
119
|
-
}
|
|
120
|
-
function addObservableHelpers(objectToDecorate, providedSubject, onSubjectConfigured) {
|
|
121
|
-
decorate(objectToDecorate, {
|
|
122
|
-
nextWith: (value) => {
|
|
123
|
-
providedSubject.next(value);
|
|
124
|
-
onSubjectConfigured(providedSubject);
|
|
125
|
-
},
|
|
126
|
-
nextOneTimeWith: (value) => {
|
|
127
|
-
providedSubject.next(value);
|
|
128
|
-
providedSubject.complete();
|
|
129
|
-
onSubjectConfigured(providedSubject);
|
|
130
|
-
},
|
|
131
|
-
nextWithValues: (valuesConfigs) => {
|
|
132
|
-
if (valuesConfigs.length === 0) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
onSubjectConfigured(mergeSubjectWithDefaultValues(providedSubject, valuesConfigs));
|
|
136
|
-
},
|
|
137
|
-
throwWith: (value) => {
|
|
138
|
-
providedSubject.error(value);
|
|
139
|
-
onSubjectConfigured(providedSubject);
|
|
140
|
-
},
|
|
141
|
-
complete: () => {
|
|
142
|
-
providedSubject.complete();
|
|
143
|
-
onSubjectConfigured(providedSubject);
|
|
144
|
-
},
|
|
145
|
-
returnSubject: () => {
|
|
146
|
-
onSubjectConfigured(providedSubject);
|
|
147
|
-
return providedSubject;
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
function buildPerCallObservable(replaySubject, config) {
|
|
152
|
-
let observable = replaySubject.asObservable();
|
|
153
|
-
if (config.delay) {
|
|
154
|
-
observable = observable.pipe(operators.delay(config.delay));
|
|
155
|
-
}
|
|
156
|
-
if (!config.doNotComplete) {
|
|
157
|
-
observable = observable.pipe(operators.take(1));
|
|
158
|
-
}
|
|
159
|
-
return observable;
|
|
160
|
-
}
|
|
161
|
-
function addNextWithPerCall(objectToDecorate, returnValueContainer, onConfigured = () => void 0) {
|
|
162
|
-
decorate(objectToDecorate, {
|
|
163
|
-
nextWithPerCall: (valueConfigsPerCall) => {
|
|
164
|
-
const returnedSubjects = [];
|
|
165
|
-
if (valueConfigsPerCall.length === 0) {
|
|
166
|
-
return returnedSubjects;
|
|
167
|
-
}
|
|
168
|
-
const valuesPerCalls = [];
|
|
169
|
-
valueConfigsPerCall.forEach((config) => {
|
|
170
|
-
const replaySubject = createReplaySubject();
|
|
171
|
-
replaySubject.next(config.value);
|
|
172
|
-
returnedSubjects.push(replaySubject);
|
|
173
|
-
valuesPerCalls.push({ wrappedValue: buildPerCallObservable(replaySubject, config) });
|
|
174
|
-
});
|
|
175
|
-
returnValueContainer.valuesPerCalls = valuesPerCalls;
|
|
176
|
-
onConfigured(returnValueContainer);
|
|
177
|
-
return returnedSubjects;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
function addObservableHelpersToFunctionSpy(spyFunction, valueContainer) {
|
|
182
|
-
const subject = createReplaySubject();
|
|
183
|
-
addObservableHelpers(spyFunction, subject, (configuredSubject) => {
|
|
184
|
-
valueContainer.value = configuredSubject;
|
|
185
|
-
});
|
|
186
|
-
addNextWithPerCall(spyFunction, valueContainer);
|
|
187
|
-
}
|
|
188
|
-
function addObservableHelpersToCalledWithObject(calledWithObject, calledWithArgs) {
|
|
189
|
-
const subject = createReplaySubject();
|
|
190
|
-
const returnValueContainer = { value: void 0 };
|
|
191
|
-
addObservableHelpers(calledWithObject, subject, (configuredSubject) => {
|
|
192
|
-
returnValueContainer.value = configuredSubject;
|
|
193
|
-
calledWithObject.argsToValuesMap.set(calledWithArgs, returnValueContainer);
|
|
194
|
-
});
|
|
195
|
-
addNextWithPerCall(calledWithObject, returnValueContainer, (configured) => {
|
|
196
|
-
calledWithObject.argsToValuesMap.set(calledWithArgs, configured);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
function createObservableWithValues(valuesConfigs, config) {
|
|
200
|
-
const subject = createReplaySubject();
|
|
201
|
-
const values$ = mergeSubjectWithDefaultValues(subject, valuesConfigs);
|
|
202
|
-
return config?.returnSubject ? { values$, subject } : values$;
|
|
203
|
-
}
|
|
204
|
-
function createObservablePropSpy() {
|
|
205
|
-
const providedSubject = createReplaySubject();
|
|
206
|
-
let published$ = providedSubject;
|
|
207
|
-
const observableSpy = rxjs.defer(() => published$);
|
|
208
|
-
addObservableHelpers(observableSpy, providedSubject, (configuredSubject) => {
|
|
209
|
-
published$ = configuredSubject;
|
|
210
|
-
});
|
|
211
|
-
return observableSpy;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// src/lib/promise-spy.ts
|
|
215
|
-
function toResolvedPerCallValues(valueConfigsPerCall) {
|
|
216
|
-
return valueConfigsPerCall.map((config) => ({
|
|
217
|
-
wrappedValue: config.delay === void 0 ? Promise.resolve(config.value) : new Promise((resolve) => setTimeout(() => resolve(config.value), config.delay))
|
|
218
|
-
}));
|
|
219
|
-
}
|
|
220
|
-
function addPromiseHelpers(target, store) {
|
|
221
|
-
decorate(target, {
|
|
222
|
-
resolveWith: (value) => {
|
|
223
|
-
store({ value: Promise.resolve(value) });
|
|
224
|
-
},
|
|
225
|
-
rejectWith: (value) => {
|
|
226
|
-
store({ value, _isRejectedPromise: true });
|
|
227
|
-
},
|
|
228
|
-
resolveWithPerCall: (valueConfigsPerCall) => {
|
|
229
|
-
if (valueConfigsPerCall.length === 0) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
store({ value: void 0, valuesPerCalls: toResolvedPerCallValues(valueConfigsPerCall) });
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
function addPromiseHelpersToFunctionSpy(spyFunction, valueContainer) {
|
|
237
|
-
addPromiseHelpers(spyFunction, (container) => {
|
|
238
|
-
valueContainer.value = container.value;
|
|
239
|
-
valueContainer._isRejectedPromise = container._isRejectedPromise ?? false;
|
|
240
|
-
valueContainer.valuesPerCalls = container.valuesPerCalls ?? [];
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
function addPromiseHelpersToCalledWithObject(calledWithObject, calledWithArgs) {
|
|
244
|
-
addPromiseHelpers(calledWithObject, (container) => {
|
|
245
|
-
calledWithObject.argsToValuesMap.set(calledWithArgs, container);
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// src/lib/function-spy.ts
|
|
250
|
-
function isReturnValueContainer(value) {
|
|
251
|
-
return typeof value === "object" && value !== null && "value" in value;
|
|
252
|
-
}
|
|
253
|
-
function unwrapContainer(container) {
|
|
254
|
-
if (container._isRejectedPromise) {
|
|
255
|
-
return Promise.reject(container.value);
|
|
256
|
-
}
|
|
257
|
-
const wrapped = container.valuesPerCalls?.shift();
|
|
258
|
-
if (wrapped) {
|
|
259
|
-
return wrapped.wrappedValue;
|
|
260
|
-
}
|
|
261
|
-
return container.value;
|
|
262
|
-
}
|
|
263
|
-
function lookupConfigured(calledWithObject, actualArgs) {
|
|
264
|
-
const configured = calledWithObject.argsToValuesMap.get(actualArgs);
|
|
265
|
-
if (isReturnValueContainer(configured)) {
|
|
266
|
-
return { found: true, value: unwrapContainer(configured) };
|
|
267
|
-
}
|
|
268
|
-
return { found: false, value: void 0 };
|
|
269
|
-
}
|
|
270
|
-
function returnTheCorrectFakeValue(calledWithObject, mustBeCalledWithObject, valueContainer, actualArgs, functionName) {
|
|
271
|
-
if (calledWithObject.wasConfigured) {
|
|
272
|
-
const match = lookupConfigured(calledWithObject, actualArgs);
|
|
273
|
-
if (match.found) {
|
|
274
|
-
return match.value;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
if (mustBeCalledWithObject.wasConfigured) {
|
|
278
|
-
const match = lookupConfigured(mustBeCalledWithObject, actualArgs);
|
|
279
|
-
if (match.found) {
|
|
280
|
-
return match.value;
|
|
281
|
-
}
|
|
282
|
-
errorHandler.throwArgumentsError(actualArgs, functionName);
|
|
283
|
-
}
|
|
284
|
-
return unwrapContainer(valueContainer);
|
|
285
|
-
}
|
|
286
|
-
function addMethodsToCalledWith(calledWith, calledWithArgs) {
|
|
287
|
-
calledWith.wasConfigured = true;
|
|
288
|
-
decorate(calledWith, {
|
|
289
|
-
mockReturnValue: (value) => {
|
|
290
|
-
calledWith.argsToValuesMap.set(calledWithArgs, { value });
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
addPromiseHelpersToCalledWithObject(calledWith, calledWithArgs);
|
|
294
|
-
addObservableHelpersToCalledWithObject(calledWith, calledWithArgs);
|
|
295
|
-
return calledWith;
|
|
296
|
-
}
|
|
297
|
-
function createCalledWithObject() {
|
|
298
|
-
return { wasConfigured: false, argsToValuesMap: new ArgsMap() };
|
|
299
|
-
}
|
|
300
|
-
function createFunctionSpy(name) {
|
|
301
|
-
const calledWithObject = createCalledWithObject();
|
|
302
|
-
const mustBeCalledWithObject = createCalledWithObject();
|
|
303
|
-
const valueContainer = { value: void 0 };
|
|
304
|
-
const functionSpy = vitest.vi.fn(
|
|
305
|
-
(...actualArgs) => returnTheCorrectFakeValue(calledWithObject, mustBeCalledWithObject, valueContainer, actualArgs, name)
|
|
306
|
-
);
|
|
307
|
-
functionSpy.mockName(name);
|
|
308
|
-
addPromiseHelpersToFunctionSpy(functionSpy, valueContainer);
|
|
309
|
-
addObservableHelpersToFunctionSpy(functionSpy, valueContainer);
|
|
310
|
-
const spy = decorate(functionSpy, {
|
|
311
|
-
calledWith: (...calledWithArgs) => addMethodsToCalledWith(calledWithObject, calledWithArgs),
|
|
312
|
-
mustBeCalledWith: (...calledWithArgs) => addMethodsToCalledWith(mustBeCalledWithObject, calledWithArgs)
|
|
313
|
-
});
|
|
314
|
-
return exposeAsSpy(spy);
|
|
315
|
-
}
|
|
316
|
-
function exposeAsSpy(spy) {
|
|
317
|
-
return spy;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// src/lib/create-spy-from-class.ts
|
|
321
|
-
var EMPTY_CONFIGURATION = {
|
|
322
|
-
methodsToSpyOn: [],
|
|
323
|
-
observablePropsToSpyOn: [],
|
|
324
|
-
settersToSpyOn: [],
|
|
325
|
-
gettersToSpyOn: []
|
|
326
|
-
};
|
|
327
|
-
function extractMethodsFromObject(obj) {
|
|
328
|
-
const descriptors = Object.getOwnPropertyDescriptors(obj);
|
|
329
|
-
return Object.keys(descriptors).filter((name) => name !== "constructor" && !descriptors[name]?.get);
|
|
330
|
-
}
|
|
331
|
-
function getAllMethodNames(prototype) {
|
|
332
|
-
const methods = /* @__PURE__ */ new Set();
|
|
333
|
-
let current = prototype;
|
|
334
|
-
while (current) {
|
|
335
|
-
const parentObj = Object.getPrototypeOf(current);
|
|
336
|
-
if (parentObj) {
|
|
337
|
-
extractMethodsFromObject(current).forEach((name) => methods.add(name));
|
|
338
|
-
}
|
|
339
|
-
current = parentObj;
|
|
340
|
-
}
|
|
341
|
-
return [...methods];
|
|
342
|
-
}
|
|
343
|
-
function resolveConfiguration(methodsToSpyOnOrConfig) {
|
|
344
|
-
if (!methodsToSpyOnOrConfig) {
|
|
345
|
-
return { ...EMPTY_CONFIGURATION };
|
|
346
|
-
}
|
|
347
|
-
if (Array.isArray(methodsToSpyOnOrConfig)) {
|
|
348
|
-
return { ...EMPTY_CONFIGURATION, methodsToSpyOn: methodsToSpyOnOrConfig };
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
methodsToSpyOn: methodsToSpyOnOrConfig.methodsToSpyOn ?? [],
|
|
352
|
-
observablePropsToSpyOn: methodsToSpyOnOrConfig.observablePropsToSpyOn ?? [],
|
|
353
|
-
settersToSpyOn: methodsToSpyOnOrConfig.settersToSpyOn ?? [],
|
|
354
|
-
gettersToSpyOn: methodsToSpyOnOrConfig.gettersToSpyOn ?? []
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
function createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig) {
|
|
358
|
-
const { methodsToSpyOn, observablePropsToSpyOn, settersToSpyOn, gettersToSpyOn } = resolveConfiguration(methodsToSpyOnOrConfig);
|
|
359
|
-
const methodNames = methodsToSpyOn.length > 0 ? methodsToSpyOn : getAllMethodNames(ObjectClass.prototype);
|
|
360
|
-
const autoSpy = {};
|
|
361
|
-
observablePropsToSpyOn.forEach((observablePropName) => {
|
|
362
|
-
autoSpy[observablePropName] = createObservablePropSpy();
|
|
363
|
-
});
|
|
364
|
-
createAccessorsSpies(autoSpy, gettersToSpyOn, settersToSpyOn);
|
|
365
|
-
methodNames.forEach((methodName) => {
|
|
366
|
-
autoSpy[methodName] = createFunctionSpy(methodName);
|
|
367
|
-
});
|
|
368
|
-
return autoSpy;
|
|
369
|
-
}
|
|
370
|
-
function provideAutoSpy(ObjectClass, methodsToSpyOnOrConfig) {
|
|
371
|
-
return {
|
|
372
|
-
provide: ObjectClass,
|
|
373
|
-
useValue: createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig)
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
function injectSpy(token) {
|
|
377
|
-
const injected = testing.TestBed.inject(token);
|
|
378
|
-
return injected;
|
|
379
|
-
}
|
|
380
|
-
function mockReadonlyProp(object, property, value) {
|
|
381
|
-
Object.defineProperty(object, property, { get: () => value, configurable: true });
|
|
382
|
-
}
|
|
383
|
-
function mockReadonlyPropGetter(object, property, getter) {
|
|
384
|
-
Object.defineProperty(object, property, { get: getter, configurable: true });
|
|
385
|
-
}
|
|
386
|
-
function mockAccessorsProp(object, property) {
|
|
387
|
-
Object.defineProperty(object, property, { get: vitest.vi.fn(), set: vitest.vi.fn(), configurable: true });
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
exports.createFunctionSpy = createFunctionSpy;
|
|
391
|
-
exports.createObservableWithValues = createObservableWithValues;
|
|
392
|
-
exports.createSpyFromClass = createSpyFromClass;
|
|
393
|
-
exports.errorHandler = errorHandler;
|
|
394
|
-
exports.injectSpy = injectSpy;
|
|
395
|
-
exports.mockAccessorsProp = mockAccessorsProp;
|
|
396
|
-
exports.mockReadonlyProp = mockReadonlyProp;
|
|
397
|
-
exports.mockReadonlyPropGetter = mockReadonlyPropGetter;
|
|
398
|
-
exports.provideAutoSpy = provideAutoSpy;
|
|
399
|
-
//# sourceMappingURL=index.cjs.map
|
|
400
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
'use strict';var vitest=require('vitest');function m(e,t){Object.defineProperty(e,t,{get(){},set(r){},configurable:true});}function S(e,t,r){let n=t;return r==="setter"?vitest.vi.spyOn(e,n,"set"):vitest.vi.spyOn(e,n,"get")}function T(e,t,r){let n={getters:{},setters:{}};e.accessorSpies=n,t.forEach(o=>{m(e,o),n.getters[o]=S(e,o,"getter");}),r.forEach(o=>{Object.prototype.hasOwnProperty.call(e,o)||m(e,o),n.setters[o]=S(e,o,"setter");});}function x(e){return `'${e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function V(e,t){return Object.entries(e).map(([r,n])=>`${r}:${i(n,t)}`).join(",")}function W(e,t){return `new Map([${[...e.entries()].map(([n,o])=>`[${i(n,t)},${i(o,t)}]`).join(",")}])`}function M(e,t){if(t.has(e))return "[Circular]";t.add(e);let r;return e instanceof Date?r=`new Date(${e.getTime()})`:e instanceof Map?r=W(e,t):e instanceof Set?r=`new Set([${[...e].map(n=>i(n,t)).join(",")}])`:Array.isArray(e)?r=`[${e.map(n=>i(n,t)).join(",")}]`:r=`{${V(e,t)}}`,t.delete(e),r}function i(e,t=new WeakSet){return typeof e=="string"?x(e):typeof e=="bigint"?`${e}n`:typeof e=="symbol"?e.toString():typeof e=="function"?`[Function: ${e.name}]`:typeof e=="object"&&e!==null?M(e,t):Object.is(e,-0)?"-0":String(e)}var l=class{#e={};set(t,r){this.#e[this.#t(t)]=r;}get(t){return this.#e[this.#t(t)]}#t(t){return i(t)}};var A=e=>`The function '${e}' was configured with 'mustBeCalledWith' and expects to be called with specific arguments. `,F="But the function was called without any arguments.",E=e=>{let t=i(e);return `But the actual arguments were: ${t.substring(1,t.length-1)}`},d={throwArgumentsError(e,t){let r=e.length===0?F:E(e);throw new Error(A(t)+r)}};var H="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 O(){throw new Error(H);}function a(e,t){return Object.assign(e,t)}function _(e){return e.map(t=>({wrappedValue:t.delay===void 0?Promise.resolve(t.value):new Promise(r=>setTimeout(()=>r(t.value),t.delay))}))}function h(e,t){a(e,{resolveWith:r=>{t({value:Promise.resolve(r)});},rejectWith:r=>{t({value:r,_isRejectedPromise:true});},resolveWithPerCall:r=>{r.length!==0&&t({value:void 0,valuesPerCalls:_(r)});}});}function w(e,t){h(e,r=>{t.value=r.value,t._isRejectedPromise=r._isRejectedPromise??false,t.valuesPerCalls=r.valuesPerCalls??[];});}function C(e,t){h(e,r=>{e.argsToValuesMap.set(t,r);});}function z(e){return typeof e=="object"&&e!==null&&"value"in e}function P(e){if(e._isRejectedPromise)return Promise.reject(e.value);let t=e.valuesPerCalls?.shift();return t?t.wrappedValue:e.value}function j(e,t){let r=e.argsToValuesMap.get(t);return z(r)?{found:true,value:P(r)}:{found:false,value:void 0}}function I(e,t,r,n,o){if(e.wasConfigured){let s=j(e,n);if(s.found)return s.value}if(t.wasConfigured){let s=j(t,n);if(s.found)return s.value;d.throwArgumentsError(n,o);}return P(r)}function k(e,t){return e.wasConfigured=true,a(e,{mockReturnValue:r=>{e.argsToValuesMap.set(t,{value:r});}}),C(e,t),e}function v(){return {wasConfigured:false,argsToValuesMap:new l}}function b(e){let t=v(),r=v(),n={value:void 0},o=vitest.vi.fn((...u)=>I(t,r,n,u,e));o.mockName(e),w(o,n);let s=a(o,{calledWith:(...u)=>k(t,u),mustBeCalledWith:(...u)=>k(r,u)});return s}var R={methodsToSpyOn:[],observablePropsToSpyOn:[],settersToSpyOn:[],gettersToSpyOn:[]};function B(e){let t=Object.getOwnPropertyDescriptors(e);return Object.keys(t).filter(r=>r!=="constructor"&&!t[r]?.get)}function q(e){let t=new Set,r=e;for(;r;){let n=Object.getPrototypeOf(r);n&&B(r).forEach(o=>t.add(o)),r=n;}return [...t]}function D(e){return e?Array.isArray(e)?{...R,methodsToSpyOn:e}:{methodsToSpyOn:e.methodsToSpyOn??[],observablePropsToSpyOn:e.observablePropsToSpyOn??[],settersToSpyOn:e.settersToSpyOn??[],gettersToSpyOn:e.gettersToSpyOn??[]}:{...R}}function G(e,t){let{methodsToSpyOn:r,observablePropsToSpyOn:n,settersToSpyOn:o,gettersToSpyOn:s}=D(t),u=r.length>0?r:q(e.prototype),p={};return n.forEach(c=>{p[c]=O().createPropSpy();}),T(p,s,o),u.forEach(c=>{p[c]=b(c);}),p}exports.createFunctionSpy=b;exports.createSpyFromClass=G;exports.errorHandler=d;
|