vitest-auto-spy 5.40.1 → 5.41.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/CHANGELOG.md CHANGED
@@ -10,6 +10,35 @@ The latest released version here must always match the one published on
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [5.41.0] - 2026-09-27
14
+
15
+ ### Changed
16
+
17
+ - **Every Angular-adapter message prints class names as the source spells them.** 5.40.1 took the
18
+ esbuild `_` prefix and the Rollup `$1` suffix off in `toHaveDirectiveApplied` only; the rest still
19
+ told the reader to edit `_ReportCardComponent`. The same cleanup now applies to `injectSpy`,
20
+ `overrideComponentProvider`, `assertComponentDefIntact`, `enableAngularDiagnostics`' shadowed-provider
21
+ report, `setInputs` / `renderShallow` input errors, `renderShallow({ keepTemplate: true })`,
22
+ `createComponentStub` (and the stub's own class name), `provideMatDialogRef` / `injectMatDialogRef`,
23
+ `hostElement` / `queryElement`, `trackInjections(...).get()` and the `createSpyFromClass(X)` label.
24
+ `trackInjections(...).names()` still returns `Function.name` unchanged.
25
+ - **`toHaveDirectiveApplied` blames the selector when the host already has the directive in scope.**
26
+ A `createDirectiveHost({ template, scope: [FlagDirective] })` whose template no longer matched the
27
+ directive's selector failed with "Build the host with createDirectiveHost({ template, scope:
28
+ [FlagDirective] })", the call the spec already made. When the host's compiled scope carries the
29
+ directive, the failure now says its selector matches nothing the template renders and prints it
30
+ (`'[appFlagX]'`; a `:not()` selector is left out). With a selector argument, a directive found only
31
+ on other elements is reported as `it is on 1 element that selector does not match`.
32
+ `/angular/matchers` is +421 B min+gzip (2241 → 2662 B, +18.8 %) and +2.4 kB to import
33
+ (19972 → 22349 B): the scope lookup, the selector printer and the two messages.
34
+
35
+ ### Fixed
36
+
37
+ - **The `signalStore()` `fillMissing` default recognises the ngrx base under a bundler's rename.** The
38
+ base was matched by `name === 'SignalStore'`, which a `_SignalStore` or `SignalStore$1` missed; the
39
+ name is now compared with the rename taken off. The `HttpTestingController` lookup behind
40
+ `enableAngularDiagnostics({ pendingRequests })` compares the same way.
41
+
13
42
  ## [5.40.1] - 2026-09-27
14
43
 
15
44
  ### Changed
@@ -5561,7 +5590,8 @@ moved under 1 %: `/angular` +192 B (+1.0 %) for the override queue and the HTTP
5561
5590
  This copy ships with the package and carries 5.x only. Releases before 5.0.0 are in the
