@vielzeug/ore 1.2.1 → 1.2.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.
@@ -1 +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 { 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 * `onMounted`/`onCleanup`/`bind`/... work exactly as they would inside a real\n * `setup()`, since they resolve the same implicit current-component context.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook(() => {\n * const count = signal(0);\n * 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>(setup: (_props: Record<never, never>) => T): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>) => T) | D,\n maybeSetup?: (props: InferProps<D>) => 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>) => T);\n\n const hostScope = _scope();\n // Minimal host element so getHost() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const formResetCallbacks: Array<() => void> = [];\n const ctx = { element: hostEl, formResetCallbacks, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>);\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":"uHAqDA,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,EAEpD,EAAM,CAAE,QAAS,EAAQ,mBAAA,CAAA,EAAoB,gBAAe,EAE9D,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAA,eAAe,MAAW,CACxB,IAAM,EAAQ,EAAW,EAAA,YAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,CAAsB,CACvC,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"}
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 { OreLifecycleError, reportRuntimeError } from '../errors';\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 * `onMounted`/`onCleanup`/`bind`/... work exactly as they would inside a real\n * `setup()`, since they resolve the same implicit current-component context.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook(() => {\n * const count = signal(0);\n * 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>(setup: (_props: Record<never, never>) => T): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>) => T) | D,\n maybeSetup?: (props: InferProps<D>) => 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>) => T);\n\n const hostScope = _scope();\n // Minimal host element so getHost() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const formResetCallbacks: Array<() => void> = [];\n const ctx = { element: hostEl, formResetCallbacks, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>);\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 (error) {\n // Mirror BaseElement's real onMounted error handling (see\n // base-element.ts's `_scheduleMountCallbacks`): report the error\n // (console + `ore:error` event on the host) and keep running the\n // remaining callbacks, instead of hiding the failure entirely.\n const err = error instanceof Error ? error : new Error(String(error));\n\n reportRuntimeError(\n new OreLifecycleError(`renderHook() mount callback failed`, {\n cause: err,\n component: 'renderHook',\n phase: 'mounted',\n }),\n hostEl,\n );\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":"kJAsDA,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,EAEpD,EAAM,CAAE,QAAS,EAAQ,mBAAA,CAAA,EAAoB,gBAAe,EAE9D,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAA,eAAe,MAAW,CACxB,IAAM,EAAQ,EAAW,EAAA,YAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,CAAsB,CACvC,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,OAAS,EAAO,CAOd,EAAA,mBACE,IAAI,EAAA,kBAAkB,qCAAsC,CAC1D,MAJQ,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,EAKhE,UAAW,aACX,MAAO,SACT,CAAC,EACD,CACF,CACF,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"render-hook.d.ts","sourceRoot":"","sources":["../../src/testing/render-hook.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,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;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AACzG,wBAAsB,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,EACzD,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"render-hook.d.ts","sourceRoot":"","sources":["../../src/testing/render-hook.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,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;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AACzG,wBAAsB,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,EACzD,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- import{flush as e}from"./flush.js";import{runWithContext as t}from"../runtime.js";import{createProps as n}from"../props.js";import{onCleanup as r,scope as i}from"@vielzeug/ripple";async function a(a,o){let s=typeof a!=`function`,c=s?a:void 0,l=s?o:a,u=i(),d=document.createElement(`div`);document.body.appendChild(d);let f=[],p={element:d,formResetCallbacks:[],mountCallbacks:f},m;try{u.run(()=>{t(p,()=>{let e=c?n(d,c):{};m=l(e)})});for(let e of f)try{u.run(()=>{t(p,()=>{let t=e();typeof t==`function`&&r(t)})})}catch{}}catch(e){throw u.dispose(),d.remove(),e}await e();let h=!1;function g(){h||(h=!0,u.dispose(),d.remove())}return{dispose:g,get disposed(){return h},async flush(){await e()},result:m,[Symbol.dispose](){g()}}}export{a as renderHook};
1
+ import{flush as e}from"./flush.js";import{OreLifecycleError as t,reportRuntimeError as n}from"../errors.js";import{runWithContext as r}from"../runtime.js";import{createProps as i}from"../props.js";import{onCleanup as a,scope as o}from"@vielzeug/ripple";async function s(s,c){let l=typeof s!=`function`,u=l?s:void 0,d=l?c:s,f=o(),p=document.createElement(`div`);document.body.appendChild(p);let m=[],h={element:p,formResetCallbacks:[],mountCallbacks:m},g;try{f.run(()=>{r(h,()=>{let e=u?i(p,u):{};g=d(e)})});for(let e of m)try{f.run(()=>{r(h,()=>{let t=e();typeof t==`function`&&a(t)})})}catch(e){n(new t(`renderHook() mount callback failed`,{cause:e instanceof Error?e:Error(String(e)),component:`renderHook`,phase:`mounted`}),p)}}catch(e){throw f.dispose(),p.remove(),e}await e();let _=!1;function v(){_||(_=!0,f.dispose(),p.remove())}return{dispose:v,get disposed(){return _},async flush(){await e()},result:g,[Symbol.dispose](){v()}}}export{s as renderHook};
2
2
  //# sourceMappingURL=render-hook.js.map
