vitest-auto-spy 4.2.0 → 4.3.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 +89 -2
- package/README.md +135 -6
- package/dist/angular.d.ts +2 -2
- package/dist/angular.js +276 -7
- package/dist/bun-angular.d.ts +3 -3
- package/dist/bun-angular.js +6 -6
- package/dist/bun.d.ts +72 -2
- package/dist/bun.js +4 -4
- package/dist/{chunk-DSIYS6Y5.js → chunk-D5LDT3W4.js} +1 -1
- package/dist/{chunk-2ZG27FVL.js → chunk-EMASXQDZ.js} +1 -1
- package/dist/{chunk-4KK3ES4P.js → chunk-FFKN6QKI.js} +22 -0
- package/dist/{chunk-4KCYFAJX.js → chunk-FYFF67EN.js} +23 -7
- package/dist/{chunk-5URFSYDT.js → chunk-GAY6LNAM.js} +300 -6
- package/dist/{chunk-WQZ2RKS7.js → chunk-KYAJCFUA.js} +1 -1
- package/dist/{chunk-KEKKEIRG.js → chunk-Z4VRMCW2.js} +1 -1
- package/dist/cli.js +606 -16
- package/dist/console.js +2 -2
- package/dist/diagnostics.d.ts +31 -1
- package/dist/diagnostics.js +350 -1
- package/dist/{expect-emission-BDuFuqTb.d.ts → expect-emission-Dy5CvsF2.d.ts} +27 -25
- package/dist/index.d.ts +2 -2
- package/dist/index.js +444 -111
- package/dist/jasmine.js +4 -4
- package/dist/nestjs.js +5 -5
- package/dist/node.cjs +272 -111
- package/dist/node.d.cts +2 -0
- package/dist/node.d.ts +2 -2
- package/dist/node.js +17 -5
- package/dist/react.d.ts +2 -2
- package/dist/react.js +5 -5
- package/dist/setup.js +4 -4
- package/dist/shared-state.js +4 -275
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +5 -5
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +6 -6
- package/dist/{zoneless-DGwkbWKm.d.ts → zoneless-LsBDcSNZ.d.ts} +1 -1
- package/package.json +6 -2
- package/skills/vitest-auto-spy/SKILL.md +4 -1
package/dist/angular.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { guardAccessorSpies, registerMockAdapter, getMockAdapter, getObservableSupport, getJasmineSupport, requireObservableSupport } from './shared-state.js';
|
|
2
|
-
export {
|
|
1
|
+
import { guardAccessorSpies, registerMockAdapter, getMockAdapter, getObservableSupport, getJasmineSupport, emissionTimeout, requireObservableSupport } from './shared-state.js';
|
|
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';
|
|
5
5
|
import { isStandalone, Component, Injector, runInInjectionContext, NO_ERRORS_SCHEMA, ApplicationRef, signal, computed, ɵSIGNAL as _SIGNAL, InjectionToken } from '@angular/core';
|
|
@@ -629,6 +629,28 @@ var ArgsMap = class {
|
|
|
629
629
|
const asymmetric = this.#matcherConfigs.map((config) => `[${config.described.join(",")}]`);
|
|
630
630
|
return [...Object.keys(this.#map), ...asymmetric];
|
|
631
631
|
}
|
|
632
|
+
/**
|
|
633
|
+
* Every configured argument list as a {@link ConfiguredEntry} — the same lists {@link configured}
|
|
634
|
+
* returns, each carrying its own position and its own predicate.
|
|
635
|
+
*
|
|
636
|
+
* The order is the order a lookup consults them (exact configs first, then the asymmetric ones in
|
|
637
|
+
* registration order), so the first entry whose `matches` holds is the config `get` would have
|
|
638
|
+
* answered from. That is what lets a reader be told "call 3 hit config 2" instead of a list of
|
|
639
|
+
* configs and a list of calls with nothing joining them.
|
|
640
|
+
*/
|
|
641
|
+
configuredEntries() {
|
|
642
|
+
const exact = Object.keys(this.#map).map((key, position) => ({
|
|
643
|
+
index: position + 1,
|
|
644
|
+
args: key,
|
|
645
|
+
matches: (actualArgs) => this.#serialize(actualArgs) === key
|
|
646
|
+
}));
|
|
647
|
+
const asymmetric = this.#matcherConfigs.map((config, position) => ({
|
|
648
|
+
index: exact.length + position + 1,
|
|
649
|
+
args: `[${config.described.join(",")}]`,
|
|
650
|
+
matches: (actualArgs) => this.#argsMatch(config, actualArgs)
|
|
651
|
+
}));
|
|
652
|
+
return [...exact, ...asymmetric];
|
|
653
|
+
}
|
|
632
654
|
/** Render one asymmetric config once, at registration time. See {@link MatcherConfig}. */
|
|
633
655
|
#buildMatcherConfig(key, value) {
|
|
634
656
|
const serialized = [];
|
|
@@ -1506,7 +1528,12 @@ function resolveAccessors(prototype, config) {
|
|
|
1506
1528
|
};
|
|
1507
1529
|
}
|
|
1508
1530
|
function resolveMethodNames(ObjectClass, config) {
|
|
1509
|
-
|
|
1531
|
+
return mergeMethodNames(
|
|
1532
|
+
config.onlyMethodsToSpyOn.length > 0 ? config.onlyMethodsToSpyOn : getAllMethodNames(ObjectClass.prototype),
|
|
1533
|
+
config
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
function mergeMethodNames(base, config) {
|
|
1510
1537
|
if (config.methodsToSpyOn.length === 0 && config.instanceMethodsToSpyOn.length === 0) {
|
|
1511
1538
|
return base;
|
|
1512
1539
|
}
|
|
@@ -1545,7 +1572,7 @@ function warnOnAccessorNamingAMethod(ObjectClass, config) {
|
|
|
1545
1572
|
function isCallable2(value) {
|
|
1546
1573
|
return typeof value === "function";
|
|
1547
1574
|
}
|
|
1548
|
-
function applyReturns(autoSpy,
|
|
1575
|
+
function applyReturns(autoSpy, factory, returns) {
|
|
1549
1576
|
const entries = Object.entries(returns);
|
|
1550
1577
|
if (entries.length === 0) {
|
|
1551
1578
|
return;
|
|
@@ -1556,7 +1583,7 @@ function applyReturns(autoSpy, ObjectClass, returns) {
|
|
|
1556
1583
|
if (!isCallable2(spy)) {
|
|
1557
1584
|
console.warn(
|
|
1558
1585
|
withDocs(
|
|
1559
|
-
`[vitest-auto-spy]
|
|
1586
|
+
`[vitest-auto-spy] ${factory}: returns names '${name}', which is not a spied method of the spy. Check the spelling, and check that a restricting onlyMethodsToSpyOn list did not leave it out \u2014 a value configured for a method that is not there is silently never returned.`,
|
|
1560
1587
|
DOCS_LINKS.createSpyFromClass
|
|
1561
1588
|
)
|
|
1562
1589
|
);
|
|
@@ -1608,7 +1635,7 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
|
|
|
1608
1635
|
function createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig) {
|
|
1609
1636
|
const config = resolveConfiguration(methodsToSpyOnOrConfig);
|
|
1610
1637
|
const autoSpy = assembleSpy(ObjectClass, config);
|
|
1611
|
-
applyReturns(autoSpy, ObjectClass
|
|
1638
|
+
applyReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config.returns);
|
|
1612
1639
|
applyOverrides(autoSpy, config.overrides);
|
|
1613
1640
|
return autoSpy;
|
|
1614
1641
|
}
|
|
@@ -2737,6 +2764,248 @@ function registerSignalMatchers() {
|
|
|
2737
2764
|
}
|
|
2738
2765
|
});
|
|
2739
2766
|
}
|
|
2767
|
+
|
|
2768
|
+
// src/lib/error-anchor.ts
|
|
2769
|
+
var OWN_FAILURE = /* @__PURE__ */ Symbol("vitest-auto-spy.own-failure");
|
|
2770
|
+
function ownFailure(message, options) {
|
|
2771
|
+
const error = new Error(message, options);
|
|
2772
|
+
Object.defineProperty(error, OWN_FAILURE, { value: true });
|
|
2773
|
+
return error;
|
|
2774
|
+
}
|
|
2775
|
+
function anchorOf(stack, boundaryName) {
|
|
2776
|
+
const frames = framesAfter(frameLines(stack), boundaryName);
|
|
2777
|
+
return (error) => anchor(frames, error);
|
|
2778
|
+
}
|
|
2779
|
+
function captureAnchor(boundary, host = Error) {
|
|
2780
|
+
const holder = new Error();
|
|
2781
|
+
const capture = host.captureStackTrace;
|
|
2782
|
+
if (capture) {
|
|
2783
|
+
capture(holder, boundary);
|
|
2784
|
+
return anchorOf(holder.stack, "");
|
|
2785
|
+
}
|
|
2786
|
+
return anchorOf(holder.stack, boundary.name);
|
|
2787
|
+
}
|
|
2788
|
+
function anchor(frames, error) {
|
|
2789
|
+
if (frames.length === 0 || Reflect.get(error, OWN_FAILURE) !== true) {
|
|
2790
|
+
return error;
|
|
2791
|
+
}
|
|
2792
|
+
error.stack = [`${error.name}: ${error.message}`, ...frames].join("\n");
|
|
2793
|
+
return error;
|
|
2794
|
+
}
|
|
2795
|
+
function frameLines(stack) {
|
|
2796
|
+
const lines = String(stack).split("\n");
|
|
2797
|
+
const first = lines.findIndex(isFrame);
|
|
2798
|
+
return first < 0 ? [] : lines.slice(first);
|
|
2799
|
+
}
|
|
2800
|
+
function isFrame(line) {
|
|
2801
|
+
return /^\s*at\s/.test(line) || /^\S*@/.test(line);
|
|
2802
|
+
}
|
|
2803
|
+
function framesAfter(frames, boundaryName) {
|
|
2804
|
+
const boundary = boundaryName === "" ? -1 : frames.findIndex((frame) => frame.includes(boundaryName));
|
|
2805
|
+
return boundary < 0 ? frames : frames.slice(boundary + 1);
|
|
2806
|
+
}
|
|
2807
|
+
function subscribeToSource(source$, observer) {
|
|
2808
|
+
if (isRxjsSource(source$)) {
|
|
2809
|
+
return source$.subscribe(observer);
|
|
2810
|
+
}
|
|
2811
|
+
return source$.subscribe(asHybridObserver(observer));
|
|
2812
|
+
}
|
|
2813
|
+
function isRxjsSource(source$) {
|
|
2814
|
+
return typeof Reflect.get(source$, "pipe") === "function";
|
|
2815
|
+
}
|
|
2816
|
+
function asHybridObserver(observer) {
|
|
2817
|
+
const listener = (value) => observer.next(value);
|
|
2818
|
+
return Object.assign(listener, observer);
|
|
2819
|
+
}
|
|
2820
|
+
var setTimer2 = globalThis.setTimeout.bind(globalThis);
|
|
2821
|
+
var clearTimer2 = globalThis.clearTimeout.bind(globalThis);
|
|
2822
|
+
function describeSource(options) {
|
|
2823
|
+
return options?.label ?? "the observable";
|
|
2824
|
+
}
|
|
2825
|
+
function accepted(values, options) {
|
|
2826
|
+
const past = options?.skip ? values.slice(options.skip) : values;
|
|
2827
|
+
const until = options?.until;
|
|
2828
|
+
return until ? past.filter((value) => until(value)) : past;
|
|
2829
|
+
}
|
|
2830
|
+
function describeExpectation(count, options) {
|
|
2831
|
+
return options?.until ? `${count} matching` : String(count);
|
|
2832
|
+
}
|
|
2833
|
+
function subscribeAndCollect(source$, options, settle, handlers) {
|
|
2834
|
+
const values = [];
|
|
2835
|
+
let subscription = void 0;
|
|
2836
|
+
let stopped = false;
|
|
2837
|
+
const stop = () => {
|
|
2838
|
+
stopped = true;
|
|
2839
|
+
clearTimer2(timer);
|
|
2840
|
+
subscription?.unsubscribe();
|
|
2841
|
+
};
|
|
2842
|
+
const timeout = options?.timeout ?? emissionTimeout();
|
|
2843
|
+
const timer = timeout > 0 ? setTimer2(() => {
|
|
2844
|
+
stop();
|
|
2845
|
+
settle.reject(handlers.onTimeout(values, options, timeout));
|
|
2846
|
+
}, timeout) : void 0;
|
|
2847
|
+
subscription = subscribeToSource(source$, {
|
|
2848
|
+
next: (value) => {
|
|
2849
|
+
values.push(value);
|
|
2850
|
+
if (handlers.isDone(values)) {
|
|
2851
|
+
stop();
|
|
2852
|
+
settle.resolve(values);
|
|
2853
|
+
}
|
|
2854
|
+
},
|
|
2855
|
+
error: (error) => {
|
|
2856
|
+
stop();
|
|
2857
|
+
handlers.onError(error, options, settle);
|
|
2858
|
+
},
|
|
2859
|
+
complete: () => {
|
|
2860
|
+
stop();
|
|
2861
|
+
handlers.onComplete(values);
|
|
2862
|
+
}
|
|
2863
|
+
});
|
|
2864
|
+
if (stopped) {
|
|
2865
|
+
subscription.unsubscribe();
|
|
2866
|
+
}
|
|
2867
|
+
if (!stopped) {
|
|
2868
|
+
options?.advance?.();
|
|
2869
|
+
}
|
|
2870
|
+
return { values, stop };
|
|
2871
|
+
}
|
|
2872
|
+
function anchoredRejecter(reject, anchor2) {
|
|
2873
|
+
return (error) => reject(anchor2(error));
|
|
2874
|
+
}
|
|
2875
|
+
function timeoutError(values, options, waited) {
|
|
2876
|
+
return ownFailure(
|
|
2877
|
+
`${describeSource(options)} did not emit within ${waited} ms (${values.length} emission(s) received). Either the stream never fired \u2014 check the trigger and any provider spy feeding it \u2014 or it is slower than the timeout; raise it with \`{ timeout: \u2026 }\`. This wait is real time even under fake timers, on purpose: a virtual watchdog would race the timers your spec advances. Lower it with \`setEmissionTimeout(100)\` in the setup file rather than disabling it with \`{ timeout: 0 }\`, which leaves the next silent stream with no message at all.`
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2880
|
+
function rejectAsSourceError(error, options, settle) {
|
|
2881
|
+
settle.reject(ownFailure(`${describeSource(options)} errored instead of emitting: ${String(error)}`, { cause: error }));
|
|
2882
|
+
}
|
|
2883
|
+
function completedError(values, expected, options) {
|
|
2884
|
+
return ownFailure(
|
|
2885
|
+
`${describeSource(options)} completed after ${values.length} emission(s), expected ${describeExpectation(expected, options)}. A completed-but-empty stream is the usual sign that the value was produced before the subscription.`
|
|
2886
|
+
);
|
|
2887
|
+
}
|
|
2888
|
+
function expectEmission(source$, options) {
|
|
2889
|
+
return collectEmissions(source$, 1, options, captureAnchor(expectEmission)).then((values) => firstOf(values));
|
|
2890
|
+
}
|
|
2891
|
+
function firstOf(values) {
|
|
2892
|
+
return values[0];
|
|
2893
|
+
}
|
|
2894
|
+
function expectEmissions(source$, count, options) {
|
|
2895
|
+
return collectEmissions(source$, count, options, captureAnchor(expectEmissions));
|
|
2896
|
+
}
|
|
2897
|
+
function collectEmissions(source$, count, options, anchor2) {
|
|
2898
|
+
return new Promise((resolve, reject) => {
|
|
2899
|
+
const fail = anchoredRejecter(reject, anchor2);
|
|
2900
|
+
subscribeAndCollect(
|
|
2901
|
+
source$,
|
|
2902
|
+
options,
|
|
2903
|
+
// Resolved with everything that arrived, then narrowed to the accepted ones: the collector's
|
|
2904
|
+
// job is to record, and `skip` / `until` decide what the caller is handed.
|
|
2905
|
+
{ resolve: (values) => resolve(accepted(values, options).slice(0, count)), reject: fail },
|
|
2906
|
+
{
|
|
2907
|
+
isDone: (values) => accepted(values, options).length >= count,
|
|
2908
|
+
onComplete: (values) => fail(completedError(values, count, options)),
|
|
2909
|
+
onTimeout: timeoutError,
|
|
2910
|
+
onError: rejectAsSourceError
|
|
2911
|
+
}
|
|
2912
|
+
);
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
function expectNoEmission(source$, options) {
|
|
2916
|
+
const quietFor = options?.timeout ?? 0;
|
|
2917
|
+
const anchor2 = captureAnchor(expectNoEmission);
|
|
2918
|
+
let quietWindow = void 0;
|
|
2919
|
+
return new Promise((resolve, reject) => {
|
|
2920
|
+
const fail = anchoredRejecter(reject, anchor2);
|
|
2921
|
+
const collector = subscribeAndCollect(
|
|
2922
|
+
source$,
|
|
2923
|
+
{ ...options, timeout: 0 },
|
|
2924
|
+
{
|
|
2925
|
+
resolve: (emitted) => fail(unexpectedEmissionError(accepted(emitted, options), options)),
|
|
2926
|
+
reject: fail
|
|
2927
|
+
},
|
|
2928
|
+
{
|
|
2929
|
+
isDone: (values) => accepted(values, options).length > 0,
|
|
2930
|
+
onComplete: () => void 0,
|
|
2931
|
+
// Never reached — the watchdog is off (`timeout: 0`) and the quiet window below is this
|
|
2932
|
+
// helper's own timer. Named rather than inlined so it is not an uncalled arrow.
|
|
2933
|
+
onTimeout: timeoutError,
|
|
2934
|
+
onError: rejectAsSourceError
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
quietWindow = setTimer2(() => {
|
|
2938
|
+
collector.stop();
|
|
2939
|
+
resolve();
|
|
2940
|
+
}, quietFor);
|
|
2941
|
+
}).finally(() => {
|
|
2942
|
+
clearTimer2(quietWindow);
|
|
2943
|
+
});
|
|
2944
|
+
}
|
|
2945
|
+
function expectCompletion(source$, options) {
|
|
2946
|
+
const anchor2 = captureAnchor(expectCompletion);
|
|
2947
|
+
return new Promise((resolve, reject) => {
|
|
2948
|
+
subscribeAndCollect(
|
|
2949
|
+
source$,
|
|
2950
|
+
options,
|
|
2951
|
+
{ resolve, reject: anchoredRejecter(reject, anchor2) },
|
|
2952
|
+
{
|
|
2953
|
+
// Emissions are collected for the failure message, but only completion settles this.
|
|
2954
|
+
isDone: staysOpen,
|
|
2955
|
+
onComplete: resolve,
|
|
2956
|
+
onTimeout: notCompletedError,
|
|
2957
|
+
onError: rejectAsNotCompleted
|
|
2958
|
+
}
|
|
2959
|
+
);
|
|
2960
|
+
}).then(() => void 0);
|
|
2961
|
+
}
|
|
2962
|
+
function staysOpen() {
|
|
2963
|
+
return false;
|
|
2964
|
+
}
|
|
2965
|
+
function notCompletedError(values, options, waited) {
|
|
2966
|
+
return ownFailure(
|
|
2967
|
+
`${describeSource(options)} did not complete within ${waited} ms (${values.length} emission(s) received). A stream that keeps running usually means the completing operator never ran \u2014 check \`take\`, \`first\`, \`takeUntil\`, or a Subject nobody calls \`complete()\` on. The wait is real time even under fake timers; raise it with \`{ timeout: \u2026 }\`, or lower the suite default with \`setEmissionTimeout(\u2026)\`.`
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
function rejectAsNotCompleted(error, options, settle) {
|
|
2971
|
+
settle.reject(ownFailure(`${describeSource(options)} errored instead of completing: ${String(error)}`, { cause: error }));
|
|
2972
|
+
}
|
|
2973
|
+
function expectError(source$, options) {
|
|
2974
|
+
const anchor2 = captureAnchor(expectError);
|
|
2975
|
+
return new Promise((resolve, reject) => {
|
|
2976
|
+
const fail = anchoredRejecter(reject, anchor2);
|
|
2977
|
+
subscribeAndCollect(
|
|
2978
|
+
source$,
|
|
2979
|
+
options,
|
|
2980
|
+
{ resolve, reject: fail },
|
|
2981
|
+
{
|
|
2982
|
+
// Only `error` settles this one: an emission is not the answer, and neither is completion.
|
|
2983
|
+
isDone: staysOpen,
|
|
2984
|
+
onComplete: (values) => fail(completedWithoutErrorError(values, options)),
|
|
2985
|
+
onTimeout: notErroredError,
|
|
2986
|
+
onError: resolveWithError
|
|
2987
|
+
}
|
|
2988
|
+
);
|
|
2989
|
+
}).then((values) => firstOf(values));
|
|
2990
|
+
}
|
|
2991
|
+
function completedWithoutErrorError(values, options) {
|
|
2992
|
+
return ownFailure(
|
|
2993
|
+
`${describeSource(options)} completed after ${values.length} emission(s) without erroring, but an error was expected. Check that the failure path is the one the spec set up \u2014 a spy configured with \`resolveWith\`/\`nextWith\` rather than \`rejectWith\`/\`throwWith\` produces exactly this.`
|
|
2994
|
+
);
|
|
2995
|
+
}
|
|
2996
|
+
function notErroredError(values, options, waited) {
|
|
2997
|
+
return ownFailure(
|
|
2998
|
+
`${describeSource(options)} did not error within ${waited} ms (${values.length} emission(s) received). The stream is still running: nothing failed, and nothing completed either.`
|
|
2999
|
+
);
|
|
3000
|
+
}
|
|
3001
|
+
function resolveWithError(error, _options, settle) {
|
|
3002
|
+
settle.resolve([error]);
|
|
3003
|
+
}
|
|
3004
|
+
function unexpectedEmissionError(values, options) {
|
|
3005
|
+
return ownFailure(`${describeSource(options)} emitted ${serializeValue(values[0])} but was expected to stay silent.`);
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
// src/angular.ts
|
|
2740
3009
|
useVitestAdapter();
|
|
2741
3010
|
|
|
2742
|
-
export { assertComponentDefIntact, assertNgModuleScopes, assertNoPendingRequests, countMockedProps, createDirectiveHost, createWithAutoSpies, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, extendWithAutoSpies, flushEffects, formatSpecTiming, getTestBedTiming, injectSpy, instrumentTestBed, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockResourceProp, mockSignalProp, mockValueProp, overrideAutoSpy, overrideComponentProvider, provideAutoSpy, provideAutoSpyForToken, registerDirectiveMatchers, registerResourceMatchers, registerSignalMatchers, renderShallow, reportSpecTiming, restoreMockedProps, runEffect, settleResource, setupAngularTestEnv, stable, trackInjections };
|
|
3011
|
+
export { assertComponentDefIntact, assertNgModuleScopes, assertNoPendingRequests, countMockedProps, createDirectiveHost, createWithAutoSpies, disableAngularDiagnostics, disableTestBedDiagnostics, enableAngularDiagnostics, enableTestBedDiagnostics, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, extendWithAutoSpies, flushEffects, formatSpecTiming, getTestBedTiming, injectSpy, instrumentTestBed, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockResourceProp, mockSignalProp, mockValueProp, overrideAutoSpy, overrideComponentProvider, provideAutoSpy, provideAutoSpyForToken, registerDirectiveMatchers, registerResourceMatchers, registerSignalMatchers, renderShallow, reportSpecTiming, restoreMockedProps, runEffect, settleResource, setupAngularTestEnv, stable, trackInjections };
|
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 Overloads, P as PropStubValue, S as Spy, t as SpyDisposable, u as SpyOptions, v as StrictSpyConfiguration, w as SubjectLike, x as SubjectOf, U as UnstubbedCall, y as UnstubbedCallHandler, V as ValueConfig, z as ValueConfigPerCall, W as WithMockReturnValue } from './types-CQLPjw8z.js';
|
|
2
|
-
export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, resetAutoSpy, settleDynamicImport, stubConstructor, withOverrides } from './bun.js';
|
|
3
|
-
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
2
|
+
export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, ConstructorSpy, FixtureFactory, FlushUntilOptions, MockDeepOptions, ModuleNamespace, ModuleNamespaceOptions, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, createSpyFromInstance, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, resetAutoSpy, restoreSpiedInstance, settleDynamicImport, stubConstructor, withOverrides } from './bun.js';
|
|
3
|
+
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-Dy5CvsF2.js';
|
|
4
4
|
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-Dp2ZMFqj.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-LsBDcSNZ.js';
|
|
7
7
|
import 'vitest';
|
|
8
8
|
import '@angular/core';
|
|
9
9
|
import '@angular/core/testing';
|
package/dist/bun-angular.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { flushEffects } from './chunk-5BPM3BLI.js';
|
|
2
2
|
export { flushEffects, stable } from './chunk-5BPM3BLI.js';
|
|
3
3
|
import './chunk-Y4YG7UOK.js';
|
|
4
|
-
import { createSpyForToken } from './chunk-
|
|
4
|
+
import { createSpyForToken } from './chunk-Z4VRMCW2.js';
|
|
5
5
|
import './chunk-NQXXUJPS.js';
|
|
6
|
-
export { asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, setEmissionTimeout, settleDynamicImport, stubConstructor, withOverrides } from './chunk-
|
|
7
|
-
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-
|
|
8
|
-
import { createSpyFromClass } from './chunk-
|
|
9
|
-
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-
|
|
10
|
-
export { createFunctionSpy, errorHandler } from './chunk-
|
|
6
|
+
export { asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, stubConstructor, withOverrides } from './chunk-GAY6LNAM.js';
|
|
7
|
+
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-D5LDT3W4.js';
|
|
8
|
+
import { createSpyFromClass } from './chunk-FYFF67EN.js';
|
|
9
|
+
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-FYFF67EN.js';
|
|
10
|
+
export { createFunctionSpy, errorHandler } from './chunk-FFKN6QKI.js';
|
|
11
11
|
import './chunk-PC3FAZT3.js';
|
|
12
12
|
import { isAutoSpyLike } from './chunk-XRVVZXOM.js';
|
|
13
13
|
import { withDocs, DOCS_LINKS } from './chunk-B45HLBA4.js';
|
package/dist/bun.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { u as SpyOptions, C as ClassType, k as ClassSpyConfiguration, o as OnlyMethodKeysOf, S as Spy, m as DeepPartial, D as DeepMockProxy, F as Func, y as UnstubbedCallHandler, g as AddSpyMethodsByReturnTypes } from './types-CQLPjw8z.js';
|
|
2
2
|
export { A as AccessorKeysOf, a as AddAccessorsSpies, b as AddCalledWithObservable, c as AddCalledWithPromise, d as AddCalledWithSpyMethods, e as AddObservableSpyMethods, f as AddPromiseSpyMethods, h as AddThrowHelper, i as AddVoidReturnHelpers, j as AutoSpyRxjsTypes, l as CompleteValueConfig, E as ErrorValueConfig, M as MethodReturns, n as Mutable, N as NextValueConfig, O as ObservableLike, p as OnlyObservablePropsOf, q as OnlyPropsOf, r as Overload, s as Overloads, P as PropStubValue, t as SpyDisposable, v as StrictSpyConfiguration, w as SubjectLike, x as SubjectOf, U as UnstubbedCall, V as ValueConfig, z as ValueConfigPerCall, W as WithMockReturnValue } from './types-CQLPjw8z.js';
|
|
3
|
-
export { A as AutoMockConfiguration, C as CallbackSubscribable, E as EmissionObserver, a as EmissionOptions, b as EmissionSource, S as SubscribableLike, c as autoMocked, d as createAutoMock, e as expectCompletion, f as expectEmission, g as expectEmissions, h as expectError, i as expectNoEmission, s as setEmissionTimeout } from './expect-emission-
|
|
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-Dy5CvsF2.js';
|
|
4
4
|
export { A as AccessorImplementations, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as restoreMockedProps } from './prop-mock-Dp2ZMFqj.js';
|
|
5
5
|
export { d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-B1pqa-Sh.js';
|
|
6
6
|
import { Mock } from 'vitest';
|
|
@@ -30,6 +30,48 @@ import { Mock } from 'vitest';
|
|
|
30
30
|
*/
|
|
31
31
|
declare function createSpyFromClass<T, Options extends SpyOptions = SpyOptions>(ObjectClass: ClassType<T>, methodsToSpyOnOrConfig?: ClassSpyConfiguration<T> | OnlyMethodKeysOf<T>[]): Spy<T, Options>;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Undo every {@link createSpyFromInstance} patch on `instance`, newest first. A no-op on an object
|
|
35
|
+
* that was never spied, or that has already been restored.
|
|
36
|
+
*
|
|
37
|
+
* `restoreMockedProps()` (and therefore `setupAutoSpy()`) undoes the same patches as part of its
|
|
38
|
+
* sweep — this is the targeted form, for an object that has to be real again inside the same test.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* restoreSpiedInstance(client); // client.send is the real method again
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function restoreSpiedInstance(instance: object): void;
|
|
46
|
+
/**
|
|
47
|
+
* Replace an existing object's methods with this library's spies, in place, and hand it back typed
|
|
48
|
+
* as a double.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const client = new PaymentsClient(config); // a real object the test already holds
|
|
53
|
+
* const spy = createSpyFromInstance(client);
|
|
54
|
+
*
|
|
55
|
+
* spy.charge.calledWith(100).resolveWith({ ok: true });
|
|
56
|
+
* await service.pay(); // the code under test still holds `client`, and sees the spy
|
|
57
|
+
*
|
|
58
|
+
* restoreSpiedInstance(client);
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @remarks
|
|
62
|
+
* Discovery takes the object's own function-valued fields *and* every prototype method up to but not
|
|
63
|
+
* including `Object.prototype`, so an arrow-function property needs no `instanceMethodsToSpyOn` here
|
|
64
|
+
* and `hasOwnProperty` is never replaced. The configuration is {@link createSpyFromClass}', minus
|
|
65
|
+
* the two options that describe a double being built rather than an object being patched:
|
|
66
|
+
* `lazySpies` (the members already exist, so there is nothing to defer) and `fillMissing` (an
|
|
67
|
+
* instance is not an erased `abstract` declaration).
|
|
68
|
+
*
|
|
69
|
+
* The returned value **is** the argument. `using spy = createSpyFromInstance(client)` restores the
|
|
70
|
+
* object at the end of the block rather than merely resetting it, which is the only sense `dispose`
|
|
71
|
+
* can have for an object the consumer owns.
|
|
72
|
+
*/
|
|
73
|
+
declare function createSpyFromInstance<T extends object, Options extends SpyOptions = SpyOptions>(instance: T, methodsToSpyOnOrConfig?: ClassSpyConfiguration<T> | OnlyMethodKeysOf<T>[]): Spy<T, Options>;
|
|
74
|
+
|
|
33
75
|
/**
|
|
34
76
|
* `createMock` — a typed stand-in built from the fields a test actually touches.
|
|
35
77
|
*
|
|
@@ -324,6 +366,24 @@ declare function clearAutoSpy(spy: object): void;
|
|
|
324
366
|
*/
|
|
325
367
|
declare function resetAutoSpy(spy: object): void;
|
|
326
368
|
|
|
369
|
+
/**
|
|
370
|
+
* One registered config, addressable on its own.
|
|
371
|
+
*
|
|
372
|
+
* {@link ArgsMap.configured} renders every config as a string, which is all a failure message
|
|
373
|
+
* needs. Attributing an actual call to *which* config it hit needs a handle instead — re-rendering
|
|
374
|
+
* the text and comparing it is not one, because two chains can render the same list.
|
|
375
|
+
*
|
|
376
|
+
* Built on demand: nothing here is written by `set` or read by `get`, so the match path is
|
|
377
|
+
* untouched by the existence of this surface.
|
|
378
|
+
*/
|
|
379
|
+
interface ConfiguredEntry {
|
|
380
|
+
/** 1-based position in {@link ArgsMap.configuredEntries}, in the order a lookup consults them. */
|
|
381
|
+
readonly index: number;
|
|
382
|
+
/** The config's argument list, rendered the way {@link ArgsMap.configured} renders it. */
|
|
383
|
+
readonly args: string;
|
|
384
|
+
/** Whether an actual call's arguments hit this config. */
|
|
385
|
+
matches(actualArgs: unknown[]): boolean;
|
|
386
|
+
}
|
|
327
387
|
declare class ArgsMap {
|
|
328
388
|
#private;
|
|
329
389
|
set(key: unknown, value: unknown): void;
|
|
@@ -337,6 +397,16 @@ declare class ArgsMap {
|
|
|
337
397
|
* assembling text it already has.
|
|
338
398
|
*/
|
|
339
399
|
configured(): string[];
|
|
400
|
+
/**
|
|
401
|
+
* Every configured argument list as a {@link ConfiguredEntry} — the same lists {@link configured}
|
|
402
|
+
* returns, each carrying its own position and its own predicate.
|
|
403
|
+
*
|
|
404
|
+
* The order is the order a lookup consults them (exact configs first, then the asymmetric ones in
|
|
405
|
+
* registration order), so the first entry whose `matches` holds is the config `get` would have
|
|
406
|
+
* answered from. That is what lets a reader be told "call 3 hit config 2" instead of a list of
|
|
407
|
+
* configs and a list of calls with nothing joining them.
|
|
408
|
+
*/
|
|
409
|
+
configuredEntries(): ConfiguredEntry[];
|
|
340
410
|
}
|
|
341
411
|
|
|
342
412
|
/**
|
|
@@ -829,4 +899,4 @@ type ModuleNamespace<T extends object> = T & {
|
|
|
829
899
|
*/
|
|
830
900
|
declare function moduleNamespace<T extends object>(exports: T, options?: ModuleNamespaceOptions): ModuleNamespace<T>;
|
|
831
901
|
|
|
832
|
-
export { AddSpyMethodsByReturnTypes, type ArgCaptor, type AsInstances, type AssertMockedOptions, ClassSpyConfiguration, ClassType, type ConstructorMock, type ConstructorSpy, DeepMockProxy, DeepPartial, type FixtureFactory, type FlushUntilOptions, Func, type MockDeepOptions, type ModuleNamespace, type ModuleNamespaceOptions, OnlyMethodKeysOf, Spy, SpyOptions, UnstubbedCallHandler, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, resetAutoSpy, settleDynamicImport, stubConstructor, withOverrides };
|
|
902
|
+
export { AddSpyMethodsByReturnTypes, type ArgCaptor, type AsInstances, type AssertMockedOptions, ClassSpyConfiguration, ClassType, type ConstructorMock, type ConstructorSpy, DeepMockProxy, DeepPartial, type FixtureFactory, type FlushUntilOptions, Func, type MockDeepOptions, type ModuleNamespace, type ModuleNamespaceOptions, OnlyMethodKeysOf, Spy, SpyOptions, UnstubbedCallHandler, asInstance, asInstances, asSpy, assertMocked, captureArg, clearAutoSpy, createFixture, createFixtureFactory, createFunctionSpy, createMock, createSpyClass, createSpyFromClass, createSpyFromInstance, errorHandler, flushEventLoop, flushEventLoopUntil, mockConstructor, mockDeep, moduleNamespace, narrow, resetAutoSpy, restoreSpiedInstance, settleDynamicImport, stubConstructor, withOverrides };
|
package/dist/bun.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import './chunk-Y4YG7UOK.js';
|
|
2
2
|
import './chunk-NQXXUJPS.js';
|
|
3
|
-
export { asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createMock, createSpyClass, describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, setEmissionTimeout, settleDynamicImport, stubConstructor, withOverrides } from './chunk-
|
|
4
|
-
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-
|
|
5
|
-
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-
|
|
6
|
-
export { createFunctionSpy, errorHandler } from './chunk-
|
|
3
|
+
export { asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, stubConstructor, withOverrides } from './chunk-GAY6LNAM.js';
|
|
4
|
+
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps } from './chunk-D5LDT3W4.js';
|
|
5
|
+
export { autoMocked, clearAutoSpy, createAutoMock, createSpyFromClass, resetAutoSpy } from './chunk-FYFF67EN.js';
|
|
6
|
+
export { createFunctionSpy, errorHandler } from './chunk-FFKN6QKI.js';
|
|
7
7
|
import './chunk-PC3FAZT3.js';
|
|
8
8
|
import './chunk-XRVVZXOM.js';
|
|
9
9
|
import './chunk-B45HLBA4.js';
|
|
@@ -122,4 +122,4 @@ function mockAccessorsProp(object, property, accessors) {
|
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, restoreMockedProps };
|
|
125
|
+
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, redefineFailure, restoreMockedProps };
|
|
@@ -247,6 +247,28 @@ var ArgsMap = class {
|
|
|
247
247
|
const asymmetric = this.#matcherConfigs.map((config) => `[${config.described.join(",")}]`);
|
|
248
248
|
return [...Object.keys(this.#map), ...asymmetric];
|
|
249
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Every configured argument list as a {@link ConfiguredEntry} — the same lists {@link configured}
|
|
252
|
+
* returns, each carrying its own position and its own predicate.
|
|
253
|
+
*
|
|
254
|
+
* The order is the order a lookup consults them (exact configs first, then the asymmetric ones in
|
|
255
|
+
* registration order), so the first entry whose `matches` holds is the config `get` would have
|
|
256
|
+
* answered from. That is what lets a reader be told "call 3 hit config 2" instead of a list of
|
|
257
|
+
* configs and a list of calls with nothing joining them.
|
|
258
|
+
*/
|
|
259
|
+
configuredEntries() {
|
|
260
|
+
const exact = Object.keys(this.#map).map((key, position) => ({
|
|
261
|
+
index: position + 1,
|
|
262
|
+
args: key,
|
|
263
|
+
matches: (actualArgs) => this.#serialize(actualArgs) === key
|
|
264
|
+
}));
|
|
265
|
+
const asymmetric = this.#matcherConfigs.map((config, position) => ({
|
|
266
|
+
index: exact.length + position + 1,
|
|
267
|
+
args: `[${config.described.join(",")}]`,
|
|
268
|
+
matches: (actualArgs) => this.#argsMatch(config, actualArgs)
|
|
269
|
+
}));
|
|
270
|
+
return [...exact, ...asymmetric];
|
|
271
|
+
}
|
|
250
272
|
/** Render one asymmetric config once, at registration time. See {@link MatcherConfig}. */
|
|
251
273
|
#buildMatcherConfig(key, value) {
|
|
252
274
|
const serialized = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { resolveUnstubbedGuard, createFunctionSpy } from './chunk-
|
|
1
|
+
import { resolveUnstubbedGuard, createFunctionSpy } from './chunk-FFKN6QKI.js';
|
|
2
2
|
import { DISPOSE } from './chunk-PC3FAZT3.js';
|
|
3
|
-
import { runClearHook, runConfigReset, AUTO_SPY_MARK, isMarkedMock, readDeepChildren
|
|
3
|
+
import { runClearHook, runConfigReset, AUTO_SPY_MARK, markAsMock, isMarkedMock, readDeepChildren } from './chunk-XRVVZXOM.js';
|
|
4
4
|
import { withDocs, DOCS_LINKS } from './chunk-B45HLBA4.js';
|
|
5
5
|
import { getMockAdapter, requireObservableSupport, getJasmineSupport } from './shared-state.js';
|
|
6
6
|
|
|
@@ -380,6 +380,17 @@ function walkOwnPrototypes(prototype, visit) {
|
|
|
380
380
|
current = parent;
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
|
+
function getCallableMemberNames(target) {
|
|
384
|
+
const names = /* @__PURE__ */ new Set();
|
|
385
|
+
walkOwnPrototypes(target, (obj) => {
|
|
386
|
+
for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(obj))) {
|
|
387
|
+
if (name !== "constructor" && typeof descriptor.value === "function") {
|
|
388
|
+
names.add(name);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
return [...names];
|
|
393
|
+
}
|
|
383
394
|
var methodNamesCache = /* @__PURE__ */ new WeakMap();
|
|
384
395
|
function getAllMethodNames(prototype) {
|
|
385
396
|
const cached = methodNamesCache.get(prototype);
|
|
@@ -437,7 +448,12 @@ function resolveAccessors(prototype, config) {
|
|
|
437
448
|
};
|
|
438
449
|
}
|
|
439
450
|
function resolveMethodNames(ObjectClass, config) {
|
|
440
|
-
|
|
451
|
+
return mergeMethodNames(
|
|
452
|
+
config.onlyMethodsToSpyOn.length > 0 ? config.onlyMethodsToSpyOn : getAllMethodNames(ObjectClass.prototype),
|
|
453
|
+
config
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
function mergeMethodNames(base, config) {
|
|
441
457
|
if (config.methodsToSpyOn.length === 0 && config.instanceMethodsToSpyOn.length === 0) {
|
|
442
458
|
return base;
|
|
443
459
|
}
|
|
@@ -476,7 +492,7 @@ function warnOnAccessorNamingAMethod(ObjectClass, config) {
|
|
|
476
492
|
function isCallable2(value) {
|
|
477
493
|
return typeof value === "function";
|
|
478
494
|
}
|
|
479
|
-
function applyReturns(autoSpy,
|
|
495
|
+
function applyReturns(autoSpy, factory, returns) {
|
|
480
496
|
const entries = Object.entries(returns);
|
|
481
497
|
if (entries.length === 0) {
|
|
482
498
|
return;
|
|
@@ -487,7 +503,7 @@ function applyReturns(autoSpy, ObjectClass, returns) {
|
|
|
487
503
|
if (!isCallable2(spy)) {
|
|
488
504
|
console.warn(
|
|
489
505
|
withDocs(
|
|
490
|
-
`[vitest-auto-spy]
|
|
506
|
+
`[vitest-auto-spy] ${factory}: returns names '${name}', which is not a spied method of the spy. Check the spelling, and check that a restricting onlyMethodsToSpyOn list did not leave it out \u2014 a value configured for a method that is not there is silently never returned.`,
|
|
491
507
|
DOCS_LINKS.createSpyFromClass
|
|
492
508
|
)
|
|
493
509
|
);
|
|
@@ -539,7 +555,7 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
|
|
|
539
555
|
function createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig) {
|
|
540
556
|
const config = resolveConfiguration(methodsToSpyOnOrConfig);
|
|
541
557
|
const autoSpy = assembleSpy(ObjectClass, config);
|
|
542
|
-
applyReturns(autoSpy, ObjectClass
|
|
558
|
+
applyReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config.returns);
|
|
543
559
|
applyOverrides(autoSpy, config.overrides);
|
|
544
560
|
return autoSpy;
|
|
545
561
|
}
|
|
@@ -586,4 +602,4 @@ function hasNothingToRead(ObjectClass, accessors, config) {
|
|
|
586
602
|
config.onlyMethodsToSpyOn.length === 0;
|
|
587
603
|
}
|
|
588
604
|
|
|
589
|
-
export { NOT_STORED, autoMocked, clearAutoSpy, createAutoMock, createProxyPropStore, createSpyFromClass, describeStoredProp, disposeAutoSpy, dropStoredProp, isDeletedProp, isProtocolKey, readStoredAccessor, resetAutoSpy, storeDefinedProp, writeStoredAccessor, writeStoredValue };
|
|
605
|
+
export { NOT_STORED, applyReturns, autoMocked, clearAutoSpy, createAccessorsSpies, createAutoMock, createProxyPropStore, createSpyFromClass, describeStoredProp, disposeAutoSpy, dropStoredProp, getCallableMemberNames, isDeletedProp, isProtocolKey, mergeMethodNames, readStoredAccessor, resetAutoSpy, resolveAccessors, resolveConfiguration, storeDefinedProp, writeStoredAccessor, writeStoredValue };
|