@llui/test 0.0.13 → 0.0.15

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":"assert-effects.js","sourceRoot":"","sources":["../src/assert-effects.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAI,MAAW,EAAE,QAA2B;IACvE,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,YAAY,QAAQ,CAAC,MAAM,iBAAiB,MAAM,CAAC,MAAM,KAAK;YAC5D,WAAW,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAC/C,CAAA;IACH,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,mBAAmB,CAAC,oBAAoB;gBACtC,uBAAuB,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;gBACvD,WAAW,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAC5C,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAe,EAAE,QAAiB;IACtD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACvC,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpC,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,QAAQ,CAAA;IAEpE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/D,MAAM,MAAM,GAAG,QAAmC,CAAA;QAClD,MAAM,MAAM,GAAG,MAAiC,CAAA;QAChD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAA;QAC3D,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC"}
1
+ {"version":3,"file":"assert-effects.js","sourceRoot":"","sources":["../src/assert-effects.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAI,MAAW,EAAE,QAA2B;IACvE,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,YAAY,QAAQ,CAAC,MAAM,iBAAiB,MAAM,CAAC,MAAM,KAAK;YAC5D,WAAW,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAC/C,CAAA;IACH,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,mBAAmB,CAAC,oBAAoB;gBACtC,uBAAuB,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;gBACvD,WAAW,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAC5C,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAe,EAAE,QAAiB;IACtD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACvC,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpC,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,QAAQ,CAAA;IAEpE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/D,MAAM,MAAM,GAAG,QAAmC,CAAA;QAClD,MAAM,MAAM,GAAG,MAAiC,CAAA;QAChD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAA;QAC3D,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["export function assertEffects<E>(actual: E[], expected: Array<Partial<E>>): void {\n if (actual.length !== expected.length) {\n throw new Error(\n `Expected ${expected.length} effects, got ${actual.length}.\\n` +\n `Actual: ${JSON.stringify(actual, null, 2)}`,\n )\n }\n\n for (let i = 0; i < expected.length; i++) {\n const act = actual[i]\n const exp = expected[i]\n if (!partialMatch(act, exp)) {\n throw new Error(\n `Effect at index ${i} does not match.\\n` +\n `Expected (partial): ${JSON.stringify(exp, null, 2)}\\n` +\n `Actual: ${JSON.stringify(act, null, 2)}`,\n )\n }\n }\n}\n\nfunction partialMatch(actual: unknown, expected: unknown): boolean {\n if (expected === undefined) return true\n if (actual === expected) return true\n if (expected === null || actual === null) return actual === expected\n\n if (typeof expected === 'object' && typeof actual === 'object') {\n const expObj = expected as Record<string, unknown>\n const actObj = actual as Record<string, unknown>\n for (const key of Object.keys(expObj)) {\n if (!partialMatch(actObj[key], expObj[key])) return false\n }\n return true\n }\n\n return false\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { testComponent } from './test-component';
2
- export { testView } from './test-view';
3
- export { assertEffects } from './assert-effects';
4
- export { propertyTest } from './property-test';
5
- export { replayTrace } from './replay-trace';
1
+ export { testComponent } from './test-component.js';
2
+ export { testView } from './test-view.js';
3
+ export { assertEffects } from './assert-effects.js';
4
+ export { propertyTest } from './property-test.js';
5
+ export { replayTrace } from './replay-trace.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { testComponent } from './test-component';
2
- export { testView } from './test-view';
3
- export { assertEffects } from './assert-effects';
4
- export { propertyTest } from './property-test';
5
- export { replayTrace } from './replay-trace';
1
+ export { testComponent } from './test-component.js';
2
+ export { testView } from './test-view.js';
3
+ export { assertEffects } from './assert-effects.js';
4
+ export { propertyTest } from './property-test.js';
5
+ export { replayTrace } from './replay-trace.js';
6
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA","sourcesContent":["export { testComponent } from './test-component.js'\nexport { testView } from './test-view.js'\nexport { assertEffects } from './assert-effects.js'\nexport { propertyTest } from './property-test.js'\nexport { replayTrace } from './replay-trace.js'\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"property-test.js","sourceRoot":"","sources":["../src/property-test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"property-test.js","sourceRoot":"","sources":["../src/property-test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef } from '@llui/dom'\n\nexport function propertyTest<S, M, E>(\n def: ComponentDef<S, M, E>,\n config: {\n invariants: Array<(state: S, effects: E[]) => boolean>\n messageGenerators: Record<string, ((state: S) => M) | (() => M)>\n runs?: number\n maxSequenceLength?: number\n },\n): void {\n const runs = config.runs ?? 1000\n const maxLen = config.maxSequenceLength ?? 50\n const genNames = Object.keys(config.messageGenerators)\n\n if (genNames.length === 0) {\n throw new Error('propertyTest: at least one message generator required')\n }\n\n for (let run = 0; run < runs; run++) {\n const [initState, initEffects] = def.init()\n let state = initState\n const sequence: { name: string; msg: M }[] = []\n\n // Check invariants on initial state\n checkInvariants(config.invariants, state, initEffects, sequence)\n\n const seqLen = 1 + Math.floor(Math.random() * maxLen)\n\n for (let step = 0; step < seqLen; step++) {\n const genName = genNames[Math.floor(Math.random() * genNames.length)]!\n const gen = config.messageGenerators[genName]!\n const msg = gen.length === 0 ? (gen as () => M)() : (gen as (s: S) => M)(state)\n sequence.push({ name: genName, msg })\n\n const [newState, effects] = def.update(state, msg)\n state = newState\n\n checkInvariants(config.invariants, state, effects, sequence)\n }\n }\n}\n\nfunction checkInvariants<S, M, E>(\n invariants: Array<(state: S, effects: E[]) => boolean>,\n state: S,\n effects: E[],\n sequence: Array<{ name: string; msg: M }>,\n): void {\n for (let i = 0; i < invariants.length; i++) {\n if (!invariants[i]!(state, effects)) {\n // Attempt to shrink\n const shrunk = shrinkSequence(sequence)\n const seqStr = shrunk.map((s) => s.name).join(' → ')\n throw new Error(\n `propertyTest: invariant ${i} violated after sequence: [${seqStr}]\\n` +\n `State: ${JSON.stringify(state)}\\n` +\n `Effects: ${JSON.stringify(effects)}`,\n )\n }\n }\n}\n\nfunction shrinkSequence<M>(\n sequence: Array<{ name: string; msg: M }>,\n): Array<{ name: string; msg: M }> {\n // Simple shrinking: try removing each element from the end\n // A full implementation would do binary search shrinking\n // For now, just return the sequence as-is (no shrinking)\n return sequence\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"replay-trace.js","sourceRoot":"","sources":["../src/replay-trace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replay-trace.js","sourceRoot":"","sources":["../src/replay-trace.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef } from '@llui/dom'\n\nexport interface LluiTrace<S, M, E> {\n lluiTrace: 1\n component: string\n generatedBy: string\n timestamp: string\n entries: Array<{\n msg: M\n expectedState: S\n expectedEffects: E[]\n }>\n}\n\nexport function replayTrace<S, M, E>(def: ComponentDef<S, M, E>, trace: LluiTrace<S, M, E>): void {\n const [initState] = def.init()\n let state = initState\n\n for (let i = 0; i < trace.entries.length; i++) {\n const entry = trace.entries[i]!\n const [newState, effects] = def.update(state, entry.msg)\n\n // Compare state\n if (!deepEqual(newState, entry.expectedState)) {\n throw new Error(\n `replayTrace: state diverged at step ${i}\\n` +\n `Message: ${JSON.stringify(entry.msg)}\\n` +\n `Expected: ${JSON.stringify(entry.expectedState)}\\n` +\n `Actual: ${JSON.stringify(newState)}`,\n )\n }\n\n // Compare effects\n if (!deepEqual(effects, entry.expectedEffects)) {\n throw new Error(\n `replayTrace: effects diverged at step ${i}\\n` +\n `Message: ${JSON.stringify(entry.msg)}\\n` +\n `Expected effects: ${JSON.stringify(entry.expectedEffects)}\\n` +\n `Actual effects: ${JSON.stringify(effects)}`,\n )\n }\n\n state = newState\n }\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (a === null || b === null) return false\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return false\n\n if (Array.isArray(a)) {\n if (!Array.isArray(b)) return false\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) return false\n }\n return true\n }\n\n const aObj = a as Record<string, unknown>\n const bObj = b as Record<string, unknown>\n const aKeys = Object.keys(aObj)\n const bKeys = Object.keys(bObj)\n if (aKeys.length !== bKeys.length) return false\n\n for (const key of aKeys) {\n if (!deepEqual(aObj[key], bObj[key])) return false\n }\n\n return true\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"test-component.js","sourceRoot":"","sources":["../src/test-component.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,aAAa,CAC3B,GAA0B,EAC1B,WAAqB;IAErB,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,GAAI,GAAG,CAAC,IAAoC,CAAC,WAAW,CAAC,CAAA;IAEvF,MAAM,OAAO,GAAyB;QACpC,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,CAAC,GAAG,WAAW,CAAC;QAC5B,OAAO,EAAE,EAAE;QAEX,IAAI,CAAC,GAAM;YACT,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAA;YAC/B,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;YACvD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;YAC5D,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;YACzB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;YACzB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,OAAO,CAAC,IAAS;YACf,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACnB,CAAC;YACD,OAAO,OAAO,CAAC,KAAK,CAAA;QACtB,CAAC;KACF,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"test-component.js","sourceRoot":"","sources":["../src/test-component.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,aAAa,CAC3B,GAA0B,EAC1B,WAAqB;IAErB,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,GAAI,GAAG,CAAC,IAAoC,CAAC,WAAW,CAAC,CAAA;IAEvF,MAAM,OAAO,GAAyB;QACpC,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,CAAC,GAAG,WAAW,CAAC;QAC5B,OAAO,EAAE,EAAE;QAEX,IAAI,CAAC,GAAM;YACT,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAA;YAC/B,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;YACvD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;YAC5D,OAAO,CAAC,KAAK,GAAG,SAAS,CAAA;YACzB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;YACzB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,OAAO,CAAC,IAAS;YACf,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACnB,CAAC;YACD,OAAO,OAAO,CAAC,KAAK,CAAA;QACtB,CAAC;KACF,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import type { ComponentDef } from '@llui/dom'\n\nexport interface TestHarness<S, M, E> {\n state: S\n effects: E[]\n allEffects: E[]\n history: Array<{ prevState: S; msg: M; nextState: S; effects: E[] }>\n send: (msg: M) => void\n sendAll: (msgs: M[]) => S\n}\n\nexport function testComponent<S, M, E>(\n def: ComponentDef<S, M, E>,\n initialData?: unknown,\n): TestHarness<S, M, E> {\n const [initState, initEffects] = (def.init as (data: unknown) => [S, E[]])(initialData)\n\n const harness: TestHarness<S, M, E> = {\n state: initState,\n effects: initEffects,\n allEffects: [...initEffects],\n history: [],\n\n send(msg: M) {\n const prevState = harness.state\n const [nextState, effects] = def.update(prevState, msg)\n harness.history.push({ prevState, msg, nextState, effects })\n harness.state = nextState\n harness.effects = effects\n harness.allEffects.push(...effects)\n },\n\n sendAll(msgs: M[]) {\n for (const msg of msgs) {\n harness.send(msg)\n }\n return harness.state\n },\n }\n\n return harness\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"test-view.js","sourceRoot":"","sources":["../src/test-view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-view.js","sourceRoot":"","sources":["../src/test-view.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle } from '@llui/dom'\nimport { mountApp } from '@llui/dom'\n\nexport interface ViewHarness<M> {\n /** Mounted container — useful for advanced cases. */\n readonly container: HTMLElement\n /** The AppHandle returned by mountApp — expose dispose/flush. */\n readonly handle: AppHandle\n /** Query a single element. */\n query(selector: string): Element | null\n /** Query all matching elements. */\n queryAll(selector: string): Element[]\n /** Read the element's text content. Returns empty string if the element is missing. */\n text(selector: string): string\n /** Read an element's attribute. */\n attr(selector: string, name: string): string | null\n /** Dispatch a message and flush synchronously. */\n send(msg: M): void\n /** Click an element and flush. Throws if no element matches. */\n click(selector: string): void\n /** Set an input's value and dispatch an 'input' event, then flush. */\n input(selector: string, value: string): void\n /** Dispatch a custom event and flush. Default bubbles: true. */\n fire(selector: string, type: string, init?: EventInit): void\n /** Dispose + remove DOM. Idempotent. */\n unmount(): void\n}\n\n/**\n * Mount a component against a fresh container and return an interactive harness.\n * Simulates events + auto-flushes so tests can chain assertions naturally.\n */\nexport function testView<S, M, E>(def: ComponentDef<S, M, E>, state: S): ViewHarness<M> {\n const container = document.createElement('div')\n\n const testDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [state, []],\n }\n\n // Capture the component's send via a view interceptor.\n let sendFn: ((msg: M) => void) | null = null\n const originalView = testDef.view\n testDef.view = (h) => {\n sendFn = h.send\n return originalView(h)\n }\n\n const handle = mountApp(container, testDef)\n let disposed = false\n\n function required(selector: string): Element {\n const el = container.querySelector(selector)\n if (!el) throw new Error(`[testView] no element matches selector ${JSON.stringify(selector)}`)\n return el\n }\n\n return {\n container,\n handle,\n query: (s) => container.querySelector(s),\n queryAll: (s) => Array.from(container.querySelectorAll(s)),\n text: (s) => container.querySelector(s)?.textContent ?? '',\n attr: (s, name) => container.querySelector(s)?.getAttribute(name) ?? null,\n send(msg) {\n if (!sendFn) throw new Error('[testView] send unavailable (mount failed?)')\n sendFn(msg)\n handle.flush()\n },\n click(selector) {\n const el = required(selector)\n ;(el as HTMLElement).click()\n handle.flush()\n },\n input(selector, value) {\n const el = required(selector) as HTMLInputElement\n el.value = value\n el.dispatchEvent(new Event('input', { bubbles: true }))\n handle.flush()\n },\n fire(selector, type, init) {\n const el = required(selector)\n el.dispatchEvent(new Event(type, { bubbles: true, ...init }))\n handle.flush()\n },\n unmount() {\n if (disposed) return\n disposed = true\n handle.dispose()\n },\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/test",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -12,14 +12,8 @@
12
12
  "files": [
13
13
  "dist"
14
14
  ],
15
- "scripts": {
16
- "build": "tsc -p tsconfig.build.json",
17
- "check": "tsc --noEmit",
18
- "lint": "eslint src",
19
- "test": "vitest run"
20
- },
21
15
  "dependencies": {
22
- "@llui/dom": "^0.0.13"
16
+ "@llui/dom": "0.0.15"
23
17
  },
24
18
  "description": "LLui test harness — testComponent, testView, propertyTest, replayTrace, assertEffects",
25
19
  "keywords": [
@@ -39,5 +33,11 @@
39
33
  "bugs": {
40
34
  "url": "https://github.com/fponticelli/llui/issues"
41
35
  },
42
- "homepage": "https://github.com/fponticelli/llui/tree/main/packages/test#readme"
43
- }
36
+ "homepage": "https://github.com/fponticelli/llui/tree/main/packages/test#readme",
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.build.json",
39
+ "check": "tsc --noEmit",
40
+ "lint": "eslint src",
41
+ "test": "vitest run"
42
+ }
43
+ }