@molecule/api-ai-tools 1.10.1 → 1.10.3
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/README.md +229 -15
- package/dist/no-test-run.d.ts +3 -1
- package/dist/no-test-run.d.ts.map +1 -1
- package/dist/no-test-run.js +114 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +64 -30
- package/dist/trace-artifacts.d.ts +65 -0
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +370 -29
- package/dist/types.d.ts +27 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities.d.ts +114 -12
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +424 -33
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-10-
|
|
6
|
+
Generated: 2026-10-19T03:15:38.119Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -586,6 +586,16 @@ interface TraceMissingText {
|
|
|
586
586
|
method: string
|
|
587
587
|
/** The path of the response that carried it (`/api/tags`). */
|
|
588
588
|
path: string
|
|
589
|
+
/**
|
|
590
|
+
* Whether the trace PROVES the page dropped the text: the named response is a successful GET
|
|
591
|
+
* of the collection that started after the last navigation, and the text is absent from the
|
|
592
|
+
* page's own failure snapshot ({@link traceArtifactsScript}).
|
|
593
|
+
*
|
|
594
|
+
* Absent when the evidence is weaker — a creation POST carried the text (m194's button failure
|
|
595
|
+
* was not a missing article), the snapshot still showed it, or the trace recorded no clock —
|
|
596
|
+
* and the note then says only that a response contained the text.
|
|
597
|
+
*/
|
|
598
|
+
dropped?: true
|
|
589
599
|
}
|
|
590
600
|
```
|
|
591
601
|
|
|
@@ -616,6 +626,43 @@ interface TraceReadContradiction {
|
|
|
616
626
|
}
|
|
617
627
|
```
|
|
618
628
|
|
|
629
|
+
#### `TraceHiddenBox`
|
|
630
|
+
|
|
631
|
+
A visibility failure whose locator RESOLVED: Playwright calls an element with a zero-size box
|
|
632
|
+
"hidden" even when it is painted, so the useful fact is why the box is empty. The trace's own
|
|
633
|
+
failure snapshot carries the element's children — read here, never guessed.
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
interface TraceHiddenBox {
|
|
637
|
+
/** The locator the assertion printed (`locator('a.navbar-brand')`), or the element it names. */
|
|
638
|
+
locator: string
|
|
639
|
+
/** The element's tag, lowercased (`a`). */
|
|
640
|
+
tag: string
|
|
641
|
+
/** The element's own inline style, when the snapshot carries one. */
|
|
642
|
+
style?: string
|
|
643
|
+
/**
|
|
644
|
+
* The `<img>` the element wraps when that image is its only element child and the element has
|
|
645
|
+
* no text of its own: the size the box would collapse to.
|
|
646
|
+
*/
|
|
647
|
+
image?: {
|
|
648
|
+
/** The image's `src`, bounded. */
|
|
649
|
+
src?: string
|
|
650
|
+
/** Its `width` attribute. */
|
|
651
|
+
width?: string
|
|
652
|
+
/** Its `height` attribute. */
|
|
653
|
+
height?: string
|
|
654
|
+
/** Its inline `style`. */
|
|
655
|
+
style?: string
|
|
656
|
+
/** Its `class`. */
|
|
657
|
+
className?: string
|
|
658
|
+
/** Its `alt` text. */
|
|
659
|
+
alt?: string
|
|
660
|
+
}
|
|
661
|
+
/** True when the element has no text and no element children at all. */
|
|
662
|
+
empty?: true
|
|
663
|
+
}
|
|
664
|
+
```
|
|
665
|
+
|
|
619
666
|
#### `TraceArtifact`
|
|
620
667
|
|
|
621
668
|
What one trace says: the test it belongs to, the requests it made, and its console lines.
|
|
@@ -705,6 +752,13 @@ interface TraceArtifact {
|
|
|
705
752
|
* and on traces read before this field existed.
|
|
706
753
|
*/
|
|
707
754
|
readContradiction?: TraceReadContradiction
|
|
755
|
+
/**
|
|
756
|
+
* A visibility failure whose locator RESOLVED into an empty box — Playwright's "hidden" — with
|
|
757
|
+
* the element's children read from the failure snapshot ({@link TraceHiddenBox}). The note uses
|
|
758
|
+
* it to name why the box is empty (an `<img>` with no CSS size, a textless element) instead of
|
|
759
|
+
* leaving the run to probe computed styles (xr-molecule-flash-m197).
|
|
760
|
+
*/
|
|
761
|
+
hiddenBox?: TraceHiddenBox
|
|
708
762
|
}
|
|
709
763
|
```
|
|
710
764
|
|
|
@@ -843,14 +897,31 @@ interface SuiteBudgetPin {
|
|
|
843
897
|
/**
|
|
844
898
|
* The Playwright flags that carry the suite's own settings onto the command
|
|
845
899
|
* (`--timeout=15000`, `--workers=1`), as the consumer's own scan reads them. Empty when the
|
|
846
|
-
* difference is in settings no flag carries
|
|
900
|
+
* difference is in settings no flag carries.
|
|
847
901
|
*/
|
|
848
902
|
flags: string[]
|
|
903
|
+
/** One sentence for the run's result: which of the suite's own settings this run uses. */
|
|
904
|
+
note: string
|
|
849
905
|
/**
|
|
850
|
-
*
|
|
851
|
-
*
|
|
906
|
+
* A config file the consumer wrote OUTSIDE the supplied suite, which re-imports the config the
|
|
907
|
+
* run selected and pins the settings no Playwright flag can carry (`expect.timeout`,
|
|
908
|
+
* `use.actionTimeout`, `use.navigationTimeout`). When present, the run is launched with
|
|
909
|
+
* `--config <this path>` in place of the config it named, so those settings are the suite's own
|
|
910
|
+
* rather than the executor's. Absent when the consumer could not write one.
|
|
852
911
|
*/
|
|
853
|
-
|
|
912
|
+
config?: string
|
|
913
|
+
/**
|
|
914
|
+
* Every setting the derived config ({@link config}) pins at the suite's own value, by the scan's
|
|
915
|
+
* key (`timeout`, `expect.timeout`, `actionTimeout`, `navigationTimeout`), in milliseconds as
|
|
916
|
+
* digits. Empty when no derived config was placed.
|
|
917
|
+
*/
|
|
918
|
+
values?: Record<string, string>
|
|
919
|
+
/**
|
|
920
|
+
* Every setting the run's own config makes different from the suite's, as the consumer's scan
|
|
921
|
+
* read them: the value this run's config writes and the suite's own. The tool reports the ones
|
|
922
|
+
* its placement did NOT put back, so a result never claims a drift it carried.
|
|
923
|
+
*/
|
|
924
|
+
drift?: Record<string, { used: string; suite: string }>
|
|
854
925
|
}
|
|
855
926
|
```
|
|
856
927
|
|
|
@@ -986,7 +1057,8 @@ interface ToolBuildConfig {
|
|
|
986
1057
|
* different settings, asked BEFORE the run executes. The consumer knows where the suite and its
|
|
987
1058
|
* base config live; this shared package does not, so the reading is the consumer's and the
|
|
988
1059
|
* mechanics — putting the flags on the runner's own arguments, before the pipeline and outside
|
|
989
|
-
* any redirect or group closer
|
|
1060
|
+
* any redirect or group closer, and pointing `--config` at the derived config that carries the
|
|
1061
|
+
* settings no flag can — are this tool's.
|
|
990
1062
|
*
|
|
991
1063
|
* Called for a Playwright suite command only, and only the LAST suite step is touched. A run
|
|
992
1064
|
* that already keeps the suite's settings, or a sandbox with no supplied suite, answers `null`.
|
|
@@ -994,7 +1066,7 @@ interface ToolBuildConfig {
|
|
|
994
1066
|
*
|
|
995
1067
|
* @param command - The shell command, as the model sent it.
|
|
996
1068
|
* @param cwd - The resolved working directory it will run in.
|
|
997
|
-
* @returns The flags and the sentence, or null when nothing is put back.
|
|
1069
|
+
* @returns The flags, the derived config and the sentence, or null when nothing is put back.
|
|
998
1070
|
*/
|
|
999
1071
|
suiteBudget?: (command: string, cwd: string) => Promise<SuiteBudgetPin | null | undefined>
|
|
1000
1072
|
|
|
@@ -1227,6 +1299,19 @@ interface CausePageErrors {
|
|
|
1227
1299
|
where: string
|
|
1228
1300
|
/** The alert / error items the page showed at the moment it failed. */
|
|
1229
1301
|
items: readonly string[]
|
|
1302
|
+
/**
|
|
1303
|
+
* The landmark roles the test's page snapshot printed (`navigation`, `banner`), read from the
|
|
1304
|
+
* YAML block of its own `error-context.md`. Present ONLY when the caller has that test's
|
|
1305
|
+
* snapshot; an empty array means the snapshot was read and showed no landmark, while an absent
|
|
1306
|
+
* field means nothing was read and no claim may be made ({@link missingHeaderNote}).
|
|
1307
|
+
*/
|
|
1308
|
+
landmarks?: readonly string[]
|
|
1309
|
+
/**
|
|
1310
|
+
* Whether the test's snapshot showed populated page content (headings, paragraphs, links,
|
|
1311
|
+
* list items, buttons), the other half of the missing-header reading: a page that painted its
|
|
1312
|
+
* main content but no navigation.
|
|
1313
|
+
*/
|
|
1314
|
+
populated?: boolean
|
|
1230
1315
|
}
|
|
1231
1316
|
```
|
|
1232
1317
|
|
|
@@ -1296,6 +1381,14 @@ from any shell runner.
|
|
|
1296
1381
|
type InstalledPackageProbe = (path: string) => Promise<InstalledPackageFacts>
|
|
1297
1382
|
```
|
|
1298
1383
|
|
|
1384
|
+
#### `RequiredLandmark`
|
|
1385
|
+
|
|
1386
|
+
A landmark role a failed selector requires: `<nav>`/`role=navigation`, `<header>`/`role=banner`.
|
|
1387
|
+
|
|
1388
|
+
```typescript
|
|
1389
|
+
type RequiredLandmark = 'navigation' | 'banner'
|
|
1390
|
+
```
|
|
1391
|
+
|
|
1299
1392
|
### Classes
|
|
1300
1393
|
|
|
1301
1394
|
#### `ToolInputError`
|
|
@@ -1769,7 +1862,9 @@ the runner invocation each caller read as a run is one.
|
|
|
1769
1862
|
|
|
1770
1863
|
A command that also runs tests is false however it is spelled: `npx playwright install &&
|
|
1771
1864
|
npx playwright test` installs and runs, so a caller that sees `playwright test` in it is
|
|
1772
|
-
reading a real run.
|
|
1865
|
+
reading a real run. So is a command carrying a segment this reader cannot place (a script it
|
|
1866
|
+
does not know, which may start a suite): only the runners and the {@link NO_TEST_PROGRAMS}
|
|
1867
|
+
table can be accounted for, and "only prints" is a claim about the WHOLE command.
|
|
1773
1868
|
|
|
1774
1869
|
```typescript
|
|
1775
1870
|
function commandRunsNoTests(command: string): boolean
|
|
@@ -2360,6 +2455,26 @@ function isCredentialExchangePath(path: string, authEndpoints?: readonly string[
|
|
|
2360
2455
|
|
|
2361
2456
|
**Returns:** True when the path names a credential exchange.
|
|
2362
2457
|
|
|
2458
|
+
#### `hiddenBoxNote(items)`
|
|
2459
|
+
|
|
2460
|
+
The sentence a "hidden" visibility failure earns when the trace proved WHY the box is empty.
|
|
2461
|
+
|
|
2462
|
+
Playwright calls an element with a zero-size box hidden even when it is painted, so the answer
|
|
2463
|
+
is in the element's children. `a.navbar-brand` on xr-molecule-flash-m197 was 0×4 px because its
|
|
2464
|
+
only child was `<img src="/conduit-logo.svg" height="26">`: an SVG with a `viewBox` and no
|
|
2465
|
+
width/height has no intrinsic size, and the `height` attribute loses to Tailwind's preflight
|
|
2466
|
+
(`img { max-width: 100%; height: auto }`), which the scaffold's own `index.css` imports. The
|
|
2467
|
+
note said only "the cause is in the page", and the run spent over four minutes rasterising an
|
|
2468
|
+
SVG to PNG. Only what the snapshot shows is claimed ({@link TraceHiddenBox}).
|
|
2469
|
+
|
|
2470
|
+
```typescript
|
|
2471
|
+
function hiddenBoxNote(items: readonly TraceArtifact[]): string | null
|
|
2472
|
+
```
|
|
2473
|
+
|
|
2474
|
+
- `items` — The traces {@link parseTraceArtifacts} read.
|
|
2475
|
+
|
|
2476
|
+
**Returns:** The sentence, or null when no failure carries a hidden-box reading.
|
|
2477
|
+
|
|
2363
2478
|
#### `failureTraceNote(items, target, earlierFailures, apiPrefixes, report)`
|
|
2364
2479
|
|
|
2365
2480
|
The note a failed suite run's result carries: what each failing test's page actually sent, and
|
|
@@ -2741,6 +2856,33 @@ function suiteRunBudgetCommand(
|
|
|
2741
2856
|
|
|
2742
2857
|
**Returns:** The command to run, the flags placed on it, and the ones it could not carry.
|
|
2743
2858
|
|
|
2859
|
+
#### `suiteRunConfigCommand(command, config)`
|
|
2860
|
+
|
|
2861
|
+
A command with the derived config put on the LAST suite runner's own arguments, replacing the
|
|
2862
|
+
config the run names or added when it names none.
|
|
2863
|
+
|
|
2864
|
+
Some of the suite's settings have no Playwright flag (`expect.timeout`, `use.actionTimeout`,
|
|
2865
|
+
`use.navigationTimeout`), so a config the executor wrote cannot be corrected from the command
|
|
2866
|
+
line. The consumer writes a derived config OUTSIDE the supplied suite that re-imports the one
|
|
2867
|
+
the run selected and pins those settings ({@link SuiteBudgetPin.config}); pointing the runner at
|
|
2868
|
+
it is the one way to carry them, and it belongs on the runner itself for the same reasons
|
|
2869
|
+
{@link suiteRunBudgetCommand}'s flags do (last suite step, before a pipe or group closer).
|
|
2870
|
+
|
|
2871
|
+
A command whose runner cannot be placed is returned exactly as written with `placed: false`, so
|
|
2872
|
+
the caller never claims a config it did not point the run at.
|
|
2873
|
+
|
|
2874
|
+
```typescript
|
|
2875
|
+
function suiteRunConfigCommand(
|
|
2876
|
+
command: string,
|
|
2877
|
+
config: string,
|
|
2878
|
+
): { command: string; placed: boolean }
|
|
2879
|
+
```
|
|
2880
|
+
|
|
2881
|
+
- `command` — The shell command about to run.
|
|
2882
|
+
- `config` — The config to run, as the runner takes it (`--config <path>`).
|
|
2883
|
+
|
|
2884
|
+
**Returns:** The command to run and whether the config was placed.
|
|
2885
|
+
|
|
2744
2886
|
#### `withoutSuiteTimeout(command)`
|
|
2745
2887
|
|
|
2746
2888
|
The command with the `timeout <N>` wrapper lifted off the statement that runs the suite, and the
|
|
@@ -3327,6 +3469,31 @@ function repeatingFailure(log: string): RepeatingFailure | null
|
|
|
3327
3469
|
|
|
3328
3470
|
**Returns:** The repeating cause, or null when no signature has {@link REPEATING_FAILURE_MIN} distinct tests behind it.
|
|
3329
3471
|
|
|
3472
|
+
#### `logShowsInlineFailureBodies(log)`
|
|
3473
|
+
|
|
3474
|
+
Whether the log read so far carries a failure's own body under a `✘` row — the evidence that a
|
|
3475
|
+
run prints each failure's error as that test fails ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}).
|
|
3476
|
+
|
|
3477
|
+
`wait_for_task` promises the executor that each failure's report sits right under its `✘` line
|
|
3478
|
+
only when the log proves it. The command's shape cannot answer: the launch sets the switch on
|
|
3479
|
+
every background command (the executor's wrapper script inherits it), so a wrapper this reader
|
|
3480
|
+
cannot place is exactly as covered as `npx playwright test` ({@link streamingBackgroundCommand}).
|
|
3481
|
+
The log is the evidence — a `1) [project] › spec › title ───` block whose test the log also
|
|
3482
|
+
printed with `✘` ({@link failureBlocks}).
|
|
3483
|
+
|
|
3484
|
+
A block alone is not enough: a FINISHED run's end-of-run summary carries the same blocks, and a
|
|
3485
|
+
running wait must not be told "as it fails" about a log whose bodies only appear at the end.
|
|
3486
|
+
During a wait the run has not ended (the exit file is read first), so a block beside a `✘` row
|
|
3487
|
+
is one the reporter printed inline.
|
|
3488
|
+
|
|
3489
|
+
```typescript
|
|
3490
|
+
function logShowsInlineFailureBodies(log: string): boolean
|
|
3491
|
+
```
|
|
3492
|
+
|
|
3493
|
+
- `log` — A log, or the slice of one a wait reads.
|
|
3494
|
+
|
|
3495
|
+
**Returns:** True when a `✘` row's own test has a failure body under it.
|
|
3496
|
+
|
|
3330
3497
|
#### `specFilesSelected(command)`
|
|
3331
3498
|
|
|
3332
3499
|
How many test FILES a Playwright run's own command narrows it to, or null when it selects the
|
|
@@ -3481,6 +3648,50 @@ function failuresByCause(log: string, excluded?: readonly string[]): FailureCaus
|
|
|
3481
3648
|
|
|
3482
3649
|
**Returns:** The causes, the one with the most tests first.
|
|
3483
3650
|
|
|
3651
|
+
#### `requiredLandmark(selector)`
|
|
3652
|
+
|
|
3653
|
+
The landmark a selector requires as an ANCESTOR (or names as its own role), or null when it
|
|
3654
|
+
names no landmark at all (`h1`, `.article-preview`, `a[href="/profile/x"]`).
|
|
3655
|
+
|
|
3656
|
+
```typescript
|
|
3657
|
+
function requiredLandmark(selector: string): RequiredLandmark | null
|
|
3658
|
+
```
|
|
3659
|
+
|
|
3660
|
+
- `selector` — One CSS selector or `getByRole` role from a failure's call log.
|
|
3661
|
+
|
|
3662
|
+
**Returns:** The landmark, or null.
|
|
3663
|
+
|
|
3664
|
+
#### `missingHeaderNote(log, pageErrors)`
|
|
3665
|
+
|
|
3666
|
+
The sentence for a run whose navigational elements are all missing from pages that otherwise
|
|
3667
|
+
painted — the missing shared header the executor must check BEFORE rewriting auth.
|
|
3668
|
+
|
|
3669
|
+
xr-molecule-flash-m193 (+13:54 → +20:00): four failures on `/` — `a[href="/profile/…"]`,
|
|
3670
|
+
`a.navbar-brand`, `nav a[href="/"]`, `nav .user-pic` — while every `error-context.md` snapshot
|
|
3671
|
+
showed the feed, sidebar and footer with no navigation at all. `Home.tsx` imported and
|
|
3672
|
+
re-exported `Navbar` but never rendered it, and `App.tsx` mounted `<Home />` in a bare route.
|
|
3673
|
+
The cause list named four unrelated symptoms, so the run rewrote `Navbar`'s auth logic and then
|
|
3674
|
+
the HTTP bond across two whole walks (~6 minutes) instead of mounting the header.
|
|
3675
|
+
|
|
3676
|
+
The reading is per FAILURE and per SNAPSHOT: each failure's own selector must require the
|
|
3677
|
+
landmark, its own snapshot must have been read AND show populated page content, and that
|
|
3678
|
+
snapshot must not contain the landmark. Two or more such failures on ONE route (the route a
|
|
3679
|
+
selector names, e.g. `nav a[href="/"]` → `/`; failures whose selector names none ride along)
|
|
3680
|
+
are the group. A page that shows the navigation and merely misses a signed-in link is not this
|
|
3681
|
+
shape — its snapshots contain the landmark, so nothing is said.
|
|
3682
|
+
|
|
3683
|
+
This never stops the run and never claims the page is blank: it is one sentence prepended to
|
|
3684
|
+
the causes note ({@link failureCausesNote}).
|
|
3685
|
+
|
|
3686
|
+
```typescript
|
|
3687
|
+
function missingHeaderNote(log: string, pageErrors?: readonly CausePageErrors[]): string | null
|
|
3688
|
+
```
|
|
3689
|
+
|
|
3690
|
+
- `log` — The run's output.
|
|
3691
|
+
- `pageErrors` — The page snapshot facts the caller read per failing test.
|
|
3692
|
+
|
|
3693
|
+
**Returns:** The sentence, or null when the failures do not share a missing landmark.
|
|
3694
|
+
|
|
3484
3695
|
#### `failureCausesNote(log, excluded, run)`
|
|
3485
3696
|
|
|
3486
3697
|
The one-line-per-cause summary of a finished run's failures, or null when the run named fewer
|
|
@@ -3514,6 +3725,7 @@ function failureCausesNote(
|
|
|
3514
3725
|
env?: readonly RunEnvSetting[]
|
|
3515
3726
|
},
|
|
3516
3727
|
pageErrors?: readonly CausePageErrors[],
|
|
3728
|
+
regressedSpecs?: readonly string[],
|
|
3517
3729
|
): string | null
|
|
3518
3730
|
```
|
|
3519
3731
|
|
|
@@ -3862,8 +4074,9 @@ the summary at the end: `list` reads it in its constructor (`ListReporterOptions
|
|
|
3862
4074
|
inline the end-of-run repeat is suppressed with it (`epilogue(!printFailuresInline)`), so one
|
|
3863
4075
|
reporter still prints each failure exactly once.
|
|
3864
4076
|
|
|
3865
|
-
|
|
3866
|
-
|
|
4077
|
+
Every background command is given this (see {@link streamingBackgroundCommand}), so a suite the
|
|
4078
|
+
executor starts through its own wrapper is covered too — the wrapper passes the environment on
|
|
4079
|
+
to the Playwright process it spawns. Without it the log's only failure lines are `✘` rows:
|
|
3867
4080
|
X1 xr-molecule-flash-m99 (+19:27 → +21:00, 2026-10-16) was told to `grep -n -A 20 '<test name>'`
|
|
3868
4081
|
the log, got nothing back through four greps, inferred causes from the spec prose instead, and
|
|
3869
4082
|
edited `app/src` while the run was still walking — which voids the run.
|
|
@@ -4174,11 +4387,12 @@ a test whose result is thrown away, and a blank page costs its per-test budget e
|
|
|
4174
4387
|
(m177: 18 tests, ~4.2 minutes, on a page whose thrown error was visible in the first
|
|
4175
4388
|
`pageerror`). Three is the smallest count that is not one page's own bug: the cause additionally
|
|
4176
4389
|
needs three DISTINCT spec files (`UNIVERSAL_CAUSE_FILES`, or the files a narrowed run selected),
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
about one test's worth
|
|
4390
|
+
no failure showing a locator RESOLVING ({@link ELEMENT_FOUND} — a blank page cannot resolve
|
|
4391
|
+
one), and no test passing after the first failure. A page that renders misses elements, but
|
|
4392
|
+
three unrelated specs in three files failing at three different locators that never resolved,
|
|
4393
|
+
with nothing passing in between, is the page, not three bugs. At the suite's own 5 s action
|
|
4394
|
+
timeout that verdict lands ~20 s into the walk, so the early stop costs about one test's worth
|
|
4395
|
+
of time instead of fifteen.
|
|
4182
4396
|
|
|
4183
4397
|
```typescript
|
|
4184
4398
|
const EMPTY_PAGE_CAUSE_TESTS: 3
|
package/dist/no-test-run.d.ts
CHANGED
|
@@ -49,7 +49,9 @@
|
|
|
49
49
|
*
|
|
50
50
|
* A command that also runs tests is false however it is spelled: `npx playwright install &&
|
|
51
51
|
* npx playwright test` installs and runs, so a caller that sees `playwright test` in it is
|
|
52
|
-
* reading a real run.
|
|
52
|
+
* reading a real run. So is a command carrying a segment this reader cannot place (a script it
|
|
53
|
+
* does not know, which may start a suite): only the runners and the {@link NO_TEST_PROGRAMS}
|
|
54
|
+
* table can be accounted for, and "only prints" is a claim about the WHOLE command.
|
|
53
55
|
*
|
|
54
56
|
* @param command - The shell command as the executor sent it.
|
|
55
57
|
* @returns True when the command invokes a runner only to print.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-test-run.d.ts","sourceRoot":"","sources":["../src/no-test-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;
|
|
1
|
+
{"version":3,"file":"no-test-run.d.ts","sourceRoot":"","sources":["../src/no-test-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAiLH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAiB3D"}
|
package/dist/no-test-run.js
CHANGED
|
@@ -75,6 +75,108 @@ const NO_RUN_FLAGS = {
|
|
|
75
75
|
],
|
|
76
76
|
hurl: [/(?:^|\s)--help(?=\s|$)/, /(?:^|\s)-h(?=\s|$)/, /(?:^|\s)--version(?=\s|$)/],
|
|
77
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* The programs that start no test — the shell's own bookkeeping (`cd`, `export`, `echo`), and the
|
|
80
|
+
* readers, printers and file commands an executor uses to look at what is already there (`cat`,
|
|
81
|
+
* `ls`, `cp`, `tail`, …).
|
|
82
|
+
*
|
|
83
|
+
* A segment whose program is neither a runner nor one of these is a program this reader cannot
|
|
84
|
+
* account for: the suite's own script (`./run-api-tests-hurl.sh`), a wrapper the executor wrote,
|
|
85
|
+
* anything that may itself start a suite. {@link commandRunsNoTests} answers false for a command
|
|
86
|
+
* carrying one — "every invocation only prints" is not a claim an unknown step can support.
|
|
87
|
+
* X1 xr-molecule-flash-m197 (+05:18) sent
|
|
88
|
+
* `hurl --version | head -2 && HOST=http://localhost:4000 ./run-api-tests-hurl.sh 2>&1 | tail -60`,
|
|
89
|
+
* the suite passed 13/13, and the supplied script was the one segment nobody could place: the
|
|
90
|
+
* whole command read as a version probe, so every "has the suite run?" reader said no for the
|
|
91
|
+
* rest of the run and the early deploy was held to the end of the list.
|
|
92
|
+
*/
|
|
93
|
+
const NO_TEST_PROGRAMS = new Set([
|
|
94
|
+
'[',
|
|
95
|
+
'[[',
|
|
96
|
+
':',
|
|
97
|
+
'awk',
|
|
98
|
+
'base64',
|
|
99
|
+
'basename',
|
|
100
|
+
'case',
|
|
101
|
+
'cat',
|
|
102
|
+
'cd',
|
|
103
|
+
'chmod',
|
|
104
|
+
'chown',
|
|
105
|
+
'column',
|
|
106
|
+
'comm',
|
|
107
|
+
'cp',
|
|
108
|
+
'cut',
|
|
109
|
+
'date',
|
|
110
|
+
'df',
|
|
111
|
+
'diff',
|
|
112
|
+
'dirname',
|
|
113
|
+
'do',
|
|
114
|
+
'done',
|
|
115
|
+
'du',
|
|
116
|
+
'echo',
|
|
117
|
+
'egrep',
|
|
118
|
+
'else',
|
|
119
|
+
'env',
|
|
120
|
+
'esac',
|
|
121
|
+
'export',
|
|
122
|
+
'expr',
|
|
123
|
+
'false',
|
|
124
|
+
'fgrep',
|
|
125
|
+
'fi',
|
|
126
|
+
'file',
|
|
127
|
+
'fold',
|
|
128
|
+
'for',
|
|
129
|
+
'grep',
|
|
130
|
+
'head',
|
|
131
|
+
'hostname',
|
|
132
|
+
'id',
|
|
133
|
+
'if',
|
|
134
|
+
'jq',
|
|
135
|
+
'kill',
|
|
136
|
+
'less',
|
|
137
|
+
'ln',
|
|
138
|
+
'ls',
|
|
139
|
+
'md5sum',
|
|
140
|
+
'mkdir',
|
|
141
|
+
'mktemp',
|
|
142
|
+
'more',
|
|
143
|
+
'mv',
|
|
144
|
+
'nl',
|
|
145
|
+
'od',
|
|
146
|
+
'paste',
|
|
147
|
+
'printf',
|
|
148
|
+
'pwd',
|
|
149
|
+
'readlink',
|
|
150
|
+
'realpath',
|
|
151
|
+
'rev',
|
|
152
|
+
'rm',
|
|
153
|
+
'rmdir',
|
|
154
|
+
'seq',
|
|
155
|
+
'set',
|
|
156
|
+
'sha256sum',
|
|
157
|
+
'sleep',
|
|
158
|
+
'sort',
|
|
159
|
+
'stat',
|
|
160
|
+
'tac',
|
|
161
|
+
'tail',
|
|
162
|
+
'tee',
|
|
163
|
+
'test',
|
|
164
|
+
'then',
|
|
165
|
+
'touch',
|
|
166
|
+
'tr',
|
|
167
|
+
'true',
|
|
168
|
+
'type',
|
|
169
|
+
'uname',
|
|
170
|
+
'uniq',
|
|
171
|
+
'unset',
|
|
172
|
+
'until',
|
|
173
|
+
'wait',
|
|
174
|
+
'wc',
|
|
175
|
+
'which',
|
|
176
|
+
'while',
|
|
177
|
+
'whoami',
|
|
178
|
+
'xxd',
|
|
179
|
+
]);
|
|
78
180
|
/**
|
|
79
181
|
* A heredoc body is data a command writes, not what it runs: a `playwright test --list` inside
|
|
80
182
|
* the config a command writes is not a run of this command either way. The pattern consumes the
|
|
@@ -113,7 +215,9 @@ function informational(runner, after) {
|
|
|
113
215
|
*
|
|
114
216
|
* A command that also runs tests is false however it is spelled: `npx playwright install &&
|
|
115
217
|
* npx playwright test` installs and runs, so a caller that sees `playwright test` in it is
|
|
116
|
-
* reading a real run.
|
|
218
|
+
* reading a real run. So is a command carrying a segment this reader cannot place (a script it
|
|
219
|
+
* does not know, which may start a suite): only the runners and the {@link NO_TEST_PROGRAMS}
|
|
220
|
+
* table can be accounted for, and "only prints" is a claim about the WHOLE command.
|
|
117
221
|
*
|
|
118
222
|
* @param command - The shell command as the executor sent it.
|
|
119
223
|
* @returns True when the command invokes a runner only to print.
|
|
@@ -123,9 +227,16 @@ export function commandRunsNoTests(command) {
|
|
|
123
227
|
return false;
|
|
124
228
|
let invocations = 0;
|
|
125
229
|
for (const segment of commandSegments(command.replace(HEREDOC, ' '))) {
|
|
126
|
-
|
|
127
|
-
|
|
230
|
+
// An own key only: `constructor` is a program name (`constructor --version`) and a
|
|
231
|
+
// prototype key is not a runner.
|
|
232
|
+
const runner = Object.hasOwn(RUNNERS, segment.program) ? RUNNERS[segment.program] : undefined;
|
|
233
|
+
if (runner === undefined) {
|
|
234
|
+
// A program this reader cannot place may start a suite of its own; only a known
|
|
235
|
+
// non-test program lets the command keep reading as "prints only".
|
|
236
|
+
if (!NO_TEST_PROGRAMS.has(segment.program))
|
|
237
|
+
return false;
|
|
128
238
|
continue;
|
|
239
|
+
}
|
|
129
240
|
invocations += 1;
|
|
130
241
|
if (!informational(runner, segment.args.join(' ')))
|
|
131
242
|
return false;
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA4K9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AA6ZD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA4K9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AA6ZD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAsHnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AA2ElF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAyvFxF"}
|