@jterrazz/test 16.1.1 → 17.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.
Files changed (304) hide show
  1. package/README.md +45 -171
  2. package/dist/browser/index.js +2 -2980
  3. package/dist/browser/services.js +2 -0
  4. package/dist/browser/stubs.js +2 -0
  5. package/dist/checker.d.ts +6 -1
  6. package/dist/checker.js +4534 -2628
  7. package/dist/config.d.ts +40 -0
  8. package/dist/config.js +309 -0
  9. package/dist/in-place.global-setup.d.ts +11 -0
  10. package/dist/in-place.global-setup.js +21 -0
  11. package/dist/index.d.ts +1653 -3004
  12. package/dist/index.js +5226 -3845
  13. package/dist/mobile-session.global-setup.d.ts +14 -0
  14. package/dist/mobile-session.global-setup.js +31 -0
  15. package/dist/oxlint.cjs +6069 -5634
  16. package/dist/oxlint.d.cts +43 -7212
  17. package/dist/oxlint.d.ts +43 -7212
  18. package/dist/oxlint.js +6127 -5693
  19. package/dist/route-coverage.global-setup.d.ts +42 -0
  20. package/dist/route-coverage.global-setup.js +2 -0
  21. package/dist/services.d.ts +3 -0
  22. package/dist/services.global-setup.d.ts +43 -0
  23. package/dist/services.global-setup.js +2 -0
  24. package/dist/services.js +597 -0
  25. package/dist/shared-appium.adapter.js +428 -0
  26. package/dist/shared-artifacts.js +32 -0
  27. package/dist/shared-chapter.js +7 -0
  28. package/dist/shared-container.port.d.ts +31 -0
  29. package/dist/shared-derived-projects.js +58 -0
  30. package/dist/shared-device.port.d.ts +189 -0
  31. package/dist/shared-exchange.js +447 -0
  32. package/dist/shared-in-place.js +172 -0
  33. package/dist/shared-index.browser.js +3191 -0
  34. package/dist/shared-index.services.d.ts +346 -0
  35. package/dist/shared-index.stubs.d.ts +287 -0
  36. package/dist/shared-json-shape.js +17 -0
  37. package/dist/shared-landmarks.js +71 -0
  38. package/dist/shared-ledger.js +68 -0
  39. package/dist/shared-literate-plugin.js +183 -0
  40. package/dist/shared-manifest.js +1321 -0
  41. package/dist/shared-pause.js +11 -0
  42. package/dist/shared-peer.js +88 -0
  43. package/dist/shared-playwright.adapter.js +330 -0
  44. package/dist/shared-process.adapter.js +74 -0
  45. package/dist/shared-refusal.js +35 -0
  46. package/dist/shared-resolve.js +24 -0
  47. package/dist/shared-route-coverage.global-setup.js +187 -0
  48. package/dist/shared-scenario-failure.js +198 -0
  49. package/dist/shared-serve.js +365 -0
  50. package/dist/shared-service-images.js +10 -0
  51. package/dist/shared-services.global-setup.js +179 -0
  52. package/dist/shared-session-ledger.js +301 -0
  53. package/dist/shared-setup-entry.js +12 -0
  54. package/dist/shared-source-scan.js +133 -0
  55. package/dist/shared-spec-document.js +365 -0
  56. package/dist/shared-specifications.js +26 -0
  57. package/dist/shared-stream-body.js +130 -0
  58. package/dist/shared-stub-server.js +190 -0
  59. package/dist/shared-temp-root.global-setup.js +80 -0
  60. package/dist/shared-test-baseline.js +26 -0
  61. package/dist/shared-test-section.js +58 -0
  62. package/dist/shared-testcontainers.adapter.js +203 -0
  63. package/dist/shared-tokens.js +55 -0
  64. package/dist/shared-yaml-document.js +119 -0
  65. package/dist/stubs.d.ts +2 -0
  66. package/dist/stubs.js +657 -0
  67. package/dist/temp-root.global-setup.d.ts +7 -0
  68. package/dist/temp-root.global-setup.js +2 -0
  69. package/dist/vitest.d.ts +97 -163
  70. package/dist/vitest.js +373 -525
  71. package/docs/README.md +82 -36
  72. package/docs/concepts/architecture.md +118 -0
  73. package/docs/concepts/conventions.md +333 -0
  74. package/docs/guides/api-specs.md +374 -0
  75. package/docs/guides/cli-specs.md +564 -0
  76. package/docs/guides/component-specs.md +252 -0
  77. package/docs/guides/develop.md +94 -0
  78. package/docs/guides/integration-specs.md +181 -0
  79. package/docs/guides/job-specs.md +180 -0
  80. package/docs/guides/lint-specs.md +174 -0
  81. package/docs/guides/mobile-specs.md +319 -0
  82. package/docs/guides/module-tests.md +149 -0
  83. package/docs/guides/release.md +43 -0
  84. package/docs/guides/spec-documents.md +189 -0
  85. package/docs/guides/website-specs.md +413 -0
  86. package/docs/reference/assertions.md +345 -0
  87. package/docs/reference/glossary.md +20 -0
  88. package/docs/reference/linting.md +483 -0
  89. package/docs/reference/services.md +236 -0
  90. package/docs/reference/stubs.md +498 -0
  91. package/docs/reference/time-and-doubles.md +137 -0
  92. package/docs/reference/tokens.md +258 -0
  93. package/docs/reference/visitor.md +221 -0
  94. package/docs/start/getting-started.md +187 -0
  95. package/docs/start/set-up-a-project.md +214 -0
  96. package/package.json +50 -30
  97. package/schema/spec.schema.json +43 -17
  98. package/dist/appium.adapter.js +0 -489
  99. package/dist/artifacts.js +0 -32
  100. package/dist/fixtures.js +0 -110
  101. package/dist/literate.js +0 -1747
  102. package/dist/match.js +0 -804
  103. package/dist/playwright.adapter.js +0 -438
  104. package/dist/server.js +0 -160
  105. package/dist/stream.js +0 -321
  106. package/dist/substring-warning.js +0 -282
  107. package/docs/01-architecture.md +0 -95
  108. package/docs/02-developing.md +0 -351
  109. package/docs/03-testing.md +0 -495
  110. package/docs/04-operating.md +0 -101
  111. package/docs/05-module-tests.md +0 -152
  112. package/docs/06-integration.md +0 -180
  113. package/docs/07-component.md +0 -246
  114. package/docs/08-website.md +0 -404
  115. package/docs/09-mobile.md +0 -270
  116. package/docs/10-api.md +0 -264
  117. package/docs/11-jobs.md +0 -157
  118. package/docs/12-cli.md +0 -677
  119. package/docs/13-elements.md +0 -248
  120. package/docs/14-assertions.md +0 -314
  121. package/docs/15-tokens.md +0 -253
  122. package/docs/16-contracts.md +0 -438
  123. package/docs/17-services.md +0 -188
  124. package/docs/18-conventions.md +0 -332
  125. package/docs/19-linting.md +0 -512
  126. package/docs/decisions/001-v9-conventions-on-three-channels.md +0 -50
  127. package/docs/decisions/002-the-statique-channel-holds-only-what-upstream-does-not.md +0 -49
  128. package/docs/decisions/003-a-rendered-component-is-a-facet-on-vitest-browser-mode.md +0 -84
  129. package/docs/decisions/004-a-module-against-real-services-or-a-golden-is-the-integration-facet.md +0 -81
  130. package/docs/decisions/005-the-doubles-ladder-is-closed.md +0 -86
  131. package/docs/decisions/006-the-catalogue-reaches-a-file-by-its-role.md +0 -245
  132. package/docs/decisions/007-compose-mode-leaves-the-package.md +0 -53
  133. package/docs/decisions/008-vitest-5-node-24-and-the-native-seams-as-optional-peers.md +0 -75
  134. package/docs/decisions/_template.md +0 -22
  135. package/docs/reference/classes/Matcher.md +0 -120
  136. package/docs/reference/classes/ProcessHandle.md +0 -368
  137. package/docs/reference/functions/defineContract.md +0 -39
  138. package/docs/reference/functions/defineContracts.md +0 -36
  139. package/docs/reference/functions/disabled.md +0 -28
  140. package/docs/reference/functions/enabled.md +0 -20
  141. package/docs/reference/functions/focused.md +0 -26
  142. package/docs/reference/functions/mockOf.md +0 -79
  143. package/docs/reference/functions/postgres.md +0 -31
  144. package/docs/reference/functions/process.md +0 -33
  145. package/docs/reference/functions/redis.md +0 -28
  146. package/docs/reference/functions/required.md +0 -41
  147. package/docs/reference/functions/selected.md +0 -26
  148. package/docs/reference/functions/sqlite.md +0 -33
  149. package/docs/reference/functions/testId.md +0 -20
  150. package/docs/reference/functions/text.md +0 -40
  151. package/docs/reference/functions/valued.md +0 -28
  152. package/docs/reference/functions/waitUntil.md +0 -46
  153. package/docs/reference/functions/within.md +0 -29
  154. package/docs/reference/index.md +0 -196
  155. package/docs/reference/interfaces/BaseResult.md +0 -87
  156. package/docs/reference/interfaces/CallResult.md +0 -160
  157. package/docs/reference/interfaces/CaptureScope.md +0 -82
  158. package/docs/reference/interfaces/CliResult.md +0 -253
  159. package/docs/reference/interfaces/ContainerAccessor.md +0 -166
  160. package/docs/reference/interfaces/DirectoryAccessor.md +0 -33
  161. package/docs/reference/interfaces/FetchResult.md +0 -180
  162. package/docs/reference/interfaces/FilesystemAccessor.md +0 -46
  163. package/docs/reference/interfaces/HttpResult.md +0 -126
  164. package/docs/reference/interfaces/JsonAccessor.md +0 -46
  165. package/docs/reference/interfaces/PageResult.md +0 -356
  166. package/docs/reference/interfaces/RenderResult.md +0 -72
  167. package/docs/reference/interfaces/RenderedText.md +0 -110
  168. package/docs/reference/interfaces/ResponseAccessor.md +0 -47
  169. package/docs/reference/interfaces/ScreenResult.md +0 -128
  170. package/docs/reference/interfaces/TableAccessor.md +0 -26
  171. package/docs/reference/interfaces/TextAccessor.md +0 -96
  172. package/docs/reference/type-aliases/ApiHandle.md +0 -68
  173. package/docs/reference/type-aliases/ApiSpecification.md +0 -213
  174. package/docs/reference/type-aliases/ApiSpecificationOptions.md +0 -68
  175. package/docs/reference/type-aliases/BrowserConsoleMessage.md +0 -30
  176. package/docs/reference/type-aliases/BrowserLinkElement.md +0 -50
  177. package/docs/reference/type-aliases/BrowserMetaElement.md +0 -40
  178. package/docs/reference/type-aliases/BrowserOpenOptions.md +0 -87
  179. package/docs/reference/type-aliases/BrowserPage.md +0 -132
  180. package/docs/reference/type-aliases/BrowserPort.md +0 -51
  181. package/docs/reference/type-aliases/CliEnv.md +0 -11
  182. package/docs/reference/type-aliases/CliHandle.md +0 -80
  183. package/docs/reference/type-aliases/CliInput.md +0 -36
  184. package/docs/reference/type-aliases/CliOutput.md +0 -46
  185. package/docs/reference/type-aliases/CliPort.md +0 -58
  186. package/docs/reference/type-aliases/CliSpecification.md +0 -144
  187. package/docs/reference/type-aliases/CliSpecificationOptions.md +0 -134
  188. package/docs/reference/type-aliases/ComponentChain.md +0 -156
  189. package/docs/reference/type-aliases/ComponentScenario.md +0 -20
  190. package/docs/reference/type-aliases/ComponentUi.md +0 -47
  191. package/docs/reference/type-aliases/ComponentVisitor.md +0 -10
  192. package/docs/reference/type-aliases/ContainerPort.md +0 -113
  193. package/docs/reference/type-aliases/Contract.md +0 -68
  194. package/docs/reference/type-aliases/ContractInput.md +0 -13
  195. package/docs/reference/type-aliases/ContractRequest.md +0 -95
  196. package/docs/reference/type-aliases/ContractResponder.md +0 -23
  197. package/docs/reference/type-aliases/ContractResponse.md +0 -78
  198. package/docs/reference/type-aliases/ContractResponseValue.md +0 -13
  199. package/docs/reference/type-aliases/Contracts.md +0 -48
  200. package/docs/reference/type-aliases/DatabaseKeys.md +0 -16
  201. package/docs/reference/type-aliases/DatabasePort.md +0 -72
  202. package/docs/reference/type-aliases/DeviceOpenOptions.md +0 -46
  203. package/docs/reference/type-aliases/DevicePort.md +0 -51
  204. package/docs/reference/type-aliases/DeviceScreen.md +0 -32
  205. package/docs/reference/type-aliases/DeviceTimeouts.md +0 -39
  206. package/docs/reference/type-aliases/DockerSpecConfig.md +0 -43
  207. package/docs/reference/type-aliases/DomMount.md +0 -21
  208. package/docs/reference/type-aliases/ElementKind.md +0 -27
  209. package/docs/reference/type-aliases/ElementMatch.md +0 -74
  210. package/docs/reference/type-aliases/ElementOptions.md +0 -29
  211. package/docs/reference/type-aliases/ElementRef.md +0 -128
  212. package/docs/reference/type-aliases/ExecOptions.md +0 -37
  213. package/docs/reference/type-aliases/FileAccessor.md +0 -54
  214. package/docs/reference/type-aliases/HonoApp.md +0 -31
  215. package/docs/reference/type-aliases/HttpContractFilter.md +0 -49
  216. package/docs/reference/type-aliases/HttpResponseInit.md +0 -46
  217. package/docs/reference/type-aliases/HttpStreamInit.md +0 -58
  218. package/docs/reference/type-aliases/IntegrationHandle.md +0 -46
  219. package/docs/reference/type-aliases/IntegrationSpecification.md +0 -111
  220. package/docs/reference/type-aliases/IntegrationSpecificationOptions.md +0 -42
  221. package/docs/reference/type-aliases/Intercept.md +0 -19
  222. package/docs/reference/type-aliases/InterceptOptions.md +0 -28
  223. package/docs/reference/type-aliases/InterceptScope.md +0 -11
  224. package/docs/reference/type-aliases/IsolationStrategy.md +0 -75
  225. package/docs/reference/type-aliases/JobHandle.md +0 -34
  226. package/docs/reference/type-aliases/JobsHandle.md +0 -57
  227. package/docs/reference/type-aliases/JobsResult.md +0 -16
  228. package/docs/reference/type-aliases/JobsSpecification.md +0 -94
  229. package/docs/reference/type-aliases/JobsSpecificationOptions.md +0 -56
  230. package/docs/reference/type-aliases/LandmarkKind.md +0 -20
  231. package/docs/reference/type-aliases/LiterateRunFlags.md +0 -27
  232. package/docs/reference/type-aliases/LiterateServeRegistration.md +0 -70
  233. package/docs/reference/type-aliases/MatchFixtureOptions.md +0 -27
  234. package/docs/reference/type-aliases/MatchableRequest.md +0 -61
  235. package/docs/reference/type-aliases/MatcherKind.md +0 -34
  236. package/docs/reference/type-aliases/MobileBackendOptions.md +0 -28
  237. package/docs/reference/type-aliases/MobileElementKind.md +0 -14
  238. package/docs/reference/type-aliases/MobileElementMatch.md +0 -60
  239. package/docs/reference/type-aliases/MobileElementRef.md +0 -20
  240. package/docs/reference/type-aliases/MobileHandle.md +0 -65
  241. package/docs/reference/type-aliases/MobileScenario.md +0 -20
  242. package/docs/reference/type-aliases/MobileSpecification.md +0 -51
  243. package/docs/reference/type-aliases/MobileSpecificationOptions.md +0 -126
  244. package/docs/reference/type-aliases/MobileVisitor.md +0 -81
  245. package/docs/reference/type-aliases/MockOfOptions.md +0 -26
  246. package/docs/reference/type-aliases/MockPort.md +0 -10
  247. package/docs/reference/type-aliases/PinnedClock.md +0 -10
  248. package/docs/reference/type-aliases/PostgresOptions.md +0 -32
  249. package/docs/reference/type-aliases/ProcessOptions.md +0 -112
  250. package/docs/reference/type-aliases/RedisOptions.md +0 -20
  251. package/docs/reference/type-aliases/RenderSubject.md +0 -12
  252. package/docs/reference/type-aliases/ScreenNode.md +0 -67
  253. package/docs/reference/type-aliases/ServerPort.md +0 -36
  254. package/docs/reference/type-aliases/ServerResponse.md +0 -46
  255. package/docs/reference/type-aliases/ServerSpec.md +0 -21
  256. package/docs/reference/type-aliases/ServiceHandle.md +0 -216
  257. package/docs/reference/type-aliases/ServiceRecord.md +0 -12
  258. package/docs/reference/type-aliases/SpecDocument.md +0 -84
  259. package/docs/reference/type-aliases/SpecEnvToken.md +0 -21
  260. package/docs/reference/type-aliases/SpecFileAssertion.md +0 -27
  261. package/docs/reference/type-aliases/SpecFixture.md +0 -30
  262. package/docs/reference/type-aliases/SpecKind.md +0 -8
  263. package/docs/reference/type-aliases/SpecRun.md +0 -108
  264. package/docs/reference/type-aliases/SpecServeEntry.md +0 -40
  265. package/docs/reference/type-aliases/SpecStream.md +0 -32
  266. package/docs/reference/type-aliases/SpecificationConfig.md +0 -290
  267. package/docs/reference/type-aliases/SqliteOptions.md +0 -36
  268. package/docs/reference/type-aliases/SseEvent.md +0 -58
  269. package/docs/reference/type-aliases/StreamBody.md +0 -61
  270. package/docs/reference/type-aliases/TextFilter.md +0 -22
  271. package/docs/reference/type-aliases/VisitScenario.md +0 -20
  272. package/docs/reference/type-aliases/Visitor.md +0 -215
  273. package/docs/reference/type-aliases/WaitUntilOptions.md +0 -46
  274. package/docs/reference/type-aliases/WebsiteBackendOptions.md +0 -37
  275. package/docs/reference/type-aliases/WebsiteHandle.md +0 -51
  276. package/docs/reference/type-aliases/WebsiteSpecification.md +0 -118
  277. package/docs/reference/type-aliases/WebsiteSpecificationOptions.md +0 -40
  278. package/docs/reference/variables/anthropic.md +0 -19
  279. package/docs/reference/variables/banner.md +0 -10
  280. package/docs/reference/variables/button.md +0 -10
  281. package/docs/reference/variables/clock.md +0 -16
  282. package/docs/reference/variables/complementary.md +0 -10
  283. package/docs/reference/variables/component.md +0 -10
  284. package/docs/reference/variables/content.md +0 -10
  285. package/docs/reference/variables/contentinfo.md +0 -10
  286. package/docs/reference/variables/dialog.md +0 -10
  287. package/docs/reference/variables/field.md +0 -10
  288. package/docs/reference/variables/form.md +0 -10
  289. package/docs/reference/variables/heading.md +0 -10
  290. package/docs/reference/variables/http.md +0 -40
  291. package/docs/reference/variables/intercept.md +0 -11
  292. package/docs/reference/variables/link.md +0 -10
  293. package/docs/reference/variables/listitem.md +0 -10
  294. package/docs/reference/variables/main.md +0 -10
  295. package/docs/reference/variables/match.md +0 -8
  296. package/docs/reference/variables/navigation.md +0 -10
  297. package/docs/reference/variables/openai.md +0 -21
  298. package/docs/reference/variables/option.md +0 -17
  299. package/docs/reference/variables/region.md +0 -10
  300. package/docs/reference/variables/row.md +0 -10
  301. package/docs/reference/variables/search.md +0 -10
  302. package/docs/reference/variables/specification.md +0 -8
  303. package/docs/reference/variables/status.md +0 -10
  304. package/docs/reference/variables/table.md +0 -10