@@ -1 +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 { 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 * `onMounted`/`onCleanup`/`bind`/... work exactly as they would inside a real\n * `setup()`, since they resolve the same implicit current-component context.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook(() => {\n * const count = signal(0);\n * 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>(setup: (_props: Record<never, never>) => T): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>) => T) | D,\n maybeSetup?: (props: InferProps<D>) => 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>) => T);\n\n const hostScope = _scope();\n // Minimal host element so getHost() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const formResetCallbacks: Array<() => void> = [];\n const ctx = { element: hostEl, formResetCallbacks, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>);\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":"oLAqDA,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,EAEpD,EAAM,CAAE,QAAS,EAAQ,mBAAA,CAAA,EAAoB,gBAAe,EAE9D,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAe,MAAW,CACxB,IAAM,EAAQ,EAAW,EAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,CAAsB,CACvC,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"}
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 { OreLifecycleError, reportRuntimeError } from '../errors';\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 * `onMounted`/`onCleanup`/`bind`/... work exactly as they would inside a real\n * `setup()`, since they resolve the same implicit current-component context.\n *\n * @example No props\n * ```ts\n * const { result, flush } = await renderHook(() => {\n * const count = signal(0);\n * 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>(setup: (_props: Record<never, never>) => T): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n propDefs: D,\n setup: (props: InferProps<D>) => T,\n): Promise<HookFixture<T>>;\nexport async function renderHook<D extends PropInputDefs, T>(\n setupOrDefs: ((_props: Record<never, never>) => T) | D,\n maybeSetup?: (props: InferProps<D>) => 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>) => T);\n\n const hostScope = _scope();\n // Minimal host element so getHost() works inside setup\n const hostEl = document.createElement('div');\n\n document.body.appendChild(hostEl);\n\n const mountCallbacks: Array<() => void | (() => void)> = [];\n const formResetCallbacks: Array<() => void> = [];\n const ctx = { element: hostEl, formResetCallbacks, mountCallbacks };\n\n let result!: T;\n\n try {\n hostScope.run(() => {\n runWithContext(ctx, () => {\n const props = propDefs ? createProps(hostEl, propDefs as PropInputDefs) : ({} as Record<never, never>);\n\n result = setup(props as InferProps<D>);\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 (error) {\n // Mirror BaseElement's real onMounted error handling (see\n // base-element.ts's `_scheduleMountCallbacks`): report the error\n // (console + `ore:error` event on the host) and keep running the\n // remaining callbacks, instead of hiding the failure entirely.\n const err = error instanceof Error ? error : new Error(String(error));\n\n reportRuntimeError(\n new OreLifecycleError(`renderHook() mount callback failed`, {\n cause: err,\n component: 'renderHook',\n phase: 'mounted',\n }),\n hostEl,\n );\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":"6PAsDA,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,EAEpD,EAAM,CAAE,QAAS,EAAQ,mBAAA,CAAA,EAAoB,gBAAe,EAE9D,EAEJ,GAAI,CACF,EAAU,QAAU,CAClB,EAAe,MAAW,CACxB,IAAM,EAAQ,EAAW,EAAY,EAAQ,CAAyB,EAAK,CAAC,EAE5E,EAAS,EAAM,CAAsB,CACvC,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,OAAS,EAAO,CAOd,EACE,IAAI,EAAkB,qCAAsC,CAC1D,MAJQ,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,EAKhE,UAAW,aACX,MAAO,SACT,CAAC,EACD,CACF,CACF,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"}
@@ -1,2 +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;
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=e=>{clearTimeout(s),i(e)},s=setTimeout(()=>{t.removeEventListener(n,o),a(new e.OreTimeoutError(`waitForEvent: "${n}" timed out after ${r}ms`))},r);t.addEventListener(n,o,{once:!0})})}exports.waitFor=t,exports.waitForEvent=n;
2
2
  //# sourceMappingURL=wait.cjs.map
@@ -1 +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"}
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 onEvent = (e: Event): void => {\n clearTimeout(timer);\n resolve(e as T);\n };\n const timer = setTimeout(() => {\n element.removeEventListener(name, onEvent);\n reject(new OreTimeoutError(`waitForEvent: \"${name}\" timed out after ${timeout}ms`));\n }, timeout);\n\n element.addEventListener(name, onEvent, { once: true });\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,EAAW,GAAmB,CAClC,aAAa,CAAK,EAClB,EAAQ,CAAM,CAChB,EACM,EAAQ,eAAiB,CAC7B,EAAQ,oBAAoB,EAAM,CAAO,EACzC,EAAO,IAAI,EAAA,gBAAgB,kBAAkB,EAAK,oBAAoB,EAAQ,GAAG,CAAC,CACpF,EAAG,CAAO,EAEV,EAAQ,iBAAiB,EAAM,EAAS,CAAE,KAAM,EAAK,CAAC,CACxD,CAAC,CACH"}
@@ -1 +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"}
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,CAahH"}
@@ -1,2 +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};
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=e=>{clearTimeout(s),i(e)},s=setTimeout(()=>{t.removeEventListener(n,o),a(new e(`waitForEvent: "${n}" timed out after ${r}ms`))},r);t.addEventListener(n,o,{once:!0})})}export{t as waitFor,n as waitForEvent};
2
2
  //# sourceMappingURL=wait.js.map
