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.
Files changed (39) hide show
  1. package/AGENTS.md +89 -2
  2. package/README.md +135 -6
  3. package/dist/angular.d.ts +2 -2
  4. package/dist/angular.js +276 -7
  5. package/dist/bun-angular.d.ts +3 -3
  6. package/dist/bun-angular.js +6 -6
  7. package/dist/bun.d.ts +72 -2
  8. package/dist/bun.js +4 -4
  9. package/dist/{chunk-DSIYS6Y5.js → chunk-D5LDT3W4.js} +1 -1
  10. package/dist/{chunk-2ZG27FVL.js → chunk-EMASXQDZ.js} +1 -1
  11. package/dist/{chunk-4KK3ES4P.js → chunk-FFKN6QKI.js} +22 -0
  12. package/dist/{chunk-4KCYFAJX.js → chunk-FYFF67EN.js} +23 -7
  13. package/dist/{chunk-5URFSYDT.js → chunk-GAY6LNAM.js} +300 -6
  14. package/dist/{chunk-WQZ2RKS7.js → chunk-KYAJCFUA.js} +1 -1
  15. package/dist/{chunk-KEKKEIRG.js → chunk-Z4VRMCW2.js} +1 -1
  16. package/dist/cli.js +606 -16
  17. package/dist/console.js +2 -2
  18. package/dist/diagnostics.d.ts +31 -1
  19. package/dist/diagnostics.js +350 -1
  20. package/dist/{expect-emission-BDuFuqTb.d.ts → expect-emission-Dy5CvsF2.d.ts} +27 -25
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +444 -111
  23. package/dist/jasmine.js +4 -4
  24. package/dist/nestjs.js +5 -5
  25. package/dist/node.cjs +272 -111
  26. package/dist/node.d.cts +2 -0
  27. package/dist/node.d.ts +2 -2
  28. package/dist/node.js +17 -5
  29. package/dist/react.d.ts +2 -2
  30. package/dist/react.js +5 -5
  31. package/dist/setup.js +4 -4
  32. package/dist/shared-state.js +4 -275
  33. package/dist/svelte.d.ts +2 -2
  34. package/dist/svelte.js +5 -5
  35. package/dist/vue.d.ts +2 -2
  36. package/dist/vue.js +6 -6
  37. package/dist/{zoneless-DGwkbWKm.d.ts → zoneless-LsBDcSNZ.d.ts} +1 -1
  38. package/package.json +6 -2
  39. package/skills/vitest-auto-spy/SKILL.md +4 -1
package/dist/cli.js CHANGED
@@ -187,13 +187,14 @@ function stripJsonComments(text) {
187
187
  return result.replace(/,(\s*[\]}])/g, "$1");
188
188
  }
