@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/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 the local server started by `specification.website()`. */
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
- /** Path polled until it answers with any HTTP status. Default `/`. */
1709
- ready?: string;
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 Matchers<T = any> {
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 };