sxy-test-runner 2.4.3 → 2.4.5
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 +77 -14
- package/dist/cli/help.js +32 -11
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.js +3 -23
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.js +1 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/lib/agentReport.d.ts +1 -1
- package/dist/cli/lib/agentReport.js +6 -1
- package/dist/cli/lib/agentReport.js.map +1 -1
- package/dist/cli/lib/defaultConfig.js +1 -0
- package/dist/cli/lib/defaultConfig.js.map +1 -1
- package/dist/cli/lib/exitCodes.d.ts +10 -0
- package/dist/cli/lib/exitCodes.js +27 -0
- package/dist/cli/lib/exitCodes.js.map +1 -0
- package/dist/cli/lib/parseCommandLineArguments.js +13 -1
- package/dist/cli/lib/parseCommandLineArguments.js.map +1 -1
- package/dist/cli/lib/resolveCommand.d.ts +8 -0
- package/dist/cli/lib/resolveCommand.js +50 -0
- package/dist/cli/lib/resolveCommand.js.map +1 -0
- package/dist/cli/lib/runDescribe.d.ts +2 -1
- package/dist/cli/lib/runDescribe.js +5 -2
- package/dist/cli/lib/runDescribe.js.map +1 -1
- package/dist/cli/lib/runDescribeRun.d.ts +2 -1
- package/dist/cli/lib/runDescribeRun.js +8 -2
- package/dist/cli/lib/runDescribeRun.js.map +1 -1
- package/dist/cli/lib/runTest.d.ts +2 -1
- package/dist/cli/lib/runTest.js +6 -2
- package/dist/cli/lib/runTest.js.map +1 -1
- package/dist/cli/lib/runTests.js +19 -4
- package/dist/cli/lib/runTests.js.map +1 -1
- package/dist/cli/lib/stopSignal.d.ts +7 -0
- package/dist/cli/lib/stopSignal.js +10 -0
- package/dist/cli/lib/stopSignal.js.map +1 -0
- package/dist/cli/once.js +40 -14
- package/dist/cli/once.js.map +1 -1
- package/dist/cli/version.d.ts +2 -0
- package/dist/cli/version.js +23 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/watch.js +3 -0
- package/dist/cli/watch.js.map +1 -1
- package/dist/types.d.ts +3 -2
- package/dist/types.js.map +1 -1
- package/package.json +3 -1
- package/readme.md +73 -6
package/AGENTS.md
CHANGED
|
@@ -19,8 +19,34 @@ For introductory human-facing usage, also see `readme.md`.
|
|
|
19
19
|
4. Import only `describe` from `sxy-test-runner`. Obtain `it`, `test`, and local hooks from
|
|
20
20
|
the `describe` callback.
|
|
21
21
|
5. Run `npx sxy-test-runner once` for finite agent or CI work.
|
|
22
|
-
6. Exit codes
|
|
23
|
-
|
|
22
|
+
6. Exit codes for `once`:
|
|
23
|
+
|
|
24
|
+
| code | meaning |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `0` | everything passed |
|
|
27
|
+
| `20` | test errors - a failed assertion, a test file that would not load, or a describe that threw |
|
|
28
|
+
| `21` | no test file matched the `tests` pattern |
|
|
29
|
+
| `22` | test files matched, but `--filter-it`/`--filter-describe` selected nothing in them |
|
|
30
|
+
| `23` | an option was not recognised, or one needing a value was given none |
|
|
31
|
+
| `24` | reserved for a failure in the runner itself - not currently emitted |
|
|
32
|
+
|
|
33
|
+
**These start at 20 deliberately.** Node reserves 1-14 for its own fatal conditions - `1`
|
|
34
|
+
uncaught exception, `2` unused because Bash claims it for builtin misuse, `3`/`4` internal
|
|
35
|
+
parse and evaluation failures, `5` a fatal V8 error, `9` invalid argument, and so on - while
|
|
36
|
+
anything over 128 is a signal exit, and the shell takes 126 and 127. A runner code inside
|
|
37
|
+
that range cannot be told apart from Node itself dying. Above 14 and below 126, every
|
|
38
|
+
non-zero code is unambiguously the runner's own.
|
|
39
|
+
|
|
40
|
+
`--help` (`-h`) and `--version` (`-v`) work on any command and take over from it, so
|
|
41
|
+
`once --help` describes `once` rather than running the suite. Both exit `0`.
|
|
42
|
+
|
|
43
|
+
An unrecognised option exits before anything runs, rather than warning and carrying on -
|
|
44
|
+
otherwise a typo like `--fitler-it` quietly runs the whole suite and reports a pass. Every
|
|
45
|
+
unrecognised option is listed at once, with a suggestion where the intent is obvious. Options
|
|
46
|
+
are per-command, so `watch --fail-fast` and `once --status-file` are usage errors too.
|
|
47
|
+
|
|
48
|
+
These are process exit codes, and are **not** the status codes used by `--status-file` and
|
|
49
|
+
`--agent`, which are a separate, smaller scheme. Read the exit code from the process.
|
|
24
50
|
|
|
25
51
|
Do not run a test file directly with `node`. `describe()` requires runner-owned global
|
|
26
52
|
state and deliberately throws if the framework has not initialized it.
|
|
@@ -85,6 +111,9 @@ npx sxy-test-runner once --filter-describe "users"
|
|
|
85
111
|
# Run tests whose names contain "creates a user"
|
|
86
112
|
npx sxy-test-runner once --filter-it "creates a user"
|
|
87
113
|
|
|
114
|
+
# Stop at the first failure instead of running the whole suite
|
|
115
|
+
npx sxy-test-runner once --fail-fast
|
|
116
|
+
|
|
88
117
|
# Watch mode, reporting each run as single agent readable lines
|
|
89
118
|
npx sxy-test-runner watch --agent
|
|
90
119
|
|
|
@@ -101,8 +130,8 @@ configured pattern. Both options are resolved relative to `testsBase` and can be
|
|
|
101
130
|
|
|
102
131
|
`--filter-describe` and `--filter-it` apply case-insensitive substring filters to describe
|
|
103
132
|
and test names. They work in both watch and `once` modes and can be combined. If the
|
|
104
|
-
filters select no runnable tests, `once` exits
|
|
105
|
-
|
|
133
|
+
filters select no runnable tests, `once` exits `22` - `21` means no test file matched the
|
|
134
|
+
`tests` pattern in the first place.
|
|
106
135
|
|
|
107
136
|
`--agent` and `--status-file` are watch-only, and are the two ways to follow a watch session
|
|
108
137
|
from outside it: `--agent` streams each run to stdout as single lines, `--status-file` writes
|
|
@@ -116,6 +145,29 @@ describes or tests afterward can therefore be much slower than file filtering. P
|
|
|
116
145
|
`--filter` when a file glob can narrow the run, then use `--filter-describe` or
|
|
117
146
|
`--filter-it` only for further narrowing inside those files.
|
|
118
147
|
|
|
148
|
+
`--fail-fast` (`-x`) stops the run at the first failure - whether that is a failing test, a
|
|
149
|
+
describe that threw, or a test file that would not load. It is a `once` flag with no config
|
|
150
|
+
equivalent: it describes a single invocation rather than a project, and in watch mode it
|
|
151
|
+
would silently truncate runs that report themselves as having covered everything.
|
|
152
|
+
The failure is reported in full, then nothing further starts: not the rest of the describe,
|
|
153
|
+
the file, or the remaining files. Hooks still unwind normally, so `afterEachTest`,
|
|
154
|
+
`afterEachDescribe`, `afterEachFile` and `teardown` all run for whatever had started.
|
|
155
|
+
|
|
156
|
+
Because the run is cut short, the tallies count only what ran - a suite of 500 tests can
|
|
157
|
+
report `Tests: 0/1`. The summary therefore ends with `stopped at the first failure
|
|
158
|
+
(failFast)`, and the status file's description gains `, stopped at the first failure`. Read
|
|
159
|
+
those before treating a tally as the size of the suite. The exit code is unchanged: `20` for
|
|
160
|
+
a test failure, so CI still fails the job.
|
|
161
|
+
|
|
162
|
+
Under parallel execution it is best-effort: work already in flight finishes, so more than
|
|
163
|
+
one failure can be reported. Sequential execution - the default - stops exactly at the
|
|
164
|
+
first.
|
|
165
|
+
|
|
166
|
+
CI usually wants this **off**, which is the default. A CI run is not interactive, so seeing
|
|
167
|
+
every failure in one round beats fixing one, pushing, and waiting again. It earns its place
|
|
168
|
+
on a slow suite where the first failure is enough to know the build is dead, or in a local
|
|
169
|
+
edit-test loop.
|
|
170
|
+
|
|
119
171
|
Test discovery uses Node's built-in glob implementation. Patterns are resolved relative to
|
|
120
172
|
`testsBase`, and ignore patterns are resolved from that same base.
|
|
121
173
|
|
|
@@ -324,20 +376,22 @@ ever sees a complete status.
|
|
|
324
376
|
|
|
325
377
|
### Following a watch session as an agent
|
|
326
378
|
|
|
327
|
-
`--agent` (or `watch.agent` in the config
|
|
328
|
-
per event, for an agent reading the process's stdout rather than a terminal. It
|
|
329
|
-
|
|
330
|
-
|
|
379
|
+
`--agent` (or `watch.agent` in the config, for watch mode) replaces the usual output with
|
|
380
|
+
one line per event, for an agent reading the process's stdout rather than a terminal. It
|
|
381
|
+
works in both modes. In `once` it leaves only the failures and the summary - no per-test
|
|
382
|
+
listing - and the process still exits on its usual code, so `once --agent` is both readable
|
|
383
|
+
and CI-safe. In `once` the flag is the only source: a config setting `watch.agent` is
|
|
384
|
+
ignored there, so the output format cannot change out from under a caller.
|
|
331
385
|
|
|
332
386
|
```
|
|
333
387
|
[sxyt] init | pid=16744
|
|
334
388
|
[sxyt] found | files=2
|
|
335
|
-
[sxyt]
|
|
389
|
+
[sxyt] running | n=1 | files=2 | why=startup | covers=all
|
|
336
390
|
[sxyt] fail | n=1 | file=tests/users.test.js | describe=creating a user | test=rejects a duplicate email | error=AssertionError: expected 409 to equal 200
|
|
337
391
|
[sxyt] done | n=1 | code=1 | desc=1 test failed | tests=2/3 | items=1/2 | files=1/2 | failing=1 | ms=150
|
|
338
392
|
[sxyt] watching | files=2
|
|
339
393
|
[sxyt] change | file=src/orders.js | event=update
|
|
340
|
-
[sxyt]
|
|
394
|
+
[sxyt] running | n=2 | files=2 | why=auto | covers=changed+failing
|
|
341
395
|
[sxyt] fail | n=2 | file=tests/users.test.js | describe=creating a user | test=rejects a duplicate email | error=AssertionError: expected 409 to equal 200
|
|
342
396
|
[sxyt] done | n=2 | code=1 | desc=1 test failed | tests=2/3 | items=1/2 | files=1/2 | failing=1 | ms=169
|
|
343
397
|
```
|
|
@@ -350,7 +404,7 @@ is always exactly one line and a field boundary is always a real one.
|
|
|
350
404
|
| --- | --- |
|
|
351
405
|
| `init` | the process is up, before the config is read - proof it started at all |
|
|
352
406
|
| `found` | test discovery finished |
|
|
353
|
-
| `
|
|
407
|
+
| `running` | tests have started running. `why` is `once`, `startup`, `auto` (a file changed), or `all`/`last`/`failed` from a keyboard command |
|
|
354
408
|
| `fail` | one failure. `describe` is absent when a file would not load, `test` when the describe itself threw |
|
|
355
409
|
| `done` | the run finished |
|
|
356
410
|
| `change` | a watched file changed |
|
|
@@ -362,12 +416,13 @@ complete end-of-run marker: wait for it and everything about that run has alread
|
|
|
362
416
|
`code` on `done` is the same status code the status file uses, so `0` is a pass and `2`
|
|
363
417
|
still means the run died partway rather than merely failing.
|
|
364
418
|
|
|
365
|
-
`covers` on the `
|
|
419
|
+
`covers` on the `running` line says what the run was built from, and so how far its result
|
|
366
420
|
generalises:
|
|
367
421
|
|
|
368
422
|
| covers | the run contained |
|
|
369
423
|
| --- | --- |
|
|
370
|
-
| `all` | every discovered test file - the startup run, `a` from the keyboard, or any change when `watch.dependencyEvaluation` is off |
|
|
424
|
+
| `all` | every discovered test file - a `once` run, the watch startup run, `a` from the keyboard, or any change when `watch.dependencyEvaluation` is off |
|
|
425
|
+
| `until-first-failure` | the run is set up to stop early (`--fail-fast`), so it can only speak for what it reached |
|
|
371
426
|
| `changed+failing` | the changed files and every file still failing (`watch.reRunFailingTests` on, the default) |
|
|
372
427
|
| `changed` | only the changed files (`watch.reRunFailingTests` off) |
|
|
373
428
|
| `last` | the previous run's file set |
|
|
@@ -401,7 +456,15 @@ Widening `watch.watchFiles` (for example to `**/*.{js,json,env}`) closes the fir
|
|
|
401
456
|
it matters, at the cost of more reruns.
|
|
402
457
|
|
|
403
458
|
Diffs, logs and stack traces are not in the agent stream; errors are reduced to one line.
|
|
404
|
-
|
|
459
|
+
|
|
460
|
+
In `once`, `code` on the `done` line is the status code above, **not** the process exit
|
|
461
|
+
code - `code=1` accompanies exit `20`. Read the process's exit code for pass/fail; read the
|
|
462
|
+
line for the detail. `watching` and `change` never appear, since there is no watcher.
|
|
463
|
+
|
|
464
|
+
```sh
|
|
465
|
+
# a finite, agent readable run: failures and a summary, exit code preserved
|
|
466
|
+
npx sxy-test-runner once --agent
|
|
467
|
+
```
|
|
405
468
|
|
|
406
469
|
## Configuration reference
|
|
407
470
|
|
package/dist/cli/help.js
CHANGED
|
@@ -18,19 +18,30 @@ export function help() {
|
|
|
18
18
|
` ${cliName} help`,
|
|
19
19
|
'',
|
|
20
20
|
'Commands:',
|
|
21
|
-
' watch
|
|
22
|
-
' once
|
|
23
|
-
' init
|
|
24
|
-
' help
|
|
25
|
-
'',
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
' -
|
|
29
|
-
' -
|
|
21
|
+
' watch Run tests and watch for related file changes (default)',
|
|
22
|
+
' once Run the test suite once and exit',
|
|
23
|
+
' init Create an initial configuration file',
|
|
24
|
+
' help Show this help',
|
|
25
|
+
' version Show the installed version',
|
|
26
|
+
'',
|
|
27
|
+
'Options for watch and once:',
|
|
28
|
+
' -c, --config <file> Use a specific configuration file',
|
|
29
|
+
' -t, --test-files <glob> Override the configured test pattern',
|
|
30
|
+
' -f, --filter <glob> Further constrain the configured test pattern',
|
|
30
31
|
' -d, --filter-describe <substring> Run matching describe blocks',
|
|
31
32
|
' -i, --filter-it <substring> Run matching tests',
|
|
32
|
-
'
|
|
33
|
-
'
|
|
33
|
+
' --agent Report the run as single agent readable lines',
|
|
34
|
+
' -h, --help Show this help instead of running',
|
|
35
|
+
' -v, --version Show the installed version instead of running',
|
|
36
|
+
'',
|
|
37
|
+
'Options for once only:',
|
|
38
|
+
' -x, --fail-fast Stop at the first failure',
|
|
39
|
+
'',
|
|
40
|
+
'Options for watch only:',
|
|
41
|
+
' -s, --status-file <file> Write each run\'s result to a file',
|
|
42
|
+
'',
|
|
43
|
+
'An option not listed for the command it is given to is an error: the command exits',
|
|
44
|
+
'without running anything, rather than ignoring it.',
|
|
34
45
|
'',
|
|
35
46
|
'Watch controls:',
|
|
36
47
|
' r/l + Enter Re-run the last set of tests',
|
|
@@ -38,11 +49,21 @@ export function help() {
|
|
|
38
49
|
' f + Enter Re-run failing tests',
|
|
39
50
|
' Set watch.ttyActionsOnKeypress to true to run these without Enter',
|
|
40
51
|
'',
|
|
52
|
+
'Exit codes for once:',
|
|
53
|
+
' 0 Everything passed',
|
|
54
|
+
' 20 Test errors - a failed assertion, a file that would not load, a describe that threw',
|
|
55
|
+
' 21 No test file matched the tests pattern',
|
|
56
|
+
' 22 Test files matched, but the name filters selected nothing in them',
|
|
57
|
+
' 23 An option was not recognised',
|
|
58
|
+
'',
|
|
41
59
|
'Examples:',
|
|
42
60
|
` ${cliName}`,
|
|
43
61
|
` ${cliName} once`,
|
|
44
62
|
` ${cliName} watch --test-files "**/*.focused.test.js"`,
|
|
45
63
|
` ${cliName} once --filter "**/users/**"`,
|
|
64
|
+
` ${cliName} once --fail-fast`,
|
|
65
|
+
` ${cliName} once --agent`,
|
|
66
|
+
` ${cliName} watch --status-file .sxyt-status`,
|
|
46
67
|
` ${cliName} once --config config/sxyt.config.js`,
|
|
47
68
|
'',
|
|
48
69
|
`Configuration: ${configNames} in ${configDirectories}.`,
|
package/dist/cli/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,sBAAsB,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAElC,MAAM,UAAU,IAAI;IAChB,MAAM,WAAW,GAAG,eAAe;SAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,eAAe,CAAC;SACnC,IAAI,CAAC,MAAM,CAAC,CAAA;IACjB,MAAM,iBAAiB,GAAG,eAAe;SACpC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;SACtE,IAAI,CAAC,MAAM,CAAC,CAAA;IAEjB,GAAG,CAAC;QACA,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;QAC7B,EAAE;QACF,QAAQ;QACR,KAAK,OAAO,oBAAoB;QAChC,KAAK,OAAO,iBAAiB;QAC7B,KAAK,OAAO,OAAO;QACnB,KAAK,OAAO,OAAO;QACnB,EAAE;QACF,WAAW;QACX,
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,sBAAsB,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAElC,MAAM,UAAU,IAAI;IAChB,MAAM,WAAW,GAAG,eAAe;SAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,eAAe,CAAC;SACnC,IAAI,CAAC,MAAM,CAAC,CAAA;IACjB,MAAM,iBAAiB,GAAG,eAAe;SACpC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;SACtE,IAAI,CAAC,MAAM,CAAC,CAAA;IAEjB,GAAG,CAAC;QACA,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;QAC7B,EAAE;QACF,QAAQ;QACR,KAAK,OAAO,oBAAoB;QAChC,KAAK,OAAO,iBAAiB;QAC7B,KAAK,OAAO,OAAO;QACnB,KAAK,OAAO,OAAO;QACnB,EAAE;QACF,WAAW;QACX,kEAAkE;QAClE,4CAA4C;QAC5C,gDAAgD;QAChD,0BAA0B;QAC1B,sCAAsC;QACtC,EAAE;QACF,6BAA6B;QAC7B,wEAAwE;QACxE,2EAA2E;QAC3E,oFAAoF;QACpF,mEAAmE;QACnE,yDAAyD;QACzD,oFAAoF;QACpF,wEAAwE;QACxE,oFAAoF;QACpF,EAAE;QACF,wBAAwB;QACxB,gEAAgE;QAChE,EAAE;QACF,yBAAyB;QACzB,yEAAyE;QACzE,EAAE;QACF,oFAAoF;QACpF,oDAAoD;QACpD,EAAE;QACF,iBAAiB;QACjB,sDAAsD;QACtD,0CAA0C;QAC1C,8CAA8C;QAC9C,qEAAqE;QACrE,EAAE;QACF,sBAAsB;QACtB,yBAAyB;QACzB,2FAA2F;QAC3F,8CAA8C;QAC9C,yEAAyE;QACzE,oCAAoC;QACpC,EAAE;QACF,WAAW;QACX,KAAK,OAAO,EAAE;QACd,KAAK,OAAO,OAAO;QACnB,KAAK,OAAO,4CAA4C;QACxD,KAAK,OAAO,8BAA8B;QAC1C,KAAK,OAAO,mBAAmB;QAC/B,KAAK,OAAO,eAAe;QAC3B,KAAK,OAAO,mCAAmC;QAC/C,KAAK,OAAO,sCAAsC;QAClD,EAAE;QACF,kBAAkB,WAAW,OAAO,iBAAiB,GAAG;QACxD,uBAAuB,OAAO,eAAe,WAAW,GAAG;KAC9D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AACjB,CAAC","sourcesContent":["import chalk from '../packages/chalk.js'\nimport { packageName, cliName, configFileNames, configLocations } from '../config.js'\nimport { out } from '../output.js'\n\nexport function help(): void {\n const configNames = configFileNames\n .map(name => `${name}.{js,cjs,mjs}`)\n .join(' or ')\n const configDirectories = configLocations\n .map(location => location === '' ? 'the project root' : `${location}/`)\n .join(' or ')\n\n out([\n chalk.brightblue(packageName),\n '',\n 'Usage:',\n ` ${cliName} [watch] [options]`,\n ` ${cliName} once [options]`,\n ` ${cliName} init`,\n ` ${cliName} help`,\n '',\n 'Commands:',\n ' watch Run tests and watch for related file changes (default)',\n ' once Run the test suite once and exit',\n ' init Create an initial configuration file',\n ' help Show this help',\n ' version Show the installed version',\n '',\n 'Options for watch and once:',\n ' -c, --config <file> Use a specific configuration file',\n ' -t, --test-files <glob> Override the configured test pattern',\n ' -f, --filter <glob> Further constrain the configured test pattern',\n ' -d, --filter-describe <substring> Run matching describe blocks',\n ' -i, --filter-it <substring> Run matching tests',\n ' --agent Report the run as single agent readable lines',\n ' -h, --help Show this help instead of running',\n ' -v, --version Show the installed version instead of running',\n '',\n 'Options for once only:',\n ' -x, --fail-fast Stop at the first failure',\n '',\n 'Options for watch only:',\n ' -s, --status-file <file> Write each run\\'s result to a file',\n '',\n 'An option not listed for the command it is given to is an error: the command exits',\n 'without running anything, rather than ignoring it.',\n '',\n 'Watch controls:',\n ' r/l + Enter Re-run the last set of tests',\n ' a + Enter Re-run all tests',\n ' f + Enter Re-run failing tests',\n ' Set watch.ttyActionsOnKeypress to true to run these without Enter',\n '',\n 'Exit codes for once:',\n ' 0 Everything passed',\n ' 20 Test errors - a failed assertion, a file that would not load, a describe that threw',\n ' 21 No test file matched the tests pattern',\n ' 22 Test files matched, but the name filters selected nothing in them',\n ' 23 An option was not recognised',\n '',\n 'Examples:',\n ` ${cliName}`,\n ` ${cliName} once`,\n ` ${cliName} watch --test-files \"**/*.focused.test.js\"`,\n ` ${cliName} once --filter \"**/users/**\"`,\n ` ${cliName} once --fail-fast`,\n ` ${cliName} once --agent`,\n ` ${cliName} watch --status-file .sxyt-status`,\n ` ${cliName} once --config config/sxyt.config.js`,\n '',\n `Configuration: ${configNames} in ${configDirectories}.`,\n `Executable aliases: ${cliName}, sxy-test, ${packageName}.`\n ].join('\\n'))\n}\n"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,27 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
switch (command) { // eslint-disable-line @typescript-eslint/switch-exhaustiveness-check
|
|
6
|
-
case 'init':
|
|
7
|
-
case 'once':
|
|
8
|
-
case 'watch':
|
|
9
|
-
case 'help':
|
|
10
|
-
await doCommand(command, args.slice(1));
|
|
11
|
-
break;
|
|
12
|
-
case '--init':
|
|
13
|
-
case '--once':
|
|
14
|
-
case '--watch':
|
|
15
|
-
case '--help':
|
|
16
|
-
await doCommand(command.substring(2), args.slice(1));
|
|
17
|
-
break;
|
|
18
|
-
default:
|
|
19
|
-
await doCommand('watch', args);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
await doCommand('watch', args);
|
|
24
|
-
}
|
|
2
|
+
const { resolveCommand } = await import('./lib/resolveCommand.js');
|
|
3
|
+
const { command, commandArgs } = resolveCommand(process.argv.slice(2));
|
|
4
|
+
await doCommand(command, commandArgs);
|
|
25
5
|
async function doCommand(command, args) {
|
|
26
6
|
global.__sxyt_commandLineArguments = args;
|
|
27
7
|
// command-named dynamic import - no static type can express "a module matching an unknown command string"
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;AAElE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAEtE,MAAM,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;AAErC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,IAAc;IACpD,MAAM,CAAC,2BAA2B,GAAG,IAAI,CAAA;IACzC,0GAA0G;IAC1G,mEAAmE;IACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,OAAO,KAAK,CAAC,CAAA;IAC9C,yGAAyG;IACzG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;IACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC","sourcesContent":["#!/usr/bin/env node\n\nconst { resolveCommand } = await import('./lib/resolveCommand.js')\n\nconst { command, commandArgs } = resolveCommand(process.argv.slice(2))\n\nawait doCommand(command, commandArgs)\n\nasync function doCommand(command: string, args: string[]): Promise<void> {\n global.__sxyt_commandLineArguments = args\n // command-named dynamic import - no static type can express \"a module matching an unknown command string\"\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const module = await import(`./${command}.js`)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n await module[command]()\n process.exit(0)\n}\n"]}
|
package/dist/cli/init.js
CHANGED
|
@@ -64,6 +64,7 @@ export default {
|
|
|
64
64
|
// whether to show the full error trace when an error occurs in a test file
|
|
65
65
|
showErrorTrace: false,
|
|
66
66
|
|
|
67
|
+
|
|
67
68
|
// tasks to run on startup
|
|
68
69
|
// accepts a function, file location (relative to project base), or array of functions and or files
|
|
69
70
|
setup: undefined,
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,MAAM,sBAAsB,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAClC,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,UAAU,IAAI;IAChB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IAEhC,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC3C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;YAC3C,IAAI,GAAG,CAAA;YACP,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,KAAK,CAAC,CAAA;YAC9D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;YACD,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,MAAM,CAAC,CAAA;YAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;YACD,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,MAAM,CAAC,CAAA;YAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;QACL,CAAC;IACL,CAAC;IAED,SAAS,mBAAmB,CAAC,GAAW;QACpC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAA,IAAI,WAAW,yCAAyC,GAAG,EAAE;cACvE,kEAAkE,OAAO,SAAS,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,0BAA0B,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IACnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAA,IAAI,WAAW,2CAA2C;cACpE,gEAAgE;cAChE,iFAAiF,CAAC,CAAA;IAC5F,CAAC;IAED,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAAA;IAC1E,mEAAmE;IACnE,MAAM,WAAW,GAAsB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAEjE,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,CAAC;QACpD,aAAa;QACb,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QACxE,SAAS;QACT,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAA;IAE7E,MAAM,aAAa,GACvB
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,MAAM,sBAAsB,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACrF,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAClC,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,UAAU,IAAI;IAChB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IAEhC,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC3C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;YAC3C,IAAI,GAAG,CAAA;YACP,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,KAAK,CAAC,CAAA;YAC9D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;YACD,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,MAAM,CAAC,CAAA;YAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;YACD,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,MAAM,CAAC,CAAA;YAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,mBAAmB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;QACL,CAAC;IACL,CAAC;IAED,SAAS,mBAAmB,CAAC,GAAW;QACpC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAA,IAAI,WAAW,yCAAyC,GAAG,EAAE;cACvE,kEAAkE,OAAO,SAAS,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,0BAA0B,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IACnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAA,IAAI,WAAW,2CAA2C;cACpE,gEAAgE;cAChE,iFAAiF,CAAC,CAAA;IAC5F,CAAC;IAED,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAAA;IAC1E,mEAAmE;IACnE,MAAM,WAAW,GAAsB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAEjE,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ,CAAC;QACpD,aAAa;QACb,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QACxE,SAAS;QACT,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAA;IAE7E,MAAM,aAAa,GACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmGE,CAAA;IAEE,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAA;IAEjD,GAAG,CAAC,KAAK,CAAC,WAAW,CAAA,IAAI,WAAW,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAC9F,CAAC","sourcesContent":["import { join } from 'path'\nimport chalk from '../packages/chalk.js'\nimport { packageName, cliName, configFileNames, configLocations } from '../config.js'\nimport { out } from '../output.js'\nimport fs from 'fs'\n\nexport function init(): void {\n const projectDir = process.cwd()\n\n for (const configLocation of configLocations) {\n for (const configFileName of configFileNames) {\n let loc\n loc = join(projectDir, configLocation, configFileName + '.js')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.cjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n loc = join(projectDir, configLocation, configFileName + '.mjs')\n if (fs.existsSync(loc)) {\n configAlreadyExists(loc)\n }\n }\n }\n\n function configAlreadyExists(loc: string): void {\n out(chalk.orange`[${packageName}] A matching config already exists at ${loc}`\n + `\\nPlease remove this config before generating a new one with \\`${cliName} init\\``)\n }\n\n const projectPackageJsonLocation = join(projectDir, 'package.json')\n if (!fs.existsSync(projectPackageJsonLocation)) {\n out(chalk.orange`[${packageName}] No package.json exists in this location`\n + '\\nPlease initialise the package with `yarn init` on `npm init`'\n + ' before running this command, and run this command from the project root folder')\n }\n\n const packageJsonRaw = fs.readFileSync(projectPackageJsonLocation, 'utf8')\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const packageJson: { type?: string } = JSON.parse(packageJsonRaw)\n\n const targetConfigName = (packageJson.type === 'module')\n // ES6 module\n ? join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.js')\n // common\n : join(projectDir, configLocations[0] ?? '', configFileNames[0] + '.mjs')\n\n const defaultConfig =\n`\n// @ts-check\n\n/** @satisfies {import('sxy-test-runner').Config} */\nexport default {\n\n // base folder for tests match and ignore patterns\n testsBase: '.',\n\n // glob pattern or array of glob patterns of test files\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n\n // glob pattern or array of patterns of test files to ignore\n testsIgnore: ['**/node_modules/**'],\n\n // whether to show the full error trace when an error occurs in a test file\n showErrorTrace: false,\n\n\n // tasks to run on startup\n // accepts a function, file location (relative to project base), or array of functions and or files\n setup: undefined,\n\n // tasks to run before each test file is run\n beforeEachFile: undefined,\n\n // tasks to run after each test file is run\n afterEachFile: undefined,\n\n // tasks to run before each describe block is processed\n // if the function returns an object with named properties, or the file exports named exports,\n // these will be passed to the callback function in argument 0, and can be access by destructruing e.g.\n // describe('thing', ({exportA, exportB}) => { it('should', ...) })\n beforeEachDescribe: undefined,\n\n // tasks to run after each describe block\n afterEachDescribe: undefined,\n\n // tasks to run before each it/test block\n // function returns and file exports will be passed to the it/test block as with describe above, e.g.\n // it('should', ({exportA, exportB}) => { assert('something') })\n beforeEachTest: undefined,\n\n // tasks to run after each it/test block\n afterEachTest: undefined,\n\n // how to execute the different parts of test files\n execution: {\n\n // run test files in 'parallel' or 'sequential'ly\n files: 'sequential',\n\n // run describe blocks within a test file in 'parallel' or 'sequential'ly\n describes: 'sequential',\n\n // run it/test blocks within a describe blocks in 'parallel' or 'sequential'ly\n tests: 'sequential'\n\n },\n\n // watch mode configurations\n watch: {\n\n //// the base directory to watch files in\n watchFilesBase: '.',\n\n //// glob filter or array of glob filters of files to watch\n watchFiles: '**/*.js',\n\n //// glob filter or array of globl filters of files to ignore\n watchFilesIgnore: '**/node_modules/**',\n\n // run all tests when starting the watcher\n runAllOnStartup: true,\n\n // re run all previously failed tests on each test run, until they pass\n reRunFailingTests: true,\n\n // evaluate the dependencies of each test file, and re-run that test file only when they change. \n // Set this to false to re-run everything on any change\n dependencyEvaluation: true,\n\n // run watch mode keyboard commands immediately, without waiting for Enter\n ttyActionsOnKeypress: false,\n\n // file to write the latest run status to, or false for none\n statusFile: false,\n\n // report the session as single agent readable lines instead of the usual output\n agent: false,\n\n },\n\n}`\n\n fs.writeFileSync(targetConfigName, defaultConfig)\n\n out(chalk.mediumgreen`[${packageName}] Created config at ` + chalk.blue(targetConfigName))\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import type { FinalConfig, TestsResultsSummary } from '../../types.js';
|
|
|
2
2
|
import type { FailureEntry } from './failureEntries.js';
|
|
3
3
|
import type { RunType } from './reRunManager.js';
|
|
4
4
|
import type { StatusCode } from './statusFile.js';
|
|
5
|
-
export type RunReason = RunType | 'startup';
|
|
5
|
+
export type RunReason = RunType | 'startup' | 'once';
|
|
6
6
|
export declare function agentEnabled(config: FinalConfig): boolean;
|
|
7
7
|
export declare function agentInit(enabled: boolean): void;
|
|
8
8
|
export declare function agentFound(config: FinalConfig, files: number): void;
|
|
@@ -45,7 +45,7 @@ export function agentRunStart(config, files) {
|
|
|
45
45
|
if (!agentEnabled(config))
|
|
46
46
|
return 0;
|
|
47
47
|
runCounter++;
|
|
48
|
-
emit('
|
|
48
|
+
emit('running', [
|
|
49
49
|
['n', runCounter],
|
|
50
50
|
['files', files],
|
|
51
51
|
['why', nextRunReason],
|
|
@@ -56,8 +56,13 @@ export function agentRunStart(config, files) {
|
|
|
56
56
|
// what the run was built from. A reader needs this to know how far the run's own `code`
|
|
57
57
|
// generalises - only a run covering everything can speak for the whole suite.
|
|
58
58
|
function runScope(config) {
|
|
59
|
+
// known before the run starts: fail fast means it is built to stop early, so it cannot
|
|
60
|
+
// promise to have covered anything beyond the first failure
|
|
61
|
+
if (config.failFast)
|
|
62
|
+
return 'until-first-failure';
|
|
59
63
|
switch (nextRunReason) {
|
|
60
64
|
case 'startup':
|
|
65
|
+
case 'once':
|
|
61
66
|
case 'all': return 'all';
|
|
62
67
|
case 'last': return 'last';
|
|
63
68
|
case 'failed': return 'failing';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAOhD,2FAA2F;AAC3F,+EAA+E;AAC/E,EAAE;AACF,mDAAmD;AACnD,EAAE;AACF,4FAA4F;AAC5F,kFAAkF;AAElF,MAAM,MAAM,GAAG,QAAQ,CAAA;AAIvB,IAAI,UAAU,GAAG,CAAC,CAAA;AAClB,4FAA4F;AAC5F,+CAA+C;AAC/C,IAAI,aAAa,GAAc,SAAS,CAAA;AAIxC,SAAS,IAAI,CAAC,KAAa,EAAE,SAAkB,EAAE;IAC7C,OAAO,CAAC,MAAM,GAAG,IAAI,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;AAC/F,CAAC;AAED,4FAA4F;AAC5F,SAAS,OAAO,CAAC,IAAY;IACzB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAA;AAC7B,CAAC;AAED,6EAA6E;AAC7E,4FAA4F;AAC5F,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,OAAgB;IACtC,UAAU,GAAG,CAAC,CAAA;IACd,aAAa,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,OAAO;QAAE,OAAM;IACpB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAmB,EAAE,KAAa;IACzD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IAC/C,aAAa,GAAG,MAAM,CAAA;AAC1B,CAAC;AAED,wFAAwF;AACxF,4BAA4B;AAC5B,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,KAAa;IAC5D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAA;IACnC,UAAU,EAAE,CAAA;IACZ,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAOhD,2FAA2F;AAC3F,+EAA+E;AAC/E,EAAE;AACF,mDAAmD;AACnD,EAAE;AACF,4FAA4F;AAC5F,kFAAkF;AAElF,MAAM,MAAM,GAAG,QAAQ,CAAA;AAIvB,IAAI,UAAU,GAAG,CAAC,CAAA;AAClB,4FAA4F;AAC5F,+CAA+C;AAC/C,IAAI,aAAa,GAAc,SAAS,CAAA;AAIxC,SAAS,IAAI,CAAC,KAAa,EAAE,SAAkB,EAAE;IAC7C,OAAO,CAAC,MAAM,GAAG,IAAI,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;AAC/F,CAAC;AAED,4FAA4F;AAC5F,SAAS,OAAO,CAAC,IAAY;IACzB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAA;AAC7B,CAAC;AAED,6EAA6E;AAC7E,4FAA4F;AAC5F,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,OAAgB;IACtC,UAAU,GAAG,CAAC,CAAA;IACd,aAAa,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,OAAO;QAAE,OAAM;IACpB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAmB,EAAE,KAAa;IACzD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IAC/C,aAAa,GAAG,MAAM,CAAA;AAC1B,CAAC;AAED,wFAAwF;AACxF,4BAA4B;AAC5B,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,KAAa;IAC5D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAA;IACnC,UAAU,EAAE,CAAA;IACZ,IAAI,CAAC,SAAS,EAAE;QACZ,CAAC,GAAG,EAAE,UAAU,CAAC;QACjB,CAAC,OAAO,EAAE,KAAK,CAAC;QAChB,CAAC,KAAK,EAAE,aAAa,CAAC;QACtB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;KAC/B,CAAC,CAAA;IACF,OAAO,UAAU,CAAA;AACrB,CAAC;AAED,wFAAwF;AACxF,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,MAAmB;IACjC,uFAAuF;IACvF,4DAA4D;IAC5D,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,qBAAqB,CAAA;IAEjD,QAAQ,aAAa,EAAE,CAAC;QACpB,KAAK,SAAS,CAAC;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK,CAAC,CAAC,OAAO,KAAK,CAAA;QACxB,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAA;QAC1B,KAAK,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAA;QAC/B,KAAK,MAAM,CAAC,CAAC,CAAC;YACV,+EAA+E;YAC/E,2CAA2C;YAC3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB;gBAAE,OAAO,KAAK,CAAA;YACpD,kFAAkF;YAClF,gDAAgD;YAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAA;QAC3E,CAAC;QACD,OAAO,CAAC,CAAC,OAAO,SAAS,CAAA;IAC7B,CAAC;AACL,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,GAAW,EAAE,KAAmB;IAC9E,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,MAAM,EAAE;QACT,CAAC,GAAG,EAAE,GAAG,CAAC;QACV,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC;YAC7B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAU,CAAC;QACtD,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAU,CAAC;QAC7E,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;KAClC,CAAC,CAAA;AACN,CAAC;AAED,wFAAwF;AACxF,4FAA4F;AAC5F,0DAA0D;AAC1D,MAAM,UAAU,SAAS,CACrB,MAAmB,EACnB,GAAW,EACX,IAAgB,EAChB,WAAmB,EACnB,OAAmC,EACnC,UAAkB,EAClB,YAAoB;IAEpB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,MAAM,EAAE;QACT,CAAC,GAAG,EAAE,GAAG,CAAC;QACV,CAAC,MAAM,EAAE,IAAI,CAAC;QACd,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9B,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACzB,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAU;YAC9D,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,cAAc,EAAE,CAAU;YAC1E,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAU;SAC3D;QACD,CAAC,SAAS,EAAE,YAAY,CAAC;QACzB,CAAC,IAAI,EAAE,UAAU,CAAC;KACrB,CAAC,CAAA;AACN,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,KAAa;IAC5D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAmB,EAAE,IAAY,EAAE,KAAa;IACxE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc;IAC1B,8DAA8D;AAClE,CAAC","sourcesContent":["import { out as mainOut } from '../../output.js'\n\nimport type { FinalConfig, TestsResultsSummary } from '../../types.js'\nimport type { FailureEntry } from './failureEntries.js'\nimport type { RunType } from './reRunManager.js'\nimport type { StatusCode } from './statusFile.js'\n\n// Agent mode reports a watch session as a stream of single lines, for a reader tailing the\n// process rather than watching the terminal. Every line is one complete event:\n//\n// [sxyt] <event> | <key>=<value> | <key>=<value>\n//\n// Values are never quoted, so free text is flattened to keep the grammar intact - one event\n// can never span two lines, and a stray `|` can never look like a field boundary.\n\nconst prefix = '[sxyt]'\n\nexport type RunReason = RunType | 'startup' | 'once'\n\nlet runCounter = 0\n// requestRun sets this before handing a run to runTests; the initial run never goes through\n// the queue, so 'startup' is the right default\nlet nextRunReason: RunReason = 'startup'\n\ntype Field = [string, string | number]\n\nfunction emit(event: string, fields: Field[] = []): void {\n mainOut(prefix + ` ${event}` + fields.map(([key, value]) => ` | ${key}=${value}`).join(''))\n}\n\n// newlines would split one event across two lines, and a `|` would read as a field boundary\nfunction flatten(text: string): string {\n return text.replace(/\\s*[\\r\\n]+\\s*/g, ' ').replace(/\\|/g, '/').trim()\n}\n\nexport function agentEnabled(config: FinalConfig): boolean {\n return config.watch.agent\n}\n\n// the process is up, before the config is even loaded - so a slow startup is\n// distinguishable from one that never began. Takes the flag rather than the config for that\n// reason, and resets the counters so repeated in process sessions start from 1.\nexport function agentInit(enabled: boolean): void {\n runCounter = 0\n nextRunReason = 'startup'\n if (!enabled) return\n emit('init', [['pid', process.pid]])\n}\n\nexport function agentFound(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('found', [['files', files]])\n}\n\nexport function agentSetRunReason(reason: RunReason): void {\n nextRunReason = reason\n}\n\n// claims the next run number and announces the run, so a reader knows work is in flight\n// before any result arrives\nexport function agentRunStart(config: FinalConfig, files: number): number {\n if (!agentEnabled(config)) return 0\n runCounter++\n emit('running', [\n ['n', runCounter],\n ['files', files],\n ['why', nextRunReason],\n ['covers', runScope(config)]\n ])\n return runCounter\n}\n\n// what the run was built from. A reader needs this to know how far the run's own `code`\n// generalises - only a run covering everything can speak for the whole suite.\nfunction runScope(config: FinalConfig): string {\n // known before the run starts: fail fast means it is built to stop early, so it cannot\n // promise to have covered anything beyond the first failure\n if (config.failFast) return 'until-first-failure'\n\n switch (nextRunReason) {\n case 'startup':\n case 'once':\n case 'all': return 'all'\n case 'last': return 'last'\n case 'failed': return 'failing'\n case 'auto': {\n // with dependency evaluation off a change runs the whole suite, so an auto run\n // carries the same weight as a startup one\n if (!config.watch.dependencyEvaluation) return 'all'\n // the reRunFailingTests case is the one worth spelling out: without it a run says\n // nothing about files that were already failing\n return (config.watch.reRunFailingTests) ? 'changed+failing' : 'changed'\n }\n default: return 'changed'\n }\n}\n\n// failures are emitted before the run's done line, so done is a complete end of run marker\nexport function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void {\n if (!agentEnabled(config)) return\n emit('fail', [\n ['n', run],\n ['file', flatten(entry.file)],\n ...(entry.describe === undefined)\n ? []\n : [['describe', flatten(entry.describe)] as Field],\n ...(entry.test === undefined) ? [] : [['test', flatten(entry.test)] as Field],\n ['error', flatten(entry.error)]\n ])\n}\n\n// `failing` counts the test files still failing across the whole session, not just this\n// run. A watch re-run usually covers only the changed files, so its own tallies can read as\n// a clean pass while the suite is still broken elsewhere.\nexport function agentDone(\n config: FinalConfig,\n run: number,\n code: StatusCode,\n description: string,\n summary: TestsResultsSummary | null,\n durationMs: number,\n failingFiles: number\n): void {\n if (!agentEnabled(config)) return\n emit('done', [\n ['n', run],\n ['code', code],\n ['desc', flatten(description)],\n ...(summary === null) ? [] : [\n ['tests', `${summary.itsPasses}/${summary.itsTotal}`] as Field,\n ['items', `${summary.describesPasses}/${summary.describesTotal}`] as Field,\n ['files', `${summary.passes}/${summary.total}`] as Field\n ],\n ['failing', failingFiles],\n ['ms', durationMs]\n ])\n}\n\nexport function agentWatching(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('watching', [['files', files]])\n}\n\nexport function agentChange(config: FinalConfig, file: string, event: string): void {\n if (!agentEnabled(config)) return\n emit('change', [['file', flatten(file)], ['event', flatten(event)]])\n}\n\n// agent mode owns stdout, so the ordinary coloured output is routed into a sink\nexport function agentSilentOut(): void {\n // deliberately nothing - the agent lines are the whole stream\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/defaultConfig.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAgB;IACtC,SAAS,EAAE,GAAG;IACd,KAAK,EAAE;QACH,wBAAwB;QACxB,wBAAwB;QACxB,wBAAwB;QACxB,0BAA0B;QAC1B,8BAA8B;KACjC;IACD,WAAW,EAAE,CAAC,oBAAoB,CAAC;IACnC,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,KAAK;IACd,SAAS,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,YAAY;KACtB;IACD,KAAK,EAAE;QACH,cAAc,EAAE,GAAG;QACnB,UAAU,EAAE,SAAS;QACrB,gBAAgB,EAAE,oBAAoB;QACtC,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,IAAI;QACvB,oBAAoB,EAAE,IAAI;QAC1B,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,KAAK;QACjB,KAAK,EAAE,KAAK;KACf;CACJ,CAAA","sourcesContent":["import type { FinalConfig } from '../../types.js'\n\nexport const defaultConfig: FinalConfig = {\n testsBase: '.',\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n testsIgnore: ['**/node_modules/**'],\n showErrorTrace: false,\n compact: false,\n execution: {\n files: 'sequential',\n describes: 'sequential',\n tests: 'sequential'\n },\n watch: {\n watchFilesBase: '.',\n watchFiles: '**/*.js',\n watchFilesIgnore: '**/node_modules/**',\n runAllOnStartup: true,\n reRunFailingTests: true,\n dependencyEvaluation: true,\n ttyActionsOnKeypress: false,\n statusFile: false,\n agent: false\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"defaultConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/defaultConfig.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAgB;IACtC,SAAS,EAAE,GAAG;IACd,KAAK,EAAE;QACH,wBAAwB;QACxB,wBAAwB;QACxB,wBAAwB;QACxB,0BAA0B;QAC1B,8BAA8B;KACjC;IACD,WAAW,EAAE,CAAC,oBAAoB,CAAC;IACnC,cAAc,EAAE,KAAK;IACrB,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,YAAY;QACvB,KAAK,EAAE,YAAY;KACtB;IACD,KAAK,EAAE;QACH,cAAc,EAAE,GAAG;QACnB,UAAU,EAAE,SAAS;QACrB,gBAAgB,EAAE,oBAAoB;QACtC,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,IAAI;QACvB,oBAAoB,EAAE,IAAI;QAC1B,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,KAAK;QACjB,KAAK,EAAE,KAAK;KACf;CACJ,CAAA","sourcesContent":["import type { FinalConfig } from '../../types.js'\n\nexport const defaultConfig: FinalConfig = {\n testsBase: '.',\n tests: [\n '**/*.sxyt.{js,mjs,jsx}',\n '**/*.test.{js,mjs,jsx}',\n '**/*.spec.{js,mjs,jsx}',\n '**/tests?/*.{js,mjs,jsx}',\n '**/__tests?__/*.{js,mjs,jsx}'\n ],\n testsIgnore: ['**/node_modules/**'],\n showErrorTrace: false,\n compact: false,\n failFast: false,\n execution: {\n files: 'sequential',\n describes: 'sequential',\n tests: 'sequential'\n },\n watch: {\n watchFilesBase: '.',\n watchFiles: '**/*.js',\n watchFilesIgnore: '**/node_modules/**',\n runAllOnStartup: true,\n reRunFailingTests: true,\n dependencyEvaluation: true,\n ttyActionsOnKeypress: false,\n statusFile: false,\n agent: false\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const exitCodes: {
|
|
2
|
+
readonly passed: 0;
|
|
3
|
+
readonly testErrors: 20;
|
|
4
|
+
readonly noTestFiles: 21;
|
|
5
|
+
readonly noMatchingTests: 22;
|
|
6
|
+
readonly usageError: 23;
|
|
7
|
+
readonly runnerError: 24;
|
|
8
|
+
};
|
|
9
|
+
export type ExitCode = typeof exitCodes[keyof typeof exitCodes];
|
|
10
|
+
//# sourceMappingURL=exitCodes.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Process exit codes for `once`.
|
|
2
|
+
//
|
|
3
|
+
// Node reserves 1-14 for its own fatal conditions, and anything over 128 is a signal exit
|
|
4
|
+
// (128 + signal), with 126 and 127 taken by the shell for "not executable" and "not found".
|
|
5
|
+
// 2 is left unused by Node because Bash uses it for builtin misuse. The whole range this
|
|
6
|
+
// runner used to sit in - 3, 4, 5 - therefore overlapped Node's own codes, so a caller
|
|
7
|
+
// could not tell "the filters matched nothing" from V8 dying. These start at 20 instead,
|
|
8
|
+
// clear of every reserved range, so a non-zero code here is always the runner's own.
|
|
9
|
+
//
|
|
10
|
+
// These are process exit codes. They are NOT the status codes written by --status-file and
|
|
11
|
+
// reported by --agent, which are a separate, smaller scheme.
|
|
12
|
+
export const exitCodes = {
|
|
13
|
+
passed: 0,
|
|
14
|
+
// tests ran and something was wrong with them: a failed assertion, a test file that
|
|
15
|
+
// would not load, or a describe that threw. All are errors in the tests, not the runner
|
|
16
|
+
testErrors: 20,
|
|
17
|
+
// nothing to run: no test file matched the `tests` pattern
|
|
18
|
+
noTestFiles: 21,
|
|
19
|
+
// test files matched, but --filter-it/--filter-describe selected nothing in them
|
|
20
|
+
noMatchingTests: 22,
|
|
21
|
+
// an option was not recognised, or an option needing a value was given none
|
|
22
|
+
usageError: 23,
|
|
23
|
+
// reserved for a failure in the runner itself. Nothing emits it today - every known
|
|
24
|
+
// failure is one of the above - but it keeps the category the original scheme intended
|
|
25
|
+
runnerError: 24
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=exitCodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exitCodes.js","sourceRoot":"","sources":["../../../src/cli/lib/exitCodes.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,0FAA0F;AAC1F,4FAA4F;AAC5F,yFAAyF;AACzF,uFAAuF;AACvF,yFAAyF;AACzF,qFAAqF;AACrF,EAAE;AACF,2FAA2F;AAC3F,6DAA6D;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG;IACrB,MAAM,EAAE,CAAC;IACT,oFAAoF;IACpF,wFAAwF;IACxF,UAAU,EAAE,EAAE;IACd,2DAA2D;IAC3D,WAAW,EAAE,EAAE;IACf,iFAAiF;IACjF,eAAe,EAAE,EAAE;IACnB,4EAA4E;IAC5E,UAAU,EAAE,EAAE;IACd,oFAAoF;IACpF,uFAAuF;IACvF,WAAW,EAAE,EAAE;CACT,CAAA","sourcesContent":["// Process exit codes for `once`.\n//\n// Node reserves 1-14 for its own fatal conditions, and anything over 128 is a signal exit\n// (128 + signal), with 126 and 127 taken by the shell for \"not executable\" and \"not found\".\n// 2 is left unused by Node because Bash uses it for builtin misuse. The whole range this\n// runner used to sit in - 3, 4, 5 - therefore overlapped Node's own codes, so a caller\n// could not tell \"the filters matched nothing\" from V8 dying. These start at 20 instead,\n// clear of every reserved range, so a non-zero code here is always the runner's own.\n//\n// These are process exit codes. They are NOT the status codes written by --status-file and\n// reported by --agent, which are a separate, smaller scheme.\nexport const exitCodes = {\n passed: 0,\n // tests ran and something was wrong with them: a failed assertion, a test file that\n // would not load, or a describe that threw. All are errors in the tests, not the runner\n testErrors: 20,\n // nothing to run: no test file matched the `tests` pattern\n noTestFiles: 21,\n // test files matched, but --filter-it/--filter-describe selected nothing in them\n noMatchingTests: 22,\n // an option was not recognised, or an option needing a value was given none\n usageError: 23,\n // reserved for a failure in the runner itself. Nothing emits it today - every known\n // failure is one of the above - but it keeps the category the original scheme intended\n runnerError: 24\n} as const\n\nexport type ExitCode = typeof exitCodes[keyof typeof exitCodes]\n"]}
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
// once:
|
|
3
3
|
// // --config configLocation
|
|
4
4
|
import { reduce as objectReduce } from 'sxy-lib/objects.js';
|
|
5
|
-
import { packageName } from '../../config.js';
|
|
5
|
+
import { packageName, cliName } from '../../config.js';
|
|
6
6
|
import { log } from '../../output.js';
|
|
7
|
+
import { exitCodes } from './exitCodes.js';
|
|
7
8
|
import { getAllowedFlags } from './getAllowedFlags.js';
|
|
8
9
|
import chalk from '../../packages/chalk.js';
|
|
9
10
|
export function parseCommandLineArguments(allowedArguments) {
|
|
10
11
|
const allowedFlags = getAllowedFlags(allowedArguments);
|
|
11
12
|
const returnArgs = {};
|
|
13
|
+
// collected rather than reported one at a time, so a mistyped command line is fixed in
|
|
14
|
+
// one go rather than one option per run
|
|
15
|
+
const unknownArgs = [];
|
|
12
16
|
for (let position = 0; position < __sxyt_commandLineArguments.length; position++) {
|
|
13
17
|
const arg = __sxyt_commandLineArguments[position];
|
|
14
18
|
if (arg === undefined)
|
|
@@ -27,6 +31,7 @@ export function parseCommandLineArguments(allowedArguments) {
|
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
else {
|
|
34
|
+
unknownArgs.push(`--${longFlag}`);
|
|
30
35
|
log(chalk.mediumred(`[${packageName}] Unknown option --${longFlag}`));
|
|
31
36
|
if (longFlag.length === 1
|
|
32
37
|
&& objectReduce(allowedArguments, (prev, _key, value) => {
|
|
@@ -56,6 +61,7 @@ export function parseCommandLineArguments(allowedArguments) {
|
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
else {
|
|
64
|
+
unknownArgs.push(`-${shortFlag}`);
|
|
59
65
|
log(chalk.mediumred(`[${packageName}] Unknown flag -${shortFlag}`));
|
|
60
66
|
if (shortFlag.length > 1 && shortFlag in allowedArguments) {
|
|
61
67
|
log(chalk.mediumred(`I think you meant --${shortFlag}`));
|
|
@@ -63,6 +69,12 @@ export function parseCommandLineArguments(allowedArguments) {
|
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
}
|
|
72
|
+
// stop rather than run something other than what was asked for: an ignored option can
|
|
73
|
+
// mean the wrong tests, or a whole suite where a single filtered test was wanted
|
|
74
|
+
if (unknownArgs.length > 0) {
|
|
75
|
+
log(chalk.orange(`Run \`${cliName} help\` to see the available options.`));
|
|
76
|
+
process.exit(exitCodes.usageError);
|
|
77
|
+
}
|
|
66
78
|
return returnArgs;
|
|
67
79
|
}
|
|
68
80
|
//# sourceMappingURL=parseCommandLineArguments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseCommandLineArguments.js","sourceRoot":"","sources":["../../../src/cli/lib/parseCommandLineArguments.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,QAAQ;AACR,6BAA6B;AAG7B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"parseCommandLineArguments.js","sourceRoot":"","sources":["../../../src/cli/lib/parseCommandLineArguments.ts"],"names":[],"mappings":"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","sourcesContent":["// watch:\n// once:\n// // --config configLocation\n\n\nimport { reduce as objectReduce } from 'sxy-lib/objects.js'\nimport { packageName, cliName } from '../../config.js'\nimport { log } from '../../output.js'\nimport type { AllowedArguments, ParsedArguments } from '../../types.js'\n\nimport { exitCodes } from './exitCodes.js'\nimport { getAllowedFlags } from './getAllowedFlags.js'\nimport chalk from '../../packages/chalk.js'\n\nexport function parseCommandLineArguments(allowedArguments: AllowedArguments): ParsedArguments {\n const allowedFlags = getAllowedFlags(allowedArguments)\n\n const returnArgs: ParsedArguments = {}\n // collected rather than reported one at a time, so a mistyped command line is fixed in\n // one go rather than one option per run\n const unknownArgs: string[] = []\n\n for (let position = 0; position < __sxyt_commandLineArguments.length; position++) {\n const arg = __sxyt_commandLineArguments[position]\n if (arg === undefined) continue\n if (arg.slice(0, 2) === '--') {\n const longFlag = arg.slice(2)\n const allowedArgument = allowedArguments[longFlag]\n if (allowedArgument) {\n if (allowedArgument.hasValue) {\n const value = __sxyt_commandLineArguments[++position]\n if (value !== undefined) returnArgs[longFlag] = value\n } else {\n returnArgs[longFlag] = true\n }\n } else {\n unknownArgs.push(`--${longFlag}`)\n log(chalk.mediumred(`[${packageName}] Unknown option --${longFlag}`))\n if (\n longFlag.length === 1\n && objectReduce(\n allowedArguments,\n (prev: boolean, _key: string, value: {\n flag?: string\n hasValue: boolean\n }) => {\n if (value.flag === longFlag) return true\n return prev\n },\n false\n )\n ) {\n log(chalk.mediumred(`I think you meant -${longFlag}`))\n }\n }\n } else if (arg.slice(0, 1) === '-') {\n const shortFlag = arg.slice(1)\n const longFlag = allowedFlags[shortFlag]\n if (longFlag !== undefined) {\n if (longFlag in returnArgs) {\n log(chalk.orange(\n `[${packageName}] Option --${longFlag} already set, being overwritten by -${shortFlag}`\n ))\n }\n\n const allowedArgument = allowedArguments[longFlag]\n if (allowedArgument?.hasValue === true) {\n const value = __sxyt_commandLineArguments[++position]\n if (value !== undefined) returnArgs[longFlag] = value\n } else {\n returnArgs[longFlag] = true\n }\n } else {\n unknownArgs.push(`-${shortFlag}`)\n log(chalk.mediumred(`[${packageName}] Unknown flag -${shortFlag}`))\n if (shortFlag.length > 1 && shortFlag in allowedArguments) {\n log(chalk.mediumred(`I think you meant --${shortFlag}`))\n }\n }\n }\n }\n\n // stop rather than run something other than what was asked for: an ignored option can\n // mean the wrong tests, or a whole suite where a single filtered test was wanted\n if (unknownArgs.length > 0) {\n log(chalk.orange(`Run \\`${cliName} help\\` to see the available options.`))\n process.exit(exitCodes.usageError)\n }\n\n return returnArgs\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const commands: readonly ["init", "once", "watch", "help", "version"];
|
|
2
|
+
export type Command = typeof commands[number];
|
|
3
|
+
export interface ResolvedCommand {
|
|
4
|
+
command: Command;
|
|
5
|
+
commandArgs: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveCommand(args: string[]): ResolvedCommand;
|
|
8
|
+
//# sourceMappingURL=resolveCommand.d.ts.map
|