@crvouga/atlas 0.4.0 → 0.6.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 (444) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +191 -611
  3. package/dist/bun/src/driver.d.ts +41 -7
  4. package/dist/bun/src/driver.js +47 -6
  5. package/dist/bun/src/index.d.ts +8 -0
  6. package/dist/bun/src/index.js +8 -0
  7. package/dist/core/src/cli.d.ts +14 -1
  8. package/dist/core/src/cli.js +35 -1
  9. package/dist/core/src/config.d.ts +77 -4
  10. package/dist/core/src/config.js +110 -17
  11. package/dist/core/src/events/cloudevents.d.ts +54 -9
  12. package/dist/core/src/events/cloudevents.js +60 -9
  13. package/dist/core/src/graph.d.ts +21 -0
  14. package/dist/core/src/graph.js +26 -0
  15. package/dist/core/src/index.d.ts +11 -0
  16. package/dist/core/src/index.js +11 -0
  17. package/dist/core/src/lint.d.ts +30 -0
  18. package/dist/core/src/lint.js +13 -0
  19. package/dist/core/src/plan.d.ts +39 -1
  20. package/dist/core/src/plan.js +28 -1
  21. package/dist/core/src/privacy.d.ts +29 -2
  22. package/dist/core/src/privacy.js +19 -2
  23. package/dist/core/src/report/formats.d.ts +34 -4
  24. package/dist/core/src/report/formats.js +24 -4
  25. package/dist/core/src/report/markdown.d.ts +15 -0
  26. package/dist/core/src/report/markdown.js +8 -0
  27. package/dist/core/src/run/clients.d.ts +44 -5
  28. package/dist/core/src/run/clients.js +46 -2
  29. package/dist/core/src/run/execute.d.ts +75 -16
  30. package/dist/core/src/run/execute.js +71 -18
  31. package/dist/core/src/run/frames.d.ts +13 -4
  32. package/dist/core/src/run/frames.js +19 -4
  33. package/dist/core/src/run/http.d.ts +34 -1
  34. package/dist/core/src/run/http.js +14 -1
  35. package/dist/core/src/run/types.d.ts +76 -3
  36. package/dist/core/src/run/types.js +19 -3
  37. package/dist/core/src/signals.d.ts +49 -5
  38. package/dist/core/src/signals.js +22 -5
  39. package/dist/core/src/spec/compose.d.ts +23 -1
  40. package/dist/core/src/spec/compose.js +10 -1
  41. package/dist/core/src/spec/index.d.ts +9 -1
  42. package/dist/core/src/spec/index.js +9 -1
  43. package/dist/core/src/spec/load.d.ts +22 -1
  44. package/dist/core/src/spec/load.js +31 -1
  45. package/dist/core/src/spec/parse.d.ts +16 -2
  46. package/dist/core/src/spec/parse.js +25 -2
  47. package/dist/core/src/spec/scxml.d.ts +25 -4
  48. package/dist/core/src/spec/scxml.js +36 -4
  49. package/dist/core/src/spec/types.d.ts +52 -1
  50. package/dist/core/src/spec/types.js +24 -0
  51. package/dist/detox/src/index.d.ts +54 -11
  52. package/dist/detox/src/index.js +45 -7
  53. package/dist/playwright/src/driver.d.ts +39 -3
  54. package/dist/playwright/src/driver.js +27 -3
  55. package/dist/playwright/src/index.d.ts +10 -0
  56. package/dist/playwright/src/index.js +10 -0
  57. package/dist/playwright/src/media.d.ts +50 -4
  58. package/dist/playwright/src/media.js +55 -4
  59. package/dist/playwright/src/signals.d.ts +44 -5
  60. package/dist/playwright/src/signals.js +29 -5
  61. package/dist/reports/src/attachment-files.d.ts +44 -0
  62. package/dist/reports/src/attachment-files.js +121 -0
  63. package/dist/reports/src/attachment-response.d.ts +31 -0
  64. package/dist/reports/src/attachment-response.js +55 -0
  65. package/dist/reports/src/aws-credentials.d.ts +48 -0
  66. package/dist/reports/src/aws-credentials.js +221 -0
  67. package/dist/reports/src/browser-navigation.d.ts +14 -0
  68. package/dist/reports/src/browser-navigation.js +7 -0
  69. package/dist/reports/src/bundle.d.ts +34 -2
  70. package/dist/reports/src/bundle.js +38 -2
  71. package/dist/reports/src/catalog.d.ts +34 -3
  72. package/dist/reports/src/catalog.js +17 -3
  73. package/dist/reports/src/cli-stores.d.ts +36 -0
  74. package/dist/reports/src/cli-stores.js +73 -0
  75. package/dist/reports/src/clock.d.ts +7 -2
  76. package/dist/reports/src/clock.js +5 -2
  77. package/dist/reports/src/completion-order.d.ts +18 -5
  78. package/dist/reports/src/completion-order.js +18 -5
  79. package/dist/reports/src/compose.d.ts +80 -0
  80. package/dist/reports/src/compose.js +117 -0
  81. package/dist/reports/src/copy-store.d.ts +29 -0
  82. package/dist/reports/src/copy-store.js +52 -0
  83. package/dist/reports/src/directory-outline.d.ts +38 -0
  84. package/dist/reports/src/directory-outline.js +103 -0
  85. package/dist/reports/src/directory-store.d.ts +20 -0
  86. package/dist/reports/src/directory-store.js +166 -0
  87. package/dist/reports/src/doctor.d.ts +29 -0
  88. package/dist/reports/src/doctor.js +85 -0
  89. package/dist/reports/src/effective-delta.d.ts +34 -0
  90. package/dist/reports/src/effective-delta.js +25 -0
  91. package/dist/reports/src/evidence-detail.d.ts +64 -0
  92. package/dist/reports/src/evidence-detail.js +92 -0
  93. package/dist/reports/src/evidence-live.d.ts +35 -5
  94. package/dist/reports/src/evidence-live.js +18 -2
  95. package/dist/reports/src/evidence-types.d.ts +68 -1
  96. package/dist/reports/src/evidence-types.js +5 -1
  97. package/dist/reports/src/evidence-view.d.ts +43 -4
  98. package/dist/reports/src/evidence-view.js +13 -2
  99. package/dist/reports/src/explorer-types.d.ts +40 -3
  100. package/dist/reports/src/explorer-types.js +8 -0
  101. package/dist/reports/src/explorer-versions.d.ts +9 -1
  102. package/dist/reports/src/explorer-versions.js +18 -1
  103. package/dist/reports/src/export-evidence.d.ts +16 -1
  104. package/dist/reports/src/export-evidence.js +52 -1
  105. package/dist/reports/src/fetcher.d.ts +27 -3
  106. package/dist/reports/src/fetcher.js +11 -3
  107. package/dist/reports/src/format-date.d.ts +6 -0
  108. package/dist/reports/src/format-date.js +6 -0
  109. package/dist/reports/src/format.d.ts +16 -0
  110. package/dist/reports/src/format.js +10 -0
  111. package/dist/reports/src/frames.d.ts +36 -3
  112. package/dist/reports/src/frames.js +22 -3
  113. package/dist/reports/src/hash.d.ts +18 -0
  114. package/dist/reports/src/hash.js +13 -0
  115. package/dist/reports/src/host.d.ts +29 -0
  116. package/dist/reports/src/host.js +64 -0
  117. package/dist/reports/src/html-frame.d.ts +5 -6
  118. package/dist/reports/src/html-frame.js +12 -1
  119. package/dist/reports/src/http-store.d.ts +56 -0
  120. package/dist/reports/src/http-store.js +148 -0
  121. package/dist/reports/src/http.d.ts +7 -0
  122. package/dist/reports/src/http.js +6 -0
  123. package/dist/reports/src/ingest.d.ts +54 -0
  124. package/dist/reports/src/ingest.js +210 -0
  125. package/dist/reports/src/init.d.ts +40 -0
  126. package/dist/reports/src/init.js +369 -0
  127. package/dist/reports/src/junit.d.ts +33 -6
  128. package/dist/reports/src/junit.js +87 -21
  129. package/dist/reports/src/keyboard.d.ts +20 -0
  130. package/dist/reports/src/keyboard.js +11 -0
  131. package/dist/reports/src/keys.d.ts +21 -3
  132. package/dist/reports/src/keys.js +21 -3
  133. package/dist/reports/src/layer-axes.d.ts +35 -5
  134. package/dist/reports/src/layer-axes.js +25 -5
  135. package/dist/reports/src/layer-catalog.d.ts +28 -1
  136. package/dist/reports/src/layer-catalog.js +18 -1
  137. package/dist/reports/src/layer-merge.d.ts +98 -9
  138. package/dist/reports/src/layer-merge.js +147 -31
  139. package/dist/reports/src/layer-source.d.ts +18 -0
  140. package/dist/reports/src/layer-source.js +11 -0
  141. package/dist/reports/src/layer-store.d.ts +42 -0
  142. package/dist/reports/src/layer-store.js +63 -5
  143. package/dist/reports/src/layer-types.d.ts +32 -1
  144. package/dist/reports/src/layers-route.d.ts +47 -4
  145. package/dist/reports/src/layers-route.js +86 -7
  146. package/dist/reports/src/live-reporter.d.ts +34 -0
  147. package/dist/reports/src/live-reporter.js +122 -0
  148. package/dist/reports/src/media-types.d.ts +11 -0
  149. package/dist/reports/src/media-types.js +22 -0
  150. package/dist/reports/src/namespace-guard.d.ts +10 -1
  151. package/dist/reports/src/namespace-guard.js +10 -1
  152. package/dist/reports/src/navigation.d.ts +12 -0
  153. package/dist/reports/src/navigation.js +7 -0
  154. package/dist/reports/src/object-io.d.ts +11 -4
  155. package/dist/reports/src/object-io.js +4 -4
  156. package/dist/reports/src/object-store-conformance.d.ts +27 -0
  157. package/dist/reports/src/object-store-conformance.js +87 -0
  158. package/dist/reports/src/object-store.d.ts +33 -24
  159. package/dist/reports/src/object-store.js +17 -24
  160. package/dist/reports/src/parse-with.d.ts +16 -0
  161. package/dist/reports/src/parse-with.js +14 -0
  162. package/dist/reports/src/performance-part.d.ts +25 -1
  163. package/dist/reports/src/performance-part.js +15 -1
  164. package/dist/reports/src/performance.d.ts +22 -2
  165. package/dist/reports/src/performance.js +12 -2
  166. package/dist/reports/src/persist.d.ts +12 -3
  167. package/dist/reports/src/persist.js +12 -3
  168. package/dist/reports/src/phone.d.ts +18 -1
  169. package/dist/reports/src/phone.js +18 -1
  170. package/dist/reports/src/protocol.d.ts +26 -4
  171. package/dist/reports/src/protocol.js +15 -4
  172. package/dist/reports/src/publication.d.ts +21 -1
  173. package/dist/reports/src/publication.js +21 -1
  174. package/dist/reports/src/publish-checks.d.ts +35 -0
  175. package/dist/reports/src/publish-checks.js +122 -0
  176. package/dist/reports/src/publish.d.ts +42 -9
  177. package/dist/reports/src/publish.js +36 -7
  178. package/dist/reports/src/read.d.ts +46 -16
  179. package/dist/reports/src/read.js +38 -14
  180. package/dist/reports/src/recording-bundle.d.ts +13 -2
  181. package/dist/reports/src/recording-bundle.js +4 -2
  182. package/dist/reports/src/recording-keys.d.ts +15 -1
  183. package/dist/reports/src/recording-keys.js +15 -1
  184. package/dist/reports/src/remote-report.d.ts +28 -7
  185. package/dist/reports/src/remote-report.js +15 -7
  186. package/dist/reports/src/report-cli.d.ts +51 -0
  187. package/dist/reports/src/report-cli.js +486 -0
  188. package/dist/reports/src/report-index.d.ts +99 -0
  189. package/dist/reports/src/report-index.js +337 -0
  190. package/dist/reports/src/report-loader.d.ts +10 -0
  191. package/dist/reports/src/report-loader.js +6 -0
  192. package/dist/reports/src/report-parts.d.ts +29 -3
  193. package/dist/reports/src/report-parts.js +37 -3
  194. package/dist/reports/src/report-status.d.ts +48 -0
  195. package/dist/reports/src/report-status.js +156 -0
  196. package/dist/reports/src/report-types.d.ts +73 -0
  197. package/dist/reports/src/report-types.js +3 -0
  198. package/dist/reports/src/reporter.d.ts +67 -0
  199. package/dist/reports/src/reporter.js +128 -0
  200. package/dist/reports/src/reports-explorer-route.d.ts +541 -0
  201. package/dist/reports/src/reports-explorer-route.js +11 -0
  202. package/dist/reports/src/reports-list-route.d.ts +9 -0
  203. package/dist/reports/src/reports-list-route.js +9 -0
  204. package/dist/reports/src/reports-route.d.ts +561 -22
  205. package/dist/reports/src/reports-route.js +11 -3
  206. package/dist/reports/src/reports-store.d.ts +19 -2
  207. package/dist/reports/src/reports-store.js +10 -2
  208. package/dist/reports/src/resilient-cache.d.ts +14 -1
  209. package/dist/reports/src/resilient-cache.js +8 -1
  210. package/dist/reports/src/retention.d.ts +17 -1
  211. package/dist/reports/src/retention.js +5 -1
  212. package/dist/reports/src/run-bundle.d.ts +63 -0
  213. package/dist/reports/src/run-bundle.js +159 -0
  214. package/dist/reports/src/s3-store.d.ts +79 -0
  215. package/dist/reports/src/s3-store.js +295 -0
  216. package/dist/reports/src/scenario.d.ts +14 -4
  217. package/dist/reports/src/scenario.js +5 -4
  218. package/dist/reports/src/sigv4.d.ts +72 -0
  219. package/dist/reports/src/sigv4.js +96 -0
  220. package/dist/reports/src/snapshot-bundle.d.ts +24 -1
  221. package/dist/reports/src/snapshot-bundle.js +27 -2
  222. package/dist/reports/src/snapshot-surface.d.ts +20 -9
  223. package/dist/reports/src/snapshot-surface.js +32 -19
  224. package/dist/reports/src/source-content.d.ts +23 -0
  225. package/dist/reports/src/source-content.js +30 -1
  226. package/dist/reports/src/source-entries.d.ts +13 -0
  227. package/dist/reports/src/source-entries.js +6 -0
  228. package/dist/reports/src/source-part.d.ts +15 -0
  229. package/dist/reports/src/source-part.js +8 -0
  230. package/dist/reports/src/source-reader.d.ts +11 -0
  231. package/dist/reports/src/source-reader.js +5 -0
  232. package/dist/reports/src/spec-evidence.d.ts +12 -2
  233. package/dist/reports/src/spec-evidence.js +6 -2
  234. package/dist/reports/src/spec-inventory.d.ts +15 -1
  235. package/dist/reports/src/spec-inventory.js +22 -1
  236. package/dist/reports/src/spec-link.d.ts +28 -0
  237. package/dist/reports/src/spec-link.js +70 -0
  238. package/dist/reports/src/spec-set.d.ts +63 -0
  239. package/dist/reports/src/spec-set.js +177 -0
  240. package/dist/reports/src/status.d.ts +10 -0
  241. package/dist/reports/src/status.js +5 -0
  242. package/dist/reports/src/store-prefix.d.ts +28 -0
  243. package/dist/reports/src/store-prefix.js +22 -0
  244. package/dist/reports/src/store-url.d.ts +89 -0
  245. package/dist/reports/src/store-url.js +160 -0
  246. package/dist/reports/src/test-catalog-entity.d.ts +11 -0
  247. package/dist/reports/src/test-catalog-entity.js +6 -0
  248. package/dist/reports/src/types.d.ts +6 -1
  249. package/dist/reports/src/use-report-nav.d.ts +35 -0
  250. package/dist/reports/src/use-report-nav.js +12 -0
  251. package/dist/runners/src/codecept.d.ts +14 -0
  252. package/dist/runners/src/codecept.js +16 -0
  253. package/dist/runners/src/jest.d.ts +50 -0
  254. package/dist/runners/src/jest.js +52 -0
  255. package/dist/runners/src/mocha.d.ts +40 -0
  256. package/dist/runners/src/mocha.js +39 -0
  257. package/dist/runners/src/node-test.d.ts +28 -0
  258. package/dist/runners/src/node-test.js +44 -0
  259. package/dist/runners/src/publish.d.ts +30 -0
  260. package/dist/runners/src/publish.js +68 -0
  261. package/dist/schema/src/api.d.ts +800 -0
  262. package/dist/schema/src/api.js +201 -0
  263. package/dist/schema/src/cli-results.d.ts +210 -0
  264. package/dist/schema/src/cli-results.js +124 -0
  265. package/dist/schema/src/common.d.ts +53 -0
  266. package/dist/schema/src/common.js +42 -0
  267. package/dist/schema/src/index.d.ts +16 -0
  268. package/dist/schema/src/index.js +16 -0
  269. package/dist/schema/src/layer.d.ts +2273 -0
  270. package/dist/schema/src/layer.js +462 -0
  271. package/dist/schema/src/live-run.d.ts +123 -0
  272. package/dist/schema/src/live-run.js +30 -0
  273. package/dist/schema/src/manifest.d.ts +97 -2
  274. package/dist/schema/src/manifest.js +84 -0
  275. package/dist/schema/src/project.d.ts +20 -0
  276. package/dist/schema/src/project.js +10 -0
  277. package/dist/schema/src/report-sources.d.ts +29 -0
  278. package/dist/schema/src/report-sources.js +27 -1
  279. package/dist/schema/src/runs-index.d.ts +17 -1
  280. package/dist/schema/src/runs-index.js +15 -0
  281. package/dist/schema/src/server-config.d.ts +177 -0
  282. package/dist/schema/src/server-config.js +85 -0
  283. package/dist/schema/src/spec.d.ts +69 -0
  284. package/dist/schema/src/spec.js +58 -0
  285. package/dist/server/src/app.d.ts +72 -0
  286. package/dist/server/src/app.js +557 -0
  287. package/dist/server/src/auth.d.ts +41 -0
  288. package/dist/server/src/auth.js +59 -0
  289. package/dist/server/src/config.d.ts +83 -0
  290. package/dist/server/src/config.js +204 -0
  291. package/dist/server/src/dev.d.ts +12 -0
  292. package/dist/server/src/dev.js +89 -0
  293. package/dist/server/src/events.d.ts +29 -0
  294. package/dist/server/src/events.js +101 -0
  295. package/dist/server/src/host.d.ts +30 -0
  296. package/dist/server/src/host.js +115 -0
  297. package/dist/server/src/index.d.ts +18 -0
  298. package/dist/server/src/index.js +18 -0
  299. package/dist/server/src/live-runs.d.ts +52 -0
  300. package/dist/server/src/live-runs.js +229 -0
  301. package/dist/server/src/llms.d.ts +19 -0
  302. package/dist/server/src/llms.js +63 -0
  303. package/dist/server/src/main.d.ts +30 -0
  304. package/dist/server/src/main.js +114 -0
  305. package/dist/server/src/openapi.d.ts +56 -0
  306. package/dist/server/src/openapi.js +438 -0
  307. package/dist/server/src/problem.d.ts +8 -0
  308. package/dist/server/src/problem.js +39 -0
  309. package/dist/server/src/projects.d.ts +3 -0
  310. package/dist/server/src/projects.js +154 -0
  311. package/dist/server/src/settings-page.d.ts +9 -0
  312. package/dist/server/src/settings-page.js +93 -0
  313. package/dist/server/src/settings.d.ts +23 -0
  314. package/dist/server/src/settings.js +72 -0
  315. package/dist/server/src/site.d.ts +15 -0
  316. package/dist/server/src/site.js +78 -0
  317. package/dist/server/src/store-api.d.ts +28 -0
  318. package/dist/server/src/store-api.js +180 -0
  319. package/dist/server/src/validate.d.ts +71 -0
  320. package/dist/server/src/validate.js +197 -0
  321. package/dist/vitest/src/index.d.ts +27 -5
  322. package/dist/vitest/src/index.js +18 -5
  323. package/dist/webdriver/src/driver.d.ts +63 -11
  324. package/dist/webdriver/src/driver.js +57 -6
  325. package/dist/webdriver/src/index.d.ts +8 -0
  326. package/dist/webdriver/src/index.js +1 -0
  327. package/dist/webdriver/src/protocol.d.ts +75 -6
  328. package/dist/webdriver/src/protocol.js +79 -6
  329. package/docs/agents.md +137 -0
  330. package/docs/deploying.md +345 -0
  331. package/docs/dogfooding.md +175 -0
  332. package/docs/extending.md +242 -0
  333. package/docs/integrating.md +485 -0
  334. package/docs/reference/bun.md +141 -0
  335. package/docs/reference/cli.md +148 -0
  336. package/docs/reference/core.md +2432 -0
  337. package/docs/reference/detox.md +150 -0
  338. package/docs/reference/http-api.md +799 -0
  339. package/docs/reference/playwright.md +303 -0
  340. package/docs/reference/reports.md +7152 -0
  341. package/docs/reference/runners.md +169 -0
  342. package/docs/reference/schema.md +1762 -0
  343. package/docs/reference/server.md +825 -0
  344. package/docs/reference/vitest.md +45 -0
  345. package/docs/reference/webdriver.md +330 -0
  346. package/docs/report-backends.md +144 -0
  347. package/docs/report-contract.md +400 -0
  348. package/docs/reporting-issues.md +160 -0
  349. package/docs/runners.md +69 -0
  350. package/docs/server.md +321 -0
  351. package/docs/statecharts.md +643 -0
  352. package/llms-full.txt +4114 -0
  353. package/llms.txt +49 -0
  354. package/package.json +61 -11
  355. package/packages/core/README.md +2 -1
  356. package/packages/reports/README.md +65 -0
  357. package/packages/reports/STORAGE.md +4 -0
  358. package/packages/runners/README.md +6 -0
  359. package/packages/runners/compat/codecept.cjs +2 -0
  360. package/packages/runners/compat/jest.cjs +2 -0
  361. package/packages/runners/compat/mocha.cjs +2 -0
  362. package/packages/schema/README.md +14 -0
  363. package/packages/schema/schemas/atlas-change.schema.json +4 -0
  364. package/packages/schema/schemas/check-detail.schema.json +1032 -0
  365. package/packages/schema/schemas/checks-result.schema.json +26 -0
  366. package/packages/schema/schemas/command-error.schema.json +35 -0
  367. package/packages/schema/schemas/doctor-result.schema.json +60 -0
  368. package/packages/schema/schemas/effective-delta.schema.json +490 -0
  369. package/packages/schema/schemas/effective-evidence.schema.json +471 -0
  370. package/packages/schema/schemas/evidence-page.schema.json +271 -0
  371. package/packages/schema/schemas/hello-event.schema.json +26 -0
  372. package/packages/schema/schemas/init-plan.schema.json +347 -0
  373. package/packages/schema/schemas/layer-rows.schema.json +199 -0
  374. package/packages/schema/schemas/layer.schema.json +2888 -0
  375. package/packages/schema/schemas/live-run-start.schema.json +42 -0
  376. package/packages/schema/schemas/live-run-update.schema.json +93 -0
  377. package/packages/schema/schemas/live-run.schema.json +225 -0
  378. package/packages/schema/schemas/merge-result.schema.json +40 -0
  379. package/packages/schema/schemas/outline.schema.json +62 -0
  380. package/packages/schema/schemas/problem.schema.json +37 -0
  381. package/packages/schema/schemas/project-slug.schema.json +8 -0
  382. package/packages/schema/schemas/project.schema.json +22 -0
  383. package/packages/schema/schemas/projects.schema.json +33 -0
  384. package/packages/schema/schemas/publish-checks.schema.json +1413 -0
  385. package/packages/schema/schemas/publish-result.schema.json +168 -0
  386. package/packages/schema/schemas/ready.schema.json +68 -0
  387. package/packages/schema/schemas/report-event.schema.json +100 -0
  388. package/packages/schema/schemas/report-status.schema.json +370 -0
  389. package/packages/schema/schemas/server-config.schema.json +208 -0
  390. package/packages/schema/schemas/server-editable-settings.schema.json +132 -0
  391. package/packages/schema/schemas/server-info.schema.json +114 -0
  392. package/packages/schema/schemas/server-settings-snapshot.schema.json +285 -0
  393. package/packages/schema/schemas/spec-set.schema.json +103 -0
  394. package/packages/schema/schemas/store-listing.schema.json +29 -0
  395. package/packages/schema/schemas/store-write-result.schema.json +28 -0
  396. package/packages/schema/schemas/stream-result.schema.json +59 -0
  397. package/packages/server/README.md +43 -0
  398. package/packages/server/openapi.json +11021 -0
  399. package/packages/visualizer/README.md +32 -11
  400. package/packages/visualizer/bin/atlas-client.mjs +176 -0
  401. package/packages/visualizer/bin/atlas-visualizer.mjs +2 -175
  402. package/packages/visualizer/src/app/AppShell.tsx +32 -16
  403. package/packages/visualizer/src/app/report-sources.tsx +7 -4
  404. package/packages/visualizer/src/app/router.tsx +3 -3
  405. package/packages/visualizer/src/components/ActivityIndicator.module.css +4 -0
  406. package/packages/visualizer/src/components/ActivityIndicator.tsx +6 -0
  407. package/packages/visualizer/src/components/Header.module.css +101 -192
  408. package/packages/visualizer/src/components/Header.tsx +88 -13
  409. package/packages/visualizer/src/components/ProjectPicker.tsx +64 -0
  410. package/packages/visualizer/src/data/adapters/adapter.ts +5 -17
  411. package/packages/visualizer/src/data/adapters/index.ts +10 -1
  412. package/packages/visualizer/src/data/adapters/report-backend.test.ts +3 -2
  413. package/packages/visualizer/src/data/adapters/report-backend.ts +1 -1
  414. package/packages/visualizer/src/data/queries.ts +14 -7
  415. package/packages/visualizer/src/evidence/api.ts +16 -3
  416. package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
  417. package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
  418. package/packages/visualizer/src/evidence/check-detail.tsx +21 -4
  419. package/packages/visualizer/src/evidence/document-page.tsx +6 -2
  420. package/packages/visualizer/src/evidence/evidence-context.tsx +79 -12
  421. package/packages/visualizer/src/evidence/evidence.module.css +11 -1
  422. package/packages/visualizer/src/evidence/feature-page.tsx +7 -3
  423. package/packages/visualizer/src/evidence/model-page.tsx +6 -2
  424. package/packages/visualizer/src/evidence/project-home.tsx +45 -0
  425. package/packages/visualizer/src/evidence/recording-page.tsx +4 -1
  426. package/packages/visualizer/src/evidence/spec-index.tsx +2 -1
  427. package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
  428. package/packages/visualizer/src/evidence/test-filter.tsx +21 -0
  429. package/packages/visualizer/src/find/Finder.tsx +1 -7
  430. package/packages/visualizer/src/find/open.ts +4 -0
  431. package/packages/visualizer/src/live/live-query.ts +21 -0
  432. package/packages/visualizer/src/live/live-runs.tsx +69 -0
  433. package/packages/visualizer/src/live/live-stream.ts +225 -0
  434. package/packages/visualizer/src/live/report-progress.ts +62 -0
  435. package/packages/visualizer/src/live/test-progress.tsx +34 -0
  436. package/packages/visualizer/src/runtime.ts +35 -0
  437. package/packages/visualizer/src/state/ui-store.ts +3 -2
  438. package/packages/visualizer/src/views/ChartPage.tsx +2 -0
  439. package/packages/visualizer/src/views/ChartTests.tsx +43 -0
  440. package/packages/visualizer/src/views/SidePanel.tsx +2 -0
  441. package/packages/visualizer/vite/atlas-files.test.ts +4 -4
  442. package/packages/visualizer/vite/atlas-files.ts +1 -5
  443. package/packages/visualizer/vite/atlas-server-proxy.ts +37 -0
  444. package/packages/visualizer/vite.config.ts +11 -3
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Atlas reads statecharts in two open formats:
2
+ * @module Statechart spec types
3
+ *
4
+ * The data model every other module works on: a chart, a bundle of charts plus journeys, and the
5
+ * helpers that walk and name states and transitions. Atlas reads statecharts in two open formats:
3
6
  *