5562
5591
  [full changelog](https://github.com/ASDAlexey/vitest-auto-spy/blob/master/CHANGELOG.md).
5563
5592
 
5564
- [Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.40.1...HEAD
5593
+ [Unreleased]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.41.0...HEAD
5594
+ [5.41.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.40.1...v5.41.0
5565
5595
  [5.40.1]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.40.0...v5.40.1
5566
5596
  [5.40.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.39.0...v5.40.0
5567
5597
  [5.39.0]: https://github.com/ASDAlexey/vitest-auto-spy/compare/v5.38.0...v5.39.0
@@ -1207,7 +1207,9 @@ assertion on the attribute alone stays green when the entry is dropped and the a
1207
1207
  written statically, or set by something else; the fixture's root element is searched, so the entry
1208
1208
  itself can be asserted with no selector. On a fixture of the component under test the failure names
1209
1209
  that component's `hostDirectives` / `imports` as the fix; only a spec-built host (`createDirectiveHost`,
1210
- `TestBed.createDirective`) is pointed at `createDirectiveHost`. A structural directive (`*dir`,
1210
+ `TestBed.createDirective`) is pointed at `createDirectiveHost`. A directive already in the host's
1211
+ compiled scope gets neither hint: the failure prints its own selector, which matches nothing in the
1212
+ template (a mutated or mistyped selector). A structural directive (`*dir`,
1211
1213
  `<ng-template dir>`) counts too: it sits on the template's comment anchor, which the search includes;
1212
1214
  assert it without a selector, since the element it renders does not carry it:
1213
1215
 
@@ -39,7 +39,8 @@ the reference suite). Method discovery walks the _prototype chain_; a callable a
39
39
 
40
40
  - an Angular `signal()` / `computed()` field — the dominant case in a signals codebase
41
41
  - an arrow-function property — `readonly reload = (): void => {}`
42
- - anything on an ngrx `signalStore()`, which puts **everything** on the instance
42
+ - anything on an ngrx `signalStore()`, which puts **everything** on the instance — covered by the
43
+ `fillMissing` default below, not by a list
43
44
  - **members Angular's own classes moved onto the instance** — `Router.currentNavigation` in
44
45
  Angular 20 is `currentNavigation = this.navigationTransitions.currentNavigation.asReadonly()`
45
46
 
@@ -1,14 +1,14 @@
1
1
  import { pendingRequestsReport, assertAngularInternals, instrumentTestBed, onTestingModuleConfigured, onComponentCreated, beforeTestBedReset, verifyOnTeardown } from './chunk-JFOJFCVQ.js';
2
2
  export { disableTestBedDiagnostics, enableTestBedDiagnostics, formatSpecTiming, getTestBedTiming, instrumentTestBed, reportSpecTiming } from './chunk-JFOJFCVQ.js';
3
- import { failOnUnspiedProvider } from './chunk-YPDMNJDB.js';
3
+ import { failOnUnspiedProvider } from './chunk-OWDUWUAO.js';
4
4
  import './chunk-GG7BQKEK.js';
5
5
  import './chunk-MNY4ZHEQ.js';
6
- import './chunk-H54YPKPT.js';
6
+ import './chunk-T7EGA4G4.js';
7
7
  import './chunk-FOL5RH22.js';
8
8
  import './chunk-PC3FAZT3.js';
9
9
  import './chunk-HUS2MHK5.js';
10
10
  import { isAutoSpyLike } from './chunk-Q7L4AWI7.js';
11
- import { count, taskName } from './chunk-DYAS4OK4.js';
11
+ import { count, sourceClassName, taskName } from './chunk-DYAS4OK4.js';
12
12
  import { angularPendingRequests, angularShadowedProviders, angularDeadSchemas, angularNgModuleScopesAuto } from './chunk-5FQZGJLJ.js';
13
13
  import { withDocs } from './chunk-ENCEEH23.js';
14
14
  import { getTestBed } from '@angular/core/testing';
@@ -31,7 +31,7 @@ function componentInjector(fixture, component) {
31
31
  }
32
32
  function describeResolved(resolved) {
33
33
  const constructorName = readProperty(readProperty(resolved, "constructor"), "name");
34
- return typeof constructorName === "string" && constructorName.length > 0 ? `a ${constructorName} instance` : String(resolved);
34
+ return typeof constructorName === "string" && constructorName.length > 0 ? `a ${sourceClassName(constructorName)} instance` : String(resolved);
35
35
  }
36
36
  function readProperty(value, key) {
37
37
  if (value === null || typeof value !== "object" && typeof value !== "function") {
@@ -59,7 +59,7 @@ function isDeadNgModuleImport(module) {
59
59
  }
60
60
  function moduleName(module) {
61
61
  const name = readProperty(module, "name");
62
- return typeof name === "string" ? name : String(module);
62
+ return typeof name === "string" ? sourceClassName(name) : String(module);
63
63
  }
64
64
  function listed(names) {
65
65
  return names.length === 1 ? String(names[0]) : `${names.slice(0, -1).join(", ")} and ${String(names.at(-1))}`;
@@ -89,7 +89,7 @@ function isComponentClass(value) {
89
89
  }
90
90
  function className(value) {
91
91
  const name = readProperty(value, "name");
92
- return typeof name === "string" ? name : String(value);
92
+ return typeof name === "string" ? sourceClassName(name) : String(value);
93
93
  }
94
94
  function checkNgModuleScopes(config) {
95
95
  failDeadNgModuleImports(readList(config, "imports").filter(isDeadNgModuleImport));
@@ -135,7 +135,7 @@ function flattenProviders(value, into) {
135
135
  function findControllerToken(providers) {
136
136
  const flat = [];
137
137
  flattenProviders(providers, flat);
138
- return flat.map((provider) => readProperty(provider, "provide")).find((token) => typeof token === "function" && token.name === HTTP_TESTING_CONTROLLER);
138
+ return flat.map((provider) => readProperty(provider, "provide")).find((token) => typeof token === "function" && sourceClassName(token.name) === HTTP_TESTING_CONTROLLER);
139
139
  }
140
140
  var controllerTokens = /* @__PURE__ */ new WeakMap();
141
141
  function findControllerTokenInModule(imported, seen) {
@@ -221,7 +221,7 @@ function collectModuleDoubles(config) {
221
221
  }
222
222
  function tokenName(token) {
223
223
  const name = readProperty(token, "name");
224
- return typeof name === "string" && name.length > 0 ? name : String(token);
224
+ return typeof name === "string" && name.length > 0 ? sourceClassName(name) : String(token);
225
225
  }
226
226
  function codeName(token) {
227
227
  const description = readProperty(token, "_desc");
@@ -1,4 +1,4 @@
1
- import { describeInstance } from './chunk-BS432KB2.js';
1
+ import { describeInstance } from './chunk-XEIOGUGP.js';
2
2
  import { useVitestAdapter } from './chunk-6ZGH56G4.js';
3
3
  import './chunk-IE4NI2OQ.js';
4
4
  import './chunk-YHDBRBGU.js';
@@ -7,7 +7,7 @@ import './chunk-FOL5RH22.js';
7
7
  import './chunk-PC3FAZT3.js';
8
8
  import { createFunctionSpy } from './chunk-HUS2MHK5.js';
9
9
  import './chunk-Q7L4AWI7.js';
10
- import './chunk-DYAS4OK4.js';
10
+ import { sourceClassName } from './chunk-DYAS4OK4.js';
11
11
  import { angularDialog } from './chunk-5FQZGJLJ.js';
12
12
  import { withDocs } from './chunk-ENCEEH23.js';
13
13
  import { TestBed } from '@angular/core/testing';
@@ -22,10 +22,10 @@ function guardMissingMembers(RefClass, double) {
22
22
  const guarded = new Proxy(double, {
23
23
  get(target, key, receiver) {
24
24
  if (typeof key === "string" && !(key in target) && declared.has(key)) {
25
- const repair = key === "componentInstance" ? `Hand the double the component's stand-in: provideMatDialogRef(${RefClass.name}, { componentInstance: { \u2026 } }).` : `${key} is the dialog doing its own work; open the real dialog through MatDialog for that.`;
25
+ const repair = key === "componentInstance" ? `Hand the double the component's stand-in: provideMatDialogRef(${sourceClassName(RefClass.name)}, { componentInstance: { \u2026 } }).` : `${key} is the dialog doing its own work; open the real dialog through MatDialog for that.`;
26
26
  throw new Error(
27
27
  withDocs(
28
- `[vitest-auto-spy] provideMatDialogRef: the code under test read ${RefClass.name}.${key}, which the double does not have.
28
+ `[vitest-auto-spy] provideMatDialogRef: the code under test read ${sourceClassName(RefClass.name)}.${key}, which the double does not have.
29
29
  ${repair}`,
30
30
  angularDialog
31
31
  )
@@ -47,7 +47,7 @@ function createMatDialogRef(RefClass, init = {}) {
47
47
  closed.next(result);
48
48
  closed.complete();
49
49
  };
50
- const close = createFunctionSpy(`${RefClass.name}.close`);
50
+ const close = createFunctionSpy(`${sourceClassName(RefClass.name)}.close`);
51
51
  getMockAdapter().restoreImplementation(close, emitClose);
52
52
  if (init.closedWith !== void 0) {
53
53
  emitClose(init.closedWith);
@@ -79,7 +79,7 @@ function injectMatDialogRef(RefClass, injector) {
79
79
  if (ref === null) {
80
80
  throw new Error(
81
81
  withDocs(
82
- `${caller}: nothing provides ${RefClass.name} in the injector given. Add provideMatDialogRef(${RefClass.name}) to its providers.`,
82
+ `${caller}: nothing provides ${sourceClassName(RefClass.name)} in the injector given. Add provideMatDialogRef(${sourceClassName(RefClass.name)}) to its providers.`,
83
83
  angularDialog
84
84
  )
85
85
  );
@@ -88,7 +88,7 @@ function injectMatDialogRef(RefClass, injector) {
88
88
  if (double === void 0) {
89
89
  throw new Error(
90
90
  withDocs(
91
- `${caller}: the ${RefClass.name} here is ${describeInstance(ref)}, not one provideMatDialogRef() built. A later provider of ${RefClass.name} won over the double \u2014 list provideMatDialogRef() last, or drop the other one.`,
91
+ `${caller}: the ${sourceClassName(RefClass.name)} here is ${describeInstance(ref)}, not one provideMatDialogRef() built. A later provider of ${sourceClassName(RefClass.name)} won over the double \u2014 list provideMatDialogRef() last, or drop the other one.`,
92
92
  angularDialog
93
93
  )
94
94
  );
@@ -46,6 +46,57 @@ function componentUnderTest(root) {
46
46
  const mirror = reflectComponentType(type);
47
47
  return mirror === null || mirror.selector.includes(TESTBED_DIRECTIVE_HOST) ? void 0 : sourceClassName(type.name);
48
48
  }
49
+ function inHostScope(root, directive) {
50
+ const host = Reflect.get(Object(root.componentInstance), "constructor");
51
+ const defs = Reflect.get(Object(Reflect.get(Object(host), "\u0275cmp")), "directiveDefs");
52
+ const list = typeof defs === "function" ? Reflect.apply(defs, void 0, []) : defs;
53
+ return Array.isArray(list) && list.some((def) => Reflect.get(Object(def), "type") === directive);
54
+ }
55
+ var SELECTOR_NOT = 1;
56
+ var SELECTOR_CLASS = 8;
57
+ function selectorText(directive) {
58
+ const selectors = Reflect.get(Object(Reflect.get(directive, "\u0275dir") ?? Reflect.get(directive, "\u0275cmp")), "selectors");
59
+ if (!Array.isArray(selectors) || selectors.length === 0) {
60
+ return void 0;
61
+ }
62
+ const parts = [];
63
+ for (const selector of selectors) {
64
+ if (!Array.isArray(selector)) {
65
+ return void 0;
66
+ }
67
+ let text = String(selector[0]);
68
+ let classes = false;
69
+ for (let index = 1; index < selector.length; index++) {
70
+ const entry = selector[index];
71
+ if (typeof entry === "number") {
72
+ if ((entry & SELECTOR_NOT) !== 0) {
73
+ return void 0;
74
+ }
75
+ classes = (entry & SELECTOR_CLASS) !== 0;
76
+ } else if (classes) {
77
+ text += `.${String(entry)}`;
78
+ } else {
79
+ const value = String(selector[++index]);
80
+ text += value === "" ? `[${String(entry)}]` : `[${String(entry)}="${value}"]`;
81
+ }
82
+ }
83
+ parts.push(text);
84
+ }
85
+ return parts.join(", ");
86
+ }
87
+ function selectorMismatch(directive, selector, root, withDirective) {
88
+ const name = sourceClassName(directive.name);
89
+ if (selector !== void 0 && withDirective.length > 0) {
90
+ return `it is on ${located(withDirective)} that selector does not match.
91
+ Check the selector against the template, or drop it: expect(fixture).toHaveDirectiveApplied(${name}).`;
92
+ }
93
+ if (!inHostScope(root, directive)) {
94
+ return void 0;
95
+ }
96
+ const own = selectorText(directive);
97
+ return `it is not on any element of this fixture, though it is in the host's scope \u2014 so its selector${own === void 0 ? "" : ` '${own}'`} matches nothing the template renders.
98
+ Check that selector against the template, and run fixture.detectChanges() before asserting if the element renders later.`;
99
+ }
49
100
  function diagnose(directive, selector, root, withDirective) {
50
101
  const name = sourceClassName(directive.name);
51
102
  const elements = selector === void 0 ? [] : matching(root, By.css(selector));
@@ -65,6 +116,10 @@ Assert it without a selector: expect(fixture).toHaveDirectiveApplied(${name}).`,
65
116
  angularDirectiveApplied
66
117
  );
67
118
  }
119
+ const mismatch = selectorMismatch(directive, selector, root, withDirective);
120
+ if (mismatch !== void 0) {
121
+ return withDocs(`${prefix}, but ${mismatch}`, angularDirectiveApplied);
122
+ }
68
123
  const component = componentUnderTest(root);
69
124
  if (component !== void 0) {
70
125
  const scope = isStandalone(directive) ? `list ${name} in ${component}'s hostDirectives if the component should carry it, or in its imports if its template uses it` : `add the NgModule that declares ${name} to ${component}'s imports if its template uses it`;
@@ -1,4 +1,4 @@
1
- import { describeInstance } from './chunk-BS432KB2.js';
1
+ import { describeInstance } from './chunk-XEIOGUGP.js';
2
2
  import { angularInternalsError } from './chunk-GG7BQKEK.js';
3
3
  import { createFunctionSpy } from './chunk-HUS2MHK5.js';
4
4
  import './chunk-Q7L4AWI7.js';
package/dist/angular.js CHANGED
@@ -40,6 +40,14 @@ var angularTypedElements = "https://asdalexey.github.io/vitest-auto-spy/adapters
40
40
  var angularTrackRuns = "https://asdalexey.github.io/vitest-auto-spy/adapters/angular#counting-recomputations-and-effect-runs";
41
41
  var trackInjectionsUntracked = "https://asdalexey.github.io/vitest-auto-spy/utilities/track-injections#get-on-a-token-that-is-not-tracked";
42
42
 
43
+ // src/lib/message-text.ts
44
+ function count(value, noun, plural = `${noun}s`) {
45
+ return `${value} ${value === 1 ? noun : plural}`;
46
+ }
47
+ function sourceClassName(name) {
48
+ return name.replace(/^_(?=[A-Z])/, "").replace(/\$\d+$/, "");
49
+ }
50
+
43
51
  // src/lib/angular.ts
44
52
  function provideAutoSpy(ObjectClass, methodsToSpyOnOrConfig) {
45
53
  return {
@@ -75,11 +83,11 @@ function describeUnspied(token, injected) {
75
83
  return `[vitest-auto-spy] injectSpy(${name2}): got a plain value, not an auto-spy \u2014 the token is provided for real.
76
84
  Provide the double instead: { provide: ${name2}, useValue: createAutoMock<T>() }.`;
77
85
  }
78
- const name = token.name;
86
+ const name = sourceClassName(token.name);
79
87
  const provider = Reflect.get(token, "\u0275prov");
80
88
  const fromRoot = Reflect.get(Object(provider), "providedIn") === "root";
81
89
  const built = Reflect.get(Object(Reflect.get(Object(injected), "constructor")), "name");
82
- const what = typeof built === "string" && built.length > 0 ? `a real ${built}` : "a real instance";
90
+ const what = typeof built === "string" && built.length > 0 ? `a real ${sourceClassName(built)}` : "a real instance";
83
91
  const why = fromRoot ? "nothing in the testing module provides a double, so Angular built it (providedIn: 'root')" : "the testing module provides the real class, not a double";
84
92
  return `[vitest-auto-spy] injectSpy(${name}): got ${what} \u2014 ${why}.
85
93
  Add provideAutoSpy(${name}) to providers.`;
@@ -240,7 +248,7 @@ function explainLateOverride(error, component, token) {
240
248
  }
241
249
  return new Error(
242
250
  _message_link$withDocs(
243
- `[vitest-auto-spy] overrideComponentProvider(${component.name}, ${token.name}) ran after the testing module was instantiated, and Angular accepts no override past that point. Something read the injector first \u2014 a \`TestBed.inject\`, an \`injectSpy\`, a \`createComponent\` \u2014 earlier in this test or in the same \`beforeCreate\`. Override first, then inject.`,
251
+ `[vitest-auto-spy] overrideComponentProvider(${sourceClassName(component.name)}, ${sourceClassName(token.name)}) ran after the testing module was instantiated, and Angular accepts no override past that point. Something read the injector first \u2014 a \`TestBed.inject\`, an \`injectSpy\`, a \`createComponent\` \u2014 earlier in this test or in the same \`beforeCreate\`. Override first, then inject.`,
244
252
  angularOverrideLate
245
253
  ),
246
254
  { cause: error }
@@ -288,7 +296,7 @@ function componentInjector(fixture, component) {
288
296
  }
289
297
  function describeResolved(resolved) {
290
298
  const constructorName = readProperty(readProperty(resolved, "constructor"), "name");
291
- return typeof constructorName === "string" && constructorName.length > 0 ? `a ${constructorName} instance` : String(resolved);
299
+ return typeof constructorName === "string" && constructorName.length > 0 ? `a ${sourceClassName(constructorName)} instance` : String(resolved);
292
300
  }
293
301
  function verify(fixture, { component, token, spy }) {
294
302
  const injector = componentInjector(fixture, component);
@@ -301,7 +309,7 @@ function verify(fixture, { component, token, spy }) {
301
309
  }
302
310
  throw new Error(
303
311
  _message_link$withDocs(
304
- `[vitest-auto-spy] overrideComponentProvider(${component.name}, ${token.name}): the override did not apply \u2014 ${component.name} resolved ${token.name} to ${describeResolved(resolved)}, not the spy this call returned.
312
+ `[vitest-auto-spy] overrideComponentProvider(${sourceClassName(component.name)}, ${sourceClassName(token.name)}): the override did not apply \u2014 ${sourceClassName(component.name)} resolved ${sourceClassName(token.name)} to ${describeResolved(resolved)}, not the spy this call returned.
305
313
  ` + explainMissedOverride(token, resolved),
306
314
  angularOverrideApplied
307
315
  )
@@ -309,7 +317,7 @@ function verify(fixture, { component, token, spy }) {
309
317
  }
310
318
  function explainMissedOverride(token, resolved) {
311
319
  const later = _spy_mark$isAutoSpyLike(resolved) ? "a different double" : "the real service";
312
- return `It got ${later} because something configured ${token.name} again after this call \u2014 a later TestBed.overrideProvider or configureTestingModule. Keep overrideComponentProvider as the last word on it.`;
320
+ return `It got ${later} because something configured ${sourceClassName(token.name)} again after this call \u2014 a later TestBed.overrideProvider or configureTestingModule. Keep overrideComponentProvider as the last word on it.`;
313
321
  }
314
322
  function verifyOnNextCreate(entry) {
315
323
  if (readTestBedMethod("createComponent") === void 0) {
@@ -342,7 +350,7 @@ function hasEmptyRuntimeScope(module) {
342
350
  }
343
351
  function moduleName(module) {
344
352
  const name = readProperty(module, "name");
345
- return typeof name === "string" ? name : String(module);
353
+ return typeof name === "string" ? sourceClassName(name) : String(module);
346
354
  }
347
355
  var DEFINITION_LISTS = ["providers", "viewProviders", "dependencies"];
348
356
  function resolveList(list) {
@@ -437,6 +445,9 @@ function tokenName(token) {
437
445
  const name = typeof token === "function" ? token.name : void 0;
438
446
  return typeof name === "string" && name.length > 0 ? name : String(token);
439
447
  }
448
+ function messageName(token) {
449
+ return sourceClassName(tokenName(token));
450
+ }
440
451
  function trackInjections(tokens, options = {}) {
441
452
  const build = options.double ?? createSpyForToken;
442
453
  const doubles = new Map(tokens.map((token) => [token, build(token)]));
@@ -457,8 +468,8 @@ function trackInjections(tokens, options = {}) {
457
468
  if (!doubles.has(token)) {
458
469
  throw new Error(
459
470
  _message_link$withDocs(
460
- `[vitest-auto-spy] trackInjections(...).get(${tokenName(token)}): that token is not tracked by this log.
461
- Tracked here: ${tokens.map(tokenName).join(", ") || "(none)"}. Add it to the trackInjections([...]) list, or read it from the injector directly \u2014 \`get\` only answers for the tokens whose providers this log created.`,
471
+ `[vitest-auto-spy] trackInjections(...).get(${messageName(token)}): that token is not tracked by this log.
472
+ Tracked here: ${tokens.map(messageName).join(", ") || "(none)"}. Add it to the trackInjections([...]) list, or read it from the injector directly \u2014 \`get\` only answers for the tokens whose providers this log created.`,
462
473
  trackInjectionsUntracked
463
474
  )
464
475
  );
@@ -536,7 +547,7 @@ var CLASS = 8;
536
547
  var SIGNAL_BASED = 1;
537
548
  var stubCount = 0;
538
549
  function createComponentStub(real, overrides = {}, options = {}) {
539
- const realName = typeof real === "function" ? real.name : String(real);
550
+ const realName = typeof real === "function" ? sourceClassName(real.name) : String(real);
540
551
  const name = `${realName}Stub`;
541
552
  const pipe = definition(real, "\u0275pipe");
542
553
  if (pipe) {
@@ -712,7 +723,7 @@ ${askFor(autoSpies.tokens().map(describeToken))}`,
712
723
  // src/lib/host-element.ts
713
724
  function describeElement(element) {
714
725
  const classes = [...element.classList].map((name) => `.${name}`).join("");
715
- return `<${element.tagName.toLowerCase()}${classes}> (${element.constructor.name})`;
726
+ return `<${element.tagName.toLowerCase()}${classes}> (${sourceClassName(element.constructor.name)})`;
716
727
  }
717
728
  function fail(message) {
718
729
  return _message_link$withDocs(`[vitest-auto-spy] ${message}`, angularTypedElements);
@@ -738,7 +749,7 @@ Check the predicate against the rendered template, or use queryElement(fixture,
738
749
  }
739
750
  function checkType(element, type, what, helper) {
740
751
  if (!(element instanceof type)) {
741
- throw new TypeError(fail(`${helper}: ${what} ${describeElement(element)}, not ${type.name}.`));
752
+ throw new TypeError(fail(`${helper}: ${what} ${describeElement(element)}, not ${sourceClassName(type.name)}.`));
742
753
  }
743
754
  return element;
744
755
  }
@@ -779,10 +790,10 @@ function whyNoInputs(component) {
779
790
  Import the component from its own file rather than through the barrel.`;
780
791
  }
781
792
  if (Reflect.get(component, "\u0275pipe") !== void 0) {
782
- return `${component.name} is a @Pipe, and a pipe has no inputs.
793
+ return `${sourceClassName(component.name)} is a @Pipe, and a pipe has no inputs.
783
794
  Call its transform() directly, or render it inside a host component.`;
784
795
  }
785
- return `${component.name} carries no \u0275cmp, so Angular never compiled it as a component and there are no inputs to set.
796
+ return `${sourceClassName(component.name)} carries no \u0275cmp, so Angular never compiled it as a component and there are no inputs to set.
786
797
  Pass the @Component class the fixture was created from.`;
787
798
  }
788
799
  function unknownInputsError(caller, component, unknown, declared) {
@@ -795,7 +806,7 @@ function unknownInputsError(caller, component, unknown, declared) {
795
806
  const known = declared.length > 0 ? `Its inputs are ${quote(declared)}.` : "It declares no inputs at all.";
796
807
  return new Error(
797
808
  _message_link$withDocs(
798
- `[vitest-auto-spy] ${caller}: ${component.name} declares no input named ${quote(unknown)}.${hint}
809
+ `[vitest-auto-spy] ${caller}: ${sourceClassName(component.name)} declares no input named ${quote(unknown)}.${hint}
799
810
  ${known} Angular would answer the name with an NG0303 and change nothing; a plain field is assigned on the instance instead, and a signal the component owns is set through the signal.`,
800
811
  angularInputs
801
812
  )
@@ -888,31 +899,32 @@ function refusedInImports(dependency) {
888
899
  return void 0;
889
900
  }
890
901
  const definition2 = DECLARATION_KEYS.map((key) => Reflect.get(dependency, key)).find((value) => value !== void 0);
891
- return definition2 !== void 0 && Reflect.get(definition2, "standalone") !== true ? dependency.name : void 0;
902
+ return definition2 !== void 0 && Reflect.get(definition2, "standalone") !== true ? sourceClassName(dependency.name) : void 0;
892
903
  }
893
904
  function assertScopeIsImportable(component, kept, candidates) {
894
905
  const refused = kept.filter((dependency) => refusedInImports(dependency) !== void 0);
895
906
  if (refused.length === 0) {
896
907
  return;
897
908
  }
898
- const names = refused.map((dependency) => dependency.name);
909
+ const names = refused.map((dependency) => sourceClassName(dependency.name));
899
910
  const owners = [...new Set(refused.map((dependency) => declaringModule(dependency, candidates)))];
900
911
  const [owner] = owners;
901
912
  const fix = owners.length === 1 && owner !== void 0 ? `keepModules: [${owner}]` : `keepModules: [<the NgModule that declares ${String(names[0])}>]`;
902
913
  throw new Error(
903
914
  _message_link$withDocs(
904
- `[vitest-auto-spy] renderShallow(${component.name}, { keepTemplate: true }): ${names.join(", ")} ${names.length === 1 ? "is" : "are"} declared by ${owner === void 0 || owners.length > 1 ? "an NgModule" : owner}, not standalone, and Angular takes only standalone declarations and NgModules in \`imports\`.
915
+ `[vitest-auto-spy] renderShallow(${sourceClassName(component.name)}, { keepTemplate: true }): ${names.join(", ")} ${names.length === 1 ? "is" : "are"} declared by ${owner === void 0 || owners.length > 1 ? "an NgModule" : owner}, not standalone, and Angular takes only standalone declarations and NgModules in \`imports\`.
905
916
  An AOT build flattened that module away, so name it and it is put back whole: ${fix}.`,
906
917
  angularKeepTemplate
907
918
  )
908
919
  );
909
920
  }
910
921
  function declaringModule(dependency, candidates) {
911
- return candidates.filter((candidate) => typeof candidate === "function").find((candidate) => {
922
+ const owner = candidates.filter((candidate) => typeof candidate === "function").find((candidate) => {
912
923
  const scope = /* @__PURE__ */ new Set();
913
924
  exportedScope(candidate, scope, /* @__PURE__ */ new Set());
914
925
  return scope.has(dependency);
915
- })?.name;
926
+ });
927
+ return owner === void 0 ? void 0 : sourceClassName(owner.name);
916
928
  }
917
929
  function unwrapList(value) {
918
930
  const resolved = typeof value === "function" ? Reflect.apply(value, void 0, []) : value;
@@ -1047,11 +1059,6 @@ function runEffect(effectRef) {
1047
1059
  });
1048
1060
  }
1049
1061
 
1050
- // src/lib/message-text.ts
1051
- function count(value, noun, plural = `${noun}s`) {
1052
- return `${value} ${value === 1 ? noun : plural}`;
1053
- }
1054
-
1055
1062
  // src/lib/zoneless.ts
1056
1063
  function flushEffects() {
1057
1064
  TestBed.inject(NgZone).run(() => {
@@ -1,21 +1,21 @@
1
- import { createSpyForToken } from './chunk-IWTUXEAR.js';
2
- export { injectSpy, provideAutoSpy } from './chunk-YPDMNJDB.js';
1
+ import { createSpyForToken } from './chunk-O55MVK7N.js';
2
+ export { injectSpy, provideAutoSpy } from './chunk-OWDUWUAO.js';
3
3
  import { stable, flushEffects } from './chunk-UH3KWLVL.js';
4
4
  export { flushEffects, stable } from './chunk-UH3KWLVL.js';
5
5
  import { angularInternalsError } from './chunk-GG7BQKEK.js';
6
6
  import './chunk-QDBRZQJO.js';
7
- export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DQCAFHHR.js';
7
+ export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DG5EP3PO.js';
8
8
  import { mockValueProp } from './chunk-MNY4ZHEQ.js';
9
9
  export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-MNY4ZHEQ.js';
10
- import { closestName } from './chunk-H54YPKPT.js';
11
- export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-H54YPKPT.js';
10
+ import { closestName } from './chunk-T7EGA4G4.js';
11
+ export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-T7EGA4G4.js';
12
12
  import { fakeClockBacklog } from './chunk-HVNKTPKG.js';
13
13
  import './chunk-TXDBDMIL.js';
14
14
  import './chunk-FOL5RH22.js';
15
15
  import './chunk-PC3FAZT3.js';
16
16
  export { createFunctionSpy, errorHandler } from './chunk-HUS2MHK5.js';
17
17
  import { libraryWarn } from './chunk-Q7L4AWI7.js';
18
- import { displayPath, count } from './chunk-DYAS4OK4.js';
18
+ import { displayPath, count, sourceClassName } from './chunk-DYAS4OK4.js';
19
19
  import { angularEffects, angularTrackRuns, bunAngular, angularUnreadResource, angularCreateWithAutoSpies, angularResources, angularTypedElements, angularInputs, angularKeepTemplate } from './chunk-5FQZGJLJ.js';
20
20
  import { withDocs } from './chunk-ENCEEH23.js';
21
21
  import '@angular/compiler';
@@ -287,7 +287,7 @@ ${askFor(autoSpies.tokens().map(describeToken))}`,
287
287
  // src/lib/host-element.ts
288
288
  function describeElement(element) {
289
289
  const classes = [...element.classList].map((name) => `.${name}`).join("");
290
- return `<${element.tagName.toLowerCase()}${classes}> (${element.constructor.name})`;
290
+ return `<${element.tagName.toLowerCase()}${classes}> (${sourceClassName(element.constructor.name)})`;
291
291
  }
292
292
  function fail(message) {
293
293
  return withDocs(`[vitest-auto-spy] ${message}`, angularTypedElements);
@@ -313,7 +313,7 @@ Check the predicate against the rendered template, or use queryElement(fixture,
313
313
  }
314
314
  function checkType(element, type, what, helper) {
315
315
  if (!(element instanceof type)) {
316
- throw new TypeError(fail(`${helper}: ${what} ${describeElement(element)}, not ${type.name}.`));
316
+ throw new TypeError(fail(`${helper}: ${what} ${describeElement(element)}, not ${sourceClassName(type.name)}.`));
317
317
  }
318
318
  return element;
319
319
  }
@@ -354,10 +354,10 @@ function whyNoInputs(component) {
354
354
  Import the component from its own file rather than through the barrel.`;
355
355
  }
356
356
  if (Reflect.get(component, "\u0275pipe") !== void 0) {
357
- return `${component.name} is a @Pipe, and a pipe has no inputs.
357
+ return `${sourceClassName(component.name)} is a @Pipe, and a pipe has no inputs.
358
358
  Call its transform() directly, or render it inside a host component.`;
359
359
  }
360
- return `${component.name} carries no \u0275cmp, so Angular never compiled it as a component and there are no inputs to set.
360
+ return `${sourceClassName(component.name)} carries no \u0275cmp, so Angular never compiled it as a component and there are no inputs to set.
361
361
  Pass the @Component class the fixture was created from.`;
362
362
  }
363
363
  function unknownInputsError(caller, component, unknown, declared) {
@@ -370,7 +370,7 @@ function unknownInputsError(caller, component, unknown, declared) {
370
370
  const known = declared.length > 0 ? `Its inputs are ${quote2(declared)}.` : "It declares no inputs at all.";
371
371
  return new Error(
372
372
  withDocs(
373
- `[vitest-auto-spy] ${caller}: ${component.name} declares no input named ${quote2(unknown)}.${hint}
373
+ `[vitest-auto-spy] ${caller}: ${sourceClassName(component.name)} declares no input named ${quote2(unknown)}.${hint}
374
374
  ${known} Angular would answer the name with an NG0303 and change nothing; a plain field is assigned on the instance instead, and a signal the component owns is set through the signal.`,
375
375
  angularInputs
376
376
  )
@@ -463,31 +463,32 @@ function refusedInImports(dependency) {
463
463
  return void 0;
464
464
  }
465
465
  const definition = DECLARATION_KEYS.map((key) => Reflect.get(dependency, key)).find((value) => value !== void 0);
466
- return definition !== void 0 && Reflect.get(definition, "standalone") !== true ? dependency.name : void 0;
466
+ return definition !== void 0 && Reflect.get(definition, "standalone") !== true ? sourceClassName(dependency.name) : void 0;
467
467
  }
468
468
  function assertScopeIsImportable(component, kept, candidates) {
469
469
  const refused = kept.filter((dependency) => refusedInImports(dependency) !== void 0);
470
470
  if (refused.length === 0) {
471
471
  return;
472
472
  }
473
- const names = refused.map((dependency) => dependency.name);
473
+ const names = refused.map((dependency) => sourceClassName(dependency.name));
474
474
  const owners = [...new Set(refused.map((dependency) => declaringModule(dependency, candidates)))];
475
475
  const [owner] = owners;
476
476
  const fix = owners.length === 1 && owner !== void 0 ? `keepModules: [${owner}]` : `keepModules: [<the NgModule that declares ${String(names[0])}>]`;
477
477
  throw new Error(
478
478
  withDocs(
479
- `[vitest-auto-spy] renderShallow(${component.name}, { keepTemplate: true }): ${names.join(", ")} ${names.length === 1 ? "is" : "are"} declared by ${owner === void 0 || owners.length > 1 ? "an NgModule" : owner}, not standalone, and Angular takes only standalone declarations and NgModules in \`imports\`.
479
+ `[vitest-auto-spy] renderShallow(${sourceClassName(component.name)}, { keepTemplate: true }): ${names.join(", ")} ${names.length === 1 ? "is" : "are"} declared by ${owner === void 0 || owners.length > 1 ? "an NgModule" : owner}, not standalone, and Angular takes only standalone declarations and NgModules in \`imports\`.
480
480
  An AOT build flattened that module away, so name it and it is put back whole: ${fix}.`,
481
481
  angularKeepTemplate
482
482
  )
483
483
  );
484
484
  }
485
485
  function declaringModule(dependency, candidates) {
486
- return candidates.filter((candidate) => typeof candidate === "function").find((candidate) => {
486
+ const owner = candidates.filter((candidate) => typeof candidate === "function").find((candidate) => {
487
487
  const scope = /* @__PURE__ */ new Set();
488
488
  exportedScope(candidate, scope, /* @__PURE__ */ new Set());
489
489
  return scope.has(dependency);
490
- })?.name;
490
+ });
491
+ return owner === void 0 ? void 0 : sourceClassName(owner.name);
491
492
  }
492
493
  function unwrapList(value) {
493
494
  const resolved = typeof value === "function" ? Reflect.apply(value, void 0, []) : value;
package/dist/bun.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import './chunk-QDBRZQJO.js';
2
- export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DQCAFHHR.js';
2
+ export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DG5EP3PO.js';
3
3
  export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-MNY4ZHEQ.js';
4
- export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-H54YPKPT.js';
4
+ export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-T7EGA4G4.js';
5
5
  import './chunk-HVNKTPKG.js';
6
6
  import './chunk-TXDBDMIL.js';
7
7
  import './chunk-FOL5RH22.js';
@@ -1,5 +1,5 @@
1
1
  import { mockValueProp, mockAccessorsProp } from './chunk-MNY4ZHEQ.js';
2
- import { resolveConfiguration, mergeAutoSpyDefaults, resolveReadGuard, mergeMethodNames, getCallableMemberNames, createTrackedPropSpy, applyConfiguredReturns, createSpyFromClass, warnOnUnknownMethods, warnOnAccessorNamingAMethod, resolveAccessors, createAccessorsSpies, ownerOf, createProxyPropStore, storeWriteTraps, describeStoredProp, hasStoredProp, isProtocolKey, isDeletedProp, readStoredAccessor, NOT_STORED, disposeAutoSpy, writeStoredValue } from './chunk-H54YPKPT.js';
2
+ import { resolveConfiguration, mergeAutoSpyDefaults, resolveReadGuard, mergeMethodNames, getCallableMemberNames, createTrackedPropSpy, applyConfiguredReturns, createSpyFromClass, warnOnUnknownMethods, warnOnAccessorNamingAMethod, resolveAccessors, createAccessorsSpies, ownerOf, createProxyPropStore, storeWriteTraps, describeStoredProp, hasStoredProp, isProtocolKey, isDeletedProp, readStoredAccessor, NOT_STORED, disposeAutoSpy, writeStoredValue } from './chunk-T7EGA4G4.js';
3
3
  import { unpatchedSetTimeout, unpatchedClearTimeout, fakeClockAdvice, fakeClockBacklog } from './chunk-HVNKTPKG.js';
4
4
  import { redefineFailure } from './chunk-FOL5RH22.js';
5
5
  import { DISPOSE } from './chunk-PC3FAZT3.js';
@@ -1,4 +1,5 @@
1
- import { createSpyFromClass, createAutoMock } from './chunk-H54YPKPT.js';
1
+ import { createSpyFromClass, createAutoMock } from './chunk-T7EGA4G4.js';
2
+ import { sourceClassName } from './chunk-DYAS4OK4.js';
2
3
  import { trackInjectionsUntracked } from './chunk-5FQZGJLJ.js';
3
4
  import { withDocs } from './chunk-ENCEEH23.js';
4
5
 
@@ -13,6 +14,9 @@ function tokenName(token) {
13
14
  const name = typeof token === "function" ? token.name : void 0;
14
15
  return typeof name === "string" && name.length > 0 ? name : String(token);
15
16
  }
17
+ function messageName(token) {
18
+ return sourceClassName(tokenName(token));
19
+ }
16
20
  function trackInjections(tokens, options = {}) {
17
21
  const build = options.double ?? createSpyForToken;
18
22
  const doubles = new Map(tokens.map((token) => [token, build(token)]));
@@ -33,8 +37,8 @@ function trackInjections(tokens, options = {}) {
33
37
  if (!doubles.has(token)) {
34
38
  throw new Error(
35
39
  withDocs(
36
- `[vitest-auto-spy] trackInjections(...).get(${tokenName(token)}): that token is not tracked by this log.
37
- Tracked here: ${tokens.map(tokenName).join(", ") || "(none)"}. Add it to the trackInjections([...]) list, or read it from the injector directly \u2014 \`get\` only answers for the tokens whose providers this log created.`,
40
+ `[vitest-auto-spy] trackInjections(...).get(${messageName(token)}): that token is not tracked by this log.
41
+ Tracked here: ${tokens.map(messageName).join(", ") || "(none)"}. Add it to the trackInjections([...]) list, or read it from the injector directly \u2014 \`get\` only answers for the tokens whose providers this log created.`,
38
42
  trackInjectionsUntracked
39
43
  )
40
44
  );
@@ -1,6 +1,7 @@
1
1
  import { currentSpecFile } from './chunk-MNY4ZHEQ.js';
2
- import { createSpyFromClass } from './chunk-H54YPKPT.js';
2
+ import { createSpyFromClass } from './chunk-T7EGA4G4.js';
3
3
  import { isAutoSpyLike, misconfigurationThrows, reportMisconfiguration } from './chunk-Q7L4AWI7.js';
4
+ import { sourceClassName } from './chunk-DYAS4OK4.js';
4
5
  import { angularInjectSpyReal } from './chunk-5FQZGJLJ.js';
5
6
  import { withDocs } from './chunk-ENCEEH23.js';
6
7
  import { TestBed } from '@angular/core/testing';
@@ -38,11 +39,11 @@ function describeUnspied(token, injected) {
38
39
  return `[vitest-auto-spy] injectSpy(${name2}): got a plain value, not an auto-spy \u2014 the token is provided for real.
39
40
  Provide the double instead: { provide: ${name2}, useValue: createAutoMock<T>() }.`;
40
41
  }
41
- const name = token.name;
42
+ const name = sourceClassName(token.name);
42
43
  const provider = Reflect.get(token, "\u0275prov");
43
44
  const fromRoot = Reflect.get(Object(provider), "providedIn") === "root";
44
45
  const built = Reflect.get(Object(Reflect.get(Object(injected), "constructor")), "name");
45
- const what = typeof built === "string" && built.length > 0 ? `a real ${built}` : "a real instance";
46
+ const what = typeof built === "string" && built.length > 0 ? `a real ${sourceClassName(built)}` : "a real instance";
46
47
  const why = fromRoot ? "nothing in the testing module provides a double, so Angular built it (providedIn: 'root')" : "the testing module provides the real class, not a double";
47
48
  return `[vitest-auto-spy] injectSpy(${name}): got ${what} \u2014 ${why}.
48
49
  Add provideAutoSpy(${name}) to providers.`;
@@ -1,6 +1,7 @@
1
1
  import { DISPOSE } from './chunk-PC3FAZT3.js';
2
2
  import { defaultStrict, resolveUnstubbedGuard, seedReturnValue, createFunctionSpy } from './chunk-HUS2MHK5.js';
3
3
  import { runClearHook, runConfigReset, reportMisconfiguration, AUTO_SPY_MARK, markAsMock, isMarkedMock, readDeepChildren } from './chunk-Q7L4AWI7.js';
4
+ import { sourceClassName } from './chunk-DYAS4OK4.js';
4
5
  import { autoMockHeldBack, createSpyFromClassInstanceMethods, createSpyFromClassAccessors, createSpyFromClassReturns, createSpyFromClassLazySpies } from './chunk-5FQZGJLJ.js';
5
6
  import { withDocs } from './chunk-ENCEEH23.js';
6
7
  import { getMockAdapter, requireObservableSupport, getJasmineSupport } from './shared-state.js';
@@ -899,7 +900,12 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
899
900
  function createSpyFromClass(ObjectClass, methodsToSpyOnOrConfig) {
900
901
  const config = resolveConfiguration(mergeAutoSpyDefaults(ObjectClass, methodsToSpyOnOrConfig));
901
902
  const autoSpy = assembleSpy(ObjectClass, config);
902
- applyConfiguredReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config, () => getAllMethodNames(ObjectClass.prototype));
903
+ applyConfiguredReturns(
904
+ autoSpy,
905
+ `createSpyFromClass(${sourceClassName(ObjectClass.name)})`,
906
+ config,
907
+ () => getAllMethodNames(ObjectClass.prototype)
908
+ );
903
909
  applyOverrides(autoSpy, config.overrides);
904
910
  return autoSpy;
905
911
  }
@@ -925,12 +931,9 @@ function assembleSpy(ObjectClass, config) {
925
931
  }
926
932
  const methodNames = resolveMethodNames(ObjectClass, config);
927
933
  const unstubbed = resolveUnstubbedGuard(ObjectClass.name, config);
934
+ const label = `createSpyFromClass(${sourceClassName(ObjectClass.name)})`;
928
935
  if (config.onlyMethodsToSpyOn.length > 0 && getAllMethodNames(ObjectClass.prototype).length > 0) {
929
- warnOnUnknownMethods(
930
- `createSpyFromClass(${ObjectClass.name})`,
931
- config.onlyMethodsToSpyOn,
932
- new Set(getAllMethodNames(ObjectClass.prototype))
933
- );
936
+ warnOnUnknownMethods(label, config.onlyMethodsToSpyOn, new Set(getAllMethodNames(ObjectClass.prototype)));
934
937
  }
935
938
  const autoSpy = {};
936
939
  const reads = accessors.getters.length > 0 || config.observablePropsToSpyOn.length > 0 ? resolveReadGuard(ObjectClass.name, config) : void 0;
@@ -938,7 +941,7 @@ function assembleSpy(ObjectClass, config) {
938
941
  autoSpy[observablePropName] = createTrackedPropSpy(observablePropName, reads);
939
942
  });
940
943
  if (config.gettersToSpyOn.length > 0 || config.settersToSpyOn.length > 0) {
941
- warnOnAccessorNamingAMethod(`createSpyFromClass(${ObjectClass.name})`, config, new Set(getAllMethodNames(ObjectClass.prototype)));
944
+ warnOnAccessorNamingAMethod(label, config, new Set(getAllMethodNames(ObjectClass.prototype)));
942
945
  }
943
946
  createAccessorsSpies(autoSpy, accessors.getters, accessors.setters, reads);
944
947
  methodNames.forEach((methodName) => {
@@ -969,7 +972,7 @@ function fillsMissing(ObjectClass, config) {
969
972
  }
970
973
  function isSignalStoreClass(ObjectClass) {
971
974
  for (let current = ObjectClass; typeof current === "function"; current = Object.getPrototypeOf(current)) {
972
- if (current.name === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
975
+ if (sourceClassName(current.name) === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
973
976
  return true;
974
977
  }
975
978
  }
@@ -1,4 +1,5 @@
1
1
  import { isAutoSpyLike } from './chunk-Q7L4AWI7.js';
2
+ import { sourceClassName } from './chunk-DYAS4OK4.js';
2
3
 
3
4
  // src/lib/angular-instance-name.ts
4
5
  function describeInstance(instance) {
@@ -7,7 +8,7 @@ function describeInstance(instance) {
7
8
  }
8
9
  const prototype = Reflect.getPrototypeOf(instance);
9
10
  const owner = prototype === null || prototype === Object.prototype ? void 0 : Reflect.get(prototype, "constructor");
10
- return typeof owner === "function" ? `an instance of ${owner.name}` : "a plain object";
11
+ return typeof owner === "function" ? `an instance of ${sourceClassName(owner.name)}` : "a plain object";
11
12
  }
12
13
 
13
14
  export { describeInstance };
package/dist/cli.js CHANGED
@@ -3446,7 +3446,7 @@ function checkForeignPragma(graph) {
3446
3446
  }
3447
3447
 
3448
3448
  // src/cli/checks/export-map.generated.ts
3449
- var EXPORT_MAP_VERSION = "5.40.0";
3449
+ var EXPORT_MAP_VERSION = "5.40.1";
3450
3450
  var ENTRY_SPECIFIERS = "vitest-auto-spy vitest-auto-spy/bun vitest-auto-spy/bun-angular vitest-auto-spy/node vitest-auto-spy/rstest vitest-auto-spy/rxjs vitest-auto-spy/console vitest-auto-spy/dom-stubs vitest-auto-spy/diagnostics vitest-auto-spy/jasmine vitest-auto-spy/jasmine-compat vitest-auto-spy/observer-spy vitest-auto-spy/angular vitest-auto-spy/angular/diagnostics vitest-auto-spy/angular/doubles vitest-auto-spy/angular/matchers vitest-auto-spy/angular-http vitest-auto-spy/angular-router vitest-auto-spy/signal-forms vitest-auto-spy/nestjs vitest-auto-spy/react vitest-auto-spy/vue vitest-auto-spy/svelte vitest-auto-spy/setup vitest-auto-spy/zone vitest-auto-spy/eslint-plugin vitest-auto-spy/perf-reporter";
3451
3451
  var EXPORTED_BY = {
3452
3452
  AccessorImplementations: "0 1 2 3 4 12 20 21 22",
package/dist/index.js CHANGED
@@ -2876,7 +2876,12 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
2876
2876
  function createSpyFromClass2(ObjectClass, methodsToSpyOnOrConfig) {
2877
2877
  const config = resolveConfiguration(mergeAutoSpyDefaults(ObjectClass, methodsToSpyOnOrConfig));
2878
2878
  const autoSpy = assembleSpy(ObjectClass, config);
2879
- applyConfiguredReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config, () => getAllMethodNames(ObjectClass.prototype));
2879
+ applyConfiguredReturns(
2880
+ autoSpy,
2881
+ `createSpyFromClass(${sourceClassName(ObjectClass.name)})`,
2882
+ config,
2883
+ () => getAllMethodNames(ObjectClass.prototype)
2884
+ );
2880
2885
  applyOverrides(autoSpy, config.overrides);
2881
2886
  return autoSpy;
2882
2887
  }
@@ -2902,12 +2907,9 @@ function assembleSpy(ObjectClass, config) {
2902
2907
  }
2903
2908
  const methodNames = resolveMethodNames(ObjectClass, config);
2904
2909
  const unstubbed = resolveUnstubbedGuard(ObjectClass.name, config);
2910
+ const label = `createSpyFromClass(${sourceClassName(ObjectClass.name)})`;
2905
2911
  if (config.onlyMethodsToSpyOn.length > 0 && getAllMethodNames(ObjectClass.prototype).length > 0) {
2906
- warnOnUnknownMethods(
2907
- `createSpyFromClass(${ObjectClass.name})`,
2908
- config.onlyMethodsToSpyOn,
2909
- new Set(getAllMethodNames(ObjectClass.prototype))
2910
- );
2912
+ warnOnUnknownMethods(label, config.onlyMethodsToSpyOn, new Set(getAllMethodNames(ObjectClass.prototype)));
2911
2913
  }
2912
2914
  const autoSpy = {};
2913
2915
  const reads = accessors.getters.length > 0 || config.observablePropsToSpyOn.length > 0 ? resolveReadGuard(ObjectClass.name, config) : void 0;
@@ -2915,7 +2917,7 @@ function assembleSpy(ObjectClass, config) {
2915
2917
  autoSpy[observablePropName] = createTrackedPropSpy(observablePropName, reads);
2916
2918
  });
2917
2919
  if (config.gettersToSpyOn.length > 0 || config.settersToSpyOn.length > 0) {
2918
- warnOnAccessorNamingAMethod(`createSpyFromClass(${ObjectClass.name})`, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2920
+ warnOnAccessorNamingAMethod(label, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2919
2921
  }
2920
2922
  createAccessorsSpies(autoSpy, accessors.getters, accessors.setters, reads);
2921
2923
  methodNames.forEach((methodName) => {
@@ -2946,7 +2948,7 @@ function fillsMissing(ObjectClass, config) {
2946
2948
  }
2947
2949
  function isSignalStoreClass(ObjectClass) {
2948
2950
  for (let current = ObjectClass; typeof current === "function"; current = Object.getPrototypeOf(current)) {
2949
- if (current.name === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2951
+ if (sourceClassName(current.name) === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2950
2952
  return true;
2951
2953
  }
2952
2954
  }
package/dist/jasmine.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { enableJasmineCompat } from './chunk-3ZBRBPOL.js';
2
2
  export { enableJasmineCompat } from './chunk-3ZBRBPOL.js';
3
- import { createSpyFromClass } from './chunk-H54YPKPT.js';
3
+ import { createSpyFromClass } from './chunk-T7EGA4G4.js';
4
4
  import { useVitestAdapter } from './chunk-6ZGH56G4.js';
5
5
  import './chunk-IE4NI2OQ.js';
6
6
  import './chunk-YHDBRBGU.js';
package/dist/nestjs.js CHANGED
@@ -1,6 +1,6 @@
1
- import { createSpyForToken } from './chunk-IWTUXEAR.js';
2
- export { trackInjections } from './chunk-IWTUXEAR.js';
3
- import { createSpyFromClass } from './chunk-H54YPKPT.js';
1
+ import { createSpyForToken } from './chunk-O55MVK7N.js';
2
+ export { trackInjections } from './chunk-O55MVK7N.js';
3
+ import { createSpyFromClass } from './chunk-T7EGA4G4.js';
4
4
  import { useVitestAdapter } from './chunk-6ZGH56G4.js';
5
5
  import './chunk-IE4NI2OQ.js';
6
6
  import './chunk-YHDBRBGU.js';
package/dist/node.cjs CHANGED
@@ -2505,7 +2505,12 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
2505
2505
  function createSpyFromClass2(ObjectClass, methodsToSpyOnOrConfig) {
2506
2506
  const config = resolveConfiguration(mergeAutoSpyDefaults(ObjectClass, methodsToSpyOnOrConfig));
2507
2507
  const autoSpy = assembleSpy(ObjectClass, config);
2508
- applyConfiguredReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config, () => getAllMethodNames(ObjectClass.prototype));
2508
+ applyConfiguredReturns(
2509
+ autoSpy,
2510
+ `createSpyFromClass(${sourceClassName(ObjectClass.name)})`,
2511
+ config,
2512
+ () => getAllMethodNames(ObjectClass.prototype)
2513
+ );
2509
2514
  applyOverrides(autoSpy, config.overrides);
2510
2515
  return autoSpy;
2511
2516
  }
@@ -2531,12 +2536,9 @@ function assembleSpy(ObjectClass, config) {
2531
2536
  }
2532
2537
  const methodNames = resolveMethodNames(ObjectClass, config);
2533
2538
  const unstubbed = resolveUnstubbedGuard(ObjectClass.name, config);
2539
+ const label = `createSpyFromClass(${sourceClassName(ObjectClass.name)})`;
2534
2540
  if (config.onlyMethodsToSpyOn.length > 0 && getAllMethodNames(ObjectClass.prototype).length > 0) {
2535
- warnOnUnknownMethods(
2536
- `createSpyFromClass(${ObjectClass.name})`,
2537
- config.onlyMethodsToSpyOn,
2538
- new Set(getAllMethodNames(ObjectClass.prototype))
2539
- );
2541
+ warnOnUnknownMethods(label, config.onlyMethodsToSpyOn, new Set(getAllMethodNames(ObjectClass.prototype)));
2540
2542
  }
2541
2543
  const autoSpy = {};
2542
2544
  const reads = accessors.getters.length > 0 || config.observablePropsToSpyOn.length > 0 ? resolveReadGuard(ObjectClass.name, config) : void 0;
@@ -2544,7 +2546,7 @@ function assembleSpy(ObjectClass, config) {
2544
2546
  autoSpy[observablePropName] = createTrackedPropSpy(observablePropName, reads);
2545
2547
  });
2546
2548
  if (config.gettersToSpyOn.length > 0 || config.settersToSpyOn.length > 0) {
2547
- warnOnAccessorNamingAMethod(`createSpyFromClass(${ObjectClass.name})`, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2549
+ warnOnAccessorNamingAMethod(label, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2548
2550
  }
2549
2551
  createAccessorsSpies(autoSpy, accessors.getters, accessors.setters, reads);
2550
2552
  methodNames.forEach((methodName) => {
@@ -2575,7 +2577,7 @@ function fillsMissing(ObjectClass, config) {
2575
2577
  }
2576
2578
  function isSignalStoreClass(ObjectClass) {
2577
2579
  for (let current = ObjectClass; typeof current === "function"; current = Object.getPrototypeOf(current)) {
2578
- if (current.name === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2580
+ if (sourceClassName(current.name) === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2579
2581
  return true;
2580
2582
  }
2581
2583
  }
package/dist/node.js CHANGED
@@ -2399,7 +2399,12 @@ function resolveConfiguration(methodsToSpyOnOrConfig) {
2399
2399
  function createSpyFromClass2(ObjectClass, methodsToSpyOnOrConfig) {
2400
2400
  const config = resolveConfiguration(mergeAutoSpyDefaults(ObjectClass, methodsToSpyOnOrConfig));
2401
2401
  const autoSpy = assembleSpy(ObjectClass, config);
2402
- applyConfiguredReturns(autoSpy, `createSpyFromClass(${ObjectClass.name})`, config, () => getAllMethodNames(ObjectClass.prototype));
2402
+ applyConfiguredReturns(
2403
+ autoSpy,
2404
+ `createSpyFromClass(${sourceClassName(ObjectClass.name)})`,
2405
+ config,
2406
+ () => getAllMethodNames(ObjectClass.prototype)
2407
+ );
2403
2408
  applyOverrides(autoSpy, config.overrides);
2404
2409
  return autoSpy;
2405
2410
  }
@@ -2425,12 +2430,9 @@ function assembleSpy(ObjectClass, config) {
2425
2430
  }
2426
2431
  const methodNames = resolveMethodNames(ObjectClass, config);
2427
2432
  const unstubbed = resolveUnstubbedGuard(ObjectClass.name, config);
2433
+ const label = `createSpyFromClass(${sourceClassName(ObjectClass.name)})`;
2428
2434
  if (config.onlyMethodsToSpyOn.length > 0 && getAllMethodNames(ObjectClass.prototype).length > 0) {
2429
- warnOnUnknownMethods(
2430
- `createSpyFromClass(${ObjectClass.name})`,
2431
- config.onlyMethodsToSpyOn,
2432
- new Set(getAllMethodNames(ObjectClass.prototype))
2433
- );
2435
+ warnOnUnknownMethods(label, config.onlyMethodsToSpyOn, new Set(getAllMethodNames(ObjectClass.prototype)));
2434
2436
  }
2435
2437
  const autoSpy = {};
2436
2438
  const reads = accessors.getters.length > 0 || config.observablePropsToSpyOn.length > 0 ? resolveReadGuard(ObjectClass.name, config) : void 0;
@@ -2438,7 +2440,7 @@ function assembleSpy(ObjectClass, config) {
2438
2440
  autoSpy[observablePropName] = createTrackedPropSpy(observablePropName, reads);
2439
2441
  });
2440
2442
  if (config.gettersToSpyOn.length > 0 || config.settersToSpyOn.length > 0) {
2441
- warnOnAccessorNamingAMethod(`createSpyFromClass(${ObjectClass.name})`, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2443
+ warnOnAccessorNamingAMethod(label, config, new Set(getAllMethodNames(ObjectClass.prototype)));
2442
2444
  }
2443
2445
  createAccessorsSpies(autoSpy, accessors.getters, accessors.setters, reads);
2444
2446
  methodNames.forEach((methodName) => {
@@ -2469,7 +2471,7 @@ function fillsMissing(ObjectClass, config) {
2469
2471
  }
2470
2472
  function isSignalStoreClass(ObjectClass) {
2471
2473
  for (let current = ObjectClass; typeof current === "function"; current = Object.getPrototypeOf(current)) {
2472
- if (current.name === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2474
+ if (sourceClassName(current.name) === "SignalStore" && Object.hasOwn(current, "\u0275prov")) {
2473
2475
  return true;
2474
2476
  }
2475
2477
  }
package/dist/rstest.js CHANGED
@@ -1,6 +1,6 @@
1
- export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DQCAFHHR.js';
1
+ export { adoptMock, asInstance, asInstances, asSpy, assertMocked, captureArg, createFixture, createFixtureFactory, createLog, createMock, createSpyClass, createSpyFromInstance, describeDuplicateCopies, expectAllEmissions, expectCompletion, expectEmission, expectEmissions, expectError, expectNoEmission, flushEventLoop, flushEventLoopUntil, getPackageCopies, mockConstructor, mockDeep, moduleNamespace, narrow, outOfType, restoreSpiedInstance, setEmissionTimeout, settleDynamicImport, spyOnOwnMethod, spyOnVoidMethod, stubConstructor, withOverrides } from './chunk-DG5EP3PO.js';
2
2
  export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-MNY4ZHEQ.js';
3
- export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-H54YPKPT.js';
3
+ export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-T7EGA4G4.js';
4
4
  import './chunk-HVNKTPKG.js';
5
5
  import { createRunnerMockAdapter } from './chunk-IE4NI2OQ.js';
6
6
  import './chunk-TXDBDMIL.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-auto-spy",
3
- "version": "5.40.1",
3
+ "version": "5.41.0",
4
4
  "description": "Auto-generate fully-typed test spies from a class — across Vitest, Bun, node:test and Rstest, with Angular/NestJS/React/Vue/Svelte recipes. Drop-in replacement for jest-auto-spies and jasmine-auto-spies.",
5
5
  "keywords": [
6
6
  "auto-mock",