@jterrazz/test 16.1.1 → 18.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 +45 -171
- package/dist/browser/index.js +1 -2980
- package/dist/browser/services.js +1 -0
- package/dist/browser/stubs.js +1 -0
- package/dist/browser-shared-index.browser.js +3233 -0
- package/dist/checker.d.ts +6 -1
- package/dist/checker.js +3721 -2624
- package/dist/config.d.ts +40 -0
- package/dist/config.js +309 -0
- package/dist/in-place.global-setup.d.ts +12 -0
- package/dist/in-place.global-setup.js +21 -0
- package/dist/index.d.ts +1641 -3004
- package/dist/index.js +5095 -3835
- package/dist/mobile-session.global-setup.d.ts +15 -0
- package/dist/mobile-session.global-setup.js +31 -0
- package/dist/oxlint.cjs +6069 -5634
- package/dist/oxlint.d.cts +43 -7212
- package/dist/oxlint.d.ts +43 -7212
- package/dist/oxlint.js +3979 -5799
- package/dist/route-coverage.global-setup.d.ts +43 -0
- package/dist/route-coverage.global-setup.js +1 -0
- package/dist/services.d.ts +3 -0
- package/dist/services.global-setup.d.ts +43 -0
- package/dist/services.global-setup.js +1 -0
- package/dist/services.js +597 -0
- package/dist/shared-appium.adapter.js +428 -0
- package/dist/shared-artifacts.js +34 -0
- package/dist/shared-chapter.js +7 -0
- package/dist/shared-container.port.d.ts +31 -0
- package/dist/shared-derived-projects.js +73 -0
- package/dist/shared-device.port.d.ts +189 -0
- package/dist/shared-exchange.js +447 -0
- package/dist/shared-in-place.js +172 -0
- package/dist/shared-index.services.d.ts +346 -0
- package/dist/shared-index.stubs.d.ts +287 -0
- package/dist/shared-json-shape.js +17 -0
- package/dist/shared-landmarks.js +71 -0
- package/dist/shared-ledger.js +68 -0
- package/dist/shared-listened-port.js +19 -0
- package/dist/shared-literate-plugin.js +184 -0
- package/dist/shared-manifest.js +1321 -0
- package/dist/shared-pause.js +22 -0
- package/dist/shared-peer.js +88 -0
- package/dist/shared-playwright.adapter.js +328 -0
- package/dist/shared-process-alive.js +13 -0
- package/dist/shared-process.adapter.js +74 -0
- package/dist/shared-record-key.js +13 -0
- package/dist/shared-refusal.js +35 -0
- package/dist/shared-resolve.js +24 -0
- package/dist/shared-route-coverage.global-setup.js +187 -0
- package/dist/shared-scenario-failure.js +198 -0
- package/dist/shared-serve.js +407 -0
- package/dist/shared-service-images.js +10 -0
- package/dist/shared-services.global-setup.js +174 -0
- package/dist/shared-session-ledger.js +305 -0
- package/dist/shared-setup-entry.js +12 -0
- package/dist/shared-source-scan.js +133 -0
- package/dist/shared-spec-document.js +303 -0
- package/dist/shared-spec-grammar.js +66 -0
- package/dist/shared-specifications.js +26 -0
- package/dist/shared-specs-modules.js +1033 -0
- package/dist/shared-stub-reply.js +167 -0
- package/dist/shared-stub-server.js +142 -0
- package/dist/shared-temp-root.global-setup.js +73 -0
- package/dist/shared-test-baseline.js +26 -0
- package/dist/shared-test-section.js +58 -0
- package/dist/shared-testcontainers.adapter.js +306 -0
- package/dist/shared-tokens.js +55 -0
- package/dist/shared-yaml-document.js +119 -0
- package/dist/stubs.d.ts +2 -0
- package/dist/stubs.js +657 -0
- package/dist/temp-root.global-setup.d.ts +7 -0
- package/dist/temp-root.global-setup.js +1 -0
- package/dist/vitest.d.ts +93 -164
- package/dist/vitest.js +382 -550
- package/docs/README.md +82 -36
- package/docs/concepts/architecture.md +118 -0
- package/docs/concepts/conventions.md +333 -0
- package/docs/guides/api-specs.md +374 -0
- package/docs/guides/cli-specs.md +566 -0
- package/docs/guides/component-specs.md +252 -0
- package/docs/guides/develop.md +97 -0
- package/docs/guides/integration-specs.md +181 -0
- package/docs/guides/job-specs.md +180 -0
- package/docs/guides/lint-specs.md +174 -0
- package/docs/guides/mobile-specs.md +319 -0
- package/docs/guides/module-tests.md +149 -0
- package/docs/guides/release.md +44 -0
- package/docs/guides/spec-documents.md +189 -0
- package/docs/guides/website-specs.md +413 -0
- package/docs/reference/assertions.md +345 -0
- package/docs/reference/glossary.md +20 -0
- package/docs/reference/linting.md +483 -0
- package/docs/reference/services.md +236 -0
- package/docs/reference/stubs.md +500 -0
- package/docs/reference/time-and-doubles.md +137 -0
- package/docs/reference/tokens.md +258 -0
- package/docs/reference/visitor.md +221 -0
- package/docs/start/getting-started.md +187 -0
- package/docs/start/set-up-a-project.md +228 -0
- package/package.json +56 -36
- package/schema/spec.schema.json +43 -17
- package/dist/appium.adapter.js +0 -489
- package/dist/artifacts.js +0 -32
- package/dist/fixtures.js +0 -110
- package/dist/literate.js +0 -1747
- package/dist/match.js +0 -804
- package/dist/playwright.adapter.js +0 -438
- package/dist/server.js +0 -160
- package/dist/stream.js +0 -321
- package/dist/substring-warning.js +0 -282
- package/docs/01-architecture.md +0 -95
- package/docs/02-developing.md +0 -351
- package/docs/03-testing.md +0 -495
- package/docs/04-operating.md +0 -101
- package/docs/05-module-tests.md +0 -152
- package/docs/06-integration.md +0 -180
- package/docs/07-component.md +0 -246
- package/docs/08-website.md +0 -404
- package/docs/09-mobile.md +0 -270
- package/docs/10-api.md +0 -264
- package/docs/11-jobs.md +0 -157
- package/docs/12-cli.md +0 -677
- package/docs/13-elements.md +0 -248
- package/docs/14-assertions.md +0 -314
- package/docs/15-tokens.md +0 -253
- package/docs/16-contracts.md +0 -438
- package/docs/17-services.md +0 -188
- package/docs/18-conventions.md +0 -332
- package/docs/19-linting.md +0 -512
- package/docs/decisions/001-v9-conventions-on-three-channels.md +0 -50
- package/docs/decisions/002-the-statique-channel-holds-only-what-upstream-does-not.md +0 -49
- package/docs/decisions/003-a-rendered-component-is-a-facet-on-vitest-browser-mode.md +0 -84
- package/docs/decisions/004-a-module-against-real-services-or-a-golden-is-the-integration-facet.md +0 -81
- package/docs/decisions/005-the-doubles-ladder-is-closed.md +0 -86
- package/docs/decisions/006-the-catalogue-reaches-a-file-by-its-role.md +0 -245
- package/docs/decisions/007-compose-mode-leaves-the-package.md +0 -53
- package/docs/decisions/008-vitest-5-node-24-and-the-native-seams-as-optional-peers.md +0 -75
- package/docs/decisions/_template.md +0 -22
- package/docs/reference/classes/Matcher.md +0 -120
- package/docs/reference/classes/ProcessHandle.md +0 -368
- package/docs/reference/functions/defineContract.md +0 -39
- package/docs/reference/functions/defineContracts.md +0 -36
- package/docs/reference/functions/disabled.md +0 -28
- package/docs/reference/functions/enabled.md +0 -20
- package/docs/reference/functions/focused.md +0 -26
- package/docs/reference/functions/mockOf.md +0 -79
- package/docs/reference/functions/postgres.md +0 -31
- package/docs/reference/functions/process.md +0 -33
- package/docs/reference/functions/redis.md +0 -28
- package/docs/reference/functions/required.md +0 -41
- package/docs/reference/functions/selected.md +0 -26
- package/docs/reference/functions/sqlite.md +0 -33
- package/docs/reference/functions/testId.md +0 -20
- package/docs/reference/functions/text.md +0 -40
- package/docs/reference/functions/valued.md +0 -28
- package/docs/reference/functions/waitUntil.md +0 -46
- package/docs/reference/functions/within.md +0 -29
- package/docs/reference/index.md +0 -196
- package/docs/reference/interfaces/BaseResult.md +0 -87
- package/docs/reference/interfaces/CallResult.md +0 -160
- package/docs/reference/interfaces/CaptureScope.md +0 -82
- package/docs/reference/interfaces/CliResult.md +0 -253
- package/docs/reference/interfaces/ContainerAccessor.md +0 -166
- package/docs/reference/interfaces/DirectoryAccessor.md +0 -33
- package/docs/reference/interfaces/FetchResult.md +0 -180
- package/docs/reference/interfaces/FilesystemAccessor.md +0 -46
- package/docs/reference/interfaces/HttpResult.md +0 -126
- package/docs/reference/interfaces/JsonAccessor.md +0 -46
- package/docs/reference/interfaces/PageResult.md +0 -356
- package/docs/reference/interfaces/RenderResult.md +0 -72
- package/docs/reference/interfaces/RenderedText.md +0 -110
- package/docs/reference/interfaces/ResponseAccessor.md +0 -47
- package/docs/reference/interfaces/ScreenResult.md +0 -128
- package/docs/reference/interfaces/TableAccessor.md +0 -26
- package/docs/reference/interfaces/TextAccessor.md +0 -96
- package/docs/reference/type-aliases/ApiHandle.md +0 -68
- package/docs/reference/type-aliases/ApiSpecification.md +0 -213
- package/docs/reference/type-aliases/ApiSpecificationOptions.md +0 -68
- package/docs/reference/type-aliases/BrowserConsoleMessage.md +0 -30
- package/docs/reference/type-aliases/BrowserLinkElement.md +0 -50
- package/docs/reference/type-aliases/BrowserMetaElement.md +0 -40
- package/docs/reference/type-aliases/BrowserOpenOptions.md +0 -87
- package/docs/reference/type-aliases/BrowserPage.md +0 -132
- package/docs/reference/type-aliases/BrowserPort.md +0 -51
- package/docs/reference/type-aliases/CliEnv.md +0 -11
- package/docs/reference/type-aliases/CliHandle.md +0 -80
- package/docs/reference/type-aliases/CliInput.md +0 -36
- package/docs/reference/type-aliases/CliOutput.md +0 -46
- package/docs/reference/type-aliases/CliPort.md +0 -58
- package/docs/reference/type-aliases/CliSpecification.md +0 -144
- package/docs/reference/type-aliases/CliSpecificationOptions.md +0 -134
- package/docs/reference/type-aliases/ComponentChain.md +0 -156
- package/docs/reference/type-aliases/ComponentScenario.md +0 -20
- package/docs/reference/type-aliases/ComponentUi.md +0 -47
- package/docs/reference/type-aliases/ComponentVisitor.md +0 -10
- package/docs/reference/type-aliases/ContainerPort.md +0 -113
- package/docs/reference/type-aliases/Contract.md +0 -68
- package/docs/reference/type-aliases/ContractInput.md +0 -13
- package/docs/reference/type-aliases/ContractRequest.md +0 -95
- package/docs/reference/type-aliases/ContractResponder.md +0 -23
- package/docs/reference/type-aliases/ContractResponse.md +0 -78
- package/docs/reference/type-aliases/ContractResponseValue.md +0 -13
- package/docs/reference/type-aliases/Contracts.md +0 -48
- package/docs/reference/type-aliases/DatabaseKeys.md +0 -16
- package/docs/reference/type-aliases/DatabasePort.md +0 -72
- package/docs/reference/type-aliases/DeviceOpenOptions.md +0 -46
- package/docs/reference/type-aliases/DevicePort.md +0 -51
- package/docs/reference/type-aliases/DeviceScreen.md +0 -32
- package/docs/reference/type-aliases/DeviceTimeouts.md +0 -39
- package/docs/reference/type-aliases/DockerSpecConfig.md +0 -43
- package/docs/reference/type-aliases/DomMount.md +0 -21
- package/docs/reference/type-aliases/ElementKind.md +0 -27
- package/docs/reference/type-aliases/ElementMatch.md +0 -74
- package/docs/reference/type-aliases/ElementOptions.md +0 -29
- package/docs/reference/type-aliases/ElementRef.md +0 -128
- package/docs/reference/type-aliases/ExecOptions.md +0 -37
- package/docs/reference/type-aliases/FileAccessor.md +0 -54
- package/docs/reference/type-aliases/HonoApp.md +0 -31
- package/docs/reference/type-aliases/HttpContractFilter.md +0 -49
- package/docs/reference/type-aliases/HttpResponseInit.md +0 -46
- package/docs/reference/type-aliases/HttpStreamInit.md +0 -58
- package/docs/reference/type-aliases/IntegrationHandle.md +0 -46
- package/docs/reference/type-aliases/IntegrationSpecification.md +0 -111
- package/docs/reference/type-aliases/IntegrationSpecificationOptions.md +0 -42
- package/docs/reference/type-aliases/Intercept.md +0 -19
- package/docs/reference/type-aliases/InterceptOptions.md +0 -28
- package/docs/reference/type-aliases/InterceptScope.md +0 -11
- package/docs/reference/type-aliases/IsolationStrategy.md +0 -75
- package/docs/reference/type-aliases/JobHandle.md +0 -34
- package/docs/reference/type-aliases/JobsHandle.md +0 -57
- package/docs/reference/type-aliases/JobsResult.md +0 -16
- package/docs/reference/type-aliases/JobsSpecification.md +0 -94
- package/docs/reference/type-aliases/JobsSpecificationOptions.md +0 -56
- package/docs/reference/type-aliases/LandmarkKind.md +0 -20
- package/docs/reference/type-aliases/LiterateRunFlags.md +0 -27
- package/docs/reference/type-aliases/LiterateServeRegistration.md +0 -70
- package/docs/reference/type-aliases/MatchFixtureOptions.md +0 -27
- package/docs/reference/type-aliases/MatchableRequest.md +0 -61
- package/docs/reference/type-aliases/MatcherKind.md +0 -34
- package/docs/reference/type-aliases/MobileBackendOptions.md +0 -28
- package/docs/reference/type-aliases/MobileElementKind.md +0 -14
- package/docs/reference/type-aliases/MobileElementMatch.md +0 -60
- package/docs/reference/type-aliases/MobileElementRef.md +0 -20
- package/docs/reference/type-aliases/MobileHandle.md +0 -65
- package/docs/reference/type-aliases/MobileScenario.md +0 -20
- package/docs/reference/type-aliases/MobileSpecification.md +0 -51
- package/docs/reference/type-aliases/MobileSpecificationOptions.md +0 -126
- package/docs/reference/type-aliases/MobileVisitor.md +0 -81
- package/docs/reference/type-aliases/MockOfOptions.md +0 -26
- package/docs/reference/type-aliases/MockPort.md +0 -10
- package/docs/reference/type-aliases/PinnedClock.md +0 -10
- package/docs/reference/type-aliases/PostgresOptions.md +0 -32
- package/docs/reference/type-aliases/ProcessOptions.md +0 -112
- package/docs/reference/type-aliases/RedisOptions.md +0 -20
- package/docs/reference/type-aliases/RenderSubject.md +0 -12
- package/docs/reference/type-aliases/ScreenNode.md +0 -67
- package/docs/reference/type-aliases/ServerPort.md +0 -36
- package/docs/reference/type-aliases/ServerResponse.md +0 -46
- package/docs/reference/type-aliases/ServerSpec.md +0 -21
- package/docs/reference/type-aliases/ServiceHandle.md +0 -216
- package/docs/reference/type-aliases/ServiceRecord.md +0 -12
- package/docs/reference/type-aliases/SpecDocument.md +0 -84
- package/docs/reference/type-aliases/SpecEnvToken.md +0 -21
- package/docs/reference/type-aliases/SpecFileAssertion.md +0 -27
- package/docs/reference/type-aliases/SpecFixture.md +0 -30
- package/docs/reference/type-aliases/SpecKind.md +0 -8
- package/docs/reference/type-aliases/SpecRun.md +0 -108
- package/docs/reference/type-aliases/SpecServeEntry.md +0 -40
- package/docs/reference/type-aliases/SpecStream.md +0 -32
- package/docs/reference/type-aliases/SpecificationConfig.md +0 -290
- package/docs/reference/type-aliases/SqliteOptions.md +0 -36
- package/docs/reference/type-aliases/SseEvent.md +0 -58
- package/docs/reference/type-aliases/StreamBody.md +0 -61
- package/docs/reference/type-aliases/TextFilter.md +0 -22
- package/docs/reference/type-aliases/VisitScenario.md +0 -20
- package/docs/reference/type-aliases/Visitor.md +0 -215
- package/docs/reference/type-aliases/WaitUntilOptions.md +0 -46
- package/docs/reference/type-aliases/WebsiteBackendOptions.md +0 -37
- package/docs/reference/type-aliases/WebsiteHandle.md +0 -51
- package/docs/reference/type-aliases/WebsiteSpecification.md +0 -118
- package/docs/reference/type-aliases/WebsiteSpecificationOptions.md +0 -40
- package/docs/reference/variables/anthropic.md +0 -19
- package/docs/reference/variables/banner.md +0 -10
- package/docs/reference/variables/button.md +0 -10
- package/docs/reference/variables/clock.md +0 -16
- package/docs/reference/variables/complementary.md +0 -10
- package/docs/reference/variables/component.md +0 -10
- package/docs/reference/variables/content.md +0 -10
- package/docs/reference/variables/contentinfo.md +0 -10
- package/docs/reference/variables/dialog.md +0 -10
- package/docs/reference/variables/field.md +0 -10
- package/docs/reference/variables/form.md +0 -10
- package/docs/reference/variables/heading.md +0 -10
- package/docs/reference/variables/http.md +0 -40
- package/docs/reference/variables/intercept.md +0 -11
- package/docs/reference/variables/link.md +0 -10
- package/docs/reference/variables/listitem.md +0 -10
- package/docs/reference/variables/main.md +0 -10
- package/docs/reference/variables/match.md +0 -8
- package/docs/reference/variables/navigation.md +0 -10
- package/docs/reference/variables/openai.md +0 -21
- package/docs/reference/variables/option.md +0 -17
- package/docs/reference/variables/region.md +0 -10
- package/docs/reference/variables/row.md +0 -10
- package/docs/reference/variables/search.md +0 -10
- package/docs/reference/variables/specification.md +0 -8
- package/docs/reference/variables/status.md +0 -10
- package/docs/reference/variables/table.md +0 -10
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Set up a project
|
|
2
|
+
|
|
3
|
+
What a project installs, how its `vitest.config.ts` is written, how it turns the conventions on, and where a run writes. [Getting started](getting-started.md) walks through the minimum; this page is the reference behind it.
|
|
4
|
+
|
|
5
|
+
## What to install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D @jterrazz/test @jterrazz/typescript vitest
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**`vitest ^5.0.4` and `@jterrazz/typescript ^11` are the only required peers.** The framework registers its matchers into vitest and has no runner of its own. The toolchain, [`@jterrazz/typescript`](https://github.com/jterrazz/package-typescript), is required because the framework prints its refusals through the toolchain's rules kit and its published types extend the toolchain's `JterrazzConfig` (`@jterrazz/typescript/config`). Its lint conventions are a separate, opt-in step ([below](#turning-the-conventions-on)).
|
|
12
|
+
|
|
13
|
+
**The vitest floor is msw's.** The framework carries msw 3, and 5.0.4 is the first vitest whose `@vitest/mocker` accepts it. Under an older one the mocker holds msw 2 at the top of `node_modules` and msw 3 lands nested under this package, where Vite never resolves `msw/browser` for a component test; the peer refuses that tree at install instead.
|
|
14
|
+
|
|
15
|
+
### Project requirements
|
|
16
|
+
|
|
17
|
+
- **ESM.** The package ships ES modules only, and every specification file awaits its constructor at the top level (`export const { api, cleanup } = await specification.api(...)`). Set `"type": "module"` in `package.json`, or name the config files `.mts` (`vitest.config.mts`).
|
|
18
|
+
- **Node 24 or newer**, as `engines` states.
|
|
19
|
+
- **A tsconfig that knows `using` and top-level await.** Tests pin time with `using _ = clock.at(...)` and dispose with `await using` ([Time and doubles](../reference/time-and-doubles.md)), which need `target` and `lib` at `ES2022` or later for top-level await and `ESNext` for `using`, with `module` at `ESNext` or `NodeNext`. The toolchain's tsconfig presets set all of it: `"extends": "@jterrazz/typescript/tsconfig/node"`.
|
|
20
|
+
|
|
21
|
+
**Everything else is an optional peer**, loaded the first time a test needs it. A project that tests no page, no component and no database installs none of them.
|
|
22
|
+
|
|
23
|
+
| Needed by | Install |
|
|
24
|
+
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
25
|
+
| A website visit | `playwright`, then `npx playwright install chromium` once |
|
|
26
|
+
| A component | `@vitest/browser-playwright` (the exact version of `vitest`), `vitest-browser-react`, `vite`, `react`, `react-dom`, `playwright` and a chromium |
|
|
27
|
+
| A mobile screen | `appium`, `webdriverio`, then `npx appium driver install xcuitest` |
|
|
28
|
+
| `postgres()`, `redis()` | `testcontainers`, plus `pg` or `redis` for the driver a table read uses, and a running Docker |
|
|
29
|
+
| `sqlite()` | `better-sqlite3` (no Docker) |
|
|
30
|
+
| A lint spec, `ruleTester()` | `oxlint` |
|
|
31
|
+
| Coverage | `@vitest/coverage-v8` |
|
|
32
|
+
|
|
33
|
+
`msw`, which delivers stubbed network replies, is a direct dependency: nothing to install. An API spec hands your app to `server`, which must answer `request(path, init)` with a Fetch `Response` and, for route coverage, expose Hono's route table. A Hono app does both. Any other framework needs a wrapper of your own for the first, and an OpenAPI document named in `test: { routes }` for the second ([API specs § An app that is not Hono](../guides/api-specs.md#an-app-that-is-not-hono)).
|
|
34
|
+
|
|
35
|
+
**A missing peer is named when it is needed.** A specification's refusal names the packages it lacks and the `npm install -D` that brings them. A service's refusal names the service that asked, the peer, and the install command of the package manager your lockfile names; under pnpm a native binding must also be listed to be built, and the message adds that line:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
found: sqlite() requires `better-sqlite3`, and it is not installed
|
|
39
|
+
why: Every seam is an optional peer of @jterrazz/test, installed by the project that specifies through it.
|
|
40
|
+
fix: pnpm add -D better-sqlite3; under pnpm the binding is not built unless the package is listed: add "better-sqlite3" to `onlyBuiltDependencies` in package.json (or `only-built-dependencies` in .npmrc) and reinstall
|
|
41
|
+
read: docs/reference/linting.md#seam-is-an-optional-peer
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**A native peer can be installed and still not built.** npm since 11, pnpm since 10 and bun since 1.2 withhold a dependency's install script by default, so a native package arrives without its compiled `.node`. `better-sqlite3` 13 ships its binding prebuilt and loads anyway; with 12, `sqlite()` notices on first load and says how to build it:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
found: sqlite() found `better-sqlite3`, and its native binding is not built
|
|
48
|
+
why: A native peer is built by its install script, and npm runs a dependency's install script only once it is told to.
|
|
49
|
+
fix: npm install-scripts approve better-sqlite3 && npm rebuild better-sqlite3
|
|
50
|
+
read: docs/start/set-up-a-project.md#what-to-install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Three more constraints come from the peers themselves:
|
|
54
|
+
|
|
55
|
+
- **One Playwright for the whole family.** This package's `playwright` peer is the exact version it is gated on, and a project declares that version: two revisions on one machine each need their own Chromium build, and `typescript doctor` names the build a project's Playwright wants and the machine lacks. `npx playwright install chromium`, run in the project, provisions it.
|
|
56
|
+
- **The browser provider moves with vitest.** `@vitest/browser-playwright@X` requires `vitest` at exactly `X`, so the two are upgraded together: `npm install -D vitest@5.0.5 @vitest/browser-playwright@5.0.5`. `component()` checks the two versions match and names both when they do not.
|
|
57
|
+
- **Vite `^6.4 || ^7 || ^8`** for a component. `component()` reads the installed major and states the JSX transform on the key that version reads.
|
|
58
|
+
- **The ARIA dialect of a `.aria.yaml` golden is Playwright's.** A Playwright major can reword a role line, and every committed tree golden then moves with it in one `TEST_UPDATE=1` run.
|
|
59
|
+
|
|
60
|
+
Why vitest 5 alone, and why the native seams became optional peers: [ADR-008](https://github.com/jterrazz/package-test/blob/main/docs/decisions/008-vitest-5-node-24-and-the-native-seams-as-optional-peers.md).
|
|
61
|
+
|
|
62
|
+
To try an unreleased build of the framework, install the tarball `npm pack` writes, never a `file:` link: a link makes the project resolve vitest's types twice, and the matchers then type on one copy and not the other. The recipe (the tarball packed into `.artifacts/packages/`, the lockfile entries to drop, bun's cache, the order a wave of projects takes the two packages in) is the toolchain's [Install an unreleased build](https://github.com/jterrazz/package-typescript/blob/main/docs/guides/install-an-unreleased-build.md), since this package is installed with it.
|
|
63
|
+
|
|
64
|
+
## The vitest config
|
|
65
|
+
|
|
66
|
+
The projects a repository runs are read off its tree: one per folder `specs/<specification>/` it keeps (`specs/api/`, `specs/cli/`, `specs/website/` and the rest), `unit` over each root holding a module test (`src/`, `lint/`, a folder of `specs/` no specification names, a `unit` one included), and `component` over the component specs and each root holding a rendered test (`*.test.tsx`). A ground, setup or dot folder is never read. `jterrazz.config.ts` states only how a project departs from the one its tree derives (a helper's options, its own global setups), keyed by its specification, with the reason. The package's standard, `src/standard/standard.ts`, states the one departure every repository shares: the `unit` project runs a worker's files in one module graph (`isolate: false`), since a module test leaves no state behind in a module; a repository whose module tests do states `isolate: true` with its reason. The standard only shapes a project the tree derives or the file declares; it makes none exist. `typescript doctor` prints the projects derived from the tree beside what each file states. The file also declares the project's `kind` and `platform`, which `@jterrazz/typescript` reads to derive the rest of the toolchain ([its Configuration § Kind and platform](https://github.com/jterrazz/package-typescript/blob/main/docs/reference/configuration.md#kind-and-platform)):
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// jterrazz.config.ts
|
|
70
|
+
import { test } from '@jterrazz/test/config';
|
|
71
|
+
import { defineConfig } from '@jterrazz/typescript/config';
|
|
72
|
+
|
|
73
|
+
export default defineConfig({
|
|
74
|
+
kind: 'website',
|
|
75
|
+
platform: 'react',
|
|
76
|
+
presets: [test()],
|
|
77
|
+
test: {
|
|
78
|
+
projects: {
|
|
79
|
+
component: {
|
|
80
|
+
reason: 'the app renders through its own Vite pipeline, inside its providers',
|
|
81
|
+
vite: './vite.config.ts',
|
|
82
|
+
wrap: './src/providers.tsx',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
A project keyed by a specification the package does not ship, a declared one with no `reason`, and `projects` written as a list are refused in four parts, reading this section.
|
|
90
|
+
|
|
91
|
+
`vitest.config.ts` is the file those projects derive, which `typescript fix` writes and `typescript check` holds ([`@jterrazz/typescript`'s Config pass](https://github.com/jterrazz/package-typescript/blob/main/docs/reference/quality-checks.md#the-config-one-file-pass)):
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { vitestConfig } from '@jterrazz/test/vitest';
|
|
95
|
+
|
|
96
|
+
export default await vitestConfig(import.meta.url);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
It reads the `jterrazz.config.ts` beside the module whose `import.meta.url` it is handed (the config file's own folder, wherever vitest, the Vitest extension or knip loads it) and builds each project the tree names, or the file declares, with its helper over the preset below. A project states no `name`, `environment` or `browser`: its helper names it for its specification and sets what the specification needs. A relative `setup` (global setups the project runs, read from the project root), `root` and `vite.resolve.alias` target are read from the project root; `wrap` stays the component's root's. A tree with no test and a file declaring no project leave the config the preset alone. It is the one-liner `@jterrazz/typescript` derives for every editor file (the entry handed the module's own `import.meta.url`, awaited at the top), which vitest and knip's loader both read whole.
|
|
100
|
+
|
|
101
|
+
### The project helpers
|
|
102
|
+
|
|
103
|
+
There is one helper per kind (`unit`, `integration`, `component`, `website`, `mobile`, `api`, `job`, `cli` and `lint`), named by the key of a project, and exported from `@jterrazz/test/vitest` beside `vitestConfig`, for a config written by a tool of your own; called directly, `component()` takes its `root` as an absolute path, since only `vitestConfig` knows where the project sits. Each collects its folder (`specs/<kind>/**/*.spec.ts`, plus the `<case>.spec.yaml` documents for `cli()`) and carries what its kind needs: a browser for `component()`, a simulator session for `mobile()`, and for `api()`, `job()` and `integration()` a global setup that starts each service container once and shares it across every file and project of the run ([Services § One container per run](../reference/services.md#one-container-per-run)). Docker is needed only by a spec that declares `postgres()` or `redis()`: with no Docker running, each such file fails with one sentence naming Docker, and every other file runs. Every helper accepts:
|
|
104
|
+
|
|
105
|
+
| Option | Does |
|
|
106
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `include` / `exclude` | Replace the default globs. A default `exclude` guards the default `include`, so state both or neither |
|
|
108
|
+
| `timeout` | Raise or lower the 30 s default for this project alone: each test's and each hook's, so the `afterAll` that stops what a slow test started has the same budget |
|
|
109
|
+
| `serial` | Run the project's files one at a time (`fileParallelism: false`), when they share one server, one file, one app |
|
|
110
|
+
|
|
111
|
+
`unit()` and `component()` are a pair: `unit()` collects `**/*.test.ts` outside `specs/` and leaves out `**/*.test.tsx`, which `component()` collects. So the suffix beside a file decides which project runs it. `unit()` also takes `roots` when the modules are not at the repository root, and `isolate: false` to run a worker's files in one module graph, only for a project whose tests leave no state behind in a module, and the default `vitestConfig` hands it. `component()` takes the options of the app it renders (`vite`, `wrap`, `viewport`, `clock`, `timezone`, `locale`, `root`), described in [Component specs](../guides/component-specs.md#the-constructor-there-is-none); `mobile()` takes the simulator the run shares ([Mobile specs](../guides/mobile-specs.md#one-session-per-run)).
|
|
112
|
+
|
|
113
|
+
Every project runs in one group, on the workers the preset sizes ([below](#what-the-preset-sets)): a `website` file takes a worker as a node file does, and the `component` pages run beside them in their one Chromium, as many at once as the run has workers. A project whose files run one at a time (`serial`, and `mobile()` unless it states `serial: false`) runs after that group, in a group of its own, so a simulator never shares its machine.
|
|
114
|
+
|
|
115
|
+
`api()`, `job()`, `integration()`, `cli()` and `website()` also take `runner`, the module (or the list of modules) their spec files import their runner from, such as `'./specs/api/api.specification.ts'`. The tree derives it from the folder: every specification module directly in it (`specs/website/*.specification.ts`), each after the sibling modules it imports, so a module reading another's address reads this file's. With it, the files of a worker share one module graph (`isolate: false`) and every one of those modules runs again before each file (`setupFiles`), booting its subject whichever module the file imports: the worker, the framework and the modules the specs import load once per worker instead of once per file, and every file still boots its own subject (an app on its own services, a binary, a served site) and cleans it up. A spec file imports its runner from the specification itself, since a module of the shared graph that imports it keeps the first file's runner. A `cli()` project shares its worker only when its documents bind one of its runners: a document imports the module its `literate` door names, which the shared graph would not run again.
|
|
116
|
+
|
|
117
|
+
An env-gated sub-suite is an `exclude`, not a second project:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const integration = {
|
|
121
|
+
exclude: process.env.E2E_NETWORK ? [] : ['specs/integration/network/**'],
|
|
122
|
+
reason: 'the network specs reach the internet, which a run turns on with E2E_NETWORK',
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### What the preset sets
|
|
127
|
+
|
|
128
|
+
| Setting | Value | Why |
|
|
129
|
+
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
130
|
+
| `test.testTimeout`, `hookTimeout` | `30_000` | vitest's 5 s never survived a container boot or a build |
|
|
131
|
+
| `test.retry` | `0` | A flaky test is fixed or deleted; a retry hides it |
|
|
132
|
+
| `test.restoreMocks`, `unstubGlobals`, `unstubEnvs` | `true` | A spy, a stubbed global or a stubbed env a test forgets to restore would fail a later file that did nothing wrong |
|
|
133
|
+
| `test.exclude` | vitest's defaults + `.artifacts/**` + `**/{__expected__,__fixtures__,__requests__,__seeds__}/**` | What a test stands on is input, never a suite to run; `.artifacts/` holds copies of the project, a mutation sandbox among them |
|
|
134
|
+
| `cacheDir`, `test.coverage.reportsDirectory`, `test.attachmentsDir`, `test.outputFile` | under `.artifacts/vitest/` | Everything a tool writes lives at `.artifacts/<tool>/` ([below](#where-a-run-writes)) |
|
|
135
|
+
| `test.globalSetup` | update mode, the run's temp root | Update mode writes after the run is reported; the temp root is [below](#where-a-run-writes) |
|
|
136
|
+
| `test.maxWorkers` | the Vitest workers of the toolchain's capacity model | A run takes its share of the machine beside the gates running on it, and a run inside a gate's slice (`TYPESCRIPT_CAPACITY`) stays in it ([the toolchain's Quality checks § How many test runners](https://github.com/jterrazz/package-typescript/blob/main/docs/reference/quality-checks.md#how-many-test-runners)) |
|
|
137
|
+
| `test.env.NODE_COMPILE_CACHE` | `.artifacts/node-compile-cache/`, as an absolute path | Every Node process a run starts reuses the code an earlier one compiled ([below](#where-a-run-writes)) |
|
|
138
|
+
|
|
139
|
+
Coverage attaches to every process a run spawns (`autoAttachSubprocess`), and reads `dist/` only to map each bundle back to the source it was built from (`excludeAfterRemap`): a spec that runs the built command counts toward the sources it exercised. A coverage run compiles without the cache: vitest turns it off, since V8 stores a cached script without the source positions precise coverage reads.
|
|
140
|
+
|
|
141
|
+
It sets nothing else on purpose. `fileParallelism`, `reporters`, `environment`, every other `env` variable and every `include` are true of one project and not of another, so a project states them; a helper does it for you. The coverage provider is yours to install.
|
|
142
|
+
|
|
143
|
+
The defaults reach every inline project too, since vitest resolves each project as its own config. A project given as a glob string, a promise or a function is handed back untouched.
|
|
144
|
+
|
|
145
|
+
The `<case>.spec.yaml` documents are collected by the `cli` project, which takes `literate` beside its own options:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const cli = {
|
|
149
|
+
literate: { runner: './specs/cli/run.specification.ts' },
|
|
150
|
+
reason: 'the documents run against the runner the run/ specs share',
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
To adopt the preset from a config written by hand, file each kind of test under its folder, move what a project passed its helper beyond that into `test.projects`, keyed by its specification and with its reason, delete what the table above already says (the 30 s timeouts, `...configDefaults.exclude`, the ground exclusions), and run `typescript fix`, which writes the derived `vitest.config.ts`. A timeout lower or higher than 30 s stays stated, as the project's `timeout`: the preset is a starting point, not a ceiling. Then add `.artifacts/` to `.gitignore`.
|
|
155
|
+
|
|
156
|
+
## Turning the conventions on
|
|
157
|
+
|
|
158
|
+
The conventions travel in the same `test()` preset that sets the vitest defaults, so the `jterrazz.config.ts` [above](#the-vitest-config) already turns them on. The base preset needs no line of its own: the declared `platform` picks the lint profile it runs ([the toolchain's Lint presets § The profiles](https://github.com/jterrazz/package-typescript/blob/main/docs/reference/lint-presets.md#the-profiles)), and `test()` adds this package's rules on top.
|
|
159
|
+
|
|
160
|
+
The linter reads them through the `oxlint.config.ts` that `npx typescript fix` derives, one line like the vitest config:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// oxlint.config.ts
|
|
164
|
+
import { oxlintConfig } from '@jterrazz/typescript/oxlint';
|
|
165
|
+
|
|
166
|
+
export default await oxlintConfig(import.meta.url);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`npx typescript check` then runs all of it: the oxlint plugin, the import and naming rules, and the conventions checker over `specs/`. Nothing is detected from your dependencies: a project that does not list `test()` runs none of these rules, and writes its tests all the same. A rule you set apart is written in `jterrazz.config.ts` with its reason, never in the derived file; how, how to suppress one finding, and the full catalogue are [Linting](../reference/linting.md).
|
|
170
|
+
|
|
171
|
+
## Where a run writes
|
|
172
|
+
|
|
173
|
+
**In the project, only under `.artifacts/`**, one folder per tool, one line in `.gitignore`, one `rm -rf .artifacts` for a clean slate:
|
|
174
|
+
|
|
175
|
+
| Path | Written by | Lifetime |
|
|
176
|
+
| ------------------------------------------------ | ---------------------------------------------------------- | ------------------------------- |
|
|
177
|
+
| `.artifacts/vitest/` | vite's transform cache, vitest's reports | Reused across runs |
|
|
178
|
+
| `.artifacts/vitest/coverage/` | the coverage provider | Rewritten per coverage run |
|
|
179
|
+
| `.artifacts/vitest/sqlite/template-<key>.sqlite` | `sqlite()`'s schema template | Reused until the schema changes |
|
|
180
|
+
| `.artifacts/vitest/evidence/<pid>-.../` | the screenshot of a website or mobile scenario that failed | Kept until the next run starts |
|
|
181
|
+
| `.artifacts/node-compile-cache/` | Node, for the workers and every process they spawn | Reused across runs |
|
|
182
|
+
|
|
183
|
+
**Everything else is scratch, in one temp folder per run.** Before the first worker starts, the preset creates `jterrazz-test-runs-<uid>/<pid>-...` in the OS temp directory and points `TMPDIR`, `TMP` and `TEMP` at it, so every temp folder a worker, a spawned child or a tool it runs makes lands inside. That holds each CLI spec's working directory, the per-worker database copies and a browser's profile. The run removes the folder when it ends, and the next run removes the folder of any run that died first. A CLI spec's working directory goes sooner, once its test has finished, except under `test.concurrent`, where it waits for the run.
|
|
184
|
+
|
|
185
|
+
**Three environment variables are yours to set**: `TEST_UPDATE=1`, which turns on update mode ([Tokens § Update mode](../reference/tokens.md#update-mode-tokens-are-preserved)), `TESTCONTAINERS_REUSE_ENABLE=true`, which keeps the service containers alive from one local run to the next ([Services § Reused across runs, locally](../reference/services.md#reused-across-runs-locally)), and `TEST_MOBILE_HEADED=1`, which shows a mobile run's simulator in a window instead of running it headless ([Mobile specs](../guides/mobile-specs.md#the-simulator-and-what-the-run-leaves-on-it)). The framework also reads `VITEST_POOL_ID`, which vitest sets, to isolate each worker's databases.
|
|
186
|
+
|
|
187
|
+
## Two rough edges of the toolchain's flow
|
|
188
|
+
|
|
189
|
+
- **An `include` that names `.test.ts`** stops collecting the moment `typescript fix` renames a spec. The fix lists every glob or literal it broke, so update them in the same commit; `include-points-at-a-folder` holds the class afterwards.
|
|
190
|
+
- **`typescript baseline` in an npm-hoisted workspace member** cannot resolve oxlint today; run it from a directory where `node_modules/.bin/oxlint` resolves.
|
|
191
|
+
|
|
192
|
+
## Pitfalls
|
|
193
|
+
|
|
194
|
+
- **Forgetting `afterAll(cleanup)` in a specification file.** The services leak into the next suite (rule `cleanup-passed-to-after-all`).
|
|
195
|
+
- **Importing from a subpath the package does not publish** (`@jterrazz/test/matchers`). A test imports from `@jterrazz/test`, `@jterrazz/test/services` and `@jterrazz/test/stubs`; the tool entries are `/vitest`, `/config`, `/oxlint` and `/schema` (rule `no-unpublished-subpath`).
|
|
196
|
+
- **Importing a service or a stub from the root.** `postgres()` comes from `@jterrazz/test/services` and `http` from `@jterrazz/test/stubs`, so a spec that starts no container and serves no stub loads neither; `npx typescript fix` moves such an import to its subpath (rule `service-or-stub-from-its-subpath`).
|
|
197
|
+
- **Writing `browser:` in a config by hand.** `component()` pins the provider to the runner's version, serves the service worker and pre-bundles cold dependencies; a derived config has no place for a hand-written one: a project's `specification` is its helper.
|
|
198
|
+
|
|
199
|
+
## Upgrading
|
|
200
|
+
|
|
201
|
+
Each release's notes are its [GitHub release](https://github.com/jterrazz/package-test/releases); the package keeps no changelog. A major carries no bridge from the one before (no codemod, no rename map, no rule that recognises the old spellings; see [ADR-014](https://github.com/jterrazz/package-test/blob/main/docs/decisions/014-a-major-carries-no-bridge-from-the-one-before.md)), so a project moves by hand, and the rules of the new major name each leftover in their own terms.
|
|
202
|
+
|
|
203
|
+
### From 17 to 18
|
|
204
|
+
|
|
205
|
+
| What a 17 project wrote | What 18 asks for |
|
|
206
|
+
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
207
|
+
| `defineSpecConfig()` and its `SpecConfig` type, in a hand-written config | the derived one-liner, `await vitestConfig(import.meta.url)`, over `test.projects` ([§ The vitest config](#the-vitest-config)) |
|
|
208
|
+
| the `SpecificationConfig` type | nothing in its place: it was the intersection of five chain configurations, and no constructor takes it |
|
|
209
|
+
| `component()` called directly, reading its root off the caller's file | `component({ root })`, an absolute path; a project `vitestConfig` builds is handed its root as before |
|
|
210
|
+
| a strict-stub test matching `declared backend: no stub matches` | `strict stubs: unmatched request`, the one wording every delivery answers an unmatched request with |
|
|
211
|
+
| `vitest` and `@vitest/browser-playwright` below 5.0.4 | both at 5.0.4 or later, in one install ([§ What to install](#what-to-install)) |
|
|
212
|
+
|
|
213
|
+
### From 16 to 17
|
|
214
|
+
|
|
215
|
+
| What a 16 project wrote | What 17 asks for |
|
|
216
|
+
| ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
217
|
+
| `@jterrazz/typescript` ^10 | ^11, released first; its own migration is [its Release § Which number moves](https://github.com/jterrazz/package-typescript/blob/main/docs/guides/release.md#which-number-moves) |
|
|
218
|
+
| a hand-written `vitest.config.ts` | `test.projects` in `jterrazz.config.ts`, and the derived one-liner `typescript fix` writes ([§ The vitest config](#the-vitest-config)) |
|
|
219
|
+
| the `jterrazz-test-check` bin, chained after `typescript check` | `presets: [test()]`; `typescript check`, `fix` and `baseline` run the checker |
|
|
220
|
+
| a bare name: `.seed('two-users.sql')`, `.request('create-user.http')`, the `$`-prefixed alias of the shared fixture pool | a path from the spec file, `file('./__seeds__/two-users.sql')` or `directory(...)`; the shared ground is the special folder of its role at the specs root, `specs/__seeds__/`, `specs/__fixtures__/` and the rest, reached by the path that climbs to it |
|
|
221
|
+
| `defineContract()`, `defineContracts()` and the `Contract*` types | `defineStub()`, `defineStubs()` and the `Stub*` types ([Stubs](../reference/stubs.md)) |
|
|
222
|
+
| `specification.jobs()`, its `jobs` runner and the `jobs` folder under `specs/` | `specification.job()`, the `job` runner and `specs/job/` ([Job specs](../guides/job-specs.md)) |
|
|
223
|
+
| field probes with no whole comparison, the matcher of a table's rows, an api or job `<case>.spec.yaml` | one `toMatch` of the whole result, written in the test or in a `file()` ([Assertions](../reference/assertions.md)); documents stay for cli and lint specs |
|
|
224
|
+
| a rule id, in a config, a suppression or a ratchet key | its new name, stated as its requirement ([Linting § The rule catalogue](../reference/linting.md#the-rule-catalogue)); a directive naming an old id is reported as dead |
|
|
225
|
+
|
|
226
|
+
## Related
|
|
227
|
+
|
|
228
|
+
[Getting started](getting-started.md) · [Component specs](../guides/component-specs.md) · [Linting](../reference/linting.md) · [Release](https://github.com/jterrazz/package-test/blob/main/docs/guides/release.md)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jterrazz/test",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Declarative testing framework for HTTP APIs, CLIs, background jobs, websites, mobile apps
|
|
3
|
+
"version": "18.0.0",
|
|
4
|
+
"description": "Declarative testing framework for HTTP APIs, CLIs, background jobs, websites, mobile apps, rendered components and the rules a project ships: one entry point, real infrastructure and a real browser, golden-file assertions, plus an oxlint convention plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api-testing",
|
|
7
7
|
"browser-mode",
|
|
@@ -25,27 +25,42 @@
|
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "https://github.com/jterrazz/package-test"
|
|
27
27
|
},
|
|
28
|
-
"bin": {
|
|
29
|
-
"jterrazz-test-check": "dist/checker.js"
|
|
30
|
-
},
|
|
31
28
|
"files": [
|
|
32
29
|
"dist",
|
|
33
|
-
"!dist
|
|
34
|
-
"!dist/coverage.*",
|
|
30
|
+
"!dist/**/*.map",
|
|
35
31
|
"docs",
|
|
32
|
+
"!docs/guides/test.md",
|
|
33
|
+
"!docs/decisions",
|
|
36
34
|
"schema"
|
|
37
35
|
],
|
|
38
36
|
"type": "module",
|
|
37
|
+
"imports": {
|
|
38
|
+
"#checker": "./dist/checker.js"
|
|
39
|
+
},
|
|
39
40
|
"exports": {
|
|
40
41
|
".": {
|
|
41
42
|
"types": "./dist/index.d.ts",
|
|
42
43
|
"browser": "./dist/browser/index.js",
|
|
43
44
|
"import": "./dist/index.js"
|
|
44
45
|
},
|
|
46
|
+
"./services": {
|
|
47
|
+
"types": "./dist/services.d.ts",
|
|
48
|
+
"browser": "./dist/browser/services.js",
|
|
49
|
+
"import": "./dist/services.js"
|
|
50
|
+
},
|
|
51
|
+
"./stubs": {
|
|
52
|
+
"types": "./dist/stubs.d.ts",
|
|
53
|
+
"browser": "./dist/browser/stubs.js",
|
|
54
|
+
"import": "./dist/stubs.js"
|
|
55
|
+
},
|
|
45
56
|
"./vitest": {
|
|
46
57
|
"types": "./dist/vitest.d.ts",
|
|
47
58
|
"import": "./dist/vitest.js"
|
|
48
59
|
},
|
|
60
|
+
"./config": {
|
|
61
|
+
"types": "./dist/config.d.ts",
|
|
62
|
+
"import": "./dist/config.js"
|
|
63
|
+
},
|
|
49
64
|
"./oxlint": {
|
|
50
65
|
"import": {
|
|
51
66
|
"types": "./dist/oxlint.d.ts",
|
|
@@ -62,59 +77,61 @@
|
|
|
62
77
|
"registry": "https://registry.npmjs.org/"
|
|
63
78
|
},
|
|
64
79
|
"scripts": {
|
|
65
|
-
"build": "
|
|
66
|
-
"docs": "npm run build && node
|
|
67
|
-
"lint": "typescript check
|
|
68
|
-
"lint:fix": "typescript fix && node dist/checker.js specs --fix",
|
|
80
|
+
"build": "typescript build",
|
|
81
|
+
"docs": "npm run build && node .artifacts/dev/self.js chapters && node .artifacts/dev/schema.js",
|
|
82
|
+
"lint": "typescript check",
|
|
69
83
|
"test": "vitest --run",
|
|
70
|
-
"
|
|
71
|
-
"coverage:check": "node dist/coverage.js"
|
|
84
|
+
"test:repeat": "vitest --run --repeats 10"
|
|
72
85
|
},
|
|
73
86
|
"dependencies": {
|
|
74
|
-
"
|
|
87
|
+
"@oxlint/plugins": "^1.89.0",
|
|
88
|
+
"msw": "^3.0.3",
|
|
89
|
+
"oxc-parser": "^0.150.0",
|
|
75
90
|
"vitest-mock-extended": "^5.0.0",
|
|
76
91
|
"yaml": "^2.9.0"
|
|
77
92
|
},
|
|
78
93
|
"devDependencies": {
|
|
79
|
-
"@hono/node-server": "^2.
|
|
80
|
-
"@jterrazz/typescript": "^
|
|
81
|
-
"@types/better-sqlite3": "^
|
|
82
|
-
"@types/node": "^26.
|
|
83
|
-
"@types/pg": "^8.
|
|
94
|
+
"@hono/node-server": "^2.1.1",
|
|
95
|
+
"@jterrazz/typescript": "^11.1.0",
|
|
96
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
97
|
+
"@types/node": "^26.6.2",
|
|
98
|
+
"@types/pg": "^8.23.1",
|
|
84
99
|
"@types/react": "^19.3.0",
|
|
85
100
|
"@types/react-dom": "^19.3.0",
|
|
86
|
-
"@vitest/browser-playwright": "5.0.
|
|
87
|
-
"@vitest/coverage-v8": "^5.0.
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
101
|
+
"@vitest/browser-playwright": "5.0.5",
|
|
102
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
103
|
+
"ajv": "^8.20.0",
|
|
104
|
+
"better-sqlite3": "^13.0.3",
|
|
105
|
+
"hono": "^4.13.9",
|
|
106
|
+
"oxlint": "1.89.0",
|
|
107
|
+
"pg": "^8.23.0",
|
|
108
|
+
"playwright": "1.63.0",
|
|
93
109
|
"react": "^19.3.0",
|
|
94
110
|
"react-dom": "^19.3.0",
|
|
95
111
|
"react-router": "^8.4.0",
|
|
96
|
-
"redis": "^6.1
|
|
97
|
-
"testcontainers": "^12.0
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"vitest": "5.0.1",
|
|
112
|
+
"redis": "^6.2.1",
|
|
113
|
+
"testcontainers": "^12.1.0",
|
|
114
|
+
"vite": "^8.3.0",
|
|
115
|
+
"vitest": "5.0.5",
|
|
101
116
|
"vitest-browser-react": "^2.3.0",
|
|
102
|
-
"webdriverio": "^9.
|
|
117
|
+
"webdriverio": "^9.32.0"
|
|
103
118
|
},
|
|
104
119
|
"peerDependencies": {
|
|
120
|
+
"@jterrazz/typescript": "^11.0.0",
|
|
105
121
|
"@vitest/browser-playwright": "*",
|
|
106
122
|
"appium": "^3.0.0",
|
|
107
|
-
"better-sqlite3": "^12.11.1",
|
|
123
|
+
"better-sqlite3": "^12.11.1 || ^13",
|
|
124
|
+
"oxlint": "^1.85.0",
|
|
108
125
|
"pg": "^8.22.0",
|
|
109
|
-
"playwright": "
|
|
126
|
+
"playwright": "1.63.0",
|
|
110
127
|
"react": "^18 || ^19",
|
|
111
128
|
"react-dom": "^18 || ^19",
|
|
112
129
|
"redis": "^6.1.0",
|
|
113
130
|
"testcontainers": "^12.0.4",
|
|
114
131
|
"vite": "^6.4.0 || ^7 || ^8",
|
|
115
|
-
"vitest": "^5",
|
|
132
|
+
"vitest": "^5.0.4",
|
|
116
133
|
"vitest-browser-react": "^2.3.0",
|
|
117
|
-
"webdriverio": "^9.30.0"
|
|
134
|
+
"webdriverio": "^9.30.0 || ^10.0.0"
|
|
118
135
|
},
|
|
119
136
|
"peerDependenciesMeta": {
|
|
120
137
|
"@vitest/browser-playwright": {
|
|
@@ -126,6 +143,9 @@
|
|
|
126
143
|
"better-sqlite3": {
|
|
127
144
|
"optional": true
|
|
128
145
|
},
|
|
146
|
+
"oxlint": {
|
|
147
|
+
"optional": true
|
|
148
|
+
},
|
|
129
149
|
"pg": {
|
|
130
150
|
"optional": true
|
|
131
151
|
},
|
package/schema/spec.schema.json
CHANGED
|
@@ -10,8 +10,23 @@
|
|
|
10
10
|
"type": "string"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
+
"allOf": [
|
|
14
|
+
{
|
|
15
|
+
"anyOf": [
|
|
16
|
+
{
|
|
17
|
+
"required": [
|
|
18
|
+
"contains"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"required": [
|
|
23
|
+
"equals"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
13
29
|
"additionalProperties": false,
|
|
14
|
-
"minProperties": 1,
|
|
15
30
|
"properties": {
|
|
16
31
|
"contains": {
|
|
17
32
|
"oneOf": [
|
|
@@ -36,6 +51,20 @@
|
|
|
36
51
|
]
|
|
37
52
|
},
|
|
38
53
|
"run": {
|
|
54
|
+
"allOf": [
|
|
55
|
+
{
|
|
56
|
+
"not": {
|
|
57
|
+
"required": [
|
|
58
|
+
"stdin",
|
|
59
|
+
"waitFor"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"required": [
|
|
65
|
+
"command",
|
|
66
|
+
"exit"
|
|
67
|
+
],
|
|
39
68
|
"additionalProperties": false,
|
|
40
69
|
"properties": {
|
|
41
70
|
"command": {
|
|
@@ -74,10 +103,6 @@
|
|
|
74
103
|
"type": "string"
|
|
75
104
|
}
|
|
76
105
|
},
|
|
77
|
-
"required": [
|
|
78
|
-
"command",
|
|
79
|
-
"exit"
|
|
80
|
-
],
|
|
81
106
|
"type": "object"
|
|
82
107
|
},
|
|
83
108
|
"serveEntry": {
|
|
@@ -102,10 +127,10 @@
|
|
|
102
127
|
"$id": "https://jterrazz.com/schema/jterrazz-test/spec.schema.json",
|
|
103
128
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
104
129
|
"additionalProperties": false,
|
|
105
|
-
"description": "One
|
|
130
|
+
"description": "One case of the @jterrazz/test literate format, one file per test: the ground it stands on, what it does, and what came back.",
|
|
106
131
|
"properties": {
|
|
107
132
|
"description": {
|
|
108
|
-
"description": "The vitest test title
|
|
133
|
+
"description": "The vitest test title: one lowercase line, no trailing period.",
|
|
109
134
|
"type": "string"
|
|
110
135
|
},
|
|
111
136
|
"env": {
|
|
@@ -124,33 +149,34 @@
|
|
|
124
149
|
"description": "A bare word names an env set registered in code; KEY=value is inline. $WORKDIR expands."
|
|
125
150
|
},
|
|
126
151
|
"fixture": {
|
|
152
|
+
"description": "Fixture paths copied into the working directory, layering in order, each relative to this document (`./...`, `../...`) and in the two forms the chain's `file()` and `directory()` take: a trailing `/` names a directory whose contents are spread, without it one file is copied under its own name. The first ground folder a path passes through is __fixtures__/: ./__fixtures__/ beside the document, or specs/__fixtures__/ reached by the path that climbs to it.",
|
|
127
153
|
"oneOf": [
|
|
128
154
|
{
|
|
155
|
+
"pattern": "^\\.\\.?/(?:(?!(?:__expected__|__fixtures__|__requests__|__seeds__)/)[^/]+/)*?__fixtures__/.*$",
|
|
129
156
|
"type": "string"
|
|
130
157
|
},
|
|
131
158
|
{
|
|
132
159
|
"items": {
|
|
160
|
+
"pattern": "^\\.\\.?/(?:(?!(?:__expected__|__fixtures__|__requests__|__seeds__)/)[^/]+/)*?__fixtures__/.*$",
|
|
133
161
|
"type": "string"
|
|
134
162
|
},
|
|
135
163
|
"minItems": 1,
|
|
136
164
|
"type": "array"
|
|
137
165
|
}
|
|
138
|
-
]
|
|
139
|
-
"description": "Fixture paths copied into the working directory, layering in order. `$FIXTURES/<name>` is the shared pool at `<specs-root>/_fixtures/`; a bare path is the ground beside this document, at `_fixtures/<name>`."
|
|
140
|
-
},
|
|
141
|
-
"kind": {
|
|
142
|
-
"default": "cli",
|
|
143
|
-
"description": "The facet this document describes.",
|
|
144
|
-
"enum": [
|
|
145
|
-
"cli"
|
|
146
|
-
],
|
|
147
|
-
"type": "string"
|
|
166
|
+
]
|
|
148
167
|
},
|
|
149
168
|
"runs": {
|
|
169
|
+
"contains": {
|
|
170
|
+
"required": [
|
|
171
|
+
"waitFor"
|
|
172
|
+
]
|
|
173
|
+
},
|
|
150
174
|
"description": "The session: one or more runs, sequential, sharing one working directory.",
|
|
151
175
|
"items": {
|
|
152
176
|
"$ref": "#/$defs/run"
|
|
153
177
|
},
|
|
178
|
+
"maxContains": 1,
|
|
179
|
+
"minContains": 0,
|
|
154
180
|
"minItems": 1,
|
|
155
181
|
"type": "array"
|
|
156
182
|
},
|