vitest-auto-spy 5.17.0 → 5.18.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 +14 -4
- package/README.md +40 -7
- package/dist/cli.js +848 -165
- package/dist/perf-profiler.js +54 -0
- package/dist/perf-reporter.js +41 -11
- package/dist/setup.js +7 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1676,7 +1676,10 @@ share a worker and never alone. The guard records the attributes of `<html>`, `<
|
|
|
1676
1676
|
before each test and compares them from `onTestFinished` — **after** the TestBed destroyed the
|
|
1677
1677
|
fixtures in its own `afterEach`, so what a component removes in `ngOnDestroy` / `DestroyRef.onDestroy`
|
|
1678
1678
|
is never reported. Every attribute added, changed or removed is named with both values, put back,
|
|
1679
|
-
and fails that test.
|
|
1679
|
+
and fails that test. An empty `class` or `style` reads as the attribute being absent, in both
|
|
1680
|
+
directions — `classList.add` followed by `remove` leaves `class=""` where there was none and nothing
|
|
1681
|
+
observable changed; any other empty value, `data-reset-focus=""` included, is still reported.
|
|
1682
|
+
A change made in a `beforeAll` and never undone fails the file, checked from a
|
|
1680
1683
|
`beforeAll` cleanup after every `afterAll`. `nodes: true` also watches the child elements of `<head>`
|
|
1681
1684
|
and `<body>`; it is off by default because a module that injects a stylesheet on first import does
|
|
1682
1685
|
so once per worker. Blind spots: a write made while the spec file is imported, and a fixture kept
|
|
@@ -3726,9 +3729,16 @@ files of a confirmation pass go.
|
|
|
3726
3729
|
|
|
3727
3730
|
**`--gate` is the only part of this command that fails anything**, and three rules keep it honest.
|
|
3728
3731
|
It judges the `tests` phase alone, because the other five are the harness and the machine rather than
|
|
3729
|
-
anybody's code. A file is
|
|
3730
|
-
|
|
3731
|
-
and
|
|
3732
|
+
anybody's code. A file budget is counted in the median test **of the same run** — the largest of
|
|
3733
|
+
`--max-file-tests` (2 000) median tests, `--factor` (10) × the median test for each test in the file,
|
|
3734
|
+
and a `--max-file-ms` (5 000) floor that can only spare a file — which is what makes the verdict the
|
|
3735
|
+
same on a loaded CI runner and on an idle laptop, and what keeps a large file of ordinary tests out of
|
|
3736
|
+
it: the rule it replaced, `--factor` × the median **file**, flagged 0 files of a 2 023-file consumer
|
|
3737
|
+
suite at ×1 slowdown and 19 at ×9, a 209-test service spec at 5 ms a test among them. A confirmed finding
|
|
3738
|
+
also says why: the confirmation pass records a CPU profile of each suspect file and every one of its
|
|
3739
|
+
test bodies, and the gate prints the slowest tests, the share in hooks against bodies, and where the
|
|
3740
|
+
time went in the spec, in your code and by package. The report ends in two tables of what is over
|
|
3741
|
+
budget and nothing else. And every candidate is re-measured on its own before it may fail anything: a
|
|
3732
3742
|
file that is fast when it has the machine to itself is reported as _not reproduced_, an `info` rather
|
|
3733
3743
|
than a finding. Without a way to re-measure, findings are warnings that fail nothing unless
|
|
3734
3744
|
`--no-confirm` says one reading is enough. Exit `1` is "over budget", exit `2` is "there was nothing
|
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ faster at suite scale ([benchmarks](#benchmarks)) — and for
|
|
|
70
70
|
- 🪆 NestJS units from their own DI metadata — `createNestUnit(Target, { expose, providers })`, the solitary / sociable model of `@suites/unit` with the real prototype behind every spy and no `@nestjs` dependency
|
|
71
71
|
- 🧱 The providers a testing module cannot reach — `overrideComponentProvider` (which verifies the override actually applied), `provideAutoSpyForToken`, `assertNgModuleScopes`, `assertComponentDefIntact`, `createDirectiveHost`, and `createComponentStub` for a child whose selector and inputs are read off the real one, so the stub cannot drift
|
|
72
72
|
- 🚨 Failures that used to be silence — `enableAngularDiagnostics()` for dead NgModule imports, dead `schemas`, an unspied provider and unflushed HTTP requests; `trackInjections` for which collaborators the code actually asked for. `injectSpy` already warns once per token when DI handed back a real instance, naming the token and the missing `provideAutoSpy` — where Spectator's `inject<T>(token): SpyObject<T>` types **every** token as a spy whether it was mocked or not, so the compiler hides the same mistake
|
|
73
|
+
- 🐢 Which test is slow, and why — [`npx vitest-auto-spy perf --gate`](#perf--where-the-cpu-time-actually-goes) fails CI over a file whose tests each cost many times the median test of the same run, so a laptop and a runner nine times slower agree; it re-measures every suspect on its own first, and a confirmed one comes with a CPU profile card: the slowest tests, hooks against bodies, the time by package and in your own code, and a likely cause. Vitest 5.0 marks a test over a fixed `slowTestThreshold` of 300 ms and says nothing about where the time went
|
|
73
74
|
- 🔒 [Strict doubles](#strict-doubles--fail-on-a-method-nobody-configured) — `strict: true` / `onUnstubbedCall` fail on a method nobody configured, naming the class, the method and the arguments instead of answering `undefined`; `unconfiguredReads` reports the getter and the stream nobody configured once the test is over
|
|
74
75
|
- ♻️ `using spy = createSpyFromClass(X)` — every double carries `[Symbol.dispose]`, so the `afterEach` that only reset one spy can go
|
|
75
76
|
- 📡 Observable assertions that fail on silence — `expectEmission` / `expectEmissions` / `expectNoEmission` / `expectCompletion` / `expectError`, no rxjs required, Angular `output()` included
|
|
@@ -345,7 +346,7 @@ The package ships one executable, with no dependencies and nothing to configure:
|
|
|
345
346
|
|
|
346
347
|
```bash
|
|
347
348
|
npx vitest-auto-spy doctor # read-only. Exits 1 when it finds something
|
|
348
|
-
npx vitest-auto-spy perf # where the suite's CPU time goes. --gate fails a budget
|
|
349
|
+
npx vitest-auto-spy perf # where the suite's CPU time goes. --gate fails a budget and says why
|
|
349
350
|
npx vitest-auto-spy codemod # prints the migration diff. Writes nothing without --write
|
|
350
351
|
npx vitest-auto-spy init # writes the agent instructions pointer
|
|
351
352
|
```
|
|
@@ -462,14 +463,46 @@ cost 2.8 % of wall clock and about 2 GB less on a 16-core machine.
|
|
|
462
463
|
|
|
463
464
|
**`--gate` is the half that may fail a pipeline**, and it is built so that it only ever fails over
|
|
464
465
|
somebody's code. It judges the `tests` phase alone — the other five are the harness and the machine
|
|
465
|
-
— it
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
466
|
+
— it counts a file's budget in the median test **of the same run** (2 000 of them, or 10× that
|
|
467
|
+
median for each test in the file, whichever is larger), so the verdict survives a change of hardware
|
|
468
|
+
and a large file of ordinary tests never fails it, and it re-measures every candidate on its own
|
|
469
|
+
before failing anything. A file that is not slow when it has the machine to itself is reported as
|
|
470
|
+
_not reproduced_ rather than as a defect; one that is gets a card saying why — its slowest tests,
|
|
471
|
+
hooks against bodies, and where the CPU profile says the time went.
|
|
469
472
|
|
|
470
473
|
```bash
|
|
471
|
-
npx vitest-auto-spy perf --
|
|
472
|
-
|
|
474
|
+
npx vitest-auto-spy perf --gate # a plain Vitest suite
|
|
475
|
+
npx vitest-auto-spy perf --command 'npm test -- {paths:--include=}' --gate # a suite behind a script
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
```
|
|
479
|
+
error perf-gate-slow-file libs/player/src/lib/vod/vod.component.spec.ts
|
|
480
|
+
The test bodies in this file add up to 9.20s, over the 5.00s budget (…). Re-measured on its own: 8.70s, still over budget.
|
|
481
|
+
|
|
482
|
+
┌─ measurements ────────────────────────────────────────────────
|
|
483
|
+
│ tests 38 242ms each 20× the median test
|
|
484
|
+
├─ slowest tests ───────────────────────────────────────────────
|
|
485
|
+
│ 527ms focus > moves through the controls
|
|
486
|
+
├─ where the time went · CPU profile, 8.41s sampled ────────────
|
|
487
|
+
│ hooks ███████████░░░░░░░░░ 54% test bodies 46%
|
|
488
|
+
│ by package ██████░░░░░░░░░░░░░░ 28% jsdom
|
|
489
|
+
│ in the spec setUpWith 38% · VodComponent_Template 17% · assertFocus 8%
|
|
490
|
+
├─ likely cause ────────────────────────────────────────────────
|
|
491
|
+
│ Most of the time is set-up that every test repeats: 54% is in hooks — setUpWith alone is 38%.
|
|
492
|
+
└───────────────────────────────────────────────────────────────
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
The profiler behind the card is loaded only for the confirmation pass; an ordinary run never pays
|
|
496
|
+
for it. The whole card, and the rule the budget is counted by, are in
|
|
497
|
+
[the CLI docs](https://asdalexey.github.io/vitest-auto-spy/utilities/cli#the-gate).
|
|
498
|
+
|
|
499
|
+
On an Angular spec the card adds a row of Angular's own costs — TestBed set-up, component creation,
|
|
500
|
+
change detection, JIT compilation, computed styles — and the likely cause reads it first; on Vitest
|
|
501
|
+
4.1+ it also lists the spec's heaviest imports. Three things need no network in CI: `--baseline
|
|
502
|
+
perf-history.jsonl` keeps the last 30 runs in a cache and fails a file only past twice its mean share
|
|
503
|
+
and above every share it was recorded at; `--fail-on-flaky` fails a test that passed only on a retry;
|
|
504
|
+
and `--code-quality <path>`, on `perf` and on `doctor`, writes the findings for the GitLab merge
|
|
505
|
+
request widget.
|
|
473
506
|
|
|
474
507
|
`--command` is also the answer to a bare `vitest run` not being your suite at all: where the suite is
|
|
475
508
|
built by an Angular builder, an Nx target or a script, there is no root config, the defaults sweep up
|