@luckystack/test-runner 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/CLAUDE.md +20 -7
- package/README.md +5 -3
- package/dist/index.d.ts +210 -22
- package/dist/index.js +560 -304
- package/dist/index.js.map +1 -1
- package/docs/auth-tests.md +2 -2
- package/docs/contract-tests.md +21 -7
- package/docs/extension-hooks.md +12 -5
- package/docs/fuzz-tests.md +3 -3
- package/docs/rate-limit-tests.md +13 -5
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,27 @@ All notable changes to `@luckystack/test-runner` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.10.2] - 2026-10-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- The auto-sweep layers (contract, auth, rate-limit, CSRF, fuzz) now cover sync routes when `runAllTests` receives the generated `syncMetaMap` (+ optionally `syncInputSchemas` for Zod-valid sync payloads). Sync probes travel over Socket.io — the pipeline real clients use — unless the project's `transport.invocation` is `routed-http` or `syncTransport: 'http'` is set; the CSRF layer always probes sync over HTTP, since CSRF is an HTTP-only guard. Each run uses one throwaway `lstest-room-<uuid>` room, which the sweep session joins when an `authToken` is given, so room-membership enforcement sees a member. Without `syncMetaMap`, `runAllTests` warns that sync routes are not swept.
|
|
13
|
+
- New exports: `createHttpProbeTransport`, `createSocketProbeTransport`, `defaultProbeTransport`, `sendProbe` and the `ProbeTransport` family of types; `createSampleInputFor` + `InputSchemaMap`; `SyncMetaMap` / `SyncMetaEntry`; `CallSyncOptions`. `EndpointDescriptor` gains an optional `kind` (`walkSyncEndpoints` sets `'sync'`; absent means API).
|
|
14
|
+
- `runAllTests` writes the full summary JSON itself: `outputFile` option, defaulting to `TEST_OUTPUT_FILE`, else `test-results.json`; `false` disables it. Entry scripts no longer need their own write.
|
|
15
|
+
- `resetServerState` accepts `only?: TestResetTarget[]` to clear just those targets (`/_test/reset?only=`).
|
|
16
|
+
- Registered custom layers receive `sampleInput` in `TestLayerInput` (the same Zod-valid payload the contract sweep sends), and `runRegisteredLayers` accepts `syncMetaMap`, `filter`, `apiInputSchemas`, `syncInputSchemas` and `inputFor`. `method` is `undefined` for sync endpoints.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`ctx.callSync` follows the project's `transport.invocation`.** For a socket-mode project (the default) it now emits a real Socket.io `sync` instead of always posting to `/sync/*`, and the case's socket joins `opts.receiver` first (except `'all'`; opt out with `joinRoom: false`). Override per call with `opts.transport: 'http'`. New `opts.ignoreSelf`. A test that relied on HTTP-only behaviour in a socket-mode project must pass `transport: 'http'`.
|
|
21
|
+
- **The runner's own resets no longer clear sessions.** The `runAllTests` bookends and the rate-limit layer's between-endpoint reset send `only=rateLimits`, so an authenticated sweep is no longer logged out by its own reset. A direct `resetServerState` call without `only` still clears sessions as before.
|
|
22
|
+
- `filter` (`TEST_FILTER`) is passed to every layer and applied before any request. Previously every route was swept and only the report was filtered.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- GET routes receive their sample payload: probes encode it into the reserved `__luckystack_data` query key (core `buildRoutedGetUrl`) instead of dropping it, so a GET route with a required field no longer fails validation in every layer.
|
|
27
|
+
- Sockets the runner opens on the caller's `authToken` session (the sync-sweep member socket and the socket probe transport) close with `intentionalDisconnect`, the signal a real client sends on a tab switch. With `@luckystack/presence` installed, a plain close made presence log that session out a few seconds after the sweep.
|
|
28
|
+
- The bookend documentation no longer claims the reset drops rows the sweep created. `/_test/reset` never touched the application database; `lstest_*` rows persist.
|
|
9
29
|
|
|
10
30
|
## [0.10.1] - 2026-09-03
|
|
11
31
|
|
package/CLAUDE.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## What this package does
|
|
6
6
|
|
|
7
|
-
Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit de generated `apiMethodMap` en draait vijf progressive layers: contract smoke (Zod-valid input), auth enforcement, rate-limit, crash-resistance fuzz, en per-route custom tests (`<name>_v<N>.tests.ts` naast `_api/`/`_sync/` sources). Elke layer is independent runnable; `runAllTests` orchestreert alles in volgorde en levert een geaggregeerde summary op. Reporter/fixture/layer-extension registries laten consumers eigen checks plug-in zonder de framework te forken.
|
|
7
|
+
Generated-type-driven test layers voor LuckyStack APIs en sync routes. Walkt elke endpoint uit de generated `apiMethodMap` (plus elke sync route uit `syncMetaMap` wanneer die wordt meegegeven) en draait vijf progressive layers: contract smoke (Zod-valid input), auth enforcement, rate-limit, crash-resistance fuzz, en per-route custom tests (`<name>_v<N>.tests.ts` naast `_api/`/`_sync/` sources). Elke layer is independent runnable; `runAllTests` orchestreert alles in volgorde en levert een geaggregeerde summary op. Reporter/fixture/layer-extension registries laten consumers eigen checks plug-in zonder de framework te forken.
|
|
8
8
|
|
|
9
9
|
## When to USE this package
|
|
10
10
|
|
|
@@ -20,17 +20,22 @@ Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit
|
|
|
20
20
|
- Voor frontend-UI tests — gebruik Playwright/`webapp-testing` skill, deze runner is server-only.
|
|
21
21
|
- Wanneer er geen generated `apiMethodMap` beschikbaar is (project gebruikt geen `@luckystack/devkit`).
|
|
22
22
|
- Wanneer de target server productie is — fuzz/rate-limit layers maken honderden requests en `/_test/reset` bestaat alleen bij exact `NODE_ENV=development|test` plus een verplicht `TEST_RESET_TOKEN`.
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
Sync routes: de auto-sweep layers dekken ze alleen wanneer `runAllTests` de generated `syncMetaMap` (+ optioneel `syncInputSchemas`) krijgt; zonder `syncMetaMap` logt `runAllTests` een waarschuwing dat sync routes niet geswept worden. Sync probes gaan over Socket.io (de pipeline van echte clients) tenzij het project `routed-http` is of `syncTransport: 'http'` gezet is; de CSRF-layer probet sync altijd over HTTP. Per run één wegwerp-room; met een `authToken` joint de sweep-sessie die room zodat room-membership-enforcement een member ziet.
|
|
24
25
|
|
|
25
26
|
## Function Index
|
|
26
27
|
|
|
27
28
|
| Function / Export | 1-regel | Deep doc |
|
|
28
29
|
|---|---|---|
|
|
29
|
-
| `runAllTests({ apiMethodMap, apiMetaMap, apiInputSchemas, baseUrl, ... })` | Orchestrator: draait contract + auth + rate-limit + fuzz + custom (Layer 5) in volgorde, levert een `RunAllTestsSummary`. | → docs/contract-tests.md |
|
|
30
|
+
| `runAllTests({ apiMethodMap, apiMetaMap, apiInputSchemas, syncMetaMap?, syncInputSchemas?, baseUrl, ... })` | Orchestrator: draait contract + auth + rate-limit + csrf + fuzz + custom (Layer 5) in volgorde, levert een `RunAllTestsSummary` en schrijft die als JSON naar `outputFile`. `filter` wordt vóór de requests toegepast. | → docs/contract-tests.md |
|
|
30
31
|
| `runCustomTests(input)` | Layer 5: draait per-route tests. Direct callers moeten lazy `loadProjectConfig` meegeven; env/secrets resolven vóór test-module imports. `runAllTests` gebruikt een interne already-prepared entrypoint om pointer-reload te voorkomen. | → docs/contract-tests.md |
|
|
31
32
|
| `discoverCustomTestFiles(srcDir?)` | Walker die elke `<name>_v<N>.tests.ts` onder de configured src dir yields. | → docs/contract-tests.md |
|
|
32
33
|
| `logRunAllSummary(summary)` | Pretty-print één `RunAllTestsSummary`. | → docs/extension-hooks.md |
|
|
33
34
|
| `walkEndpoints(apiMethodMap)` | Genereert `EndpointDescriptor[]` uit de generated map | → docs/contract-tests.md |
|
|
35
|
+
| `walkSyncEndpoints(syncMap)` | Zelfde voor sync routes (`syncMetaMap` of `syncMethodMap`); descriptors krijgen `kind: 'sync'` | → docs/contract-tests.md |
|
|
36
|
+
| `sendProbe(input)` / `createHttpProbeTransport(opts?)` / `defaultProbeTransport` | Eén HTTP-probe (GET-payload in de `__luckystack_data` query) / transport die API- en `/sync/*`-routes over HTTP bereikt | → docs/contract-tests.md |
|
|
37
|
+
| `createSocketProbeTransport(opts)` | Transport die sync probes als Socket.io `sync` emit verstuurt | → docs/contract-tests.md |
|
|
38
|
+
| `createSampleInputFor({ apiInputSchemas?, syncInputSchemas?, stringPrefix? })` | `inputFor`-factory: Zod-valid sample per API- of sync-route | → docs/contract-tests.md |
|
|
34
39
|
| `runContractCheck({ endpoint, baseUrl, inputFor?, headers? })` | Single-endpoint contract smoke | → docs/contract-tests.md |
|
|
35
40
|
| `runContractTests({ apiMethodMap, baseUrl, skip?, inputFor?, headers?, onResult? })` | Full sweep contract layer | → docs/contract-tests.md |
|
|
36
41
|
| `runAuthEnforcementCheck({ endpoint, baseUrl, inputFor? })` | Single-endpoint auth check (verwacht 401 zonder token) | → docs/auth-tests.md |
|
|
@@ -39,7 +44,7 @@ Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit
|
|
|
39
44
|
| `runRateLimitTests({ apiMethodMap, apiMetaMap, baseUrl, skip?, inputFor?, headers?, maxRateLimitToTest?, resetBetweenEndpoints?, resetToken?, onResult? })` | Sweep alle `rateLimit: N` endpoints | → docs/rate-limit-tests.md |
|
|
40
45
|
| `runFuzzCheck({ endpoint, baseUrl, headers? })` | Single-endpoint crash-resistance fuzz | → docs/fuzz-tests.md |
|
|
41
46
|
| `runFuzzTests({ apiMethodMap, baseUrl, skip?, headers?, onResult? })` | Sweep fuzz layer (nightly CI) | → docs/fuzz-tests.md |
|
|
42
|
-
| `resetServerState({ baseUrl, token? })` | POST naar `/_test/reset`
|
|
47
|
+
| `resetServerState({ baseUrl, token?, only? })` | POST naar `/_test/reset`. Zonder `only` wist hij rate limits + standaard Redis-sessienamespaces; met `only` alleen de genoemde targets (de runner stuurt altijd `only: ['rateLimits']`). Nooit app-DB/custom adapters | → docs/rate-limit-tests.md |
|
|
43
48
|
| `resolveTestBaseUrl({ cwd?, fallbackUrl? })` | Resolves `TEST_BASE_URL` → actually-bound dev port advertisement → caller fallback, so an auto-hop does not create false connection failures. | → docs/contract-tests.md |
|
|
44
49
|
| `resolveTestEnvironment({ loadProjectConfig? })` | Laadt `.env`-lagen en resolveert optionele secret-manager-pointers in het testproces vóór DB/Redis-backed Layer-5 modules importeren. | → docs/contract-tests.md |
|
|
45
50
|
| `sampleSchemaInput(schema, options?)` | Genereert Zod-valid sample payload uit een schema. `options.stringPrefix` tagt UNCONSTRAINED strings (finding #98) — format/checked strings blijven ongeprefixt zodat ze valid blijven. | → docs/contract-tests.md |
|
|
@@ -53,7 +58,10 @@ Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit
|
|
|
53
58
|
| `registerTestReporter(reporter)` | Plug-in onResult/onSummary/webhookUrl callbacks | → docs/extension-hooks.md |
|
|
54
59
|
| `getTestReporter()` | Lees actieve reporter callbacks | → docs/extension-hooks.md |
|
|
55
60
|
| `resetTestExtensionsForTests()` | Clear alle registries (alleen voor interne tests) | → docs/extension-hooks.md |
|
|
56
|
-
| Type: `EndpointDescriptor` | `{ page, name, version, method, fullPath }` | → docs/contract-tests.md |
|
|
61
|
+
| Type: `EndpointDescriptor` | `{ page, name, version, method, fullPath, kind? }` — `kind` ontbreekt = `'api'` | → docs/contract-tests.md |
|
|
62
|
+
| Type: `SyncMetaMap` / `SyncMetaEntry` | Spiegel van de generated `syncMetaMap` (auth + rateLimit per sync route) | → docs/contract-tests.md |
|
|
63
|
+
| Type: `ProbeTransport` / `ProbeTransportRequest` / `ProbeRequestInput` / `ProbeResponse` / `HttpProbeTransportOptions` / `SocketProbeTransportOptions` | Probe-transport contract | → docs/contract-tests.md |
|
|
64
|
+
| Type: `InputSchemaMap` / `CreateSampleInputForOptions` | Inputs voor `createSampleInputFor` | → docs/contract-tests.md |
|
|
57
65
|
| Type: `HttpMethod` | `'GET' \| 'POST' \| 'PUT' \| 'DELETE'` | → docs/contract-tests.md |
|
|
58
66
|
| Type: `ContractCheckResult` | Single-result shape (status, httpStatus, responseStatus, errorCode, reason, durationMs) | → docs/contract-tests.md |
|
|
59
67
|
| Type: `RunContractSummary` | Aggregate shape (total, passed, failed, skipped, results[]) | → docs/contract-tests.md |
|
|
@@ -66,7 +74,8 @@ Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit
|
|
|
66
74
|
| Type: `RunRateLimitTestsInput` / `RateLimitCheckInput` | Inputs voor rate-limit layer | → docs/rate-limit-tests.md |
|
|
67
75
|
| Type: `RunFuzzTestsInput` / `FuzzCheckInput` | Inputs voor fuzz layer | → docs/fuzz-tests.md |
|
|
68
76
|
| Type: `ResetServerStateInput` | Input voor `resetServerState` | → docs/rate-limit-tests.md |
|
|
69
|
-
| Type: `TestContext` | `{ callApi, callSync, watchStream, session, prisma, expect }` — handed naar elke Layer-5 custom-tests case. | → docs/contract-tests.md |
|
|
77
|
+
| Type: `TestContext` | `{ callApi, callSync, watchStream, session, prisma, expect }` — handed naar elke Layer-5 custom-tests case. `callSync` volgt `transport.invocation` van het project (`socket` → echte Socket.io emit, `routed-http` → `/sync/*`). | → docs/contract-tests.md |
|
|
78
|
+
| Type: `CallSyncOptions` | `callSync` opts: `receiver`, `ignoreSelf`, `transport` (per-call override), `joinRoom` (default `true`: de case-socket joint eerst `receiver`) | → docs/contract-tests.md |
|
|
70
79
|
| `ctx.watchStream(roomCode)` | Open een second-socket (socket B) joined aan `roomCode` om de chunk stream van `broadcastStream`/`streamTo`/`_client_v{N}` te observeren. Returnt `StreamWatcher<TChunk>` met `.chunks[]`, `.stopAt(predicate, timeoutMs?)`, `.waitForCount(n, timeoutMs?)`, `.close()`. Watchers worden auto-closed na elke case. | → docs/contract-tests.md |
|
|
71
80
|
| `openStreamWatcher(input)` | Lower-level factory voor `watchStream` — direct bruikbaar buiten een `TestContext` (custom layers, ad-hoc harness scripts). | → docs/contract-tests.md |
|
|
72
81
|
| Type: `StreamWatcher<TChunk>` | `{ readonly chunks, stopAt, waitForCount, close }` — observable chunk stream voor één route. | → docs/contract-tests.md |
|
|
@@ -84,7 +93,11 @@ Generated-type-driven test layers voor LuckyStack APIs. Walkt elke endpoint uit
|
|
|
84
93
|
- `TEST_RESET_TOKEN` (env, optional, server-side) — wanneer gezet moet `resetServerState({ token })` deze meesturen als `X-Test-Reset-Token`. Verplicht voor staging/preview deploys die het endpoint over het netwerk exposen.
|
|
85
94
|
- `RunRateLimitTestsInput.maxRateLimitToTest` (default `50`) — endpoints met hogere `rateLimit` worden geskipt om duizenden requests in CI te vermijden.
|
|
86
95
|
- `RunRateLimitTestsInput.resetBetweenEndpoints` (default `false`) — hit `/_test/reset` voor elke endpoint zodat het shared IP-bucket schoon is.
|
|
87
|
-
- `RunAllTestsInput.resetBookends` (default `true` wanneer een reset-token beschikbaar is) — POST `/_test/reset` één keer vóór en één keer ná de auto-sweep
|
|
96
|
+
- `RunAllTestsInput.resetBookends` (default `true` wanneer een reset-token beschikbaar is) — POST `/_test/reset?only=rateLimits` één keer vóór en één keer ná de auto-sweep, zodat geen limiter-bucket leeggelopen achterblijft. Wist alleen limiter-state: sessies (ook die van `authToken`) blijven staan, en de app-database wordt nooit aangeraakt — door de sweep aangemaakte `lstest_*` rows blijven dus bestaan. Zonder token (`resetToken`/`TEST_RESET_TOKEN`) worden de bookends met een logregel geskipt, niet gefaald.
|
|
97
|
+
- `RunAllTestsInput.outputFile` (default `TEST_OUTPUT_FILE` env, anders `test-results.json`; `false` = uit) — `runAllTests` schrijft de volledige summary-JSON zelf; een entry-script hoeft dat niet meer te doen.
|
|
98
|
+
- `RunAllTestsInput.syncMetaMap` / `syncInputSchemas` — generated door devkit; zonder `syncMetaMap` worden sync routes niet geswept.
|
|
99
|
+
- `RunAllTestsInput.syncTransport` (`'socket' | 'http'`, default afgeleid van `transport.invocation`) — hoe de sweep sync routes bereikt.
|
|
100
|
+
- `RunAllTestsInput.filter` (het `testAll.ts` entry-script vult hem uit `TEST_FILTER`) — substring op `<page>/<name>/<version>`; niet-matchende routes worden niet aangevraagd (niet alleen uit het rapport gefilterd).
|
|
88
101
|
- `registerTestLayer({ name, run })` — custom check per endpoint (CORS, business rules, custom auth-schemes, multi-tenant isolation).
|
|
89
102
|
- `registerTestFixture(typeKey, { valid, invalid })` — realistic payloads die de fuzz layer prefereert boven schema-random.
|
|
90
103
|
- `registerTestReporter({ onResult?, onSummary?, webhookUrl?, webhookAuth? })` — wire per-result/per-summary callbacks of POST de summary naar een webhook.
|
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ import {
|
|
|
18
18
|
resolveTestBaseUrl,
|
|
19
19
|
logRunAllSummary,
|
|
20
20
|
} from '@luckystack/test-runner';
|
|
21
|
-
import { apiInputSchemas } from './src/_sockets/apiInputSchemas.generated';
|
|
22
|
-
import { apiMetaMap, apiMethodMap } from './src/_sockets/apiTypes.generated';
|
|
21
|
+
import { apiInputSchemas, syncInputSchemas } from './src/_sockets/apiInputSchemas.generated';
|
|
22
|
+
import { apiMetaMap, apiMethodMap, syncMetaMap } from './src/_sockets/apiTypes.generated';
|
|
23
23
|
import { ports } from './config.ports';
|
|
24
24
|
|
|
25
25
|
const baseUrl = resolveTestBaseUrl({ fallbackUrl: `http://localhost:${ports.backend}` });
|
|
@@ -27,6 +27,8 @@ const summary = await runAllTests({
|
|
|
27
27
|
apiMethodMap,
|
|
28
28
|
apiMetaMap,
|
|
29
29
|
apiInputSchemas,
|
|
30
|
+
syncMetaMap, // omit and sync routes are not swept (a warning says so)
|
|
31
|
+
syncInputSchemas,
|
|
30
32
|
baseUrl,
|
|
31
33
|
// Loaded only after .env/.env.local. If config.secretManager.url is set,
|
|
32
34
|
// pointers are resolved in THIS process before Layer-5 tests touch Prisma.
|
|
@@ -52,7 +54,7 @@ The fuzz layer is intentionally exhaustive and slow — wire it into nightly CI
|
|
|
52
54
|
|
|
53
55
|
## Server hooks it depends on
|
|
54
56
|
|
|
55
|
-
- `/_test/reset` endpoint — served by `@luckystack/server` only when `NODE_ENV` is exactly `development` or `test`, and always gated by a non-empty `TEST_RESET_TOKEN`. `resetServerState` clears framework rate-limit state plus the default Redis session/active-user namespaces; it does not clear application database rows or custom `SessionAdapter` stores.
|
|
57
|
+
- `/_test/reset` endpoint — served by `@luckystack/server` only when `NODE_ENV` is exactly `development` or `test`, and always gated by a non-empty `TEST_RESET_TOKEN`. `resetServerState` clears framework rate-limit state plus the default Redis session/active-user namespaces, or only the targets passed as `only` (the runner's own resets clear rate limits only, so an authenticated sweep keeps its session); it does not clear application database rows or custom `SessionAdapter` stores.
|
|
56
58
|
- `apiMethodMap.generated.ts` — produced by `@luckystack/devkit` from your `_api/*` files. Defaults are read via `getApiMethodMapPath()` from `@luckystack/core`.
|
|
57
59
|
|
|
58
60
|
## Public API
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { TestResetTarget, getPrismaClient } from '@luckystack/core';
|
|
2
|
+
import { ZodType, z } from 'zod';
|
|
3
3
|
|
|
4
4
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
5
5
|
type ApiMethodMap$1 = Partial<Record<string, Partial<Record<string, Partial<Record<string, string>>>>>>;
|
|
@@ -14,13 +14,20 @@ interface ApiMetaEntry {
|
|
|
14
14
|
rateLimit?: number | false;
|
|
15
15
|
}
|
|
16
16
|
type ApiMetaMap = Partial<Record<string, Partial<Record<string, Partial<Record<string, ApiMetaEntry>>>>>>;
|
|
17
|
+
interface SyncMetaEntry {
|
|
18
|
+
auth: ApiMetaEntry['auth'];
|
|
19
|
+
rateLimit?: number | false;
|
|
20
|
+
}
|
|
21
|
+
type SyncMetaMap = Partial<Record<string, Partial<Record<string, Partial<Record<string, SyncMetaEntry>>>>>>;
|
|
17
22
|
interface EndpointDescriptor {
|
|
18
23
|
page: string;
|
|
19
24
|
name: string;
|
|
20
25
|
version: string;
|
|
21
26
|
method: HttpMethod;
|
|
22
|
-
/** `api/<page>/<name>/<version>` */
|
|
27
|
+
/** `api/<page>/<name>/<version>` or `sync/<page>/<name>/<version>` */
|
|
23
28
|
fullPath: string;
|
|
29
|
+
/** Route kind. Absent means `'api'` — only `walkSyncEndpoints` sets `'sync'`. */
|
|
30
|
+
kind?: 'api' | 'sync';
|
|
24
31
|
}
|
|
25
32
|
interface ContractCheckResult {
|
|
26
33
|
endpoint: EndpointDescriptor;
|
|
@@ -41,7 +48,56 @@ interface RunContractSummary {
|
|
|
41
48
|
|
|
42
49
|
type ApiMethodMap = Partial<Record<string, Partial<Record<string, Partial<Record<string, string>>>>>>;
|
|
43
50
|
declare const walkEndpoints: (apiMethodMap: ApiMethodMap) => EndpointDescriptor[];
|
|
44
|
-
|
|
51
|
+
type SyncRouteMap = Partial<Record<string, Partial<Record<string, Partial<Record<string, unknown>>>>>>;
|
|
52
|
+
declare const walkSyncEndpoints: (syncMap: SyncMethodMap | SyncMetaMap | SyncRouteMap) => EndpointDescriptor[];
|
|
53
|
+
|
|
54
|
+
interface ProbeRequestInput {
|
|
55
|
+
url: string;
|
|
56
|
+
method: HttpMethod;
|
|
57
|
+
baseUrl: string;
|
|
58
|
+
body?: unknown;
|
|
59
|
+
headers?: Record<string, string>;
|
|
60
|
+
requestTimeoutMs: number;
|
|
61
|
+
}
|
|
62
|
+
interface ProbeResponse {
|
|
63
|
+
/** HTTP status. Absent when the probe travelled over Socket.io. */
|
|
64
|
+
httpStatus?: number;
|
|
65
|
+
parsed: {
|
|
66
|
+
status?: string;
|
|
67
|
+
errorCode?: string;
|
|
68
|
+
} | null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Send a single timed fetch probe and parse the JSON envelope. Returns
|
|
72
|
+
* `null` when the request itself fails (network error or abort).
|
|
73
|
+
*/
|
|
74
|
+
declare const sendProbe: (input: ProbeRequestInput) => Promise<ProbeResponse | null>;
|
|
75
|
+
interface ProbeTransportRequest {
|
|
76
|
+
endpoint: EndpointDescriptor;
|
|
77
|
+
baseUrl: string;
|
|
78
|
+
/** The route payload — the API `data`, or the sync `data` (the transport adds the sync envelope). */
|
|
79
|
+
body: unknown;
|
|
80
|
+
/** HTTP headers (session Cookie, CSRF). A socket transport reads only the Cookie. */
|
|
81
|
+
headers?: Record<string, string>;
|
|
82
|
+
requestTimeoutMs: number;
|
|
83
|
+
}
|
|
84
|
+
interface ProbeTransport {
|
|
85
|
+
readonly name: 'http' | 'socket';
|
|
86
|
+
/** Resolve with the parsed reply, or `null` when no reply arrived (network error / timeout). */
|
|
87
|
+
send: (request: ProbeTransportRequest) => Promise<ProbeResponse | null>;
|
|
88
|
+
/** Release held connections. Optional — the HTTP transport holds none. */
|
|
89
|
+
close?: () => Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
interface HttpProbeTransportOptions {
|
|
92
|
+
/**
|
|
93
|
+
* Room sent as `receiver` on sync probes. Without one the server answers
|
|
94
|
+
* `sync.missingReceiver`, which proves the envelope but not the route.
|
|
95
|
+
*/
|
|
96
|
+
syncReceiver?: string;
|
|
97
|
+
}
|
|
98
|
+
declare const createHttpProbeTransport: (options?: HttpProbeTransportOptions) => ProbeTransport;
|
|
99
|
+
/** Transport the checks use when the caller supplies none. */
|
|
100
|
+
declare const defaultProbeTransport: ProbeTransport;
|
|
45
101
|
|
|
46
102
|
interface ContractCheckInput {
|
|
47
103
|
endpoint: EndpointDescriptor;
|
|
@@ -61,11 +117,15 @@ interface ContractCheckInput {
|
|
|
61
117
|
* the contract check.
|
|
62
118
|
*/
|
|
63
119
|
requestTimeoutMs?: number;
|
|
120
|
+
/** How the probe reaches the server. Defaults to HTTP. */
|
|
121
|
+
transport?: ProbeTransport;
|
|
64
122
|
}
|
|
65
123
|
declare const runContractCheck: (input: ContractCheckInput) => Promise<ContractCheckResult>;
|
|
66
124
|
|
|
67
125
|
interface RunContractTestsInput {
|
|
68
126
|
apiMethodMap: ApiMethodMap$1;
|
|
127
|
+
/** Generated `syncMetaMap`. When given, sync routes are swept too. */
|
|
128
|
+
syncMetaMap?: SyncMetaMap;
|
|
69
129
|
baseUrl: string;
|
|
70
130
|
/**
|
|
71
131
|
* Endpoints to skip. Matched against `<page>/<name>` (version-agnostic) and
|
|
@@ -73,8 +133,12 @@ interface RunContractTestsInput {
|
|
|
73
133
|
* are known to need real input (e.g. a file upload).
|
|
74
134
|
*/
|
|
75
135
|
skip?: string[];
|
|
136
|
+
/** Substring filter on `<page>/<name>/<version>`; other routes are not requested at all. */
|
|
137
|
+
filter?: string;
|
|
76
138
|
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
77
139
|
headers?: Record<string, string>;
|
|
140
|
+
/** Transport for sync routes (e.g. the socket transport). API routes always use HTTP. */
|
|
141
|
+
syncTransport?: ProbeTransport;
|
|
78
142
|
onResult?: (result: ContractCheckResult) => void;
|
|
79
143
|
}
|
|
80
144
|
declare const runContractTests: (input: RunContractTestsInput) => Promise<RunContractSummary>;
|
|
@@ -85,15 +149,23 @@ interface AuthEnforcementCheckInput {
|
|
|
85
149
|
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
86
150
|
/** Per-call request timeout in ms. Defaults to 5000. */
|
|
87
151
|
requestTimeoutMs?: number;
|
|
152
|
+
/** How the probe reaches the server. Defaults to HTTP. */
|
|
153
|
+
transport?: ProbeTransport;
|
|
88
154
|
}
|
|
89
155
|
declare const runAuthEnforcementCheck: (input: AuthEnforcementCheckInput) => Promise<ContractCheckResult>;
|
|
90
156
|
|
|
91
157
|
interface RunAuthEnforcementTestsInput {
|
|
92
158
|
apiMethodMap: ApiMethodMap$1;
|
|
93
159
|
apiMetaMap: ApiMetaMap;
|
|
160
|
+
/** Generated `syncMetaMap`. When given, sync routes are swept too. */
|
|
161
|
+
syncMetaMap?: SyncMetaMap;
|
|
94
162
|
baseUrl: string;
|
|
95
163
|
skip?: string[];
|
|
164
|
+
/** Substring filter on `<page>/<name>/<version>`; other routes are not requested at all. */
|
|
165
|
+
filter?: string;
|
|
96
166
|
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
167
|
+
/** Transport for sync routes (e.g. the socket transport). API routes always use HTTP. */
|
|
168
|
+
syncTransport?: ProbeTransport;
|
|
97
169
|
onResult?: (result: ContractCheckResult) => void;
|
|
98
170
|
}
|
|
99
171
|
declare const runAuthEnforcementTests: (input: RunAuthEnforcementTestsInput) => Promise<RunContractSummary>;
|
|
@@ -106,27 +178,37 @@ interface RateLimitCheckInput {
|
|
|
106
178
|
headers?: Record<string, string>;
|
|
107
179
|
/** Per-call request timeout in ms. Defaults to 10000. */
|
|
108
180
|
requestTimeoutMs?: number;
|
|
181
|
+
/** How the probes reach the server. Defaults to HTTP. */
|
|
182
|
+
transport?: ProbeTransport;
|
|
109
183
|
}
|
|
110
184
|
declare const runRateLimitCheck: (input: RateLimitCheckInput) => Promise<ContractCheckResult>;
|
|
111
185
|
|
|
112
186
|
interface RunRateLimitTestsInput {
|
|
113
187
|
apiMethodMap: ApiMethodMap$1;
|
|
114
188
|
apiMetaMap: ApiMetaMap;
|
|
189
|
+
/** Generated `syncMetaMap`. When given, sync routes are swept too. */
|
|
190
|
+
syncMetaMap?: SyncMetaMap;
|
|
115
191
|
baseUrl: string;
|
|
116
192
|
skip?: string[];
|
|
193
|
+
/** Substring filter on `<page>/<name>/<version>`; other routes are not requested at all. */
|
|
194
|
+
filter?: string;
|
|
117
195
|
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
118
196
|
headers?: Record<string, string>;
|
|
197
|
+
/** Transport for sync routes (e.g. the socket transport). API routes always use HTTP. */
|
|
198
|
+
syncTransport?: ProbeTransport;
|
|
119
199
|
/**
|
|
120
200
|
* Max rateLimit value to test. Endpoints with a higher limit are skipped
|
|
121
201
|
* to avoid firing thousands of requests in CI.
|
|
122
202
|
*/
|
|
123
203
|
maxRateLimitToTest?: number;
|
|
124
204
|
/**
|
|
125
|
-
* When true, hit `/_test/reset` before each endpoint so
|
|
126
|
-
* clean.
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
205
|
+
* When true, hit `/_test/reset?only=rateLimits` before each endpoint so
|
|
206
|
+
* limiter state is clean. Only the limiter buckets are cleared — sessions
|
|
207
|
+
* survive, so an authenticated sweep keeps its session. Requires the server
|
|
208
|
+
* to allow the endpoint: `NODE_ENV` in { 'development', 'test' } AND
|
|
209
|
+
* `TEST_RESET_TOKEN` set on the server with a matching `resetToken` here (an
|
|
210
|
+
* unset token is 403, never open). Without resetting, the shared IP bucket
|
|
211
|
+
* leaks state between endpoints.
|
|
130
212
|
*/
|
|
131
213
|
resetBetweenEndpoints?: boolean;
|
|
132
214
|
/**
|
|
@@ -153,17 +235,33 @@ interface CsrfEnforcementCheckInput {
|
|
|
153
235
|
expectedErrorCode?: string;
|
|
154
236
|
/** HTTP status expected on CSRF rejection. Defaults to 403; pass `false` to skip. */
|
|
155
237
|
expectedHttpStatus?: number | false;
|
|
238
|
+
/**
|
|
239
|
+
* HTTP transport the probe uses (e.g. one carrying the sync `receiver`).
|
|
240
|
+
* CSRF is an HTTP-only guard, so a non-HTTP transport makes the check skip.
|
|
241
|
+
* Defaults to plain HTTP.
|
|
242
|
+
*/
|
|
243
|
+
transport?: ProbeTransport;
|
|
156
244
|
}
|
|
157
245
|
declare const runCsrfEnforcementCheck: (input: CsrfEnforcementCheckInput) => Promise<ContractCheckResult>;
|
|
158
246
|
|
|
159
247
|
interface RunCsrfEnforcementTestsInput {
|
|
160
248
|
apiMethodMap: ApiMethodMap$1;
|
|
161
249
|
apiMetaMap: ApiMetaMap;
|
|
250
|
+
/** Generated `syncMetaMap`. When given, sync routes' `/sync/*` HTTP endpoints are probed too. */
|
|
251
|
+
syncMetaMap?: SyncMetaMap;
|
|
162
252
|
baseUrl: string;
|
|
163
253
|
/** Valid session Cookie header (`<name>=<token>`) the probes carry so they reach the CSRF check. */
|
|
164
254
|
authCookie: string;
|
|
165
255
|
skip?: string[];
|
|
256
|
+
/** Substring filter on `<page>/<name>/<version>`; other routes are not requested at all. */
|
|
257
|
+
filter?: string;
|
|
166
258
|
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
259
|
+
/**
|
|
260
|
+
* HTTP transport for sync routes (one carrying the sync `receiver`). CSRF is
|
|
261
|
+
* an HTTP-only guard, so this must be an HTTP transport even when the project
|
|
262
|
+
* syncs over Socket.io — the `/sync/*` HTTP route is reachable either way.
|
|
263
|
+
*/
|
|
264
|
+
syncTransport?: ProbeTransport;
|
|
167
265
|
/** Per-call request timeout in ms forwarded to each check. */
|
|
168
266
|
requestTimeoutMs?: number;
|
|
169
267
|
/** Error code expected on CSRF rejection. Defaults to `auth.csrfMismatch`. */
|
|
@@ -180,14 +278,22 @@ interface FuzzCheckInput {
|
|
|
180
278
|
headers?: Record<string, string>;
|
|
181
279
|
/** Per-call request timeout in ms. Defaults to 5000. */
|
|
182
280
|
requestTimeoutMs?: number;
|
|
281
|
+
/** How the probes reach the server. Defaults to HTTP. */
|
|
282
|
+
transport?: ProbeTransport;
|
|
183
283
|
}
|
|
184
284
|
declare const runFuzzCheck: (input: FuzzCheckInput) => Promise<ContractCheckResult>;
|
|
185
285
|
|
|
186
286
|
interface RunFuzzTestsInput {
|
|
187
287
|
apiMethodMap: ApiMethodMap$1;
|
|
288
|
+
/** Generated `syncMetaMap`. When given, sync routes are swept too. */
|
|
289
|
+
syncMetaMap?: SyncMetaMap;
|
|
188
290
|
baseUrl: string;
|
|
189
291
|
skip?: string[];
|
|
292
|
+
/** Substring filter on `<page>/<name>/<version>`; other routes are not requested at all. */
|
|
293
|
+
filter?: string;
|
|
190
294
|
headers?: Record<string, string>;
|
|
295
|
+
/** Transport for sync routes (e.g. the socket transport). API routes always use HTTP. */
|
|
296
|
+
syncTransport?: ProbeTransport;
|
|
191
297
|
onResult?: (result: ContractCheckResult) => void;
|
|
192
298
|
}
|
|
193
299
|
declare const runFuzzTests: (input: RunFuzzTestsInput) => Promise<RunContractSummary>;
|
|
@@ -196,8 +302,35 @@ interface ResetServerStateInput {
|
|
|
196
302
|
baseUrl: string;
|
|
197
303
|
token?: string;
|
|
198
304
|
requestTimeoutMs?: number;
|
|
305
|
+
/**
|
|
306
|
+
* Clear only these targets (`?only=`). Omit for the server's default reset,
|
|
307
|
+
* which ALSO deletes every Redis session — including an authenticated sweep's
|
|
308
|
+
* own. The runner itself always passes `['rateLimits']`.
|
|
309
|
+
*/
|
|
310
|
+
only?: TestResetTarget[];
|
|
311
|
+
}
|
|
312
|
+
declare const resetServerState: ({ baseUrl, token, requestTimeoutMs, only }: ResetServerStateInput) => Promise<boolean>;
|
|
313
|
+
|
|
314
|
+
interface SocketProbeTransportOptions {
|
|
315
|
+
baseUrl: string;
|
|
316
|
+
/** Room every sync probe targets; authenticated sockets join it first. */
|
|
317
|
+
receiver: string;
|
|
318
|
+
/** Session cookie name, used to read the token out of a probe's Cookie header. */
|
|
319
|
+
sessionCookieName: string;
|
|
199
320
|
}
|
|
200
|
-
declare const
|
|
321
|
+
declare const createSocketProbeTransport: (options: SocketProbeTransportOptions) => ProbeTransport;
|
|
322
|
+
|
|
323
|
+
type InputSchemaMap = Partial<Record<string, Partial<Record<string, Partial<Record<string, ZodType | undefined>>>>>>;
|
|
324
|
+
interface CreateSampleInputForOptions {
|
|
325
|
+
apiInputSchemas?: InputSchemaMap;
|
|
326
|
+
syncInputSchemas?: InputSchemaMap;
|
|
327
|
+
/**
|
|
328
|
+
* Prefix for generated unconstrained strings — pass the run's
|
|
329
|
+
* `createTestDataMarker()` so rows the probes create are identifiable.
|
|
330
|
+
*/
|
|
331
|
+
stringPrefix?: string;
|
|
332
|
+
}
|
|
333
|
+
declare const createSampleInputFor: (options: CreateSampleInputForOptions) => (endpoint: EndpointDescriptor) => unknown;
|
|
201
334
|
|
|
202
335
|
interface ResolveTestBaseUrlOptions {
|
|
203
336
|
/** Project root containing node_modules/.luckystack/dev-server.json. */
|
|
@@ -343,6 +476,16 @@ interface DiscoveredTestFile {
|
|
|
343
476
|
};
|
|
344
477
|
}
|
|
345
478
|
declare const discoverCustomTestFiles: (srcDir?: string) => DiscoveredTestFile[];
|
|
479
|
+
interface CallSyncOptions {
|
|
480
|
+
/** Room the sync targets (the server requires one). */
|
|
481
|
+
receiver?: string;
|
|
482
|
+
/** Skip the sender's own socket in the fan-out (socket transport). */
|
|
483
|
+
ignoreSelf?: boolean;
|
|
484
|
+
/** Force a transport. Defaults to the project's `transport.invocation`. */
|
|
485
|
+
transport?: 'socket' | 'http';
|
|
486
|
+
/** Socket transport: join `receiver` before sending. Default `true`. */
|
|
487
|
+
joinRoom?: boolean;
|
|
488
|
+
}
|
|
346
489
|
interface TestContext {
|
|
347
490
|
/**
|
|
348
491
|
* Invoke the route under test. Page / name / version are baked in.
|
|
@@ -354,9 +497,15 @@ interface TestContext {
|
|
|
354
497
|
* receives them.
|
|
355
498
|
*/
|
|
356
499
|
callApi: <TInput = unknown, TOutput = unknown>(input: TInput) => Promise<TOutput>;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
500
|
+
/**
|
|
501
|
+
* Invoke the sync route under test over the SAME transport the project's
|
|
502
|
+
* real client uses (`transport.invocation`): Socket.io for `'socket'` (the
|
|
503
|
+
* default), the `/sync/*` HTTP route for `'routed-http'`. Override per call
|
|
504
|
+
* with `opts.transport`. Over the socket, the case's session socket first
|
|
505
|
+
* joins `opts.receiver` (like a real client joins its room before syncing);
|
|
506
|
+
* pass `joinRoom: false` to test a non-member.
|
|
507
|
+
*/
|
|
508
|
+
callSync: <TInput = unknown, TOutput = unknown>(input: TInput, opts?: CallSyncOptions) => Promise<TOutput>;
|
|
360
509
|
/**
|
|
361
510
|
* Open a second socket connection that joins `roomCode` as a pure
|
|
362
511
|
* subscriber and exposes the incoming chunk stream for assertions.
|
|
@@ -393,9 +542,29 @@ interface TestExpect {
|
|
|
393
542
|
}
|
|
394
543
|
declare const runCustomTests: (input: RunCustomTestsInput) => Promise<RunCustomTestsSummary>;
|
|
395
544
|
|
|
396
|
-
type ApiInputSchemas = Partial<Record<string, Partial<Record<string, Partial<Record<string, ZodType | undefined>>>>>>;
|
|
397
545
|
interface RunAllTestsInput {
|
|
398
546
|
apiMethodMap: ApiMethodMap$1;
|
|
547
|
+
/**
|
|
548
|
+
* Generated `syncMetaMap` (from `apiTypes.generated.ts`). When given, the
|
|
549
|
+
* sweep layers exercise every sync route too; without it sync routes are
|
|
550
|
+
* not swept (a warning says so).
|
|
551
|
+
*/
|
|
552
|
+
syncMetaMap?: SyncMetaMap;
|
|
553
|
+
/** Generated `syncInputSchemas` (from `apiInputSchemas.generated.ts`) — Zod-valid sync sample payloads. */
|
|
554
|
+
syncInputSchemas?: InputSchemaMap;
|
|
555
|
+
/**
|
|
556
|
+
* How sync routes are probed. Defaults to the project's own
|
|
557
|
+
* `transport.invocation`: `'socket'` → Socket.io (the pipeline real clients
|
|
558
|
+
* hit), `'routed-http'` → the `/sync/*` HTTP route. The CSRF layer always
|
|
559
|
+
* probes over HTTP — CSRF is an HTTP-only guard.
|
|
560
|
+
*/
|
|
561
|
+
syncTransport?: 'socket' | 'http';
|
|
562
|
+
/**
|
|
563
|
+
* Write the full `RunAllTestsSummary` as JSON to this path (relative to the
|
|
564
|
+
* process cwd). Defaults to `TEST_OUTPUT_FILE`, else `test-results.json`;
|
|
565
|
+
* `false` disables the file.
|
|
566
|
+
*/
|
|
567
|
+
outputFile?: string | false;
|
|
399
568
|
/**
|
|
400
569
|
* Lazy loader for the consumer's default `config.ts` export. Required so
|
|
401
570
|
* runAllTests cannot silently skip a configured secret manager; resolution
|
|
@@ -403,7 +572,7 @@ interface RunAllTestsInput {
|
|
|
403
572
|
*/
|
|
404
573
|
loadProjectConfig: NonNullable<ResolveTestEnvironmentInput['loadProjectConfig']>;
|
|
405
574
|
apiMetaMap: ApiMetaMap;
|
|
406
|
-
apiInputSchemas:
|
|
575
|
+
apiInputSchemas: InputSchemaMap;
|
|
407
576
|
baseUrl: string;
|
|
408
577
|
/** Cookie name for the session token. Defaults to the project's configured session cookie name (`projectConfig.http.sessionCookieName`). */
|
|
409
578
|
sessionCookieName?: string;
|
|
@@ -434,12 +603,14 @@ interface RunAllTestsInput {
|
|
|
434
603
|
*/
|
|
435
604
|
resetToken?: string;
|
|
436
605
|
/**
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
606
|
+
* When a reset token is available, the sweep POSTs
|
|
607
|
+
* `/_test/reset?only=rateLimits` ONCE before the first layer (no bucket left
|
|
608
|
+
* drained by an earlier run) and ONCE after the last (the custom layer and the
|
|
609
|
+
* next run start unthrottled). Only limiter state is cleared: sessions — the
|
|
610
|
+
* `authToken` session above all — survive, so `TEST_RESET_TOKEN` can be set
|
|
611
|
+
* on an authenticated sweep. The reset never touches the app database.
|
|
441
612
|
* Defaults to ON; set `false` to opt out. With no token the bookends are
|
|
442
|
-
*
|
|
613
|
+
* skipped with a logged note (they can't run — `/_test/reset` 403s).
|
|
443
614
|
*/
|
|
444
615
|
resetBookends?: boolean;
|
|
445
616
|
}
|
|
@@ -457,12 +628,19 @@ declare const runAllTests: (input: RunAllTestsInput) => Promise<RunAllTestsSumma
|
|
|
457
628
|
declare const logRunAllSummary: (summary: RunAllTestsSummary) => void;
|
|
458
629
|
|
|
459
630
|
interface TestLayerInput {
|
|
460
|
-
/** Resolved route name (`api/billing/getInvoice/v1`). */
|
|
631
|
+
/** Resolved route name (`api/billing/getInvoice/v1` or `sync/chat/send/v1`). */
|
|
461
632
|
endpoint: string;
|
|
462
633
|
/** Method when applicable, undefined for sync endpoints. */
|
|
463
634
|
method?: string;
|
|
464
635
|
/** Bearer token / session token to use for auth-aware checks. */
|
|
465
636
|
authToken?: string;
|
|
637
|
+
/**
|
|
638
|
+
* A Zod-valid sample `data` payload for this route — generated from the
|
|
639
|
+
* route's input schema when `runRegisteredLayers` received the generated
|
|
640
|
+
* schemas (or an `inputFor`), `{}` otherwise. The same payload the built-in
|
|
641
|
+
* contract sweep sends, so a layer can exercise the route past validation.
|
|
642
|
+
*/
|
|
643
|
+
sampleInput?: unknown;
|
|
466
644
|
}
|
|
467
645
|
interface TestLayerResult {
|
|
468
646
|
passed: boolean;
|
|
@@ -535,6 +713,8 @@ declare const resetTestExtensionsForTests: () => void;
|
|
|
535
713
|
|
|
536
714
|
interface RunRegisteredLayersInput {
|
|
537
715
|
apiMethodMap: ApiMethodMap$1;
|
|
716
|
+
/** Generated `syncMetaMap`. When given, layers also run against every sync route. */
|
|
717
|
+
syncMetaMap?: SyncMetaMap;
|
|
538
718
|
/** Session/bearer token forwarded to each layer's `run({ authToken })`. */
|
|
539
719
|
authToken?: string;
|
|
540
720
|
/**
|
|
@@ -542,6 +722,14 @@ interface RunRegisteredLayersInput {
|
|
|
542
722
|
* `<page>/<name>/<version>`, same convention as the built-in sweeps.
|
|
543
723
|
*/
|
|
544
724
|
skip?: string[];
|
|
725
|
+
/** Substring filter on `<page>/<name>/<version>`, same as the built-in sweeps. */
|
|
726
|
+
filter?: string;
|
|
727
|
+
/** Generated `apiInputSchemas` — source of each API route's `sampleInput`. */
|
|
728
|
+
apiInputSchemas?: InputSchemaMap;
|
|
729
|
+
/** Generated `syncInputSchemas` — source of each sync route's `sampleInput`. */
|
|
730
|
+
syncInputSchemas?: InputSchemaMap;
|
|
731
|
+
/** Custom sample factory; wins over the schema maps when given. */
|
|
732
|
+
inputFor?: (endpoint: EndpointDescriptor) => unknown;
|
|
545
733
|
}
|
|
546
734
|
declare const runRegisteredLayers: (input: RunRegisteredLayersInput) => Promise<TestSummary>;
|
|
547
735
|
|
|
@@ -554,4 +742,4 @@ declare const LAYER_KEYS: {
|
|
|
554
742
|
readonly custom: "custom";
|
|
555
743
|
};
|
|
556
744
|
|
|
557
|
-
export { type ApiMetaEntry, type ApiMetaMap, type ApiMethodMap$1 as ApiMethodMap, type AuthEnforcementCheckInput, type ContractCheckInput, type ContractCheckResult, type CsrfEnforcementCheckInput, type CustomTestCase, type CustomTestResult, type EndpointDescriptor, type FuzzCheckInput, type HttpMethod, LAYER_KEYS, type OpenStreamWatcherInput, type RateLimitCheckInput, type ResetServerStateInput, type ResolveTestBaseUrlOptions, type ResolveTestEnvironmentInput, type RunAllTestsInput, type RunAllTestsSummary, type RunAuthEnforcementTestsInput, type RunContractSummary, type RunContractTestsInput, type RunCsrfEnforcementTestsInput, type RunCustomTestsInput, type RunCustomTestsSummary, type RunFuzzTestsInput, type RunRateLimitTestsInput, type RunRegisteredLayersInput, type SampleSchemaOptions, type StreamChunkFrame, type StreamWatcher, type SyncMethodMap, TEST_DATA_PREFIX, type TestContext, type TestExpect, type TestFixture, type TestLayer, type TestLayerInput, type TestLayerResult, type TestReporter, type TestResult, type TestSummary, createTestDataMarker, discoverCustomTestFiles, getTestFixture, getTestReporter, listTestLayers, logContractResult, logContractSummary, logRunAllSummary, openStreamWatcher, registerTestFixture, registerTestLayer, registerTestReporter, resetServerState, resetTestExtensionsForTests, resolveTestBaseUrl, resolveTestEnvironment, runAllTests, runAuthEnforcementCheck, runAuthEnforcementTests, runContractCheck, runContractTests, runCsrfEnforcementCheck, runCsrfEnforcementTests, runCustomTests, runFuzzCheck, runFuzzTests, runRateLimitCheck, runRateLimitTests, runRegisteredLayers, sampleSchemaInput, walkEndpoints, walkSyncEndpoints };
|
|
745
|
+
export { type ApiMetaEntry, type ApiMetaMap, type ApiMethodMap$1 as ApiMethodMap, type AuthEnforcementCheckInput, type CallSyncOptions, type ContractCheckInput, type ContractCheckResult, type CreateSampleInputForOptions, type CsrfEnforcementCheckInput, type CustomTestCase, type CustomTestResult, type EndpointDescriptor, type FuzzCheckInput, type HttpMethod, type HttpProbeTransportOptions, type InputSchemaMap, LAYER_KEYS, type OpenStreamWatcherInput, type ProbeRequestInput, type ProbeResponse, type ProbeTransport, type ProbeTransportRequest, type RateLimitCheckInput, type ResetServerStateInput, type ResolveTestBaseUrlOptions, type ResolveTestEnvironmentInput, type RunAllTestsInput, type RunAllTestsSummary, type RunAuthEnforcementTestsInput, type RunContractSummary, type RunContractTestsInput, type RunCsrfEnforcementTestsInput, type RunCustomTestsInput, type RunCustomTestsSummary, type RunFuzzTestsInput, type RunRateLimitTestsInput, type RunRegisteredLayersInput, type SampleSchemaOptions, type SocketProbeTransportOptions, type StreamChunkFrame, type StreamWatcher, type SyncMetaEntry, type SyncMetaMap, type SyncMethodMap, TEST_DATA_PREFIX, type TestContext, type TestExpect, type TestFixture, type TestLayer, type TestLayerInput, type TestLayerResult, type TestReporter, type TestResult, type TestSummary, createHttpProbeTransport, createSampleInputFor, createSocketProbeTransport, createTestDataMarker, defaultProbeTransport, discoverCustomTestFiles, getTestFixture, getTestReporter, listTestLayers, logContractResult, logContractSummary, logRunAllSummary, openStreamWatcher, registerTestFixture, registerTestLayer, registerTestReporter, resetServerState, resetTestExtensionsForTests, resolveTestBaseUrl, resolveTestEnvironment, runAllTests, runAuthEnforcementCheck, runAuthEnforcementTests, runContractCheck, runContractTests, runCsrfEnforcementCheck, runCsrfEnforcementTests, runCustomTests, runFuzzCheck, runFuzzTests, runRateLimitCheck, runRateLimitTests, runRegisteredLayers, sampleSchemaInput, sendProbe, walkEndpoints, walkSyncEndpoints };
|