0
# Testing Utilities
1
2
Comprehensive testing framework with unit testing, E2E testing, and screenshot testing capabilities. Stencil provides Jest integration, Puppeteer-based E2E testing, and extensive mocking utilities.
3
4
## Capabilities
5
6
### Spec Testing
7
8
Unit testing utilities for testing components in isolation with JSDOM.
9
10
```typescript { .api }
11
/**
12
* Creates a new spec page for unit testing components
13
* @param opts - Configuration options for the spec page
14
* @returns Promise resolving to SpecPage instance
15
*/
16
function newSpecPage(opts: NewSpecPageOptions): Promise<SpecPage>;
17
18
interface NewSpecPageOptions {
19
/** Components to register for testing */
20
components: any[];
21
/** HTML content to render */
22
html?: string;
23
/** Template function that returns HTML */
24
template?: () => string;
25
/** Include Stencil's built-in polyfills */
26
includeAnnotations?: boolean;
27
/** Support for checking HTML attribute/properties */
28
supportsShadowDom?: boolean;
29
/** Auto apply changes and trigger lifecycle methods */
30
autoApplyChanges?: boolean;
31
/** Suppress console logs during testing */
32
strictBuild?: boolean;
33
/** Cookie string to set on document */
34
cookie?: string;
35
/** Direction attribute for document */
36
direction?: string;
37
/** Language attribute for document */
38
language?: string;
39
/** User agent string */
40
userAgent?: string;
41
/** URL for the page */
42
url?: string;
43
}
44
45
interface SpecPage {
46
/** Document body element */
47
body: HTMLElement;
48
/** Full document */
49
doc: Document;
50
/** Root component element */
51
root?: HTMLElement;
52
/** Root component instance */
53
rootInstance?: any;
54
/** Window object */
55
win: Window;
56
57
/** Set HTML content and wait for changes */
58
setContent(html: string): Promise<void>;
59
/** Wait for all component changes to complete */
60
waitForChanges(): Promise<void>;
61
/** Flush all pending tasks */
62
flushLoadModule(): Promise<void>;
63
/** Flush all rendering tasks */
64
flushQueue(): Promise<void>;
65
}
66
```
67
68
**Usage Examples:**
69
70
```typescript
71
import { newSpecPage } from '@stencil/core/testing';
72
import { MyComponent } from './my-component';
73
74
describe('my-component', () => {
75
it('renders', async () => {
76
const page = await newSpecPage({
77
components: [MyComponent],
78
html: `<my-component first="Stencil" last="JS"></my-component>`,
79
});
80
81
expect(page.root).toEqualHtml(`
82
<my-component first="Stencil" last="JS">
83
<div>Hello, Stencil JS!</div>
84
</my-component>
85
`);
86
});
87
88
it('updates properties', async () => {
89
const page = await newSpecPage({
90
components: [MyComponent],
91
html: `<my-component first="John"></my-component>`,
92
});
93
94
page.root.last = 'Doe';
95
await page.waitForChanges();
96
97
expect(page.root).toEqualHtml(`
98
<my-component first="John" last="Doe">
99
<div>Hello, John Doe!</div>
100
</my-component>
101
`);
102
});
103
});
104
```
105
106
### E2E Testing
107
108
End-to-end testing utilities using Puppeteer for real browser testing.
109
110
```typescript { .api }
111
/**
112
* Creates a new E2E page for end-to-end testing
113
* @param opts - Configuration options for the E2E page
114
* @returns Promise resolving to E2EPage instance
115
*/
116
function newE2EPage(opts?: NewE2EPageOptions): Promise<E2EPage>;
117
118
interface NewE2EPageOptions {
119
/** Base URL for the test server */
120
url?: string;
121
/** HTML content to load */
122
html?: string;
123
/** Wait condition before proceeding */
124
waitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
125
/** User agent string */
126
userAgent?: string;
127
/** Cookie strings to set */
128
cookie?: string | string[];
129
/** Viewport size */
130
viewport?: { width: number; height: number };
131
/** Disable JavaScript */
132
disableJavaScript?: boolean;
133
}
134
135
interface E2EPage {
136
/** Navigate to a URL */
137
goto(url: string, opts?: any): Promise<any>;
138
/** Set HTML content */
139
setContent(html: string, opts?: any): Promise<void>;
140
/** Wait for selector to appear */
141
waitForSelector(selector: string, opts?: any): Promise<E2EElement>;
142
/** Wait for function result */
143
waitForFunction(fn: Function | string, opts?: any, ...args: any[]): Promise<any>;
144
/** Wait for specified time */
145
waitFor(milliseconds: number): Promise<void>;
146
/** Find element by selector */
147
find(selector: string): Promise<E2EElement>;
148
/** Find all elements by selector */
149
findAll(selector: string): Promise<E2EElement[]>;
150
/** Set viewport size */
151
setViewport(viewport: { width: number; height: number }): Promise<void>;
152
/** Take screenshot */
153
screenshot(opts?: any): Promise<Buffer>;
154
/** Compare screenshot against baseline */
155
compareScreenshot(desc?: string, opts?: any): Promise<any>;
156
/** Close the page */
157
close(): Promise<void>;
158
}
159
160
interface E2EElement {
161
/** Click the element */
162
click(opts?: any): Promise<void>;
163
/** Focus the element */
164
focus(): Promise<void>;
165
/** Hover over the element */
166
hover(): Promise<void>;
167
/** Type text into the element */
168
type(text: string, opts?: any): Promise<void>;
169
/** Press a key */
170
press(key: string, opts?: any): Promise<void>;
171
/** Get element property */
172
getProperty(name: string): Promise<any>;
173
/** Get element attribute */
174
getAttribute(name: string): Promise<string>;
175
/** Get element text content */
176
textContent(): Promise<string>;
177
/** Get element inner text */
178
innerText(): Promise<string>;
179
/** Check if element is visible */
180
isVisible(): Promise<boolean>;
181
/** Wait for element to be visible */
182
waitForVisible(): Promise<void>;
183
/** Wait for element to be hidden */
184
waitForNotVisible(): Promise<void>;
185
}
186
```
187
188
**Usage Examples:**
189
190
```typescript
191
import { newE2EPage } from '@stencil/core/testing';
192
193
describe('my-component e2e', () => {
194
it('renders', async () => {
195
const page = await newE2EPage();
196
await page.setContent('<my-component></my-component>');
197
198
const element = await page.find('my-component');
199
expect(element).toHaveClass('hydrated');
200
});
201
202
it('handles interactions', async () => {
203
const page = await newE2EPage();
204
await page.setContent(`
205
<my-component first="John" last="Doe"></my-component>
206
`);
207
208
const button = await page.find('my-component >>> button');
209
await button.click();
210
211
const result = await page.find('my-component >>> .result');
212
expect(await result.textContent()).toBe('Button clicked!');
213
});
214
215
it('takes screenshots', async () => {
216
const page = await newE2EPage();
217
await page.setContent('<my-component></my-component>');
218
219
await page.compareScreenshot('my-component-default');
220
});
221
});
222
```
223
224
### Mock Utilities
225
226
Utilities for creating mock objects and DOM elements for testing.
227
228
```typescript { .api }
229
/**
230
* Create a mock build context
231
* @returns Mock BuildCtx instance
232
*/
233
function mockBuildCtx(): BuildCtx;
234
235
/**
236
* Create a mock compiler context
237
* @returns Mock CompilerCtx instance
238
*/
239
function mockCompilerCtx(): CompilerCtx;
240
241
/**
242
* Create a mock compiler system
243
* @returns Mock CompilerSystem instance
244
*/
245
function mockCompilerSystem(): CompilerSystem;
246
247
/**
248
* Create a mock Stencil configuration
249
* @returns Mock Config instance
250
*/
251
function mockConfig(): Config;
252
253
/**
254
* Create a mock validated configuration
255
* @returns Mock ValidatedConfig instance
256
*/
257
function mockValidatedConfig(): ValidatedConfig;
258
259
/**
260
* Create a mock load config initialization
261
* @returns Mock LoadConfigInit instance
262
*/
263
function mockLoadConfigInit(): LoadConfigInit;
264
265
/**
266
* Create a mock logger
267
* @returns Mock Logger instance
268
*/
269
function mockLogger(): Logger;
270
271
/**
272
* Create a mock module
273
* @returns Mock module object
274
*/
275
function mockModule(): any;
276
277
/**
278
* Create a mock DOM document
279
* @returns Mock Document instance
280
*/
281
function mockDocument(): Document;
282
283
/**
284
* Create a mock DOM window
285
* @returns Mock Window instance
286
*/
287
function mockWindow(): Window;
288
```
289
290
**Usage Examples:**
291
292
```typescript
293
import { mockConfig, mockLogger, mockDocument } from '@stencil/core/testing';
294
295
describe('utility function', () => {
296
it('works with mock config', () => {
297
const config = mockConfig();
298
config.namespace = 'TestApp';
299
300
const result = processConfig(config);
301
expect(result.namespace).toBe('TestApp');
302
});
303
304
it('works with mock document', () => {
305
const doc = mockDocument();
306
const div = doc.createElement('div');
307
div.textContent = 'Hello';
308
309
expect(div.textContent).toBe('Hello');
310
});
311
});
312
```
313
314
### Mock Fetch API
315
316
Mock implementation of the Fetch API for testing HTTP requests.
317
318
```typescript { .api }
319
/**
320
* Mock fetch function for testing HTTP requests
321
* @param input - Request URL or Request object
322
* @param init - Request configuration options
323
* @returns Promise resolving to MockResponse
324
*/
325
function mockFetch(input: MockRequestInfo, init?: MockRequestInit): Promise<MockResponse>;
326
327
type MockRequestInfo = string | MockRequest;
328
329
interface MockRequestInit {
330
method?: string;
331
headers?: MockHeaders | Record<string, string>;
332
body?: string | FormData | URLSearchParams;
333
credentials?: 'omit' | 'same-origin' | 'include';
334
cache?: string;
335
redirect?: string;
336
referrer?: string;
337
integrity?: string;
338
}
339
340
class MockRequest {
341
constructor(input: MockRequestInfo, init?: MockRequestInit);
342
readonly method: string;
343
readonly url: string;
344
readonly headers: MockHeaders;
345
readonly body: string | null;
346
clone(): MockRequest;
347
text(): Promise<string>;
348
json(): Promise<any>;
349
}
350
351
class MockResponse {
352
constructor(body?: string, init?: MockResponseInit);
353
readonly status: number;
354
readonly statusText: string;
355
readonly headers: MockHeaders;
356
readonly ok: boolean;
357
readonly url: string;
358
clone(): MockResponse;
359
text(): Promise<string>;
360
json(): Promise<any>;
361
static json(object: any, init?: MockResponseInit): MockResponse;
362
}
363
364
interface MockResponseInit {
365
status?: number;
366
statusText?: string;
367
headers?: MockHeaders | Record<string, string>;
368
url?: string;
369
}
370
371
class MockHeaders {
372
constructor(init?: Record<string, string> | MockHeaders);
373
append(name: string, value: string): void;
374
delete(name: string): void;
375
get(name: string): string | null;
376
has(name: string): boolean;
377
set(name: string, value: string): void;
378
forEach(callback: (value: string, key: string) => void): void;
379
}
380
```
381
382
**Usage Examples:**
383
384
```typescript
385
import { mockFetch, MockResponse } from '@stencil/core/testing';
386
387
describe('API service', () => {
388
beforeEach(() => {
389
global.fetch = mockFetch;
390
});
391
392
it('handles successful response', async () => {
393
(fetch as any).mockResolvedValue(
394
new MockResponse(JSON.stringify({ id: 1, name: 'Test' }), {
395
status: 200,
396
headers: { 'Content-Type': 'application/json' }
397
})
398
);
399
400
const result = await apiService.getUser(1);
401
expect(result.name).toBe('Test');
402
});
403
404
it('handles error response', async () => {
405
(fetch as any).mockResolvedValue(
406
new MockResponse('Not found', { status: 404 })
407
);
408
409
await expect(apiService.getUser(999)).rejects.toThrow('User not found');
410
});
411
});
412
```
413
414
### Jest Integration
415
416
Functions for integrating Stencil with Jest testing framework.
417
418
```typescript { .api }
419
/**
420
* Get Jest Puppeteer environment factory
421
* @returns Jest environment factory function
422
*/
423
function getCreateJestPuppeteerEnvironment(): any;
424
425
/**
426
* Get Jest test runner factory
427
* @returns Jest test runner factory function
428
*/
429
function getCreateJestTestRunner(): any;
430
431
/**
432
* Get Jest preprocessor for Stencil files
433
* @returns Jest preprocessor configuration
434
*/
435
function getJestPreprocessor(): any;
436
437
/**
438
* Get Jest preset configuration for Stencil
439
* @returns Jest preset configuration object
440
*/
441
function getJestPreset(): any;
442
443
/**
444
* Get Jest setup test framework function
445
* @returns Jest setup function
446
*/
447
function getJestSetupTestFramework(): any;
448
```
449
450
### Testing Utilities
451
452
Additional utilities for test setup and execution.
453
454
```typescript { .api }
455
/**
456
* Transpile TypeScript code for testing
457
* @param code - TypeScript source code
458
* @param opts - Transpilation options
459
* @returns Transpiled JavaScript code
460
*/
461
function transpile(code: string, opts?: any): Promise<string>;
462
463
/**
464
* Create testing environment
465
* @param opts - Testing configuration options
466
* @returns Testing environment instance
467
*/
468
function createTesting(opts?: any): Testing;
469
470
interface Testing {
471
run(opts: TestingRunOptions): Promise<boolean>;
472
destroy(): Promise<void>;
473
}
474
475
interface TestingRunOptions {
476
e2e?: boolean;
477
screenshot?: boolean;
478
spec?: boolean;
479
updateScreenshot?: boolean;
480
}
481
482
/**
483
* Set up console mocking utilities
484
* @returns Console mocker instance
485
*/
486
function setupConsoleMocker(): any;
487
488
/**
489
* Shuffle array elements for randomized testing
490
* @param array - Array to shuffle
491
* @returns Shuffled array
492
*/
493
function shuffleArray<T>(array: T[]): T[];
494
495
/**
496
* Event spy for testing component events
497
*/
498
interface EventSpy {
499
eventName: string;
500
firstEvent: CustomEvent;
501
lastEvent: CustomEvent;
502
events: CustomEvent[];
503
called: boolean;
504
callCount: number;
505
}
506
```
507
508
**Usage Examples:**
509
510
```typescript
511
import { createTesting, transpile } from '@stencil/core/testing';
512
513
// Create testing environment
514
const testing = createTesting();
515
516
// Run specific test types
517
await testing.run({
518
spec: true,
519
e2e: false,
520
screenshot: false
521
});
522
523
// Transpile TypeScript for testing
524
const jsCode = await transpile(`
525
const x: number = 42;
526
console.log(x);
527
`);
528
```