Custom Cypress commands and utilities that encourage good testing practices by providing DOM Testing Library query methods for end-to-end tests
npx @tessl/cli install tessl/npm-testing-library--cypress@10.1.00
# Cypress Testing Library
1
2
Cypress Testing Library extends Cypress with DOM Testing Library query methods, providing simple and complete custom commands that encourage good testing practices. It enables developers to write tests that mirror how users interact with applications, focusing on accessibility and semantic HTML elements rather than implementation details.
3
4
## Package Information
5
6
- **Package Name**: @testing-library/cypress
7
- **Package Type**: npm
8
- **Language**: JavaScript with TypeScript definitions
9
- **Installation**: `npm install --save-dev @testing-library/cypress`
10
11
## Core Imports
12
13
To register all commands with Cypress:
14
15
```javascript
16
import '@testing-library/cypress/add-commands';
17
```
18
19
For configuration:
20
21
```javascript
22
import { configure } from '@testing-library/cypress';
23
```
24
25
CommonJS:
26
27
```javascript
28
require('@testing-library/cypress/add-commands');
29
```
30
31
## Basic Usage
32
33
```javascript
34
// Add to cypress/support/commands.js or cypress/support/e2e.js
35
import '@testing-library/cypress/add-commands';
36
37
// Use in tests
38
cy.findByText('Submit').click();
39
cy.findByLabelText('Email').type('user@example.com');
40
cy.findByRole('button', { name: 'Save' }).should('be.visible');
41
cy.findAllByTestId('product-card').should('have.length', 3);
42
43
// Configure DOM Testing Library options
44
cy.configureCypressTestingLibrary({
45
testIdAttribute: 'data-test-id'
46
});
47
```
48
49
## Architecture
50
51
Cypress Testing Library is built around several key concepts:
52
53
- **Automatic Command Generation**: All `find*` queries from @testing-library/dom are dynamically converted to Cypress commands
54
- **Semantic Queries**: Commands encourage testing based on how users interact with the UI (text, labels, roles) rather than implementation details
55
- **Cypress Integration**: Full integration with Cypress chaining, subjects, timeouts, and within() contexts
56
- **Error Preservation**: Meaningful error messages from DOM Testing Library are forwarded to Cypress
57
- **jQuery Compatibility**: Seamlessly handles both jQuery objects and DOM elements
58
59
## Capabilities
60
61
### Element Query Commands
62
63
All query commands support the same patterns: `findBy*` (single element) and `findAllBy*` (multiple elements). These commands automatically retry until elements are found or timeout occurs.
64
65
```javascript { .api }
66
// Text-based queries
67
findByText(id: Matcher, options?: SelectorMatcherOptions): Chainable<JQuery>;
68
findAllByText(id: Matcher, options?: SelectorMatcherOptions): Chainable<JQuery>;
69
70
// Label-based queries
71
findByLabelText(id: Matcher, options?: SelectorMatcherOptions): Chainable<JQuery>;
72
findAllByLabelText(id: Matcher, options?: SelectorMatcherOptions): Chainable<JQuery>;
73
74
// Placeholder queries
75
findByPlaceholderText(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
76
findAllByPlaceholderText(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
77
78
// Display value queries
79
findByDisplayValue(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
80
findAllByDisplayValue(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
81
82
// Alt text queries
83
findByAltText(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
84
findAllByAltText(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
85
86
// Title attribute queries
87
findByTitle(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
88
findAllByTitle(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
89
90
// Role-based queries
91
findByRole(id: ByRoleMatcher, options?: ByRoleOptions): Chainable<JQuery>;
92
findAllByRole(id: ByRoleMatcher, options?: ByRoleOptions): Chainable<JQuery>;
93
94
// Test ID queries
95
findByTestId(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
96
findAllByTestId(id: Matcher, options?: MatcherOptions): Chainable<JQuery>;
97
```
98
99
**Usage Examples:**
100
101
```javascript
102
// Text queries - find by visible text content
103
cy.findByText('Submit Form').click();
104
cy.findByText(/^Click here/i).should('be.visible');
105
cy.findAllByText('Delete').should('have.length', 3);
106
107
// Label queries - find form elements by their labels
108
cy.findByLabelText('Email Address').type('user@example.com');
109
cy.findByLabelText(/password/i).type('secret123');
110
cy.findAllByLabelText(/required/i).should('not.be.empty');
111
112
// Role queries - find by ARIA roles
113
cy.findByRole('button').click();
114
cy.findByRole('textbox', { name: /search/i }).type('query');
115
cy.findAllByRole('listitem').should('have.length.greaterThan', 0);
116
117
// Test ID queries - find by data-testid attributes
118
cy.findByTestId('login-form').should('be.visible');
119
cy.findAllByTestId(/^product-/i).should('have.length', 5);
120
121
// With options
122
cy.findByText('Loading...', { timeout: 10000 }).should('not.exist');
123
cy.findByText('Button', { container: cy.get('.modal') }).click();
124
```
125
126
### Configuration
127
128
Configure DOM Testing Library options through Cypress:
129
130
```javascript { .api }
131
/**
132
* Configure DOM Testing Library through Cypress
133
* @param config - Configuration options for DOM Testing Library
134
*/
135
configureCypressTestingLibrary(config: DTLConfiguration): Chainable<void>;
136
```
137
138
**Usage Examples:**
139
140
```javascript
141
// Change default test ID attribute
142
cy.configureCypressTestingLibrary({
143
testIdAttribute: 'data-test-id'
144
});
145
146
// Configure text normalization
147
cy.configureCypressTestingLibrary({
148
normalizer: getDefaultNormalizer({
149
trim: true,
150
collapseWhitespace: true
151
})
152
});
153
154
// Configure default hidden behavior
155
cy.configureCypressTestingLibrary({
156
defaultHidden: true
157
});
158
```
159
160
### Programmatic Configuration
161
162
Configure DOM Testing Library outside of tests:
163
164
```javascript { .api }
165
/**
166
* Configure DOM Testing Library options
167
* @param config - Configuration options
168
* @returns Configuration object
169
*/
170
function configure(config: DTLConfiguration): DTLConfiguration;
171
```
172
173
**Usage Examples:**
174
175
```javascript
176
import { configure } from '@testing-library/cypress';
177
178
// In cypress/support/e2e.js
179
configure({
180
testIdAttribute: 'data-test-id',
181
asyncUtilTimeout: 5000
182
});
183
```
184
185
### Advanced Usage Patterns
186
187
**Chaining with Previous Subjects:**
188
189
```javascript
190
// Find within a specific container
191
cy.get('.sidebar').findByText('Settings').click();
192
193
// Use within() for scoping
194
cy.get('.modal').within(() => {
195
cy.findByLabelText('Name').type('John Doe');
196
cy.findByRole('button', { name: 'Save' }).click();
197
});
198
199
// Container option
200
cy.get('.product-list').then($container => {
201
cy.findByText('Add to Cart', { container: $container }).click();
202
});
203
```
204
205
**Error Handling:**
206
207
```javascript
208
// Check for non-existence
209
cy.findByText('Error Message').should('not.exist');
210
211
// Handle multiple matches (findBy* commands will fail)
212
cy.findAllByText('Delete').should('have.length', 1);
213
214
// Timeout configuration
215
cy.findByText('Loading Complete', { timeout: 30000 }).should('exist');
216
```
217
218
## Types
219
220
```javascript { .api }
221
// Matcher types (from @testing-library/dom)
222
type Matcher = string | RegExp | ((content: string, element?: Element) => boolean);
223
type ByRoleMatcher = string;
224
225
// Cypress Testing Library specific options
226
interface CTLMatcherOptions extends Partial<Cypress.Timeoutable>, Partial<Cypress.Loggable> {
227
/** Container element to search within */
228
container?: Element | JQuery<Element>;
229
}
230
231
// Combined option types
232
type MatcherOptions = DTLMatcherOptions | CTLMatcherOptions;
233
type SelectorMatcherOptions = DTLSelectorMatcherOptions | CTLMatcherOptions;
234
type ByRoleOptions = DTLByRoleOptions | CTLMatcherOptions;
235
236
// DOM Testing Library configuration
237
interface DTLConfiguration {
238
/** Attribute used for test IDs (default: 'data-testid') */
239
testIdAttribute?: string;
240
/** Default timeout for async utilities */
241
asyncUtilTimeout?: number;
242
/** Text normalizer function */
243
normalizer?: (text: string) => string;
244
/** Default hidden element behavior */
245
defaultHidden?: boolean;
246
/** Custom get error message function */
247
getElementError?: (message: string | null, container: HTMLElement) => Error;
248
}
249
250
// Cypress command return type
251
type Chainable<T> = Cypress.Chainable<T>;
252
```
253
254
## Key Differences from DOM Testing Library
255
256
1. **No `query*` or `get*` commands**: Only `find*` and `findAllBy*` commands are available
257
2. **Cypress retry logic**: Commands automatically retry using Cypress' built-in retryability
258
3. **jQuery compatibility**: Handles both jQuery objects and DOM elements seamlessly
259
4. **Multiple element handling**: `findAllBy*` commands can return multiple elements (unlike DOM Testing Library's `getBy*`)
260
5. **Error forwarding**: DOM Testing Library error messages are preserved and forwarded to Cypress
261
6. **Container support**: All commands support a `container` option for scoping queries
262
7. **Timeout support**: All commands respect Cypress timeout options
263
264
## Best Practices
265
266
- Use `findBy*` when expecting exactly one element (will fail if multiple found)
267
- Use `findAllBy*` when expecting one or more elements
268
- Prefer semantic queries (`findByRole`, `findByLabelText`) over test IDs when possible
269
- Use `should('not.exist')` instead of `query*` commands to check for element absence
270
- Configure `testIdAttribute` consistently across your application
271
- Use `container` option or `within()` to scope queries to specific sections
272
- Leverage meaningful error messages by using descriptive matcher patterns