@vielzeug/ore 1.0.3

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 (294) hide show
  1. package/README.md +73 -0
  2. package/dist/_dev.cjs +2 -0
  3. package/dist/_dev.cjs.map +1 -0
  4. package/dist/_dev.d.ts +2 -0
  5. package/dist/_dev.d.ts.map +1 -0
  6. package/dist/_dev.js +2 -0
  7. package/dist/_dev.js.map +1 -0
  8. package/dist/aria.cjs +2 -0
  9. package/dist/aria.cjs.map +1 -0
  10. package/dist/aria.d.ts +12 -0
  11. package/dist/aria.d.ts.map +1 -0
  12. package/dist/aria.js +2 -0
  13. package/dist/aria.js.map +1 -0
  14. package/dist/base-element.cjs +2 -0
  15. package/dist/base-element.cjs.map +1 -0
  16. package/dist/base-element.d.ts +22 -0
  17. package/dist/base-element.d.ts.map +1 -0
  18. package/dist/base-element.js +2 -0
  19. package/dist/base-element.js.map +1 -0
  20. package/dist/component-types.d.ts +104 -0
  21. package/dist/component-types.d.ts.map +1 -0
  22. package/dist/context-bag.cjs +2 -0
  23. package/dist/context-bag.cjs.map +1 -0
  24. package/dist/context-bag.d.ts +12 -0
  25. package/dist/context-bag.d.ts.map +1 -0
  26. package/dist/context-bag.js +2 -0
  27. package/dist/context-bag.js.map +1 -0
  28. package/dist/context.cjs +2 -0
  29. package/dist/context.cjs.map +1 -0
  30. package/dist/context.d.ts +15 -0
  31. package/dist/context.d.ts.map +1 -0
  32. package/dist/context.js +2 -0
  33. package/dist/context.js.map +1 -0
  34. package/dist/define.cjs +2 -0
  35. package/dist/define.cjs.map +1 -0
  36. package/dist/define.d.ts +33 -0
  37. package/dist/define.d.ts.map +1 -0
  38. package/dist/define.js +2 -0
  39. package/dist/define.js.map +1 -0
  40. package/dist/devtools.cjs +2 -0
  41. package/dist/devtools.cjs.map +1 -0
  42. package/dist/devtools.d.ts +32 -0
  43. package/dist/devtools.d.ts.map +1 -0
  44. package/dist/devtools.js +2 -0
  45. package/dist/devtools.js.map +1 -0
  46. package/dist/directives/classMap.cjs +2 -0
  47. package/dist/directives/classMap.cjs.map +1 -0
  48. package/dist/directives/classMap.d.ts +19 -0
  49. package/dist/directives/classMap.d.ts.map +1 -0
  50. package/dist/directives/classMap.js +2 -0
  51. package/dist/directives/classMap.js.map +1 -0
  52. package/dist/directives/each.cjs +2 -0
  53. package/dist/directives/each.cjs.map +1 -0
  54. package/dist/directives/each.d.ts +25 -0
  55. package/dist/directives/each.d.ts.map +1 -0
  56. package/dist/directives/each.js +2 -0
  57. package/dist/directives/each.js.map +1 -0
  58. package/dist/directives/index.d.ts +8 -0
  59. package/dist/directives/index.d.ts.map +1 -0
  60. package/dist/directives/live.cjs +2 -0
  61. package/dist/directives/live.cjs.map +1 -0
  62. package/dist/directives/live.d.ts +25 -0
  63. package/dist/directives/live.d.ts.map +1 -0
  64. package/dist/directives/live.js +2 -0
  65. package/dist/directives/live.js.map +1 -0
  66. package/dist/directives/model.cjs +2 -0
  67. package/dist/directives/model.cjs.map +1 -0
  68. package/dist/directives/model.d.ts +28 -0
  69. package/dist/directives/model.d.ts.map +1 -0
  70. package/dist/directives/model.js +2 -0
  71. package/dist/directives/model.js.map +1 -0
  72. package/dist/directives/raw.cjs +2 -0
  73. package/dist/directives/raw.cjs.map +1 -0
  74. package/dist/directives/raw.d.ts +16 -0
  75. package/dist/directives/raw.d.ts.map +1 -0
  76. package/dist/directives/raw.js +2 -0
  77. package/dist/directives/raw.js.map +1 -0
  78. package/dist/directives/styleMap.cjs +2 -0
  79. package/dist/directives/styleMap.cjs.map +1 -0
  80. package/dist/directives/styleMap.d.ts +25 -0
  81. package/dist/directives/styleMap.d.ts.map +1 -0
  82. package/dist/directives/styleMap.js +2 -0
  83. package/dist/directives/styleMap.js.map +1 -0
  84. package/dist/directives/when.cjs +2 -0
  85. package/dist/directives/when.cjs.map +1 -0
  86. package/dist/directives/when.d.ts +19 -0
  87. package/dist/directives/when.d.ts.map +1 -0
  88. package/dist/directives/when.js +2 -0
  89. package/dist/directives/when.js.map +1 -0
  90. package/dist/directives.cjs +1 -0
  91. package/dist/directives.js +1 -0
  92. package/dist/errors.cjs +3 -0
  93. package/dist/errors.cjs.map +1 -0
  94. package/dist/errors.d.ts +47 -0
  95. package/dist/errors.d.ts.map +1 -0
  96. package/dist/errors.js +3 -0
  97. package/dist/errors.js.map +1 -0
  98. package/dist/form-context.cjs +2 -0
  99. package/dist/form-context.cjs.map +1 -0
  100. package/dist/form-context.d.ts +56 -0
  101. package/dist/form-context.d.ts.map +1 -0
  102. package/dist/form-context.js +2 -0
  103. package/dist/form-context.js.map +1 -0
  104. package/dist/form-field.cjs +2 -0
  105. package/dist/form-field.cjs.map +1 -0
  106. package/dist/form-field.d.ts +31 -0
  107. package/dist/form-field.d.ts.map +1 -0
  108. package/dist/form-field.js +2 -0
  109. package/dist/form-field.js.map +1 -0
  110. package/dist/host-bind.cjs +2 -0
  111. package/dist/host-bind.cjs.map +1 -0
  112. package/dist/host-bind.d.ts +37 -0
  113. package/dist/host-bind.d.ts.map +1 -0
  114. package/dist/host-bind.js +2 -0
  115. package/dist/host-bind.js.map +1 -0
  116. package/dist/index.cjs +1 -0
  117. package/dist/index.d.ts +15 -0
  118. package/dist/index.d.ts.map +1 -0
  119. package/dist/index.js +1 -0
  120. package/dist/observers/index.d.ts +5 -0
  121. package/dist/observers/index.d.ts.map +1 -0
  122. package/dist/observers/intersection-observe.cjs +2 -0
  123. package/dist/observers/intersection-observe.cjs.map +1 -0
  124. package/dist/observers/intersection-observe.d.ts +9 -0
  125. package/dist/observers/intersection-observe.d.ts.map +1 -0
  126. package/dist/observers/intersection-observe.js +2 -0
  127. package/dist/observers/intersection-observe.js.map +1 -0
  128. package/dist/observers/media-observe.cjs +2 -0
  129. package/dist/observers/media-observe.cjs.map +1 -0
  130. package/dist/observers/media-observe.d.ts +8 -0
  131. package/dist/observers/media-observe.d.ts.map +1 -0
  132. package/dist/observers/media-observe.js +2 -0
  133. package/dist/observers/media-observe.js.map +1 -0
  134. package/dist/observers/mutation-observe.cjs +2 -0
  135. package/dist/observers/mutation-observe.cjs.map +1 -0
  136. package/dist/observers/mutation-observe.d.ts +10 -0
  137. package/dist/observers/mutation-observe.d.ts.map +1 -0
  138. package/dist/observers/mutation-observe.js +2 -0
  139. package/dist/observers/mutation-observe.js.map +1 -0
  140. package/dist/observers/resize-observe.cjs +2 -0
  141. package/dist/observers/resize-observe.cjs.map +1 -0
  142. package/dist/observers/resize-observe.d.ts +11 -0
  143. package/dist/observers/resize-observe.d.ts.map +1 -0
  144. package/dist/observers/resize-observe.js +2 -0
  145. package/dist/observers/resize-observe.js.map +1 -0
  146. package/dist/observers.cjs +1 -0
  147. package/dist/observers.js +1 -0
  148. package/dist/ore.cjs +3 -0
  149. package/dist/ore.cjs.map +1 -0
  150. package/dist/ore.iife.js +3 -0
  151. package/dist/ore.iife.js.map +1 -0
  152. package/dist/ore.js +3 -0
  153. package/dist/ore.js.map +1 -0
  154. package/dist/props.cjs +2 -0
  155. package/dist/props.cjs.map +1 -0
  156. package/dist/props.d.ts +76 -0
  157. package/dist/props.d.ts.map +1 -0
  158. package/dist/props.js +2 -0
  159. package/dist/props.js.map +1 -0
  160. package/dist/runtime.cjs +2 -0
  161. package/dist/runtime.cjs.map +1 -0
  162. package/dist/runtime.d.ts +34 -0
  163. package/dist/runtime.d.ts.map +1 -0
  164. package/dist/runtime.js +2 -0
  165. package/dist/runtime.js.map +1 -0
  166. package/dist/slots.cjs +2 -0
  167. package/dist/slots.cjs.map +1 -0
  168. package/dist/slots.d.ts +13 -0
  169. package/dist/slots.d.ts.map +1 -0
  170. package/dist/slots.js +2 -0
  171. package/dist/slots.js.map +1 -0
  172. package/dist/template/bindings.cjs +2 -0
  173. package/dist/template/bindings.cjs.map +1 -0
  174. package/dist/template/bindings.d.ts +17 -0
  175. package/dist/template/bindings.d.ts.map +1 -0
  176. package/dist/template/bindings.js +2 -0
  177. package/dist/template/bindings.js.map +1 -0
  178. package/dist/template/compiler.cjs +2 -0
  179. package/dist/template/compiler.cjs.map +1 -0
  180. package/dist/template/compiler.d.ts +27 -0
  181. package/dist/template/compiler.d.ts.map +1 -0
  182. package/dist/template/compiler.js +2 -0
  183. package/dist/template/compiler.js.map +1 -0
  184. package/dist/template/instantiator.cjs +2 -0
  185. package/dist/template/instantiator.cjs.map +1 -0
  186. package/dist/template/instantiator.d.ts +16 -0
  187. package/dist/template/instantiator.d.ts.map +1 -0
  188. package/dist/template/instantiator.js +2 -0
  189. package/dist/template/instantiator.js.map +1 -0
  190. package/dist/template.cjs +1 -0
  191. package/dist/template.d.ts +4 -0
  192. package/dist/template.d.ts.map +1 -0
  193. package/dist/template.js +1 -0
  194. package/dist/testing/events.cjs +2 -0
  195. package/dist/testing/events.cjs.map +1 -0
  196. package/dist/testing/events.d.ts +37 -0
  197. package/dist/testing/events.d.ts.map +1 -0
  198. package/dist/testing/events.js +2 -0
  199. package/dist/testing/events.js.map +1 -0
  200. package/dist/testing/flush.cjs +2 -0
  201. package/dist/testing/flush.cjs.map +1 -0
  202. package/dist/testing/flush.d.ts +55 -0
  203. package/dist/testing/flush.d.ts.map +1 -0
  204. package/dist/testing/flush.js +2 -0
  205. package/dist/testing/flush.js.map +1 -0
  206. package/dist/testing/index.d.ts +2 -0
  207. package/dist/testing/index.d.ts.map +1 -0
  208. package/dist/testing/interactions.cjs +2 -0
  209. package/dist/testing/interactions.cjs.map +1 -0
  210. package/dist/testing/interactions.d.ts +27 -0
  211. package/dist/testing/interactions.d.ts.map +1 -0
  212. package/dist/testing/interactions.js +2 -0
  213. package/dist/testing/interactions.js.map +1 -0
  214. package/dist/testing/mount.cjs +2 -0
  215. package/dist/testing/mount.cjs.map +1 -0
  216. package/dist/testing/mount.d.ts +107 -0
  217. package/dist/testing/mount.d.ts.map +1 -0
  218. package/dist/testing/mount.js +2 -0
  219. package/dist/testing/mount.js.map +1 -0
  220. package/dist/testing/query.cjs +2 -0
  221. package/dist/testing/query.cjs.map +1 -0
  222. package/dist/testing/query.d.ts +24 -0
  223. package/dist/testing/query.d.ts.map +1 -0
  224. package/dist/testing/query.js +2 -0
  225. package/dist/testing/query.js.map +1 -0
  226. package/dist/testing/render-hook.cjs +2 -0
  227. package/dist/testing/render-hook.cjs.map +1 -0
  228. package/dist/testing/render-hook.d.ts +44 -0
  229. package/dist/testing/render-hook.d.ts.map +1 -0
  230. package/dist/testing/render-hook.js +2 -0
  231. package/dist/testing/render-hook.js.map +1 -0
  232. package/dist/testing/testing.cjs +2 -0
  233. package/dist/testing/testing.cjs.map +1 -0
  234. package/dist/testing/testing.d.ts +26 -0
  235. package/dist/testing/testing.d.ts.map +1 -0
  236. package/dist/testing/testing.js +2 -0
  237. package/dist/testing/testing.js.map +1 -0
  238. package/dist/testing/wait.cjs +2 -0
  239. package/dist/testing/wait.cjs.map +1 -0
  240. package/dist/testing/wait.d.ts +35 -0
  241. package/dist/testing/wait.d.ts.map +1 -0
  242. package/dist/testing/wait.js +2 -0
  243. package/dist/testing/wait.js.map +1 -0
  244. package/dist/testing.cjs +1 -0
  245. package/dist/testing.js +1 -0
  246. package/dist/types/bindings.cjs +2 -0
  247. package/dist/types/bindings.cjs.map +1 -0
  248. package/dist/types/bindings.d.ts +125 -0
  249. package/dist/types/bindings.d.ts.map +1 -0
  250. package/dist/types/bindings.js +2 -0
  251. package/dist/types/bindings.js.map +1 -0
  252. package/dist/types.cjs +2 -0
  253. package/dist/types.cjs.map +1 -0
  254. package/dist/types.d.ts +19 -0
  255. package/dist/types.d.ts.map +1 -0
  256. package/dist/types.js +2 -0
  257. package/dist/types.js.map +1 -0
  258. package/dist/utils/aria.cjs +2 -0
  259. package/dist/utils/aria.cjs.map +1 -0
  260. package/dist/utils/aria.d.ts +16 -0
  261. package/dist/utils/aria.d.ts.map +1 -0
  262. package/dist/utils/aria.js +2 -0
  263. package/dist/utils/aria.js.map +1 -0
  264. package/dist/utils/css.cjs +2 -0
  265. package/dist/utils/css.cjs.map +1 -0
  266. package/dist/utils/css.d.ts +11 -0
  267. package/dist/utils/css.d.ts.map +1 -0
  268. package/dist/utils/css.js +2 -0
  269. package/dist/utils/css.js.map +1 -0
  270. package/dist/utils/dom.cjs +2 -0
  271. package/dist/utils/dom.cjs.map +1 -0
  272. package/dist/utils/dom.d.ts +10 -0
  273. package/dist/utils/dom.d.ts.map +1 -0
  274. package/dist/utils/dom.js +2 -0
  275. package/dist/utils/dom.js.map +1 -0
  276. package/dist/utils/emit.cjs +2 -0
  277. package/dist/utils/emit.cjs.map +1 -0
  278. package/dist/utils/emit.d.ts +16 -0
  279. package/dist/utils/emit.d.ts.map +1 -0
  280. package/dist/utils/emit.js +2 -0
  281. package/dist/utils/emit.js.map +1 -0
  282. package/dist/utils/event-modifiers.cjs +2 -0
  283. package/dist/utils/event-modifiers.cjs.map +1 -0
  284. package/dist/utils/event-modifiers.d.ts +11 -0
  285. package/dist/utils/event-modifiers.d.ts.map +1 -0
  286. package/dist/utils/event-modifiers.js +2 -0
  287. package/dist/utils/event-modifiers.js.map +1 -0
  288. package/dist/utils/id.cjs +2 -0
  289. package/dist/utils/id.cjs.map +1 -0
  290. package/dist/utils/id.d.ts +18 -0
  291. package/dist/utils/id.d.ts.map +1 -0
  292. package/dist/utils/id.js +2 -0
  293. package/dist/utils/id.js.map +1 -0
  294. package/package.json +68 -0
