0
# Configuration
1
2
Configuration system for customizing DOM Testing Library behavior, timeouts, error handling, and debugging features. Allows global configuration of library defaults and behavior patterns.
3
4
## Capabilities
5
6
### Configuration Management
7
8
Configure global library behavior and settings.
9
10
```typescript { .api }
11
function configure(configDelta: ConfigFn | Partial<Config>): void;
12
13
function getConfig(): Config;
14
15
interface Config {
16
/** Attribute name for test IDs (default: "data-testid") */
17
testIdAttribute: string;
18
19
/** Wrapper function for async utilities */
20
asyncWrapper(cb: (...args: any[]) => any): Promise<any>;
21
22
/** Wrapper function for event handlers */
23
eventWrapper(cb: (...args: any[]) => any): void;
24
25
/** Default timeout for async utilities in milliseconds (default: 1000) */
26
asyncUtilTimeout: number;
27
28
/** Whether computed styles support pseudo-elements (default: false) */
29
computedStyleSupportsPseudoElements: boolean;
30
31
/** Default value for hidden option in queries (default: false) */
32
defaultHidden: boolean;
33
34
/** Default value for ignore option in ByText queries */
35
defaultIgnore: string;
36
37
/** Whether to show original stack traces in errors (default: false) */
38
showOriginalStackTrace: boolean;
39
40
/** Whether to throw suggestion errors (default: false) */
41
throwSuggestions: boolean;
42
43
/** Custom error generator for element not found errors */
44
getElementError: (message: string | null, container: Element) => Error;
45
46
/** UNSTABLE: Wrapper for timer advancement in fake timer scenarios */
47
unstable_advanceTimersWrapper(cb: (...args: unknown[]) => unknown): unknown;
48
}
49
50
type ConfigFn = (existingConfig: Config) => Partial<Config>;
51
```
52
53
**Usage Examples:**
54
55
```typescript
56
import { configure, getConfig } from "@testing-library/dom";
57
58
// Basic configuration
59
configure({
60
testIdAttribute: 'data-cy', // Use Cypress convention
61
asyncUtilTimeout: 5000, // Increase default timeout
62
defaultHidden: true, // Include hidden elements by default
63
});
64
65
// Function-based configuration
66
configure((existingConfig) => ({
67
asyncUtilTimeout: existingConfig.asyncUtilTimeout * 2, // Double current timeout
68
defaultIgnore: 'script, style, svg', // Ignore more elements
69
}));
70
71
// Get current configuration
72
const currentConfig = getConfig();
73
console.log('Current testId attribute:', currentConfig.testIdAttribute);
74
console.log('Current timeout:', currentConfig.asyncUtilTimeout);
75
76
// Custom async wrapper for testing framework integration
77
configure({
78
asyncWrapper: async (cb) => {
79
// Add custom async handling, logging, etc.
80
console.log('Starting async operation');
81
try {
82
const result = await cb();
83
console.log('Async operation completed');
84
return result;
85
} catch (error) {
86
console.log('Async operation failed:', error);
87
throw error;
88
}
89
},
90
});
91
92
// Custom event wrapper
93
configure({
94
eventWrapper: (cb) => {
95
// Wrap all event handlers
96
try {
97
cb();
98
} catch (error) {
99
console.log('Event handler error:', error);
100
throw error;
101
}
102
},
103
});
104
105
// Enhanced error reporting
106
configure({
107
showOriginalStackTrace: true,
108
getElementError: (message, container) => {
109
// Custom error with additional context
110
const error = new Error(message || 'Element not found');
111
error.name = 'TestingLibraryElementError';
112
113
// Add container information
114
if (container) {
115
error.container = container;
116
error.containerHTML = container.innerHTML;
117
}
118
119
return error;
120
},
121
});
122
123
// Framework-specific configuration
124
// For Jest
125
configure({
126
asyncWrapper: async (cb) => {
127
// Integrate with Jest's async handling
128
return cb();
129
},
130
});
131
132
// For testing with fake timers
133
configure({
134
unstable_advanceTimersWrapper: (cb) => {
135
const originalSetTimeout = global.setTimeout;
136
// Custom timer handling logic
137
return cb();
138
},
139
});
140
```
141
142
### Test ID Configuration
143
144
Customize the attribute used for test IDs.
145
146
```typescript
147
// Default configuration (data-testid)
148
const element = getByTestId(container, 'submit-button');
149
// Looks for: <button data-testid="submit-button">
150
151
// Configure for Cypress convention
152
configure({ testIdAttribute: 'data-cy' });
153
const element = getByTestId(container, 'submit-button');
154
// Now looks for: <button data-cy="submit-button">
155
156
// Configure for custom attribute
157
configure({ testIdAttribute: 'test-id' });
158
const element = getByTestId(container, 'submit-button');
159
// Now looks for: <button test-id="submit-button">
160
161
// Multiple environment setup
162
if (process.env.E2E_FRAMEWORK === 'cypress') {
163
configure({ testIdAttribute: 'data-cy' });
164
} else if (process.env.E2E_FRAMEWORK === 'playwright') {
165
configure({ testIdAttribute: 'data-pw' });
166
} else {
167
configure({ testIdAttribute: 'data-testid' });
168
}
169
```
170
171
### Timeout Configuration
172
173
Adjust default timeouts for async operations.
174
175
```typescript
176
// Increase timeout for slower CI environments
177
if (process.env.CI) {
178
configure({ asyncUtilTimeout: 10000 }); // 10 seconds
179
} else {
180
configure({ asyncUtilTimeout: 3000 }); // 3 seconds for local
181
}
182
183
// Per-test timeout override
184
await waitFor(() => {
185
expect(getByText(container, "Slow operation complete")).toBeInTheDocument();
186
}, { timeout: 15000 }); // Override global setting
187
188
// Get current timeout
189
const config = getConfig();
190
console.log(`Current timeout: ${config.asyncUtilTimeout}ms`);
191
```
192
193
### Debug Configuration
194
195
Control debugging and error reporting behavior.
196
197
```typescript
198
// Enable detailed error messages
199
configure({
200
showOriginalStackTrace: true,
201
throwSuggestions: true, // Throw errors for better queries
202
});
203
204
// Custom error handling
205
configure({
206
getElementError: (message, container) => {
207
const error = new Error(message);
208
209
// Add debugging information
210
if (container) {
211
error.debugInfo = {
212
containerTag: container.tagName,
213
containerClass: container.className,
214
containerChildren: container.children.length,
215
availableText: container.textContent?.slice(0, 100),
216
};
217
}
218
219
return error;
220
},
221
});
222
223
// Development vs production configuration
224
if (process.env.NODE_ENV === 'development') {
225
configure({
226
showOriginalStackTrace: true,
227
throwSuggestions: true,
228
});
229
} else {
230
configure({
231
showOriginalStackTrace: false,
232
throwSuggestions: false,
233
});
234
}
235
```
236
237
### Framework Integration
238
239
Configure for specific testing frameworks and environments.
240
241
```typescript
242
// React Testing Library integration
243
configure({
244
asyncWrapper: async (cb) => {
245
// React-specific async handling
246
return cb();
247
},
248
eventWrapper: (cb) => {
249
// React event handling
250
act(() => {
251
cb();
252
});
253
},
254
});
255
256
// Vue Testing Library integration
257
configure({
258
asyncWrapper: async (cb) => {
259
await nextTick();
260
return cb();
261
},
262
});
263
264
// Angular Testing Library integration
265
configure({
266
asyncWrapper: async (cb) => {
267
await fixture.whenStable();
268
return cb();
269
},
270
});
271
272
// JSDOM environment configuration
273
configure({
274
computedStyleSupportsPseudoElements: false, // JSDOM limitation
275
});
276
277
// Real browser environment
278
configure({
279
computedStyleSupportsPseudoElements: true,
280
});
281
```
282
283
### Accessibility Configuration
284
285
Configure accessibility-related behavior.
286
287
```typescript
288
// Include hidden elements by default for accessibility testing
289
configure({
290
defaultHidden: true,
291
});
292
293
// Now queries include hidden elements unless explicitly excluded
294
const hiddenButton = getByRole(container, 'button'); // Includes hidden buttons
295
const visibleButton = getByRole(container, 'button', { hidden: false }); // Explicit override
296
297
// Configure text matching to ignore certain elements
298
configure({
299
defaultIgnore: 'script, style, svg, [aria-hidden="true"]',
300
});
301
302
// Text queries now ignore these elements by default
303
const text = getByText(container, 'Content'); // Ignores text in <script>, <style>, etc.
304
```
305
306
### Advanced Configuration
307
308
Complex configuration patterns for specific use cases.
309
310
```typescript
311
// Multi-environment configuration
312
const configureForEnvironment = () => {
313
const baseConfig = {
314
showOriginalStackTrace: process.env.NODE_ENV === 'development',
315
throwSuggestions: process.env.NODE_ENV === 'development',
316
};
317
318
if (process.env.TEST_ENV === 'ci') {
319
return {
320
...baseConfig,
321
asyncUtilTimeout: 10000,
322
defaultIgnore: 'script, style, svg, noscript',
323
};
324
}
325
326
if (process.env.TEST_ENV === 'accessibility') {
327
return {
328
...baseConfig,
329
defaultHidden: true,
330
throwSuggestions: true,
331
};
332
}
333
334
return baseConfig;
335
};
336
337
configure(configureForEnvironment());
338
339
// Conditional configuration
340
configure((existingConfig) => {
341
const updates = {};
342
343
// Increase timeout for slow tests
344
if (process.env.SLOW_TESTS) {
345
updates.asyncUtilTimeout = existingConfig.asyncUtilTimeout * 3;
346
}
347
348
// Custom test ID for specific test suites
349
if (process.env.TEST_SUITE === 'e2e') {
350
updates.testIdAttribute = 'data-e2e';
351
}
352
353
return updates;
354
});
355
356
// Restore configuration
357
const originalConfig = getConfig();
358
359
// Temporarily change config
360
configure({ asyncUtilTimeout: 500 });
361
362
// ... run tests ...
363
364
// Restore
365
configure(originalConfig);
366
```
367
368
## Configuration Best Practices
369
370
### Global Setup
371
372
```typescript
373
// test-setup.js
374
import { configure } from '@testing-library/dom';
375
376
// Global configuration for all tests
377
configure({
378
testIdAttribute: 'data-testid',
379
asyncUtilTimeout: process.env.CI ? 10000 : 5000,
380
showOriginalStackTrace: process.env.NODE_ENV === 'development',
381
throwSuggestions: process.env.NODE_ENV === 'development',
382
defaultIgnore: 'script, style, svg',
383
});
384
```
385
386
### Per-Test Configuration
387
388
```typescript
389
// Individual test file
390
import { configure, getConfig } from '@testing-library/dom';
391
392
describe('Slow operations', () => {
393
let originalConfig;
394
395
beforeAll(() => {
396
originalConfig = getConfig();
397
configure({ asyncUtilTimeout: 15000 });
398
});
399
400
afterAll(() => {
401
configure(originalConfig);
402
});
403
404
test('handles slow async operation', async () => {
405
// Tests run with increased timeout
406
});
407
});
408
```
409
410
### Environment Detection
411
412
```typescript
413
// config/testing-library.js
414
import { configure } from '@testing-library/dom';
415
416
const isCI = process.env.CI === 'true';
417
const isDevelopment = process.env.NODE_ENV === 'development';
418
const isJSDOM = typeof window !== 'undefined' && !window.navigator.userAgent.includes('Chrome');
419
420
configure({
421
asyncUtilTimeout: isCI ? 10000 : 5000,
422
showOriginalStackTrace: isDevelopment,
423
throwSuggestions: isDevelopment,
424
computedStyleSupportsPseudoElements: !isJSDOM,
425
defaultHidden: false,
426
testIdAttribute: 'data-testid',
427
});
428
```
429
430
## Types
431
432
```typescript { .api }
433
interface Config {
434
testIdAttribute: string;
435
unstable_advanceTimersWrapper(cb: (...args: unknown[]) => unknown): unknown;
436
asyncWrapper(cb: (...args: any[]) => any): Promise<any>;
437
eventWrapper(cb: (...args: any[]) => any): void;
438
asyncUtilTimeout: number;
439
computedStyleSupportsPseudoElements: boolean;
440
defaultHidden: boolean;
441
defaultIgnore: string;
442
showOriginalStackTrace: boolean;
443
throwSuggestions: boolean;
444
getElementError: (message: string | null, container: Element) => Error;
445
}
446
447
interface ConfigFn {
448
(existingConfig: Config): Partial<Config>;
449
}
450
```