@@ -1 +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"}
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 onEvent = (e: Event): void => {\n clearTimeout(timer);\n resolve(e as T);\n };\n const timer = setTimeout(() => {\n element.removeEventListener(name, onEvent);\n reject(new OreTimeoutError(`waitForEvent: \"${name}\" timed out after ${timeout}ms`));\n }, timeout);\n\n element.addEventListener(name, onEvent, { once: true });\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,EAAW,GAAmB,CAClC,aAAa,CAAK,EAClB,EAAQ,CAAM,CAChB,EACM,EAAQ,eAAiB,CAC7B,EAAQ,oBAAoB,EAAM,CAAO,EACzC,EAAO,IAAI,EAAgB,kBAAkB,EAAK,oBAAoB,EAAQ,GAAG,CAAC,CACpF,EAAG,CAAO,EAEV,EAAQ,iBAAiB,EAAM,EAAS,CAAE,KAAM,EAAK,CAAC,CACxD,CAAC,CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/ore",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Custom element authoring primitives — reactive templates, signals, slots, and automatic lifecycle management",
5
5
  "type": "module",
6
6
  "files": [
@@ -62,10 +62,10 @@
62
62
  "registry": "https://registry.npmjs.org/"
63
63
  },
64
64
  "engines": {
65
- "node": ">=18"
65
+ "node": ">=22"
66
66
  },
67
67
  "dependencies": {
68
- "@vielzeug/ripple": "1.2.1"
68
+ "@vielzeug/ripple": "1.2.3"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^26.1.0",