@@ -0,0 +1,71 @@
1
+ //#region src/visitor/targets/roles.ts
2
+ const stated = (options) => options?.exact === void 0 ? {} : { exact: options.exact };
3
+ const named = (kind) => (name, options) => ({
4
+ kind,
5
+ name,
6
+ ...stated(options)
7
+ });
8
+ const optionallyNamed = (kind) => (name, options) => ({
9
+ kind,
10
+ ...name === void 0 ? {} : { name },
11
+ ...stated(options)
12
+ });
13
+ /** A button (or element with the button role), by accessible name. */
14
+ const button = named("button");
15
+ /** A form field, by label. */
16
+ const field = named("field");
17
+ /** A heading, by accessible name. */
18
+ const heading = named("heading");
19
+ /** A link, by accessible name. */
20
+ const link = named("link");
21
+ /** An element containing the given text. */
22
+ const content = named("text");
23
+ /** An option of a select or listbox, by label; asserted by presence, since a collapsed select's options have no box. */
24
+ const option = named("option");
25
+ /** A modal or non-modal `<dialog>`, by accessible name. A closed one is absent. */
26
+ const dialog = optionallyNamed("dialog");
27
+ /** A live region announcing a result: `role="status"`, an `<output>`. */
28
+ const status = optionallyNamed("status");
29
+ /** A table, by its caption or accessible name. */
30
+ const table = optionallyNamed("table");
31
+ /** A row of a table or grid, by the text of its cells. */
32
+ const row = optionallyNamed("row");
33
+ /** An item of a list, by its text. */
34
+ const listitem = optionallyNamed("listitem");
35
+ /** The escape hatch: an element by `data-testid`. Prefer user-facing targets. */
36
+ const testId = (id) => ({
37
+ kind: "testId",
38
+ name: id
39
+ });
40
+ //#endregion
41
+ //#region src/visitor/targets/landmarks.ts
42
+ /** The `banner` landmark: the page header. */
43
+ const banner = optionallyNamed("banner");
44
+ /** The `complementary` landmark: an `<aside>`, a sidebar. */
45
+ const complementary = optionallyNamed("complementary");
46
+ /** The `contentinfo` landmark: the page footer. */
47
+ const contentinfo = optionallyNamed("contentinfo");
48
+ /** The `form` landmark: a form carrying an accessible name. */
49
+ const form = optionallyNamed("form");
50
+ /** The `main` landmark: the primary content of the document. */
51
+ const main = optionallyNamed("main");
52
+ /** The `navigation` landmark: a `<nav>`. Name it when a page has several. */
53
+ const navigation = optionallyNamed("navigation");
54
+ /** The `region` landmark: a `<section>` carrying an accessible name. */
55
+ const region = optionallyNamed("region");
56
+ /** The `search` landmark. */
57
+ const search = optionallyNamed("search");
58
+ /** Restrict a target to the inside of another: `click(within(navigation(), link('Articles')))`. */
59
+ const within = (scope, target) => ({
60
+ ...target,
61
+ scope: target.scope ? within(scope, target.scope) : scope
62
+ });
63
+ function scopeChain(target) {
64
+ const chain = [];
65
+ for (let current = target; current; current = current.scope) chain.unshift(current);
66
+ return chain;
67
+ }
68
+ //#endregion
69
+ export { testId as S, listitem as _, main as a, status as b, scopeChain as c, button as d, content as f, link as g, heading as h, form as i, search as l, field as m, complementary as n, navigation as o, dialog as p, contentinfo as r, region as s, banner as t, within as u, option as v, table as x, row as y };
70
+
71
+ //# sourceMappingURL=shared-landmarks.js.map
@@ -0,0 +1,68 @@
1
+ import { t as isRecord } from "./shared-json-shape.js";
2
+ import { l as VITEST_ARTIFACTS_DIR } from "./shared-artifacts.js";
3
+ import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { randomUUID } from "node:crypto";
6
+ //#region src/expectations/in-place/update.ts
7
+ /** `TEST_UPDATE=1` or vitest's `-u` / `--update`. */
8
+ function shouldUpdateSnapshots() {
9
+ if (process.env.TEST_UPDATE === "1") return true;
10
+ return process.argv.includes("-u") || process.argv.includes("--update");
11
+ }
12
+ const UPDATE_HINT = "Run with TEST_UPDATE=1 (or vitest -u) to create it.";
13
+ const FROZEN_HINT = "This golden is `{ frozen }`: update mode never writes it. Write the file by hand, or drop `{ frozen }` for one TEST_UPDATE=1 run and put it back.";
14
+ function missingHint(frozen) {
15
+ return frozen ? FROZEN_HINT : UPDATE_HINT;
16
+ }
17
+ //#endregion
18
+ //#region src/specifications/api/routes/ledger.ts
19
+ const isLedger = (value) => isRecord(value) && Array.isArray(value.reached) && (value.declared === void 0 || Array.isArray(value.declared));
20
+ function entriesOf(directory) {
21
+ try {
22
+ return readdirSync(directory, { withFileTypes: true });
23
+ } catch {
24
+ return [];
25
+ }
26
+ }
27
+ const ROUTES_DIR = `${VITEST_ARTIFACTS_DIR}/routes`;
28
+ function shardLedgersDir(shard) {
29
+ return `${ROUTES_DIR}/shard-${shard.index}-${shard.count}`;
30
+ }
31
+ function clearLedgers(directory) {
32
+ rmSync(directory, {
33
+ force: true,
34
+ recursive: true
35
+ });
36
+ }
37
+ function writeLedger(directory, ledger) {
38
+ mkdirSync(directory, { recursive: true });
39
+ writeFileSync(join(directory, `${randomUUID()}.json`), `${JSON.stringify(ledger)}\n`);
40
+ }
41
+ const parsed = (path) => JSON.parse(readFileSync(path, "utf8"));
42
+ function readLedgers(directory) {
43
+ return entriesOf(directory).filter((entry) => entry.name.endsWith(".json")).map((entry) => parsed(join(directory, entry.name))).filter((ledger) => isLedger(ledger));
44
+ }
45
+ const PARTIAL_MARK = "partial";
46
+ function markPartial(directory) {
47
+ mkdirSync(directory, { recursive: true });
48
+ writeFileSync(join(directory, PARTIAL_MARK), "");
49
+ }
50
+ function measure(ledgers) {
51
+ const tables = ledgers.map((ledger) => ledger.declared);
52
+ return {
53
+ declared: tables.every((table) => table !== void 0) ? tables.flat() : void 0,
54
+ reached: ledgers.flatMap((ledger) => ledger.reached)
55
+ };
56
+ }
57
+ async function routesLedger() {
58
+ try {
59
+ const { inject } = await import("vitest");
60
+ return inject("routesLedger");
61
+ } catch {
62
+ return;
63
+ }
64
+ }
65
+ //#endregion
66
+ export { readLedgers as a, writeLedger as c, measure as i, missingHint as l, clearLedgers as n, routesLedger as o, markPartial as r, shardLedgersDir as s, ROUTES_DIR as t, shouldUpdateSnapshots as u };
67
+
68
+ //# sourceMappingURL=shared-ledger.js.map
@@ -0,0 +1,183 @@
1
+ import { n as refusal } from "./shared-refusal.js";
2
+ import { d as isRelativePath, i as readSpecFile, l as SpecSyntaxError, u as dedent } from "./shared-spec-document.js";
3
+ import { readFileSync } from "node:fs";
4
+ import { basename, isAbsolute, resolve } from "node:path";
5
+ //#region src/disk/spec-path.ts
6
+ const DISK_KEY = "@jterrazz/test:disk";
7
+ const DISK = Symbol.for(DISK_KEY);
8
+ /** Name one file, by its path from the spec file. */
9
+ function file(path) {
10
+ requireRelativePath("file", path);
11
+ if (path.endsWith("/")) {
12
+ const bare = path.replace(/\/+$/u, "");
13
+ throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
14
+ fix: `name the directory with directory(${JSON.stringify(path)}), or the file without its /: file(${JSON.stringify(bare)})`,
15
+ found: `file(${JSON.stringify(path)}), a path ending in /, which is a directory's`
16
+ }));
17
+ }
18
+ return diskValue("file", path);
19
+ }
20
+ function diskValue(brand, path) {
21
+ const value = {
22
+ [DISK]: brand,
23
+ path
24
+ };
25
+ Object.defineProperty(value, Symbol.match, { value: () => {
26
+ throw new TypeError(refusal("one-verb-per-meaning", {
27
+ fix: `wrap the string to golden it, \`expect(text(value)).toMatch(${brand}(...))\`, or compare it to a value, \`toMatch('...')\``,
28
+ found: `toMatch(${brand}(${JSON.stringify(path)})) on a string, a value with no golden`
29
+ }));
30
+ } });
31
+ return Object.freeze(value);
32
+ }
33
+ /** Name one directory, by its path from the spec file, ending in `/`. */
34
+ function directory(path) {
35
+ requireRelativePath("directory", path);
36
+ if (!path.endsWith("/")) throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
37
+ fix: `end it in /: directory(${JSON.stringify(`${path}/`)}), or name a file with file(${JSON.stringify(path)})`,
38
+ found: `directory(${JSON.stringify(path)}), a path that does not end in /`
39
+ }));
40
+ return diskValue("directory", path);
41
+ }
42
+ function isDiskFile(value) {
43
+ return brandOf(value) === "file";
44
+ }
45
+ function isDiskDirectory(value) {
46
+ return brandOf(value) === "directory";
47
+ }
48
+ function isDiskTarget(value) {
49
+ return brandOf(value) !== void 0;
50
+ }
51
+ function brandOf(value) {
52
+ if (value === null || typeof value !== "object") return;
53
+ const brand = Reflect.get(value, DISK);
54
+ return brand === "file" || brand === "directory" ? brand : void 0;
55
+ }
56
+ function spelled(value) {
57
+ if (isDiskTarget(value)) return `${brandOf(value)}(${JSON.stringify(value.path)})`;
58
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
59
+ }
60
+ function requireDiskFile(verb, value, extension = "") {
61
+ if (!isDiskFile(value)) throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
62
+ fix: `name one file: ${verb}(file('./${exampleOf(verb, extension)}'))`,
63
+ found: isDiskDirectory(value) ? `${verb}(${spelled(value)}), a directory where one file is read` : `${verb}(${spelled(value)}), a value where a file is read`
64
+ }));
65
+ if (!value.path.endsWith(extension)) throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
66
+ fix: `name the ${extension} file ${verb}() reads: ${verb}(file('./${exampleOf(verb, extension)}'))`,
67
+ found: `${verb}(${spelled(value)}), a file not ending in ${extension}`
68
+ }));
69
+ return value;
70
+ }
71
+ function requireDiskTarget(verb, value) {
72
+ if (!isDiskTarget(value)) throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
73
+ fix: `name the disk: ${verb}(file('./<path>')) for a file, ${verb}(directory('./<path>/')) for a directory`,
74
+ found: `${verb}(${spelled(value)}), a value where the disk is read`
75
+ }));
76
+ return value;
77
+ }
78
+ function exampleOf(verb, extension) {
79
+ return {
80
+ fixture: "__fixtures__/config.json",
81
+ request: "__requests__/create.http",
82
+ run: "case.spec.yaml",
83
+ seed: "__seeds__/rows.sql"
84
+ }[verb] ?? `__expected__/output${extension || ".txt"}`;
85
+ }
86
+ function asRelative(path) {
87
+ const bare = typeof path === "string" ? path.replace(/^\/+/u, "") : "";
88
+ return `./${bare === "" ? "__expected__/output.txt" : bare}`;
89
+ }
90
+ function requireRelativePath(call, path) {
91
+ if (typeof path !== "string" || !isRelativePath(path)) throw new TypeError(refusal("disk-named-by-relative-path-at-runtime", {
92
+ fix: `start it with ./ or ../, from the spec file: ${call}('${asRelative(path)}')`,
93
+ found: `${call}(${JSON.stringify(path)}), a path that is not relative to the spec file`
94
+ }));
95
+ }
96
+ //#endregion
97
+ //#region src/disk/resolved-spec-path.ts
98
+ function resolveSpecPath(verb, path, specDir) {
99
+ requireRelativePath(verb, path);
100
+ return resolve(specDir, path);
101
+ }
102
+ //#endregion
103
+ //#region src/expectations/in-place/render.ts
104
+ function escapeTemplate(text) {
105
+ return text.replaceAll("\\", String.raw`\\`).replaceAll("`", "\\`").replaceAll("${", "\\${");
106
+ }
107
+ function renderText(text, indent) {
108
+ if (!text.includes("\n")) return `\`${escapeTemplate(text)}\``;
109
+ const inner = `${indent} `;
110
+ const lines = text.split("\n");
111
+ const last = String(lines.pop());
112
+ const block = `\n${lines.map((line) => line === "" ? "" : `${inner}${line}`).join("\n")}\n${last === "" ? indent : `${inner}${last}`}`;
113
+ return dedent(block) === text ? `\`${escapeTemplate(block)}\`` : JSON.stringify(text);
114
+ }
115
+ const NUMBER_MARK = "@@in-place-number:";
116
+ const GROUPED_FROM = 1e4;
117
+ function grouped(value) {
118
+ return typeof value === "number" && Number.isSafeInteger(value) && Math.abs(value) >= GROUPED_FROM ? `${NUMBER_MARK}${String(value).replaceAll(/\B(?=(?:\d{3})+$)/gu, "_")}` : value;
119
+ }
120
+ const MARKED = new RegExp(`"${NUMBER_MARK}(?<digits>-?[\\d_]+)"`, "gu");
121
+ const literal = (value, space) => JSON.stringify(value, (_key, item) => grouped(item), space)?.replaceAll(MARKED, "$<digits>");
122
+ function renderValue(value, indent) {
123
+ return (literal(value, 4) ?? "undefined").split("\n").join(`\n${indent}`);
124
+ }
125
+ function renderRows(rows, indent) {
126
+ if (rows.length === 0) return "[]";
127
+ return `[\n${rows.map((row) => `${indent} [${row.map((cell) => literal(cell) ?? "null").join(", ")}],`).join("\n")}\n${indent}]`;
128
+ }
129
+ //#endregion
130
+ //#region src/specifications/cli/documents/literate-plugin.ts
131
+ const SPEC_FILE = /\.spec\.yaml(?:\?.*)?$/u;
132
+ function grammarRefusal(error, displayPath) {
133
+ return new Error(refusal({
134
+ fix: "write the key the grammar names; the reason prints the accepted set",
135
+ found: `${displayPath}:${error.line}: ${error.reason}`,
136
+ read: "docs/reference/linting.md#document-follows-its-grammar",
137
+ why: "A spec document follows one grammar, read by the parser the runner and the linter share: closed keys, `description:` and `runs:` required, `command:` and `exit:` in every run."
138
+ }), { cause: error });
139
+ }
140
+ function readDocument(content, displayPath) {
141
+ try {
142
+ return readSpecFile(content, displayPath);
143
+ } catch (error) {
144
+ throw error instanceof SpecSyntaxError ? grammarRefusal(error, displayPath) : error;
145
+ }
146
+ }
147
+ function literateModule(content, filePath, runnerPath) {
148
+ const { description } = readDocument(content, filePath).document;
149
+ return [
150
+ "import { test } from 'vitest';",
151
+ `import { cli } from ${JSON.stringify(runnerPath)};`,
152
+ "",
153
+ `test(${JSON.stringify(description)}, async () => {`,
154
+ ` await cli.run({ [Symbol.for(${JSON.stringify(DISK_KEY)})]: 'file', path: ${JSON.stringify(`./${basename(filePath)}`)} });`,
155
+ "});",
156
+ ""
157
+ ].join("\n");
158
+ }
159
+ function cleanId(id) {
160
+ return id.split("?")[0] ?? id;
161
+ }
162
+ function literate(options) {
163
+ const include = options.include ?? ["**/*.spec.yaml"];
164
+ let root = process.cwd();
165
+ return {
166
+ config: () => ({ test: { include } }),
167
+ configResolved: (resolved) => {
168
+ ({root} = resolved);
169
+ },
170
+ enforce: "pre",
171
+ load: (id) => {
172
+ if (!SPEC_FILE.test(id)) return null;
173
+ const filePath = cleanId(id);
174
+ const runnerPath = isAbsolute(options.runner) ? options.runner : resolve(root, options.runner);
175
+ return literateModule(readFileSync(filePath, "utf8"), filePath, runnerPath);
176
+ },
177
+ name: "jterrazz-test:literate"
178
+ };
179
+ }
180
+ //#endregion
181
+ export { renderValue as a, file as c, isDiskTarget as d, requireDiskFile as f, renderText as i, isDiskDirectory as l, literate as n, resolveSpecPath as o, requireDiskTarget as p, renderRows as r, directory as s, grammarRefusal as t, isDiskFile as u };
182
+
183
+ //# sourceMappingURL=shared-literate-plugin.js.map