@coherent.js/tooling 1.0.0 → 1.0.1

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.
@@ -7081,5 +7081,5 @@
7081
7081
  "optional": true
7082
7082
  }
7083
7083
  ],
7084
- "generatedAt": "2026-07-29T21:27:27.486Z"
7084
+ "generatedAt": "2026-07-30T17:11:42.897Z"
7085
7085
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/tooling",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Coherent.js dev-time tooling: testing utilities (Vitest matchers, render harness) and Language Server Protocol implementation.",
5
5
  "type": "module",
6
6
  "main": "./dist/testing/index.js",
@@ -64,7 +64,7 @@
64
64
  "url": "https://github.com/Tomdrouv1/coherent.js/issues"
65
65
  },
66
66
  "peerDependencies": {
67
- "@coherent.js/core": "1.0.0"
67
+ "@coherent.js/core": "1.0.1"
68
68
  },
69
69
  "dependencies": {
70
70
  "typescript": "^5.9.3",
@@ -3,7 +3,7 @@
3
3
  * @module @coherent.js/testing
4
4
  */
5
5
 
6
- import type { CoherentNode, CoherentElement, CoherentComponent, ComponentProps } from '@coherent.js/core';
6
+ import type { CoherentNode, CoherentElement, CoherentComponent } from '@coherent.js/core';
7
7
 
8
8
  // ============================================================================
9
9
  // Test Renderer Types
@@ -78,20 +78,33 @@ export class TestRendererResult {
78
78
  }
79
79
 
80
80
  /**
81
- * Test renderer class
81
+ * Renders one component repeatedly, tracking how many times.
82
+ *
83
+ * The component and options are fixed at construction; `render()` and
84
+ * `update()` return a queryable {@link TestRendererResult}.
82
85
  */
83
86
  export class TestRenderer {
84
- /** Render a component */
85
- render(component: CoherentNode, options?: RenderOptions): RenderResult;
87
+ constructor(component: CoherentNode, options?: RenderOptions);
86
88
 
87
- /** Render a component asynchronously */
88
- renderAsync(component: CoherentNode, options?: RenderOptions): Promise<RenderResult>;
89
+ component: CoherentNode | null;
90
+ options: RenderOptions;
91
+ result: TestRendererResult | null;
92
+ renderCount: number;
89
93
 
90
- /** Shallow render (no children) */
91
- shallow(component: CoherentNode): RenderResult;
94
+ /** Render the current component and record the result */
95
+ render(): TestRendererResult;
92
96
 
93
- /** Cleanup all renders */
94
- cleanup(): void;
97
+ /** Swap in a new component and re-render */
98
+ update(newComponent: CoherentNode): TestRendererResult;
99
+
100
+ /** The most recent result, or `null` before the first render */
101
+ getResult(): TestRendererResult | null;
102
+
103
+ /** How many times `render()` has run */
104
+ getRenderCount(): number;
105
+
106
+ /** Drop the component and its result */
107
+ unmount(): void;
95
108
  }
96
109
 
97
110
  /**
@@ -176,33 +189,17 @@ export interface EventOptions {
176
189
  }
177
190
 
178
191
  /**
179
- * Fire DOM events on elements
192
+ * Simulate an event on a test element.
193
+ *
194
+ * Calls the element's `on<eventType>` handler with a synthetic event built
195
+ * from `eventData`. Throws when `element` is missing.
180
196
  */
181
- export const fireEvent: {
182
- /** Fire any event */
183
- (element: Element, event: Event): boolean;
184
- /** Fire click event */
185
- click(element: Element, options?: EventOptions): boolean;
186
- /** Fire change event */
187
- change(element: Element, options?: EventOptions & { target?: { value?: unknown } }): boolean;
188
- /** Fire input event */
189
- input(element: Element, options?: EventOptions & { target?: { value?: unknown } }): boolean;
190
- /** Fire submit event */
191
- submit(element: Element, options?: EventOptions): boolean;
192
- /** Fire keydown event */
193
- keyDown(element: Element, options?: EventOptions & { key?: string; code?: string }): boolean;
194
- /** Fire keyup event */
195
- keyUp(element: Element, options?: EventOptions & { key?: string; code?: string }): boolean;
196
- /** Fire focus event */
197
- focus(element: Element, options?: EventOptions): boolean;
198
- /** Fire blur event */
199
- blur(element: Element, options?: EventOptions): boolean;
200
- /** Fire mouseenter event */
201
- mouseEnter(element: Element, options?: EventOptions): boolean;
202
- /** Fire mouseleave event */
203
- mouseLeave(element: Element, options?: EventOptions): boolean;
204
- [key: string]: unknown;
205
- };
197
+ export function fireEvent(
198
+ element: unknown,
199
+ eventType: string,
200
+ eventData?: EventOptions
201
+ ): unknown;
202
+
206
203
 
207
204
  /**
208
205
  * Wait options
@@ -318,16 +315,15 @@ export const screen: Within;
318
315
  * User event simulation
319
316
  */
320
317
  export const userEvent: {
321
- click(element: Element): Promise<void>;
322
- dblClick(element: Element): Promise<void>;
323
- type(element: Element, text: string, options?: { delay?: number }): Promise<void>;
324
- clear(element: Element): Promise<void>;
325
- selectOptions(element: Element, values: string | string[]): Promise<void>;
326
- tab(options?: { shift?: boolean }): Promise<void>;
327
- hover(element: Element): Promise<void>;
328
- unhover(element: Element): Promise<void>;
329
- upload(element: Element, files: File | File[]): Promise<void>;
330
- paste(element: Element, text: string): Promise<void>;
318
+ /** Fire keydown/input/keyup per character, optionally spaced by `delay` ms */
319
+ type(element: unknown, text: string, options?: { delay?: number }): Promise<void>;
320
+ click(element: unknown): Promise<void>;
321
+ dblClick(element: unknown): Promise<void>;
322
+ /** Set the value to the empty string and fire `change` */
323
+ clear(element: unknown): Promise<void>;
324
+ selectOptions(element: unknown, values: string | string[]): Promise<void>;
325
+ /** Move focus to the next focusable element */
326
+ tab(): Promise<void>;
331
327
  };
332
328
 
333
329
  // ============================================================================
@@ -338,12 +334,16 @@ export const userEvent: {
338
334
  * Standard assertions
339
335
  */
340
336
  export const assertions: {
341
- assertElement(element: unknown): asserts element is Element;
342
- assertHTMLElement(element: unknown): asserts element is HTMLElement;
343
- assertInDocument(element: Element | null): asserts element is Element;
344
- assertVisible(element: Element): void;
345
- assertHasAttribute(element: Element, attr: string): void;
346
- assertHasClass(element: Element, className: string): void;
337
+ /** Throw unless the match's text equals `text` */
338
+ assertHasText(element: TestRendererMatch | null, text: string): void;
339
+ /** Throw unless the match exists */
340
+ assertExists(element: TestRendererMatch | null): void;
341
+ /** Throw unless the match's className contains `className` */
342
+ assertHasClass(element: TestRendererMatch | null, className: string): void;
343
+ /** Throw unless the HTML, or a result's HTML, contains `substring` */
344
+ assertContainsHTML(html: string | { html?: string } | null, substring: string): void;
345
+ /** Throw unless the render produced non-empty HTML */
346
+ assertRendered(result: { html?: string } | null): void;
347
347
  };
348
348
 
349
349
  // ============================================================================
@@ -12,3 +12,28 @@ export {
12
12
  waitForElementToBeRemoved,
13
13
  within
14
14
  } from './index.js';
15
+
16
+ // `export type {}` re-exports without binding locally, so the signatures below
17
+ // need their own import.
18
+ import type { EventOptions } from './index.js';
19
+ export type { EventOptions, WaitOptions } from './index.js';
20
+
21
+ // Per-event shorthands. They live on this module only -- ./testing does not
22
+ // re-export them -- so they are declared here rather than in index.d.ts.
23
+
24
+ /** {@link fireEvent} with `'click'`. */
25
+ export function fireEvent_click(element: unknown, eventData?: EventOptions): unknown;
26
+ /** {@link fireEvent} with `'change'`, setting `target.value`. */
27
+ export function fireEvent_change(element: unknown, value?: unknown): unknown;
28
+ /** {@link fireEvent} with `'input'`, setting `target.value`. */
29
+ export function fireEvent_input(element: unknown, value?: unknown): unknown;
30
+ /** {@link fireEvent} with `'submit'`. */
31
+ export function fireEvent_submit(element: unknown, eventData?: EventOptions): unknown;
32
+ /** {@link fireEvent} with `'keydown'`, setting `key`. */
33
+ export function fireEvent_keyDown(element: unknown, key?: string): unknown;
34
+ /** {@link fireEvent} with `'keyup'`, setting `key`. */
35
+ export function fireEvent_keyUp(element: unknown, key?: string): unknown;
36
+ /** {@link fireEvent} with `'focus'`. */
37
+ export function fireEvent_focus(element: unknown): unknown;
38
+ /** {@link fireEvent} with `'blur'`. */
39
+ export function fireEvent_blur(element: unknown): unknown;