@jterrazz/test 12.1.0 → 13.0.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/README.md +16 -2
- package/dist/checker.js +587 -15
- package/dist/index.d.ts +194 -17
- package/dist/index.js +66 -1145
- package/dist/literate.js +1726 -0
- package/dist/match.js +73 -1
- package/dist/oxlint.cjs +168 -13
- package/dist/oxlint.js +168 -13
- package/dist/queue.js +3 -295
- package/dist/spec-document.js +536 -0
- package/dist/vitest.d.ts +41 -0
- package/dist/vitest.js +69 -0
- package/package.json +10 -4
- package/schema/spec.schema.json +179 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Scalar } from "yaml";
|
|
1
2
|
import { DeepMockProxy } from "vitest-mock-extended";
|
|
2
3
|
//#region src/core/matching/match.d.ts
|
|
3
4
|
/**
|
|
@@ -390,9 +391,20 @@ type CliEnv = Record<string, null | string>;
|
|
|
390
391
|
* Abstract command interface for specification runners.
|
|
391
392
|
* Implement this to plug in your command execution strategy.
|
|
392
393
|
*/
|
|
394
|
+
/**
|
|
395
|
+
* What one invocation is handed beyond its arguments — the two per-run inputs a
|
|
396
|
+
* spec document may state. Both are absent by default: the child gets an
|
|
397
|
+
* immediately-closed stdin (never a TTY) and the adapter's own timeout.
|
|
398
|
+
*/
|
|
399
|
+
interface CliInput {
|
|
400
|
+
/** Written to the child's stdin, which is then closed. */
|
|
401
|
+
stdin?: string;
|
|
402
|
+
/** Milliseconds after which the run is killed (exit code 124). */
|
|
403
|
+
timeout?: number;
|
|
404
|
+
}
|
|
393
405
|
interface CliPort {
|
|
394
406
|
/** Execute a command with the given arguments in the given working directory. */
|
|
395
|
-
exec: (args: string, cwd: string, env?: CliEnv) => Promise<CliOutput>;
|
|
407
|
+
exec: (args: string, cwd: string, env?: CliEnv, input?: CliInput) => Promise<CliOutput>;
|
|
396
408
|
/** Run a long-running process and wait for a pattern or timeout. */
|
|
397
409
|
watch: (args: string, cwd: string, options: ExecOptions, env?: CliEnv) => Promise<CliOutput>;
|
|
398
410
|
}
|
|
@@ -926,6 +938,49 @@ declare class HttpResult extends BaseResult {
|
|
|
926
938
|
get status(): number;
|
|
927
939
|
}
|
|
928
940
|
//#endregion
|
|
941
|
+
//#region src/core/specification/cli/literate.d.ts
|
|
942
|
+
/**
|
|
943
|
+
* Running a `<case>.spec.yaml` document: one scenario, one working directory,
|
|
944
|
+
* one set of servers, every run executed and asserted.
|
|
945
|
+
*
|
|
946
|
+
* The engine composes pieces that already exist rather than adding a second of
|
|
947
|
+
* anything — {@link copyPlan} for `fixture:`, the runner's own command adapter
|
|
948
|
+
* for each run, {@link ServeAdapter} for `serve:`, the `{{token}}` engine for
|
|
949
|
+
* every comparison, and {@link mergeTextPreservingPlaceholders} for the
|
|
950
|
+
* rewrite. What is new here is only the ORCHESTRATION the chain cannot express:
|
|
951
|
+
* several commands sharing one working directory, each asserted, none stopping
|
|
952
|
+
* the run.
|
|
953
|
+
*/
|
|
954
|
+
/**
|
|
955
|
+
* A server a document may start by name (`serve: mcp`), registered once per app
|
|
956
|
+
* in the `serve` option of `specification.cli()`.
|
|
957
|
+
*/
|
|
958
|
+
interface LiterateServeRegistration {
|
|
959
|
+
/** Shell command that starts the server, run from the project root. */
|
|
960
|
+
command: string;
|
|
961
|
+
/** The variable the resolved URL is bound to in every run's child env. */
|
|
962
|
+
env: string;
|
|
963
|
+
/**
|
|
964
|
+
* Matched against the server's output; the FIRST capture group is the port
|
|
965
|
+
* it chose — named (`(?<port>\d+)`) or not, it is group 1 either way.
|
|
966
|
+
*/
|
|
967
|
+
ready: RegExp;
|
|
968
|
+
/** Builds the URL bound to {@link env} from the announced port. */
|
|
969
|
+
url: (port: number) => string;
|
|
970
|
+
}
|
|
971
|
+
/** Per-call options for {@link runSpecDocument} / `cli.run()`. */
|
|
972
|
+
interface LiterateRunFlags {
|
|
973
|
+
/**
|
|
974
|
+
* Opt this document OUT of the update-mode rewrite. A frozen document is
|
|
975
|
+
* NEVER written under `TEST_UPDATE=1`: its mismatch still throws its diff.
|
|
976
|
+
* That is what makes a DELIBERATELY-WRONG `.spec.yaml` — one whose failure
|
|
977
|
+
* rendering is the subject of a negative test — survive an update run
|
|
978
|
+
* instead of being silently corrected into a passing file. The document's
|
|
979
|
+
* mirror of `toMatch(name, { frozen: true })`.
|
|
980
|
+
*/
|
|
981
|
+
frozen?: boolean;
|
|
982
|
+
}
|
|
983
|
+
//#endregion
|
|
929
984
|
//#region src/core/specification/mobile/result.d.ts
|
|
930
985
|
/** Result from a `.open()` action — the screen as the device saw it, final state. */
|
|
931
986
|
declare class ScreenResult extends BaseResult {
|
|
@@ -1135,13 +1190,25 @@ interface SpecificationConfig {
|
|
|
1135
1190
|
* facet factories auto-populate this when `dockerConfig` is present.
|
|
1136
1191
|
*/
|
|
1137
1192
|
dockerTestRunId?: string;
|
|
1193
|
+
/**
|
|
1194
|
+
* Named environment SETS a spec document may name by bare word
|
|
1195
|
+
* (`env: frozen`). Declared once per app in `specification.cli()`.
|
|
1196
|
+
*/
|
|
1197
|
+
envSets?: Record<string, CliEnv>;
|
|
1138
1198
|
/**
|
|
1139
1199
|
* When set, `.intercept()` is unavailable on this runner and throws this
|
|
1140
1200
|
* reason immediately (compose mode — MSW is in-process, CONVENTIONS I3).
|
|
1141
1201
|
*/
|
|
1142
1202
|
interceptDisabledReason?: string;
|
|
1143
1203
|
jobs?: JobHandle[];
|
|
1204
|
+
/** The project root — the working directory a document's `serve:` command runs from. */
|
|
1205
|
+
root?: string;
|
|
1144
1206
|
server?: ServerPort;
|
|
1207
|
+
/**
|
|
1208
|
+
* Named servers a spec document may start (`serve: [mcp]`). Declared once
|
|
1209
|
+
* per app in `specification.cli()`.
|
|
1210
|
+
*/
|
|
1211
|
+
serveRegistry?: Record<string, LiterateServeRegistration>;
|
|
1145
1212
|
/**
|
|
1146
1213
|
* The declared services record. In cli mode, drives the automatic
|
|
1147
1214
|
* connection-URL injection into the child env (CONVENTIONS B6):
|
|
@@ -1230,6 +1297,14 @@ interface CliSpecification<DatabaseKey extends string = string> {
|
|
|
1230
1297
|
* timeout.
|
|
1231
1298
|
*/
|
|
1232
1299
|
exec: (args?: string | string[], options?: ExecOptions) => Promise<CliResult>;
|
|
1300
|
+
/**
|
|
1301
|
+
* Run a `<case>.spec.yaml` document — its ground (fixtures, env sets,
|
|
1302
|
+
* servers) and every run, each asserted — and resolve with the LAST run's
|
|
1303
|
+
* result, so a `.test.ts` can add an assertion the document cannot express
|
|
1304
|
+
* (a directory golden, a grep). The path is relative to the test file's own
|
|
1305
|
+
* directory, where the document lives.
|
|
1306
|
+
*/
|
|
1307
|
+
run: (file: string, options?: LiterateRunFlags) => Promise<CliResult>;
|
|
1233
1308
|
}
|
|
1234
1309
|
/**
|
|
1235
1310
|
* The `website` facet — page chain entry handed out by
|
|
@@ -1561,6 +1636,20 @@ interface CliSpecificationOptions<Services extends ServiceRecord = ServiceRecord
|
|
|
1561
1636
|
* containers get force-removed at scope exit (CONVENTIONS B5).
|
|
1562
1637
|
*/
|
|
1563
1638
|
docker?: DockerSpecConfig;
|
|
1639
|
+
/**
|
|
1640
|
+
* Named environment SETS for literate `.cli` specs. A header line
|
|
1641
|
+
* `env: frozen` applies the whole `frozen` record; `$WORKDIR` expands and
|
|
1642
|
+
* `null` unsets, exactly as in `.env()`. Declared once per app so a
|
|
1643
|
+
* scenario file states WHICH ground it stands on, not how to build it.
|
|
1644
|
+
*/
|
|
1645
|
+
env?: Record<string, CliEnv>;
|
|
1646
|
+
/**
|
|
1647
|
+
* Named servers a literate `.cli` header may start (`serve: mcp KEY=value`).
|
|
1648
|
+
* Each entry names the shell `command`, the `ready` regex whose capture
|
|
1649
|
+
* group holds the port the server announces, the `url(port)` builder, and
|
|
1650
|
+
* the `env` variable that URL is bound to in every block's child.
|
|
1651
|
+
*/
|
|
1652
|
+
serve?: Record<string, LiterateServeRegistration>;
|
|
1564
1653
|
/**
|
|
1565
1654
|
* Project-root override (CONVENTIONS A9) — the single meaning of `root`:
|
|
1566
1655
|
* it anchors compose detection and local-bin resolution for the tested
|
|
@@ -1699,14 +1788,24 @@ interface MobileHandle {
|
|
|
1699
1788
|
declare function startMobile(options: MobileSpecificationOptions): Promise<MobileHandle>;
|
|
1700
1789
|
//#endregion
|
|
1701
1790
|
//#region src/core/specification/website/serve.adapter.d.ts
|
|
1702
|
-
/** Options for
|
|
1791
|
+
/** Options for a local server started by the framework. */
|
|
1703
1792
|
interface ServeOptions {
|
|
1704
1793
|
/** Shell command that starts the site. Receives the chosen port as `PORT`. */
|
|
1705
1794
|
command: string;
|
|
1706
1795
|
/** Fixed port. Default: an OS-assigned free port, injected as `PORT`. */
|
|
1707
1796
|
port?: number;
|
|
1708
|
-
/**
|
|
1709
|
-
|
|
1797
|
+
/**
|
|
1798
|
+
* How readiness is observed. Two forms:
|
|
1799
|
+
*
|
|
1800
|
+
* - a **path** (or nothing) — the framework picks the port, injects it as
|
|
1801
|
+
* `PORT`, and polls `<baseUrl><path>` until it answers any HTTP status
|
|
1802
|
+
* (default `/`). This is `specification.website()`'s form.
|
|
1803
|
+
* - a **regex over the child's output** with ONE capture group holding the
|
|
1804
|
+
* port the server chose itself. Nothing is injected as `PORT`: the server
|
|
1805
|
+
* announces its port and the framework reads it from the banner. This is
|
|
1806
|
+
* the form a literate `serve:` registration uses.
|
|
1807
|
+
*/
|
|
1808
|
+
ready?: RegExp | string;
|
|
1710
1809
|
/** Readiness budget in milliseconds. Default 30 000. */
|
|
1711
1810
|
timeout?: number;
|
|
1712
1811
|
}
|
|
@@ -1840,6 +1939,86 @@ declare const specification: {
|
|
|
1840
1939
|
website: typeof startWebsite;
|
|
1841
1940
|
};
|
|
1842
1941
|
//#endregion
|
|
1942
|
+
//#region src/core/literate/spec-document.d.ts
|
|
1943
|
+
/**
|
|
1944
|
+
* The facets a document may describe. `cli` is the only one implemented; the
|
|
1945
|
+
* key exists so a second facet can arrive without a second grammar.
|
|
1946
|
+
*/
|
|
1947
|
+
declare const SPEC_KINDS: readonly ["cli"];
|
|
1948
|
+
type SpecKind = (typeof SPEC_KINDS)[number];
|
|
1949
|
+
/** One `env:` entry — a bare word naming a registered set, or a `KEY=value` pair. */
|
|
1950
|
+
type SpecEnvToken = {
|
|
1951
|
+
key: string;
|
|
1952
|
+
kind: 'pair';
|
|
1953
|
+
line: number;
|
|
1954
|
+
value: string;
|
|
1955
|
+
} | {
|
|
1956
|
+
kind: 'set';
|
|
1957
|
+
line: number;
|
|
1958
|
+
name: string;
|
|
1959
|
+
};
|
|
1960
|
+
/** One `serve:` entry — a registered server plus the extra env it is started with. */
|
|
1961
|
+
interface SpecServeEntry {
|
|
1962
|
+
env: Record<string, string>;
|
|
1963
|
+
line: number;
|
|
1964
|
+
name: string;
|
|
1965
|
+
}
|
|
1966
|
+
/** One `fixture:` entry — a path with the line it was declared on. */
|
|
1967
|
+
interface SpecFixture {
|
|
1968
|
+
line: number;
|
|
1969
|
+
path: string;
|
|
1970
|
+
}
|
|
1971
|
+
/** An expected stream: its text, and the first line of that text in the file. */
|
|
1972
|
+
interface SpecStream {
|
|
1973
|
+
/** 1-based line the scalar's content starts on — where a token defect is reported. */
|
|
1974
|
+
line: number;
|
|
1975
|
+
text: string;
|
|
1976
|
+
}
|
|
1977
|
+
/** One `files:` assertion, keyed by a workdir-relative path. */
|
|
1978
|
+
type SpecFileAssertion = {
|
|
1979
|
+
contains: SpecStream[];
|
|
1980
|
+
equals: null | SpecStream;
|
|
1981
|
+
kind: 'content';
|
|
1982
|
+
line: number;
|
|
1983
|
+
path: string;
|
|
1984
|
+
} | {
|
|
1985
|
+
kind: 'absent';
|
|
1986
|
+
line: number;
|
|
1987
|
+
path: string;
|
|
1988
|
+
} | {
|
|
1989
|
+
kind: 'exists';
|
|
1990
|
+
line: number;
|
|
1991
|
+
path: string;
|
|
1992
|
+
};
|
|
1993
|
+
/** One run: a command, what it must exit with, and what it must have produced. */
|
|
1994
|
+
interface SpecRun {
|
|
1995
|
+
command: string;
|
|
1996
|
+
/** 1-based line of the `command:` key — the frame a failure points at. */
|
|
1997
|
+
commandLine: number;
|
|
1998
|
+
exitCode: number;
|
|
1999
|
+
files: SpecFileAssertion[];
|
|
2000
|
+
/** `null` when the key is absent, which asserts an empty stream. */
|
|
2001
|
+
stderr: null | SpecStream;
|
|
2002
|
+
/** Written to the child then closed; `null` keeps the empty-pipe EOF. */
|
|
2003
|
+
stdin: null | string;
|
|
2004
|
+
stdout: null | SpecStream;
|
|
2005
|
+
timeout: null | number;
|
|
2006
|
+
/** Only ever on the LAST run — a long-running command ends the session. */
|
|
2007
|
+
waitFor: null | string;
|
|
2008
|
+
}
|
|
2009
|
+
/** A parsed `<case>.spec.yaml`. */
|
|
2010
|
+
interface SpecDocument {
|
|
2011
|
+
/** The vitest test title. */
|
|
2012
|
+
description: string;
|
|
2013
|
+
/** 1-based line of the `description:` key. */
|
|
2014
|
+
descriptionLine: number;
|
|
2015
|
+
env: SpecEnvToken[];
|
|
2016
|
+
fixtures: SpecFixture[];
|
|
2017
|
+
kind: SpecKind;
|
|
2018
|
+
runs: SpecRun[];
|
|
2019
|
+
serve: SpecServeEntry[];
|
|
2020
|
+
}
|
|
2021
|
+
//#endregion
|
|
1843
2022
|
//#region src/integrations/docker/docker-lookup.d.ts
|
|
1844
2023
|
/** Return all container IDs (running or stopped) that carry `key=value`. */
|
|
1845
2024
|
declare function findContainersByLabel(key: string, value: string): string[];
|
|
@@ -2262,7 +2441,7 @@ declare const mockOfDate: MockDatePort;
|
|
|
2262
2441
|
//#endregion
|
|
2263
2442
|
//#region src/index.d.ts
|
|
2264
2443
|
declare module 'vitest' {
|
|
2265
|
-
interface
|
|
2444
|
+
interface Assertion<T = any> {
|
|
2266
2445
|
/**
|
|
2267
2446
|
* Assert the subject is empty — zero rows for a table (async), an
|
|
2268
2447
|
* empty stream for a text accessor (console, errors, stdout).
|
|
@@ -2272,17 +2451,6 @@ declare module 'vitest' {
|
|
|
2272
2451
|
} ? () => Promise<void> : never;
|
|
2273
2452
|
/** Assert the container is running. Async — docker-backed subject. */
|
|
2274
2453
|
toBeRunning: T extends ContainerAccessor ? () => Promise<void> : never;
|
|
2275
|
-
/**
|
|
2276
|
-
* Assert the table contains exactly the given rows for the given
|
|
2277
|
-
* columns. Cells accept `match.*` dynamic-value matchers. Async —
|
|
2278
|
-
* queries the database.
|
|
2279
|
-
*/
|
|
2280
|
-
toMatchRows: T extends TableAccessor ? (expected: {
|
|
2281
|
-
columns: string[];
|
|
2282
|
-
rows: readonly (readonly unknown[])[];
|
|
2283
|
-
}) => Promise<void> : never;
|
|
2284
|
-
}
|
|
2285
|
-
interface Assertion<T = any> {
|
|
2286
2454
|
/**
|
|
2287
2455
|
* On `@jterrazz/test` accessors: assert the subject matches a fixture
|
|
2288
2456
|
* file under `expected/<name>` (flat — a slash creates a subfolder;
|
|
@@ -2297,7 +2465,16 @@ declare module 'vitest' {
|
|
|
2297
2465
|
* the behaviour under test.
|
|
2298
2466
|
*/
|
|
2299
2467
|
toMatch: T extends DirectoryAccessor | FilesystemAccessor ? (name: RegExp | string, options?: MatchFixtureOptions) => Promise<void> : T extends JsonAccessor | ResponseAccessor | TextAccessor ? (name: RegExp | string, options?: MatchFixtureOptions) => void : (expected: RegExp | string, options?: MatchFixtureOptions) => void;
|
|
2468
|
+
/**
|
|
2469
|
+
* Assert the table contains exactly the given rows for the given
|
|
2470
|
+
* columns. Cells accept `match.*` dynamic-value matchers. Async —
|
|
2471
|
+
* queries the database.
|
|
2472
|
+
*/
|
|
2473
|
+
toMatchRows: T extends TableAccessor ? (expected: {
|
|
2474
|
+
columns: string[];
|
|
2475
|
+
rows: readonly (readonly unknown[])[];
|
|
2476
|
+
}) => Promise<void> : never;
|
|
2300
2477
|
}
|
|
2301
2478
|
}
|
|
2302
2479
|
//#endregion
|
|
2303
|
-
export { type ApiHandle, type ApiSpecification, type ApiSpecificationOptions, BaseResult, type BrowserConsoleMessage, type BrowserLinkElement, type BrowserMetaElement, type BrowserOpenOptions, type BrowserPage, type BrowserPort, type CaptureScope, type CliEnv, type CliHandle, type CliOutput, type CliPort, CliResult, type CliSpecification, type CliSpecificationOptions, ContainerAccessor, type ContainerPort, type Contract, type ContractInput, type ContractRequest, type ContractResponder, type ContractResponse, type ContractResponseValue, type Contracts, type DatabaseKeys, type DatabasePort, type DeviceOpenOptions, type DevicePort, type DeviceScreen, DirectoryAccessor, type DockerSpecConfig, type ElementKind, type ElementMatch, type ElementOptions, type ElementRef, type ExecOptions, FetchResult, type FileAccessor, FilesystemAccessor, type HonoApp, type HttpContractFilter, type HttpResponseInit, HttpResult, type IsolationStrategy, type JobHandle, type JobsHandle, type JobsSpecification, type JobsSpecificationOptions, JsonAccessor, type LandmarkKind, type MatchFixtureOptions, type MatchableRequest, Matcher, type MatcherKind, type MobileBackendOptions, type MobileElementKind, type MobileElementMatch, type MobileElementRef, type MobileHandle, type MobileScenario, type MobileSpecification, type MobileSpecificationOptions, type MobileVisitor, type MockDatePort, type MockPort, Orchestrator, PageResult, type PostgresOptions, type RedisOptions, ResponseAccessor, type ScreenNode, ScreenResult, type ServeOptions, type ServerPort, type ServerResponse, type ServiceHandle, type ServiceRecord, type SpecificationConfig, type SpecificationMode, type SqliteOptions, TableAccessor, TextAccessor, type TextFilter, type VisitScenario, type Visitor, type WebsiteBackendOptions, type WebsiteHandle, type WebsiteSpecification, type WebsiteSpecificationOptions, anthropic, banner, button, complementary, content, contentinfo, defineContract, defineContracts, field, findContainersByLabel, form, heading, http, inspectContainer, link, main, match, mockOf, mockOfDate, navigation, openai, postgres, redis, region, removeContainers, search, specification, sqlite, testId, text, within };
|
|
2480
|
+
export { type ApiHandle, type ApiSpecification, type ApiSpecificationOptions, BaseResult, type BrowserConsoleMessage, type BrowserLinkElement, type BrowserMetaElement, type BrowserOpenOptions, type BrowserPage, type BrowserPort, type CaptureScope, type CliEnv, type CliHandle, type CliInput, type CliOutput, type CliPort, CliResult, type CliSpecification, type CliSpecificationOptions, ContainerAccessor, type ContainerPort, type Contract, type ContractInput, type ContractRequest, type ContractResponder, type ContractResponse, type ContractResponseValue, type Contracts, type DatabaseKeys, type DatabasePort, type DeviceOpenOptions, type DevicePort, type DeviceScreen, DirectoryAccessor, type DockerSpecConfig, type ElementKind, type ElementMatch, type ElementOptions, type ElementRef, type ExecOptions, FetchResult, type FileAccessor, FilesystemAccessor, type HonoApp, type HttpContractFilter, type HttpResponseInit, HttpResult, type IsolationStrategy, type JobHandle, type JobsHandle, type JobsSpecification, type JobsSpecificationOptions, JsonAccessor, type LandmarkKind, type LiterateRunFlags, type LiterateServeRegistration, type MatchFixtureOptions, type MatchableRequest, Matcher, type MatcherKind, type MobileBackendOptions, type MobileElementKind, type MobileElementMatch, type MobileElementRef, type MobileHandle, type MobileScenario, type MobileSpecification, type MobileSpecificationOptions, type MobileVisitor, type MockDatePort, type MockPort, Orchestrator, PageResult, type PostgresOptions, type RedisOptions, ResponseAccessor, type ScreenNode, ScreenResult, type ServeOptions, type ServerPort, type ServerResponse, type ServiceHandle, type ServiceRecord, type SpecDocument, type SpecEnvToken, type SpecFileAssertion, type SpecFixture, type SpecKind, type SpecRun, type SpecServeEntry, type SpecStream, type SpecificationConfig, type SpecificationMode, type SqliteOptions, TableAccessor, TextAccessor, type TextFilter, type VisitScenario, type Visitor, type WebsiteBackendOptions, type WebsiteHandle, type WebsiteSpecification, type WebsiteSpecificationOptions, anthropic, banner, button, complementary, content, contentinfo, defineContract, defineContracts, field, findContainersByLabel, form, heading, http, inspectContainer, link, main, match, mockOf, mockOfDate, navigation, openai, postgres, redis, region, removeContainers, search, specification, sqlite, testId, text, within };
|