@overcrow/mcp 0.0.0 → 0.1.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 (461) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -1
  3. package/dist/audit/index.js +103 -0
  4. package/dist/audit/lexer.js +417 -0
  5. package/dist/audit/project.js +200 -0
  6. package/dist/audit/rules.js +661 -0
  7. package/dist/bootstrap/download.js +229 -0
  8. package/dist/bootstrap/install.js +280 -0
  9. package/dist/bootstrap/pin.js +85 -0
  10. package/dist/bootstrap/pin.json +119 -0
  11. package/dist/bootstrap/zip.js +258 -0
  12. package/dist/cli.js +200 -0
  13. package/dist/confine.js +244 -0
  14. package/dist/content/docs/en/cli.md +353 -0
  15. package/dist/content/docs/en/dev-channel.md +130 -0
  16. package/dist/content/docs/en/elements.md +469 -0
  17. package/dist/content/docs/en/forms.md +328 -0
  18. package/dist/content/docs/en/guide.md +253 -0
  19. package/dist/content/docs/en/index.md +85 -0
  20. package/dist/content/docs/en/limits.md +241 -0
  21. package/dist/content/docs/en/logic.md +446 -0
  22. package/dist/content/docs/en/manifest.md +381 -0
  23. package/dist/content/docs/en/mcp.md +165 -0
  24. package/dist/content/docs/en/package.md +131 -0
  25. package/dist/content/docs/en/publishing.md +162 -0
  26. package/dist/content/docs/en/reference.md +55 -0
  27. package/dist/content/docs/en/result-shapes.md +332 -0
  28. package/dist/content/docs/en/sdk.md +295 -0
  29. package/dist/content/docs/en/security.md +115 -0
  30. package/dist/content/docs/en/service-reference.md +344 -0
  31. package/dist/content/docs/en/services.md +517 -0
  32. package/dist/content/docs/en/style-properties.md +270 -0
  33. package/dist/content/docs/en/style.md +266 -0
  34. package/dist/content/docs/en/testing.md +400 -0
  35. package/dist/content/docs/en/view.md +338 -0
  36. package/dist/content/docs/en/widgets.md +76 -0
  37. package/dist/content/docs/fr/cli.md +367 -0
  38. package/dist/content/docs/fr/dev-channel.md +140 -0
  39. package/dist/content/docs/fr/elements.md +475 -0
  40. package/dist/content/docs/fr/forms.md +341 -0
  41. package/dist/content/docs/fr/guide.md +264 -0
  42. package/dist/content/docs/fr/index.md +90 -0
  43. package/dist/content/docs/fr/limits.md +244 -0
  44. package/dist/content/docs/fr/logic.md +461 -0
  45. package/dist/content/docs/fr/manifest.md +392 -0
  46. package/dist/content/docs/fr/mcp.md +173 -0
  47. package/dist/content/docs/fr/package.md +139 -0
  48. package/dist/content/docs/fr/publishing.md +172 -0
  49. package/dist/content/docs/fr/reference.md +59 -0
  50. package/dist/content/docs/fr/result-shapes.md +333 -0
  51. package/dist/content/docs/fr/sdk.md +301 -0
  52. package/dist/content/docs/fr/security.md +129 -0
  53. package/dist/content/docs/fr/service-reference.md +346 -0
  54. package/dist/content/docs/fr/services.md +540 -0
  55. package/dist/content/docs/fr/style-properties.md +272 -0
  56. package/dist/content/docs/fr/style.md +281 -0
  57. package/dist/content/docs/fr/testing.md +417 -0
  58. package/dist/content/docs/fr/view.md +352 -0
  59. package/dist/content/docs/fr/widgets.md +81 -0
  60. package/dist/content/examples/clock/LICENSE +21 -0
  61. package/dist/content/examples/clock/README.md +75 -0
  62. package/dist/content/examples/clock/listing.json +19 -0
  63. package/dist/content/examples/clock/locales/en.json +4 -0
  64. package/dist/content/examples/clock/locales/fr.json +4 -0
  65. package/dist/content/examples/clock/logic.ts +85 -0
  66. package/dist/content/examples/clock/manifest.json +44 -0
  67. package/dist/content/examples/clock/package.json +16 -0
  68. package/dist/content/examples/clock/style.ocss +26 -0
  69. package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
  70. package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
  71. package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
  72. package/dist/content/examples/clock/tests/options.scenario.json +108 -0
  73. package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
  74. package/dist/content/examples/clock/tests/render.scenario.json +94 -0
  75. package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
  76. package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
  77. package/dist/content/examples/clock/tsconfig.json +16 -0
  78. package/dist/content/examples/clock/view.ocml +8 -0
  79. package/dist/content/examples/countdown/LICENSE +20 -0
  80. package/dist/content/examples/countdown/listing.json +10 -0
  81. package/dist/content/examples/countdown/locales/en.json +15 -0
  82. package/dist/content/examples/countdown/locales/fr.json +15 -0
  83. package/dist/content/examples/countdown/logic.ts +179 -0
  84. package/dist/content/examples/countdown/manifest.json +34 -0
  85. package/dist/content/examples/countdown/package.json +15 -0
  86. package/dist/content/examples/countdown/style.ocss +94 -0
  87. package/dist/content/examples/countdown/tsconfig.json +16 -0
  88. package/dist/content/examples/countdown/view.ocml +42 -0
  89. package/dist/content/examples/fps/LICENSE +21 -0
  90. package/dist/content/examples/fps/README.md +64 -0
  91. package/dist/content/examples/fps/listing.json +19 -0
  92. package/dist/content/examples/fps/locales/en.json +11 -0
  93. package/dist/content/examples/fps/locales/fr.json +11 -0
  94. package/dist/content/examples/fps/logic.ts +64 -0
  95. package/dist/content/examples/fps/manifest.json +30 -0
  96. package/dist/content/examples/fps/package.json +16 -0
  97. package/dist/content/examples/fps/style.ocss +31 -0
  98. package/dist/content/examples/fps/tests/label.scenario.json +63 -0
  99. package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
  100. package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
  101. package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
  102. package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
  103. package/dist/content/examples/fps/tests/render.scenario.json +96 -0
  104. package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
  105. package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
  106. package/dist/content/examples/fps/tsconfig.json +16 -0
  107. package/dist/content/examples/fps/view.ocml +11 -0
  108. package/dist/content/examples/media/LICENSE +21 -0
  109. package/dist/content/examples/media/README.md +147 -0
  110. package/dist/content/examples/media/listing.json +19 -0
  111. package/dist/content/examples/media/locales/en.json +11 -0
  112. package/dist/content/examples/media/locales/fr.json +11 -0
  113. package/dist/content/examples/media/logic.ts +191 -0
  114. package/dist/content/examples/media/manifest.json +35 -0
  115. package/dist/content/examples/media/package.json +16 -0
  116. package/dist/content/examples/media/style.ocss +148 -0
  117. package/dist/content/examples/media/tests/covers.scenario.json +144 -0
  118. package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
  119. package/dist/content/examples/media/tests/load-logic.mjs +22 -0
  120. package/dist/content/examples/media/tests/logic.test.mjs +176 -0
  121. package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
  122. package/dist/content/examples/media/tests/preview.scenario.json +52 -0
  123. package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
  124. package/dist/content/examples/media/tests/refused.scenario.json +22 -0
  125. package/dist/content/examples/media/tests/refused.test.mjs +31 -0
  126. package/dist/content/examples/media/tests/render.scenario.json +136 -0
  127. package/dist/content/examples/media/tests/states.scenario.json +257 -0
  128. package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
  129. package/dist/content/examples/media/tsconfig.json +16 -0
  130. package/dist/content/examples/media/view.ocml +41 -0
  131. package/dist/content/examples/notes/LICENSE +21 -0
  132. package/dist/content/examples/notes/README.md +219 -0
  133. package/dist/content/examples/notes/listing.json +19 -0
  134. package/dist/content/examples/notes/locales/en.json +25 -0
  135. package/dist/content/examples/notes/locales/fr.json +25 -0
  136. package/dist/content/examples/notes/logic.ts +799 -0
  137. package/dist/content/examples/notes/manifest.json +40 -0
  138. package/dist/content/examples/notes/package.json +16 -0
  139. package/dist/content/examples/notes/style.ocss +469 -0
  140. package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
  141. package/dist/content/examples/notes/tests/create.scenario.json +260 -0
  142. package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
  143. package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
  144. package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
  145. package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
  146. package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
  147. package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
  148. package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
  149. package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
  150. package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
  151. package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
  152. package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
  153. package/dist/content/examples/notes/tests/save.scenario.json +378 -0
  154. package/dist/content/examples/notes/tests/states.scenario.json +640 -0
  155. package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
  156. package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
  157. package/dist/content/examples/notes/tsconfig.json +16 -0
  158. package/dist/content/examples/notes/view.ocml +154 -0
  159. package/dist/content/examples/performance/LICENSE +21 -0
  160. package/dist/content/examples/performance/README.md +134 -0
  161. package/dist/content/examples/performance/listing.json +19 -0
  162. package/dist/content/examples/performance/locales/en.json +20 -0
  163. package/dist/content/examples/performance/locales/fr.json +20 -0
  164. package/dist/content/examples/performance/logic.ts +210 -0
  165. package/dist/content/examples/performance/manifest.json +83 -0
  166. package/dist/content/examples/performance/package.json +16 -0
  167. package/dist/content/examples/performance/style.ocss +75 -0
  168. package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
  169. package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
  170. package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
  171. package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
  172. package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
  173. package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
  174. package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
  175. package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
  176. package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
  177. package/dist/content/examples/performance/tests/region.scenario.json +89 -0
  178. package/dist/content/examples/performance/tests/render.scenario.json +112 -0
  179. package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
  180. package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
  181. package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
  182. package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
  183. package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
  184. package/dist/content/examples/performance/tsconfig.json +16 -0
  185. package/dist/content/examples/performance/view.ocml +18 -0
  186. package/dist/content/examples/playervox-journal/LICENSE +21 -0
  187. package/dist/content/examples/playervox-journal/README.md +150 -0
  188. package/dist/content/examples/playervox-journal/listing.json +19 -0
  189. package/dist/content/examples/playervox-journal/locales/en.json +25 -0
  190. package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
  191. package/dist/content/examples/playervox-journal/logic.ts +556 -0
  192. package/dist/content/examples/playervox-journal/manifest.json +19 -0
  193. package/dist/content/examples/playervox-journal/package.json +16 -0
  194. package/dist/content/examples/playervox-journal/style.ocss +142 -0
  195. package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
  196. package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
  197. package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
  198. package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
  199. package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
  200. package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
  201. package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
  202. package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
  203. package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
  204. package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
  205. package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
  206. package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
  207. package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
  208. package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
  209. package/dist/content/examples/playervox-journal/view.ocml +52 -0
  210. package/dist/content/examples/playervox-rating/LICENSE +21 -0
  211. package/dist/content/examples/playervox-rating/README.md +166 -0
  212. package/dist/content/examples/playervox-rating/listing.json +19 -0
  213. package/dist/content/examples/playervox-rating/locales/en.json +35 -0
  214. package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
  215. package/dist/content/examples/playervox-rating/logic.ts +581 -0
  216. package/dist/content/examples/playervox-rating/manifest.json +19 -0
  217. package/dist/content/examples/playervox-rating/package.json +16 -0
  218. package/dist/content/examples/playervox-rating/style.ocss +333 -0
  219. package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
  220. package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
  221. package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
  222. package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
  223. package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
  224. package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
  225. package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
  226. package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
  227. package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
  228. package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
  229. package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
  230. package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
  231. package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
  232. package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
  233. package/dist/content/examples/playervox-rating/view.ocml +62 -0
  234. package/dist/content/examples/playervox-reviews/LICENSE +21 -0
  235. package/dist/content/examples/playervox-reviews/README.md +194 -0
  236. package/dist/content/examples/playervox-reviews/listing.json +19 -0
  237. package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
  238. package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
  239. package/dist/content/examples/playervox-reviews/logic.ts +822 -0
  240. package/dist/content/examples/playervox-reviews/manifest.json +30 -0
  241. package/dist/content/examples/playervox-reviews/package.json +16 -0
  242. package/dist/content/examples/playervox-reviews/style.ocss +260 -0
  243. package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
  244. package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
  245. package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
  246. package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
  247. package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
  248. package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
  249. package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
  250. package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
  251. package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
  252. package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
  253. package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
  254. package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
  255. package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
  256. package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
  257. package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
  258. package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
  259. package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
  260. package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
  261. package/dist/content/examples/playervox-reviews/view.ocml +110 -0
  262. package/dist/content/examples/playervox-score/LICENSE +21 -0
  263. package/dist/content/examples/playervox-score/README.md +131 -0
  264. package/dist/content/examples/playervox-score/listing.json +19 -0
  265. package/dist/content/examples/playervox-score/locales/en.json +23 -0
  266. package/dist/content/examples/playervox-score/locales/fr.json +23 -0
  267. package/dist/content/examples/playervox-score/logic.ts +430 -0
  268. package/dist/content/examples/playervox-score/manifest.json +47 -0
  269. package/dist/content/examples/playervox-score/package.json +16 -0
  270. package/dist/content/examples/playervox-score/style.ocss +247 -0
  271. package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
  272. package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
  273. package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
  274. package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
  275. package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
  276. package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
  277. package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
  278. package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
  279. package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
  280. package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
  281. package/dist/content/examples/playervox-score/tsconfig.json +16 -0
  282. package/dist/content/examples/playervox-score/view.ocml +51 -0
  283. package/dist/content/examples/session/LICENSE +21 -0
  284. package/dist/content/examples/session/README.md +57 -0
  285. package/dist/content/examples/session/listing.json +19 -0
  286. package/dist/content/examples/session/locales/en.json +3 -0
  287. package/dist/content/examples/session/locales/fr.json +3 -0
  288. package/dist/content/examples/session/logic.ts +26 -0
  289. package/dist/content/examples/session/manifest.json +19 -0
  290. package/dist/content/examples/session/package.json +16 -0
  291. package/dist/content/examples/session/style.ocss +16 -0
  292. package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
  293. package/dist/content/examples/session/tests/load-logic.mjs +22 -0
  294. package/dist/content/examples/session/tests/logic.test.mjs +37 -0
  295. package/dist/content/examples/session/tests/preview.scenario.json +28 -0
  296. package/dist/content/examples/session/tests/refused.scenario.json +20 -0
  297. package/dist/content/examples/session/tests/refused.test.mjs +16 -0
  298. package/dist/content/examples/session/tests/render.scenario.json +95 -0
  299. package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
  300. package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
  301. package/dist/content/examples/session/tsconfig.json +16 -0
  302. package/dist/content/examples/session/view.ocml +11 -0
  303. package/dist/content/examples/stopwatch/LICENSE +21 -0
  304. package/dist/content/examples/stopwatch/README.md +99 -0
  305. package/dist/content/examples/stopwatch/listing.json +19 -0
  306. package/dist/content/examples/stopwatch/locales/en.json +8 -0
  307. package/dist/content/examples/stopwatch/locales/fr.json +8 -0
  308. package/dist/content/examples/stopwatch/logic.ts +93 -0
  309. package/dist/content/examples/stopwatch/manifest.json +19 -0
  310. package/dist/content/examples/stopwatch/package.json +16 -0
  311. package/dist/content/examples/stopwatch/style.ocss +54 -0
  312. package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
  313. package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
  314. package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
  315. package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
  316. package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
  317. package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
  318. package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
  319. package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
  320. package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
  321. package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
  322. package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
  323. package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
  324. package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
  325. package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
  326. package/dist/content/examples/stopwatch/tsconfig.json +16 -0
  327. package/dist/content/examples/stopwatch/view.ocml +29 -0
  328. package/dist/content/examples/twitch-chat/LICENSE +21 -0
  329. package/dist/content/examples/twitch-chat/README.md +283 -0
  330. package/dist/content/examples/twitch-chat/listing.json +19 -0
  331. package/dist/content/examples/twitch-chat/locales/en.json +52 -0
  332. package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
  333. package/dist/content/examples/twitch-chat/logic.ts +887 -0
  334. package/dist/content/examples/twitch-chat/manifest.json +33 -0
  335. package/dist/content/examples/twitch-chat/package.json +16 -0
  336. package/dist/content/examples/twitch-chat/style.ocss +544 -0
  337. package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
  338. package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
  339. package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
  340. package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
  341. package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
  342. package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
  343. package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
  344. package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
  345. package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
  346. package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
  347. package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
  348. package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
  349. package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
  350. package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
  351. package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
  352. package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
  353. package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
  354. package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
  355. package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
  356. package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
  357. package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
  358. package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
  359. package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
  360. package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
  361. package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
  362. package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
  363. package/dist/content/examples/twitch-chat/view.ocml +141 -0
  364. package/dist/content/examples/warframe-market/LICENSE +21 -0
  365. package/dist/content/examples/warframe-market/README.md +176 -0
  366. package/dist/content/examples/warframe-market/listing.json +19 -0
  367. package/dist/content/examples/warframe-market/locales/en.json +44 -0
  368. package/dist/content/examples/warframe-market/locales/fr.json +44 -0
  369. package/dist/content/examples/warframe-market/logic.ts +1265 -0
  370. package/dist/content/examples/warframe-market/manifest.json +92 -0
  371. package/dist/content/examples/warframe-market/package.json +16 -0
  372. package/dist/content/examples/warframe-market/style.ocss +422 -0
  373. package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
  374. package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
  375. package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
  376. package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
  377. package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
  378. package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
  379. package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
  380. package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
  381. package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
  382. package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
  383. package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
  384. package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
  385. package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
  386. package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
  387. package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
  388. package/dist/content/examples/warframe-market/tsconfig.json +16 -0
  389. package/dist/content/examples/warframe-market/view.ocml +116 -0
  390. package/dist/content/examples/weather/LICENSE +20 -0
  391. package/dist/content/examples/weather/listing.json +10 -0
  392. package/dist/content/examples/weather/locales/en.json +9 -0
  393. package/dist/content/examples/weather/locales/fr.json +9 -0
  394. package/dist/content/examples/weather/logic.ts +62 -0
  395. package/dist/content/examples/weather/manifest.json +51 -0
  396. package/dist/content/examples/weather/package.json +15 -0
  397. package/dist/content/examples/weather/style.ocss +29 -0
  398. package/dist/content/examples/weather/tsconfig.json +16 -0
  399. package/dist/content/examples/weather/view.ocml +12 -0
  400. package/dist/content/index.json +3601 -0
  401. package/dist/content/reference/errors.json +1712 -0
  402. package/dist/content/reference/limits.json +1154 -0
  403. package/dist/content/reference/manifest.md +223 -0
  404. package/dist/content/reference/permissions.json +413 -0
  405. package/dist/content/templates/blank/locales/en.json +3 -0
  406. package/dist/content/templates/blank/locales/fr.json +3 -0
  407. package/dist/content/templates/blank/logic.ts +7 -0
  408. package/dist/content/templates/blank/manifest.json +16 -0
  409. package/dist/content/templates/blank/style.ocss +10 -0
  410. package/dist/content/templates/blank/tests/example.scenario.json +10 -0
  411. package/dist/content/templates/blank/view.ocml +6 -0
  412. package/dist/content/templates/chart/locales/en.json +3 -0
  413. package/dist/content/templates/chart/locales/fr.json +3 -0
  414. package/dist/content/templates/chart/logic.ts +27 -0
  415. package/dist/content/templates/chart/manifest.json +16 -0
  416. package/dist/content/templates/chart/style.ocss +27 -0
  417. package/dist/content/templates/chart/tests/example.scenario.json +10 -0
  418. package/dist/content/templates/chart/view.ocml +10 -0
  419. package/dist/content/templates/counter/locales/en.json +4 -0
  420. package/dist/content/templates/counter/locales/fr.json +4 -0
  421. package/dist/content/templates/counter/logic.ts +20 -0
  422. package/dist/content/templates/counter/manifest.json +16 -0
  423. package/dist/content/templates/counter/style.ocss +26 -0
  424. package/dist/content/templates/counter/tests/example.scenario.json +11 -0
  425. package/dist/content/templates/counter/view.ocml +13 -0
  426. package/dist/content/templates/list/locales/en.json +8 -0
  427. package/dist/content/templates/list/locales/fr.json +8 -0
  428. package/dist/content/templates/list/logic.ts +35 -0
  429. package/dist/content/templates/list/manifest.json +16 -0
  430. package/dist/content/templates/list/style.ocss +42 -0
  431. package/dist/content/templates/list/tests/example.scenario.json +10 -0
  432. package/dist/content/templates/list/view.ocml +17 -0
  433. package/dist/content/templates/shared/LICENSE +20 -0
  434. package/dist/content/templates/shared/package.json +14 -0
  435. package/dist/content/templates/shared/tsconfig.json +16 -0
  436. package/dist/content.js +68 -0
  437. package/dist/env.js +156 -0
  438. package/dist/fingerprint.js +32 -0
  439. package/dist/ids.js +27 -0
  440. package/dist/index.js +82 -0
  441. package/dist/knowledge.js +222 -0
  442. package/dist/npm.js +149 -0
  443. package/dist/prompts.js +47 -0
  444. package/dist/resources.js +82 -0
  445. package/dist/run.js +120 -0
  446. package/dist/server.js +43 -0
  447. package/dist/session.js +205 -0
  448. package/dist/sources.js +218 -0
  449. package/dist/text.js +80 -0
  450. package/dist/texts.js +44 -0
  451. package/dist/tools/audit.js +105 -0
  452. package/dist/tools/build.js +453 -0
  453. package/dist/tools/common.js +122 -0
  454. package/dist/tools/docs.js +196 -0
  455. package/dist/tools/preview.js +87 -0
  456. package/dist/tools/project.js +178 -0
  457. package/dist/tools/setup.js +146 -0
  458. package/dist/tools/submission.js +369 -0
  459. package/dist/version.js +3 -0
  460. package/npm-shrinkwrap.json +402 -0
  461. package/package.json +50 -4