4
7
  * - W3C SCXML (`*.scxml`), the standard for statecharts.
5
8
  * - XState v5 machine config (`*.machine.json`, `*.machine.yaml`), the JSON form Stately Studio
@@ -9,24 +12,43 @@
9
12
  * walked without running code: states, nesting, parallel regions, final states, event
10
13
  * transitions, statically resolvable child charts (`invoke` with a `src` naming another chart),
11
14
  * and `meta`. Guards, actions, context, delays and `always` are rejected by the linter.
15
+ * This module has no I/O and no Node built-ins.
16
+ *
17
+ * @see docs/statecharts.md
12
18
  */
19
+ /** The object form of a transition. `target` is a state name, optionally prefixed with `#` (a reference by name across the composed product). */
13
20
  export type TransitionConfig = {
14
21
  target: string;
15
22
  };
23
+ /** An `invoke` that runs another chart inside a state. It is never executed: `composeCharts` inlines the child chart statically. */
16
24
  export type InvokeConfig = {
17
25
  /** The id of another chart in the bundle; composed statically. */
18
26
  src: string;
27
+ /** Names the invocation; the parent hears `done.invoke.<id>` (`<src>` when omitted) when the child ends. */
19
28
  id?: string;
20
29
  /** Where the parent goes when the child reaches a final state (`done.invoke.<id>`). */
21
30
  onDone?: string | TransitionConfig;
22
31
  };
