@coherent.js/tooling 1.0.0-rc.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.
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/lsp/analysis/coherent-analyzer.d.ts +93 -0
- package/dist/lsp/analysis/coherent-analyzer.d.ts.map +1 -0
- package/dist/lsp/analysis/coherent-analyzer.js +288 -0
- package/dist/lsp/analysis/coherent-analyzer.js.map +1 -0
- package/dist/lsp/analysis/element-validator.d.ts +45 -0
- package/dist/lsp/analysis/element-validator.d.ts.map +1 -0
- package/dist/lsp/analysis/element-validator.js +84 -0
- package/dist/lsp/analysis/element-validator.js.map +1 -0
- package/dist/lsp/analysis/nesting-validator.d.ts +49 -0
- package/dist/lsp/analysis/nesting-validator.d.ts.map +1 -0
- package/dist/lsp/analysis/nesting-validator.js +68 -0
- package/dist/lsp/analysis/nesting-validator.js.map +1 -0
- package/dist/lsp/data/element-attributes.d.ts +92 -0
- package/dist/lsp/data/element-attributes.d.ts.map +1 -0
- package/dist/lsp/data/element-attributes.generated.json +7085 -0
- package/dist/lsp/data/element-attributes.js +282 -0
- package/dist/lsp/data/element-attributes.js.map +1 -0
- package/dist/lsp/data/nesting-rules.d.ts +67 -0
- package/dist/lsp/data/nesting-rules.d.ts.map +1 -0
- package/dist/lsp/data/nesting-rules.js +240 -0
- package/dist/lsp/data/nesting-rules.js.map +1 -0
- package/dist/lsp/providers/code-actions.d.ts +15 -0
- package/dist/lsp/providers/code-actions.d.ts.map +1 -0
- package/dist/lsp/providers/code-actions.js +191 -0
- package/dist/lsp/providers/code-actions.js.map +1 -0
- package/dist/lsp/providers/completion.d.ts +15 -0
- package/dist/lsp/providers/completion.d.ts.map +1 -0
- package/dist/lsp/providers/completion.js +247 -0
- package/dist/lsp/providers/completion.js.map +1 -0
- package/dist/lsp/providers/diagnostics.d.ts +26 -0
- package/dist/lsp/providers/diagnostics.d.ts.map +1 -0
- package/dist/lsp/providers/diagnostics.js +143 -0
- package/dist/lsp/providers/diagnostics.js.map +1 -0
- package/dist/lsp/providers/hover.d.ts +15 -0
- package/dist/lsp/providers/hover.d.ts.map +1 -0
- package/dist/lsp/providers/hover.js +215 -0
- package/dist/lsp/providers/hover.js.map +1 -0
- package/dist/lsp/server.d.ts +17 -0
- package/dist/lsp/server.d.ts.map +1 -0
- package/dist/lsp/server.js +82 -0
- package/dist/lsp/server.js.map +1 -0
- package/dist/testing/index.js +746 -0
- package/dist/testing/index.js.map +7 -0
- package/dist/testing/matchers.js +246 -0
- package/dist/testing/matchers.js.map +7 -0
- package/dist/testing/test-renderer.js +254 -0
- package/dist/testing/test-renderer.js.map +7 -0
- package/dist/testing/test-utils.js +262 -0
- package/dist/testing/test-utils.js.map +7 -0
- package/package.json +96 -0
- package/types/testing/index.d.ts +404 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coherent.js Testing Utilities TypeScript Definitions
|
|
3
|
+
* @module @coherent.js/testing
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CoherentNode, CoherentElement, CoherentComponent, ComponentProps } from '@coherent.js/core';
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Test Renderer Types
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Render options for test utilities
|
|
14
|
+
*/
|
|
15
|
+
export interface RenderOptions {
|
|
16
|
+
/** Wrapper component */
|
|
17
|
+
wrapper?: CoherentComponent;
|
|
18
|
+
/** Context values to provide */
|
|
19
|
+
context?: Record<string, unknown>;
|
|
20
|
+
/** Props to pass to component */
|
|
21
|
+
props?: Record<string, unknown>;
|
|
22
|
+
/** Initial state */
|
|
23
|
+
initialState?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Result from rendering a component
|
|
28
|
+
*/
|
|
29
|
+
export interface RenderResult {
|
|
30
|
+
/** Rendered HTML string */
|
|
31
|
+
html: string;
|
|
32
|
+
/** The rendered element structure */
|
|
33
|
+
element: CoherentElement;
|
|
34
|
+
/** Container element (if DOM is available) */
|
|
35
|
+
container: HTMLElement | null;
|
|
36
|
+
/** Re-render with new props */
|
|
37
|
+
rerender(props?: Record<string, unknown>): void;
|
|
38
|
+
/** Unmount and cleanup */
|
|
39
|
+
unmount(): void;
|
|
40
|
+
/** Debug output */
|
|
41
|
+
debug(): void;
|
|
42
|
+
/** Query helpers */
|
|
43
|
+
getByText(text: string | RegExp): Element | null;
|
|
44
|
+
getByTestId(testId: string): Element | null;
|
|
45
|
+
getAllByText(text: string | RegExp): Element[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Test renderer class
|
|
50
|
+
*/
|
|
51
|
+
export class TestRenderer {
|
|
52
|
+
/** Render a component */
|
|
53
|
+
render(component: CoherentNode, options?: RenderOptions): RenderResult;
|
|
54
|
+
|
|
55
|
+
/** Render a component asynchronously */
|
|
56
|
+
renderAsync(component: CoherentNode, options?: RenderOptions): Promise<RenderResult>;
|
|
57
|
+
|
|
58
|
+
/** Shallow render (no children) */
|
|
59
|
+
shallow(component: CoherentNode): RenderResult;
|
|
60
|
+
|
|
61
|
+
/** Cleanup all renders */
|
|
62
|
+
cleanup(): void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Render a component for testing
|
|
67
|
+
*/
|
|
68
|
+
export function renderComponent(
|
|
69
|
+
component: CoherentComponent | CoherentNode,
|
|
70
|
+
props?: Record<string, unknown>
|
|
71
|
+
): RenderResult;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Render a component asynchronously
|
|
75
|
+
*/
|
|
76
|
+
export function renderComponentAsync(
|
|
77
|
+
component: CoherentNode,
|
|
78
|
+
options?: RenderOptions
|
|
79
|
+
): Promise<RenderResult>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Create a new test renderer instance
|
|
83
|
+
*/
|
|
84
|
+
export function createTestRenderer(): TestRenderer;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Shallow render a component
|
|
88
|
+
*/
|
|
89
|
+
export function shallowRender(component: CoherentNode): RenderResult;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Render a node to HTML string
|
|
93
|
+
*/
|
|
94
|
+
export function renderToString(node: CoherentNode): string;
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Custom Matchers for Coherent.js
|
|
98
|
+
// ============================================================================
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Coherent.js-specific test matchers
|
|
102
|
+
*/
|
|
103
|
+
export interface CoherentMatchers<R = unknown> {
|
|
104
|
+
// Element structure matchers
|
|
105
|
+
/** Assert element has specific tag name */
|
|
106
|
+
toHaveTag(tagName: string): R;
|
|
107
|
+
/** Assert element contains text */
|
|
108
|
+
toHaveText(text: string): R;
|
|
109
|
+
/** Assert element has attribute (optionally with value) */
|
|
110
|
+
toHaveAttribute(name: string, value?: string): R;
|
|
111
|
+
/** Assert element has CSS class */
|
|
112
|
+
toHaveClassName(className: string): R;
|
|
113
|
+
/** Assert element has children (optionally specific count) */
|
|
114
|
+
toHaveChildren(count?: number): R;
|
|
115
|
+
|
|
116
|
+
// Component matchers
|
|
117
|
+
/** Assert component renders an element with tag */
|
|
118
|
+
toRenderElement(tagName: string): R;
|
|
119
|
+
/** Assert component renders text content */
|
|
120
|
+
toRenderText(text: string): R;
|
|
121
|
+
/** Assert component matches snapshot */
|
|
122
|
+
toMatchComponentSnapshot(): R;
|
|
123
|
+
|
|
124
|
+
// Hydration matchers
|
|
125
|
+
/** Assert hydration completes without mismatch */
|
|
126
|
+
toHydrateWithoutMismatch(): R;
|
|
127
|
+
/** Assert hydrated component has specific state */
|
|
128
|
+
toHaveState(state: Record<string, unknown>): R;
|
|
129
|
+
|
|
130
|
+
// Accessibility matchers
|
|
131
|
+
/** Assert element has accessible name */
|
|
132
|
+
toHaveAccessibleName(name: string): R;
|
|
133
|
+
/** Assert element has ARIA role */
|
|
134
|
+
toHaveRole(role: string): R;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ============================================================================
|
|
138
|
+
// Test Utilities
|
|
139
|
+
// ============================================================================
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Event simulation options
|
|
143
|
+
*/
|
|
144
|
+
export interface EventOptions {
|
|
145
|
+
bubbles?: boolean;
|
|
146
|
+
cancelable?: boolean;
|
|
147
|
+
composed?: boolean;
|
|
148
|
+
[key: string]: unknown;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Fire DOM events on elements
|
|
153
|
+
*/
|
|
154
|
+
export const fireEvent: {
|
|
155
|
+
/** Fire any event */
|
|
156
|
+
(element: Element, event: Event): boolean;
|
|
157
|
+
/** Fire click event */
|
|
158
|
+
click(element: Element, options?: EventOptions): boolean;
|
|
159
|
+
/** Fire change event */
|
|
160
|
+
change(element: Element, options?: EventOptions & { target?: { value?: unknown } }): boolean;
|
|
161
|
+
/** Fire input event */
|
|
162
|
+
input(element: Element, options?: EventOptions & { target?: { value?: unknown } }): boolean;
|
|
163
|
+
/** Fire submit event */
|
|
164
|
+
submit(element: Element, options?: EventOptions): boolean;
|
|
165
|
+
/** Fire keydown event */
|
|
166
|
+
keyDown(element: Element, options?: EventOptions & { key?: string; code?: string }): boolean;
|
|
167
|
+
/** Fire keyup event */
|
|
168
|
+
keyUp(element: Element, options?: EventOptions & { key?: string; code?: string }): boolean;
|
|
169
|
+
/** Fire focus event */
|
|
170
|
+
focus(element: Element, options?: EventOptions): boolean;
|
|
171
|
+
/** Fire blur event */
|
|
172
|
+
blur(element: Element, options?: EventOptions): boolean;
|
|
173
|
+
/** Fire mouseenter event */
|
|
174
|
+
mouseEnter(element: Element, options?: EventOptions): boolean;
|
|
175
|
+
/** Fire mouseleave event */
|
|
176
|
+
mouseLeave(element: Element, options?: EventOptions): boolean;
|
|
177
|
+
[key: string]: unknown;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Wait options
|
|
182
|
+
*/
|
|
183
|
+
export interface WaitOptions {
|
|
184
|
+
/** Timeout in ms */
|
|
185
|
+
timeout?: number;
|
|
186
|
+
/** Check interval in ms */
|
|
187
|
+
interval?: number;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Wait for a condition to be true
|
|
192
|
+
*/
|
|
193
|
+
export function waitFor<T>(
|
|
194
|
+
callback: () => T | Promise<T>,
|
|
195
|
+
options?: WaitOptions
|
|
196
|
+
): Promise<T>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Wait for an element to appear
|
|
200
|
+
*/
|
|
201
|
+
export function waitForElement(selector: string, options?: WaitOptions): Promise<Element>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Wait for an element to be removed
|
|
205
|
+
*/
|
|
206
|
+
export function waitForElementToBeRemoved(
|
|
207
|
+
selector: string | Element,
|
|
208
|
+
options?: WaitOptions
|
|
209
|
+
): Promise<void>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Run a callback and flush pending state updates
|
|
213
|
+
*/
|
|
214
|
+
export function act<T>(callback: () => T | Promise<T>): Promise<T>;
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Mock Utilities
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Mock function interface
|
|
222
|
+
*/
|
|
223
|
+
export interface Mock<T extends (...args: unknown[]) => unknown = (...args: unknown[]) => unknown> {
|
|
224
|
+
(...args: Parameters<T>): ReturnType<T>;
|
|
225
|
+
mock: {
|
|
226
|
+
calls: Parameters<T>[];
|
|
227
|
+
results: Array<{ type: 'return' | 'throw'; value: unknown }>;
|
|
228
|
+
instances: unknown[];
|
|
229
|
+
};
|
|
230
|
+
mockClear(): void;
|
|
231
|
+
mockReset(): void;
|
|
232
|
+
mockRestore(): void;
|
|
233
|
+
mockImplementation(fn: T): this;
|
|
234
|
+
mockReturnValue(value: ReturnType<T>): this;
|
|
235
|
+
mockReturnValueOnce(value: ReturnType<T>): this;
|
|
236
|
+
mockResolvedValue(value: ReturnType<T> extends Promise<infer U> ? U : never): this;
|
|
237
|
+
mockRejectedValue(error: unknown): this;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Create a mock function
|
|
242
|
+
*/
|
|
243
|
+
export function createMock<T extends (...args: unknown[]) => unknown>(
|
|
244
|
+
implementation?: T
|
|
245
|
+
): Mock<T>;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Create a spy on an object method
|
|
249
|
+
*/
|
|
250
|
+
export function createSpy<T extends (...args: unknown[]) => unknown>(
|
|
251
|
+
object: object,
|
|
252
|
+
method: string
|
|
253
|
+
): Mock<T>;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Mock a component
|
|
257
|
+
*/
|
|
258
|
+
export function mockComponent<P extends ComponentProps = ComponentProps>(
|
|
259
|
+
name: string,
|
|
260
|
+
render?: (props: P) => CoherentNode
|
|
261
|
+
): CoherentComponent<P>;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Create test state with reset capability
|
|
265
|
+
*/
|
|
266
|
+
export function createTestState<T extends Record<string, unknown>>(
|
|
267
|
+
initial: T
|
|
268
|
+
): {
|
|
269
|
+
getState: () => T;
|
|
270
|
+
setState: (updates: Partial<T>) => void;
|
|
271
|
+
reset: () => void;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Cleanup all mocks and rendered components
|
|
276
|
+
*/
|
|
277
|
+
export function cleanup(): void;
|
|
278
|
+
|
|
279
|
+
// ============================================================================
|
|
280
|
+
// Query Utilities
|
|
281
|
+
// ============================================================================
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Query helper interface
|
|
285
|
+
*/
|
|
286
|
+
export interface Within {
|
|
287
|
+
getByText(text: string | RegExp): Element;
|
|
288
|
+
getByRole(role: string, options?: { name?: string | RegExp }): Element;
|
|
289
|
+
getByLabelText(text: string | RegExp): Element;
|
|
290
|
+
getByPlaceholderText(text: string | RegExp): Element;
|
|
291
|
+
getByTestId(testId: string): Element;
|
|
292
|
+
queryByText(text: string | RegExp): Element | null;
|
|
293
|
+
queryByRole(role: string, options?: { name?: string | RegExp }): Element | null;
|
|
294
|
+
queryAllByText(text: string | RegExp): Element[];
|
|
295
|
+
findByText(text: string | RegExp): Promise<Element>;
|
|
296
|
+
findAllByText(text: string | RegExp): Promise<Element[]>;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Create query helpers scoped to an element
|
|
301
|
+
*/
|
|
302
|
+
export function within(element: Element): Within;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Global screen queries (document.body)
|
|
306
|
+
*/
|
|
307
|
+
export const screen: Within;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* User event simulation
|
|
311
|
+
*/
|
|
312
|
+
export const userEvent: {
|
|
313
|
+
click(element: Element): Promise<void>;
|
|
314
|
+
dblClick(element: Element): Promise<void>;
|
|
315
|
+
type(element: Element, text: string, options?: { delay?: number }): Promise<void>;
|
|
316
|
+
clear(element: Element): Promise<void>;
|
|
317
|
+
selectOptions(element: Element, values: string | string[]): Promise<void>;
|
|
318
|
+
tab(options?: { shift?: boolean }): Promise<void>;
|
|
319
|
+
hover(element: Element): Promise<void>;
|
|
320
|
+
unhover(element: Element): Promise<void>;
|
|
321
|
+
upload(element: Element, files: File | File[]): Promise<void>;
|
|
322
|
+
paste(element: Element, text: string): Promise<void>;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// ============================================================================
|
|
326
|
+
// Assertion Utilities
|
|
327
|
+
// ============================================================================
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Assert element structure matches expected
|
|
331
|
+
*/
|
|
332
|
+
export function assertElementStructure(
|
|
333
|
+
element: CoherentElement,
|
|
334
|
+
expected: Partial<CoherentElement>
|
|
335
|
+
): void;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Standard assertions
|
|
339
|
+
*/
|
|
340
|
+
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;
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// ============================================================================
|
|
350
|
+
// DOM Matchers (for Vitest/Jest)
|
|
351
|
+
// ============================================================================
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Custom DOM matchers
|
|
355
|
+
*/
|
|
356
|
+
export interface CustomMatchers<R = void> {
|
|
357
|
+
toHaveHTML(html: string): R;
|
|
358
|
+
toContainHTML(html: string): R;
|
|
359
|
+
toHaveTextContent(text: string | RegExp): R;
|
|
360
|
+
toHaveAttribute(attr: string, value?: string): R;
|
|
361
|
+
toHaveClass(className: string): R;
|
|
362
|
+
toBeInTheDocument(): R;
|
|
363
|
+
toBeVisible(): R;
|
|
364
|
+
toBeDisabled(): R;
|
|
365
|
+
toBeEnabled(): R;
|
|
366
|
+
toHaveValue(value: unknown): R;
|
|
367
|
+
toHaveStyle(style: Record<string, unknown>): R;
|
|
368
|
+
toHaveFocus(): R;
|
|
369
|
+
toBeChecked(): R;
|
|
370
|
+
toBeValid(): R;
|
|
371
|
+
toBeInvalid(): R;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Custom matchers object
|
|
376
|
+
*/
|
|
377
|
+
export const customMatchers: CustomMatchers;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Extend test framework expect
|
|
381
|
+
*/
|
|
382
|
+
export function extendExpect(matchers: Record<string, (...args: unknown[]) => unknown>): void;
|
|
383
|
+
|
|
384
|
+
// ============================================================================
|
|
385
|
+
// Vitest/Jest Module Extensions
|
|
386
|
+
// ============================================================================
|
|
387
|
+
|
|
388
|
+
// Extend Vitest matchers
|
|
389
|
+
declare module 'vitest' {
|
|
390
|
+
interface Assertion<T = unknown> extends CoherentMatchers<T>, CustomMatchers<T> {}
|
|
391
|
+
interface AsymmetricMatchersContaining extends CoherentMatchers, CustomMatchers {}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Extend Jest matchers (for users using Jest)
|
|
395
|
+
declare global {
|
|
396
|
+
namespace Vi {
|
|
397
|
+
interface Matchers<R = void> extends CustomMatchers<R>, CoherentMatchers<R> {}
|
|
398
|
+
interface AsymmetricMatchers extends CustomMatchers, CoherentMatchers {}
|
|
399
|
+
}
|
|
400
|
+
namespace jest {
|
|
401
|
+
interface Matchers<R = void> extends CustomMatchers<R>, CoherentMatchers<R> {}
|
|
402
|
+
interface Expect extends CustomMatchers, CoherentMatchers {}
|
|
403
|
+
}
|
|
404
|
+
}
|