1 | <div align="center">
|
2 | <h1>jest-dom</h1>
|
3 |
|
4 | <a href="https://www.emojione.com/emoji/1f989">
|
5 | <img
|
6 | height="80"
|
7 | width="80"
|
8 | alt="owl"
|
9 | src="https://raw.githubusercontent.com/testing-library/jest-dom/master/other/owl.png"
|
10 | />
|
11 | </a>
|
12 |
|
13 | <p>Custom jest matchers to test the state of the DOM</p>
|
14 |
|
15 | </div>
|
16 |
|
17 | ---
|
18 |
|
19 | [![Build Status][build-badge]][build]
|
20 | [![Code Coverage][coverage-badge]][coverage]
|
21 | [![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends]
|
22 | [![MIT License][license-badge]][license]
|
23 |
|
24 | [![All Contributors](https://img.shields.io/badge/all_contributors-28-orange.svg?style=flat-square)](#contributors-)
|
25 | [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc]
|
26 | [![Discord][discord-badge]][discord]
|
27 |
|
28 | [![Watch on GitHub][github-watch-badge]][github-watch]
|
29 | [![Star on GitHub][github-star-badge]][github-star]
|
30 | [![Tweet][twitter-badge]][twitter]
|
31 |
|
32 | ## The problem
|
33 |
|
34 | You want to use [jest][] to write tests that assert various things about the
|
35 | state of a DOM. As part of that goal, you want to avoid all the repetitive
|
36 | patterns that arise in doing so. Checking for an element's attributes, its text
|
37 | content, its css classes, you name it.
|
38 |
|
39 | ## This solution
|
40 |
|
41 | The `@testing-library/jest-dom` library provides a set of custom jest matchers
|
42 | that you can use to extend jest. These will make your tests more declarative,
|
43 | clear to read and to maintain.
|
44 |
|
45 | ## Table of Contents
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | - [Installation](#installation)
|
51 | - [Usage](#usage)
|
52 | - [Custom matchers](#custom-matchers)
|
53 | - [`toBeDisabled`](#tobedisabled)
|
54 | - [`toBeEnabled`](#tobeenabled)
|
55 | - [`toBeEmpty`](#tobeempty)
|
56 | - [`toBeEmptyDOMElement`](#tobeemptydomelement)
|
57 | - [`toBeInTheDocument`](#tobeinthedocument)
|
58 | - [`toBeInvalid`](#tobeinvalid)
|
59 | - [`toBeRequired`](#toberequired)
|
60 | - [`toBeValid`](#tobevalid)
|
61 | - [`toBeVisible`](#tobevisible)
|
62 | - [`toContainElement`](#tocontainelement)
|
63 | - [`toContainHTML`](#tocontainhtml)
|
64 | - [`toHaveAttribute`](#tohaveattribute)
|
65 | - [`toHaveClass`](#tohaveclass)
|
66 | - [`toHaveFocus`](#tohavefocus)
|
67 | - [`toHaveFormValues`](#tohaveformvalues)
|
68 | - [`toHaveStyle`](#tohavestyle)
|
69 | - [`toHaveTextContent`](#tohavetextcontent)
|
70 | - [`toHaveValue`](#tohavevalue)
|
71 | - [`toHaveDisplayValue`](#tohavedisplayvalue)
|
72 | - [`toBeChecked`](#tobechecked)
|
73 | - [`toBePartiallyChecked`](#tobepartiallychecked)
|
74 | - [`toHaveDescription`](#tohavedescription)
|
75 | - [Deprecated matchers](#deprecated-matchers)
|
76 | - [`toBeInTheDOM`](#tobeinthedom)
|
77 | - [Inspiration](#inspiration)
|
78 | - [Other Solutions](#other-solutions)
|
79 | - [Guiding Principles](#guiding-principles)
|
80 | - [Contributors](#contributors)
|
81 | - [LICENSE](#license)
|
82 |
|
83 |
|
84 |
|
85 | ## Installation
|
86 |
|
87 | This module is distributed via [npm][npm] which is bundled with [node][node] and
|
88 | should be installed as one of your project's `devDependencies`:
|
89 |
|
90 | ```
|
91 | npm install --save-dev @testing-library/jest-dom
|
92 | ```
|
93 |
|
94 | or
|
95 |
|
96 | for installation with [yarn](https://yarnpkg.com/) package manager.
|
97 |
|
98 | ```
|
99 | yarn add --dev @testing-library/jest-dom
|
100 | ```
|
101 |
|
102 | > Note: We also recommend installing the jest-dom eslint plugin which provides
|
103 | > auto-fixable lint rules that prevent false positive tests and improve test
|
104 | > readability by ensuring you are using the right matchers in your tests. More
|
105 | > details can be found at
|
106 | > [eslint-plugin-jest-dom](https://github.com/testing-library/eslint-plugin-jest-dom).
|
107 |
|
108 | ## Usage
|
109 |
|
110 | Import `@testing-library/jest-dom` once (for instance in your [tests setup
|
111 | file][]) and you're good to go:
|
112 |
|
113 | [tests setup file]:
|
114 | https://jestjs.io/docs/en/configuration.html#setupfilesafterenv-array
|
115 |
|
116 | ```javascript
|
117 | import '@testing-library/jest-dom'
|
118 | ```
|
119 |
|
120 | > Note: If you're using TypeScript, make sure your setup file is a `.ts` and not
|
121 | > a `.js` to include the necessary types.
|
122 |
|
123 | Alternatively, you can selectively import only the matchers you intend to use,
|
124 | and extend jest's `expect` yourself:
|
125 |
|
126 | ```javascript
|
127 | import {
|
128 | toBeInTheDocument,
|
129 | toHaveClass,
|
130 | } from '@testing-library/jest-dom/matchers'
|
131 |
|
132 | expect.extend({toBeInTheDocument, toHaveClass})
|
133 | ```
|
134 |
|
135 | > Note: when using TypeScript, this way of importing matchers won't provide the
|
136 | > necessary type definitions. More on this
|
137 | > [here](https://github.com/testing-library/jest-dom/pull/11#issuecomment-387817459).
|
138 |
|
139 | ## Custom matchers
|
140 |
|
141 | `@testing-library/jest-dom` can work with any library or framework that returns
|
142 | DOM elements from queries. The custom matcher examples below are written using
|
143 | matchers from `@testing-library`'s suite of libraries (e.g. `getByTestId`,
|
144 | `queryByTestId`, `getByText`, etc.)
|
145 |
|
146 | ### `toBeDisabled`
|
147 |
|
148 | ```typescript
|
149 | toBeDisabled()
|
150 | ```
|
151 |
|
152 | This allows you to check whether an element is disabled from the user's
|
153 | perspective.
|
154 |
|
155 | It matches if the element is a form control and the `disabled` attribute is
|
156 | specified on this element or the element is a descendant of a form element with
|
157 | a `disabled` attribute.
|
158 |
|
159 | According to the specification, the following elements can be
|
160 | [actually disabled](https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements):
|
161 | `button`, `input`, `select`, `textarea`, `optgroup`, `option`, `fieldset`.
|
162 |
|
163 | #### Examples
|
164 |
|
165 | ```html
|
166 | <button data-testid="button" type="submit" disabled>submit</button>
|
167 | <fieldset disabled><input type="text" data-testid="input" /></fieldset>
|
168 | <a href="..." disabled>link</a>
|
169 | ```
|
170 |
|
171 | ```javascript
|
172 | expect(getByTestId('button')).toBeDisabled()
|
173 | expect(getByTestId('input')).toBeDisabled()
|
174 | expect(getByText('link')).not.toBeDisabled()
|
175 | ```
|
176 |
|
177 | <hr />
|
178 |
|
179 | ### `toBeEnabled`
|
180 |
|
181 | ```typescript
|
182 | toBeEnabled()
|
183 | ```
|
184 |
|
185 | This allows you to check whether an element is not disabled from the user's
|
186 | perspective.
|
187 |
|
188 | It works like `not.toBeDisabled()`. Use this matcher to avoid double negation in
|
189 | your tests.
|
190 |
|
191 | <hr />
|
192 |
|
193 | ### `toBeEmpty`
|
194 |
|
195 | ```typescript
|
196 | toBeEmpty()
|
197 | ```
|
198 |
|
199 | This allows you to assert whether an element has content or not.
|
200 |
|
201 | #### Examples
|
202 |
|
203 | ```html
|
204 | <span data-testid="not-empty"><span data-testid="empty"></span></span>
|
205 | ```
|
206 |
|
207 | ```javascript
|
208 | expect(getByTestId('empty')).toBeEmpty()
|
209 | expect(getByTestId('not-empty')).not.toBeEmpty()
|
210 | ```
|
211 |
|
212 | > Note: This matcher is being deprecated due to a name clash with
|
213 | > `jest-extended`. See more info in #216. In the future, please use only:
|
214 | > [`toBeEmptyDOMElement`](#toBeEmptyDOMElement)
|
215 |
|
216 | <hr />
|
217 |
|
218 | ### `toBeEmptyDOMElement`
|
219 |
|
220 | ```typescript
|
221 | toBeEmptyDOMElement()
|
222 | ```
|
223 |
|
224 | This allows you to assert whether an element has content or not.
|
225 |
|
226 | #### Examples
|
227 |
|
228 | ```html
|
229 | <span data-testid="not-empty"><span data-testid="empty"></span></span>
|
230 | ```
|
231 |
|
232 | ```javascript
|
233 | expect(getByTestId('empty')).toBeEmptyDOMElement()
|
234 | expect(getByTestId('not-empty')).not.toBeEmptyDOMElement()
|
235 | ```
|
236 |
|
237 | <hr />
|
238 |
|
239 | ### `toBeInTheDocument`
|
240 |
|
241 | ```typescript
|
242 | toBeInTheDocument()
|
243 | ```
|
244 |
|
245 | This allows you to assert whether an element is present in the document or not.
|
246 |
|
247 | #### Examples
|
248 |
|
249 | ```html
|
250 | <span data-testid="html-element"><span>Html Element</span></span>
|
251 | <svg data-testid="svg-element"></svg>
|
252 | ```
|
253 |
|
254 | ```javascript
|
255 | expect(
|
256 | queryByTestId(document.documentElement, 'html-element'),
|
257 | ).toBeInTheDocument()
|
258 | expect(
|
259 | queryByTestId(document.documentElement, 'svg-element'),
|
260 | ).toBeInTheDocument()
|
261 | expect(
|
262 | queryByTestId(document.documentElement, 'does-not-exist'),
|
263 | ).not.toBeInTheDocument()
|
264 | ```
|
265 |
|
266 | > Note: This matcher does not find detached elements. The element must be added
|
267 | > to the document to be found by toBeInTheDocument. If you desire to search in a
|
268 | > detached element please use: [`toContainElement`](#tocontainelement)
|
269 |
|
270 | <hr />
|
271 |
|
272 | ### `toBeInvalid`
|
273 |
|
274 | ```typescript
|
275 | toBeInvalid()
|
276 | ```
|
277 |
|
278 | This allows you to check if an element, is currently invalid.
|
279 |
|
280 | An element is invalid if it has an
|
281 | [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-invalid_attribute)
|
282 | with no value or a value of `"true"`, or if the result of
|
283 | [`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation)
|
284 | is `false`.
|
285 |
|
286 | #### Examples
|
287 |
|
288 | ```html
|
289 | <input data-testid="no-aria-invalid" />
|
290 | <input data-testid="aria-invalid" aria-invalid />
|
291 | <input data-testid="aria-invalid-value" aria-invalid="true" />
|
292 | <input data-testid="aria-invalid-false" aria-invalid="false" />
|
293 |
|
294 | <form data-testid="valid-form">
|
295 | <input />
|
296 | </form>
|
297 |
|
298 | <form data-testid="invalid-form">
|
299 | <input required />
|
300 | </form>
|
301 | ```
|
302 |
|
303 | ```javascript
|
304 | expect(getByTestId('no-aria-invalid')).not.toBeInvalid()
|
305 | expect(getByTestId('aria-invalid')).toBeInvalid()
|
306 | expect(getByTestId('aria-invalid-value')).toBeInvalid()
|
307 | expect(getByTestId('aria-invalid-false')).not.toBeInvalid()
|
308 |
|
309 | expect(getByTestId('valid-form')).not.toBeInvalid()
|
310 | expect(getByTestId('invalid-form')).toBeInvalid()
|
311 | ```
|
312 |
|
313 | <hr />
|
314 |
|
315 | ### `toBeRequired`
|
316 |
|
317 | ```typescript
|
318 | toBeRequired()
|
319 | ```
|
320 |
|
321 | This allows you to check if a form element is currently required.
|
322 |
|
323 | An element is required if it is having a `required` or `aria-required="true"`
|
324 | attribute.
|
325 |
|
326 | #### Examples
|
327 |
|
328 | ```html
|
329 | <input data-testid="required-input" required />
|
330 | <input data-testid="aria-required-input" aria-required="true" />
|
331 | <input data-testid="conflicted-input" required aria-required="false" />
|
332 | <input data-testid="aria-not-required-input" aria-required="false" />
|
333 | <input data-testid="optional-input" />
|
334 | <input data-testid="unsupported-type" type="image" required />
|
335 | <select data-testid="select" required></select>
|
336 | <textarea data-testid="textarea" required></textarea>
|
337 | <div data-testid="supported-role" role="tree" required></div>
|
338 | <div data-testid="supported-role-aria" role="tree" aria-required="true"></div>
|
339 | ```
|
340 |
|
341 | ```javascript
|
342 | expect(getByTestId('required-input')).toBeRequired()
|
343 | expect(getByTestId('aria-required-input')).toBeRequired()
|
344 | expect(getByTestId('conflicted-input')).toBeRequired()
|
345 | expect(getByTestId('aria-not-required-input')).not.toBeRequired()
|
346 | expect(getByTestId('optional-input')).not.toBeRequired()
|
347 | expect(getByTestId('unsupported-type')).not.toBeRequired()
|
348 | expect(getByTestId('select')).toBeRequired()
|
349 | expect(getByTestId('textarea')).toBeRequired()
|
350 | expect(getByTestId('supported-role')).not.toBeRequired()
|
351 | expect(getByTestId('supported-role-aria')).toBeRequired()
|
352 | ```
|
353 |
|
354 | <hr />
|
355 |
|
356 | ### `toBeValid`
|
357 |
|
358 | ```typescript
|
359 | toBeValid()
|
360 | ```
|
361 |
|
362 | This allows you to check if the value of an element, is currently valid.
|
363 |
|
364 | An element is valid if it has no
|
365 | [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-invalid_attribute)s
|
366 | or an attribute value of `"false"`. The result of
|
367 | [`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation)
|
368 | must also be `true` if it's a form element.
|
369 |
|
370 | #### Examples
|
371 |
|
372 | ```html
|
373 | <input data-testid="no-aria-invalid" />
|
374 | <input data-testid="aria-invalid" aria-invalid />
|
375 | <input data-testid="aria-invalid-value" aria-invalid="true" />
|
376 | <input data-testid="aria-invalid-false" aria-invalid="false" />
|
377 |
|
378 | <form data-testid="valid-form">
|
379 | <input />
|
380 | </form>
|
381 |
|
382 | <form data-testid="invalid-form">
|
383 | <input required />
|
384 | </form>
|
385 | ```
|
386 |
|
387 | ```javascript
|
388 | expect(getByTestId('no-aria-invalid')).toBeValid()
|
389 | expect(getByTestId('aria-invalid')).not.toBeValid()
|
390 | expect(getByTestId('aria-invalid-value')).not.toBeValid()
|
391 | expect(getByTestId('aria-invalid-false')).toBeValid()
|
392 |
|
393 | expect(getByTestId('valid-form')).toBeValid()
|
394 | expect(getByTestId('invalid-form')).not.toBeValid()
|
395 | ```
|
396 |
|
397 | <hr />
|
398 |
|
399 | ### `toBeVisible`
|
400 |
|
401 | ```typescript
|
402 | toBeVisible()
|
403 | ```
|
404 |
|
405 | This allows you to check if an element is currently visible to the user.
|
406 |
|
407 | An element is visible if **all** the following conditions are met:
|
408 |
|
409 | - it does not have its css property `display` set to `none`
|
410 | - it does not have its css property `visibility` set to either `hidden` or
|
411 | `collapse`
|
412 | - it does not have its css property `opacity` set to `0`
|
413 | - its parent element is also visible (and so on up to the top of the DOM tree)
|
414 | - it does not have the
|
415 | [`hidden`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden)
|
416 | attribute
|
417 | - if `<details />` it has the `open` attribute
|
418 |
|
419 | #### Examples
|
420 |
|
421 | ```html
|
422 | <div data-testid="zero-opacity" style="opacity: 0">Zero Opacity Example</div>
|
423 | <div data-testid="visibility-hidden" style="visibility: hidden">
|
424 | Visibility Hidden Example
|
425 | </div>
|
426 | <div data-testid="display-none" style="display: none">Display None Example</div>
|
427 | <div style="opacity: 0">
|
428 | <span data-testid="hidden-parent">Hidden Parent Example</span>
|
429 | </div>
|
430 | <div data-testid="visible">Visible Example</div>
|
431 | <div data-testid="hidden-attribute" hidden>Hidden Attribute Example</div>
|
432 | ```
|
433 |
|
434 | ```javascript
|
435 | expect(getByText('Zero Opacity Example')).not.toBeVisible()
|
436 | expect(getByText('Visibility Hidden Example')).not.toBeVisible()
|
437 | expect(getByText('Display None Example')).not.toBeVisible()
|
438 | expect(getByText('Hidden Parent Example')).not.toBeVisible()
|
439 | expect(getByText('Visible Example')).toBeVisible()
|
440 | expect(getByText('Hidden Attribute Example')).not.toBeVisible()
|
441 | ```
|
442 |
|
443 | <hr />
|
444 |
|
445 | ### `toContainElement`
|
446 |
|
447 | ```typescript
|
448 | toContainElement(element: HTMLElement | SVGElement | null)
|
449 | ```
|
450 |
|
451 | This allows you to assert whether an element contains another element as a
|
452 | descendant or not.
|
453 |
|
454 | #### Examples
|
455 |
|
456 | ```html
|
457 | <span data-testid="ancestor"><span data-testid="descendant"></span></span>
|
458 | ```
|
459 |
|
460 | ```javascript
|
461 | const ancestor = getByTestId('ancestor')
|
462 | const descendant = getByTestId('descendant')
|
463 | const nonExistantElement = getByTestId('does-not-exist')
|
464 |
|
465 | expect(ancestor).toContainElement(descendant)
|
466 | expect(descendant).not.toContainElement(ancestor)
|
467 | expect(ancestor).not.toContainElement(nonExistantElement)
|
468 | ```
|
469 |
|
470 | <hr />
|
471 |
|
472 | ### `toContainHTML`
|
473 |
|
474 | ```typescript
|
475 | toContainHTML(htmlText: string)
|
476 | ```
|
477 |
|
478 | Assert whether a string representing a HTML element is contained in another
|
479 | element:
|
480 |
|
481 | #### Examples
|
482 |
|
483 | ```html
|
484 | <span data-testid="parent"><span data-testid="child"></span></span>
|
485 | ```
|
486 |
|
487 | ```javascript
|
488 | expect(getByTestId('parent')).toContainHTML('<span data-testid="child"></span>')
|
489 | ```
|
490 |
|
491 | > Chances are you probably do not need to use this matcher. We encourage testing
|
492 | > from the perspective of how the user perceives the app in a browser. That's
|
493 | > why testing against a specific DOM structure is not advised.
|
494 | >
|
495 | > It could be useful in situations where the code being tested renders html that
|
496 | > was obtained from an external source, and you want to validate that that html
|
497 | > code was used as intended.
|
498 | >
|
499 | > It should not be used to check DOM structure that you control. Please use
|
500 | > [`toContainElement`](#tocontainelement) instead.
|
501 |
|
502 | <hr />
|
503 |
|
504 | ### `toHaveAttribute`
|
505 |
|
506 | ```typescript
|
507 | toHaveAttribute(attr: string, value?: any)
|
508 | ```
|
509 |
|
510 | This allows you to check whether the given element has an attribute or not. You
|
511 | can also optionally check that the attribute has a specific expected value or
|
512 | partial match using
|
513 | [expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)/[expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp)
|
514 |
|
515 | #### Examples
|
516 |
|
517 | ```html
|
518 | <button data-testid="ok-button" type="submit" disabled>ok</button>
|
519 | ```
|
520 |
|
521 | ```javascript
|
522 | const button = getByTestId('ok-button')
|
523 |
|
524 | expect(button).toHaveAttribute('disabled')
|
525 | expect(button).toHaveAttribute('type', 'submit')
|
526 | expect(button).not.toHaveAttribute('type', 'button')
|
527 |
|
528 | expect(button).toHaveAttribute('type', expect.stringContaining('sub'))
|
529 | expect(button).toHaveAttribute('type', expect.not.stringContaining('but'))
|
530 | ```
|
531 |
|
532 | <hr />
|
533 |
|
534 | ### `toHaveClass`
|
535 |
|
536 | ```typescript
|
537 | toHaveClass(...classNames: string[], options?: {exact: boolean})
|
538 | ```
|
539 |
|
540 | This allows you to check whether the given element has certain classes within
|
541 | its `class` attribute.
|
542 |
|
543 | You must provide at least one class, unless you are asserting that an element
|
544 | does not have any classes.
|
545 |
|
546 | #### Examples
|
547 |
|
548 | ```html
|
549 | <button data-testid="delete-button" class="btn extra btn-danger">
|
550 | Delete item
|
551 | </button>
|
552 | <button data-testid="no-classes">No Classes</button>
|
553 | ```
|
554 |
|
555 | ```javascript
|
556 | const deleteButton = getByTestId('delete-button')
|
557 | const noClasses = getByTestId('no-classes')
|
558 |
|
559 | expect(deleteButton).toHaveClass('extra')
|
560 | expect(deleteButton).toHaveClass('btn-danger btn')
|
561 | expect(deleteButton).toHaveClass('btn-danger', 'btn')
|
562 | expect(deleteButton).not.toHaveClass('btn-link')
|
563 |
|
564 | expect(deleteButton).toHaveClass('btn-danger extra btn', {exact: true}) // to check if the element has EXACTLY a set of classes
|
565 | expect(deleteButton).not.toHaveClass('btn-danger extra', {exact: true}) // if it has more than expected it is going to fail
|
566 |
|
567 | expect(noClasses).not.toHaveClass()
|
568 | ```
|
569 |
|
570 | <hr />
|
571 |
|
572 | ### `toHaveFocus`
|
573 |
|
574 | ```typescript
|
575 | toHaveFocus()
|
576 | ```
|
577 |
|
578 | This allows you to assert whether an element has focus or not.
|
579 |
|
580 | #### Examples
|
581 |
|
582 | ```html
|
583 | <div><input type="text" data-testid="element-to-focus" /></div>
|
584 | ```
|
585 |
|
586 | ```javascript
|
587 | const input = getByTestId('element-to-focus')
|
588 |
|
589 | input.focus()
|
590 | expect(input).toHaveFocus()
|
591 |
|
592 | input.blur()
|
593 | expect(input).not.toHaveFocus()
|
594 | ```
|
595 |
|
596 | <hr />
|
597 |
|
598 | ### `toHaveFormValues`
|
599 |
|
600 | ```typescript
|
601 | toHaveFormValues(expectedValues: {
|
602 | [name: string]: any
|
603 | })
|
604 | ```
|
605 |
|
606 | This allows you to check if a form or fieldset contains form controls for each
|
607 | given name, and having the specified value.
|
608 |
|
609 | > It is important to stress that this matcher can only be invoked on a [form][]
|
610 | > or a [fieldset][] element.
|
611 | >
|
612 | > This allows it to take advantage of the [.elements][] property in `form` and
|
613 | > `fieldset` to reliably fetch all form controls within them.
|
614 | >
|
615 | > This also avoids the possibility that users provide a container that contains
|
616 | > more than one `form`, thereby intermixing form controls that are not related,
|
617 | > and could even conflict with one another.
|
618 |
|
619 | This matcher abstracts away the particularities with which a form control value
|
620 | is obtained depending on the type of form control. For instance, `<input>`
|
621 | elements have a `value` attribute, but `<select>` elements do not. Here's a list
|
622 | of all cases covered:
|
623 |
|
624 | - `<input type="number">` elements return the value as a **number**, instead of
|
625 | a string.
|
626 | - `<input type="checkbox">` elements:
|
627 | - if there's a single one with the given `name` attribute, it is treated as a
|
628 | **boolean**, returning `true` if the checkbox is checked, `false` if
|
629 | unchecked.
|
630 | - if there's more than one checkbox with the same `name` attribute, they are
|
631 | all treated collectively as a single form control, which returns the value
|
632 | as an **array** containing all the values of the selected checkboxes in the
|
633 | collection.
|
634 | - `<input type="radio">` elements are all grouped by the `name` attribute, and
|
635 | such a group treated as a single form control. This form control returns the
|
636 | value as a **string** corresponding to the `value` attribute of the selected
|
637 | radio button within the group.
|
638 | - `<input type="text">` elements return the value as a **string**. This also
|
639 | applies to `<input>` elements having any other possible `type` attribute
|
640 | that's not explicitly covered in different rules above (e.g. `search`,
|
641 | `email`, `date`, `password`, `hidden`, etc.)
|
642 | - `<select>` elements without the `multiple` attribute return the value as a
|
643 | **string** corresponding to the `value` attribute of the selected `option`, or
|
644 | `undefined` if there's no selected option.
|
645 | - `<select multiple>` elements return the value as an **array** containing all
|
646 | the values of the [selected options][].
|
647 | - `<textarea>` elements return their value as a **string**. The value
|
648 | corresponds to their node content.
|
649 |
|
650 | The above rules make it easy, for instance, to switch from using a single select
|
651 | control to using a group of radio buttons. Or to switch from a multi select
|
652 | control, to using a group of checkboxes. The resulting set of form values used
|
653 | by this matcher to compare against would be the same.
|
654 |
|
655 | [selected options]:
|
656 | https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedOptions
|
657 | [form]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement
|
658 | [fieldset]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement
|
659 | [.elements]:
|
660 | https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
|
661 |
|
662 | #### Examples
|
663 |
|
664 | ```html
|
665 | <form data-testid="login-form">
|
666 | <input type="text" name="username" value="jane.doe" />
|
667 | <input type="password" name="password" value="12345678" />
|
668 | <input type="checkbox" name="rememberMe" checked />
|
669 | <button type="submit">Sign in</button>
|
670 | </form>
|
671 | ```
|
672 |
|
673 | ```javascript
|
674 | expect(getByTestId('login-form')).toHaveFormValues({
|
675 | username: 'jane.doe',
|
676 | rememberMe: true,
|
677 | })
|
678 | ```
|
679 |
|
680 | ### `toHaveStyle`
|
681 |
|
682 | ```typescript
|
683 | toHaveStyle(css: string | object)
|
684 | ```
|
685 |
|
686 | This allows you to check if a certain element has some specific css properties
|
687 | with specific values applied. It matches only if the element has _all_ the
|
688 | expected properties applied, not just some of them.
|
689 |
|
690 | #### Examples
|
691 |
|
692 | ```html
|
693 | <button
|
694 | data-testid="delete-button"
|
695 | style="display: none; background-color: red"
|
696 | >
|
697 | Delete item
|
698 | </button>
|
699 | ```
|
700 |
|
701 | ```javascript
|
702 | const button = getByTestId('delete-button')
|
703 |
|
704 | expect(button).toHaveStyle('display: none')
|
705 | expect(button).toHaveStyle({display: 'none'})
|
706 | expect(button).toHaveStyle(`
|
707 | background-color: red;
|
708 | display: none;
|
709 | `)
|
710 | expect(button).toHaveStyle({
|
711 | backgroundColor: 'red',
|
712 | display: 'none',
|
713 | })
|
714 | expect(button).not.toHaveStyle(`
|
715 | background-color: blue;
|
716 | display: none;
|
717 | `)
|
718 | expect(button).not.toHaveStyle({
|
719 | backgroundColor: 'blue',
|
720 | display: 'none',
|
721 | })
|
722 | ```
|
723 |
|
724 | This also works with rules that are applied to the element via a class name for
|
725 | which some rules are defined in a stylesheet currently active in the document.
|
726 | The usual rules of css precedence apply.
|
727 |
|
728 | <hr />
|
729 |
|
730 | ### `toHaveTextContent`
|
731 |
|
732 | ```typescript
|
733 | toHaveTextContent(text: string | RegExp, options?: {normalizeWhitespace: boolean})
|
734 | ```
|
735 |
|
736 | This allows you to check whether the given element has a text content or not.
|
737 |
|
738 | When a `string` argument is passed through, it will perform a partial
|
739 | case-sensitive match to the element content.
|
740 |
|
741 | To perform a case-insensitive match, you can use a `RegExp` with the `/i`
|
742 | modifier.
|
743 |
|
744 | If you want to match the whole content, you can use a `RegExp` to do it.
|
745 |
|
746 | #### Examples
|
747 |
|
748 | ```html
|
749 | <span data-testid="text-content">Text Content</span>
|
750 | ```
|
751 |
|
752 | ```javascript
|
753 | const element = getByTestId('text-content')
|
754 |
|
755 | expect(element).toHaveTextContent('Content')
|
756 | expect(element).toHaveTextContent(/^Text Content$/) // to match the whole content
|
757 | expect(element).toHaveTextContent(/content$/i) // to use case-insensitive match
|
758 | expect(element).not.toHaveTextContent('content')
|
759 | ```
|
760 |
|
761 | <hr />
|
762 |
|
763 | ### `toHaveValue`
|
764 |
|
765 | ```typescript
|
766 | toHaveValue(value: string | string[] | number)
|
767 | ```
|
768 |
|
769 | This allows you to check whether the given form element has the specified value.
|
770 | It accepts `<input>`, `<select>` and `<textarea>` elements with the exception of
|
771 | `<input type="checkbox">` and `<input type="radio">`, which can be meaningfully
|
772 | matched only using [`toBeChecked`](#tobechecked) or
|
773 | [`toHaveFormValues`](#tohaveformvalues).
|
774 |
|
775 | For all other form elements, the value is matched using the same algorithm as in
|
776 | [`toHaveFormValues`](#tohaveformvalues) does.
|
777 |
|
778 | #### Examples
|
779 |
|
780 | ```html
|
781 | <input type="text" value="text" data-testid="input-text" />
|
782 | <input type="number" value="5" data-testid="input-number" />
|
783 | <input type="text" data-testid="input-empty" />
|
784 | <select data-testid="multiple" multiple data-testid="select-number">
|
785 | <option value="first">First Value</option>
|
786 | <option value="second" selected>Second Value</option>
|
787 | <option value="third" selected>Third Value</option>
|
788 | </select>
|
789 | ```
|
790 |
|
791 | ##### Using DOM Testing Library
|
792 |
|
793 | ```javascript
|
794 | const textInput = getByTestId('input-text')
|
795 | const numberInput = getByTestId('input-number')
|
796 | const emptyInput = getByTestId('input-empty')
|
797 | const selectInput = getByTestId('select-number')
|
798 |
|
799 | expect(textInput).toHaveValue('text')
|
800 | expect(numberInput).toHaveValue(5)
|
801 | expect(emptyInput).not.toHaveValue()
|
802 | expect(selectInput).not.toHaveValue(['second', 'third'])
|
803 | ```
|
804 |
|
805 | <hr />
|
806 |
|
807 | ### `toHaveDisplayValue`
|
808 |
|
809 | ```typescript
|
810 | toHaveDisplayValue(value: string | RegExp | (string|RegExp)[])
|
811 | ```
|
812 |
|
813 | This allows you to check whether the given form element has the specified
|
814 | displayed value (the one the end user will see). It accepts `<input>`,
|
815 | `<select>` and `<textarea>` elements with the exception of
|
816 | `<input type="checkbox">` and `<input type="radio">`, which can be meaningfully
|
817 | matched only using [`toBeChecked`](#tobechecked) or
|
818 | [`toHaveFormValues`](#tohaveformvalues).
|
819 |
|
820 | #### Examples
|
821 |
|
822 | ```html
|
823 | <label for="input-example">First name</label>
|
824 | <input type="text" id="input-example" value="Luca" />
|
825 |
|
826 | <label for="textarea-example">Description</label>
|
827 | <textarea id="textarea-example">An example description here.</textarea>
|
828 |
|
829 | <label for="single-select-example">Fruit</label>
|
830 | <select id="single-select-example">
|
831 | <option value="">Select a fruit...</option>
|
832 | <option value="banana">Banana</option>
|
833 | <option value="ananas">Ananas</option>
|
834 | <option value="avocado">Avocado</option>
|
835 | </select>
|
836 |
|
837 | <label for="mutiple-select-example">Fruits</label>
|
838 | <select id="multiple-select-example" multiple>
|
839 | <option value="">Select a fruit...</option>
|
840 | <option value="banana" selected>Banana</option>
|
841 | <option value="ananas">Ananas</option>
|
842 | <option value="avocado" selected>Avocado</option>
|
843 | </select>
|
844 | ```
|
845 |
|
846 | ##### Using DOM Testing Library
|
847 |
|
848 | ```javascript
|
849 | const input = screen.getByLabelText('First name')
|
850 | const textarea = screen.getByLabelText('Description')
|
851 | const selectSingle = screen.getByLabelText('Fruit')
|
852 | const selectMultiple = screen.getByLabelText('Fruits')
|
853 |
|
854 | expect(input).toHaveDisplayValue('Luca')
|
855 | expect(input).toHaveDisplayValue(/Luc/)
|
856 | expect(textarea).toHaveDisplayValue('An example description here.')
|
857 | expect(textarea).toHaveDisplayValue(/example/)
|
858 | expect(selectSingle).toHaveDisplayValue('Select a fruit...')
|
859 | expect(selectSingle).toHaveDisplayValue(/Select/)
|
860 | expect(selectMultiple).toHaveDisplayValue([/Avocado/, 'Banana'])
|
861 | ```
|
862 |
|
863 | <hr />
|
864 |
|
865 | ### `toBeChecked`
|
866 |
|
867 | ```typescript
|
868 | toBeChecked()
|
869 | ```
|
870 |
|
871 | This allows you to check whether the given element is checked. It accepts an
|
872 | `input` of type `checkbox` or `radio` and elements with a `role` of `checkbox`,
|
873 | `radio` or `switch` with a valid `aria-checked` attribute of `"true"` or
|
874 | `"false"`.
|
875 |
|
876 | #### Examples
|
877 |
|
878 | ```html
|
879 | <input type="checkbox" checked data-testid="input-checkbox-checked" />
|
880 | <input type="checkbox" data-testid="input-checkbox-unchecked" />
|
881 | <div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
|
882 | <div
|
883 | role="checkbox"
|
884 | aria-checked="false"
|
885 | data-testid="aria-checkbox-unchecked"
|
886 | />
|
887 |
|
888 | <input type="radio" checked value="foo" data-testid="input-radio-checked" />
|
889 | <input type="radio" value="foo" data-testid="input-radio-unchecked" />
|
890 | <div role="radio" aria-checked="true" data-testid="aria-radio-checked" />
|
891 | <div role="radio" aria-checked="false" data-testid="aria-radio-unchecked" />
|
892 | <div role="switch" aria-checked="true" data-testid="aria-switch-checked" />
|
893 | <div role="switch" aria-checked="false" data-testid="aria-switch-unchecked" />
|
894 | ```
|
895 |
|
896 | ```javascript
|
897 | const inputCheckboxChecked = getByTestId('input-checkbox-checked')
|
898 | const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked')
|
899 | const ariaCheckboxChecked = getByTestId('aria-checkbox-checked')
|
900 | const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked')
|
901 | expect(inputCheckboxChecked).toBeChecked()
|
902 | expect(inputCheckboxUnchecked).not.toBeChecked()
|
903 | expect(ariaCheckboxChecked).toBeChecked()
|
904 | expect(ariaCheckboxUnchecked).not.toBeChecked()
|
905 |
|
906 | const inputRadioChecked = getByTestId('input-radio-checked')
|
907 | const inputRadioUnchecked = getByTestId('input-radio-unchecked')
|
908 | const ariaRadioChecked = getByTestId('aria-radio-checked')
|
909 | const ariaRadioUnchecked = getByTestId('aria-radio-unchecked')
|
910 | expect(inputRadioChecked).toBeChecked()
|
911 | expect(inputRadioUnchecked).not.toBeChecked()
|
912 | expect(ariaRadioChecked).toBeChecked()
|
913 | expect(ariaRadioUnchecked).not.toBeChecked()
|
914 |
|
915 | const ariaSwitchChecked = getByTestId('aria-switch-checked')
|
916 | const ariaSwitchUnchecked = getByTestId('aria-switch-unchecked')
|
917 | expect(ariaSwitchChecked).toBeChecked()
|
918 | expect(ariaSwitchUnchecked).not.toBeChecked()
|
919 | ```
|
920 |
|
921 | <hr />
|
922 |
|
923 | ### `toBePartiallyChecked`
|
924 |
|
925 | ```typescript
|
926 | toBePartiallyChecked()
|
927 | ```
|
928 |
|
929 | This allows you to check whether the given element is partially checked. It
|
930 | accepts an `input` of type `checkbox` and elements with a `role` of `checkbox`
|
931 | with a `aria-checked="mixed"`, or `input` of type `checkbox` with
|
932 | `indeterminate` set to `true`
|
933 |
|
934 | #### Examples
|
935 |
|
936 | ```html
|
937 | <input type="checkbox" aria-checked="mixed" data-testid="aria-checkbox-mixed" />
|
938 | <input type="checkbox" checked data-testid="input-checkbox-checked" />
|
939 | <input type="checkbox" data-testid="input-checkbox-unchecked" />
|
940 | <div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
|
941 | <div
|
942 | role="checkbox"
|
943 | aria-checked="false"
|
944 | data-testid="aria-checkbox-unchecked"
|
945 | />
|
946 | <input type="checkbox" data-testid="input-checkbox-indeterminate" />
|
947 | ```
|
948 |
|
949 | ```javascript
|
950 | const ariaCheckboxMixed = getByTestId('aria-checkbox-mixed')
|
951 | const inputCheckboxChecked = getByTestId('input-checkbox-checked')
|
952 | const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked')
|
953 | const ariaCheckboxChecked = getByTestId('aria-checkbox-checked')
|
954 | const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked')
|
955 | const inputCheckboxIndeterminate = getByTestId('input-checkbox-indeterminate')
|
956 |
|
957 | expect(ariaCheckboxMixed).toBePartiallyChecked()
|
958 | expect(inputCheckboxChecked).not.toBePartiallyChecked()
|
959 | expect(inputCheckboxUnchecked).not.toBePartiallyChecked()
|
960 | expect(ariaCheckboxChecked).not.toBePartiallyChecked()
|
961 | expect(ariaCheckboxUnchecked).not.toBePartiallyChecked()
|
962 |
|
963 | inputCheckboxIndeterminate.indeterminate = true
|
964 | expect(inputCheckboxIndeterminate).toBePartiallyChecked()
|
965 | ```
|
966 |
|
967 | <hr />
|
968 |
|
969 | ### `toHaveDescription`
|
970 |
|
971 | ```typescript
|
972 | toHaveDescription(text: string | RegExp)
|
973 | ```
|
974 |
|
975 | This allows you to check whether the given element has a description or not.
|
976 |
|
977 | An element gets its description via the
|
978 | [`aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute).
|
979 | Set this to the `id` of one or more other elements. These elements may be nested
|
980 | inside, be outside, or a sibling of the passed in element.
|
981 |
|
982 | Whitespace is normalized. Using multiple ids will
|
983 | [join the referenced elementsโ text content separated by a space](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description).
|
984 |
|
985 | When a `string` argument is passed through, it will perform a whole
|
986 | case-sensitive match to the description text.
|
987 |
|
988 | To perform a case-insensitive match, you can use a `RegExp` with the `/i`
|
989 | modifier.
|
990 |
|
991 | To perform a partial match, you can pass a `RegExp` or use
|
992 | `expect.stringContaining("partial string")`.
|
993 |
|
994 | #### Examples
|
995 |
|
996 | ```html
|
997 | <button aria-label="Close" aria-describedby="description-close">
|
998 | X
|
999 | </button>
|
1000 | <div id="description-close">
|
1001 | Closing will discard any changes
|
1002 | </div>
|
1003 |
|
1004 | <button>Delete</button>
|
1005 | ```
|
1006 |
|
1007 | ```javascript
|
1008 | const closeButton = getByRole('button', {name: 'Close'})
|
1009 |
|
1010 | expect(closeButton).toHaveDescription('Closing will discard any changes')
|
1011 | expect(closeButton).toHaveDescription(/will discard/) // to partially match
|
1012 | expect(closeButton).toHaveDescription(expect.stringContaining('will discard')) // to partially match
|
1013 | expect(closeButton).toHaveDescription(/^closing/i) // to use case-insensitive match
|
1014 | expect(closeButton).not.toHaveDescription('Other description')
|
1015 |
|
1016 | const deleteButton = getByRole('button', {name: 'Delete'})
|
1017 | expect(deleteButton).not.toHaveDescription()
|
1018 | expect(deleteButton).toHaveDescription('') // Missing or empty description always becomes a blank string
|
1019 | ```
|
1020 |
|
1021 | ## Deprecated matchers
|
1022 |
|
1023 | ### `toBeInTheDOM`
|
1024 |
|
1025 | ```typescript
|
1026 | toBeInTheDOM()
|
1027 | ```
|
1028 |
|
1029 | This allows you to check whether a value is a DOM element, or not.
|
1030 |
|
1031 | Contrary to what its name implies, this matcher only checks that you passed to
|
1032 | it a valid DOM element. It does not have a clear definition of what "the DOM"
|
1033 | is. Therefore, it does not check whether that element is contained anywhere.
|
1034 |
|
1035 | This is the main reason why this matcher is deprecated, and will be removed in
|
1036 | the next major release. You can follow the discussion around this decision in
|
1037 | more detail [here](https://github.com/testing-library/jest-dom/issues/34).
|
1038 |
|
1039 | As an alternative, you can use [`toBeInTheDocument`](#tobeinthedocument) or
|
1040 | [`toContainElement`](#tocontainelement). Or if you just want to check if a value
|
1041 | is indeed an `HTMLElement` you can always use some of
|
1042 | [jest's built-in matchers](https://jestjs.io/docs/en/expect#tobeinstanceofclass):
|
1043 |
|
1044 | ```js
|
1045 | expect(document.querySelector('.ok-button')).toBeInstanceOf(HTMLElement)
|
1046 | expect(document.querySelector('.cancel-button')).toBeTruthy()
|
1047 | ```
|
1048 |
|
1049 | > Note: The differences between `toBeInTheDOM` and `toBeInTheDocument` are
|
1050 | > significant. Replacing all uses of `toBeInTheDOM` with `toBeInTheDocument`
|
1051 | > will likely cause unintended consequences in your tests. Please make sure when
|
1052 | > replacing `toBeInTheDOM` to read through the documentation of the proposed
|
1053 | > alternatives to see which use case works better for your needs.
|
1054 |
|
1055 | ## Inspiration
|
1056 |
|
1057 | This whole library was extracted out of Kent C. Dodds' [DOM Testing
|
1058 | Library][dom-testing-library], which was in turn extracted out of [React Testing
|
1059 | Library][react-testing-library].
|
1060 |
|
1061 | The intention is to make this available to be used independently of these other
|
1062 | libraries, and also to make it more clear that these other libraries are
|
1063 | independent from jest, and can be used with other tests runners as well.
|
1064 |
|
1065 | ## Other Solutions
|
1066 |
|
1067 | I'm not aware of any, if you are please [make a pull request][prs] and add it
|
1068 | here!
|
1069 |
|
1070 | If you would like to further test the accessibility and validity of the DOM
|
1071 | consider [`jest-axe`](https://github.com/nickcolley/jest-axe). It doesn't
|
1072 | overlap with `jest-dom` but can complement it for more in-depth accessibility
|
1073 | checking (eg: validating `aria` attributes or ensuring unique id attributes).
|
1074 |
|
1075 | ## Guiding Principles
|
1076 |
|
1077 | > [The more your tests resemble the way your software is used, the more
|
1078 | > confidence they can give you.][guiding-principle]
|
1079 |
|
1080 | This library follows the same guiding principles as its mother library [DOM
|
1081 | Testing Library][dom-testing-library]. Go [check them out][guiding-principle]
|
1082 | for more details.
|
1083 |
|
1084 | Additionally, with respect to custom DOM matchers, this library aims to maintain
|
1085 | a minimal but useful set of them, while avoiding bloating itself with merely
|
1086 | convenient ones that can be easily achieved with other APIs. In general, the
|
1087 | overall criteria for what is considered a useful custom matcher to add to this
|
1088 | library, is that doing the equivalent assertion on our own makes the test code
|
1089 | more verbose, less clear in its intent, and/or harder to read.
|
1090 |
|
1091 | ## Contributors
|
1092 |
|
1093 | Thanks goes to these people ([emoji key][emojis]):
|
1094 |
|
1095 |
|
1096 |
|
1097 |
|
1098 | <table>
|
1099 | <tr>
|
1100 | <td align="center"><a href="https://kentcdodds.com"><img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;" alt=""/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=kentcdodds" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=kentcdodds" title="Documentation">๐</a> <a href="#infra-kentcdodds" title="Infrastructure (Hosting, Build-Tools, etc)">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=kentcdodds" title="Tests">โ ๏ธ</a></td>
|
1101 | <td align="center"><a href="http://audiolion.github.io"><img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;" alt=""/><br /><sub><b>Ryan Castner</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=audiolion" title="Documentation">๐</a></td>
|
1102 | <td align="center"><a href="https://www.dnlsandiego.com"><img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Sandiego</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=dnlsandiego" title="Code">๐ป</a></td>
|
1103 | <td align="center"><a href="https://github.com/Miklet"><img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;" alt=""/><br /><sub><b>Paweล Mikoลajczyk</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=Miklet" title="Code">๐ป</a></td>
|
1104 | <td align="center"><a href="http://co.linkedin.com/in/alejandronanez/"><img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;" alt=""/><br /><sub><b>Alejandro รรกรฑez Ortiz</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=alejandronanez" title="Documentation">๐</a></td>
|
1105 | <td align="center"><a href="https://github.com/pbomb"><img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;" alt=""/><br /><sub><b>Matt Parrish</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Apbomb" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=pbomb" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=pbomb" title="Documentation">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=pbomb" title="Tests">โ ๏ธ</a></td>
|
1106 | <td align="center"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="#platform-wKovacs64" title="Packaging/porting to new platform">๐ฆ</a></td>
|
1107 | </tr>
|
1108 | <tr>
|
1109 | <td align="center"><a href="https://github.com/antoaravinth"><img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Anto Aravinth</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=antoaravinth" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=antoaravinth" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=antoaravinth" title="Documentation">๐</a></td>
|
1110 | <td align="center"><a href="https://github.com/JonahMoses"><img src="https://avatars2.githubusercontent.com/u/3462296?v=4" width="100px;" alt=""/><br /><sub><b>Jonah Moses</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=JonahMoses" title="Documentation">๐</a></td>
|
1111 | <td align="center"><a href="http://team.thebrain.pro"><img src="https://avatars1.githubusercontent.com/u/4002543?v=4" width="100px;" alt=""/><br /><sub><b>ลukasz Gandecki</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=lgandecki" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=lgandecki" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=lgandecki" title="Documentation">๐</a></td>
|
1112 | <td align="center"><a href="https://sompylasar.github.io"><img src="https://avatars2.githubusercontent.com/u/498274?v=4" width="100px;" alt=""/><br /><sub><b>Ivan Babak</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Asompylasar" title="Bug reports">๐</a> <a href="#ideas-sompylasar" title="Ideas, Planning, & Feedback">๐ค</a></td>
|
1113 | <td align="center"><a href="https://github.com/jday3"><img src="https://avatars3.githubusercontent.com/u/4439618?v=4" width="100px;" alt=""/><br /><sub><b>Jesse Day</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jday3" title="Code">๐ป</a></td>
|
1114 | <td align="center"><a href="http://gnapse.github.io"><img src="https://avatars0.githubusercontent.com/u/15199?v=4" width="100px;" alt=""/><br /><sub><b>Ernesto Garcรญa</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=gnapse" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=gnapse" title="Documentation">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=gnapse" title="Tests">โ ๏ธ</a></td>
|
1115 | <td align="center"><a href="http://ociweb.com/mark/"><img src="https://avatars0.githubusercontent.com/u/79312?v=4" width="100px;" alt=""/><br /><sub><b>Mark Volkmann</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Amvolkmann" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=mvolkmann" title="Code">๐ป</a></td>
|
1116 | </tr>
|
1117 | <tr>
|
1118 | <td align="center"><a href="https://github.com/smacpherson64"><img src="https://avatars1.githubusercontent.com/u/1659099?v=4" width="100px;" alt=""/><br /><sub><b>smacpherson64</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=smacpherson64" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=smacpherson64" title="Documentation">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=smacpherson64" title="Tests">โ ๏ธ</a></td>
|
1119 | <td align="center"><a href="https://github.com/jgoz"><img src="https://avatars2.githubusercontent.com/u/132233?v=4" width="100px;" alt=""/><br /><sub><b>John Gozde</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Ajgoz" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=jgoz" title="Code">๐ป</a></td>
|
1120 | <td align="center"><a href="https://github.com/callada"><img src="https://avatars2.githubusercontent.com/u/7830590?v=4" width="100px;" alt=""/><br /><sub><b>Iwona</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=callada" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=callada" title="Documentation">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=callada" title="Tests">โ ๏ธ</a></td>
|
1121 | <td align="center"><a href="https://github.com/6ewis"><img src="https://avatars0.githubusercontent.com/u/840609?v=4" width="100px;" alt=""/><br /><sub><b>Lewis</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=6ewis" title="Code">๐ป</a></td>
|
1122 | <td align="center"><a href="https://blog.lourenci.com/"><img src="https://avatars3.githubusercontent.com/u/2339362?v=4" width="100px;" alt=""/><br /><sub><b>Leandro Lourenci</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Alourenci" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=lourenci" title="Documentation">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=lourenci" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=lourenci" title="Tests">โ ๏ธ</a></td>
|
1123 | <td align="center"><a href="https://github.com/mufasa71"><img src="https://avatars1.githubusercontent.com/u/626420?v=4" width="100px;" alt=""/><br /><sub><b>Shukhrat Mukimov</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Amufasa71" title="Bug reports">๐</a></td>
|
1124 | <td align="center"><a href="https://github.com/dreyks"><img src="https://avatars3.githubusercontent.com/u/1481264?v=4" width="100px;" alt=""/><br /><sub><b>Roman Usherenko</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=dreyks" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=dreyks" title="Tests">โ ๏ธ</a></td>
|
1125 | </tr>
|
1126 | <tr>
|
1127 | <td align="center"><a href="http://josephhsu.com"><img src="https://avatars1.githubusercontent.com/u/648?v=4" width="100px;" alt=""/><br /><sub><b>Joe Hsu</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jhsu" title="Documentation">๐</a></td>
|
1128 | <td align="center"><a href="https://twitter.com/diegohaz"><img src="https://avatars3.githubusercontent.com/u/3068563?v=4" width="100px;" alt=""/><br /><sub><b>Haz</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Adiegohaz" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=diegohaz" title="Code">๐ป</a></td>
|
1129 | <td align="center"><a href="https://blog.revathskumar.com"><img src="https://avatars3.githubusercontent.com/u/463904?v=4" width="100px;" alt=""/><br /><sub><b>Revath S Kumar</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=revathskumar" title="Code">๐ป</a></td>
|
1130 | <td align="center"><a href="https://raccoon.studio"><img src="https://avatars0.githubusercontent.com/u/4989733?v=4" width="100px;" alt=""/><br /><sub><b>hiwelo.</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=hiwelo" title="Code">๐ป</a> <a href="#ideas-hiwelo" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/testing-library/jest-dom/commits?author=hiwelo" title="Tests">โ ๏ธ</a></td>
|
1131 | <td align="center"><a href="https://github.com/lukaszfiszer"><img src="https://avatars3.githubusercontent.com/u/1201711?v=4" width="100px;" alt=""/><br /><sub><b>ลukasz Fiszer</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=lukaszfiszer" title="Code">๐ป</a></td>
|
1132 | <td align="center"><a href="https://github.com/jeanchung"><img src="https://avatars0.githubusercontent.com/u/10778036?v=4" width="100px;" alt=""/><br /><sub><b>Jean Chung</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jeanchung" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=jeanchung" title="Tests">โ ๏ธ</a></td>
|
1133 | <td align="center"><a href="https://github.com/CarlaTeo"><img src="https://avatars3.githubusercontent.com/u/9220147?v=4" width="100px;" alt=""/><br /><sub><b>CarlaTeo</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=CarlaTeo" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=CarlaTeo" title="Tests">โ ๏ธ</a></td>
|
1134 | </tr>
|
1135 | <tr>
|
1136 | <td align="center"><a href="https://github.com/YardenShoham"><img src="https://avatars3.githubusercontent.com/u/20454870?v=4" width="100px;" alt=""/><br /><sub><b>Yarden Shoham</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=YardenShoham" title="Documentation">๐</a></td>
|
1137 | <td align="center"><a href="http://jagascript.com"><img src="https://avatars0.githubusercontent.com/u/4562878?v=4" width="100px;" alt=""/><br /><sub><b>Jaga Santagostino</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/issues?q=author%3Akandros" title="Bug reports">๐</a> <a href="https://github.com/testing-library/jest-dom/commits?author=kandros" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=kandros" title="Documentation">๐</a></td>
|
1138 | <td align="center"><a href="https://github.com/connormeredith"><img src="https://avatars0.githubusercontent.com/u/4907463?v=4" width="100px;" alt=""/><br /><sub><b>Connor Meredith</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=connormeredith" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=connormeredith" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=connormeredith" title="Documentation">๐</a></td>
|
1139 | <td align="center"><a href="https://github.com/pwolaq"><img src="https://avatars3.githubusercontent.com/u/10261750?v=4" width="100px;" alt=""/><br /><sub><b>Pawel Wolak</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=pwolaq" title="Tests">โ ๏ธ</a></td>
|
1140 | <td align="center"><a href="https://michaeldeboey.be"><img src="https://avatars3.githubusercontent.com/u/6643991?v=4" width="100px;" alt=""/><br /><sub><b>Michaรซl De Boey</b></sub></a><br /><a href="#infra-MichaelDeBoey" title="Infrastructure (Hosting, Build-Tools, etc)">๐</a></td>
|
1141 | <td align="center"><a href="https://github.com/jzarzeckis"><img src="https://avatars3.githubusercontent.com/u/919350?v=4" width="100px;" alt=""/><br /><sub><b>Jฤnis Zarลพeckis</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jzarzeckis" title="Documentation">๐</a></td>
|
1142 | <td align="center"><a href="https://github.com/koala-lava"><img src="https://avatars0.githubusercontent.com/u/15828770?v=4" width="100px;" alt=""/><br /><sub><b>koala-lava</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=koala-lava" title="Documentation">๐</a></td>
|
1143 | </tr>
|
1144 | <tr>
|
1145 | <td align="center"><a href="https://jpblanco.dev"><img src="https://avatars1.githubusercontent.com/u/16567863?v=4" width="100px;" alt=""/><br /><sub><b>Juan Pablo Blanco</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=JPBlancoDB" title="Documentation">๐</a></td>
|
1146 | <td align="center"><a href="https://github.com/benmonro"><img src="https://avatars3.githubusercontent.com/u/399236?v=4" width="100px;" alt=""/><br /><sub><b>Ben Monro</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=benmonro" title="Documentation">๐</a></td>
|
1147 | <td align="center"><a href="http://jeffbernstein.io"><img src="https://avatars1.githubusercontent.com/u/6685560?v=4" width="100px;" alt=""/><br /><sub><b>Jeff Bernstein</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jeffbernst" title="Documentation">๐</a></td>
|
1148 | <td align="center"><a href="https://github.com/SergiCL"><img src="https://avatars3.githubusercontent.com/u/41625166?v=4" width="100px;" alt=""/><br /><sub><b>Sergi</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=SergiCL" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=SergiCL" title="Tests">โ ๏ธ</a></td>
|
1149 | <td align="center"><a href="https://skovy.dev"><img src="https://avatars1.githubusercontent.com/u/5247455?v=4" width="100px;" alt=""/><br /><sub><b>Spencer Miskoviak</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=skovy" title="Documentation">๐</a></td>
|
1150 | <td align="center"><a href="https://twitter.com/jonrimmer"><img src="https://avatars1.githubusercontent.com/u/183786?v=4" width="100px;" alt=""/><br /><sub><b>Jon Rimmer</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=jonrimmer" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=jonrimmer" title="Tests">โ ๏ธ</a></td>
|
1151 | <td align="center"><a href="https://github.com/cloud-walker"><img src="https://avatars3.githubusercontent.com/u/1144075?v=4" width="100px;" alt=""/><br /><sub><b>Luca Barone</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=cloud-walker" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=cloud-walker" title="Tests">โ ๏ธ</a> <a href="#ideas-cloud-walker" title="Ideas, Planning, & Feedback">๐ค</a></td>
|
1152 | </tr>
|
1153 | <tr>
|
1154 | <td align="center"><a href="https://github.com/mfelmy"><img src="https://avatars2.githubusercontent.com/u/29504917?v=4" width="100px;" alt=""/><br /><sub><b>Malte Felmy</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=mfelmy" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=mfelmy" title="Tests">โ ๏ธ</a></td>
|
1155 | <td align="center"><a href="https://ghuser.io/Ishaan28malik"><img src="https://avatars3.githubusercontent.com/u/27343592?v=4" width="100px;" alt=""/><br /><sub><b>Championrunner</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=Ishaan28malik" title="Documentation">๐</a></td>
|
1156 | <td align="center"><a href="https://icing.space/"><img src="https://avatars0.githubusercontent.com/u/2635733?v=4" width="100px;" alt=""/><br /><sub><b>Patrick Smith</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=BurntCaramel" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=BurntCaramel" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=BurntCaramel" title="Documentation">๐</a></td>
|
1157 | <td align="center"><a href="https://rubenmoya.dev"><img src="https://avatars3.githubusercontent.com/u/905225?v=4" width="100px;" alt=""/><br /><sub><b>Rubรฉn Moya</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=rubenmoya" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=rubenmoya" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=rubenmoya" title="Documentation">๐</a></td>
|
1158 | <td align="center"><a href="https://danielavalero.com/"><img src="https://avatars1.githubusercontent.com/u/1307954?v=4" width="100px;" alt=""/><br /><sub><b>Daniela Valero</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=DanielaValero" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=DanielaValero" title="Tests">โ ๏ธ</a> <a href="https://github.com/testing-library/jest-dom/commits?author=DanielaValero" title="Documentation">๐</a></td>
|
1159 | <td align="center"><a href="https://github.com/missilev"><img src="https://avatars1.githubusercontent.com/u/33201468?v=4" width="100px;" alt=""/><br /><sub><b>Vladislav Katsura</b></sub></a><br /><a href="https://github.com/testing-library/jest-dom/commits?author=missilev" title="Code">๐ป</a> <a href="https://github.com/testing-library/jest-dom/commits?author=missilev" title="Tests">โ ๏ธ</a></td>
|
1160 | </tr>
|
1161 | </table>
|
1162 |
|
1163 |
|
1164 |
|
1165 |
|
1166 |
|
1167 | This project follows the [all-contributors][all-contributors] specification.
|
1168 | Contributions of any kind welcome!
|
1169 |
|
1170 | ## LICENSE
|
1171 |
|
1172 | MIT
|
1173 |
|
1174 | [jest]: https://facebook.github.io/jest/
|
1175 | [dom-testing-library]: https://github.com/testing-library/dom-testing-library
|
1176 | [react-testing-library]:
|
1177 | https://github.com/testing-library/react-testing-library
|
1178 | [npm]: https://www.npmjs.com/
|
1179 | [node]: https://nodejs.org
|
1180 | [build-badge]:
|
1181 | https://img.shields.io/travis/testing-library/jest-dom.svg?style=flat-square
|
1182 | [build]: https://travis-ci.org/testing-library/jest-dom
|
1183 | [coverage-badge]:
|
1184 | https://img.shields.io/codecov/c/github/testing-library/jest-dom.svg?style=flat-square
|
1185 | [coverage]: https://codecov.io/github/testing-library/jest-dom
|
1186 | [version-badge]:
|
1187 | https://img.shields.io/npm/v/@testing-library/jest-dom.svg?style=flat-square
|
1188 | [package]: https://www.npmjs.com/package/@testing-library/jest-dom
|
1189 | [downloads-badge]:
|
1190 | https://img.shields.io/npm/dm/@testing-library/jest-dom.svg?style=flat-square
|
1191 | [npmtrends]: http://www.npmtrends.com/@testing-library/jest-dom
|
1192 | [license-badge]:
|
1193 | https://img.shields.io/npm/l/@testing-library/jest-dom.svg?style=flat-square
|
1194 | [license]: https://github.com/testing-library/jest-dom/blob/master/LICENSE
|
1195 | [prs-badge]:
|
1196 | https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
1197 | [prs]: http://makeapullrequest.com
|
1198 | [coc-badge]:
|
1199 | https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
|
1200 | [coc]:
|
1201 | https://github.com/testing-library/jest-dom/blob/master/other/CODE_OF_CONDUCT.md
|
1202 | [github-watch-badge]:
|
1203 | https://img.shields.io/github/watchers/testing-library/jest-dom.svg?style=social
|
1204 | [github-watch]: https://github.com/testing-library/jest-dom/watchers
|
1205 | [github-star-badge]:
|
1206 | https://img.shields.io/github/stars/testing-library/jest-dom.svg?style=social
|
1207 | [github-star]: https://github.com/testing-library/jest-dom/stargazers
|
1208 | [twitter]:
|
1209 | https://twitter.com/intent/tweet?text=Check%20out%20jest-dom%20by%20%40gnapse%20https%3A%2F%2Fgithub.com%2Ftesting-library%2Fjest-dom%20%F0%9F%91%8D
|
1210 | [twitter-badge]:
|
1211 | https://img.shields.io/twitter/url/https/github.com/testing-library/jest-dom.svg?style=social
|
1212 | [emojis]: https://allcontributors.org/docs/en/emoji-key
|
1213 | [all-contributors]: https://github.com/all-contributors/all-contributors
|
1214 | [guiding-principle]: https://testing-library.com/docs/guiding-principles
|
1215 | [discord-badge]: https://img.shields.io/discord/723559267868737556.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
|
1216 | [discord]: https://discord.gg/c6JN9fM
|