32
+ /**
33
+ * The `meta` of a state: the business-language facts about it that Atlas lints, shows and checks.
34
+ * Open object: unknown keys are kept and ignored.
35
+ *
36
+ * @see docs/statecharts.md
37
+ */
23
38
  export type StateMeta = {
39
+ /** What is true in this state. Required on every state by default (`requiredMeta` in the config changes that). */
24
40
  description?: string;
41
+ /** What a person sees in this state, in words. */
25
42
  snapshot?: string;
43
+ /** Business events that happen on entering the state, compared with what event sources observed. */
26
44
  events?: string[];
45
+ /** Whether the behaviour is `confirmed` against the product or only `assumed`. */
27
46
  confidence?: 'confirmed' | 'assumed';
47
+ /** Where the behaviour is documented. */
28
48
  source?: string[];
49
+ /** Things to verify on screen, quoted from the spec; the implementation's `checks()` returns their results. */
29
50
  checks?: string[];
51
+ /** Gherkin-style contracts attached to the state. Core does not read them; they are carried through for viewers. */
30
52
  contracts?: {
31
53
  id: string;
32
54
  name: string;
@@ -39,6 +61,7 @@ export type StateMeta = {
39
61
  docString?: string;
40
62
  }[];
41
63
  }[];
64
+ /** Why a state with no way out is meant to be one. Without it, a state with no outgoing transition is a lint error. */
42
65
  deadEnd?: string;
43
66
  /** Legacy composition: the chart that runs inside this state. Prefer `invoke`. */
44
67
  childMachine?: string;
@@ -48,49 +71,77 @@ export type StateMeta = {
48
71
  doneEvent?: string;
49
72
  [key: string]: unknown;
50
73
  };
74
+ /**
75
+ * One state of an XState-shaped chart, recursively. Keys not listed here (guards, actions, `after`,
76
+ * ...) are accepted by the type so the linter can report them; the planner never executes them.
77
+ */
51
78
  export type StateConfig = {
79
+ /** Set by `composeCharts` to the state's name when absent; used by `#<name>` targets. */
52
80
  id?: string;
81
+ /** The child state entered first. */
53
82
  initial?: string;
83
+ /** `parallel`: all child regions are active together. `final`: the state ends its chart (or hands off to the parent). */
54
84
  type?: 'parallel' | 'final';
55
85
  meta?: StateMeta;
56
86
  states?: Record<string, StateConfig>;
87
+ /** Event name (exact business wording) to its transition: a target string or `{ target }`. */
57
88
  on?: Record<string, TransitionConfig | string>;
89
+ /** Child chart(s) that run inside this state. */
58
90
  invoke?: InvokeConfig | InvokeConfig[];
59
91
  [key: string]: unknown;
60
92
  };
93
+ /** A whole chart: a state config with a required `id`, which is the name other charts `invoke` it by. */
61
94
  export type MachineConfig = StateConfig & {
62
95
  id: string;
63
96
  };
97
+ /** A curated, named sequence of events, replayed by the linter and run as its own path(s). */
64
98
  export type Journey = {
99
+ /** The key in `journeys.yaml`. */
65
100
  name: string;
101
+ /** Empty string when the file gives none. */
66
102
  description: string;
103
+ /** Event names in order, using the exact spec wording. Hand-off events are never listed; the planner inserts them. */
67
104
  events: string[];
105
+ /** State names that must all be active after the last event. Empty when the file gives none. */
68
106
  endsIn: string[];
69
107
  };
108
+ /** One loaded chart file. */
70
109
  export type Chart = {
71
110
  /** Path relative to the spec directory. */
72
111
  file: string;
112
+ /** The notation the file was parsed from. */
73
113
  format: 'scxml' | 'xstate';
74
114
  machine: MachineConfig;
75
115
  };
116
+ /** Everything loaded from a specs directory. */
76
117
  export type SpecBundle = {
118
+ /** The directory the files were read from. */
77
119
  directory: string;
120
+ /** Charts in load order, one per chart id. */
78
121
  charts: Chart[];
122
+ /** Journeys from every journeys file, in file then declaration order. */
79
123
  journeys: Journey[];
80
124
  /** The chart the others are composed into: the one no other chart invokes. */
81
125
  root: string;
82
126
  };
127
+ /** The separator inside a transition id (`<source> :: <event>`). The ids are not escaped, so a state name containing it makes `splitTransitionId` ambiguous. */
83
128
  export declare const TRANSITION_SEPARATOR = " :: ";
129
+ /** The id of a transition: the source state's name and the event, joined by `TRANSITION_SEPARATOR`. */
84
130
  export declare function transitionId(source: string, event: string): string;
131
+ /** Splits a transition id at its first separator into `{ source, event }`; the inverse of `transitionId`. */
85
132
  export declare function splitTransitionId(id: string): {
86
133
  source: string;
87
134
  event: string;
88
135
  };
136
+ /** The state name a transition leads to, with any leading `#` removed; `undefined` when there is no transition. */
89
137
  export declare function targetOf(t: TransitionConfig | string | undefined): string | undefined;
138
+ /** A state found by `walkStates`: its name, its config, and the names of its ancestors from the outermost down. */
90
139
  export type StateEntry = {
91
140
  name: string;
92
141
  node: StateConfig;
93
142
  trail: string[];
94
143
  };
144
+ /** Lists every state under `config` depth-first, parents before their children, in declaration order. The root `config` itself is not listed. */
95
145
  export declare function walkStates(config: StateConfig, trail?: string[]): StateEntry[];
146
+ /** The `invoke` entries of a state as an array (empty when it has none). */
96
147
  export declare function invokesOf(node: StateConfig): InvokeConfig[];
@@ -1,23 +1,47 @@
1
+ /**
2
+ * @module Statechart spec types
3
+ *
4
+ * The data model every other module works on: a chart, a bundle of charts plus journeys, and the
5
+ * helpers that walk and name states and transitions. Atlas reads statecharts in two open formats:
6
+ *
7
+ * - W3C SCXML (`*.scxml`), the standard for statecharts.
8
+ * - XState v5 machine config (`*.machine.json`, `*.machine.yaml`), the JSON form Stately Studio
9
+ * imports and exports.
10
+ *
11
+ * Both load into the XState config shape below. Atlas executes only the pure subset that can be
12
+ * walked without running code: states, nesting, parallel regions, final states, event
13
+ * transitions, statically resolvable child charts (`invoke` with a `src` naming another chart),
14
+ * and `meta`. Guards, actions, context, delays and `always` are rejected by the linter.
15
+ * This module has no I/O and no Node built-ins.
16
+ *
17
+ * @see docs/statecharts.md
18
+ */
19
+ /** The separator inside a transition id (`<source> :: <event>`). The ids are not escaped, so a state name containing it makes `splitTransitionId` ambiguous. */
1
20
  export const TRANSITION_SEPARATOR = ' :: ';
21
+ /** The id of a transition: the source state's name and the event, joined by `TRANSITION_SEPARATOR`. */
2
22
  export function transitionId(source, event) {
3
23
  return `${source}${TRANSITION_SEPARATOR}${event}`;
4
24
  }
25
+ /** Splits a transition id at its first separator into `{ source, event }`; the inverse of `transitionId`. */
5
26
  export function splitTransitionId(id) {
6
27
  const at = id.indexOf(TRANSITION_SEPARATOR);
7
28
  return { source: id.slice(0, at), event: id.slice(at + TRANSITION_SEPARATOR.length) };
8
29
  }
30
+ /** The state name a transition leads to, with any leading `#` removed; `undefined` when there is no transition. */
9
31
  export function targetOf(t) {
10
32
  if (t === undefined)
11
33
  return undefined;
12
34
  const raw = typeof t === 'string' ? t : t.target;
13
35
  return raw.startsWith('#') ? raw.slice(1) : raw;
14
36
  }
37
+ /** Lists every state under `config` depth-first, parents before their children, in declaration order. The root `config` itself is not listed. */
15
38
  export function walkStates(config, trail = []) {
16
39
  return Object.entries(config.states ?? {}).flatMap(([name, node]) => [
17
40
  { name, node, trail },
18
41
  ...walkStates(node, [...trail, name])
19
42
  ]);
20
43
  }
44
+ /** The `invoke` entries of a state as an array (empty when it has none). */
21
45
  export function invokesOf(node) {
22
46
  if (!node.invoke)
23
47
  return [];
@@ -1,24 +1,32 @@
1
1
  import type { Driver, StateImplementation, Timeline } from '../../core/src/index.js';
2
2
  import type { Signal, SignalContext } from '../../core/src/signals.js';
3
+ /** What Detox's `by.*` builders return: an opaque matcher that is only passed back to Detox's `element(...)`. */
4
+ export type DetoxMatcher = unknown;
3
5
  /**
4
6
  * The parts of Detox's global API the driver uses (`device`, `element`, `by`, `waitFor`), typed
5
- * structurally so this package needs no Detox install to build.
7
+ * structurally so this package needs no Detox install to build. Detox's real globals satisfy it.
6
8
  */
7
- export type DetoxMatcher = unknown;
8
9
  export type DetoxApi = {
10
+ /** The device under test; Detox's `device`. */
9
11
  device: {
12
+ /** Launches the app; the driver passes `newInstance: true` and any `launchArgs`. */
10
13
  launchApp(params?: Record<string, unknown>): Promise<void>;
14
+ /** Opens a deep link; when the device lacks it, `goto` throws. */
11
15
  openURL?(params: {
12
16
  url: string;
13
17
  }): Promise<void>;
18
+ /** Terminates the app; skipped when absent. */
14
19
  terminateApp?(): Promise<void>;
20
+ /** Takes a screenshot and resolves to the path of the file Detox wrote. */
15
21
  takeScreenshot(name: string): Promise<string>;
16
22
  };
23
+ /** Detox's `element(matcher)`: the actions the driver performs on an element. */
17
24
  element(matcher: DetoxMatcher): {
18
25
  tap(): Promise<void>;
19
26
  typeText(text: string): Promise<void>;
20
27
  replaceText?(text: string): Promise<void>;
21
28
  };
29
+ /** Detox's `by`: matcher builders. `traits` exists on iOS only. */
22
30
  by: {
23
31
  id(id: string): DetoxMatcher;
24
32
  text(text: string): DetoxMatcher;
@@ -27,37 +35,72 @@ export type DetoxApi = {
27
35
  and?(other: DetoxMatcher): DetoxMatcher;
28
36
  };
29
37
  };
38
+ /** Detox's `waitFor(element)`, used to ask whether an element is visible. */
30
39
  waitFor(element: unknown): {
31
40
  toBeVisible(): {
32
41
  withTimeout(ms: number): Promise<void>;
33
42
  };
34
43
  };
35
44
  };
36
- /** Detox's API plus a `SignalContext`, so implementations written against signals run here too. */
45
+ /**
46
+ * What every event and recogniser receives from `detoxDriver`: Detox's API plus a `SignalContext`,
47
+ * so implementations written against signals run here too. One context is created per path attempt.
48
+ */
37
49
  export type DetoxContext = DetoxApi & SignalContext & {
50
+ /** The step timeline the actions below write to. */
38
51
  timeline: Timeline;
39
- /** Tap an element and log it to the step timeline. */
52
+ /** Tap the element a matcher finds and log it to the step timeline. Rejects with Detox's error if the element is not found. */
40
53
  tap(matcher: DetoxMatcher, label: string): Promise<void>;
54
+ /** Type `text` into the element a matcher finds (Detox `typeText`, which appends) and log it to the step timeline; `label` is the caption. */
41
55
  type(matcher: DetoxMatcher, text: string, label: string): Promise<void>;
42
56
  };
57
+ /** Options of `detoxDriver`. */
43
58
  export type DetoxDriverOptions = {
44
59
  /** Detox's globals; `globalThis` (where Detox puts them) by default. */
45
60
  api?: DetoxApi;
61
+ /** Passed to `device.launchApp` as `launchArgs` at the start of every attempt. */
46
62
  launchArgs?: Record<string, unknown>;
47
63
  };
48
64
  /**
49
- * A signal as a Detox matcher: test IDs are `by.id` (React Native's `testID`), labels `by.label`,
50
- * text `by.text`, a role with a name `by.label` (with the iOS `button` trait when Detox has it).
51
- * Detox matches exact strings, so regular expressions and CSS selectors are refused.
65
+ * Translates a signal into a Detox matcher: test IDs are `by.id` (React Native's `testID`), labels
66
+ * `by.label`, text `by.text`, a role with a name `by.label` (with the iOS `button` trait when Detox
67
+ * has it). Detox matches exact strings, so regular expressions and CSS selectors are refused.
68
+ *
69
+ * @param api the Detox API whose `by` builds the matcher.
70
+ * @throws Error for a `css` signal, a regular expression, or a role without a name.
52
71
  */
53
72
  export declare function detoxMatcher(api: DetoxApi, signal: Signal): DetoxMatcher;
54
73
  /**
55
- * Drive a native app with Detox. Screenshots come from `device.takeScreenshot`. Detox records
56
- * video per test through its artifacts plugin rather than per call, so this driver does not
57
- * record clips; enable Detox's `--record-videos` to keep a video of each attempt.
74
+ * Creates a driver for a native app tested with Detox. Every path attempt relaunches the app
75
+ * (`device.launchApp({ newInstance: true })`) and terminates it afterwards. Screenshots come from
76
+ * `device.takeScreenshot`. Detox records video per test through its artifacts plugin rather than per
77
+ * call, so this driver does not record clips; enable Detox's `--record-videos` to keep a video of
78
+ * each attempt.
79
+ *
80
+ * The Detox globals are read when an attempt opens, so call `runConfig` from inside a Detox test.
81
+ * Signals are resolved with `detoxMatcher`, so regular expressions and CSS selectors are refused.
82
+ *
83
+ * @param options `api` to use instead of the globals, and `launchArgs` for the app.
84
+ * @returns a driver whose context is a `DetoxContext`.
85
+ *
86
+ * @example
87
+ * const config = defineConfig<DetoxContext>({
88
+ * specs: './specs',
89
+ * driver: detoxDriver({ launchArgs: { resetData: true } }),
90
+ * implementation
91
+ * });
92
+ * await runConfig(config, { mode: 'fast' });
58
93
  */
59
94
  export declare function detoxDriver(options?: DetoxDriverOptions): Driver<DetoxContext>;
60
- /** A state recognised by Detox matchers: every `all` visible and no `none` visible. */
95
+ /**
96
+ * Builds a state implementation recognised by Detox matchers: matched when every `all` matcher is
97
+ * visible and no `none` matcher is. `checks` pair a statement from the state's `meta.checks` with
98
+ * the matcher that proves it. Each entry's `name` appears in failure reports. Unlike
99
+ * `screen(...)` from the signals module it takes matchers, not signals, and has no `any`.
100
+ *
101
+ * @example
102
+ * states: { 'No todos': detoxScreen({ all: [{ matcher: by.text('Nothing to do yet'), name: 'empty message' }] }) }
103
+ */
61
104
  export declare function detoxScreen(spec: {
62
105
  all: {
63
106
  matcher: DetoxMatcher;
@@ -1,10 +1,23 @@
1
+ /**
2
+ * @module Detox driver
3
+ *
4
+ * The Atlas driver for native iOS and Android apps tested with Detox (https://wix.github.io/Detox/).
5
+ * It owns launching and terminating the app, mapping signals to Detox matchers, screenshots, and
6
+ * logging taps and typing to the step timeline; it does not record video (Detox does that through its
7
+ * artifacts plugin). It must run inside a Detox test, where Detox's `device`, `element`, `by` and
8
+ * `waitFor` globals exist, or be given them as `api`. Detox is typed structurally here, so importing
9
+ * this module needs no Detox install.
10
+ */
1
11
  import { copyFileSync, mkdirSync } from 'node:fs';
2
12
  import path from 'node:path';
3
13
  import { describeSignal } from '../../core/src/signals.js';
4
14
  /**
5
- * A signal as a Detox matcher: test IDs are `by.id` (React Native's `testID`), labels `by.label`,
6
- * text `by.text`, a role with a name `by.label` (with the iOS `button` trait when Detox has it).
7
- * Detox matches exact strings, so regular expressions and CSS selectors are refused.
15
+ * Translates a signal into a Detox matcher: test IDs are `by.id` (React Native's `testID`), labels
16
+ * `by.label`, text `by.text`, a role with a name `by.label` (with the iOS `button` trait when Detox
17
+ * has it). Detox matches exact strings, so regular expressions and CSS selectors are refused.
18
+ *
19
+ * @param api the Detox API whose `by` builds the matcher.
20
+ * @throws Error for a `css` signal, a regular expression, or a role without a name.
8
21
  */
9
22
  export function detoxMatcher(api, signal) {
10
23
  if ('testId' in signal)
@@ -26,9 +39,25 @@ export function detoxMatcher(api, signal) {
26
39
  return byLabel;
27
40
  }
28
41
  /**
29
- * Drive a native app with Detox. Screenshots come from `device.takeScreenshot`. Detox records
30
- * video per test through its artifacts plugin rather than per call, so this driver does not
31
- * record clips; enable Detox's `--record-videos` to keep a video of each attempt.
42
+ * Creates a driver for a native app tested with Detox. Every path attempt relaunches the app
43
+ * (`device.launchApp({ newInstance: true })`) and terminates it afterwards. Screenshots come from
44
+ * `device.takeScreenshot`. Detox records video per test through its artifacts plugin rather than per
45
+ * call, so this driver does not record clips; enable Detox's `--record-videos` to keep a video of
46
+ * each attempt.
47
+ *
48
+ * The Detox globals are read when an attempt opens, so call `runConfig` from inside a Detox test.
49
+ * Signals are resolved with `detoxMatcher`, so regular expressions and CSS selectors are refused.
50
+ *
51
+ * @param options `api` to use instead of the globals, and `launchArgs` for the app.
52
+ * @returns a driver whose context is a `DetoxContext`.
53
+ *
54
+ * @example
55
+ * const config = defineConfig<DetoxContext>({
56
+ * specs: './specs',
57
+ * driver: detoxDriver({ launchArgs: { resetData: true } }),
58
+ * implementation
59
+ * });
60
+ * await runConfig(config, { mode: 'fast' });
32
61
  */
33
62
  export function detoxDriver(options = {}) {
34
63
  const api = () => options.api ?? globalThis;
@@ -74,6 +103,7 @@ export function detoxDriver(options = {}) {
74
103
  }
75
104
  };
76
105
  }
106
+ /** Whether the matcher's element is visible right now: asks Detox with a zero timeout and counts any failure as not visible. */
77
107
  async function visible(ctx, matcher) {
78
108
  try {
79
109
  await ctx.waitFor(ctx.element(matcher)).toBeVisible().withTimeout(0);
@@ -83,7 +113,15 @@ async function visible(ctx, matcher) {
83
113
  return false;
84
114
  }
85
115
  }
86
- /** A state recognised by Detox matchers: every `all` visible and no `none` visible. */
116
+ /**
117
+ * Builds a state implementation recognised by Detox matchers: matched when every `all` matcher is
118
+ * visible and no `none` matcher is. `checks` pair a statement from the state's `meta.checks` with
119
+ * the matcher that proves it. Each entry's `name` appears in failure reports. Unlike
120
+ * `screen(...)` from the signals module it takes matchers, not signals, and has no `any`.
121
+ *
122
+ * @example
123
+ * states: { 'No todos': detoxScreen({ all: [{ matcher: by.text('Nothing to do yet'), name: 'empty message' }] }) }
124
+ */
87
125
  export function detoxScreen(spec) {
88
126
  return {
89
127
  async recognize(ctx) {
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @module Playwright driver
3
+ *
4
+ * `playwrightDriver()` is the core `Driver` that runs a statechart's paths against a web app (or a React Native app
5
+ * on the web) in Chromium. Each path attempt gets its own browser context and page; the `PlaywrightContext` it passes
6
+ * to event and state implementations carries the page and paced user actions. Screens are recognised by signals
7
+ * (`signals.ts`), and screenshots, clips and touch overlay come from `media.ts`.
8
+ *
9
+ * @see docs/statecharts.md
10
+ */
1
11
  import type { Driver } from '../../core/src/index.js';
2
12
  import type { SignalContext } from '../../core/src/signals.js';
3
13
  import type { Browser, BrowserContext, BrowserContextOptions, LaunchOptions, Page } from 'playwright';
@@ -14,11 +24,13 @@ export type PlaywrightContext = SignalContext & {
14
24
  /** Paced taps and typing, logged to the step's timeline and shown by the touch overlay in videos. */
15
25
  user: UserActions;
16
26
  };
27
+ /** Options of `playwrightDriver`; every field is optional. */
17
28
  export type PlaywrightDriverOptions = {
18
29
  /** Where `goto` paths resolve; the implementation's setup decides where to open. */
19
30
  baseUrl?: string | (() => string | Promise<string>);
20
31
  /** Browser context options; a 390×844 phone at device scale factor 3 with touch by default. */
21
32
  device?: BrowserContextOptions;
33
+ /** Options for `chromium.launch`. */
22
34
  launch?: LaunchOptions;
23
35
  /** Override the pacing used in showcase mode. */
24
36
  pacing?: Partial<Pacing>;
@@ -37,8 +49,32 @@ export type PlaywrightDriverOptions = {
37
49
  concurrency?: number;
38
50
  };
39
51
  /**
40
- * Drive a web app (or a React Native app on the web) with Playwright. Screenshots are taken at the
41
- * device's physical resolution; clips are recorded at that resolution too and encoded with
42
- * FFmpeg as H.264 MP4 (FFmpeg on the PATH is needed for video and WebP thumbnails).
52
+ * Drives a web app (or a React Native app on the web) in Chromium with Playwright, for `atlas run`. Pass it in the
53
+ * config as `driver: () => playwrightDriver(options)`. The browser launches on first use (and again if it was
54
+ * disconnected) and is shared by every context; each path attempt opens a fresh context from `options.device`
55
+ * (default `PHONE`). Screenshots are taken at the device's physical resolution; clips are recorded at that
56
+ * resolution too and encoded with FFmpeg as H.264 MP4. FFmpeg must be on the PATH: each screenshot also writes a
57
+ * WebP thumbnail with it, so without FFmpeg no screenshot is recorded (the run goes on). A Playwright trace is
58
+ * kept only for a failed attempt that was traced (see `trace`), and `dispose` closes the browser.
59
+ *
60
+ * @see docs/statecharts.md
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { defineConfig } from '@crvouga/atlas';
65
+ * import { playwrightDriver, screen, text } from '@crvouga/atlas/playwright';
66
+ *
67
+ * export default defineConfig({
68
+ * specs: './specs',
69
+ * driver: () => playwrightDriver({ clock: true }),
70
+ * implementation: {
71
+ * async setup({ page }) { await page.goto('http://127.0.0.1:4317'); },
72
+ * events: {
73
+ * // one entry per event of the spec
74
+ * },
75
+ * states: { 'No todos': screen({ all: [text('Nothing to do yet')] }) }
76
+ * }
77
+ * });
78
+ * ```
43
79
  */
44
80
  export declare function playwrightDriver(options?: PlaywrightDriverOptions): Driver<PlaywrightContext>;
@@ -2,9 +2,33 @@ import { chromium } from 'playwright';
2
2
  import { captureScreen, FAST_PACING, PHONE, ScreencastRecorder, SHOWCASE_PACING, UserActions } from './media.js';
3
3
  import { locate } from './signals.js';
4
4
  /**
5
- * Drive a web app (or a React Native app on the web) with Playwright. Screenshots are taken at the
6
- * device's physical resolution; clips are recorded at that resolution too and encoded with
7
- * FFmpeg as H.264 MP4 (FFmpeg on the PATH is needed for video and WebP thumbnails).
5
+ * Drives a web app (or a React Native app on the web) in Chromium with Playwright, for `atlas run`. Pass it in the
6
+ * config as `driver: () => playwrightDriver(options)`. The browser launches on first use (and again if it was
7
+ * disconnected) and is shared by every context; each path attempt opens a fresh context from `options.device`
8
+ * (default `PHONE`). Screenshots are taken at the device's physical resolution; clips are recorded at that
9
+ * resolution too and encoded with FFmpeg as H.264 MP4. FFmpeg must be on the PATH: each screenshot also writes a
10
+ * WebP thumbnail with it, so without FFmpeg no screenshot is recorded (the run goes on). A Playwright trace is
11
+ * kept only for a failed attempt that was traced (see `trace`), and `dispose` closes the browser.
12
+ *
13
+ * @see docs/statecharts.md
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { defineConfig } from '@crvouga/atlas';
18
+ * import { playwrightDriver, screen, text } from '@crvouga/atlas/playwright';
19
+ *
20
+ * export default defineConfig({
21
+ * specs: './specs',
22
+ * driver: () => playwrightDriver({ clock: true }),
23
+ * implementation: {
24
+ * async setup({ page }) { await page.goto('http://127.0.0.1:4317'); },
25
+ * events: {
26
+ * // one entry per event of the spec
27
+ * },
28
+ * states: { 'No todos': screen({ all: [text('Nothing to do yet')] }) }
29
+ * }
30
+ * });
31
+ * ```
8
32
  */
9
33
  export function playwrightDriver(options = {}) {
10
34
  let browser = null;
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @module Playwright driver entry point (`@crvouga/atlas/playwright`)
3
+ *
4
+ * Re-exports the Playwright driver for statechart runs (`playwrightDriver`), the helpers an implementation uses to
5
+ * recognise screens and tap or type (`screen`, `recognize`, `locate`, the signal constructors and `UserActions`), and
6
+ * the media tools (`captureScreen`, `ScreencastRecorder`, `ffmpeg`, `PHONE` and the pacing presets). Needs the
7
+ * `playwright` package; clips and thumbnails need FFmpeg on the PATH.
8
+ *
9
+ * @see docs/statecharts.md
10
+ */
1
11
  export { playwrightDriver, type PlaywrightContext, type PlaywrightDriverOptions } from './driver.js';
2
12
  export { captureScreen, ScreencastRecorder, UserActions, PHONE, SHOWCASE_PACING, FAST_PACING, ffmpeg, type Pacing } from './media.js';
3
13
  export { recognize, checkSignals, screen, locate, describeSignal, testId, text, role, label, css, type Signal, type SignatureSpec } from './signals.js';
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @module Playwright driver entry point (`@crvouga/atlas/playwright`)
3
+ *
4
+ * Re-exports the Playwright driver for statechart runs (`playwrightDriver`), the helpers an implementation uses to
5
+ * recognise screens and tap or type (`screen`, `recognize`, `locate`, the signal constructors and `UserActions`), and
6
+ * the media tools (`captureScreen`, `ScreencastRecorder`, `ffmpeg`, `PHONE` and the pacing presets). Needs the
7
+ * `playwright` package; clips and thumbnails need FFmpeg on the PATH.
8
+ *
9
+ * @see docs/statecharts.md
10
+ */
1
11
  export { playwrightDriver } from './driver.js';
2
12
  export { captureScreen, ScreencastRecorder, UserActions, PHONE, SHOWCASE_PACING, FAST_PACING, ffmpeg } from './media.js';
3
13
  export { recognize, checkSignals, screen, locate, describeSignal, testId, text, role, label, css } from './signals.js';
@@ -1,6 +1,10 @@
1
1
  import type { Locator, Page } from 'playwright';
2
2
  import type { Timeline } from '../../core/src/index.js';
3
3
  import type { Signal } from '../../core/src/signals.js';
4
+ /**
5
+ * Pauses, in milliseconds, that make a showcase video readable: how long the touch indicator takes to glide to a tap
6
+ * target, the pause before the tap, the delay between typed characters, and the holds after and before a step.
7
+ */
4
8
  export type Pacing = {
5
9
  moveMs: number;
6
10
  pauseBeforeTapMs: number;
@@ -8,8 +12,14 @@ export type Pacing = {
8
12
  holdAfterMs: number;
9
13
  holdBeforeMs: number;
10
14
  };
15
+ /** The default pacing of showcase mode: a visible glide and pauses, so a person can follow the clip. */
11
16
  export declare const SHOWCASE_PACING: Pacing;
17
+ /** No pauses at all; the pacing of fast mode. */
12
18
  export declare const FAST_PACING: Pacing;
19
+ /**
20
+ * The default `device` of `playwrightDriver`: a 390 by 844 CSS pixel viewport at device scale factor 3 (screenshots
21
+ * are 1170 by 2532 pixels), a mobile user agent and touch.
22
+ */
13
23
  export declare const PHONE: {
14
24
  readonly viewport: {
15
25
  readonly width: 390;
@@ -19,31 +29,61 @@ export declare const PHONE: {
19
29
  readonly isMobile: true;
20
30
  readonly hasTouch: true;
21
31
  };
22
- /** Taps and typing a person would do, paced for showcase videos and logged to the step timeline. */
32
+ /**
33
+ * Taps and typing a person would do, paced for showcase videos and logged to the step timeline. Provided to event
34
+ * implementations as `user` on the `PlaywrightContext`. `showTouches` turns on the touch indicator (showcase mode).
35
+ */
23
36
  export declare class UserActions {
24
37
  readonly page: Page;
25
38
  readonly pacing: Pacing;
26
39
  timeline: Timeline;
27
40
  readonly showTouches: boolean;
28
41
  constructor(page: Page, pacing: Pacing, timeline: Timeline, showTouches: boolean);
42
+ /**
43
+ * Registers the touch indicator overlay to be added to every page load, so it exists before the app's scripts run.
44
+ * Call it once per page, before navigating.
45
+ */
29
46
  static install(page: Page): Promise<void>;
30
47
  private overlay;
31
- /** Tap a locator or a signal (resolved with `locate`). */
48
+ /**
49
+ * Taps the centre of a locator or a signal (resolved with `locate`). Waits up to 15 s for it to be visible, scrolls
50
+ * it
51
+ * into view, logs a `tap` entry labelled `label` to the timeline, then clicks (10 s timeout). In showcase mode the
52
+ * touch
53
+ * indicator glides there first. Throws when the target has no position on screen.
54
+ */
32
55
  tap(target: Locator | Signal, label: string): Promise<void>;
56
+ /**
57
+ * Taps `target`, clears it, then types `text` one character at a time, `pacing.typeDelayMs` apart. Logs a `tap` and
58
+ * a `type` entry labelled `label` to the timeline.
59
+ */
33
60
  type(target: Locator | Signal, text: string, label: string): Promise<void>;
61
+ /** Waits `ms` milliseconds; does nothing when `ms` is zero or less. */
34
62
  hold(ms: number): Promise<void>;
63
+ /** Hides the touch indicator, so a screenshot does not show it. */
35
64
  hideTouches(): Promise<void>;
65
+ /** Shows the touch indicator again after `hideTouches`. */
36
66
  showTouchLayer(): Promise<void>;
37
67
  }
68
+ /** The files `captureScreen` wrote: the full-size PNG and its WebP thumbnail. */
38
69
  export type ScreenshotFiles = {
39
70
  png: string;
40
71
  webp?: string;
41
72
  };
42
- /** A settled, deterministic capture at device resolution, with the touch layer hidden. */
73
+ /**
74
+ * Takes a settled, deterministic screenshot at device resolution, with the touch layer hidden: waits for the network to
75
+ * go quiet (up to 5 s) and for fonts, disables animations and hides the caret. Writes the PNG to `file` (creating its
76
+ * folder) and a 400 px wide WebP thumbnail beside it with FFmpeg. `mask` lists locators to paint over. Rejects when
77
+ * FFmpeg is missing or fails.
78
+ */
43
79
  export declare function captureScreen(page: Page, driver: UserActions, file: string, mask?: Locator[]): Promise<ScreenshotFiles>;
80
+ /**
81
+ * Runs `ffmpeg` with `args` and resolves when it exits with code 0. Rejects with the spawn error when `ffmpeg` is not
82
+ * on the PATH, or with `ffmpeg <code>: <stderr>` when it fails.
83
+ */
44
84
  export declare function ffmpeg(args: string[]): Promise<void>;
45
85
  /**
46
- * Records a clip at the phone's physical resolution (1170×2532). Chrome's screencast, and
86
+ * Records a clip of a page at its physical resolution (1170×2532 for the default `PHONE`). Chrome's screencast, and
47
87
  * Playwright's built-in video that rides on it, only deliver CSS-pixel frames (390×844) and
48
88
  * upscale them, so text goes soft. Instead this loops device-scale JPEG captures (about 20 fps
49
89
  * here), keeps each frame's own timestamp, and encodes H.264 at 30 fps, holding each frame for as
@@ -59,7 +99,13 @@ export declare class ScreencastRecorder {
59
99
  private running;
60
100
  private loop;
61
101
  constructor(page: Page, scale?: number);
102
+ /** Begins capturing frames of the page into `workDirectory`, which is emptied first. Call `stop` to encode them. */
62
103
  start(workDirectory: string): Promise<void>;
104
+ /**
105
+ * Stops capturing and encodes the frames to the MP4 file `output` (the poster is written beside it, with `.mp4`
106
+ * replaced by `.poster.webp`), then deletes the work directory. Resolves to `{ video, poster, durationMs }`, or
107
+ * `null` when no frame was captured.
108
+ */
63
109
  stop(output: string): Promise<{
64
110
  video: string;
65
111
  poster: string;