@@ -0,0 +1,2 @@
1
+ const e=require("./flush.cjs"),t=require("./events.cjs");var n=()=>e.flush(),r={async clear(e){e.focus(),e.value=``,t.fire.input(e),t.fire.change(e),await n()},async click(e,r){t.fire.pointerEnter(e,r),t.fire.click(e,r),await n()},async dblClick(e){for(let n=0;n<2;n++)t.fire.pointerDown(e),t.fire.pointerUp(e),t.fire.click(e);e.dispatchEvent(new MouseEvent(`dblclick`,{bubbles:!0,cancelable:!0})),await n()},async fill(e,r){e.focus(),e.value=``;for(let i of r)e.value+=i,t.fire.input(e),t.fire.keyDown(e,{key:i}),t.fire.keyUp(e,{key:i}),await n();t.fire.change(e)},async hover(e){t.fire.pointerEnter(e),await n()},async press(e,r,i){t.fire.keyDown(e,{key:r,...i}),t.fire.keyUp(e,{key:r,...i}),await n()},async select(e,r){let i=Array.isArray(r)?r:[r];for(let t of e.options)t.selected=i.includes(t.value);t.fire.change(e),await n()},async type(e,r){e.focus();for(let i of r)e.value+=i,t.fire.input(e),t.fire.keyDown(e,{key:i}),t.fire.keyUp(e,{key:i}),await n();t.fire.change(e)},async unhover(e){t.fire.pointerLeave(e),await n()}};exports.user=r;
2
+ //# sourceMappingURL=interactions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactions.cjs","names":[],"sources":["../../src/testing/interactions.ts"],"sourcesContent":["/**\n * Higher-level async user interaction helpers for test environments.\n */\n\nimport { fire } from './events';\nimport { flush } from './flush';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nconst tick = (): Promise<void> => flush();\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Higher-level async user interactions that mirror real browser behavior.\n *\n * @example\n * await user.type(input, 'hello');\n * await user.fill(input, 'replacement'); // clear then type\n * await user.click(button);\n * await user.press(input, 'Enter');\n */\nexport const user = {\n async clear(el: HTMLInputElement | HTMLTextAreaElement): Promise<void> {\n el.focus();\n el.value = '';\n fire.input(el);\n fire.change(el);\n await tick();\n },\n\n async click(el: Element, opts?: PointerEventInit): Promise<void> {\n fire.pointerEnter(el, opts);\n fire.click(el, opts);\n await tick();\n },\n\n async dblClick(el: Element): Promise<void> {\n for (let i = 0; i < 2; i++) {\n fire.pointerDown(el);\n fire.pointerUp(el);\n fire.click(el);\n }\n el.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, cancelable: true }));\n await tick();\n },\n\n /** Clear existing value and type new text (select-all-and-replace semantics) */\n async fill(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n el.value = '';\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async hover(el: Element): Promise<void> {\n fire.pointerEnter(el);\n await tick();\n },\n\n /** Dispatch keydown + keyup for a single key */\n async press(el: Element, key: string, opts?: KeyboardEventInit): Promise<void> {\n fire.keyDown(el, { key, ...opts });\n fire.keyUp(el, { key, ...opts });\n await tick();\n },\n\n async select(el: HTMLSelectElement, value: string | string[]): Promise<void> {\n const values = Array.isArray(value) ? value : [value];\n\n for (const opt of el.options) opt.selected = values.includes(opt.value);\n fire.change(el);\n await tick();\n },\n\n /** Type text character-by-character, appending to any existing value */\n async type(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async unhover(el: Element): Promise<void> {\n fire.pointerLeave(el);\n await tick();\n },\n} as const;\n"],"mappings":"yDASA,IAAM,MAA4B,EAAA,MAAM,EAa3B,EAAO,CAClB,MAAM,MAAM,EAA2D,CACrE,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAEA,MAAM,MAAM,EAAa,EAAwC,CAC/D,EAAA,KAAK,aAAa,EAAI,CAAI,EAC1B,EAAA,KAAK,MAAM,EAAI,CAAI,EACnB,MAAM,EAAK,CACb,EAEA,MAAM,SAAS,EAA4B,CACzC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IACrB,EAAA,KAAK,YAAY,CAAE,EACnB,EAAA,KAAK,UAAU,CAAE,EACjB,EAAA,KAAK,MAAM,CAAE,EAEf,EAAG,cAAc,IAAI,WAAW,WAAY,CAAE,QAAS,GAAM,WAAY,EAAK,CAAC,CAAC,EAChF,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAA,KAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAA,KAAK,OAAO,CAAE,CAChB,EAEA,MAAM,MAAM,EAA4B,CACtC,EAAA,KAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,EAGA,MAAM,MAAM,EAAa,EAAa,EAAyC,CAC7E,EAAA,KAAK,QAAQ,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EACjC,EAAA,KAAK,MAAM,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EAC/B,MAAM,EAAK,CACb,EAEA,MAAM,OAAO,EAAuB,EAAyC,CAC3E,IAAM,EAAS,MAAM,QAAQ,CAAK,EAAI,EAAQ,CAAC,CAAK,EAEpD,IAAK,IAAM,KAAO,EAAG,QAAS,EAAI,SAAW,EAAO,SAAS,EAAI,KAAK,EACtE,EAAA,KAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAA,KAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAA,KAAK,OAAO,CAAE,CAChB,EAEA,MAAM,QAAQ,EAA4B,CACxC,EAAA,KAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,CACF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Higher-level async user interaction helpers for test environments.
3
+ */
4
+ /**
5
+ * Higher-level async user interactions that mirror real browser behavior.
6
+ *
7
+ * @example
8
+ * await user.type(input, 'hello');
9
+ * await user.fill(input, 'replacement'); // clear then type
10
+ * await user.click(button);
11
+ * await user.press(input, 'Enter');
12
+ */
13
+ export declare const user: {
14
+ readonly clear: (el: HTMLInputElement | HTMLTextAreaElement) => Promise<void>;
15
+ readonly click: (el: Element, opts?: PointerEventInit) => Promise<void>;
16
+ readonly dblClick: (el: Element) => Promise<void>;
17
+ /** Clear existing value and type new text (select-all-and-replace semantics) */
18
+ readonly fill: (el: HTMLInputElement | HTMLTextAreaElement, text: string) => Promise<void>;
19
+ readonly hover: (el: Element) => Promise<void>;
20
+ /** Dispatch keydown + keyup for a single key */
21
+ readonly press: (el: Element, key: string, opts?: KeyboardEventInit) => Promise<void>;
22
+ readonly select: (el: HTMLSelectElement, value: string | string[]) => Promise<void>;
23
+ /** Type text character-by-character, appending to any existing value */
24
+ readonly type: (el: HTMLInputElement | HTMLTextAreaElement, text: string) => Promise<void>;
25
+ readonly unhover: (el: Element) => Promise<void>;
26
+ };
27
+ //# sourceMappingURL=interactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/testing/interactions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI;yBACC,gBAAgB,GAAG,mBAAmB,KAAG,OAAO,CAAC,IAAI,CAAC;yBAQtD,OAAO,SAAS,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAAC;4BAM7C,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;IAU1C,gFAAgF;wBACjE,gBAAgB,GAAG,mBAAmB,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;yBAanE,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,gDAAgD;yBAChC,OAAO,OAAO,MAAM,SAAS,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC;0BAM7D,iBAAiB,SAAS,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC;IAQ5E,wEAAwE;wBACzD,gBAAgB,GAAG,mBAAmB,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;2BAYjE,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;CAIjC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import{flush as e}from"./flush.js";import{fire as t}from"./events.js";var n=()=>e(),r={async clear(e){e.focus(),e.value=``,t.input(e),t.change(e),await n()},async click(e,r){t.pointerEnter(e,r),t.click(e,r),await n()},async dblClick(e){for(let n=0;n<2;n++)t.pointerDown(e),t.pointerUp(e),t.click(e);e.dispatchEvent(new MouseEvent(`dblclick`,{bubbles:!0,cancelable:!0})),await n()},async fill(e,r){e.focus(),e.value=``;for(let i of r)e.value+=i,t.input(e),t.keyDown(e,{key:i}),t.keyUp(e,{key:i}),await n();t.change(e)},async hover(e){t.pointerEnter(e),await n()},async press(e,r,i){t.keyDown(e,{key:r,...i}),t.keyUp(e,{key:r,...i}),await n()},async select(e,r){let i=Array.isArray(r)?r:[r];for(let t of e.options)t.selected=i.includes(t.value);t.change(e),await n()},async type(e,r){e.focus();for(let i of r)e.value+=i,t.input(e),t.keyDown(e,{key:i}),t.keyUp(e,{key:i}),await n();t.change(e)},async unhover(e){t.pointerLeave(e),await n()}};export{r as user};
2
+ //# sourceMappingURL=interactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactions.js","names":[],"sources":["../../src/testing/interactions.ts"],"sourcesContent":["/**\n * Higher-level async user interaction helpers for test environments.\n */\n\nimport { fire } from './events';\nimport { flush } from './flush';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nconst tick = (): Promise<void> => flush();\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Higher-level async user interactions that mirror real browser behavior.\n *\n * @example\n * await user.type(input, 'hello');\n * await user.fill(input, 'replacement'); // clear then type\n * await user.click(button);\n * await user.press(input, 'Enter');\n */\nexport const user = {\n async clear(el: HTMLInputElement | HTMLTextAreaElement): Promise<void> {\n el.focus();\n el.value = '';\n fire.input(el);\n fire.change(el);\n await tick();\n },\n\n async click(el: Element, opts?: PointerEventInit): Promise<void> {\n fire.pointerEnter(el, opts);\n fire.click(el, opts);\n await tick();\n },\n\n async dblClick(el: Element): Promise<void> {\n for (let i = 0; i < 2; i++) {\n fire.pointerDown(el);\n fire.pointerUp(el);\n fire.click(el);\n }\n el.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, cancelable: true }));\n await tick();\n },\n\n /** Clear existing value and type new text (select-all-and-replace semantics) */\n async fill(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n el.value = '';\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async hover(el: Element): Promise<void> {\n fire.pointerEnter(el);\n await tick();\n },\n\n /** Dispatch keydown + keyup for a single key */\n async press(el: Element, key: string, opts?: KeyboardEventInit): Promise<void> {\n fire.keyDown(el, { key, ...opts });\n fire.keyUp(el, { key, ...opts });\n await tick();\n },\n\n async select(el: HTMLSelectElement, value: string | string[]): Promise<void> {\n const values = Array.isArray(value) ? value : [value];\n\n for (const opt of el.options) opt.selected = values.includes(opt.value);\n fire.change(el);\n await tick();\n },\n\n /** Type text character-by-character, appending to any existing value */\n async type(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async unhover(el: Element): Promise<void> {\n fire.pointerLeave(el);\n await tick();\n },\n} as const;\n"],"mappings":"sEASA,IAAM,MAA4B,EAAM,EAa3B,EAAO,CAClB,MAAM,MAAM,EAA2D,CACrE,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,EAAK,MAAM,CAAE,EACb,EAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAEA,MAAM,MAAM,EAAa,EAAwC,CAC/D,EAAK,aAAa,EAAI,CAAI,EAC1B,EAAK,MAAM,EAAI,CAAI,EACnB,MAAM,EAAK,CACb,EAEA,MAAM,SAAS,EAA4B,CACzC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IACrB,EAAK,YAAY,CAAE,EACnB,EAAK,UAAU,CAAE,EACjB,EAAK,MAAM,CAAE,EAEf,EAAG,cAAc,IAAI,WAAW,WAAY,CAAE,QAAS,GAAM,WAAY,EAAK,CAAC,CAAC,EAChF,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAK,MAAM,CAAE,EACb,EAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAK,OAAO,CAAE,CAChB,EAEA,MAAM,MAAM,EAA4B,CACtC,EAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,EAGA,MAAM,MAAM,EAAa,EAAa,EAAyC,CAC7E,EAAK,QAAQ,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EACjC,EAAK,MAAM,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EAC/B,MAAM,EAAK,CACb,EAEA,MAAM,OAAO,EAAuB,EAAyC,CAC3E,IAAM,EAAS,MAAM,QAAQ,CAAK,EAAI,EAAQ,CAAC,CAAK,EAEpD,IAAK,IAAM,KAAO,EAAG,QAAS,EAAI,SAAW,EAAO,SAAS,EAAI,KAAK,EACtE,EAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAK,MAAM,CAAE,EACb,EAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAK,OAAO,CAAE,CAChB,EAEA,MAAM,QAAQ,EAA4B,CACxC,EAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,CACF"}
@@ -0,0 +1,2 @@
1
+ const e=require("./flush.cjs");require("../types/bindings.cjs");const t=require("../directives/live.cjs"),n=require("../directives/raw.cjs"),r=require("../utils/css.cjs"),i=require("../define.cjs"),a=require("../utils/id.cjs"),o=require("./query.cjs");var s=[],c=0;function l(e,t,n){n===!1?e.removeAttribute(t):e.setAttribute(t,n===!0?``:String(n))}var u=e=>e instanceof Error?e:Error(String(e)),d=async e=>{if(typeof window>`u`)return e();let t=null,n=e=>{t=u(e.error??e.message),e.preventDefault()},r=e=>{t=u(e.reason),e.preventDefault()};window.addEventListener(`error`,n),window.addEventListener(`unhandledrejection`,r);try{let n=await e();if(t)throw t;return n}finally{window.removeEventListener(`error`,n),window.removeEventListener(`unhandledrejection`,r)}};async function f(t,n={}){let{attrs:r={},componentOptions:a,container:u=document.body,html:f,props:p={}}=n,m,h;typeof t==`string`?m=t:(m=`trial-${++c}-${Math.random().toString(36).slice(2,7)}`,h={...a??{},setup:t}),h&&i.define(m,h);let g=document.createElement(m);f&&(g.innerHTML=f),Object.keys(p).length&&Object.assign(g,p);for(let[e,t]of Object.entries(r))l(g,e,t);await d(async()=>{u.appendChild(g),s.push(g),await e.flush()});let _=!1;function v(){if(_)return;_=!0,g.remove();let e=s.indexOf(g);e!==-1&&s.splice(e,1)}return{async act(t){await t(),await e.flush()},async attr(t,n){l(g,t,n),await e.flush()},async attrs(t){for(let[e,n]of Object.entries(t))l(g,e,n);await e.flush()},dispose:v,get disposed(){return _},element:g,flush:e.flush,query(e){return(g.shadowRoot??g).querySelector(e)},queryAll(e){return Array.from((g.shadowRoot??g).querySelectorAll(e))},queryAllByTestId(e){return Array.from((g.shadowRoot??g).querySelectorAll(`[data-testid="${e}"]`))},queryAllByText(e,t=`*`){return o.queryAllByText(g.shadowRoot??g,e,t)},queryByTestId(e){return(g.shadowRoot??g).querySelector(`[data-testid="${e}"]`)},queryByText(e,t=`*`){return o.queryByText(g.shadowRoot??g,e,t)},get shadow(){return g.shadowRoot},[Symbol.dispose](){v()}}}async function p(e,t,n){return i.define(e,t),f(e,n)}function m(e,t=``){customElements.get(e)||customElements.define(e,class extends HTMLElement{connectedCallback(){this.innerHTML=t}})}function h(){for(let e of s)e.remove();s.length=0,n._resetRawSanitizer(),t._resetLiveSignals(),r._clearStylesheetCache(),a._resetIdCounter()}Object.defineProperty(exports,"_componentTagCounter",{enumerable:!0,get:function(){return c}}),exports._mountedElements=s,exports.cleanup=h,exports.mock=m,exports.mount=f,exports.mountComponent=p;
2
+ //# sourceMappingURL=mount.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.cjs","names":[],"sources":["../../src/testing/mount.ts"],"sourcesContent":["/**\n * Component mounting utilities for test environments.\n */\n\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { type ComponentDefinition, type SetupContextBag } from '../component-types';\nimport { define } from '../define';\nimport { _resetLiveSignals } from '../directives/live';\nimport { _resetRawSanitizer } from '../directives/raw';\nimport { type HTMLResult } from '../types/bindings';\nimport { _clearStylesheetCache } from '../utils/css';\nimport { _resetIdCounter } from '../utils/id';\nimport { flush, type FlushOptions } from './flush';\nimport { queryAllByText, queryByText, type QueryScope } from './query';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface Fixture<T extends HTMLElement = HTMLElement> {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose](): void;\n /** Run a callback then flush — the standard way to trigger and assert a reactive update */\n act(fn: () => unknown): Promise<void>;\n /** Set an attribute (boolean `false` removes it) then flush */\n attr(name: string, value: string | number | boolean): Promise<void>;\n /** Set multiple attributes then flush */\n attrs(record: Record<string, string | number | boolean>): Promise<void>;\n /** Remove the component from the DOM. Idempotent. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** The component element */\n element: T;\n /** Wait for all reactive updates and animation frames */\n flush(options?: FlushOptions): Promise<void>;\n /** Query a single element within shadow root */\n query<E extends Element = Element>(selector: string): E | null;\n /** Query all elements within shadow root */\n queryAll<E extends Element = Element>(selector: string): E[];\n /** Query all elements by their `data-testid` attribute */\n queryAllByTestId<E extends Element = Element>(testId: string): E[];\n /** Query all elements whose trimmed text content matches */\n queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];\n /** Query a single element by its `data-testid` attribute */\n queryByTestId<E extends Element = Element>(testId: string): E | null;\n /** Query the first element whose trimmed text content matches */\n queryByText<E extends Element = Element>(text: string, selector?: string): E | null;\n /** The component's shadow root (null for light-DOM components) */\n readonly shadow: ShadowRoot | null;\n}\n\nexport interface MountOptions {\n /** Properties assigned directly onto the element */\n props?: Record<string, unknown>;\n /** HTML attributes to set on the element */\n attrs?: Record<string, string | number | boolean>;\n /** Inner HTML for slot content */\n html?: string;\n /** Parent container (default: document.body) */\n container?: HTMLElement;\n /** Extra component options when passing an inline setup function */\n componentOptions?: Omit<ComponentDefinition<any, any>, 'setup'>;\n}\n\ntype MountProps = { readonly [x: string]: Readable<unknown> };\n\n// Bivariant callback type keeps inline test callbacks ergonomic across varying setup context specializations.\nexport type MountSetup = {\n bivarianceHack: (props: MountProps, ctx: SetupContextBag<any>) => HTMLResult | null | Promise<HTMLResult | null>;\n}['bivarianceHack'];\n\n// ─── Test environment state ───────────────────────────────────────────────────\n\nexport const _mountedElements: HTMLElement[] = [];\nexport let _componentTagCounter = 0;\n\n/**\n * Resets global test counters used for deterministic IDs/markers.\n * @internal\n */\nexport const _resetCounters = (): void => {\n _resetIdCounter();\n _componentTagCounter = 0;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction applyAttr(element: Element, name: string, value: string | number | boolean): void {\n if (value === false) element.removeAttribute(name);\n else element.setAttribute(name, value === true ? '' : String(value));\n}\n\nconst toError = (value: unknown): Error => {\n return value instanceof Error ? value : new Error(String(value));\n};\n\nconst withWindowErrorCapture = async <T>(action: () => Promise<T>): Promise<T> => {\n if (typeof window === 'undefined') return action();\n\n let captured: Error | null = null;\n const onError = (event: ErrorEvent) => {\n captured = toError(event.error ?? event.message);\n event.preventDefault();\n };\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n captured = toError(event.reason);\n event.preventDefault();\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n try {\n const result = await action();\n\n if (captured) throw captured;\n\n return result;\n } finally {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n }\n};\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Mount a component into the DOM and return a test fixture.\n *\n * Accepts a registered tag name, an inline setup function, or a component\n * options object. Setup functions are auto-registered with generated tag names.\n *\n * @example — inline setup function\n * const { query } = await mount(() => {\n * const count = signal(0);\n * return html`<button @click=${() => count.value++}>${count}</button>`;\n * });\n *\n * @example — registered tag name\n * const { query } = await mount('my-counter');\n */\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: string,\n options?: MountOptions,\n): Promise<Fixture<T>>;\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: MountSetup,\n options?: MountOptions,\n): Promise<Fixture<T>>;\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: string | MountSetup,\n options: MountOptions = {},\n): Promise<Fixture<T>> {\n const { attrs = {}, componentOptions, container = document.body, html, props = {} } = options;\n\n let tagName: string;\n let inlineDefinition: ComponentDefinition<any, any> | undefined;\n\n if (typeof tagOrSetup === 'string') {\n tagName = tagOrSetup;\n } else {\n tagName = `trial-${++_componentTagCounter}-${Math.random().toString(36).slice(2, 7)}`;\n inlineDefinition = {\n ...(componentOptions ?? {}),\n setup: tagOrSetup as ComponentDefinition<any, any>['setup'],\n };\n }\n\n if (inlineDefinition) {\n define(tagName, inlineDefinition);\n }\n\n const element = document.createElement(tagName) as T;\n\n if (html) element.innerHTML = html;\n\n if (Object.keys(props).length) Object.assign(element, props);\n\n for (const [name, value] of Object.entries(attrs)) applyAttr(element, name, value);\n\n await withWindowErrorCapture(async () => {\n container.appendChild(element);\n _mountedElements.push(element);\n await flush();\n });\n\n let isDisposed = false;\n\n function dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n element.remove();\n\n const i = _mountedElements.indexOf(element);\n\n if (i !== -1) _mountedElements.splice(i, 1);\n }\n\n return {\n async act(fn) {\n await fn();\n await flush();\n },\n\n async attr(name, value) {\n applyAttr(element, name, value);\n await flush();\n },\n\n async attrs(record) {\n for (const [name, value] of Object.entries(record)) applyAttr(element, name, value);\n await flush();\n },\n\n dispose,\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n element,\n\n flush,\n\n query<E extends Element = Element>(selector: string): E | null {\n return (element.shadowRoot ?? element).querySelector<E>(selector);\n },\n\n queryAll<E extends Element = Element>(selector: string): E[] {\n return Array.from((element.shadowRoot ?? element).querySelectorAll<E>(selector));\n },\n\n queryAllByTestId<E extends Element = Element>(testId: string): E[] {\n return Array.from((element.shadowRoot ?? element).querySelectorAll<E>(`[data-testid=\"${testId}\"]`));\n },\n\n queryAllByText<E extends Element = Element>(text: string, selector = '*'): E[] {\n return queryAllByText<E>((element.shadowRoot ?? element) as Element, text, selector);\n },\n\n queryByTestId<E extends Element = Element>(testId: string): E | null {\n return (element.shadowRoot ?? element).querySelector<E>(`[data-testid=\"${testId}\"]`);\n },\n\n queryByText<E extends Element = Element>(text: string, selector = '*'): E | null {\n return queryByText<E>((element.shadowRoot ?? element) as Element, text, selector);\n },\n\n get shadow(): ShadowRoot | null {\n return element.shadowRoot;\n },\n\n [Symbol.dispose]() {\n dispose();\n },\n };\n}\n\n/**\n * Register and mount a component definition in a single call.\n *\n * Combines `define(tag, definition)` + `mount(tag, options)` — the standard\n * pattern for testing full custom-element lifecycle (props, reconnect, etc.).\n *\n * @example\n * const { query } = await mountComponent('my-counter', {\n * props: { count: prop.number(0) },\n * setup: (props) => html`<div>${props.count}</div>`,\n * });\n */\nexport async function mountComponent<T extends HTMLElement = HTMLElement>(\n tag: string,\n definition: ComponentDefinition<any, any>,\n options?: MountOptions,\n): Promise<Fixture<T>> {\n define(tag, definition);\n\n return mount<T>(tag, options);\n}\n\n/**\n * Register a stub custom element (no-op if already defined).\n *\n * @example\n * mock('child-button', '<slot></slot>');\n */\nexport function mock(tagName: string, template = ''): void {\n if (!customElements.get(tagName)) {\n customElements.define(\n tagName,\n class extends HTMLElement {\n connectedCallback() {\n this.innerHTML = template;\n }\n },\n );\n }\n}\n\n/**\n * Remove all elements mounted via `mount()`.\n * Call in `afterEach` to keep tests isolated.\n *\n * @example\n * afterEach(() => cleanup());\n */\nexport function cleanup(): void {\n for (const el of _mountedElements) el.remove();\n _mountedElements.length = 0;\n _resetRawSanitizer();\n _resetLiveSignals();\n _clearStylesheetCache();\n _resetIdCounter();\n}\n\n/** @internal re-export for within() */\nexport type { QueryScope };\n"],"mappings":"4PAyEA,IAAa,EAAkC,CAAC,EACrC,EAAuB,EAalC,SAAS,EAAU,EAAkB,EAAc,EAAwC,CACrF,IAAU,GAAO,EAAQ,gBAAgB,CAAI,EAC5C,EAAQ,aAAa,EAAM,IAAU,GAAO,GAAK,OAAO,CAAK,CAAC,CACrE,CAEA,IAAM,EAAW,GACR,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,EAG3D,EAAyB,KAAU,IAAyC,CAChF,GAAI,OAAO,OAAW,IAAa,OAAO,EAAO,EAEjD,IAAI,EAAyB,KACvB,EAAW,GAAsB,CACrC,EAAW,EAAQ,EAAM,OAAS,EAAM,OAAO,EAC/C,EAAM,eAAe,CACvB,EACM,EAAwB,GAAiC,CAC7D,EAAW,EAAQ,EAAM,MAAM,EAC/B,EAAM,eAAe,CACvB,EAEA,OAAO,iBAAiB,QAAS,CAAO,EACxC,OAAO,iBAAiB,qBAAsB,CAAoB,EAElE,GAAI,CACF,IAAM,EAAS,MAAM,EAAO,EAE5B,GAAI,EAAU,MAAM,EAEpB,OAAO,CACT,QAAU,CACR,OAAO,oBAAoB,QAAS,CAAO,EAC3C,OAAO,oBAAoB,qBAAsB,CAAoB,CACvE,CACF,EA2BA,eAAsB,EACpB,EACA,EAAwB,CAAC,EACJ,CACrB,GAAM,CAAE,QAAQ,CAAC,EAAG,mBAAkB,YAAY,SAAS,KAAM,OAAM,QAAQ,CAAC,GAAM,EAElF,EACA,EAEA,OAAO,GAAe,SACxB,EAAU,GAEV,EAAU,SAAS,EAAE,EAAqB,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAG,CAAC,IAClF,EAAmB,CACjB,GAAI,GAAoB,CAAC,EACzB,MAAO,CACT,GAGE,GACF,EAAA,OAAO,EAAS,CAAgB,EAGlC,IAAM,EAAU,SAAS,cAAc,CAAO,EAE1C,IAAM,EAAQ,UAAY,GAE1B,OAAO,KAAK,CAAK,CAAC,CAAC,QAAQ,OAAO,OAAO,EAAS,CAAK,EAE3D,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,CAAK,EAAG,EAAU,EAAS,EAAM,CAAK,EAEjF,MAAM,EAAuB,SAAY,CACvC,EAAU,YAAY,CAAO,EAC7B,EAAiB,KAAK,CAAO,EAC7B,MAAM,EAAA,MAAM,CACd,CAAC,EAED,IAAI,EAAa,GAEjB,SAAS,GAAU,CACjB,GAAI,EAAY,OAEhB,EAAa,GACb,EAAQ,OAAO,EAEf,IAAM,EAAI,EAAiB,QAAQ,CAAO,EAEtC,IAAM,IAAI,EAAiB,OAAO,EAAG,CAAC,CAC5C,CAEA,MAAO,CACL,MAAM,IAAI,EAAI,CACZ,MAAM,EAAG,EACT,MAAM,EAAA,MAAM,CACd,EAEA,MAAM,KAAK,EAAM,EAAO,CACtB,EAAU,EAAS,EAAM,CAAK,EAC9B,MAAM,EAAA,MAAM,CACd,EAEA,MAAM,MAAM,EAAQ,CAClB,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,CAAM,EAAG,EAAU,EAAS,EAAM,CAAK,EAClF,MAAM,EAAA,MAAM,CACd,EAEA,UAEA,IAAI,UAAoB,CACtB,OAAO,CACT,EAEA,UAEA,MAAA,EAAA,MAEA,MAAmC,EAA4B,CAC7D,OAAQ,EAAQ,YAAc,EAAA,CAAS,cAAiB,CAAQ,CAClE,EAEA,SAAsC,EAAuB,CAC3D,OAAO,MAAM,MAAM,EAAQ,YAAc,EAAA,CAAS,iBAAoB,CAAQ,CAAC,CACjF,EAEA,iBAA8C,EAAqB,CACjE,OAAO,MAAM,MAAM,EAAQ,YAAc,EAAA,CAAS,iBAAoB,iBAAiB,EAAO,GAAG,CAAC,CACpG,EAEA,eAA4C,EAAc,EAAW,IAAU,CAC7E,OAAO,EAAA,eAAmB,EAAQ,YAAc,EAAqB,EAAM,CAAQ,CACrF,EAEA,cAA2C,EAA0B,CACnE,OAAQ,EAAQ,YAAc,EAAA,CAAS,cAAiB,iBAAiB,EAAO,GAAG,CACrF,EAEA,YAAyC,EAAc,EAAW,IAAe,CAC/E,OAAO,EAAA,YAAgB,EAAQ,YAAc,EAAqB,EAAM,CAAQ,CAClF,EAEA,IAAI,QAA4B,CAC9B,OAAO,EAAQ,UACjB,EAEA,CAAC,OAAO,UAAW,CACjB,EAAQ,CACV,CACF,CACF,CAcA,eAAsB,EACpB,EACA,EACA,EACqB,CAGrB,OAFA,EAAA,OAAO,EAAK,CAAU,EAEf,EAAS,EAAK,CAAO,CAC9B,CAQA,SAAgB,EAAK,EAAiB,EAAW,GAAU,CACpD,eAAe,IAAI,CAAO,GAC7B,eAAe,OACb,EACA,cAAc,WAAY,CACxB,mBAAoB,CAClB,KAAK,UAAY,CACnB,CACF,CACF,CAEJ,CASA,SAAgB,GAAgB,CAC9B,IAAK,IAAM,KAAM,EAAkB,EAAG,OAAO,EAC7C,EAAiB,OAAS,EAC1B,EAAA,mBAAmB,EACnB,EAAA,kBAAkB,EAClB,EAAA,sBAAsB,EACtB,EAAA,gBAAgB,CAClB"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Component mounting utilities for test environments.
3
+ */
4
+ import type { Readable } from '@vielzeug/ripple';
5
+ import { type ComponentDefinition, type SetupContextBag } from '../component-types';
6
+ import { type HTMLResult } from '../types/bindings';
7
+ import { type FlushOptions } from './flush';
8
+ import { type QueryScope } from './query';
9
+ export interface Fixture<T extends HTMLElement = HTMLElement> {
10
+ /** Delegates to `dispose()`. Enables `using` declarations. */
11
+ [Symbol.dispose](): void;
12
+ /** Run a callback then flush — the standard way to trigger and assert a reactive update */
13
+ act(fn: () => unknown): Promise<void>;
14
+ /** Set an attribute (boolean `false` removes it) then flush */
15
+ attr(name: string, value: string | number | boolean): Promise<void>;
16
+ /** Set multiple attributes then flush */
17
+ attrs(record: Record<string, string | number | boolean>): Promise<void>;
18
+ /** Remove the component from the DOM. Idempotent. */
19
+ dispose(): void;
20
+ /** `true` after `dispose()` has been called. */
21
+ readonly disposed: boolean;
22
+ /** The component element */
23
+ element: T;
24
+ /** Wait for all reactive updates and animation frames */
25
+ flush(options?: FlushOptions): Promise<void>;
26
+ /** Query a single element within shadow root */
27
+ query<E extends Element = Element>(selector: string): E | null;
28
+ /** Query all elements within shadow root */
29
+ queryAll<E extends Element = Element>(selector: string): E[];
30
+ /** Query all elements by their `data-testid` attribute */
31
+ queryAllByTestId<E extends Element = Element>(testId: string): E[];
32
+ /** Query all elements whose trimmed text content matches */
33
+ queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];
34
+ /** Query a single element by its `data-testid` attribute */
35
+ queryByTestId<E extends Element = Element>(testId: string): E | null;
36
+ /** Query the first element whose trimmed text content matches */
37
+ queryByText<E extends Element = Element>(text: string, selector?: string): E | null;
38
+ /** The component's shadow root (null for light-DOM components) */
39
+ readonly shadow: ShadowRoot | null;
40
+ }
41
+ export interface MountOptions {
42
+ /** Properties assigned directly onto the element */
43
+ props?: Record<string, unknown>;
44
+ /** HTML attributes to set on the element */
45
+ attrs?: Record<string, string | number | boolean>;
46
+ /** Inner HTML for slot content */
47
+ html?: string;
48
+ /** Parent container (default: document.body) */
49
+ container?: HTMLElement;
50
+ /** Extra component options when passing an inline setup function */
51
+ componentOptions?: Omit<ComponentDefinition<any, any>, 'setup'>;
52
+ }
53
+ type MountProps = {
54
+ readonly [x: string]: Readable<unknown>;
55
+ };
56
+ export type MountSetup = {
57
+ bivarianceHack: (props: MountProps, ctx: SetupContextBag<any>) => HTMLResult | null | Promise<HTMLResult | null>;
58
+ }['bivarianceHack'];
59
+ export declare const _mountedElements: HTMLElement[];
60
+ export declare let _componentTagCounter: number;
61
+ /**
62
+ * Mount a component into the DOM and return a test fixture.
63
+ *
64
+ * Accepts a registered tag name, an inline setup function, or a component
65
+ * options object. Setup functions are auto-registered with generated tag names.
66
+ *
67
+ * @example — inline setup function
68
+ * const { query } = await mount(() => {
69
+ * const count = signal(0);
70
+ * return html`<button @click=${() => count.value++}>${count}</button>`;
71
+ * });
72
+ *
73
+ * @example — registered tag name
74
+ * const { query } = await mount('my-counter');
75
+ */
76
+ export declare function mount<T extends HTMLElement = HTMLElement>(tagOrSetup: string, options?: MountOptions): Promise<Fixture<T>>;
77
+ export declare function mount<T extends HTMLElement = HTMLElement>(tagOrSetup: MountSetup, options?: MountOptions): Promise<Fixture<T>>;
78
+ /**
79
+ * Register and mount a component definition in a single call.
80
+ *
81
+ * Combines `define(tag, definition)` + `mount(tag, options)` — the standard
82
+ * pattern for testing full custom-element lifecycle (props, reconnect, etc.).
83
+ *
84
+ * @example
85
+ * const { query } = await mountComponent('my-counter', {
86
+ * props: { count: prop.number(0) },
87
+ * setup: (props) => html`<div>${props.count}</div>`,
88
+ * });
89
+ */
90
+ export declare function mountComponent<T extends HTMLElement = HTMLElement>(tag: string, definition: ComponentDefinition<any, any>, options?: MountOptions): Promise<Fixture<T>>;
91
+ /**
92
+ * Register a stub custom element (no-op if already defined).
93
+ *
94
+ * @example
95
+ * mock('child-button', '<slot></slot>');
96
+ */
97
+ export declare function mock(tagName: string, template?: string): void;
98
+ /**
99
+ * Remove all elements mounted via `mount()`.
100
+ * Call in `afterEach` to keep tests isolated.
101
+ *
102
+ * @example
103
+ * afterEach(() => cleanup());
104
+ */
105
+ export declare function cleanup(): void;
106
+ export {};
107
+ //# sourceMappingURL=mount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/testing/mount.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{flush as e}from"./flush.js";import"../types/bindings.js";import{_resetLiveSignals as t}from"../directives/live.js";import{_resetRawSanitizer as n}from"../directives/raw.js";import{_clearStylesheetCache as r}from"../utils/css.js";import{define as i}from"../define.js";import{_resetIdCounter as a}from"../utils/id.js";import{queryAllByText as o,queryByText as s}from"./query.js";var c=[],l=0;function u(e,t,n){n===!1?e.removeAttribute(t):e.setAttribute(t,n===!0?``:String(n))}var d=e=>e instanceof Error?e:Error(String(e)),f=async e=>{if(typeof window>`u`)return e();let t=null,n=e=>{t=d(e.error??e.message),e.preventDefault()},r=e=>{t=d(e.reason),e.preventDefault()};window.addEventListener(`error`,n),window.addEventListener(`unhandledrejection`,r);try{let n=await e();if(t)throw t;return n}finally{window.removeEventListener(`error`,n),window.removeEventListener(`unhandledrejection`,r)}};async function p(t,n={}){let{attrs:r={},componentOptions:a,container:d=document.body,html:p,props:m={}}=n,h,g;typeof t==`string`?h=t:(h=`trial-${++l}-${Math.random().toString(36).slice(2,7)}`,g={...a??{},setup:t}),g&&i(h,g);let _=document.createElement(h);p&&(_.innerHTML=p),Object.keys(m).length&&Object.assign(_,m);for(let[e,t]of Object.entries(r))u(_,e,t);await f(async()=>{d.appendChild(_),c.push(_),await e()});let v=!1;function y(){if(v)return;v=!0,_.remove();let e=c.indexOf(_);e!==-1&&c.splice(e,1)}return{async act(t){await t(),await e()},async attr(t,n){u(_,t,n),await e()},async attrs(t){for(let[e,n]of Object.entries(t))u(_,e,n);await e()},dispose:y,get disposed(){return v},element:_,flush:e,query(e){return(_.shadowRoot??_).querySelector(e)},queryAll(e){return Array.from((_.shadowRoot??_).querySelectorAll(e))},queryAllByTestId(e){return Array.from((_.shadowRoot??_).querySelectorAll(`[data-testid="${e}"]`))},queryAllByText(e,t=`*`){return o(_.shadowRoot??_,e,t)},queryByTestId(e){return(_.shadowRoot??_).querySelector(`[data-testid="${e}"]`)},queryByText(e,t=`*`){return s(_.shadowRoot??_,e,t)},get shadow(){return _.shadowRoot},[Symbol.dispose](){y()}}}async function m(e,t,n){return i(e,t),p(e,n)}function h(e,t=``){customElements.get(e)||customElements.define(e,class extends HTMLElement{connectedCallback(){this.innerHTML=t}})}function g(){for(let e of c)e.remove();c.length=0,n(),t(),r(),a()}export{l as _componentTagCounter,c as _mountedElements,g as cleanup,h as mock,p as mount,m as mountComponent};
2
+ //# sourceMappingURL=mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.js","names":[],"sources":["../../src/testing/mount.ts"],"sourcesContent":["/**\n * Component mounting utilities for test environments.\n */\n\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { type ComponentDefinition, type SetupContextBag } from '../component-types';\nimport { define } from '../define';\nimport { _resetLiveSignals } from '../directives/live';\nimport { _resetRawSanitizer } from '../directives/raw';\nimport { type HTMLResult } from '../types/bindings';\nimport { _clearStylesheetCache } from '../utils/css';\nimport { _resetIdCounter } from '../utils/id';\nimport { flush, type FlushOptions } from './flush';\nimport { queryAllByText, queryByText, type QueryScope } from './query';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface Fixture<T extends HTMLElement = HTMLElement> {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose](): void;\n /** Run a callback then flush — the standard way to trigger and assert a reactive update */\n act(fn: () => unknown): Promise<void>;\n /** Set an attribute (boolean `false` removes it) then flush */\n attr(name: string, value: string | number | boolean): Promise<void>;\n /** Set multiple attributes then flush */\n attrs(record: Record<string, string | number | boolean>): Promise<void>;\n /** Remove the component from the DOM. Idempotent. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** The component element */\n element: T;\n /** Wait for all reactive updates and animation frames */\n flush(options?: FlushOptions): Promise<void>;\n /** Query a single element within shadow root */\n query<E extends Element = Element>(selector: string): E | null;\n /** Query all elements within shadow root */\n queryAll<E extends Element = Element>(selector: string): E[];\n /** Query all elements by their `data-testid` attribute */\n queryAllByTestId<E extends Element = Element>(testId: string): E[];\n /** Query all elements whose trimmed text content matches */\n queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];\n /** Query a single element by its `data-testid` attribute */\n queryByTestId<E extends Element = Element>(testId: string): E | null;\n /** Query the first element whose trimmed text content matches */\n queryByText<E extends Element = Element>(text: string, selector?: string): E | null;\n /** The component's shadow root (null for light-DOM components) */\n readonly shadow: ShadowRoot | null;\n}\n\nexport interface MountOptions {\n /** Properties assigned directly onto the element */\n props?: Record<string, unknown>;\n /** HTML attributes to set on the element */\n attrs?: Record<string, string | number | boolean>;\n /** Inner HTML for slot content */\n html?: string;\n /** Parent container (default: document.body) */\n container?: HTMLElement;\n /** Extra component options when passing an inline setup function */\n componentOptions?: Omit<ComponentDefinition<any, any>, 'setup'>;\n}\n\ntype MountProps = { readonly [x: string]: Readable<unknown> };\n\n// Bivariant callback type keeps inline test callbacks ergonomic across varying setup context specializations.\nexport type MountSetup = {\n bivarianceHack: (props: MountProps, ctx: SetupContextBag<any>) => HTMLResult | null | Promise<HTMLResult | null>;\n}['bivarianceHack'];\n\n// ─── Test environment state ───────────────────────────────────────────────────\n\nexport const _mountedElements: HTMLElement[] = [];\nexport let _componentTagCounter = 0;\n\n/**\n * Resets global test counters used for deterministic IDs/markers.\n * @internal\n */\nexport const _resetCounters = (): void => {\n _resetIdCounter();\n _componentTagCounter = 0;\n};\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction applyAttr(element: Element, name: string, value: string | number | boolean): void {\n if (value === false) element.removeAttribute(name);\n else element.setAttribute(name, value === true ? '' : String(value));\n}\n\nconst toError = (value: unknown): Error => {\n return value instanceof Error ? value : new Error(String(value));\n};\n\nconst withWindowErrorCapture = async <T>(action: () => Promise<T>): Promise<T> => {\n if (typeof window === 'undefined') return action();\n\n let captured: Error | null = null;\n const onError = (event: ErrorEvent) => {\n captured = toError(event.error ?? event.message);\n event.preventDefault();\n };\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n captured = toError(event.reason);\n event.preventDefault();\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n try {\n const result = await action();\n\n if (captured) throw captured;\n\n return result;\n } finally {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n }\n};\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Mount a component into the DOM and return a test fixture.\n *\n * Accepts a registered tag name, an inline setup function, or a component\n * options object. Setup functions are auto-registered with generated tag names.\n *\n * @example — inline setup function\n * const { query } = await mount(() => {\n * const count = signal(0);\n * return html`<button @click=${() => count.value++}>${count}</button>`;\n * });\n *\n * @example — registered tag name\n * const { query } = await mount('my-counter');\n */\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: string,\n options?: MountOptions,\n): Promise<Fixture<T>>;\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: MountSetup,\n options?: MountOptions,\n): Promise<Fixture<T>>;\nexport async function mount<T extends HTMLElement = HTMLElement>(\n tagOrSetup: string | MountSetup,\n options: MountOptions = {},\n): Promise<Fixture<T>> {\n const { attrs = {}, componentOptions, container = document.body, html, props = {} } = options;\n\n let tagName: string;\n let inlineDefinition: ComponentDefinition<any, any> | undefined;\n\n if (typeof tagOrSetup === 'string') {\n tagName = tagOrSetup;\n } else {\n tagName = `trial-${++_componentTagCounter}-${Math.random().toString(36).slice(2, 7)}`;\n inlineDefinition = {\n ...(componentOptions ?? {}),\n setup: tagOrSetup as ComponentDefinition<any, any>['setup'],\n };\n }\n\n if (inlineDefinition) {\n define(tagName, inlineDefinition);\n }\n\n const element = document.createElement(tagName) as T;\n\n if (html) element.innerHTML = html;\n\n if (Object.keys(props).length) Object.assign(element, props);\n\n for (const [name, value] of Object.entries(attrs)) applyAttr(element, name, value);\n\n await withWindowErrorCapture(async () => {\n container.appendChild(element);\n _mountedElements.push(element);\n await flush();\n });\n\n let isDisposed = false;\n\n function dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n element.remove();\n\n const i = _mountedElements.indexOf(element);\n\n if (i !== -1) _mountedElements.splice(i, 1);\n }\n\n return {\n async act(fn) {\n await fn();\n await flush();\n },\n\n async attr(name, value) {\n applyAttr(element, name, value);\n await flush();\n },\n\n async attrs(record) {\n for (const [name, value] of Object.entries(record)) applyAttr(element, name, value);\n await flush();\n },\n\n dispose,\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n element,\n\n flush,\n\n query<E extends Element = Element>(selector: string): E | null {\n return (element.shadowRoot ?? element).querySelector<E>(selector);\n },\n\n queryAll<E extends Element = Element>(selector: string): E[] {\n return Array.from((element.shadowRoot ?? element).querySelectorAll<E>(selector));\n },\n\n queryAllByTestId<E extends Element = Element>(testId: string): E[] {\n return Array.from((element.shadowRoot ?? element).querySelectorAll<E>(`[data-testid=\"${testId}\"]`));\n },\n\n queryAllByText<E extends Element = Element>(text: string, selector = '*'): E[] {\n return queryAllByText<E>((element.shadowRoot ?? element) as Element, text, selector);\n },\n\n queryByTestId<E extends Element = Element>(testId: string): E | null {\n return (element.shadowRoot ?? element).querySelector<E>(`[data-testid=\"${testId}\"]`);\n },\n\n queryByText<E extends Element = Element>(text: string, selector = '*'): E | null {\n return queryByText<E>((element.shadowRoot ?? element) as Element, text, selector);\n },\n\n get shadow(): ShadowRoot | null {\n return element.shadowRoot;\n },\n\n [Symbol.dispose]() {\n dispose();\n },\n };\n}\n\n/**\n * Register and mount a component definition in a single call.\n *\n * Combines `define(tag, definition)` + `mount(tag, options)` — the standard\n * pattern for testing full custom-element lifecycle (props, reconnect, etc.).\n *\n * @example\n * const { query } = await mountComponent('my-counter', {\n * props: { count: prop.number(0) },\n * setup: (props) => html`<div>${props.count}</div>`,\n * });\n */\nexport async function mountComponent<T extends HTMLElement = HTMLElement>(\n tag: string,\n definition: ComponentDefinition<any, any>,\n options?: MountOptions,\n): Promise<Fixture<T>> {\n define(tag, definition);\n\n return mount<T>(tag, options);\n}\n\n/**\n * Register a stub custom element (no-op if already defined).\n *\n * @example\n * mock('child-button', '<slot></slot>');\n */\nexport function mock(tagName: string, template = ''): void {\n if (!customElements.get(tagName)) {\n customElements.define(\n tagName,\n class extends HTMLElement {\n connectedCallback() {\n this.innerHTML = template;\n }\n },\n );\n }\n}\n\n/**\n * Remove all elements mounted via `mount()`.\n * Call in `afterEach` to keep tests isolated.\n *\n * @example\n * afterEach(() => cleanup());\n */\nexport function cleanup(): void {\n for (const el of _mountedElements) el.remove();\n _mountedElements.length = 0;\n _resetRawSanitizer();\n _resetLiveSignals();\n _clearStylesheetCache();\n _resetIdCounter();\n}\n\n/** @internal re-export for within() */\nexport type { QueryScope };\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ function e(e,t,n){for(let r of e.querySelectorAll(n))if(r.textContent?.trim()===t)return r;return null}function t(e,t,n){return Array.from(e.querySelectorAll(n)).filter(e=>e.textContent?.trim()===t)}function n(n){return{query:e=>n.querySelector(e),queryAll:e=>Array.from(n.querySelectorAll(e)),queryAllByTestId:e=>Array.from(n.querySelectorAll(`[data-testid="${e}"]`)),queryAllByText:(e,r=`*`)=>t(n,e,r),queryByTestId:e=>n.querySelector(`[data-testid="${e}"]`),queryByText:(t,r=`*`)=>e(n,t,r)}}exports.queryAllByText=t,exports.queryByText=e,exports.within=n;
2
+ //# sourceMappingURL=query.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.cjs","names":[],"sources":["../../src/testing/query.ts"],"sourcesContent":["/**\n * DOM query helpers for test environments.\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Scoped query helpers for any DOM element — see {@link within} */\nexport interface QueryScope {\n query<E extends Element = Element>(selector: string): E | null;\n queryAll<E extends Element = Element>(selector: string): E[];\n queryByText<E extends Element = Element>(text: string, selector?: string): E | null;\n queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];\n queryByTestId<E extends Element = Element>(testId: string): E | null;\n queryAllByTestId<E extends Element = Element>(testId: string): E[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nexport function queryByText<E extends Element = Element>(\n root: Element | ShadowRoot,\n text: string,\n selector: string,\n): E | null {\n for (const el of root.querySelectorAll<E>(selector)) {\n if (el.textContent?.trim() === text) return el;\n }\n\n return null;\n}\n\nexport function queryAllByText<E extends Element = Element>(\n root: Element | ShadowRoot,\n text: string,\n selector: string,\n): E[] {\n return Array.from(root.querySelectorAll<E>(selector)).filter((el) => el.textContent?.trim() === text);\n}\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Create query helpers scoped to any element — useful for slotted/light DOM content.\n *\n * @example\n * const panel = fixture.query('.panel')!;\n * const { query } = within(panel);\n * expect(query('.title')?.textContent).toBe('Hello');\n */\nexport function within(element: Element): QueryScope {\n return {\n query: <E extends Element = Element>(selector: string) => element.querySelector<E>(selector),\n queryAll: <E extends Element = Element>(selector: string) => Array.from(element.querySelectorAll<E>(selector)),\n queryAllByTestId: <E extends Element = Element>(testId: string) =>\n Array.from(element.querySelectorAll<E>(`[data-testid=\"${testId}\"]`)),\n queryAllByText: <E extends Element = Element>(text: string, selector = '*') =>\n queryAllByText<E>(element, text, selector),\n queryByTestId: <E extends Element = Element>(testId: string) =>\n element.querySelector<E>(`[data-testid=\"${testId}\"]`),\n queryByText: <E extends Element = Element>(text: string, selector = '*') => queryByText<E>(element, text, selector),\n };\n}\n"],"mappings":"AAkBA,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAK,IAAM,KAAM,EAAK,iBAAoB,CAAQ,EAChD,GAAI,EAAG,aAAa,KAAK,IAAM,EAAM,OAAO,EAG9C,OAAO,IACT,CAEA,SAAgB,EACd,EACA,EACA,EACK,CACL,OAAO,MAAM,KAAK,EAAK,iBAAoB,CAAQ,CAAC,CAAC,CAAC,OAAQ,GAAO,EAAG,aAAa,KAAK,IAAM,CAAI,CACtG,CAYA,SAAgB,EAAO,EAA8B,CACnD,MAAO,CACL,MAAqC,GAAqB,EAAQ,cAAiB,CAAQ,EAC3F,SAAwC,GAAqB,MAAM,KAAK,EAAQ,iBAAoB,CAAQ,CAAC,EAC7G,iBAAgD,GAC9C,MAAM,KAAK,EAAQ,iBAAoB,iBAAiB,EAAO,GAAG,CAAC,EACrE,gBAA8C,EAAc,EAAW,MACrE,EAAkB,EAAS,EAAM,CAAQ,EAC3C,cAA6C,GAC3C,EAAQ,cAAiB,iBAAiB,EAAO,GAAG,EACtD,aAA2C,EAAc,EAAW,MAAQ,EAAe,EAAS,EAAM,CAAQ,CACpH,CACF"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * DOM query helpers for test environments.
3
+ */
4
+ /** Scoped query helpers for any DOM element — see {@link within} */
5
+ export interface QueryScope {
6
+ query<E extends Element = Element>(selector: string): E | null;
7
+ queryAll<E extends Element = Element>(selector: string): E[];
8
+ queryByText<E extends Element = Element>(text: string, selector?: string): E | null;
9
+ queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];
10
+ queryByTestId<E extends Element = Element>(testId: string): E | null;
11
+ queryAllByTestId<E extends Element = Element>(testId: string): E[];
12
+ }
13
+ export declare function queryByText<E extends Element = Element>(root: Element | ShadowRoot, text: string, selector: string): E | null;
14
+ export declare function queryAllByText<E extends Element = Element>(root: Element | ShadowRoot, text: string, selector: string): E[];
15
+ /**
16
+ * Create query helpers scoped to any element — useful for slotted/light DOM content.
17
+ *
18
+ * @example
19
+ * const panel = fixture.query('.panel')!;
20
+ * const { query } = within(panel);
21
+ * expect(query('.title')?.textContent).toBe('Hello');
22
+ */
23
+ export declare function within(element: Element): QueryScope;
24
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/testing/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC;IAC/D,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IAC7D,WAAW,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC;IACpF,cAAc,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IAClF,aAAa,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC;IACrE,gBAAgB,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;CACpE;AAID,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EACrD,IAAI,EAAE,OAAO,GAAG,UAAU,EAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,CAAC,GAAG,IAAI,CAMV;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EACxD,IAAI,EAAE,OAAO,GAAG,UAAU,EAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,CAAC,EAAE,CAEL;AAID;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAYnD"}
@@ -0,0 +1,2 @@
1
+ function e(e,t,n){for(let r of e.querySelectorAll(n))if(r.textContent?.trim()===t)return r;return null}function t(e,t,n){return Array.from(e.querySelectorAll(n)).filter(e=>e.textContent?.trim()===t)}function n(n){return{query:e=>n.querySelector(e),queryAll:e=>Array.from(n.querySelectorAll(e)),queryAllByTestId:e=>Array.from(n.querySelectorAll(`[data-testid="${e}"]`)),queryAllByText:(e,r=`*`)=>t(n,e,r),queryByTestId:e=>n.querySelector(`[data-testid="${e}"]`),queryByText:(t,r=`*`)=>e(n,t,r)}}export{t as queryAllByText,e as queryByText,n as within};
2
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","names":[],"sources":["../../src/testing/query.ts"],"sourcesContent":["/**\n * DOM query helpers for test environments.\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Scoped query helpers for any DOM element — see {@link within} */\nexport interface QueryScope {\n query<E extends Element = Element>(selector: string): E | null;\n queryAll<E extends Element = Element>(selector: string): E[];\n queryByText<E extends Element = Element>(text: string, selector?: string): E | null;\n queryAllByText<E extends Element = Element>(text: string, selector?: string): E[];\n queryByTestId<E extends Element = Element>(testId: string): E | null;\n queryAllByTestId<E extends Element = Element>(testId: string): E[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nexport function queryByText<E extends Element = Element>(\n root: Element | ShadowRoot,\n text: string,\n selector: string,\n): E | null {\n for (const el of root.querySelectorAll<E>(selector)) {\n if (el.textContent?.trim() === text) return el;\n }\n\n return null;\n}\n\nexport function queryAllByText<E extends Element = Element>(\n root: Element | ShadowRoot,\n text: string,\n selector: string,\n): E[] {\n return Array.from(root.querySelectorAll<E>(selector)).filter((el) => el.textContent?.trim() === text);\n}\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Create query helpers scoped to any element — useful for slotted/light DOM content.\n *\n * @example\n * const panel = fixture.query('.panel')!;\n * const { query } = within(panel);\n * expect(query('.title')?.textContent).toBe('Hello');\n */\nexport function within(element: Element): QueryScope {\n return {\n query: <E extends Element = Element>(selector: string) => element.querySelector<E>(selector),\n queryAll: <E extends Element = Element>(selector: string) => Array.from(element.querySelectorAll<E>(selector)),\n queryAllByTestId: <E extends Element = Element>(testId: string) =>\n Array.from(element.querySelectorAll<E>(`[data-testid=\"${testId}\"]`)),\n queryAllByText: <E extends Element = Element>(text: string, selector = '*') =>\n queryAllByText<E>(element, text, selector),\n queryByTestId: <E extends Element = Element>(testId: string) =>\n element.querySelector<E>(`[data-testid=\"${testId}\"]`),\n queryByText: <E extends Element = Element>(text: string, selector = '*') => queryByText<E>(element, text, selector),\n };\n}\n"],"mappings":"AAkBA,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAK,IAAM,KAAM,EAAK,iBAAoB,CAAQ,EAChD,GAAI,EAAG,aAAa,KAAK,IAAM,EAAM,OAAO,EAG9C,OAAO,IACT,CAEA,SAAgB,EACd,EACA,EACA,EACK,CACL,OAAO,MAAM,KAAK,EAAK,iBAAoB,CAAQ,CAAC,CAAC,CAAC,OAAQ,GAAO,EAAG,aAAa,KAAK,IAAM,CAAI,CACtG,CAYA,SAAgB,EAAO,EAA8B,CACnD,MAAO,CACL,MAAqC,GAAqB,EAAQ,cAAiB,CAAQ,EAC3F,SAAwC,GAAqB,MAAM,KAAK,EAAQ,iBAAoB,CAAQ,CAAC,EAC7G,iBAAgD,GAC9C,MAAM,KAAK,EAAQ,iBAAoB,iBAAiB,EAAO,GAAG,CAAC,EACrE,gBAA8C,EAAc,EAAW,MACrE,EAAkB,EAAS,EAAM,CAAQ,EAC3C,cAA6C,GAC3C,EAAQ,cAAiB,iBAAiB,EAAO,GAAG,EACtD,aAA2C,EAAc,EAAW,MAAQ,EAAe,EAAS,EAAM,CAAQ,CACpH,CACF"}
@@ -0,0 +1,2 @@
1
+ const e=require("./flush.cjs"),t=require("../runtime.cjs"),n=require("../context-bag.cjs"),r=require("../props.cjs");let i=require("@vielzeug/ripple");async function a(a,o){let s=typeof a!=`function`,c=s?a:void 0,l=s?o:a,u=(0,i.scope)(),d=document.createElement(`div`);document.body.appendChild(d);let f=[],p={element:d,mountCallbacks:f},m;try{u.run(()=>{t.runWithContext(p,()=>{let e=n.createContextBag(d),t=c?r.createProps(d,c):{};m=l(t,e)})});for(let e of f)try{u.run(()=>{t.runWithContext(p,()=>{let t=e();typeof t==`function`&&(0,i.onCleanup)(t)})})}catch{}}catch(e){throw u.dispose(),d.remove(),e}await e.flush();let h=!1;function g(){h||(h=!0,u.dispose(),d.remove())}return{dispose:g,get disposed(){return h},async flush(){await e.flush()},result:m,[Symbol.dispose](){g()}}}exports.renderHook=a;
2
+ //# sourceMappingURL=render-hook.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-hook.cjs","names":[],"sources":["../../src/testing/render-hook.ts"],"sourcesContent":["/**\n * renderHook — test composable hooks (lifecycle, reactive state, etc.) in isolation\n * without rendering a full component template.\n */\n\nimport { onCleanup as _onCleanup, scope as _scope } from '@vielzeug/ripple';\n\nimport type { SetupContextBag } from '../component-types';\n\nimport { createContextBag } from '../context-bag';\nimport { createProps, type InferProps, type PropInputDefs } from '../props';\nimport { runWithContext } from '../runtime';\nimport { flush } from './flush';\n\nexport interface HookFixture<T> {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose](): void;\n /** Teardown the hook (runs cleanups). Idempotent. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Flush pending reactive updates */\n flush(): Promise<void>;\n /** The value returned by the setup function */\n result: T;\n}\n\n/**\n * Run a setup function in a component-like context and return the result.\n * The callback receives the same `SetupContextBag` as a real `setup()` function.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook((_props, ctx) => {\n * const count = signal(0);\n * ctx.onMounted(() => { count.value = 1; });\n * return count;\n * });\n * expect(result.value).toBe(1);\n * ```\n *\n * @example With props\n * ```ts\n * const { result } = await renderHook(\n * { label: prop.string('hello') },\n * (props) => props.label,\n * );\n * expect(result.value).toBe('hello');\n * ```\n */\nexport async function renderHook<T>(\n setup: (_props: Record<never, never>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>, ctx: SetupContextBag) => T) | D,\n maybeSetup?: (props: InferProps<D>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>> {\n const hasPropDefs = typeof setupOrDefs !== 'function';\n const propDefs = hasPropDefs ? (setupOrDefs as D) : undefined;\n const setup = hasPropDefs ? maybeSetup! : (setupOrDefs as (_props: Record<never, never>, ctx: SetupContextBag) => T);\n\n const hostScope = _scope();\n // Minimal host element so getCurrentElement() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const ctx = { element: hostEl, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const contextBag = createContextBag(hostEl);\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>, contextBag);\n });\n });\n\n // Run mount callbacks (simulates connectedCallback → queueMicrotask)\n for (const cb of mountCallbacks) {\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const cleanup = cb();\n\n if (typeof cleanup === 'function') _onCleanup(cleanup);\n });\n });\n } catch {\n /* test will surface the error via result */\n }\n }\n } catch (err) {\n hostScope.dispose();\n hostEl.remove();\n throw err;\n }\n\n await flush();\n\n let isDisposed = false;\n\n function dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n hostScope.dispose();\n hostEl.remove();\n }\n\n return {\n dispose,\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n async flush() {\n await flush();\n },\n\n result,\n\n [Symbol.dispose]() {\n dispose();\n },\n };\n}\n"],"mappings":"uJAyDA,eAAsB,EACpB,EACA,EACyB,CACzB,IAAM,EAAc,OAAO,GAAgB,WACrC,EAAW,EAAe,EAAoB,IAAA,GAC9C,EAAQ,EAAc,EAAe,EAErC,GAAA,EAAA,EAAA,MAAA,CAAmB,EAEnB,EAAS,SAAS,cAAc,KAAK,EAE3C,SAAS,KAAK,YAAY,CAAM,EAEhC,IAAM,EAAmD,CAAC,EACpD,EAAM,CAAE,QAAS,EAAQ,gBAAe,EAE1C,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAA,eAAe,MAAW,CACxB,IAAM,EAAa,EAAA,iBAAiB,CAAM,EACpC,EAAQ,EAAW,EAAA,YAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,EAAwB,CAAU,CACnD,CAAC,CACH,CAAC,EAGD,IAAK,IAAM,KAAM,EACf,GAAI,CACF,EAAU,QAAU,CAClB,EAAA,eAAe,MAAW,CACxB,IAAM,EAAU,EAAG,EAEf,OAAO,GAAY,aAAY,EAAA,EAAA,UAAA,CAAW,CAAO,CACvD,CAAC,CACH,CAAC,CACH,MAAQ,CAER,CAEJ,OAAS,EAAK,CAGZ,MAFA,EAAU,QAAQ,EAClB,EAAO,OAAO,EACR,CACR,CAEA,MAAM,EAAA,MAAM,EAEZ,IAAI,EAAa,GAEjB,SAAS,GAAU,CACb,IAEJ,EAAa,GACb,EAAU,QAAQ,EAClB,EAAO,OAAO,EAChB,CAEA,MAAO,CACL,UAEA,IAAI,UAAoB,CACtB,OAAO,CACT,EAEA,MAAM,OAAQ,CACZ,MAAM,EAAA,MAAM,CACd,EAEA,SAEA,CAAC,OAAO,UAAW,CACjB,EAAQ,CACV,CACF,CACF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * renderHook — test composable hooks (lifecycle, reactive state, etc.) in isolation
3
+ * without rendering a full component template.
4
+ */
5
+ import type { SetupContextBag } from '../component-types';
6
+ import { type InferProps, type PropInputDefs } from '../props';
7
+ export interface HookFixture<T> {
8
+ /** Delegates to `dispose()`. Enables `using` declarations. */
9
+ [Symbol.dispose](): void;
10
+ /** Teardown the hook (runs cleanups). Idempotent. */
11
+ dispose(): void;
12
+ /** `true` after `dispose()` has been called. */
13
+ readonly disposed: boolean;
14
+ /** Flush pending reactive updates */
15
+ flush(): Promise<void>;
16
+ /** The value returned by the setup function */
17
+ result: T;
18
+ }
19
+ /**
20
+ * Run a setup function in a component-like context and return the result.
21
+ * The callback receives the same `SetupContextBag` as a real `setup()` function.
22
+ *
23
+ * @example No props
24
+ * ```ts
25
+ * const { result, flush } = await renderHook((_props, ctx) => {
26
+ * const count = signal(0);
27
+ * ctx.onMounted(() => { count.value = 1; });
28
+ * return count;
29
+ * });
30
+ * expect(result.value).toBe(1);
31
+ * ```
32
+ *
33
+ * @example With props
34
+ * ```ts
35
+ * const { result } = await renderHook(
36
+ * { label: prop.string('hello') },
37
+ * (props) => props.label,
38
+ * );
39
+ * expect(result.value).toBe('hello');
40
+ * ```
41
+ */
42
+ export declare function renderHook<T>(setup: (_props: Record<never, never>, ctx: SetupContextBag) => T): Promise<HookFixture<T>>;
43
+ export declare function renderHook<D extends PropInputDefs, T>(propDefs: D, setup: (props: InferProps<D>, ctx: SetupContextBag) => T): Promise<HookFixture<T>>;
44
+ //# sourceMappingURL=render-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-hook.d.ts","sourceRoot":"","sources":["../../src/testing/render-hook.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAI5E,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,8DAA8D;IAC9D,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,qDAAqD;IACrD,OAAO,IAAI,IAAI,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,qCAAqC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,+CAA+C;IAC/C,MAAM,EAAE,CAAC,CAAC;CACX;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,eAAe,KAAK,CAAC,GAC/D,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,wBAAsB,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,EACzD,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,KAAK,CAAC,GACvD,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import{flush as e}from"./flush.js";import{runWithContext as t}from"../runtime.js";import{createContextBag as n}from"../context-bag.js";import{createProps as r}from"../props.js";import{onCleanup as i,scope as a}from"@vielzeug/ripple";async function o(o,s){let c=typeof o!=`function`,l=c?o:void 0,u=c?s:o,d=a(),f=document.createElement(`div`);document.body.appendChild(f);let p=[],m={element:f,mountCallbacks:p},h;try{d.run(()=>{t(m,()=>{let e=n(f),t=l?r(f,l):{};h=u(t,e)})});for(let e of p)try{d.run(()=>{t(m,()=>{let t=e();typeof t==`function`&&i(t)})})}catch{}}catch(e){throw d.dispose(),f.remove(),e}await e();let g=!1;function _(){g||(g=!0,d.dispose(),f.remove())}return{dispose:_,get disposed(){return g},async flush(){await e()},result:h,[Symbol.dispose](){_()}}}export{o as renderHook};
2
+ //# sourceMappingURL=render-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-hook.js","names":[],"sources":["../../src/testing/render-hook.ts"],"sourcesContent":["/**\n * renderHook — test composable hooks (lifecycle, reactive state, etc.) in isolation\n * without rendering a full component template.\n */\n\nimport { onCleanup as _onCleanup, scope as _scope } from '@vielzeug/ripple';\n\nimport type { SetupContextBag } from '../component-types';\n\nimport { createContextBag } from '../context-bag';\nimport { createProps, type InferProps, type PropInputDefs } from '../props';\nimport { runWithContext } from '../runtime';\nimport { flush } from './flush';\n\nexport interface HookFixture<T> {\n /** Delegates to `dispose()`. Enables `using` declarations. */\n [Symbol.dispose](): void;\n /** Teardown the hook (runs cleanups). Idempotent. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Flush pending reactive updates */\n flush(): Promise<void>;\n /** The value returned by the setup function */\n result: T;\n}\n\n/**\n * Run a setup function in a component-like context and return the result.\n * The callback receives the same `SetupContextBag` as a real `setup()` function.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook((_props, ctx) => {\n * const count = signal(0);\n * ctx.onMounted(() => { count.value = 1; });\n * return count;\n * });\n * expect(result.value).toBe(1);\n * ```\n *\n * @example With props\n * ```ts\n * const { result } = await renderHook(\n * { label: prop.string('hello') },\n * (props) => props.label,\n * );\n * expect(result.value).toBe('hello');\n * ```\n */\nexport async function renderHook<T>(\n setup: (_props: Record<never, never>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>, ctx: SetupContextBag) => T) | D,\n maybeSetup?: (props: InferProps<D>, ctx: SetupContextBag) => T,\n): Promise<HookFixture<T>> {\n const hasPropDefs = typeof setupOrDefs !== 'function';\n const propDefs = hasPropDefs ? (setupOrDefs as D) : undefined;\n const setup = hasPropDefs ? maybeSetup! : (setupOrDefs as (_props: Record<never, never>, ctx: SetupContextBag) => T);\n\n const hostScope = _scope();\n // Minimal host element so getCurrentElement() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const ctx = { element: hostEl, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const contextBag = createContextBag(hostEl);\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>, contextBag);\n });\n });\n\n // Run mount callbacks (simulates connectedCallback → queueMicrotask)\n for (const cb of mountCallbacks) {\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const cleanup = cb();\n\n if (typeof cleanup === 'function') _onCleanup(cleanup);\n });\n });\n } catch {\n /* test will surface the error via result */\n }\n }\n } catch (err) {\n hostScope.dispose();\n hostEl.remove();\n throw err;\n }\n\n await flush();\n\n let isDisposed = false;\n\n function dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n hostScope.dispose();\n hostEl.remove();\n }\n\n return {\n dispose,\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n async flush() {\n await flush();\n },\n\n result,\n\n [Symbol.dispose]() {\n dispose();\n },\n };\n}\n"],"mappings":"yOAyDA,eAAsB,EACpB,EACA,EACyB,CACzB,IAAM,EAAc,OAAO,GAAgB,WACrC,EAAW,EAAe,EAAoB,IAAA,GAC9C,EAAQ,EAAc,EAAe,EAErC,EAAY,EAAO,EAEnB,EAAS,SAAS,cAAc,KAAK,EAE3C,SAAS,KAAK,YAAY,CAAM,EAEhC,IAAM,EAAmD,CAAC,EACpD,EAAM,CAAE,QAAS,EAAQ,gBAAe,EAE1C,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAe,MAAW,CACxB,IAAM,EAAa,EAAiB,CAAM,EACpC,EAAQ,EAAW,EAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,EAAwB,CAAU,CACnD,CAAC,CACH,CAAC,EAGD,IAAK,IAAM,KAAM,EACf,GAAI,CACF,EAAU,QAAU,CAClB,EAAe,MAAW,CACxB,IAAM,EAAU,EAAG,EAEf,OAAO,GAAY,YAAY,EAAW,CAAO,CACvD,CAAC,CACH,CAAC,CACH,MAAQ,CAER,CAEJ,OAAS,EAAK,CAGZ,MAFA,EAAU,QAAQ,EAClB,EAAO,OAAO,EACR,CACR,CAEA,MAAM,EAAM,EAEZ,IAAI,EAAa,GAEjB,SAAS,GAAU,CACb,IAEJ,EAAa,GACb,EAAU,QAAQ,EAClB,EAAO,OAAO,EAChB,CAEA,MAAO,CACL,UAEA,IAAI,UAAoB,CACtB,OAAO,CACT,EAEA,MAAM,OAAQ,CACZ,MAAM,EAAM,CACd,EAEA,SAEA,CAAC,OAAO,UAAW,CACjB,EAAQ,CACV,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ const e=require("./flush.cjs"),t=require("./query.cjs"),n=require("./mount.cjs"),r=require("./events.cjs"),i=require("./interactions.cjs"),a=require("./wait.cjs"),o=require("./render-hook.cjs");function s(e){e(n.cleanup)}exports.FLUSH_DEEP=e.FLUSH_DEEP,exports.cleanup=n.cleanup,exports.createPointerEvent=r.createPointerEvent,exports.fire=r.fire,exports.flush=e.flush,exports.install=s,exports.mock=n.mock,exports.mount=n.mount,exports.mountComponent=n.mountComponent,exports.renderHook=o.renderHook,exports.user=i.user,exports.waitFor=a.waitFor,exports.waitForEvent=a.waitForEvent,exports.within=t.within;
2
+ //# sourceMappingURL=testing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.cjs","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["/**\n * Testing utilities for Ore components\n *\n * ⚠️ Requires DOM environment (browser / jsdom / happy-dom)\n *\n * This barrel re-exports the full testing API for convenience.\n * For tree-shaking, import directly from the focused sub-modules.\n */\n\nimport { cleanup } from './mount';\n\nexport { fire, createPointerEvent } from './events';\nexport { FLUSH_DEEP, flush, type FlushOptions } from './flush';\nexport { user } from './interactions';\nexport { cleanup, mock, mount, mountComponent, type Fixture, type MountOptions, type MountSetup } from './mount';\nexport { within, type QueryScope } from './query';\nexport { waitFor, waitForEvent, type WaitOptions } from './wait';\nexport { renderHook, type HookFixture } from './render-hook';\n\n/**\n * Register auto-cleanup after each test. Call once in your test setup file.\n *\n * @example\n * // vitest.setup.ts\n * import { afterEach } from 'vitest';\n * import { install } from '@vielzeug/ore/testing';\n * install(afterEach);\n */\nexport function install(afterEachHook: (fn: () => void) => void): void {\n afterEachHook(cleanup);\n}\n"],"mappings":"kMA4BA,SAAgB,EAAQ,EAA+C,CACrE,EAAc,EAAA,OAAO,CACvB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Testing utilities for Ore components
3
+ *
4
+ * ⚠️ Requires DOM environment (browser / jsdom / happy-dom)
5
+ *
6
+ * This barrel re-exports the full testing API for convenience.
7
+ * For tree-shaking, import directly from the focused sub-modules.
8
+ */
9
+ export { fire, createPointerEvent } from './events';
10
+ export { FLUSH_DEEP, flush, type FlushOptions } from './flush';
11
+ export { user } from './interactions';
12
+ export { cleanup, mock, mount, mountComponent, type Fixture, type MountOptions, type MountSetup } from './mount';
13
+ export { within, type QueryScope } from './query';
14
+ export { waitFor, waitForEvent, type WaitOptions } from './wait';
15
+ export { renderHook, type HookFixture } from './render-hook';
16
+ /**
17
+ * Register auto-cleanup after each test. Call once in your test setup file.
18
+ *
19
+ * @example
20
+ * // vitest.setup.ts
21
+ * import { afterEach } from 'vitest';
22
+ * import { install } from '@vielzeug/ore/testing';
23
+ * install(afterEach);
24
+ */
25
+ export declare function install(afterEachHook: (fn: () => void) => void): void;
26
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,GAAG,IAAI,CAErE"}
@@ -0,0 +1,2 @@
1
+ import{FLUSH_DEEP as e,flush as t}from"./flush.js";import{within as n}from"./query.js";import{cleanup as r,mock as i,mount as a,mountComponent as o}from"./mount.js";import{createPointerEvent as s,fire as c}from"./events.js";import{user as l}from"./interactions.js";import{waitFor as u,waitForEvent as d}from"./wait.js";import{renderHook as f}from"./render-hook.js";function p(e){e(r)}export{e as FLUSH_DEEP,r as cleanup,s as createPointerEvent,c as fire,t as flush,p as install,i as mock,a as mount,o as mountComponent,f as renderHook,l as user,u as waitFor,d as waitForEvent,n as within};
2
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["/**\n * Testing utilities for Ore components\n *\n * ⚠️ Requires DOM environment (browser / jsdom / happy-dom)\n *\n * This barrel re-exports the full testing API for convenience.\n * For tree-shaking, import directly from the focused sub-modules.\n */\n\nimport { cleanup } from './mount';\n\nexport { fire, createPointerEvent } from './events';\nexport { FLUSH_DEEP, flush, type FlushOptions } from './flush';\nexport { user } from './interactions';\nexport { cleanup, mock, mount, mountComponent, type Fixture, type MountOptions, type MountSetup } from './mount';\nexport { within, type QueryScope } from './query';\nexport { waitFor, waitForEvent, type WaitOptions } from './wait';\nexport { renderHook, type HookFixture } from './render-hook';\n\n/**\n * Register auto-cleanup after each test. Call once in your test setup file.\n *\n * @example\n * // vitest.setup.ts\n * import { afterEach } from 'vitest';\n * import { install } from '@vielzeug/ore/testing';\n * install(afterEach);\n */\nexport function install(afterEachHook: (fn: () => void) => void): void {\n afterEachHook(cleanup);\n}\n"],"mappings":"6WA4BA,SAAgB,EAAQ,EAA+C,CACrE,EAAc,CAAO,CACvB"}
@@ -0,0 +1,2 @@
1
+ const e=require("../errors.cjs");async function t(t,{interval:n=50,message:r,timeout:i=1e3}={}){let a=Date.now()+i,o,s=async()=>{try{let e=await t();return e===void 0||!!e}catch(e){return o=e,!1}};for(;Date.now()<a;){if(await s())return;await new Promise(e=>setTimeout(e,n))}if(await s())return;let c=r??`waitFor timed out after ${i}ms`;throw o instanceof Error?(o.message=`${c}\n${o.message}`,o):new e.OreTimeoutError(o==null?c:`${c}\nCause: ${o}`)}function n(t,n,r=1e3){return new Promise((i,a)=>{let o=setTimeout(()=>a(new e.OreTimeoutError(`waitForEvent: "${n}" timed out after ${r}ms`)),r);t.addEventListener(n,e=>{clearTimeout(o),i(e)},{once:!0})})}exports.waitFor=t,exports.waitForEvent=n;
2
+ //# sourceMappingURL=wait.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.cjs","names":[],"sources":["../../src/testing/wait.ts"],"sourcesContent":["/**\n * Async waiting utilities for test environments.\n */\n\nimport { OreTimeoutError } from '../errors';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface WaitOptions {\n /** Maximum wait time in ms (default: 1000) */\n timeout?: number;\n /** Polling interval in ms (default: 50) */\n interval?: number;\n /** Message included in timeout error */\n message?: string;\n}\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Poll until a callback returns truthy (or void) without throwing.\n * Supports both boolean conditions and `expect()` assertions.\n *\n * - Returns truthy → success\n * - Returns `undefined` (e.g. bare `expect()` call) → success\n * - Returns falsy value → retry\n * - Throws → retry, re-throw original error on timeout\n *\n * @example\n * await waitFor(() => query('.status')?.textContent === 'loaded');\n * await waitFor(() => expect(count).toBe(3));\n */\nexport async function waitFor(\n fn: () => unknown,\n { interval = 50, message, timeout = 1000 }: WaitOptions = {},\n): Promise<void> {\n const deadline = Date.now() + timeout;\n let lastError: unknown;\n\n const attempt = async (): Promise<boolean> => {\n try {\n const result = await fn();\n\n return result === undefined || !!result;\n } catch (e) {\n lastError = e;\n\n return false;\n }\n };\n\n while (Date.now() < deadline) {\n if (await attempt()) return;\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n if (await attempt()) return;\n\n const base = message ?? `waitFor timed out after ${timeout}ms`;\n\n if (lastError instanceof Error) {\n lastError.message = `${base}\\n${lastError.message}`;\n throw lastError;\n }\n\n throw new OreTimeoutError(lastError != null ? `${base}\\nCause: ${lastError}` : base);\n}\n\n/**\n * Resolve when the target element emits the given event.\n *\n * @example\n * const promise = waitForEvent(el, 'change');\n * fire.click(trigger);\n * const event = await promise;\n */\nexport function waitForEvent<T extends Event = Event>(element: Element, name: string, timeout = 1000): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new OreTimeoutError(`waitForEvent: \"${name}\" timed out after ${timeout}ms`)),\n timeout,\n );\n\n element.addEventListener(\n name,\n (e) => {\n clearTimeout(timer);\n resolve(e as T);\n },\n { once: true },\n );\n });\n}\n"],"mappings":"iCAgCA,eAAsB,EACpB,EACA,CAAE,WAAW,GAAI,UAAS,UAAU,KAAsB,CAAC,EAC5C,CACf,IAAM,EAAW,KAAK,IAAI,EAAI,EAC1B,EAEE,EAAU,SAA8B,CAC5C,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,EAExB,OAAO,IAAW,IAAA,IAAa,CAAC,CAAC,CACnC,OAAS,EAAG,CAGV,MAFA,GAAY,EAEL,EACT,CACF,EAEA,KAAO,KAAK,IAAI,EAAI,GAAU,CAC5B,GAAI,MAAM,EAAQ,EAAG,OAErB,MAAM,IAAI,QAAS,GAAM,WAAW,EAAG,CAAQ,CAAC,CAClD,CAEA,GAAI,MAAM,EAAQ,EAAG,OAErB,IAAM,EAAO,GAAW,2BAA2B,EAAQ,IAO3D,MALI,aAAqB,OACvB,EAAU,QAAU,GAAG,EAAK,IAAI,EAAU,UACpC,GAGF,IAAI,EAAA,gBAAgB,GAAa,KAAwC,EAAjC,GAAG,EAAK,WAAW,GAAkB,CACrF,CAUA,SAAgB,EAAsC,EAAkB,EAAc,EAAU,IAAkB,CAChH,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAQ,eACN,EAAO,IAAI,EAAA,gBAAgB,kBAAkB,EAAK,oBAAoB,EAAQ,GAAG,CAAC,EACxF,CACF,EAEA,EAAQ,iBACN,EACC,GAAM,CACL,aAAa,CAAK,EAClB,EAAQ,CAAM,CAChB,EACA,CAAE,KAAM,EAAK,CACf,CACF,CAAC,CACH"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Async waiting utilities for test environments.
3
+ */
4
+ export interface WaitOptions {
5
+ /** Maximum wait time in ms (default: 1000) */
6
+ timeout?: number;
7
+ /** Polling interval in ms (default: 50) */
8
+ interval?: number;
9
+ /** Message included in timeout error */
10
+ message?: string;
11
+ }
12
+ /**
13
+ * Poll until a callback returns truthy (or void) without throwing.
14
+ * Supports both boolean conditions and `expect()` assertions.
15
+ *
16
+ * - Returns truthy → success
17
+ * - Returns `undefined` (e.g. bare `expect()` call) → success
18
+ * - Returns falsy value → retry
19
+ * - Throws → retry, re-throw original error on timeout
20
+ *
21
+ * @example
22
+ * await waitFor(() => query('.status')?.textContent === 'loaded');
23
+ * await waitFor(() => expect(count).toBe(3));
24
+ */
25
+ export declare function waitFor(fn: () => unknown, { interval, message, timeout }?: WaitOptions): Promise<void>;
26
+ /**
27
+ * Resolve when the target element emits the given event.
28
+ *
29
+ * @example
30
+ * const promise = waitForEvent(el, 'change');
31
+ * fire.click(trigger);
32
+ * const event = await promise;
33
+ */
34
+ export declare function waitForEvent<T extends Event = Event>(element: Element, name: string, timeout?: number): Promise<T>;
35
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/testing/wait.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAC3B,EAAE,EAAE,MAAM,OAAO,EACjB,EAAE,QAAa,EAAE,OAAO,EAAE,OAAc,EAAE,GAAE,WAAgB,GAC3D,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,SAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAgBhH"}
@@ -0,0 +1,2 @@
1
+ import{OreTimeoutError as e}from"../errors.js";async function t(t,{interval:n=50,message:r,timeout:i=1e3}={}){let a=Date.now()+i,o,s=async()=>{try{let e=await t();return e===void 0||!!e}catch(e){return o=e,!1}};for(;Date.now()<a;){if(await s())return;await new Promise(e=>setTimeout(e,n))}if(await s())return;let c=r??`waitFor timed out after ${i}ms`;throw o instanceof Error?(o.message=`${c}\n${o.message}`,o):new e(o==null?c:`${c}\nCause: ${o}`)}function n(t,n,r=1e3){return new Promise((i,a)=>{let o=setTimeout(()=>a(new e(`waitForEvent: "${n}" timed out after ${r}ms`)),r);t.addEventListener(n,e=>{clearTimeout(o),i(e)},{once:!0})})}export{t as waitFor,n as waitForEvent};
2
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","names":[],"sources":["../../src/testing/wait.ts"],"sourcesContent":["/**\n * Async waiting utilities for test environments.\n */\n\nimport { OreTimeoutError } from '../errors';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface WaitOptions {\n /** Maximum wait time in ms (default: 1000) */\n timeout?: number;\n /** Polling interval in ms (default: 50) */\n interval?: number;\n /** Message included in timeout error */\n message?: string;\n}\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Poll until a callback returns truthy (or void) without throwing.\n * Supports both boolean conditions and `expect()` assertions.\n *\n * - Returns truthy → success\n * - Returns `undefined` (e.g. bare `expect()` call) → success\n * - Returns falsy value → retry\n * - Throws → retry, re-throw original error on timeout\n *\n * @example\n * await waitFor(() => query('.status')?.textContent === 'loaded');\n * await waitFor(() => expect(count).toBe(3));\n */\nexport async function waitFor(\n fn: () => unknown,\n { interval = 50, message, timeout = 1000 }: WaitOptions = {},\n): Promise<void> {\n const deadline = Date.now() + timeout;\n let lastError: unknown;\n\n const attempt = async (): Promise<boolean> => {\n try {\n const result = await fn();\n\n return result === undefined || !!result;\n } catch (e) {\n lastError = e;\n\n return false;\n }\n };\n\n while (Date.now() < deadline) {\n if (await attempt()) return;\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n if (await attempt()) return;\n\n const base = message ?? `waitFor timed out after ${timeout}ms`;\n\n if (lastError instanceof Error) {\n lastError.message = `${base}\\n${lastError.message}`;\n throw lastError;\n }\n\n throw new OreTimeoutError(lastError != null ? `${base}\\nCause: ${lastError}` : base);\n}\n\n/**\n * Resolve when the target element emits the given event.\n *\n * @example\n * const promise = waitForEvent(el, 'change');\n * fire.click(trigger);\n * const event = await promise;\n */\nexport function waitForEvent<T extends Event = Event>(element: Element, name: string, timeout = 1000): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new OreTimeoutError(`waitForEvent: \"${name}\" timed out after ${timeout}ms`)),\n timeout,\n );\n\n element.addEventListener(\n name,\n (e) => {\n clearTimeout(timer);\n resolve(e as T);\n },\n { once: true },\n );\n });\n}\n"],"mappings":"+CAgCA,eAAsB,EACpB,EACA,CAAE,WAAW,GAAI,UAAS,UAAU,KAAsB,CAAC,EAC5C,CACf,IAAM,EAAW,KAAK,IAAI,EAAI,EAC1B,EAEE,EAAU,SAA8B,CAC5C,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,EAExB,OAAO,IAAW,IAAA,IAAa,CAAC,CAAC,CACnC,OAAS,EAAG,CAGV,MAFA,GAAY,EAEL,EACT,CACF,EAEA,KAAO,KAAK,IAAI,EAAI,GAAU,CAC5B,GAAI,MAAM,EAAQ,EAAG,OAErB,MAAM,IAAI,QAAS,GAAM,WAAW,EAAG,CAAQ,CAAC,CAClD,CAEA,GAAI,MAAM,EAAQ,EAAG,OAErB,IAAM,EAAO,GAAW,2BAA2B,EAAQ,IAO3D,MALI,aAAqB,OACvB,EAAU,QAAU,GAAG,EAAK,IAAI,EAAU,UACpC,GAGF,IAAI,EAAgB,GAAa,KAAwC,EAAjC,GAAG,EAAK,WAAW,GAAkB,CACrF,CAUA,SAAgB,EAAsC,EAAkB,EAAc,EAAU,IAAkB,CAChH,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAQ,eACN,EAAO,IAAI,EAAgB,kBAAkB,EAAK,oBAAoB,EAAQ,GAAG,CAAC,EACxF,CACF,EAEA,EAAQ,iBACN,EACC,GAAM,CACL,aAAa,CAAK,EAClB,EAAQ,CAAM,CAChB,EACA,CAAE,KAAM,EAAK,CACf,CACF,CAAC,CACH"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./testing/flush.cjs"),t=require("./testing/query.cjs"),n=require("./testing/mount.cjs"),r=require("./testing/events.cjs"),i=require("./testing/interactions.cjs"),a=require("./testing/wait.cjs"),o=require("./testing/render-hook.cjs"),s=require("./testing/testing.cjs");exports.FLUSH_DEEP=e.FLUSH_DEEP,exports.cleanup=n.cleanup,exports.createPointerEvent=r.createPointerEvent,exports.fire=r.fire,exports.flush=e.flush,exports.install=s.install,exports.mock=n.mock,exports.mount=n.mount,exports.mountComponent=n.mountComponent,exports.renderHook=o.renderHook,exports.user=i.user,exports.waitFor=a.waitFor,exports.waitForEvent=a.waitForEvent,exports.within=t.within;
@@ -0,0 +1 @@
1
+ import{FLUSH_DEEP as e,flush as t}from"./testing/flush.js";import{within as n}from"./testing/query.js";import{cleanup as r,mock as i,mount as a,mountComponent as o}from"./testing/mount.js";import{createPointerEvent as s,fire as c}from"./testing/events.js";import{user as l}from"./testing/interactions.js";import{waitFor as u,waitForEvent as d}from"./testing/wait.js";import{renderHook as f}from"./testing/render-hook.js";import{install as p}from"./testing/testing.js";export{e as FLUSH_DEEP,r as cleanup,s as createPointerEvent,c as fire,t as flush,p as install,i as mock,a as mount,o as mountComponent,f as renderHook,l as user,u as waitFor,d as waitForEvent,n as within};
@@ -0,0 +1,2 @@
1
+ let e=require("@vielzeug/ripple");function t(){return(0,e.signal)(null)}var n=e=>{let t=Symbol.for(e);return{is:e=>typeof e==`object`&&!!e&&t in e,stamp:e=>Object.assign(e,{[t]:!0})}},r=n(`ore:directive`),i=e=>r.stamp({mount:e}),a=r.is,o=n(`ore:spread`),s=e=>o.stamp({apply:e}),c=o.is,l=n(`ore:html-result`),u=l.is;function d(e,t){return l.stamp({apply:t,fragment:e,mount:(n,r,i)=>{let a=Array.from(e.childNodes);return n.insertBefore(e,r),t(i),a}})}exports.createDirectiveResult=i,exports.createHtmlResult=d,exports.createSpreadObject=s,exports.isDirectiveResult=a,exports.isHtmlResult=u,exports.isSpreadObject=c,exports.ref=t;
2
+ //# sourceMappingURL=bindings.cjs.map