vitest-auto-spy 5.15.1 → 5.17.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 +36 -4
- package/README.md +29 -6
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +27 -4
- package/dist/bun-angular.d.ts +1 -1
- package/dist/bun-angular.js +28 -5
- package/dist/bun.d.ts +23 -0
- package/dist/bun.js +1 -1
- package/dist/{chunk-5XLI5JYC.js → chunk-4SJ7EGIY.js} +7 -0
- package/dist/cli.js +4 -1
- package/dist/eslint-plugin.cjs +9 -2
- package/dist/index.js +7 -0
- package/dist/node.cjs +7 -0
- package/dist/node.js +1 -1
- package/dist/react.js +1 -1
- package/dist/rstest.js +1 -1
- package/dist/setup.d.ts +46 -4
- package/dist/setup.js +145 -12
- package/dist/svelte.js +1 -1
- package/dist/{track-signal-runs-C-DgtCj9.d.ts → track-signal-runs-BOfsdYsC.d.ts} +8 -2
- package/dist/vue.js +1 -1
- package/package.json +1 -1
- package/skills/vitest-auto-spy/SKILL.md +95 -92
package/AGENTS.md
CHANGED
|
@@ -1662,6 +1662,28 @@ a `useValue` provider or a test double — patch the prototype of the class the
|
|
|
1662
1662
|
`guardPrototypePollution(reaction)` from `/setup` registers the same check on its own, for a suite
|
|
1663
1663
|
that does not call `setupAutoSpy()`.
|
|
1664
1664
|
|
|
1665
|
+
### Naming the test that left an attribute on `<body>`
|
|
1666
|
+
|
|
1667
|
+
```ts
|
|
1668
|
+
setupAutoSpy({ documentPollution: 'throw' }); // default 'off'; 'throw' under preset: 'strict'
|
|
1669
|
+
setupAutoSpy({ documentPollution: { reaction: 'throw', nodes: true, ignoreAttributes: [/^data-cdk-/], ignoreNodes: 'style' } });
|
|
1670
|
+
```
|
|
1671
|
+
|
|
1672
|
+
Under `isolate: false` every spec file in a worker shares one document. An attribute a component set
|
|
1673
|
+
on `<body>` — `renderer.setAttribute(document.body, 'data-reset-focus', '')` in an `effect` — that
|
|
1674
|
+
nothing took off changes the branch a later file's code takes, so that file fails, only when the two
|
|
1675
|
+
share a worker and never alone. The guard records the attributes of `<html>`, `<head>` and `<body>`
|
|
1676
|
+
before each test and compares them from `onTestFinished` — **after** the TestBed destroyed the
|
|
1677
|
+
fixtures in its own `afterEach`, so what a component removes in `ngOnDestroy` / `DestroyRef.onDestroy`
|
|
1678
|
+
is never reported. Every attribute added, changed or removed is named with both values, put back,
|
|
1679
|
+
and fails that test. A change made in a `beforeAll` and never undone fails the file, checked from a
|
|
1680
|
+
`beforeAll` cleanup after every `afterAll`. `nodes: true` also watches the child elements of `<head>`
|
|
1681
|
+
and `<body>`; it is off by default because a module that injects a stylesheet on first import does
|
|
1682
|
+
so once per worker. Blind spots: a write made while the spec file is imported, and a fixture kept
|
|
1683
|
+
alive by `teardown: { destroyAfterEach: false }` (reported against the test that rendered it).
|
|
1684
|
+
`guardDocumentPollution(option)` from `/setup` registers the same check on its own. Vitest only, like
|
|
1685
|
+
every `/setup` guard — `bun:test`, `node:test` and Rstest have no setup entry to host it.
|
|
1686
|
+
|
|
1665
1687
|
### Failing on console output nothing absorbed
|
|
1666
1688
|
|
|
1667
1689
|
```ts
|
|
@@ -1701,8 +1723,8 @@ frame outside `node_modules`:
|
|
|
1701
1723
|
setupAutoSpy({ preset: 'strict' });
|
|
1702
1724
|
```
|
|
1703
1725
|
|
|
1704
|
-
Sets `duplicateCopies`, `propsOutsideHooks`, `guardGlobals`, `prototypePollution`, `
|
|
1705
|
-
`misconfiguration` to `'throw'`, turns `strayTimers` on, and `strayRejections` on when zone.js is
|
|
1726
|
+
Sets `duplicateCopies`, `propsOutsideHooks`, `guardGlobals`, `prototypePollution`, `documentPollution`,
|
|
1727
|
+
`strayConsole` and `misconfiguration` to `'throw'`, turns `strayTimers` on, and `strayRejections` on when zone.js is
|
|
1706
1728
|
loaded. An option passed alongside still wins. **Not** included: `strict` (strict doubles change what
|
|
1707
1729
|
an unconfigured call returns — a semantic switch, not a grade; the name was taken, hence `preset`) and
|
|
1708
1730
|
`unconfiguredReads`, its read side (survey with `onUnstubbedRead` before turning it on),
|
|
@@ -3189,7 +3211,7 @@ blanket downgrade so those keep their severity; do not copy the two names into a
|
|
|
3189
3211
|
| `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
|
|
3190
3212
|
| `no-private-member-access` | `error` | — | `instance['privateMember']`, `(instance as any).privateMember` (and `as unknown as`, and a decoy type), `vi.spyOn(Object.getPrototypeOf(x), 'm')` → drive the member through the public API. **Type-aware**: silent without `parserOptions.project`, and silent on an index signature |
|
|
3191
3213
|
| `no-dead-schemas` | `error` | — | `schemas` on a testing module with no `declarations` — the schema applies to nothing; the file decides, so a `declarations` in another `configureTestingModule` call silences it |
|
|
3192
|
-
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError
|
|
3214
|
+
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError`, or a silently empty object, while the bundle loads |
|
|
3193
3215
|
| `no-unregistered-inject-spy` | `error` | — | `injectSpy(X)` for a token this file never registered → the real instance, whose spy helpers exist only for the compiler |
|
|
3194
3216
|
| `prefer-render-shallow` | `warn` | suggest | `TestBed.createComponent` in a file that never reads the template → `renderShallow(X)`; 0.24× the per-test cycle at 100 children |
|
|
3195
3217
|
| `prefer-set-inputs` | `warn` | suggest | a run of `fixture.componentRef.setInput('title', v)` on one fixture → `await setInputs(fixture, { title: v })` — the name is resolved against the compiled definition before the first write (an undeclared one is an `NG0303` and no change) and the value is typed. The run collapses into one call and a `detectChanges()` under it goes; offered, not applied, because `stable()` ticks and a zone.js suite answers that with `NG0101` |
|
|
@@ -3281,7 +3303,12 @@ passes: `export const events = [...BaseEvents]` at module scope raises
|
|
|
3281
3303
|
`Spread syntax requires ...iterable[Symbol.iterator] to be a function` when a shared chunk is
|
|
3282
3304
|
evaluated while the binding it re-exports is still `undefined`. Safe under `tsc` and under a
|
|
3283
3305
|
browser's ESM loader, which is why nothing else catches it. A function body and an instance field are
|
|
3284
|
-
not reported (they run later); a `static` field is.
|
|
3306
|
+
not reported (they run later); a `static` field is. An **object** spread is reported through a second
|
|
3307
|
+
message, `noImportTimeSpreadObject`, because that half fails without failing: `[...undefined]` and
|
|
3308
|
+
`f(...undefined)` throw, `{ ...undefined }` is `{}`, so `{ ...ShelfItemTypeEnum, ...Local }` loads
|
|
3309
|
+
clean and every key it meant to copy reads `undefined` for the rest of the run. One message cannot
|
|
3310
|
+
carry both: a reader sent looking for `Spread syntax requires …` in an object spread finds no such
|
|
3311
|
+
error in the log and takes the report for a false positive.
|
|
3285
3312
|
|
|
3286
3313
|
`prefer-as-spy` is the one a migration meets in bulk: a `jest-auto-spies` suite writes
|
|
3287
3314
|
`TestBed.inject(X) as Spy<X>` once per injected double, and that cast fails here with `TS2352`.
|
|
@@ -3454,6 +3481,9 @@ packages, which a subpath export can never be.
|
|
|
3454
3481
|
| `Cannot set base providers because it has already been called` | zone and zoneless spec files sharing one worker | `setupAngularTestEnv({ zoneless, initZone, initZoneless })` (§13) |
|
|
3455
3482
|
| a stub that works in the first test of the file and in no other | installed at `describe` level or in `beforeAll`, then restored away | install it in `beforeEach`, or `installPerTest(() => stub…())` |
|
|
3456
3483
|
| a third-party library failing every other run, no test named | a test sealed a global with `Object.defineProperty` (non-configurable) | `setupAutoSpy({ guardGlobals: 'throw' })` names the file; then `mockValueProp` |
|
|
3484
|
+
| a spec green alone that fails only in a full run, on something it reads off `<body>` / `<html>` (`querySelector('[data-…]')`, a class) | an earlier file in the worker left an attribute on the shared document | `setupAutoSpy({ documentPollution: 'throw' })` (in `preset: 'strict'`) names the test; take the attribute off in `ngOnDestroy` / `DestroyRef.onDestroy` or an `afterEach` |
|
|
3485
|
+
| `A metric with the name … has already been registered` as a failed suite with 0 failed tests, only in a full run | under `@angular/build:unit-test` with `isolate: false` a workspace module can run its module scope once **per spec file**, while an external package such as `prom-client` keeps one default registry per worker | not something a hook can catch — it throws at import. Look the metric up before creating it: `register.getSingleMetric(name) ?? new Histogram({ name, … })`, or give the module its own `new Registry()` |
|
|
3486
|
+
| `NotSupportedError: This name has already been registered in the registry` at import | the same per-spec-file evaluation reaching a module-scope `customElements.define` — the registry belongs to the worker's document | `if (!customElements.get(name)) customElements.define(name, Element)`; a definition cannot be undone, so nothing can sweep it |
|
|
3457
3487
|
| a block of files reported as failed suites with no stack, and zero failing tests | a test left an own enumerable key on `Object.prototype`; `mergeHooks` spreads it and collection dies | `setupAutoSpy()` guards it by default; `prototypePollution` tunes the reaction |
|
|
3458
3488
|
| `expected [ { at: 1, …(5) }, …(8) ] to deeply equal [ { …(6) }, … ]` | one field moved in every element — usually a frozen clock or an id | `expect(diffByField(actual, expected)).toBeUndefined()` |
|
|
3459
3489
|
| a hand-tuned number of turns waiting for a `resource()` to load | a resource needs a change-detection **tick**, not event-loop turns; `flushEventLoopUntil` never ticks and the resource never even issues its request | `flushEffects()`, flush the request, then `await settleResource(r, { label })` |
|
|
@@ -3467,6 +3497,7 @@ packages, which a subpath export can never be.
|
|
|
3467
3497
|
| `setInputs: … declares no input named …` | the key is not an input of that component — a typo, an input renamed since, or one of its own fields | set the names the message lists; a signal the component owns is moved through the signal (§13) |
|
|
3468
3498
|
| `setInputs: X carries no ɵcmp, so there are no inputs to set` | the fixture's `componentType` is not a compiled `@Component` — a `@Directive` or `@Pipe` class, or one Angular never compiled (a barrel import that resolved to `undefined`) | pass a component fixture; a directive takes its inputs through the host element that applies it (`createDirectiveHost`), and for `undefined` import the class from its own file (§13) |
|
|
3469
3499
|
| `TypeError: dependencies is not a function`, from `renderShallow({ keepTemplate: true })` | the compiled `ɵcmp.dependencies` is the flat array AOT emits when no cycle forced a factory, and the trim called it | upgrade — all three shapes (array, factory, `null`) are read; nothing to change in the spec |
|
|
3500
|
+
| `renderShallow(X, { keepTemplate: true }): … declared by an NgModule rather than standalone` | an AOT dependency list: ngtsc flattened an imported `NgModule`'s exported declarations into it, and Angular takes only standalone declarations and `NgModule`s in `imports` | drop `keepTemplate` when the spec reads TypeScript state only, or build the component with `TestBed` directly and keep its compiled scope — the declarations named are not the thing to change |
|
|
3470
3501
|
| `TS2540: Cannot assign to 'X' because it is a read-only property` | a `readonly` field of an object under test | `mockValueProp(obj, 'X', value)` — on a class **getter**, `mockReadonlyProp` |
|
|
3471
3502
|
| `TypeError: Cannot read properties of undefined (reading 'mockReturnValue')` | the member is an **instance field**, not on the prototype — `Router.currentNavigation` since Angular 20 | `provideAutoSpy(Router, { instanceMethodsToSpyOn: ['currentNavigation'] })` (§5) |
|
|
3472
3503
|
| `throwWith` reaching the success branch first, with the previous test's value | the spy's `ReplaySubject(1)` outlived the test that filled it | upgrade; and `resetAutoSpy(spy)` in `beforeEach` when the TestBed is built in `beforeAll` |
|
|
@@ -3558,6 +3589,7 @@ diagnostic and is free to change: print it, never assert on it.
|
|
|
3558
3589
|
| `it('x', (done) => …)` / `beforeEach((done) => …)` | `async` + `await` — Vitest passes a `TestContext`, not `done` |
|
|
3559
3590
|
| `{ ...modelInstance, flag: true }` (drops every getter) | `withOverrides(modelInstance, { flag: true })` |
|
|
3560
3591
|
| `if ('params' in link) … else throw` in every spec | `narrow.byKey(link, 'params')` |
|
|
3592
|
+
| `const x = a?.b; assert.exists(x); … x …` on every optional read | `narrow.defined(a?.b)` — it returns the value, so the narrowing sits in the expression |
|
|
3561
3593
|
| five `asInstance(...)` in one call | `...asInstances(a, b, c, d, e)` |
|
|
3562
3594
|
| `vi.stubGlobal('Image', vi.fn(() => ({ src: '' })))` | `stubConstructor(globalThis, 'Image', () => ({ src: '' }))` |
|
|
3563
3595
|
| `Object.defineProperty(document, 'cookie', { value })` | `mockValueProp(document, 'cookie', value)` |
|
package/README.md
CHANGED
|
@@ -2408,7 +2408,14 @@ it, or `null` for a component that imports nothing — and which one is not deci
|
|
|
2408
2408
|
AOT: JIT always emits the factory, AOT emits the array unless a cycle between two components forces
|
|
2409
2409
|
it to defer the read. All three are handled; calling the array unconditionally was a
|
|
2410
2410
|
`TypeError: dependencies is not a function` on an AOT-compiled component with no cycle in its
|
|
2411
|
-
imports. A child re-exported by an imported `NgModule` still renders
|
|
2411
|
+
imports. A child re-exported by an imported `NgModule` still renders **under JIT**, where the module
|
|
2412
|
+
is in that list and is kept whole. Under AOT it is not: ngtsc resolves the module at compile time and
|
|
2413
|
+
flattens its exported declarations into the list, so a `standalone: false` pipe or directive is what
|
|
2414
|
+
arrives, and Angular takes only standalone declarations and `NgModule`s in `imports`. That scope
|
|
2415
|
+
cannot be rebuilt from what the definition holds, so `renderShallow` refuses it by name instead of
|
|
2416
|
+
letting Angular answer `The "X" pipe … is not standalone` — a message aimed at the pipe's author,
|
|
2417
|
+
about a pipe that is fine and that works under JIT. Drop `keepTemplate` when the spec reads
|
|
2418
|
+
TypeScript state only, or build the component with `TestBed` directly and keep its compiled scope.
|
|
2412
2419
|
Reach for it when the spec reads
|
|
2413
2420
|
something the template creates, and keep `keepChildren` for the handful of children it genuinely
|
|
2414
2421
|
needs resolvable. Full write-up:
|
|
@@ -2882,7 +2889,7 @@ single-purpose utility you can pick up independently — they all ride on the sa
|
|
|
2882
2889
|
| `captureArg<T>()` | core | Take hold of a callback or config the code under test built, instead of describing its shape — assertions only, never `calledWith` |
|
|
2883
2890
|
| `explainSpy(spy, method?)` | `/diagnostics` | Every configured argument list next to every recorded call, each attributed to the config it hit — before anything failed |
|
|
2884
2891
|
| `asInstances(...spies)` | core | `asInstance` for a whole argument list — one edit against one compiler error, not five |
|
|
2885
|
-
| `narrow(value, guard)` / `narrow.byKey` / `narrow.observable`
|
|
2892
|
+
| `narrow(value, guard)` / `narrow.byKey` / `narrow.defined` / `narrow.observable` | core | The branch of a union a test knows it got, failing with the shape the value actually had |
|
|
2886
2893
|
| `withOverrides(model, overrides?)` | core | A fixture from a model instance: its getters read once, as data — a spread drops them |
|
|
2887
2894
|
| `compareTestRuns(a, b, root?)` | core | Whether a migration lost a test — the set of `file::name`, which matching counters cannot answer |
|
|
2888
2895
|
| `provideAutoSpyForToken(TOKEN, overrides?)` | `/angular` | The provider for a dependency behind an `InjectionToken` — no stand-in class to write |
|
|
@@ -2916,6 +2923,7 @@ single-purpose utility you can pick up independently — they all ride on the sa
|
|
|
2916
2923
|
| `withoutStrayTimerTracking(work)` | `/setup` | Run setup work whose timers the stray-timer tracker neither counts nor cancels — jsdom schedules one per Web Storage write |
|
|
2917
2924
|
| `describeStrayTimers()` | `/setup` | Every timer still pending, with its kind, the spec file that scheduled it and the scheduling frames — the list `onStrayTimers` gets |
|
|
2918
2925
|
| `guardPrototypePollution(reaction)` | `/setup` | Name the test that left a key on `Object.prototype` — it stops later files collecting ([details](#test-run-hygiene)) |
|
|
2926
|
+
| `guardDocumentPollution(option)` | `/setup` | Name the test that left an attribute on `<html>` / `<body>`, and put it back ([details](#test-run-hygiene)) |
|
|
2919
2927
|
| `installPerTest(install)` | `/setup` | Re-install a stub before every test of the block — a `describe`-level stub is restored away after the first |
|
|
2920
2928
|
| `setupAngularTestEnv(opts)` | `/angular` | Zone and zoneless spec files in one worker, switching platforms per file |
|
|
2921
2929
|
| `restoreTimerGlobals()` | `/setup` | Put back timer globals that uninstalling the fakes deleted rather than restored |
|
|
@@ -3195,8 +3203,16 @@ not a function` on Node 25, `undefined` on Node 26, under jsdom and happy-dom al
|
|
|
3195
3203
|
console method a test replaced is put back after it, so one file's silence cannot reach the next,
|
|
3196
3204
|
and the library's own warnings count like any other output. `allow: [...]` is the last resort,
|
|
3197
3205
|
for environment noise no spec can reach.
|
|
3198
|
-
13. **
|
|
3199
|
-
`
|
|
3206
|
+
13. **Attributes left on the shared document.** Opt-in, `documentPollution: 'throw'`, and on under
|
|
3207
|
+
`preset: 'strict'`. Under `isolate: false` a worker's spec files share one jsdom document, so a
|
|
3208
|
+
`data-*` attribute or a class a component set on `<body>` and never took off changes what a later
|
|
3209
|
+
file's code sees: `document.querySelector('[data-reset-focus]')` matches, a service returns early,
|
|
3210
|
+
and 34 of 209 tests fail only when the two files share a worker. The guard compares the attributes
|
|
3211
|
+
of `<html>`, `<head>` and `<body>` around every test, puts them back and fails the test that changed
|
|
3212
|
+
them; `{ nodes: true }` watches their child elements too. It looks after the TestBed's own teardown,
|
|
3213
|
+
so what a destroyed component cleans up is never reported.
|
|
3214
|
+
14. **Every guard at its strictest — `preset: 'strict'`.** `duplicateCopies`, `propsOutsideHooks`,
|
|
3215
|
+
`guardGlobals`, `prototypePollution`, `documentPollution`, `strayConsole` and `misconfiguration` to `'throw'`,
|
|
3200
3216
|
`strayTimers` on, `strayRejections` on where zone.js is loaded; an option passed alongside still
|
|
3201
3217
|
wins. Not in it: strict doubles (a semantic switch, not a grade) and `unconfiguredReads`, their read
|
|
3202
3218
|
side, `blockNetwork`, `restoreMocks`,
|
|
@@ -3217,6 +3233,7 @@ not a function` on Node 25, `undefined` on Node 26, under jsdom and happy-dom al
|
|
|
3217
3233
|
| `blockNetwork` | `false` | Close every network channel the environment has — `true`, or a narrowing object |
|
|
3218
3234
|
| `guardGlobals` | `'off'` | Report a test that redefines a global property as non-configurable |
|
|
3219
3235
|
| `prototypePollution` | `'throw'` | Sweep and report an enumerable key a test left on a built-in prototype |
|
|
3236
|
+
| `documentPollution` | `'off'` | Put back and report an attribute a test left on `<html>` / `<head>` / `<body>` — `'warn'`, `'throw'`, or `{ reaction, nodes, ignoreAttributes, ignoreNodes }` |
|
|
3220
3237
|
| `strayConsole` | `'off'` | Fail a test (or a file) whose console output nothing absorbed — `'warn'`, `'throw'`, or `{ reaction, allow }` |
|
|
3221
3238
|
| `misconfiguration` | `'warn'` | `'throw'` fails the library's own misuse reports at the call site, every occurrence |
|
|
3222
3239
|
| `preset` | — | `'strict'` starts every guard above at its strictest grade; explicit options still win |
|
|
@@ -3460,7 +3477,7 @@ export can never be.
|
|
|
3460
3477
|
| `no-inject-before-override` | `error` | — | `TestBed.inject()` / `injectSpy()` / `renderShallow()` in a hook, in a suite that still calls `override*` |
|
|
3461
3478
|
| `no-private-member-access` | `error` | — | `instance['privateMember']`, `(instance as any).privateMember` and `vi.spyOn(Object.getPrototypeOf(x), 'm')` — the three spellings that get past `private`; **type-aware**, and silent without `parserOptions.project` |
|
|
3462
3479
|
| `no-dead-schemas` | `error` | — | `schemas` on a testing module that declares nothing — a charm protecting nobody, and one that starts working the day `declarations` arrive |
|
|
3463
|
-
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError
|
|
3480
|
+
| `no-import-time-spread` | `error` | suggest | `export const x = [...Imported]` at module scope → a `TypeError`, or a silently empty object, while the bundle loads |
|
|
3464
3481
|
| `no-unregistered-inject-spy` | `error` | — | `injectSpy(X)` for a token this file never registered → the real instance, whose spy helpers exist only for the compiler |
|
|
3465
3482
|
| `prefer-render-shallow` | `warn` | suggest | `TestBed.createComponent` in a file that never reads the template → `renderShallow(X)`; 0.24× the per-test cycle at 100 children |
|
|
3466
3483
|
| `prefer-set-inputs` | `warn` | suggest | a run of `fixture.componentRef.setInput('title', v)` on one fixture → `await setInputs(fixture, { title: v })`, which resolves every name against the compiled definition before it writes one — an undeclared name is an `NG0303` on the console and no change at all — and types the value. The suggestion collapses the run, drops a `detectChanges()` under it and makes the callback `async`; it is offered rather than applied, because `stable()` ticks and a zone.js suite can answer that with `NG0101` |
|
|
@@ -3542,7 +3559,12 @@ while a binding it re-exports is still `undefined`, so the spread throws
|
|
|
3542
3559
|
`Spread syntax requires ...iterable[Symbol.iterator] to be a function`. An AST pass found exactly
|
|
3543
3560
|
seven sites in an 8 673-file workspace, which is small enough to flag at the cursor. A function body
|
|
3544
3561
|
and an instance field are deliberately not reported — they run later than the module does — while a
|
|
3545
|
-
`static` field is.
|
|
3562
|
+
`static` field is. An **object** spread of the same binding gets a message of its own,
|
|
3563
|
+
because it fails without failing: `[...undefined]` throws, `{ ...undefined }` is `{}`, so
|
|
3564
|
+
`export const ItemType = { ...ShelfItemTypeEnum, ...Local }` loads clean and every key it meant to
|
|
3565
|
+
copy reads `undefined` for the rest of the run. Told to look for `Spread syntax requires …`, a
|
|
3566
|
+
reader finds no such error and takes the report for a false positive — so the object message opens
|
|
3567
|
+
by saying there is nothing to find.
|
|
3546
3568
|
|
|
3547
3569
|
`no-unregistered-inject-spy` catches `injectSpy(X)` for a token nothing in the file
|
|
3548
3570
|
registered as an auto-spy. What comes back is whatever Angular DI already had — the real service, or
|
|
@@ -3788,6 +3810,7 @@ another, and the next one is in that same file.
|
|
|
3788
3810
|
| `guardStrayConsole(reaction)` / `withoutStrayTimerTracking(work)` _(`/setup`)_ | Fail a test on console output nothing absorbed; keep setup work's timers out of the stray-timer count |
|
|
3789
3811
|
| `describeStrayTimers()` _(`/setup`)_ | Each pending timer with the spec file and frames that scheduled it — for a suite that sweeps by hand |
|
|
3790
3812
|
| `guardPrototypePollution(reaction)` _(`/setup`)_ | Name the test that left a key on `Object.prototype`, before the next file fails to collect |
|
|
3813
|
+
| `guardDocumentPollution(option)` _(`/setup`)_ | Name the test that left an attribute on `<html>` / `<body>`, before a later file takes another branch on it |
|
|
3791
3814
|
| `consoleDebugSpy` … `consoleWarnSpy` _(`/console`)_ | Silent typed spies replacing the global `console` methods on import |
|
|
3792
3815
|
| `installConsoleSpies()` / `resetConsoleSpies()` / `restoreConsole()` | Install / clear / undo the console spies |
|
|
3793
3816
|
| `explainSpy(spy, method?)` _(`/diagnostics`)_ | Every configured argument list next to every recorded call, attributed to the config it hit |
|
package/dist/angular.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { o as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, q as provideAutoSpyForToken, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-
|
|
1
|
+
export { o as AngularTokenProvider, A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, q as provideAutoSpyForToken, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-BOfsdYsC.js';
|
|
2
2
|
import { InjectionToken, Provider, Type, WritableSignal, Signal, ProviderToken, FactoryProvider, AbstractType, Injector, ValueProvider } from '@angular/core';
|
|
3
3
|
import { A as AutoMockConfiguration, D as DeepReadonly } from './expect-emission-CmN9ADyN.js';
|
|
4
4
|
export { C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, s as setEmissionTimeout } from './expect-emission-CmN9ADyN.js';
|
package/dist/angular.js
CHANGED
|
@@ -3306,15 +3306,38 @@ function importsOf(definition2) {
|
|
|
3306
3306
|
function isChildComponent(dependency) {
|
|
3307
3307
|
return Reflect.get(dependency, "\u0275cmp") !== void 0;
|
|
3308
3308
|
}
|
|
3309
|
-
|
|
3309
|
+
var DECLARATION_KEYS = ["\u0275cmp", "\u0275dir", "\u0275pipe"];
|
|
3310
|
+
function refusedInImports(dependency) {
|
|
3311
|
+
if (Reflect.get(dependency, "\u0275mod") !== void 0) {
|
|
3312
|
+
return void 0;
|
|
3313
|
+
}
|
|
3314
|
+
const definition2 = DECLARATION_KEYS.map((key) => Reflect.get(dependency, key)).find((value) => value !== void 0);
|
|
3315
|
+
return definition2 !== void 0 && Reflect.get(definition2, "standalone") !== true ? dependency.name : void 0;
|
|
3316
|
+
}
|
|
3317
|
+
function assertScopeIsImportable(component, kept) {
|
|
3318
|
+
const refused = kept.map(refusedInImports).filter((name) => name !== void 0);
|
|
3319
|
+
if (refused.length === 0) {
|
|
3320
|
+
return;
|
|
3321
|
+
}
|
|
3322
|
+
throw new Error(
|
|
3323
|
+
withDocs(
|
|
3324
|
+
`[vitest-auto-spy] renderShallow(${component.name}, { keepTemplate: true }): ${refused.length} of its template dependencies are declared by an NgModule rather than standalone \u2014 ${refused.join(", ")} \u2014 and Angular takes only standalone declarations and NgModules in \`imports\`.
|
|
3325
|
+
Nothing is wrong with those declarations, and the same call works under JIT. This is an AOT dependency list: ngtsc resolves an imported NgModule at compile time and flattens its exported declarations into the component, so the module that would carry them is not in the list to keep. The scope cannot be rebuilt from what the definition holds.
|
|
3326
|
+
Drop \`keepTemplate\` when the spec reads TypeScript state only \u2014 that is the case \`renderShallow\` is for \u2014 or build ${component.name} with \`TestBed\` directly, which keeps its compiled scope untouched, and hold the cost down by seeding the services its children inject rather than by trimming the template.`,
|
|
3327
|
+
DOCS_LINKS.angular
|
|
3328
|
+
)
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3331
|
+
function keptScope(component, definition2, options) {
|
|
3310
3332
|
const kept = importsOf(definition2).filter((dependency) => !isChildComponent(dependency));
|
|
3311
3333
|
kept.push(...options.keepChildren ?? NOTHING);
|
|
3334
|
+
assertScopeIsImportable(component, kept);
|
|
3312
3335
|
return kept;
|
|
3313
3336
|
}
|
|
3314
|
-
function buildOverride(definition2, options) {
|
|
3337
|
+
function buildOverride(component, definition2, options) {
|
|
3315
3338
|
const override = {};
|
|
3316
3339
|
if (isStandalone3(definition2)) {
|
|
3317
|
-
override.imports = options.keepTemplate ? keptScope(definition2, options) : options.keepChildren ?? NOTHING;
|
|
3340
|
+
override.imports = options.keepTemplate ? keptScope(component, definition2, options) : options.keepChildren ?? NOTHING;
|
|
3318
3341
|
override.schemas = PERMISSIVE_SCHEMAS;
|
|
3319
3342
|
}
|
|
3320
3343
|
if (!options.keepTemplate) {
|
|
@@ -3341,7 +3364,7 @@ function renderShallow(component, options = {}) {
|
|
|
3341
3364
|
// is right to report one, which made these two features of the same package cancel each other out.
|
|
3342
3365
|
...standalone ? {} : { schemas: PERMISSIVE_SCHEMAS }
|
|
3343
3366
|
});
|
|
3344
|
-
TestBed.overrideComponent(component, { set: buildOverride(definition2, options) });
|
|
3367
|
+
TestBed.overrideComponent(component, { set: buildOverride(component, definition2, options) });
|
|
3345
3368
|
options.beforeCreate?.();
|
|
3346
3369
|
const fixture = TestBed.createComponent(component);
|
|
3347
3370
|
applyInputs(fixture, options.inputs);
|
package/dist/bun-angular.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { ArgCaptor, AsInstances, AssertMockedOptions, ConstructorMock, Construct
|
|
|
3
3
|
export { A as AutoMockConfiguration, a as AutoSpyDefaultEntry, C as CallbackSubscribable, E as EmissionObserver, b as EmissionOptions, c as EmissionSource, S as SubscribableLike, d as autoMocked, e as clearAutoSpyDefaults, f as createAutoMock, g as expectCompletion, h as expectEmission, i as expectEmissions, j as expectError, k as expectNoEmission, r as registerAutoSpyDefaults, s as setEmissionTimeout } from './expect-emission-CmN9ADyN.js';
|
|
4
4
|
export { c as createFunctionSpy, d as describeDuplicateCopies, g as getPackageCopies } from './package-identity-lm-gqZAR.js';
|
|
5
5
|
export { A as AccessorImplementations, O as OutsideHookReaction, R as RestoreProp, c as countMockedProps, m as mockAccessorsProp, a as mockReadonlyProp, b as mockReadonlyPropGetter, d as mockValueProp, r as reportPropsOutsideHooks, e as restoreMockedProps } from './prop-mock-DnYNBNJL.js';
|
|
6
|
-
export { A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-
|
|
6
|
+
export { A as AngularValueProvider, a as AutoSpiedInstance, C as ComponentInputs, b as CreateWithAutoSpiesOptions, R as RenderShallowOptions, c as ResourceStatusLike, d as RunCounter, S as SettleResourceOptions, e as ShallowRender, f as SpyRegistry, g as StableOptions, h as createWithAutoSpies, i as flushEffects, j as injectSpy, p as provideAutoSpy, r as renderShallow, k as runEffect, s as setInputs, l as settleResource, m as stable, t as trackEffectRuns, n as trackRecomputations } from './track-signal-runs-BOfsdYsC.js';
|
|
7
7
|
import 'vitest';
|
|
8
8
|
import '@angular/core';
|
|
9
9
|
import '@angular/core/testing';
|
package/dist/bun-angular.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { stable, flushEffects } from './chunk-M5BULP7X.js';
|
|
2
2
|
export { flushEffects, stable } from './chunk-M5BULP7X.js';
|
|
3
3
|
import './chunk-M6VMOOZ2.js';
|
|
4
|
-
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-
|
|
4
|
+
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-4SJ7EGIY.js';
|
|
5
5
|
import { currentSpecFile, mockValueProp } from './chunk-N3T7KWWA.js';
|
|
6
6
|
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-N3T7KWWA.js';
|
|
7
7
|
import { createSpyForToken } from './chunk-DUFMKOKF.js';
|
|
@@ -317,15 +317,38 @@ function importsOf(definition) {
|
|
|
317
317
|
function isChildComponent(dependency) {
|
|
318
318
|
return Reflect.get(dependency, "\u0275cmp") !== void 0;
|
|
319
319
|
}
|
|
320
|
-
|
|
320
|
+
var DECLARATION_KEYS = ["\u0275cmp", "\u0275dir", "\u0275pipe"];
|
|
321
|
+
function refusedInImports(dependency) {
|
|
322
|
+
if (Reflect.get(dependency, "\u0275mod") !== void 0) {
|
|
323
|
+
return void 0;
|
|
324
|
+
}
|
|
325
|
+
const definition = DECLARATION_KEYS.map((key) => Reflect.get(dependency, key)).find((value) => value !== void 0);
|
|
326
|
+
return definition !== void 0 && Reflect.get(definition, "standalone") !== true ? dependency.name : void 0;
|
|
327
|
+
}
|
|
328
|
+
function assertScopeIsImportable(component, kept) {
|
|
329
|
+
const refused = kept.map(refusedInImports).filter((name) => name !== void 0);
|
|
330
|
+
if (refused.length === 0) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
throw new Error(
|
|
334
|
+
withDocs(
|
|
335
|
+
`[vitest-auto-spy] renderShallow(${component.name}, { keepTemplate: true }): ${refused.length} of its template dependencies are declared by an NgModule rather than standalone \u2014 ${refused.join(", ")} \u2014 and Angular takes only standalone declarations and NgModules in \`imports\`.
|
|
336
|
+
Nothing is wrong with those declarations, and the same call works under JIT. This is an AOT dependency list: ngtsc resolves an imported NgModule at compile time and flattens its exported declarations into the component, so the module that would carry them is not in the list to keep. The scope cannot be rebuilt from what the definition holds.
|
|
337
|
+
Drop \`keepTemplate\` when the spec reads TypeScript state only \u2014 that is the case \`renderShallow\` is for \u2014 or build ${component.name} with \`TestBed\` directly, which keeps its compiled scope untouched, and hold the cost down by seeding the services its children inject rather than by trimming the template.`,
|
|
338
|
+
DOCS_LINKS.angular
|
|
339
|
+
)
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
function keptScope(component, definition, options) {
|
|
321
343
|
const kept = importsOf(definition).filter((dependency) => !isChildComponent(dependency));
|
|
322
344
|
kept.push(...options.keepChildren ?? NOTHING);
|
|
345
|
+
assertScopeIsImportable(component, kept);
|
|
323
346
|
return kept;
|
|
324
347
|
}
|
|
325
|
-
function buildOverride(definition, options) {
|
|
348
|
+
function buildOverride(component, definition, options) {
|
|
326
349
|
const override = {};
|
|
327
350
|
if (isStandalone(definition)) {
|
|
328
|
-
override.imports = options.keepTemplate ? keptScope(definition, options) : options.keepChildren ?? NOTHING;
|
|
351
|
+
override.imports = options.keepTemplate ? keptScope(component, definition, options) : options.keepChildren ?? NOTHING;
|
|
329
352
|
override.schemas = PERMISSIVE_SCHEMAS;
|
|
330
353
|
}
|
|
331
354
|
if (!options.keepTemplate) {
|
|
@@ -352,7 +375,7 @@ function renderShallow(component, options = {}) {
|
|
|
352
375
|
// is right to report one, which made these two features of the same package cancel each other out.
|
|
353
376
|
...standalone ? {} : { schemas: PERMISSIVE_SCHEMAS }
|
|
354
377
|
});
|
|
355
|
-
TestBed.overrideComponent(component, { set: buildOverride(definition, options) });
|
|
378
|
+
TestBed.overrideComponent(component, { set: buildOverride(component, definition, options) });
|
|
356
379
|
options.beforeCreate?.();
|
|
357
380
|
const fixture = TestBed.createComponent(component);
|
|
358
381
|
applyInputs(fixture, options.inputs);
|
package/dist/bun.d.ts
CHANGED
|
@@ -551,6 +551,27 @@ type Subscribable<T> = [Extract<T, {
|
|
|
551
551
|
}>] extends [never] ? T : Extract<T, {
|
|
552
552
|
subscribe: Func;
|
|
553
553
|
}>;
|
|
554
|
+
/**
|
|
555
|
+
* The narrowing every optional read needs: neither `null` nor `undefined`, handed back.
|
|
556
|
+
*
|
|
557
|
+
* ```ts
|
|
558
|
+
* const covers = narrow.defined(row.content?.covers);
|
|
559
|
+
*
|
|
560
|
+
* expect(covers.map((cover) => cover.code)).toEqual(['a', 'b']);
|
|
561
|
+
* ```
|
|
562
|
+
*
|
|
563
|
+
* `expect(value).toBeDefined()` and `assert.exists(value)` both assert this, and neither **returns**
|
|
564
|
+
* it — so under a strict spec type-check each optional read costs two statements and a local that
|
|
565
|
+
* exists for the narrowing alone (`const x = obj.member; assert.exists(x); … x …`). That shape
|
|
566
|
+
* multiplies: one suite hit it fifteen times across four files, and twice it grew a helper function
|
|
567
|
+
* per member of a stub. This returns the value, so the narrowing sits inside the expression that
|
|
568
|
+
* needed it.
|
|
569
|
+
*
|
|
570
|
+
* It is not a replacement for `assert.exists` where the *assertion* is the point of the test. The
|
|
571
|
+
* difference is which of the two the line is about: asserting that a value arrived, or reading a
|
|
572
|
+
* value the test already knows arrived.
|
|
573
|
+
*/
|
|
574
|
+
declare function defined<T>(value: T, label?: string): NonNullable<T>;
|
|
554
575
|
/**
|
|
555
576
|
* The most common narrowing, without writing the guard: the branch that has this key.
|
|
556
577
|
*
|
|
@@ -581,6 +602,8 @@ interface Narrow {
|
|
|
581
602
|
<T>(value: T, predicate: (candidate: T) => boolean, label?: string): T;
|
|
582
603
|
/** {@link byKey} */
|
|
583
604
|
byKey: typeof byKey;
|
|
605
|
+
/** {@link defined} */
|
|
606
|
+
defined: typeof defined;
|
|
584
607
|
/** {@link observable} */
|
|
585
608
|
observable: typeof observable;
|
|
586
609
|
}
|
package/dist/bun.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import './chunk-M6VMOOZ2.js';
|
|
2
|
-
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-
|
|
2
|
+
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-4SJ7EGIY.js';
|
|
3
3
|
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-N3T7KWWA.js';
|
|
4
4
|
export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-WAMFS3UI.js';
|
|
5
5
|
import './chunk-OS4PTU6D.js';
|
|
@@ -554,6 +554,12 @@ var narrowValue = defineHelper((value, predicate, label) => {
|
|
|
554
554
|
}
|
|
555
555
|
return value;
|
|
556
556
|
});
|
|
557
|
+
function defined(value, label = "a value that is neither null nor undefined") {
|
|
558
|
+
if (value === null || value === void 0) {
|
|
559
|
+
throw narrowingFailed(label, value);
|
|
560
|
+
}
|
|
561
|
+
return value;
|
|
562
|
+
}
|
|
557
563
|
function byKey(value, key) {
|
|
558
564
|
if (typeof value !== "object" || value === null || !(key in value)) {
|
|
559
565
|
throw narrowingFailed(`an object with a '${String(key)}' property`, value);
|
|
@@ -568,6 +574,7 @@ function observable(value) {
|
|
|
568
574
|
}
|
|
569
575
|
var narrow = Object.assign(narrowValue, {
|
|
570
576
|
byKey: defineHelper(byKey),
|
|
577
|
+
defined: defineHelper(defined),
|
|
571
578
|
observable: defineHelper(observable)
|
|
572
579
|
});
|
|
573
580
|
|
package/dist/cli.js
CHANGED
|
@@ -2455,7 +2455,7 @@ function checkForeignPragma(graph) {
|
|
|
2455
2455
|
}
|
|
2456
2456
|
|
|
2457
2457
|
// src/cli/checks/export-map.generated.ts
|
|
2458
|
-
var EXPORT_MAP_VERSION = "5.
|
|
2458
|
+
var EXPORT_MAP_VERSION = "5.17.0";
|
|
2459
2459
|
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-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";
|
|
2460
2460
|
var EXPORTED_BY = {
|
|
2461
2461
|
AccessorImplementations: "0 1 2 3 4 12 17 18 19",
|
|
@@ -2571,6 +2571,8 @@ var EXPORTED_BY = {
|
|
|
2571
2571
|
DirectiveHostOptions: "12",
|
|
2572
2572
|
disableAngularDiagnostics: "12",
|
|
2573
2573
|
disableTestBedDiagnostics: "12",
|
|
2574
|
+
DocumentPollutionOptions: "20",
|
|
2575
|
+
DocumentPollutionReaction: "20",
|
|
2574
2576
|
DomRegistrar: "2",
|
|
2575
2577
|
DuplicateCopiesReaction: "20",
|
|
2576
2578
|
EmissionObserver: "0 1 2 3 4 12 17 18 19",
|
|
@@ -2612,6 +2614,7 @@ var EXPORTED_BY = {
|
|
|
2612
2614
|
getWatchedTimerGlobals: "20",
|
|
2613
2615
|
GlobalPatchReaction: "20",
|
|
2614
2616
|
GlobalRegistratorOptions: "2",
|
|
2617
|
+
guardDocumentPollution: "20",
|
|
2615
2618
|
guardGlobalPatches: "20",
|
|
2616
2619
|
guardPrototypePollution: "20",
|
|
2617
2620
|
guardStrayConsole: "20",
|
package/dist/eslint-plugin.cjs
CHANGED
|
@@ -779,6 +779,8 @@ var SPY_FACTORIES = /* @__PURE__ */ new Set([
|
|
|
779
779
|
"autoMocked",
|
|
780
780
|
"createActivatedRoute",
|
|
781
781
|
"createAutoMock",
|
|
782
|
+
"createComponentStub",
|
|
783
|
+
"createDirectiveHost",
|
|
782
784
|
"createDocumentDouble",
|
|
783
785
|
"createMock",
|
|
784
786
|
"createRouterDouble",
|
|
@@ -904,6 +906,9 @@ function spreadOfImport(context, node) {
|
|
|
904
906
|
const binding = findBinding(context.sourceCode.getScope(node), argument.name);
|
|
905
907
|
return binding?.defs.some((definition) => definition.type === IMPORT_DEFINITION2) ? argument : void 0;
|
|
906
908
|
}
|
|
909
|
+
function spreadFailureMode(node) {
|
|
910
|
+
return isObjectExpression(node.parent) ? "object" : "iterable";
|
|
911
|
+
}
|
|
907
912
|
function isDeferred(node) {
|
|
908
913
|
return isFunctionNode(node) || node.type === "PropertyDefinition" && Reflect.get(node, "static") !== true;
|
|
909
914
|
}
|
|
@@ -3311,7 +3316,8 @@ var noImportTimeSpread = defineRule({
|
|
|
3311
3316
|
description: "Do not spread an imported binding at module scope \u2014 inside a bundle it can still be undefined",
|
|
3312
3317
|
hasSuggestions: true,
|
|
3313
3318
|
messages: {
|
|
3314
|
-
noImportTimeSpread: "This spreads `{{name}}`, a binding another module owns, while this module is still being evaluated. Under `tsc` and under a browser\u2019s ESM loader that is safe \u2014 nothing runs before its dependency. Inside one bundle it is not: the spec bundle emits shared chunks, a chunk can be evaluated while the binding it re-exports is still `undefined`, and `[...undefined]` throws `Spread syntax requires ...iterable[Symbol.iterator] to be a function` before a single test runs \u2014 on a tree whose every test passes. Build the value lazily (a function, called where it is read), or inline the constant so nothing has to be imported for this line to work. Nothing inside a function body is reported: that runs later, which is the whole repair."
|
|
3319
|
+
noImportTimeSpread: "This spreads `{{name}}`, a binding another module owns, while this module is still being evaluated. Under `tsc` and under a browser\u2019s ESM loader that is safe \u2014 nothing runs before its dependency. Inside one bundle it is not: the spec bundle emits shared chunks, a chunk can be evaluated while the binding it re-exports is still `undefined`, and `[...undefined]` throws `Spread syntax requires ...iterable[Symbol.iterator] to be a function` before a single test runs \u2014 on a tree whose every test passes. Build the value lazily (a function, called where it is read), or inline the constant so nothing has to be imported for this line to work. Nothing inside a function body is reported: that runs later, which is the whole repair.",
|
|
3320
|
+
noImportTimeSpreadObject: "This spreads `{{name}}`, a binding another module owns, into an object literal while this module is still being evaluated. Under `tsc` and under a browser\u2019s ESM loader that is safe \u2014 nothing runs before its dependency. Inside one bundle it is not: the spec bundle emits shared chunks, and a chunk can be evaluated while the binding it re-exports is still `undefined`. Do not look for an error \u2014 an object spread of `undefined` throws nothing, `{ ...undefined }` is `{}`, so the module loads and every key this line was meant to copy reads `undefined` for the rest of the run, on a tree whose every test passes. Build the value lazily (a function, called where it is read), or write the keys out so nothing has to be imported for this line to work. Nothing inside a function body is reported: that runs later, which is the whole repair."
|
|
3315
3321
|
},
|
|
3316
3322
|
create: (context) => ({
|
|
3317
3323
|
SpreadElement: (node) => {
|
|
@@ -3320,7 +3326,8 @@ var noImportTimeSpread = defineRule({
|
|
|
3320
3326
|
return;
|
|
3321
3327
|
}
|
|
3322
3328
|
const suggestion = lazyValueSuggestion(context, node);
|
|
3323
|
-
const
|
|
3329
|
+
const messageId = spreadFailureMode(node) === "object" ? "noImportTimeSpreadObject" : "noImportTimeSpread";
|
|
3330
|
+
const report = { node, messageId, data: { name: imported.name } };
|
|
3324
3331
|
context.report(suggestion ? { ...report, suggest: [suggestion] } : report);
|
|
3325
3332
|
}
|
|
3326
3333
|
})
|
package/dist/index.js
CHANGED
|
@@ -2885,6 +2885,12 @@ var narrowValue = defineHelper((value, predicate, label) => {
|
|
|
2885
2885
|
}
|
|
2886
2886
|
return value;
|
|
2887
2887
|
});
|
|
2888
|
+
function defined(value, label = "a value that is neither null nor undefined") {
|
|
2889
|
+
if (value === null || value === void 0) {
|
|
2890
|
+
throw narrowingFailed(label, value);
|
|
2891
|
+
}
|
|
2892
|
+
return value;
|
|
2893
|
+
}
|
|
2888
2894
|
function byKey(value, key) {
|
|
2889
2895
|
if (typeof value !== "object" || value === null || !(key in value)) {
|
|
2890
2896
|
throw narrowingFailed(`an object with a '${String(key)}' property`, value);
|
|
@@ -2899,6 +2905,7 @@ function observable(value) {
|
|
|
2899
2905
|
}
|
|
2900
2906
|
var narrow = Object.assign(narrowValue, {
|
|
2901
2907
|
byKey: defineHelper(byKey),
|
|
2908
|
+
defined: defineHelper(defined),
|
|
2902
2909
|
observable: defineHelper(observable)
|
|
2903
2910
|
});
|
|
2904
2911
|
|
package/dist/node.cjs
CHANGED
|
@@ -2618,6 +2618,12 @@ var narrowValue = defineHelper((value, predicate, label) => {
|
|
|
2618
2618
|
}
|
|
2619
2619
|
return value;
|
|
2620
2620
|
});
|
|
2621
|
+
function defined(value, label = "a value that is neither null nor undefined") {
|
|
2622
|
+
if (value === null || value === void 0) {
|
|
2623
|
+
throw narrowingFailed(label, value);
|
|
2624
|
+
}
|
|
2625
|
+
return value;
|
|
2626
|
+
}
|
|
2621
2627
|
function byKey(value, key) {
|
|
2622
2628
|
if (typeof value !== "object" || value === null || !(key in value)) {
|
|
2623
2629
|
throw narrowingFailed(`an object with a '${String(key)}' property`, value);
|
|
@@ -2632,6 +2638,7 @@ function observable(value) {
|
|
|
2632
2638
|
}
|
|
2633
2639
|
var narrow = Object.assign(narrowValue, {
|
|
2634
2640
|
byKey: defineHelper(byKey),
|
|
2641
|
+
defined: defineHelper(defined),
|
|
2635
2642
|
observable: defineHelper(observable)
|
|
2636
2643
|
});
|
|
2637
2644
|
|
package/dist/node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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-4SJ7EGIY.js';
|
|
2
2
|
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-N3T7KWWA.js';
|
|
3
3
|
export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-WAMFS3UI.js';
|
|
4
4
|
import './chunk-OS4PTU6D.js';
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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-4SJ7EGIY.js';
|
|
2
2
|
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-N3T7KWWA.js';
|
|
3
3
|
export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-WAMFS3UI.js';
|
|
4
4
|
import './chunk-OS4PTU6D.js';
|
package/dist/rstest.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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-4SJ7EGIY.js';
|
|
2
2
|
export { countMockedProps, mockAccessorsProp, mockReadonlyProp, mockReadonlyPropGetter, mockValueProp, reportPropsOutsideHooks, restoreMockedProps } from './chunk-N3T7KWWA.js';
|
|
3
3
|
export { autoMocked, clearAutoSpy, clearAutoSpyDefaults, createAutoMock, createSpyFromClass, registerAutoSpyDefaults, resetAutoSpy } from './chunk-WAMFS3UI.js';
|
|
4
4
|
import './chunk-OS4PTU6D.js';
|