@@ -0,0 +1,400 @@
1
+ # Testing a widget
2
+
3
+ A PlayerVox OverCrow widget is tested in two ways, both without a desktop,
4
+ a game or an account:
5
+
6
+ - **Unit tests of the logic**, in Node.js, with `@overcrow/sdk/testing`:
7
+ fast, for the functions of `logic.ts`.
8
+ - **Scenarios**, played by `overcrow-widget test` in OverCrow's **headless
9
+ runtime**: the real VM, style, layout and renderer, OverCrow's own
10
+ checks, simulated services, virtual time and reference images. What
11
+ passes there is what the overlay shows.
12
+
13
+ <!-- source: templates/counter/tests/example.scenario.json -->
14
+ ```json
15
+ {
16
+ "scenarioVersion": 1,
17
+ "name": "example",
18
+ "description": "The counter starts at 0 and Increase adds one. `overcrow-widget test` plays it and compares the images with tests/reference/example/; `--update` records them again (https://overcrow.playervox.com/docs/en/testing/).",
19
+ "host": { "mode": "interactive" },
20
+ "steps": [
21
+ { "expect": { "state": "running", "text": ["0"], "image": "initial" } },
22
+ { "pointer": { "click": { "label": "Increase" } } },
23
+ { "expect": { "text": ["1"], "noText": ["0"], "image": "increased", "fault": "none" } }
24
+ ]
25
+ }
26
+ ```
27
+
28
+ This scenario starts the counter in Interactive mode, checks that it shows
29
+ `0` and compares its image with a reference, clicks the button whose label
30
+ is "Increase", then checks the new text and image.
31
+
32
+ ## Unit tests
33
+
34
+ `@overcrow/sdk/testing` comes with the SDK: `npm install` in a project made
35
+ by `overcrow-widget init`, otherwise
36
+ `npm install --save-dev --save-exact @overcrow/sdk@1.0.0`.
37
+
38
+ `installRuntime()` puts a stand-in for OverCrow in place before the logic
39
+ is imported: service calls return promises that your test settles,
40
+ subscriptions take the values you push, timers fire when you advance the
41
+ time, and `Date.now()` is virtual.
42
+
43
+ <!-- source: widgets/clock/tests/logic.test.mjs -->
44
+ ```js
45
+ const START = Date.UTC(2026, 6, 17, 12, 8, 42, 250);
46
+ const vm = installRuntime({
47
+ now: START,
48
+ host: {
49
+ region: { numberFormat: "us", dateOrder: "mdy", offsetMinutes: 120 },
50
+ messages: { label: "Local time {time}", "label-date": "Local time {time}, {date}" },
51
+ },
52
+ });
53
+ const logic = await loadLogic();
54
+ const { state } = await import("@overcrow/sdk");
55
+ ```
56
+
57
+ <!-- source: widgets/clock/tests/logic.test.mjs -->
58
+ ```js
59
+ test("one timer at the next local minute, then each minute", () => {
60
+ assert.equal(vm.timers.length, 1);
61
+ assert.equal(vm.timers[0].dueAt, Date.UTC(2026, 6, 17, 12, 9));
62
+ vm.advance(Date.UTC(2026, 6, 17, 12, 9) - vm.now);
63
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:09");
64
+ assert.deepEqual(
65
+ vm.timers.map(({ intervalMs, repeat }) => ({ intervalMs, repeat })),
66
+ [{ intervalMs: 60_000, repeat: true }],
67
+ );
68
+ assert.equal(vm.advance(120_000), 2);
69
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:11");
70
+ });
71
+ ```
72
+
73
+ | Member | Does |
74
+ | --- | --- |
75
+ | `installRuntime({ now, host })` | Installs the stand-in; `Date.now()` returns the virtual time. One at a time. |
76
+ | `now`, `advance(ms)` | The virtual time; `advance` fires the timers that fall due, in order (a repeating one re-arms), and returns their count. |
77
+ | `setHost(changes)` | Changes `host` as OverCrow does: `region`, `locale`, `options`… |
78
+ | `calls`, `lastCall(service)` | Every service call, with `resolve(value)` and `reject(code)`. |
79
+ | `push(service, value)`, `fail(service, code)` | The next update, or the final failure, of the subscriptions to a service. |
80
+ | `menu(row)` | Chooses an `action` row of the options menu. |
81
+ | `draws`, `logs`, `timers`, `table` | What the logic sent: canvas drawings, logs, timers, and the functions of the view. |
82
+ | `uninstall()` | Removes the stand-in and gives `Date.now` back. |
83
+
84
+ The stand-in runs your logic only: it does not apply OverCrow's rules (the
85
+ grants, the accounts, the user-action rule) and renders nothing. Scenarios
86
+ do. The reference widgets compile their `logic.ts` with a small loader
87
+ before importing it:
88
+
89
+ <!-- source: widgets/clock/tests/load-logic.mjs -->
90
+ ```js
91
+ export async function loadLogic() {
92
+ const root = new URL("../", import.meta.url);
93
+ const source = readFileSync(new URL("logic.ts", root), "utf8");
94
+ const { outputText } = ts.transpileModule(source, {
95
+ compilerOptions: {
96
+ module: ts.ModuleKind.ES2022,
97
+ target: ts.ScriptTarget.ES2023,
98
+ verbatimModuleSyntax: true,
99
+ },
100
+ });
101
+ mkdirSync(new URL("dist/", root), { recursive: true });
102
+ // One file per test process: test files run in parallel.
103
+ const output = new URL(`dist/logic-${process.pid}.mjs`, root);
104
+ writeFileSync(output, outputText);
105
+ return import(output.href);
106
+ }
107
+ ```
108
+
109
+ ## Scenarios
110
+
111
+ A scenario is a JSON file of the project, `tests/<name>.scenario.json`,
112
+ whose `name` is `<name>`. Its reference images are
113
+ `tests/reference/<name>/<image>.png`. Neither is packaged.
114
+
115
+ ```sh
116
+ overcrow-widget test
117
+ overcrow-widget test --scenario example
118
+ overcrow-widget test --update
119
+ ```
120
+
121
+ `--update` records the captured images as the references: look at them
122
+ before you commit them. A failed image writes
123
+ `tests/output/<name>/<image>.actual.png` and, for a difference,
124
+ `<image>.diff.png`, with the differing pixels in red.
125
+
126
+ A scenario has four parts: `host` (the user's settings), `fixtures` (what
127
+ the services answer), `assets` (images for the fixtures) and `steps` (what
128
+ happens, and what must hold). The format is strict: an unknown field, name
129
+ or value is an error of the scenario, reported with its path
130
+ (`steps[3].pointer.click`) before anything runs. It is also checked against
131
+ the manifest: the grants the widget declares, the menu rows that exist, the
132
+ services of its capabilities.
133
+
134
+ ### `host`
135
+
136
+ Everything is optional.
137
+
138
+ | Member | Default | Meaning |
139
+ | --- | --- | --- |
140
+ | `locale` | `en` | `en` or `fr`. |
141
+ | `theme` | `dark` | `dark` or `light`. |
142
+ | `scale` | `1000` | Content scale in thousandths: 500 to 1750 (50 % to 175 %). |
143
+ | `size` | the manifest's preferred size | `{ width, height }` of the frame, in logical pixels; the manifest's `fit` still applies. |
144
+ | `mode` | `passive` | `interactive` gives input to the widget. |
145
+ | `visible` | `true` | Hidden, the widget gets no timer tick. |
146
+ | `frame` | `false` | `true` captures OverCrow's frame around the content. |
147
+ | `background` | the theme's panel colour | `#rrggbb` behind the widget. |
148
+ | `region` | `us`, date order of the locale | `{ numberFormat, dateOrder }`. |
149
+ | `zone` | UTC | `{ offsetMinutes, transitions: [{ at, offsetMinutes }] }`: the user's UTC offset, and the instants at which it changes. |
150
+ | `startAt` | 2026-01-01T00:00:00Z | The virtual time at which the widget starts, in Unix milliseconds. |
151
+ | `options` | the rows' defaults | Values of the rows of the options menu. |
152
+ | `grants` | `"declared"` | Or the exact list of what the user granted (`storage`, `network`, `fps.read`…): OverCrow refuses the rest. |
153
+ | `accounts` | connected | `{ playervox, twitch }`, each `connected`, `disconnected`, `pending`, `expired` or `offline`. |
154
+ | `features` | all | The data sources of the machine, for `requires`. |
155
+ | `storage` | empty | The widget's storage before it starts. |
156
+
157
+ <!-- source: widgets/clock/tests/summer-time.scenario.json -->
158
+ ```json
159
+ "host": {
160
+ "zone": {
161
+ "offsetMinutes": 60,
162
+ "transitions": [
163
+ {
164
+ "at": 1774746000000,
165
+ "offsetMinutes": 120
166
+ },
167
+ {
168
+ "at": 1792890000000,
169
+ "offsetMinutes": 60
170
+ }
171
+ ]
172
+ },
173
+ "startAt": 1774745970000
174
+ },
175
+ ```
176
+
177
+ With an account that is not `connected`, OverCrow draws its own account
178
+ panel over the widget, as it does for the user; capture it with `frame`.
179
+
180
+ ### `fixtures`
181
+
182
+ Fixtures replace where the data comes from, never OverCrow's checks. A call
183
+ first passes the grants, its parameters, the user-action rule and the
184
+ account check, exactly as in the overlay; only then does a fixture answer
185
+ it. Every value must have the shape of the service's
186
+ [result](result-shapes.md): one that does not is an error of the scenario,
187
+ not of the widget.
188
+
189
+ | Member | Answers |
190
+ | --- | --- |
191
+ | `subscriptions` | The value of a subscription when it starts; `publish` steps send the next ones. |
192
+ | `calls` | The calls of a service, in order: `{ "value": … }` or `{ "error": code }`. A call beyond them is an error of the scenario. |
193
+ | `http` | The `http.fetch` requests, each used once: `{ "request": { method, url }, "response": { status, contentType, body } }` (or `bodyBase64`), or `{ "request": …, "error": code }`. The manifest's network rules apply first, and the response bounds apply as in the overlay. |
194
+ | `confirmations` | `accept` or `cancel`, in order, for OverCrow's confirmation of `notes.delete` and `journal.delete`. |
195
+ | `intents` | The answer to each submitted [write intent](forms.md#forms-that-write-user-data), in order: `"accepted"`, `{ "error": code }` or `"pending"`. |
196
+
197
+ <!-- source: widgets/stopwatch/tests/errors.scenario.json -->
198
+ ```json
199
+ "fixtures": {
200
+ "calls": {
201
+ "stopwatch.toggle": [
202
+ {
203
+ "error": "unavailable"
204
+ },
205
+ {
206
+ "value": {
207
+ "running": true,
208
+ "elapsedMs": 5000,
209
+ "at": 0,
210
+ "shortcuts": {
211
+ "toggle": "Super+Alt+T",
212
+ "reset": "Super+Alt+Z",
213
+ "bound": true
214
+ }
215
+ }
216
+ }
217
+ ],
218
+ "stopwatch.reset": [
219
+ {
220
+ "error": "stale_context"
221
+ }
222
+ ]
223
+ },
224
+ "subscriptions": {
225
+ "stopwatch.subscribe": {
226
+ "running": false,
227
+ "elapsedMs": 5000,
228
+ "at": 0,
229
+ "shortcuts": {
230
+ "toggle": "Super+Alt+T",
231
+ "reset": "Super+Alt+Z",
232
+ "bound": true
233
+ }
234
+ }
235
+ }
236
+ },
237
+ ```
238
+
239
+ <!-- source: widgets/warframe-market/tests/errors.scenario.json -->
240
+ ```json
241
+ "http": [
242
+ {
243
+ "request": {
244
+ "method": "GET",
245
+ "url": "https://api.warframe.market/v2/versions"
246
+ },
247
+ "error": "timeout"
248
+ },
249
+ {
250
+ "request": {
251
+ "method": "GET",
252
+ "url": "https://api.warframe.market/v2/orders/item/primed_flow"
253
+ },
254
+ "error": "transport_failed"
255
+ },
256
+ {
257
+ "request": {
258
+ "method": "GET",
259
+ "url": "https://api.warframe.market/v2/orders/item/primed_flow"
260
+ },
261
+ "response": {
262
+ "status": 200,
263
+ "contentType": "application/json",
264
+ "body": "{\"apiVersion\":\"0.25.0\",\"data\":[],\"error\":null}"
265
+ }
266
+ }
267
+ ]
268
+ ```
269
+
270
+ The codes that OverCrow gives itself (`permission_denied`,
271
+ `gesture_required`, `not_connected`, `invalid_request`) cannot be written
272
+ in a fixture: get them the real way, with `grants`, `accounts`, a call
273
+ outside a user action, or wrong parameters. Storage, timers and the
274
+ clipboard are OverCrow's own and need no fixture.
275
+
276
+ ### `assets`
277
+
278
+ Images that a fixture hands to the widget, as OverCrow hands it a media
279
+ cover or a chat emote: `{ "<name>": "<path>" }`, at most 8, each a PNG or
280
+ JPEG of the project (`tests/assets/cover.png`). Where a result holds an
281
+ image handle, the fixture writes `"fixture:<name>"`.
282
+
283
+ ### `steps`
284
+
285
+ | Step | Does |
286
+ | --- | --- |
287
+ | `{ "advance": { "ms": N } }` | Moves the virtual time by `N` ms. Every timer due on the way fires in order, and the UTC offset changes at its instant. |
288
+ | `{ "advance": { "ms": N, "jump": true } }` | Moves the time at once, as a machine waking from sleep: each due timer fires once, late. |
289
+ | `{ "host": { … } }` | Changes `locale`, `theme`, `scale`, `size`, `mode`, `visible`, `region`, `zone` or `accounts`. |
290
+ | `{ "pointer": { "click": target } }` | A click. Also `rightClick`, `move` (hover), `wheel` (`{ target, dx, dy }`) and `"leave"`. |
291
+ | `{ "key": { "key": "Enter", "modifiers": ["shift"] } }` | A key press: `Tab`, `Escape`, `ArrowUp`, letters, digits… |
292
+ | `{ "text": "…" }` | Text typed into the focused field. |
293
+ | `{ "menu": { "id": "row", "value": … } }` | A row of the options menu: the value of a toggle, slider or choice, none for an action. |
294
+ | `{ "publish": { "service": "fps.subscribe", "value": … } }` | The next value of a subscription. |
295
+ | `{ "publish": { "service": "media.subscribe", "error": "unavailable" } }` | Ends the subscription with this failure. |
296
+ | `{ "expect": { … } }` | What must hold once the previous steps settled. |
297
+
298
+ A pointer target is `{ "at": [x, y] }` (logical pixels of the content),
299
+ `{ "text": "…" }` (the first element showing exactly this text) or
300
+ `{ "label": "…" }` (its accessible label). Input reaches the widget in
301
+ Interactive mode only. A click is a user action; a menu row never is.
302
+
303
+ Each step settles before the next: the widget has answered everything it
304
+ was sent and nothing is in flight. There is no real waiting.
305
+
306
+ ### `expect`
307
+
308
+ | Member | Holds when |
309
+ | --- | --- |
310
+ | `image` | The capture matches `tests/reference/<scenario>/<image>.png`. Names are unique in a scenario. |
311
+ | `text`, `noText` | Each text is (is not) the whole text of an element the widget shows. |
312
+ | `calls` | Exactly these service calls were made since the previous `calls` expectation, in order: `{ service, params?, outcome? }`, `outcome` being `ok` or the error code the widget received. |
313
+ | `state` | `starting`, `running`, `restarting`, `failed`, `refused` or `stopped`. |
314
+ | `fault` | The last fault of the widget's VM, or `none`. |
315
+ | `clipboard` | The last text the widget wrote to the clipboard. |
316
+ | `intents` | Exactly these write intents were submitted since the previous `intents` expectation, in order: `{ intent, fields?, outcome? }`. `fields` are the exact values OverCrow's form sent. |
317
+
318
+ <!-- source: templates/chart/tests/example.scenario.json -->
319
+ ```json
320
+ "steps": [
321
+ { "expect": { "state": "running", "text": ["Activity", "50"], "image": "initial" } },
322
+ { "advance": { "ms": 10000 } },
323
+ { "expect": { "noText": ["50"], "image": "ten-seconds", "fault": "none" } }
324
+ ]
325
+ ```
326
+
327
+ The faults a widget's VM can report:
328
+
329
+ <!-- generated:fault-categories -->
330
+ | Category | Fatal | Meaning |
331
+ | --- | --- | --- |
332
+ | `resource_limit` | yes | Heap, stack, job queue or message budget exhausted inside the VM. |
333
+ | `unresponsive` | yes | The turn budget interrupted the VM. |
334
+ | `protocol_violation` | yes | The host sent a message the VM cannot accept. |
335
+ | `invalid_bundle` | yes | `logic.js` or the compiled view failed to load or register. |
336
+ | `handler_exception` | no | An event handler threw; the VM keeps running. |
337
+ <!-- /generated:fault-categories -->
338
+
339
+ ## Reference images
340
+
341
+ An image is the widget's content, rendered at the scenario's scale, theme
342
+ and size. Record the states that matter in both themes, both languages and
343
+ two scales, as the reference widgets do: a scenario can change `theme`,
344
+ `locale` and `scale` between two `expect` steps.
345
+
346
+ <!-- source: templates/list/tests/example.scenario.json -->
347
+ ```json
348
+ "steps": [
349
+ { "expect": { "state": "running", "text": ["Today", "2 left"], "image": "initial" } },
350
+ { "host": { "locale": "fr", "theme": "light" } },
351
+ { "expect": { "image": "french-light", "fault": "none" } }
352
+ ]
353
+ ```
354
+
355
+ Images are compared with a small tolerance: a pixel differs when one of its
356
+ channels differs by more than 2 levels, and the image differs when more
357
+ than 100 pixels per million do. One wrong letter is far above that. A
358
+ reference is never rewritten by a test run: only `--update` records images.
359
+
360
+ ## Time and determinism
361
+
362
+ The runtime is deterministic: the same package and scenario render the same
363
+ bytes, on Linux and on Windows.
364
+
365
+ - Time is virtual: `Date.now()` and `new Date()` return the scenario's
366
+ time, timers fire when the scenario moves it.
367
+ - `Math.random()` is seeded with a fixed value.
368
+ - Text uses the fonts bundled with OverCrow, never the system's.
369
+ - Rendering does not depend on the graphics card.
370
+
371
+ This holds for the test runtime only: in the overlay, time and randomness
372
+ are real.
373
+
374
+ ## The headless runtime
375
+
376
+ `overcrow-widget-headless` is OverCrow's own code without a window: it
377
+ validates the package as the overlay does and runs the widget's logic in
378
+ the same sandbox. `overcrow-widget test` runs the version this CLI pins,
379
+ 0.6.0-beta.2, and prints its version and SHA-256. Without the operating
380
+ system's sandbox the runtime refuses to run and says so; the test command
381
+ then ends with status 2.
382
+
383
+ The first time `test` needs the runtime, it downloads it: from the
384
+ creator tools ZIP of your platform in the OverCrow release that
385
+ published it, it keeps only the runtime, and only once its SHA-256 is the
386
+ one this CLI pins. The ZIP is not kept. The runtime then stays in the CLI's cache:
387
+
388
+ | Platform | Path |
389
+ | --- | --- |
390
+ | Linux | `~/.cache/overcrow-widget/runtime/0.6.0-beta.2/` (`$XDG_CACHE_HOME` instead of `~/.cache` when set) |
391
+ | Windows | `%LOCALAPPDATA%\overcrow-widget\runtime\0.6.0-beta.2\` |
392
+
393
+ To work offline, put the runtime of the creator tools ZIP there yourself
394
+ (executable on Linux): `test` finds it and downloads nothing. With
395
+ `--offline`, `test` never downloads. A proxy set in `HTTPS_PROXY` is used.
396
+
397
+ The CLI checks its SHA-256 before every run. When a download fails,
398
+ nothing is kept and `test` says to try again or to pass `--runtime`.
399
+ `--runtime <path>` runs another runtime instead, such as one built from
400
+ OverCrow; the output then says it is not the pinned one.