0
# Browser Environment
1
2
The Web Component Tester browser environment provides a comprehensive client-side testing runtime with pre-loaded testing libraries and web component-specific utilities.
3
4
## Capabilities
5
6
### Global WCT Object
7
8
The main browser-side API exposed through the global `WCT` object.
9
10
```javascript { .api }
11
/**
12
* Global WCT object providing browser-side testing functionality
13
*/
14
interface WCT {
15
/** Shared object for data between test suites */
16
share: any;
17
/** Load and run test suites from files */
18
loadSuites(files: string[]): void;
19
/** Current browser configuration */
20
_config: Config;
21
/** Current test reporter instance */
22
_reporter: any;
23
/** Child runner constructor for nested tests */
24
_ChildRunner: typeof ChildRunner;
25
}
26
```
27
28
**Usage Examples:**
29
30
```javascript
31
// Load test suites dynamically
32
WCT.loadSuites([
33
'test/unit-tests.js',
34
'test/integration-tests.html'
35
]);
36
37
// Share data between test suites
38
WCT.share.testData = { userId: 123, apiKey: 'test-key' };
39
40
// Access shared data in tests
41
suite('API Tests', function() {
42
test('uses shared data', function() {
43
assert.equal(WCT.share.testData.userId, 123);
44
});
45
});
46
```
47
48
### Helper Functions
49
50
Web component-specific testing utilities available globally in the browser.
51
52
```javascript { .api }
53
/**
54
* Safely execute a test step with error handling
55
* @param callback - Node-style callback function
56
* @param stepFn - Function to execute safely
57
*/
58
function safeStep(callback: (error?: any) => void, stepFn: () => void): void;
59
60
/**
61
* Run test at declaration time (before Mocha starts)
62
* @param name - Test name
63
* @param testFn - Test function (sync or async)
64
*/
65
function testImmediate(name: string, testFn: Function): void;
66
67
/**
68
* Async-only variant of testImmediate
69
* @param name - Test name
70
* @param testFn - Async test function
71
*/
72
function testImmediateAsync(name: string, testFn: Function): void;
73
74
/**
75
* Trigger flush of pending events, observations, and DOM updates
76
* @param callback - Function to call after flush completes
77
*/
78
function flush(callback: () => void): void;
79
80
/**
81
* Advance a single animation frame with flush
82
* @param callback - Function to call after animation frame
83
*/
84
function animationFrameFlush(callback: () => void): void;
85
86
/**
87
* Wait for a condition to be met with timeout
88
* @param fn - Function to test (should throw if condition not met)
89
* @param next - Function to call when condition is met
90
* @param intervalOrMutationEl - Polling interval or mutation element
91
* @param timeout - Maximum wait time in milliseconds
92
* @param timeoutTime - Internal parameter (calculated automatically)
93
*/
94
function waitFor(
95
fn: () => void,
96
next: () => void,
97
intervalOrMutationEl?: number | MutationEl,
98
timeout?: number,
99
timeoutTime?: number
100
): void;
101
```
102
103
**Usage Examples:**
104
105
```javascript
106
// Safe step execution
107
test('handles async operations', function(done) {
108
safeStep(done, function() {
109
// This code is wrapped in try/catch
110
myAsyncOperation().then(function(result) {
111
assert.equal(result.status, 'success');
112
});
113
});
114
});
115
116
// Immediate test execution
117
testImmediate('runs before Mocha setup', function() {
118
// This runs at page load time
119
assert.isTrue(document.readyState !== 'loading');
120
});
121
122
// DOM flush utility
123
test('waits for DOM updates', function(done) {
124
element.someProperty = 'new value';
125
126
flush(function() {
127
// DOM is now updated
128
assert.equal(element.textContent, 'new value');
129
done();
130
});
131
});
132
133
// Animation frame utility
134
test('waits for animations', function(done) {
135
element.classList.add('animate');
136
137
animationFrameFlush(function() {
138
// Animation frame has completed
139
assert.isTrue(element.classList.contains('animated'));
140
done();
141
});
142
});
143
144
// Wait for condition
145
test('waits for condition', function(done) {
146
let ready = false;
147
148
setTimeout(() => ready = true, 500);
149
150
waitFor(
151
function() {
152
if (!ready) throw new Error('Not ready yet');
153
},
154
function() {
155
assert.isTrue(ready);
156
done();
157
},
158
50, // Check every 50ms
159
1000 // Timeout after 1 second
160
);
161
});
162
```
163
164
### Browser Configuration
165
166
Client-side configuration interface for customizing the browser environment.
167
168
```javascript { .api }
169
interface Config {
170
/** Scripts to load before WCT starts */
171
environmentScripts: string[];
172
/** HTML imports to load */
173
environmentImports: string[];
174
/** Absolute root for client scripts */
175
root: string | null;
176
/** Wait for web component frameworks to load */
177
waitForFrameworks: boolean;
178
/** Custom wait function */
179
waitFor: Function | null;
180
/** Maximum concurrent HTML suites */
181
numConcurrentSuites: number;
182
/** Treat console.error as test failure */
183
trackConsoleError: boolean;
184
/** Mocha configuration options */
185
mochaOptions: MochaSetupOptions;
186
/** Enable debug logging */
187
verbose: boolean;
188
}
189
190
/**
191
* Setup browser configuration
192
* @param options - Configuration options to merge
193
*/
194
function setup(options: Partial<Config>): void;
195
196
/**
197
* Get configuration value
198
* @param key - Configuration key
199
* @returns Configuration value
200
*/
201
function get<K extends keyof Config>(key: K): Config[K];
202
```
203
204
**Usage Examples:**
205
206
```html
207
<script>
208
// Configure before loading browser.js
209
WCT = {
210
environmentScripts: [
211
'custom-assertion-library.js',
212
'test-utilities.js'
213
],
214
waitForFrameworks: true,
215
mochaOptions: {
216
timeout: 30000,
217
ui: 'bdd'
218
},
219
verbose: true
220
};
221
</script>
222
<script src="../web-component-tester/browser.js"></script>
223
```
224
225
### Test Fixture Integration
226
227
Integration with `@polymer/test-fixture` for DOM state management.
228
229
```javascript { .api }
230
/**
231
* Create DOM fixture from template
232
* @param id - Fixture template ID
233
* @returns Created DOM element(s)
234
*/
235
function fixture(id: string): Element | DocumentFragment;
236
```
237
238
**Usage Examples:**
239
240
```html
241
<test-fixture id="basic">
242
<template>
243
<my-element foo="bar"></my-element>
244
</template>
245
</test-fixture>
246
247
<test-fixture id="multiple">
248
<template>
249
<div>First</div>
250
<div>Second</div>
251
</template>
252
</test-fixture>
253
254
<script>
255
suite('<my-element>', function() {
256
let element;
257
258
setup(function() {
259
element = fixture('basic');
260
});
261
262
test('has initial properties', function() {
263
assert.equal(element.foo, 'bar');
264
});
265
266
test('handles multiple elements', function() {
267
const elements = fixture('multiple');
268
assert.equal(elements.length, 2);
269
});
270
});
271
</script>
272
```
273
274
### Accessibility Testing
275
276
Integration with accessibility-developer-tools for automated accessibility testing.
277
278
```javascript { .api }
279
/**
280
* Run accessibility test suite on a fixture
281
* @param fixtureId - ID of test fixture to test
282
* @param ignoredTests - Array of test names to ignore (optional)
283
* @param beforeEach - Function to run before each test (optional)
284
*/
285
function a11ySuite(
286
fixtureId: string,
287
ignoredTests?: string[],
288
beforeEach?: Function
289
): void;
290
```
291
292
**Usage Examples:**
293
294
```html
295
<test-fixture id="basic-button">
296
<template>
297
<paper-button>Click me</paper-button>
298
</template>
299
</test-fixture>
300
301
<test-fixture id="form-elements">
302
<template>
303
<paper-input label="Name"></paper-input>
304
<paper-button>Submit</paper-button>
305
</template>
306
</test-fixture>
307
308
<script>
309
// Basic accessibility testing
310
a11ySuite('basic-button');
311
312
// Ignore specific tests
313
a11ySuite('form-elements', [
314
'AX_COLOR_01', // Skip color contrast test
315
'AX_FOCUS_02' // Skip focus management test
316
]);
317
318
// Custom setup before each accessibility test
319
a11ySuite('form-elements', [], function() {
320
// Setup test state
321
fixture('form-elements').querySelector('paper-input').value = 'Test';
322
});
323
</script>
324
```
325
326
### Suite Loading
327
328
Dynamic test suite loading functionality.
329
330
```javascript { .api }
331
/**
332
* Load and execute test suites from file URLs
333
* @param files - Array of test file URLs (.js or .html)
334
*/
335
function loadSuites(files: string[]): void;
336
```
337
338
**Usage Examples:**
339
340
```html
341
<!doctype html>
342
<html>
343
<head>
344
<script src="../web-component-tester/browser.js"></script>
345
</head>
346
<body>
347
<script>
348
// Load multiple test suites
349
WCT.loadSuites([
350
'unit/element-tests.html',
351
'unit/behavior-tests.js',
352
'integration/full-tests.html'
353
]);
354
</script>
355
</body>
356
</html>
357
```
358
359
## Pre-loaded Testing Libraries
360
361
The browser environment automatically loads these testing libraries:
362
363
### Mocha
364
- **TDD Interface**: `suite()`, `test()`, `setup()`, `teardown()`
365
- **BDD Interface**: `describe()`, `it()`, `before()`, `after()`, `beforeEach()`, `afterEach()`
366
367
### Chai
368
- **Expect Interface**: `expect(value).to.equal(expected)`
369
- **Assert Interface**: `assert.equal(actual, expected)`
370
371
### Sinon
372
- **Spies**: `sinon.spy()`, `sinon.stub()`
373
- **Mocks**: `sinon.mock(object)`
374
- **Fake Timers**: `sinon.useFakeTimers()`
375
376
### Sinon-Chai
377
- **Chai Assertions for Sinon**: `expect(spy).to.have.been.called`
378
379
### Additional Libraries
380
- **Lodash**: Utility functions (`_.forEach`, `_.map`, etc.)
381
- **Async**: Async utilities (`async.parallel`, `async.series`)
382
- **Stacky**: Stack trace formatting
383
384
## Types
385
386
```javascript { .api }
387
interface MutationEl {
388
onMutation(mutationEl: this, cb: () => void): void;
389
}
390
391
interface MochaSetupOptions {
392
ui?: string;
393
timeout?: number;
394
slow?: number;
395
bail?: boolean;
396
grep?: string | RegExp;
397
}
398
```