test-inventory 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +70 -0
- package/README.md +4 -1
- package/dist/ast.d.ts +3 -3
- package/dist/ast.js +4 -4
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -5
- package/dist/config-runs.d.ts +97 -0
- package/dist/config-runs.js +784 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.js +652 -0
- package/dist/diagnostics.js +5 -1
- package/dist/extract.d.ts +8 -0
- package/dist/extract.js +6 -0
- package/dist/filter.js +7 -0
- package/dist/frameworks/bindings.d.ts +22 -0
- package/dist/frameworks/bindings.js +19 -9
- package/dist/frameworks/playwright.d.ts +2 -1
- package/dist/frameworks/playwright.js +1 -0
- package/dist/frameworks/vitest.d.ts +2 -1
- package/dist/frameworks/vitest.js +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/inventory.d.ts +2 -2
- package/dist/inventory.js +2 -1
- package/dist/json.js +2 -0
- package/dist/model.d.ts +6 -1
- package/dist/options.d.ts +2 -2
- package/dist/records.d.ts +54 -1
- package/dist/records.js +192 -28
- package/dist/scan-file.d.ts +5 -1
- package/dist/scan-file.js +5 -2
- package/dist/scan-source.js +1 -1
- package/dist/scan.d.ts +2 -1
- package/dist/scan.js +58 -16
- package/dist/types.d.ts +73 -7
- package/dist/values.d.ts +5 -0
- package/dist/values.js +5 -0
- package/dist/vitest-config.d.ts +6 -4
- package/dist/vitest-config.js +32 -28
- package/dist/vitest-defaults.d.ts +6 -0
- package/dist/vitest-defaults.js +16 -0
- package/package.json +10 -8
- package/schema/v1.json +180 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# test-inventory
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#51](https://github.com/Huldoser/test-inventory/pull/51) [`acec7e7`](https://github.com/Huldoser/test-inventory/commit/acec7e7fd9bae8301ba3559c3986264ea35c3056) - Each file record has a new `config` key: the config the file uses, as the runner started at the root would pick it.
|
|
8
|
+
That is the outermost config at or above the file that runs it, and for Vitest `projects` the project that does,
|
|
9
|
+
read from Playwright's `testDir`, `testMatch`, `testIgnore` and `.gitignore` files, and from Vitest's `include`,
|
|
10
|
+
`exclude`, `includeSource`, `typecheck.include` and `benchmark.include` with each version's defaults. Before, the
|
|
11
|
+
nearest config was taken, which is wrong for a root config whose `include` covers packages that have their own
|
|
12
|
+
`vite.config.ts`. A file with tests that no config runs gets the new `file-not-run` warning.
|
|
13
|
+
|
|
14
|
+
The globals check follows the same choice, so a test in a folder project without a config of its own gets Vitest's
|
|
15
|
+
defaults, and a test the root config runs takes the root's `test.globals`. Files named by `benchmark.include` are
|
|
16
|
+
marked `isBenchmark`, in place of the default `*.bench.*` and `*.benchmark.*` names. The config reader now reads
|
|
17
|
+
regular expressions and paths built from `__dirname`, `__filename` or `import.meta` with `path.join()`,
|
|
18
|
+
`path.resolve()`, `path.dirname()`, `fileURLToPath()` and `new URL()`.
|
|
19
|
+
|
|
20
|
+
- [#50](https://github.com/Huldoser/test-inventory/pull/50) [`3e55445`](https://github.com/Huldoser/test-inventory/commit/3e55445d0b195941813368b7beeea239ccf8792f) - The output lists the configs the scanned files use in a new top-level `configs` key, and as `config` lines in JSON
|
|
21
|
+
Lines. A file uses the nearest `playwright.config.*`, `vitest.config.*` or `vite.config.*` in its folder or a folder
|
|
22
|
+
above, up to the root, as the runner started in that folder would. A config is read as code, never run, and `extends`
|
|
23
|
+
lists the files it takes settings from through imports, such as a shared base config.
|
|
24
|
+
|
|
25
|
+
Vitest's globals now come from `test.globals` in the config a file uses, read through `defineConfig()`,
|
|
26
|
+
`mergeConfig()`, spreads, constants and imported base configs. Before, any `globals: true` in a Vitest or Vite config
|
|
27
|
+
in the file's folder or a folder above counted, also one Vitest doesn't read for the file, as in a `vite.config.ts`
|
|
28
|
+
next to a `vitest.config.ts`. So `globals-not-enabled` can now appear where it didn't, and go away where a base config
|
|
29
|
+
turns globals on. A `test.globals` the scan can't work out without running the config, and a config it can't read,
|
|
30
|
+
get the new `config-value-unknown` warning.
|
|
31
|
+
|
|
32
|
+
- [#55](https://github.com/Huldoser/test-inventory/pull/55) [`a714612`](https://github.com/Huldoser/test-inventory/commit/a714612dcaf01eaa40d218bae44e7d27e68dbce6) - Run settings now come also from the config a file uses: Playwright's `timeout`, `retries` and `repeatEach`, and
|
|
33
|
+
Vitest's `testTimeout`, `retry` and `repeats`, where the file sets none. New `timeoutSource`, `retriesSource` and `repeatsSource`
|
|
34
|
+
keys say where each value comes from: `test`, `suite`, `file` or `config`, or `null` when nothing sets it. A test
|
|
35
|
+
takes the settings of the projects that run it, after their `grep`. When those projects disagree, the config sets the
|
|
36
|
+
value under a condition, as in `process.env.CI ? 2 : 0`, or the scan can't work out the projects, the value is `null`
|
|
37
|
+
with its source `config`. For a value under a condition, `timeoutConfigText`, `retriesConfigText` and
|
|
38
|
+
`repeatsConfigText` hold the config's text for it, so `retries: process.env.CI ? 2 : 0` reads as written. Playwright's `fullyParallel` and Vitest's `sequence.concurrent` make tests
|
|
39
|
+
`isParallel` where the file sets no mode, when every project that runs the test sets it.
|
|
40
|
+
|
|
41
|
+
A `.only` in a Playwright file whose config sets `forbidOnly` gets the new `forbidden-only` error, since the run then
|
|
42
|
+
fails before any test runs. When `forbidOnly` depends on a condition, as in `!!process.env.CI`, it is a warning that
|
|
43
|
+
quotes the condition.
|
|
44
|
+
|
|
45
|
+
- [#59](https://github.com/Huldoser/test-inventory/pull/59) [`aeb3eb1`](https://github.com/Huldoser/test-inventory/commit/aeb3eb10896ba79b82fb34e5b3dd08cb601a251d) - Vitest tags the config defines in `test.tags` now apply to the tests that carry them, as Vitest applies them. Their
|
|
46
|
+
`skip`, `todo`, `fails` and `only` are merged with the test's own and those a describe passes down, and Vitest's order,
|
|
47
|
+
`only` over `skip` over `todo`, gives the state, with the new `stateSource` value `config` when a tag sets it. Their
|
|
48
|
+
`concurrent`, `timeout`, `retry`, `repeats` and `meta` set those keys where the test sets none: from Vitest 5 over a
|
|
49
|
+
describe's options, and in Vitest 4.1 under them. The lowest `priority` wins between tags, and a Vitest 5 project's
|
|
50
|
+
own `tags` replace those of the config it extends.
|
|
51
|
+
|
|
52
|
+
A tag the config doesn't define fails the file in Vitest unless `strictTags` is off, also when there is no config, so
|
|
53
|
+
it now gets the new `undefined-tag` error, and the file's tests are `notLoaded`; in a function or under a condition it
|
|
54
|
+
is a warning, as that code may not run. The `config-may-change-state` warning now shows only when
|
|
55
|
+
the scan can't work out the config's tags.
|
|
56
|
+
|
|
57
|
+
- [#54](https://github.com/Huldoser/test-inventory/pull/54) [`c610789`](https://github.com/Huldoser/test-inventory/commit/c61078957ce5150fde089a45a444cf5bef41cfe5) - Each test record has a new `projects` key: the names of the projects that run the test, of the config its file uses.
|
|
58
|
+
For Playwright, those whose `testDir`, `testMatch` and `testIgnore` include the file, less those whose `grep` or
|
|
59
|
+
`grepInvert` leaves the test's title and tags out; for Vitest, those whose files include it, with each browser
|
|
60
|
+
instance as a project, named as Vitest names it, such as `unit (chromium)`. It is `[]` when no project runs the test,
|
|
61
|
+
and `null` without a config or when the scan can't tell. Config records list their projects in `projects`, each with
|
|
62
|
+
its `name`, `testDir` and Playwright's `dependencies`.
|
|
63
|
+
|
|
64
|
+
- [#53](https://github.com/Huldoser/test-inventory/pull/53) [`b9471ec`](https://github.com/Huldoser/test-inventory/commit/b9471ecd36f9f6157c21b013c7fa6cc9584250cd) - Glob patterns are optional, in `scan()` and on the command line: without them, the test files are those the
|
|
65
|
+
Playwright or Vitest configs in the root and the folders below it run, each with the config it uses. A config whose
|
|
66
|
+
files the scan can't work out gets a `config-value-unknown` warning that says to give patterns, and a scan without
|
|
67
|
+
patterns and without a config says so in `no-files-matched`. An empty list of patterns is still an error.
|
|
68
|
+
|
|
69
|
+
### Patch Changes
|
|
70
|
+
|
|
71
|
+
- [#58](https://github.com/Huldoser/test-inventory/pull/58) [`1a34d74`](https://github.com/Huldoser/test-inventory/commit/1a34d74e76faead734afe87c0babc2a23fdbe4b7) - oxc-parser is updated from 0.154.0 to 0.156.0. The scan output doesn't change.
|
|
72
|
+
|
|
3
73
|
## 0.4.1
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ Node.js 22.12 or newer, on Linux, macOS or Windows. Playwright 1.42 or newer, Vi
|
|
|
25
25
|
npx test-inventory "tests/**/*.spec.ts" --framework playwright --output inventory.json
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
Without the glob, the test files are those the Playwright or Vitest configs in the project run.
|
|
29
|
+
|
|
28
30
|
For this spec from a trading app's UI tests, `tests/alerts.spec.ts`:
|
|
29
31
|
|
|
30
32
|
<!-- code: trading-web/tests/alerts.spec.ts -->
|
|
@@ -94,7 +96,8 @@ in Claude Code, Cursor, VS Code and other MCP clients ask it which tests a proje
|
|
|
94
96
|
|
|
95
97
|
## Limits
|
|
96
98
|
|
|
97
|
-
- Config files are
|
|
99
|
+
- Config files are read as code, never run, and only in part: settings computed at run time, as from `process.env`,
|
|
100
|
+
can't be worked out, and settings such as `workers` or `use` are not read.
|
|
98
101
|
- Values imported from other files are not worked out. A tag or title that comes from an import gets a diagnostic
|
|
99
102
|
that names the module. A custom `test` object is followed through as many files as it takes, through relative
|
|
100
103
|
paths, tsconfig path aliases, `#` imports in package.json and workspace packages; one that can't be followed gets
|
package/dist/ast.d.ts
CHANGED
|
@@ -11,10 +11,10 @@ export interface ReturnValue {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* The values a function returns; null when it may return no value, as with `return;` or no `return` at all, and for
|
|
14
|
-
* an async function or a generator, which returns a promise or an iterator whatever its `return` says.
|
|
15
|
-
* function inside it is that function's.
|
|
14
|
+
* an async function or a generator, which returns a promise or an iterator whatever its `return` says. With `awaited`,
|
|
15
|
+
* an async function's values are those its promise resolves to. A `return` in a function inside it is that function's.
|
|
16
16
|
*/
|
|
17
|
-
export declare function returnValues(fn: FunctionNode): ReturnValue[] | null;
|
|
17
|
+
export declare function returnValues(fn: FunctionNode, awaited?: boolean): ReturnValue[] | null;
|
|
18
18
|
export declare function isStringLiteral(node: Node): node is StringLiteral;
|
|
19
19
|
/** `import.meta.vitest`, which in-source Vitest tests read their functions from. */
|
|
20
20
|
export declare function isImportMetaVitest(expression: Expression): boolean;
|
package/dist/ast.js
CHANGED
|
@@ -34,11 +34,11 @@ export function isFunctionNode(node) {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* The values a function returns; null when it may return no value, as with `return;` or no `return` at all, and for
|
|
37
|
-
* an async function or a generator, which returns a promise or an iterator whatever its `return` says.
|
|
38
|
-
* function inside it is that function's.
|
|
37
|
+
* an async function or a generator, which returns a promise or an iterator whatever its `return` says. With `awaited`,
|
|
38
|
+
* an async function's values are those its promise resolves to. A `return` in a function inside it is that function's.
|
|
39
39
|
*/
|
|
40
|
-
export function returnValues(fn) {
|
|
41
|
-
if (fn.async || fn.generator)
|
|
40
|
+
export function returnValues(fn, awaited = false) {
|
|
41
|
+
if ((fn.async && !awaited) || fn.generator)
|
|
42
42
|
return null;
|
|
43
43
|
// Only declarations of overloads have no body.
|
|
44
44
|
const body = fn.body;
|
package/dist/cli.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export interface Io {
|
|
|
4
4
|
stderr: Writable;
|
|
5
5
|
cwd: string;
|
|
6
6
|
}
|
|
7
|
-
export declare const HELP = "Usage: test-inventory
|
|
7
|
+
export declare const HELP = "Usage: test-inventory [glob...] --framework <playwright|vitest> [options]\n\nLists the tests in the matching files as JSON, read from the source code without running them. Without globs, the\ntest files are those the Playwright or Vitest configs in the root and the folders below it run.\n\nOptions:\n --framework <name> playwright or vitest (required)\n --root <dir> project root; paths in the output are relative to it (default: current directory)\n --ignore <glob> leave out matching files; can be repeated (node_modules is always left out)\n --framework-version <x.y.z> apply the rules of this framework version instead of the one in the project\n --comments <mode> comments above tests: all, non-active or none (default: non-active)\n --state <state> keep tests in this state, such as skip or fixme; can be repeated\n --tag <tag> keep tests with this tag, such as @smoke; can be repeated\n --grep <regex> keep tests whose full name matches, ignoring case\n --only keep tests that use .only, or are inside a describe that does\n --without-reason keep tests that don't run and give no reason\n --fields <keys> write only these keys of each test, separated by commas; id is always kept\n --format <format> json or jsonl, one record per line (default: json)\n -o, --output <file> write to a file instead of standard output\n --pretty indent the JSON\n -h, --help show this help\n -v, --version show the version\n\nExit codes: 0 when the scan finishes, even with diagnostics; 2 for invalid arguments, an output that cannot be\nwritten, or a crash. 1 is reserved for a future release.\n\nExamples:\n test-inventory \"tests/**/*.spec.ts\" --framework playwright --output inventory.json\n test-inventory \"tests/**/*.spec.ts\" --framework playwright --state skip --fields fullName,reason\n";
|
|
8
8
|
/** Runs the command line with the given arguments and streams. Resolves to the exit code. */
|
|
9
9
|
export declare function run(argv: string[], io: Io): Promise<number>;
|
package/dist/cli.js
CHANGED
|
@@ -8,9 +8,10 @@ import { writeInventory, writeInventoryLines } from "./json.js";
|
|
|
8
8
|
import { OptionsError } from "./options.js";
|
|
9
9
|
import { scan } from "./scan.js";
|
|
10
10
|
import { toolVersion } from "./version.js";
|
|
11
|
-
export const HELP = `Usage: test-inventory
|
|
11
|
+
export const HELP = `Usage: test-inventory [glob...] --framework <playwright|vitest> [options]
|
|
12
12
|
|
|
13
|
-
Lists the tests in the matching files as JSON, read from the source code without running them.
|
|
13
|
+
Lists the tests in the matching files as JSON, read from the source code without running them. Without globs, the
|
|
14
|
+
test files are those the Playwright or Vitest configs in the root and the folders below it run.
|
|
14
15
|
|
|
15
16
|
Options:
|
|
16
17
|
--framework <name> playwright or vitest (required)
|
|
@@ -129,8 +130,6 @@ export async function run(argv, io) {
|
|
|
129
130
|
io.stdout.write(`${toolVersion}\n`);
|
|
130
131
|
return FINISHED;
|
|
131
132
|
}
|
|
132
|
-
if (positionals.length === 0)
|
|
133
|
-
return fail('give at least one glob pattern for the test files.');
|
|
134
133
|
if (values.framework === undefined)
|
|
135
134
|
return fail('--framework is required: playwright or vitest.');
|
|
136
135
|
const format = values.format ?? 'json';
|
|
@@ -154,7 +153,7 @@ export async function run(argv, io) {
|
|
|
154
153
|
if (fields !== undefined)
|
|
155
154
|
checkFields(fields);
|
|
156
155
|
inventory = await scan({
|
|
157
|
-
patterns: positionals,
|
|
156
|
+
patterns: positionals.length > 0 ? positionals : undefined,
|
|
158
157
|
framework: values.framework,
|
|
159
158
|
root: path.resolve(io.cwd, values.root ?? '.'),
|
|
160
159
|
ignore: values.ignore ?? [],
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type ConfigFile, type Configs, type Setting } from './config.ts';
|
|
2
|
+
import type { FileConfig, VitestTags } from './records.ts';
|
|
3
|
+
import type { Framework, ProjectRecord } from './types.ts';
|
|
4
|
+
/** What makes a file run: as a test, or as a Vitest benchmark, which plain `vitest` doesn't run. */
|
|
5
|
+
type Run = 'test' | 'benchmark';
|
|
6
|
+
/**
|
|
7
|
+
* What the output says of a project: its name, the folder its test files are found from and Playwright's
|
|
8
|
+
* `dependencies`. `grep` is Playwright's filter of its test titles, which start from the path in `grepRoot`.
|
|
9
|
+
*/
|
|
10
|
+
export interface ProjectAbout {
|
|
11
|
+
name: string;
|
|
12
|
+
testDir: string;
|
|
13
|
+
dependencies: string[];
|
|
14
|
+
grep: ((title: string) => boolean) | null;
|
|
15
|
+
grepRoot: string;
|
|
16
|
+
defaults: ProjectDefaults;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The settings a project gives its tests, as written; null when unset. Playwright's `timeout`, `retries`, `repeatEach`
|
|
20
|
+
* and `fullyParallel`; Vitest's `testTimeout`, `retry`, `repeats` and `sequence.concurrent`, and the tags it defines.
|
|
21
|
+
*/
|
|
22
|
+
interface ProjectDefaults {
|
|
23
|
+
timeout: Setting | null;
|
|
24
|
+
retry: Setting | null;
|
|
25
|
+
repeatEach: Setting | null;
|
|
26
|
+
repeats: Setting | null;
|
|
27
|
+
parallel: Setting | null;
|
|
28
|
+
tags: VitestTags | null;
|
|
29
|
+
}
|
|
30
|
+
/** The config a file uses, the settings of its project, and how that config runs it. */
|
|
31
|
+
export interface Placement {
|
|
32
|
+
config: ConfigFile | null;
|
|
33
|
+
settings: Setting | null;
|
|
34
|
+
/** False when no config runs the file; null when there is no config, or one can't tell. */
|
|
35
|
+
runs: Run | false | null;
|
|
36
|
+
/** The projects of the config that run the file, which a Playwright `grep` may narrow per test; null when unknown. */
|
|
37
|
+
projects: ProjectAbout[] | null;
|
|
38
|
+
}
|
|
39
|
+
/** Finds the configs a file is under and decides which one runs it, as the runner started at the root would. */
|
|
40
|
+
export declare class ConfigRuns {
|
|
41
|
+
private readonly configs;
|
|
42
|
+
private readonly framework;
|
|
43
|
+
private readonly version;
|
|
44
|
+
/** Whether the configs find the test files, as in a scan without patterns, rather than the patterns. */
|
|
45
|
+
private readonly findsFiles;
|
|
46
|
+
private readonly projects;
|
|
47
|
+
private readonly ignoreRules;
|
|
48
|
+
private readonly folderStates;
|
|
49
|
+
/** The Vitest configs whose projects are being found, to stop at one whose projects name itself. */
|
|
50
|
+
private readonly expanding;
|
|
51
|
+
constructor(configs: Configs, framework: Framework, version: [number, number] | null, findsFiles: boolean);
|
|
52
|
+
/**
|
|
53
|
+
* The config a file uses, as the runner started at the root would: the outermost config at or above it that runs it,
|
|
54
|
+
* with the project that does; else the outermost one whose files the scan can't work out, reported then; else the
|
|
55
|
+
* nearest config.
|
|
56
|
+
*/
|
|
57
|
+
placementOf(file: string): Placement;
|
|
58
|
+
/** The projects of a config the output lists; null when the scan can't work them out. */
|
|
59
|
+
projectsIn(config: ConfigFile): ProjectRecord[] | null;
|
|
60
|
+
private projectsOf;
|
|
61
|
+
/** Vitest's `retry`: before 4.1, which reads only a count, an object is one the scan can't work out. */
|
|
62
|
+
private vitestRetry;
|
|
63
|
+
/** A project whose files can't be worked out, because of `setting` under `key`: it may run any file. */
|
|
64
|
+
private unknownProject;
|
|
65
|
+
private playwrightProjects;
|
|
66
|
+
/** A Playwright project: its own settings, else the config's, else Playwright's defaults. */
|
|
67
|
+
private playwrightProject;
|
|
68
|
+
/**
|
|
69
|
+
* Whether `.gitignore` files in a project's test folder, and the folders below it on the way to the file, leave the
|
|
70
|
+
* file out, as Playwright reads them.
|
|
71
|
+
*/
|
|
72
|
+
private isGitIgnored;
|
|
73
|
+
/** A folder's status and the rules inside it, worked out once per project folder however many files it holds. */
|
|
74
|
+
private folderState;
|
|
75
|
+
private rulesIn;
|
|
76
|
+
private vitestProjects;
|
|
77
|
+
/** A project written in `test.projects`, which inherits the root config as each version of Vitest decides. */
|
|
78
|
+
private vitestEntry;
|
|
79
|
+
/**
|
|
80
|
+
* The projects of a config file or folder `test.projects` names: the config's own, also the projects it lists in
|
|
81
|
+
* Vitest 5, or a project with Vitest's defaults for a folder without a config.
|
|
82
|
+
*/
|
|
83
|
+
private vitestPath;
|
|
84
|
+
/**
|
|
85
|
+
* A Vitest project: its files are found from `test.dir`, else `test.root` or `root`, else its folder. With browser
|
|
86
|
+
* mode on, each of `browser.instances` is a project of its own, named as Vitest names it.
|
|
87
|
+
*/
|
|
88
|
+
private vitestProject;
|
|
89
|
+
/** The files a Vitest project runs and its settings; `ownTags`, when set, in place of the tags in `settings`. */
|
|
90
|
+
private vitestFiles;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* What the config a file uses gives it: Playwright's `forbidOnly`, read from the top level only, as Playwright reads
|
|
94
|
+
* it, and for each test, the projects that run it and what they set; null without a config.
|
|
95
|
+
*/
|
|
96
|
+
export declare function fileConfig(placement: Placement, framework: Framework, version: [number, number] | null, file: string): FileConfig | null;
|
|
97
|
+
export {};
|