@jterrazz/test 16.1.0 → 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 -2867
  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 +4551 -2612
  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 -3002
  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 +6073 -5616
  16. package/dist/oxlint.d.cts +43 -7212
  17. package/dist/oxlint.d.ts +43 -7212
  18. package/dist/oxlint.js +6065 -5609
  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 +374 -507
  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 -349
  104. package/dist/server.js +0 -160
  105. package/dist/stream.js +0 -321
  106. package/dist/substring-warning.js +0 -244
  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 -242
  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 -305
  125. package/docs/19-linting.md +0 -510
  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,40 @@
1
+ import { Preset } from "@jterrazz/typescript/config";
2
+ //#region lint/consumer/rulebook/preset.d.ts
3
+ declare function testPreset(): Preset;
4
+ //#endregion
5
+ //#region lint/kit/project/settings.d.ts
6
+ /** The `test` section of `jterrazz.config.ts`. */
7
+ type TestSettings = {
8
+ /** The path every api route is mounted under (`'/api'`), left out of the folder each route's subject derives. */
9
+ basePath?: `/${string}`;
10
+ /** Api collections no English plural names (`data`, `people`), by route segment. */
11
+ collections?: readonly string[];
12
+ /** Routes the api takes on any method (`app.all('/mcp', ...)`), each path mapped to why it takes any. */
13
+ methodless?: Readonly<Record<string, string>>;
14
+ production?: {
15
+ allow: Readonly<Record<string, string>>;
16
+ };
17
+ /** How a project departs from the one its tree derives, keyed by its specification, with the reason. */
18
+ projects?: Readonly<Partial<Record<TestSpecification, TestProject>>>;
19
+ /** Path to an OpenAPI document (JSON or YAML) declaring the routes, when the app carries no route table. */
20
+ routes?: string;
21
+ /** The folders of `specs/` that hold specifications, each filing its specs under the subject they prove: `specs/<specification>/<subject>/`. */
22
+ specifications?: readonly string[];
23
+ };
24
+ /** The helpers a project is built by, named by their specification. */
25
+ type TestSpecification = 'api' | 'cli' | 'component' | 'integration' | 'job' | 'lint' | 'mobile' | 'unit' | 'website';
26
+ /** What a declared project states beyond its derived one: the global setups it runs, the options its helper takes, and why. */
27
+ type TestProject = {
28
+ readonly reason: string;
29
+ readonly setup?: readonly string[];
30
+ readonly [option: string]: unknown;
31
+ };
32
+ declare module '@jterrazz/typescript/config' {
33
+ interface JterrazzConfig {
34
+ /** What `@jterrazz/test` reads. */
35
+ test?: TestSettings;
36
+ }
37
+ }
38
+ //#endregion
39
+ export { type TestProject, type TestSettings, type TestSpecification, testPreset as test };
40
+ //# sourceMappingURL=config.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,309 @@
1
+ import { t as isRecord } from "./shared-json-shape.js";
2
+ import { t as CATALOGUE_CHAPTER } from "./shared-chapter.js";
3
+ import { n as specificationModules, t as derivedProjects } from "./shared-derived-projects.js";
4
+ import { t as TEST_SECTION } from "./shared-test-section.js";
5
+ import { n as recommendedRules, t as consumerRows } from "./shared-manifest.js";
6
+ import { createRequire } from "node:module";
7
+ import { RENAMED_FOLDERS, SETUP_FOLDER, SPECIAL_FOLDERS, declaredSubpaths, readAt, rowNamed, whyOf } from "@jterrazz/typescript/rules";
8
+ import { posix } from "node:path";
9
+ import { defineStandard } from "@jterrazz/typescript/config";
10
+ //#region src/standard/standard.ts
11
+ var standard_default = defineStandard({ test: {
12
+ specifications: [
13
+ "api",
14
+ "cli",
15
+ "component",
16
+ "integration",
17
+ "job",
18
+ "lint",
19
+ "mobile",
20
+ "website"
21
+ ],
22
+ projects: { unit: {
23
+ isolate: false,
24
+ reason: "a module test leaves no state behind in a module, so a worker runs its files in one module graph"
25
+ } }
26
+ } });
27
+ //#endregion
28
+ //#region lint/kit/project/loaded-packages.ts
29
+ const LOADED_BY = {
30
+ component: [
31
+ "@vitest/browser-playwright",
32
+ "playwright",
33
+ "vitest-browser-react"
34
+ ],
35
+ mobile: ["appium", "webdriverio"],
36
+ website: ["@vitest/browser-playwright", "playwright"]
37
+ };
38
+ /** The peers the projects a tree names drive through this package, which the project declares and imports nowhere. */
39
+ function packagesLoadedFor(root) {
40
+ const projects = derivedProjects(root);
41
+ return Object.entries(LOADED_BY).flatMap(([project, names]) => projects.has(project) ? names : []);
42
+ }
43
+ //#endregion
44
+ //#region lint/consumer/rulebook/import.ts
45
+ const importRulesForSpecifications = {
46
+ files: ["**/*.specification.ts"],
47
+ rules: { "import/exports-last": "off" }
48
+ };
49
+ /** Set in an override because a base profile turns the vitest plugin on in an override over the test globs, and an override's entry replaces a top-level one. */
50
+ const vitestOnTests = {
51
+ files: ["**/*.{test,spec,test-d,spec-d}.{ts,tsx,js,jsx}", "**/specs/**/*.{ts,tsx}"],
52
+ rules: {
53
+ "vitest/consistent-test-filename": ["error", { pattern: String.raw`.*\.(?:test\.[tj]sx?|spec\.[tj]s)$` }],
54
+ "vitest/max-nested-describe": ["error", { max: 1 }],
55
+ "vitest/no-restricted-matchers": ["error", {
56
+ toMatchAriaSnapshot: "The ARIA tree is a golden: `expect(result.tree).toMatch(file('./__expected__/<case>.aria.yaml'))`.",
57
+ toMatchFileSnapshot: "Name the file yourself: `expect(subject).toMatch(file('./__expected__/<case>.<ext>'))`.",
58
+ toMatchInlineSnapshot: "An inline snapshot is the run judging itself: `expect(subject).toMatch(file('./__expected__/<case>.<ext>'))`, or compare to a literal with `toStrictEqual`.",
59
+ toMatchScreenshot: "A screenshot is not a golden this dialect can read: assert the ARIA tree, the content, or the markup.",
60
+ toMatchSnapshot: "The golden is `expect(subject).toMatch(file('./__expected__/<name>.<ext>'))`, a path from the spec file; under `src/` compare to a literal with `toStrictEqual`.",
61
+ toThrowErrorMatchingInlineSnapshot: "State the message: `expect(fn).toThrow('<what the subject says>')`.",
62
+ toThrowErrorMatchingSnapshot: "State the message: `expect(fn).toThrow('<what the subject says>')`."
63
+ }],
64
+ "vitest/no-restricted-vi-methods": ["error", {
65
+ setSystemTime: "`vi.setSystemTime` gives way to `clock.at(iso)`, which gives the calendar back.",
66
+ stubGlobal: "`vi.stubGlobal('fetch')` gives way to `await using _ = await intercept(defineStubs(...))`; a subject that fetches a PATH states where it resolves: `intercept(stubs, { origin: 'http://<host>.test' })`.",
67
+ useFakeTimers: "`vi.useFakeTimers` gives way to `clock.at(iso)` and `clock.advance(ms)`.",
68
+ useRealTimers: "`vi.useRealTimers` gives way to nothing: `using` gives the clock back at the scope end."
69
+ }],
70
+ "vitest/prefer-lowercase-title": ["error", { ignoreTopLevelDescribe: true }]
71
+ }
72
+ };
73
+ //#endregion
74
+ //#region lint/consumer/rulebook/preset.ts
75
+ function taughtBy(name) {
76
+ const row = rowNamed(consumerRows, name);
77
+ return {
78
+ read: readAt(row, CATALOGUE_CHAPTER),
79
+ why: whyOf(row)
80
+ };
81
+ }
82
+ const escaped = (text) => text.replaceAll(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`);
83
+ const either = (patterns) => `(?:${patterns.map((pattern) => `(${pattern})`).join("|")})`;
84
+ const SOURCE = String.raw`\.[cm]?[jt]sx?$`;
85
+ const TEST_FILE = String.raw`\.(test\.[cm]?[jt]sx?|spec\.[cm]?[jt]s)$`;
86
+ const RUNS_A_TEST = String.raw`\.(test\.tsx?|spec\.ts|specification\.tsx?)$`;
87
+ function packages(names) {
88
+ return either(names.map((name) => {
89
+ const written = name.endsWith("*") ? `${escaped(name.slice(0, -1))}[^/]*` : escaped(name);
90
+ return String.raw`(^|/)node_modules/${written}([./]|$)|^${written}([./]|$)`;
91
+ }));
92
+ }
93
+ const SEAMS = [
94
+ {
95
+ fix: "`component.render()` and the element vocabulary render in a real browser: the queries are the same nouns, and they run against what ships",
96
+ packages: ["@testing-library/*"],
97
+ seam: "renderer"
98
+ },
99
+ {
100
+ fix: "a drawing of a browser proves what a browser does not: a rendered thing is a `.test.tsx` in the `__tests__/` of its component's folder, collected by `component()`",
101
+ packages: ["happy-dom", "jsdom"],
102
+ seam: "simulated-dom"
103
+ },
104
+ {
105
+ fix: "Browser Mode is the seam, not the surface: `component.render()` owns the locators, the visitor and the ARIA tree",
106
+ packages: [
107
+ "vitest/browser",
108
+ "vitest-browser-*",
109
+ "@vitest/browser*"
110
+ ],
111
+ seam: "browser-mode"
112
+ },
113
+ {
114
+ fix: "the network answers through stubs: `await using _ = await intercept(defineStubs(...))` in module scope, `.intercept()` on a chain",
115
+ packages: ["msw", "nock"],
116
+ seam: "network"
117
+ },
118
+ {
119
+ fix: "the doubles ladder is closed: `mockOf<Port>()` for an injected interface, `vi.fn()` for a function, `vi.spyOn` for an object the test passes in",
120
+ packages: ["sinon", "vitest-mock-extended"],
121
+ seam: "doubles"
122
+ },
123
+ {
124
+ fix: "vitest is the runner this vocabulary speaks: `test`, `expect` and `vi` come from it",
125
+ packages: ["jest", "@jest/*"],
126
+ seam: "runner"
127
+ },
128
+ {
129
+ fix: "time is one primitive: `using _ = clock.at(iso)` pins the calendar and gives it back at the end of the scope",
130
+ packages: ["mockdate"],
131
+ seam: "clock"
132
+ },
133
+ {
134
+ fix: "the website specification drives the browser: `specification.website()` owns the page, and the peer is its",
135
+ packages: [
136
+ "playwright",
137
+ "playwright-core",
138
+ "@playwright/test"
139
+ ],
140
+ seam: "browser"
141
+ },
142
+ {
143
+ fix: "the mobile specification drives the simulator: `specification.mobile()` owns the session, and the peers are its",
144
+ packages: ["webdriverio", "appium"],
145
+ seam: "simulator"
146
+ },
147
+ {
148
+ fix: "a component rendered to a string is still a component: the test is a `.test.tsx` in the `__tests__/` of its folder, and `result.html` carries the markup",
149
+ from: String.raw`\.test\.ts$`,
150
+ packages: ["react-dom/server"],
151
+ seam: "string-renderer"
152
+ }
153
+ ];
154
+ const secondRuntime = taughtBy("no-second-test-runtime");
155
+ function secondRuntimeLaw(seam, pathNot) {
156
+ return {
157
+ fix: seam.fix,
158
+ from: {
159
+ path: seam.from ?? RUNS_A_TEST,
160
+ ...pathNot === void 0 ? {} : { pathNot }
161
+ },
162
+ name: `no-second-test-runtime-${seam.seam}`,
163
+ read: secondRuntime.read,
164
+ to: { path: packages(seam.packages) },
165
+ why: secondRuntime.why
166
+ };
167
+ }
168
+ function publishedFix() {
169
+ const published = declaredSubpaths("@jterrazz/test", import.meta.dirname);
170
+ return `import from "@jterrazz/test"; the published subpaths are ${published.length === 0 ? "none" : published.join(", ")}`;
171
+ }
172
+ const LAYERS = [
173
+ {
174
+ ...taughtBy("no-test-to-test-import"),
175
+ fix: "under `specs/`, move what both read into the `__setup__/` of the lowest folder they share; under `src/`, into a `__tests__/<file>.fixtures.ts` for typed input data",
176
+ from: { path: TEST_FILE },
177
+ name: "no-test-to-test-import",
178
+ to: { path: String.raw`\.test\.[cm]?[jt]sx?$` }
179
+ },
180
+ {
181
+ ...taughtBy("fixtures-imported-by-tests-only"),
182
+ fix: "import it from a `*.test.ts` only, or move what the file needs into a module of its own",
183
+ from: { pathNot: TEST_FILE },
184
+ name: "fixtures-imported-by-tests-only",
185
+ to: { path: String.raw`\.fixtures${SOURCE}` }
186
+ },
187
+ ...SEAMS.map((seam) => secondRuntimeLaw(seam)),
188
+ {
189
+ ...taughtBy("no-unpublished-subpath"),
190
+ fix: publishedFix(),
191
+ from: {},
192
+ name: "no-unpublished-subpath",
193
+ to: {
194
+ couldNotResolve: true,
195
+ path: "^@jterrazz/test/"
196
+ }
197
+ }
198
+ ];
199
+ const EXTENSIONS = [
200
+ "c",
201
+ "m",
202
+ ""
203
+ ].flatMap((module) => ["j", "t"].flatMap((language) => ["x", ""].map((jsx) => `${module}${language}s${jsx}`)));
204
+ const AT_THE_SPECS_ROOT = [...[
205
+ "test",
206
+ "test-d",
207
+ "spec",
208
+ "specification"
209
+ ].flatMap((kind) => EXTENSIONS.map((extension) => `.${kind}.${extension}`)), ".spec.yaml"];
210
+ const ANY_OTHER_FILE = [
211
+ ".*",
212
+ ".*.*",
213
+ ".*.*.*",
214
+ ".*.*.*.*"
215
+ ];
216
+ const OF_A_UNIT = [[".json", "regex:(package|tsconfig)"], [".config.ts", "regex:(jterrazz|vitest)"]];
217
+ function specsRootFiles() {
218
+ const refused = ANY_OTHER_FILE.map((key) => [key, "exists:0"]);
219
+ const held = AT_THE_SPECS_ROOT.flatMap((key) => [[key, "regex:.+"], [`.*${key}`, "regex:.+"]]);
220
+ return Object.fromEntries([
221
+ ...refused,
222
+ ...held,
223
+ ...OF_A_UNIT
224
+ ]);
225
+ }
226
+ const CLOSED_LIST = `regex:${either(["[^_].*", ...SPECIAL_FOLDERS.map((name) => escaped(name))])}`;
227
+ const LISTED = SPECIAL_FOLDERS.map((name) => `\`${name}/\``).join(", ");
228
+ const EARLIER_SPELLINGS = Object.entries(RENAMED_FOLDERS).filter(([earlier]) => earlier.startsWith("_")).map(([earlier, now]) => `\`${earlier}/\` is \`${now}/\``).join(", ");
229
+ const NAMES = [
230
+ {
231
+ ...taughtBy("specs-root-holds-specifications-and-shared"),
232
+ fix: `move a file where it belongs: code into \`specs/${SETUP_FOLDER}/\` or the \`${SETUP_FOLDER}/\` of the one specification that reads it, data into the ground folder of its role`,
233
+ ls: {
234
+ "**/specs": specsRootFiles(),
235
+ "**/specs/*": {}
236
+ },
237
+ name: "specs-root-holds-specifications-and-shared"
238
+ },
239
+ {
240
+ ...taughtBy("special-folder-in-closed-list"),
241
+ fix: `rename it to the special folder that says what it holds (${LISTED}), or drop the \`_\` if it is a subject; an earlier spelling names its own (${EARLIER_SPELLINGS}), and what \`_shared/\` held sits in the special folders at the specs root`,
242
+ ignore: SPECIAL_FOLDERS.map((name) => `**/${name}`),
243
+ ls: { "**/specs/**": { ".dir": CLOSED_LIST } },
244
+ name: "special-folder-in-closed-list"
245
+ },
246
+ {
247
+ ...taughtBy("spec-file-in-a-specs-tree"),
248
+ fix: "move it under `specs/<specification>/`, or rename it `.test.ts` in the `__tests__/` of the folder of the module it covers",
249
+ ignore: ["specs", "**/specs"],
250
+ ls: { "**": {
251
+ ".*.spec.ts": "exists:0",
252
+ ".spec.ts": "exists:0"
253
+ } },
254
+ name: "spec-file-in-a-specs-tree"
255
+ }
256
+ ];
257
+ const TEST_COMMENT_OPENINGS = Object.freeze([
258
+ "Given - ",
259
+ "When - ",
260
+ "Then - ",
261
+ "And - ",
262
+ "checker-disable",
263
+ "testId:"
264
+ ]);
265
+ const TEST_STANDARD = standard_default.test ?? {};
266
+ const recordOf = (value) => isRecord(value) ? value : {};
267
+ function loadedByName(section) {
268
+ return Object.values(recordOf(section.projects)).flatMap((project) => {
269
+ const { root, wrap } = recordOf(project);
270
+ return typeof wrap === "string" ? [posix.normalize(typeof root === "string" ? posix.join(root, wrap) : wrap)] : [];
271
+ });
272
+ }
273
+ function testPreset() {
274
+ return {
275
+ baseline: [TEST_SECTION],
276
+ layers: LAYERS,
277
+ name: TEST_SECTION,
278
+ names: NAMES,
279
+ oxlint: {
280
+ jsPlugins: ["@jterrazz/test/oxlint"],
281
+ overrides: [importRulesForSpecifications, vitestOnTests],
282
+ rules: {
283
+ ...recommendedRules,
284
+ "jterrazz-typescript/comment-states-its-kind": ["error", { openings: [...TEST_COMMENT_OPENINGS] }]
285
+ }
286
+ },
287
+ checker: {
288
+ label: "Test Conventions (@jterrazz/test)",
289
+ module: createRequire(import.meta.url).resolve("#checker")
290
+ },
291
+ derive: (root) => ({ projects: Object.fromEntries(derivedProjects(root)) }),
292
+ entries: (section, root) => [...loadedByName(section), ...specificationModules(root)],
293
+ loadedPackages: packagesLoadedFor,
294
+ files: { "vitest.config.ts": {
295
+ scope: "unit",
296
+ text: "import { vitestConfig } from '@jterrazz/test/vitest';\n\nexport default await vitestConfig(import.meta.url);\n"
297
+ } },
298
+ origins: [{
299
+ file: "src/standard/standard.ts",
300
+ settings: TEST_STANDARD
301
+ }],
302
+ package: "@jterrazz/test",
303
+ settings: TEST_STANDARD
304
+ };
305
+ }
306
+ //#endregion
307
+ export { testPreset as test };
308
+
309
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,11 @@
1
+ //#region src/expectations/in-place/in-place.global-setup.d.ts
2
+ export declare function inPlaceSetup(): string;
3
+ type RunProject = {
4
+ config: {
5
+ root: string;
6
+ };
7
+ provide: (key: 'inPlaceRewrites', value: string) => void;
8
+ };
9
+ export default function setup(project: RunProject): () => void;
10
+ //#endregion
11
+ //# sourceMappingURL=in-place.global-setup.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { i as writePendingRewrites } from "./shared-in-place.js";
2
+ import { l as VITEST_ARTIFACTS_DIR } from "./shared-artifacts.js";
3
+ import { t as setupEntry } from "./shared-setup-entry.js";
4
+ import { join } from "node:path";
5
+ import { randomUUID } from "node:crypto";
6
+ //#region src/expectations/in-place/in-place.global-setup.ts
7
+ function inPlaceSetup() {
8
+ return setupEntry(import.meta.dirname, "in-place");
9
+ }
10
+ const IN_PLACE_DIR = `${VITEST_ARTIFACTS_DIR}/in-place`;
11
+ function setup(project) {
12
+ const folder = join(project.config.root, IN_PLACE_DIR, randomUUID());
13
+ project.provide("inPlaceRewrites", folder);
14
+ return () => {
15
+ writePendingRewrites(folder);
16
+ };
17
+ }
18
+ //#endregion
19
+ export { setup as default, inPlaceSetup };
20
+
21
+ //# sourceMappingURL=in-place.global-setup.js.map