189
189
  function findStringEnd(text, start) {
190
+ const quote = text[start];
190
191
  let index = start + 1;
191
192
  while (index < text.length) {
192
193
  if (text[index] === "\\") {
193
194
  index += 2;
194
195
  continue;
195
196
  }
196
- if (text[index] === '"') {
197
+ if (text[index] === quote) {
197
198
  return index + 1;
198
199
  }
199
200
  index += 1;
@@ -643,12 +644,12 @@ function insertIntoBraces(source, host, needs) {
643
644
  return { start: last, end: last, text: /,$/.test(source.slice(open + 1, last)) ? ` ${addition}` : `, ${addition}` };
644
645
  }
645
646
  function pickHost(statements, specifier, needs) {
646
- const candidates = hostsFor(statements, specifier);
647
- const value = candidates.find((host) => !host.statement.typeOnly);
647
+ const candidates2 = hostsFor(statements, specifier);
648
+ const value = candidates2.find((host) => !host.statement.typeOnly);
648
649
  if (value !== void 0) {
649
650
  return value;
650
651
  }
651
- return needs.every((need) => need.typeOnly) ? candidates[0] : void 0;
652
+ return needs.every((need) => need.typeOnly) ? candidates2[0] : void 0;
652
653
  }
653
654
  function uniqueNeeds(source, statements, needs) {
654
655
  const bound = allBound(source, statements);
@@ -1076,8 +1077,8 @@ function best(pool) {
1076
1077
  function partsOf(specifier) {
1077
1078
  return specifier.slice(specifier.indexOf("/") + 1).split("-");
1078
1079
  }
1079
- function narrow(candidates, framework) {
1080
- return framework === void 0 ? [] : candidates.filter((candidate) => partsOf(candidate).includes(framework));
1080
+ function narrow(candidates2, framework) {
1081
+ return framework === void 0 ? [] : candidates2.filter((candidate) => partsOf(candidate).includes(framework));
1081
1082
  }
1082
1083
  function sameRuntime(pool, preferred) {
1083
1084
  const wanted = pool.filter((candidate) => candidate.startsWith(BUN_PREFIX) === preferred.startsWith(BUN_PREFIX));
@@ -1096,16 +1097,16 @@ function chooseEntry(map, name, preferred, hint) {
1096
1097
  }
1097
1098
  return specifiers.length === 1 ? { kind: "chosen", entry: best(specifiers) } : decide(specifiers, preferred, hint);
1098
1099
  }
1099
- function decide(candidates, preferred, hint) {
1100
- const known = candidates.find((candidate) => hint.imported.includes(candidate));
1100
+ function decide(candidates2, preferred, hint) {
1101
+ const known = candidates2.find((candidate) => hint.imported.includes(candidate));
1101
1102
  if (known !== void 0) {
1102
1103
  return { kind: "chosen", entry: known };
1103
1104
  }
1104
- const scoped = narrow(candidates, hint.framework);
1105
+ const scoped = narrow(candidates2, hint.framework);
1105
1106
  if (scoped.length > 0) {
1106
1107
  return { kind: "chosen", entry: best(sameRuntime(scoped, preferred)) };
1107
1108
  }
1108
- return { kind: "guessed", entry: best(sameRuntime(candidates, preferred)), candidates };
1109
+ return { kind: "guessed", entry: best(sameRuntime(candidates2, preferred)), candidates: candidates2 };
1109
1110
  }
1110
1111
  function entryFor(map, name, preferred) {
1111
1112
  const choice = chooseEntry(map, name, preferred, NO_HINT);
@@ -2353,6 +2354,521 @@ function checkForeignPragma(graph) {
2353
2354
  }
2354
2355
  return findings;
2355
2356
  }
2357
+
2358
+ // src/cli/checks/export-map.generated.ts
2359
+ var EXPORT_MAP_VERSION = "4.2.0";
2360
+ var ENTRY_SPECIFIERS = "vitest-auto-spy vitest-auto-spy/bun vitest-auto-spy/bun-angular vitest-auto-spy/node 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-http 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";
2361
+ var EXPORTED_BY = {
2362
+ AccessorImplementations: "0 1 2 3 11 14 15 16",
2363
+ AccessorKeysOf: "0 1 2 3 14 15 16",
2364
+ AddAccessorsSpies: "0 1 2 3 14 15 16",
2365
+ AddCalledWithObservable: "0 1 2 3 14 15 16",
2366
+ AddCalledWithPromise: "0 1 2 3 14 15 16",
2367
+ AddCalledWithSpyMethods: "0 1 2 3 14 15 16",
2368
+ AddObservableSpyMethods: "0 1 2 3 4 14 15 16",
2369
+ AddPromiseSpyMethods: "0 1 2 3 14 15 16",
2370
+ AddSpyMethodsByReturnTypes: "0 1 2 3 14 15 16",
2371
+ AddThrowHelper: "0 1 2 3 14 15 16",
2372
+ AddVoidReturnHelpers: "0 1 2 3 14 15 16",
2373
+ advanceTimers: "17",
2374
+ AngularDiagnosticsOptions: "11",
2375
+ AngularResourceInlinerOptions: "2",
2376
+ AngularTestEnvMode: "11",
2377
+ AngularTestEnvOptions: "11",
2378
+ AngularTokenProvider: "11",
2379
+ AngularValueProvider: "2 8 11",
2380
+ ArgCaptor: "0 1 2 3 14 15 16",
2381
+ asInstance: "0 1 2 3 14 15 16",
2382
+ asInstances: "0 1 2 3 14 15 16",
2383
+ AsInstances: "0 1 2 3 14 15 16",
2384
+ assertComponentDefIntact: "11",
2385
+ assertMocked: "0 1 2 3 14 15 16",
2386
+ AssertMockedOptions: "0 1 2 3 14 15 16",
2387
+ assertNgModuleScopes: "11",
2388
+ assertNoPendingRequests: "11",
2389
+ asSpy: "0 1 2 3 14 15 16",
2390
+ AutoMockConfiguration: "0 1 2 3 14 15 16",
2391
+ autoMocked: "0 1 2 3 14 15 16",
2392
+ AutoSpiedInstance: "2 11",
2393
+ AutoSpyEslintPlugin: "19",
2394
+ AutoSpyFixture: "11",
2395
+ AutoSpyOverride: "11",
2396
+ AutoSpyRxjsTypes: "0 1 2 3 14 15 16",
2397
+ BLOCKED_FETCH_MESSAGE: "17",
2398
+ BLOCKED_XHR_MESSAGE: "17",
2399
+ blockNetwork: "17",
2400
+ BlockNetworkOptions: "17",
2401
+ CallbackSubscribable: "0 1 2 3 11 14 15 16",
2402
+ cancelStrayTimers: "17",
2403
+ captureArg: "0 1 2 3 14 15 16",
2404
+ captureMockRegistry: "17",
2405
+ ClassSpyConfiguration: "0 1 2 3 8 14 15 16",
2406
+ ClassType: "0 1 2 3 8 14 15 16",
2407
+ clearAutoSpy: "0 1 2 3 14 15 16",
2408
+ compareTestRuns: "7",
2409
+ CompleteValueConfig: "0 1 2 3 4 14 15 16",
2410
+ ComponentInputs: "2 11",
2411
+ consoleDebugSpy: "5",
2412
+ consoleErrorSpy: "5",
2413
+ consoleInfoSpy: "5",
2414
+ consoleLogSpy: "5",
2415
+ ConsoleMethodSpy: "5",
2416
+ ConsoleSpies: "5",
2417
+ consoleTimeEndSpy: "5",
2418
+ consoleTimeSpy: "5",
2419
+ consoleTraceSpy: "5",
2420
+ consoleWarnSpy: "5",
2421
+ ConstructorMock: "0 1 2 3 14 15 16",
2422
+ ConstructorSpy: "0 1 2 3 14 15 16",
2423
+ copyWindowGlobals: "2",
2424
+ CountingClock: "17",
2425
+ CountingClockOptions: "17",
2426
+ countMockedProps: "0 1 2 3 11 14 15 16",
2427
+ countNodeMocks: "3",
2428
+ countStrayRejections: "17",
2429
+ countStrayTimers: "17",
2430
+ createAutoMock: "0 1 2 3 14 15 16",
2431
+ createDirectiveHost: "11",
2432
+ createFixture: "0 1 2 3 14 15 16",
2433
+ createFixtureFactory: "0 1 2 3 14 15 16",
2434
+ createFunctionSpy: "0 1 2 3 8 14 15 16",
2435
+ createGlobalRegistratorRegistrar: "2",
2436
+ createJsdomRegistrar: "2",
2437
+ createMock: "0 1 2 3 14 15 16",
2438
+ createNestUnit: "13",
2439
+ CreateNestUnitOptions: "13",
2440
+ createObservableWithValues: "4",
2441
+ createSpyClass: "0 1 2 3 14 15 16",
2442
+ createSpyFromClass: "0 1 2 3 8 14 15 16",
2443
+ createSpyFromInstance: "0 1 2 3 14 15 16",
2444
+ createSpyObj: "8",
2445
+ createWithAutoSpies: "2 11",
2446
+ CreateWithAutoSpiesOptions: "2 11",
2447
+ DeepMockProxy: "0 1 2 3 14 15 16",
2448
+ DeepPartial: "0 1 2 3 14 15 16",
2449
+ default: "19",
2450
+ describeDuplicateCopies: "0 1 2 3 14 15 16 17",
2451
+ diffByField: "7",
2452
+ DirectiveHostOptions: "11",
2453
+ disableAngularDiagnostics: "11",
2454
+ disableTestBedDiagnostics: "11",
2455
+ DomRegistrar: "2",
2456
+ DuplicateCopiesReaction: "17",
2457
+ EmissionObserver: "0 1 2 3 11 14 15 16",
2458
+ EmissionOptions: "0 1 2 3 11 14 15 16",
2459
+ EmissionSource: "0 1 2 3 11 14 15 16",
2460
+ enableAngularDiagnostics: "11",
2461
+ enableJasmineCompat: "8 9",
2462
+ enableTestBedDiagnostics: "11",
2463
+ errorHandler: "0 1 2 3 14 15 16",
2464
+ ErrorValueConfig: "0 1 2 3 4 14 15 16",
2465
+ expectCompletion: "0 1 2 3 11 14 15 16",
2466
+ expectEmission: "0 1 2 3 11 14 15 16",
2467
+ expectEmissions: "0 1 2 3 11 14 15 16",
2468
+ expectError: "0 1 2 3 11 14 15 16",
2469
+ expectNoEmission: "0 1 2 3 11 14 15 16",
2470
+ expectNoRequest: "12",
2471
+ expectRequest: "12",
2472
+ ExpectRequestOptions: "12",
2473
+ explainSpy: "7",
2474
+ extendWithAutoSpies: "11",
2475
+ ExtendWithAutoSpiesOptions: "11",
2476
+ FakeTimersConfig: "17",
2477
+ FixtureFactory: "0 1 2 3 14 15 16",
2478
+ FlatConfig: "19",
2479
+ flushEffects: "2 11",
2480
+ flushEventLoop: "0 1 2 3 14 15 16",
2481
+ flushEventLoopUntil: "0 1 2 3 14 15 16",
2482
+ FlushOptions: "12",
2483
+ flushStrayRejections: "17",
2484
+ FlushUntilOptions: "0 1 2 3 14 15 16",
2485
+ formatSpecTiming: "11",
2486
+ formatTestRunComparison: "7",
2487
+ Func: "0 1 2 3 14 15 16",
2488
+ getMockRegistrySize: "17",
2489
+ getPackageCopies: "0 1 2 3 14 15 16 17",
2490
+ getSpyEngine: "17",
2491
+ getTestBedTiming: "11",
2492
+ getWatchedTimerGlobals: "17",
2493
+ GlobalPatchReaction: "17",
2494
+ GlobalRegistratorOptions: "2",
2495
+ guardGlobalPatches: "17",
2496
+ HttpTestingOptions: "12",
2497
+ InjectionLog: "11 13",
2498
+ injectSpy: "2 11 13",
2499
+ inlineAngularResources: "2",
2500
+ installConsoleSpies: "5",
2501
+ installPerTest: "17",
2502
+ installProxyZonePatch: "18",
2503
+ instrumentTestBed: "11",
2504
+ intersectionEntry: "6",
2505
+ IntersectionObserverStubOptions: "6",
2506
+ jasmine: "8",
2507
+ JasmineAccessorSpies: "8 9",
2508
+ JasmineAccessorSpy: "8 9",
2509
+ JasmineAnd: "8 9",
2510
+ JasmineCallInfo: "8 9",
2511
+ JasmineCalls: "8 9",
2512
+ JasmineClassSpyConfiguration: "8",
2513
+ JasmineClock: "8",
2514
+ JasmineMethodSpy: "8 9",
2515
+ JasmineNamespaces: "8 9",
2516
+ JasmineSpy: "8 9",
2517
+ JasmineStrategies: "8 9",
2518
+ JasmineWithArgsAnd: "8 9",
2519
+ JasmineWithArgsSync: "8 9",
2520
+ JsdomModule: "2",
2521
+ JsdomRegistrarOptions: "2",
2522
+ keepMockRegistered: "17",
2523
+ keepRegisteredMocks: "17",
2524
+ MediaElementState: "6",
2525
+ MediaElementStub: "6",
2526
+ MediaElementStubOptions: "6",
2527
+ MethodReturns: "0 1 2 3 14 15 16",
2528
+ mockAccessorsProp: "0 1 2 3 11 14 15 16",
2529
+ mockConstructor: "0 1 2 3 14 15 16",
2530
+ mockDeep: "0 1 2 3 14 15 16",
2531
+ MockDeepOptions: "0 1 2 3 14 15 16",
2532
+ MockedResource: "11",
2533
+ mockNow: "17",
2534
+ mockReadonlyProp: "0 1 2 3 11 14 15 16",
2535
+ mockReadonlyPropGetter: "0 1 2 3 11 14 15 16",
2536
+ mockResourceProp: "11",
2537
+ mockSignalProp: "11",
2538
+ mockSystemTime: "17",
2539
+ mockValueProp: "0 1 2 3 11 14 15 16",
2540
+ moduleNamespace: "0 1 2 3 14 15 16",
2541
+ ModuleNamespace: "0 1 2 3 14 15 16",
2542
+ ModuleNamespaceOptions: "0 1 2 3 14 15 16",
2543
+ Mutable: "0 1 2 3 14 15 16",
2544
+ mutationRecord: "6",
2545
+ MutationRecordInit: "6",
2546
+ narrow: "0 1 2 3 14 15 16",
2547
+ NestModuleRef: "13",
2548
+ NestUnit: "13",
2549
+ NestUnitClass: "13",
2550
+ NestUnitProvider: "13",
2551
+ NestUnitSpies: "13",
2552
+ NestValueProvider: "13",
2553
+ NextValueConfig: "0 1 2 3 4 14 15 16",
2554
+ ObservableLike: "0 1 2 3 14 15 16",
2555
+ ObserverGlobal: "6",
2556
+ ObserverInstance: "6",
2557
+ ObserverSpy: "10",
2558
+ ObserverSpyConfig: "10",
2559
+ ObserverStub: "6",
2560
+ ObserverStubOptions: "6",
2561
+ OnlyMethodKeysOf: "0 1 2 3 8 14 15 16",
2562
+ OnlyObservablePropsOf: "0 1 2 3 8 14 15 16",
2563
+ OnlyPropsOf: "0 1 2 3 8 14 15 16",
2564
+ Overload: "0 1 2 3 14 15 16",
2565
+ Overloads: "0 1 2 3 14 15 16",
2566
+ overrideAutoSpy: "11",
2567
+ overrideComponentProvider: "11",
2568
+ PerTestHandle: "17",
2569
+ PropStubValue: "0 1 2 3 14 15 16",
2570
+ provideAutoSpy: "2 8 11 13 15",
2571
+ provideAutoSpyForToken: "11",
2572
+ provideHttpTesting: "12",
2573
+ ProxyZonePatchOptions: "18",
2574
+ ProxyZoneScope: "18",
2575
+ pruneMockRegistry: "17",
2576
+ pruneNodeMocks: "3",
2577
+ registerDirectiveMatchers: "11",
2578
+ registerDomGlobals: "2",
2579
+ RegisterDomGlobalsOptions: "2",
2580
+ registerFocusMatchers: "17",
2581
+ registerJasmineMatchers: "8",
2582
+ registerResourceMatchers: "11",
2583
+ registerSignalMatchers: "11",
2584
+ RejectionHost: "17",
2585
+ renderShallow: "2 11",
2586
+ RenderShallowOptions: "2 11",
2587
+ reportSpecTiming: "11",
2588
+ RequestErrorOptions: "12",
2589
+ RequestExpectation: "12",
2590
+ RequestMatcher: "12",
2591
+ resetAutoSpy: "0 1 2 3 14 15 16",
2592
+ resetConsoleSpies: "5",
2593
+ resetMockRegistryTracking: "17",
2594
+ resizeEntry: "6",
2595
+ ResizeEntryRect: "6",
2596
+ ResourceDouble: "11",
2597
+ ResourceDoubleStatus: "11",
2598
+ ResourceLike: "11",
2599
+ ResourceStatusLike: "2 11",
2600
+ ResponseBody: "12",
2601
+ restoreConsole: "5",
2602
+ restoreLongLivedImplementations: "17",
2603
+ restoreMockedProps: "0 1 2 3 11 14 15 16",
2604
+ RestoreProp: "0 1 2 3 11 14 15 16",
2605
+ restoreSpiedInstance: "0 1 2 3 14 15 16",
2606
+ restoreTimerGlobals: "17",
2607
+ RuleSeverity: "19",
2608
+ runEffect: "2 11",
2609
+ SchedulerHost: "17",
2610
+ setEmissionTimeout: "0 1 2 3 11 14 15 16",
2611
+ setSpyEngine: "17",
2612
+ settleDynamicImport: "0 1 2 3 14 15 16",
2613
+ settleResource: "2 11",
2614
+ SettleResourceOptions: "2 11",
2615
+ setupAngularTestEnv: "11",
2616
+ setupAutoSpy: "17",
2617
+ SetupAutoSpyOptions: "17",
2618
+ setupFakeTimers: "17",
2619
+ ShallowRender: "2 11",
2620
+ SignalLike: "11",
2621
+ SpecTiming: "11",
2622
+ SpiedFixtures: "11",
2623
+ Spy: "0 1 2 3 8 14 15 16",
2624
+ SpyDisposable: "0 1 2 3 14 15 16",
2625
+ SpyEngine: "17",
2626
+ SpyObj: "8",
2627
+ SpyOptions: "0 1 2 3 14 15 16",
2628
+ SpyRegistry: "2 11",
2629
+ stable: "2 11",
2630
+ StableOptions: "2 11",
2631
+ StopTrackingNodeMocks: "3",
2632
+ StopTrackingRejections: "17",
2633
+ StopTrackingTimers: "17",
2634
+ StrayRejection: "17",
2635
+ StrictSpyConfiguration: "0 1 2 3 14 15 16",
2636
+ stubAbortController: "6",
2637
+ stubConstructor: "0 1 2 3 14 15 16",
2638
+ stubIntersectionObserver: "6",
2639
+ stubMediaElement: "6",
2640
+ stubMutationObserver: "6",
2641
+ stubObserver: "6",
2642
+ stubResizeObserver: "6",
2643
+ SubjectLike: "0 1 2 3 14 15 16",
2644
+ SubjectOf: "0 1 2 3 14 15 16",
2645
+ SubscribableLike: "0 1 2 3 11 14 15 16",
2646
+ SubscriberSpy: "10",
2647
+ subscribeSpyTo: "10",
2648
+ summarizeTestRun: "7",
2649
+ SystemTime: "17",
2650
+ TestBedDiagnosticsOptions: "11",
2651
+ TestRunComparison: "7",
2652
+ TestRunReport: "7",
2653
+ TestRunSummary: "7",
2654
+ TrackedProvider: "11 13",
2655
+ trackInjections: "11 13",
2656
+ TrackInjectionsOptions: "11 13",
2657
+ trackMockRegistry: "17",
2658
+ trackNodeMocks: "3",
2659
+ trackStrayRejections: "17",
2660
+ trackStrayTimers: "17",
2661
+ UnstubbedCall: "0 1 2 3 14 15 16",
2662
+ UnstubbedCallHandler: "0 1 2 3 14 15 16",
2663
+ useCountingClock: "17",
2664
+ ValueConfig: "0 1 2 3 4 14 15 16",
2665
+ ValueConfigPerCall: "0 1 2 3 4 14 15 16",
2666
+ verifyNoPendingRequests: "12",
2667
+ VueInjectionToken: "15",
2668
+ VueProvideSpy: "15",
2669
+ WithMockReturnValue: "0 1 2 3 14 15 16",
2670
+ withOverrides: "0 1 2 3 14 15 16",
2671
+ withSystemTime: "17",
2672
+ XhrBlockMode: "17"
2673
+ };
2674
+ var AWAITABLE_HELPERS = "advanceTimers expectCompletion expectEmission expectEmissions expectError expectNoEmission flushEventLoop flushEventLoopUntil registerDomGlobals settleDynamicImport settleResource stable withSystemTime";
2675
+
2676
+ // src/cli/checks/literals.ts
2677
+ var QUOTES = /* @__PURE__ */ new Set(["'", '"']);
2678
+ var BLOCK_END = "*/";
2679
+ function endOfLineComment(source, start) {
2680
+ const newline = source.indexOf("\n", start);
2681
+ return newline === -1 ? source.length : newline;
2682
+ }
2683
+ function endOfBlockComment(source, start) {
2684
+ const close = source.indexOf(BLOCK_END, start + BLOCK_END.length);
2685
+ return close === -1 ? source.length : close + BLOCK_END.length;
2686
+ }
2687
+ function endOfInterpolation(source, start) {
2688
+ let depth = 1;
2689
+ let index = start;
2690
+ while (index < source.length) {
2691
+ const char = source.charAt(index);
2692
+ if (char === "`") {
2693
+ index = endOfTemplate(source, index);
2694
+ continue;
2695
+ }
2696
+ if (QUOTES.has(char)) {
2697
+ index = findStringEnd(source, index);
2698
+ continue;
2699
+ }
2700
+ if (char === "{") {
2701
+ depth += 1;
2702
+ }
2703
+ if (char === "}") {
2704
+ depth -= 1;
2705
+ if (depth === 0) {
2706
+ return index + 1;
2707
+ }
2708
+ }
2709
+ index += 1;
2710
+ }
2711
+ return source.length;
2712
+ }
2713
+ function endOfTemplate(source, start) {
2714
+ let index = start + 1;
2715
+ while (index < source.length) {
2716
+ const char = source.charAt(index);
2717
+ if (char === "\\") {
2718
+ index += 2;
2719
+ continue;
2720
+ }
2721
+ if (char === "`") {
2722
+ return index + 1;
2723
+ }
2724
+ if (char === "$" && source.charAt(index + 1) === "{") {
2725
+ index = endOfInterpolation(source, index + 2);
2726
+ continue;
2727
+ }
2728
+ index += 1;
2729
+ }
2730
+ return source.length;
2731
+ }
2732
+ function spanEnd(source, index) {
2733
+ const char = source.charAt(index);
2734
+ if (char === "/") {
2735
+ const next = source.charAt(index + 1);
2736
+ if (next === "/") {
2737
+ return endOfLineComment(source, index);
2738
+ }
2739
+ return next === "*" ? endOfBlockComment(source, index) : -1;
2740
+ }
2741
+ if (QUOTES.has(char)) {
2742
+ return findStringEnd(source, index);
2743
+ }
2744
+ return char === "`" ? endOfTemplate(source, index) : -1;
2745
+ }
2746
+ function literalSpans(source) {
2747
+ const spans = [];
2748
+ let index = 0;
2749
+ while (index < source.length) {
2750
+ const end = spanEnd(source, index);
2751
+ if (end === -1) {
2752
+ index += 1;
2753
+ continue;
2754
+ }
2755
+ spans.push({ start: index, end });
2756
+ index = end;
2757
+ }
2758
+ return spans;
2759
+ }
2760
+ function isInsideLiteral(spans, offset) {
2761
+ return spans.some((span) => span.start <= offset && offset < span.end);
2762
+ }
2763
+
2764
+ // src/cli/checks/entry-imports.ts
2765
+ var ENTRIES = ENTRY_SPECIFIERS.split(" ");
2766
+ var AWAITABLE = new Set(AWAITABLE_HELPERS.split(" "));
2767
+ var NO_OWNERS = [];
2768
+ var OWNERS = new Map(
2769
+ Object.entries(EXPORTED_BY).map(([name, indices]) => {
2770
+ const owned = new Set(indices.split(" ").map(Number));
2771
+ return [name, ENTRIES.filter((_entry, index) => owned.has(index))];
2772
+ })
2773
+ );
2774
+ var NAMES_BY_ENTRY = new Map(
2775
+ ENTRIES.map((entry) => [entry, new Set([...OWNERS].filter(([, owners]) => owners.includes(entry)).map(([name]) => name))])
2776
+ );
2777
+ var IMPORT = /\bimport\s+(?:type\s+)?([\s\w$*,{}]*?)\s*from\s*["'](vitest-auto-spy(?:\/[\w-]+)?)["']/g;
2778
+ var BRACED = /{([^}]*)}/g;
2779
+ var RENAME = " as ";
2780
+ function parseClause(clause, entry) {
2781
+ const found = [];
2782
+ for (const inner of captures(clause, BRACED)) {
2783
+ for (const raw of inner.split(",")) {
2784
+ const token = raw.trim().replace(/\s+/g, " ").replace(/^type /, "");
2785
+ const rename = token.indexOf(RENAME);
2786
+ if (token !== "") {
2787
+ found.push({
2788
+ entry,
2789
+ name: rename === -1 ? token : token.slice(0, rename),
2790
+ local: rename === -1 ? token : token.slice(rename + RENAME.length)
2791
+ });
2792
+ }
2793
+ }
2794
+ }
2795
+ return found;
2796
+ }
2797
+ function findEntryImports(source) {
2798
+ const spans = literalSpans(source);
2799
+ const found = [];
2800
+ source.replace(IMPORT, (whole, clause, entry, offset) => {
2801
+ if (!isInsideLiteral(spans, offset)) {
2802
+ found.push(...parseClause(clause, entry));
2803
+ }
2804
+ return whole;
2805
+ });
2806
+ return found;
2807
+ }
2808
+ function entryExports(entry) {
2809
+ return NAMES_BY_ENTRY.get(entry);
2810
+ }
2811
+ function ownersOf(name) {
2812
+ return OWNERS.get(name) ?? NO_OWNERS;
2813
+ }
2814
+ function isAwaitableHelper(name) {
2815
+ return AWAITABLE.has(name);
2816
+ }
2817
+ function majorOf(version) {
2818
+ return captures(version, /^(\d+)\./g)[0];
2819
+ }
2820
+ function installedVersion2(cwd) {
2821
+ let directory = cwd;
2822
+ for (; ; ) {
2823
+ const text = readTextFile(join(directory, "node_modules/vitest-auto-spy/package.json"));
2824
+ const parsed = text === void 0 ? void 0 : parseJsonc(text);
2825
+ const version = isRecord(parsed) ? parsed["version"] : void 0;
2826
+ if (typeof version === "string") {
2827
+ return version;
2828
+ }
2829
+ const parent = dirname(directory);
2830
+ if (parent === directory) {
2831
+ return void 0;
2832
+ }
2833
+ directory = parent;
2834
+ }
2835
+ }
2836
+ function tableApplies(cwd) {
2837
+ const installed = installedVersion2(cwd);
2838
+ const theirs = installed === void 0 ? void 0 : majorOf(installed);
2839
+ return theirs === void 0 || theirs === majorOf(EXPORT_MAP_VERSION);
2840
+ }
2841
+
2842
+ // src/cli/checks/helper-entry.ts
2843
+ function candidates(owners, preferred) {
2844
+ return owners.includes(preferred) ? [preferred] : owners;
2845
+ }
2846
+ function findingFor(file, entry, name, owners) {
2847
+ const list = owners.map((owner) => `\`${owner}\``).join(" or ");
2848
+ return {
2849
+ check: "helper-from-wrong-entry",
2850
+ severity: "error",
2851
+ file,
2852
+ message: `Imports \`${name}\` from \`${entry}\`, which does not export it.`,
2853
+ fix: `Change the specifier to ${list}. The entry point decides which mock adapter and which framework wiring the file gets, which is why the name is not re-exported from the root.`
2854
+ };
2855
+ }
2856
+ function checkHelperEntry(profile, graph) {
2857
+ if (!tableApplies(profile.cwd)) {
2858
+ return [];
2859
+ }
2860
+ const findings = [];
2861
+ for (const [file, text] of graph.texts) {
2862
+ for (const { entry, name } of findEntryImports(text)) {
2863
+ const exported = entryExports(entry);
2864
+ const owners = candidates(ownersOf(name), profile.entry);
2865
+ if (exported !== void 0 && !exported.has(name) && owners.length > 0) {
2866
+ findings.push(findingFor(file, entry, name, owners));
2867
+ }
2868
+ }
2869
+ }
2870
+ return findings;
2871
+ }
2356
2872
  var JASMINE_PACKAGES = ["@hirez_io/observer-spy", "@types/jasmine", "jasmine-auto-spies", "jasmine-core"];
2357
2873
  var KARMA_PACKAGE = /^karma/;
2358
2874
  var KARMA_CONFIG = /(^|\/)karma\.conf\.[cm]?[jt]s$/;
@@ -2446,7 +2962,7 @@ function checkOrphanRunnerConfig(profile, graph) {
2446
2962
  }
2447
2963
 
2448
2964
  // src/cli/checks/spec-imports.ts
2449
- function findingFor(importer, imported) {
2965
+ function findingFor2(importer, imported) {
2450
2966
  if (isSpecFile(importer)) {
2451
2967
  return {
2452
2968
  check: "spec-exports-fixture",
@@ -2469,7 +2985,7 @@ function checkSpecImports(graph) {
2469
2985
  for (const [importer, imported] of graph.imports) {
2470
2986
  for (const target of imported) {
2471
2987
  if (isSpecFile(target)) {
2472
- findings.push(findingFor(importer, target));
2988
+ findings.push(findingFor2(importer, target));
2473
2989
  }
2474
2990
  }
2475
2991
  }
@@ -2580,6 +3096,78 @@ function checkTsconfigGlobs(profile) {
2580
3096
  return configs.flatMap((config) => checkOne(profile.cwd, config, profile.files));
2581
3097
  }
2582
3098
 
3099
+ // src/cli/checks/unawaited-helper.ts
3100
+ var QUOTES2 = /* @__PURE__ */ new Set(["'", '"', "`"]);
3101
+ var SPACING = /* @__PURE__ */ new Set([" ", " "]);
3102
+ var STATEMENT_ENDERS = /* @__PURE__ */ new Set(["", ";", "\n", "\r", "}"]);
3103
+ function awaitableLocals(source) {
3104
+ const locals = findEntryImports(source).filter(({ name }) => isAwaitableHelper(name)).map(({ local }) => local);
3105
+ return [...new Set(locals)];
3106
+ }
3107
+ function endOfCall(source, open) {
3108
+ let depth = 0;
3109
+ let index = open;
3110
+ while (index < source.length) {
3111
+ const char = source.charAt(index);
3112
+ if (QUOTES2.has(char)) {
3113
+ index = findStringEnd(source, index);
3114
+ continue;
3115
+ }
3116
+ if (char === "(") {
3117
+ depth += 1;
3118
+ }
3119
+ if (char === ")") {
3120
+ depth -= 1;
3121
+ if (depth === 0) {
3122
+ return index;
3123
+ }
3124
+ }
3125
+ index += 1;
3126
+ }
3127
+ return -1;
3128
+ }
3129
+ function isStatementEnd(source, from) {
3130
+ let index = from;
3131
+ while (SPACING.has(source.charAt(index))) {
3132
+ index += 1;
3133
+ }
3134
+ return STATEMENT_ENDERS.has(source.charAt(index));
3135
+ }
3136
+ function findUnawaitedCalls(source, locals) {
3137
+ if (locals.length === 0) {
3138
+ return [];
3139
+ }
3140
+ const spans = literalSpans(source);
3141
+ const pattern = new RegExp(`(?:^|[;{}])\\s*(${locals.join("|")})\\s*\\(`, "g");
3142
+ const found = [];
3143
+ source.replace(pattern, (whole, local, offset) => {
3144
+ const close = endOfCall(source, offset + whole.length - 1);
3145
+ if (!isInsideLiteral(spans, offset) && close !== -1 && isStatementEnd(source, close + 1)) {
3146
+ found.push(local);
3147
+ }
3148
+ return whole;
3149
+ });
3150
+ return found;
3151
+ }
3152
+ function checkUnawaitedHelper(profile, graph) {
3153
+ if (!tableApplies(profile.cwd)) {
3154
+ return [];
3155
+ }
3156
+ const findings = [];
3157
+ for (const [file, text] of graph.texts) {
3158
+ for (const local of new Set(findUnawaitedCalls(text, awaitableLocals(text)))) {
3159
+ findings.push({
3160
+ check: "no-unawaited-helper",
3161
+ severity: "error",
3162
+ file,
3163
+ message: `Calls \`${local}()\` as a statement and drops the promise it returns.`,
3164
+ fix: "Await it. Unawaited, it settles after the test has already ended, so the assertion inside it can only report into a later test \u2014 or nowhere at all."
3165
+ });
3166
+ }
3167
+ }
3168
+ return findings;
3169
+ }
3170
+
2583
3171
  // src/cli/doctor.ts
2584
3172
  function runDoctor(profile) {
2585
3173
  const graph = buildGraph(profile);
@@ -2591,7 +3179,9 @@ function runDoctor(profile) {
2591
3179
  ...checkAngularBuild(profile),
2592
3180
  ...checkCoverageConfig(profile),
2593
3181
  ...checkAgentInstructions(profile),
2594
- ...checkJasmineEra(profile)
3182
+ ...checkJasmineEra(profile),
3183
+ ...checkHelperEntry(profile, graph),
3184
+ ...checkUnawaitedHelper(profile, graph)
2595
3185
  ];
2596
3186
  }
2597
3187
 
@@ -3132,10 +3722,10 @@ function findDomFreeSpecs(profile, graph) {
3132
3722
  for (const [file, text] of graph.texts) {
3133
3723
  locals.set(file, classify(file, text, known, aliases));
3134
3724
  }
3135
- const candidates = [...graph.texts].filter(([file, text]) => isSpecFile(file) && !DECLARED_ENVIRONMENT.test(text)).map(([file]) => file);
3725
+ const candidates2 = [...graph.texts].filter(([file, text]) => isSpecFile(file) && !DECLARED_ENVIRONMENT.test(text)).map(([file]) => file);
3136
3726
  const setup = profile.setupFiles.map((entry) => entry.replace(/^\.\//, ""));
3137
- const specs = candidates.filter((file) => isClean(file, setup, locals));
3138
- return { specs, undecided: candidates.length - specs.length };
3727
+ const specs = candidates2.filter((file) => isClean(file, setup, locals));
3728
+ return { specs, undecided: candidates2.length - specs.length };
3139
3729
  }
3140
3730
 
3141
3731
  // src/cli/perf-data.ts