diff --git a/README.md b/README.md index 9762210e..0ccd2d74 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,13 @@ clear to read and to maintain. + - [Installation](#installation) - [Usage](#usage) - [With TypeScript](#with-typescript) - [Custom matchers](#custom-matchers) - [`toBeDisabled`](#tobedisabled) - [`toBeEnabled`](#tobeenabled) - - [`toBeEmpty`](#tobeempty) - [`toBeEmptyDOMElement`](#tobeemptydomelement) - [`toBeInTheDocument`](#tobeinthedocument) - [`toBeInvalid`](#tobeinvalid) @@ -76,10 +76,11 @@ clear to read and to maintain. - [`toHaveDisplayValue`](#tohavedisplayvalue) - [`toBeChecked`](#tobechecked) - [`toBePartiallyChecked`](#tobepartiallychecked) - - [`toHaveDescription`](#tohavedescription) - [`toHaveErrorMessage`](#tohaveerrormessage) - [Deprecated matchers](#deprecated-matchers) + - [`toBeEmpty`](#tobeempty) - [`toBeInTheDOM`](#tobeinthedom) + - [`toHaveDescription`](#tohavedescription) - [Inspiration](#inspiration) - [Other Solutions](#other-solutions) - [Guiding Principles](#guiding-principles) @@ -205,31 +206,6 @@ your tests.
-### `toBeEmpty` - -```typescript -toBeEmpty() -``` - -This allows you to assert whether an element has content or not. - -#### Examples - -```html - -``` - -```javascript -expect(getByTestId('empty')).toBeEmpty() -expect(getByTestId('not-empty')).not.toBeEmpty() -``` - -> Note: This matcher is being deprecated due to a name clash with -> `jest-extended`. See more info in #216. In the future, please use only: -> [`toBeEmptyDOMElement`](#toBeEmptyDOMElement) - -
- ### `toBeEmptyDOMElement` ```typescript @@ -1081,58 +1057,6 @@ expect(inputCheckboxIndeterminate).toBePartiallyChecked()
-### `toHaveDescription` - -```typescript -toHaveDescription(text: string | RegExp) -``` - -This allows you to check whether the given element has a description or not. - -An element gets its description via the -[`aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute). -Set this to the `id` of one or more other elements. These elements may be nested -inside, be outside, or a sibling of the passed in element. - -Whitespace is normalized. Using multiple ids will -[join the referenced elements’ text content separated by a space](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description). - -When a `string` argument is passed through, it will perform a whole -case-sensitive match to the description text. - -To perform a case-insensitive match, you can use a `RegExp` with the `/i` -modifier. - -To perform a partial match, you can pass a `RegExp` or use -`expect.stringContaining("partial string")`. - -#### Examples - -```html - -
- Closing will discard any changes -
- - -``` - -```javascript -const closeButton = getByRole('button', {name: 'Close'}) - -expect(closeButton).toHaveDescription('Closing will discard any changes') -expect(closeButton).toHaveDescription(/will discard/) // to partially match -expect(closeButton).toHaveDescription(expect.stringContaining('will discard')) // to partially match -expect(closeButton).toHaveDescription(/^closing/i) // to use case-insensitive match -expect(closeButton).not.toHaveDescription('Other description') - -const deleteButton = getByRole('button', {name: 'Delete'}) -expect(deleteButton).not.toHaveDescription() -expect(deleteButton).toHaveDescription('') // Missing or empty description always becomes a blank string -``` - ### `toHaveErrorMessage` ```typescript @@ -1187,8 +1111,36 @@ expect(timeInput).not.toHaveErrorMessage('Pikachu!') ## Deprecated matchers +### `toBeEmpty` + +> Note: This matcher is being deprecated due to a name clash with +> `jest-extended`. See more info in #216. In the future, please use only +> [`toBeEmptyDOMElement`](#toBeEmptyDOMElement) + +```typescript +toBeEmpty() +``` + +This allows you to assert whether an element has content or not. + +#### Examples + +```html + +``` + +```javascript +expect(getByTestId('empty')).toBeEmpty() +expect(getByTestId('not-empty')).not.toBeEmpty() +``` + +
+ ### `toBeInTheDOM` +> This custom matcher is deprecated. Prefer +> [`toBeInTheDocument`](#tobeinthedocument) instead. + ```typescript toBeInTheDOM() ``` @@ -1219,6 +1171,62 @@ expect(document.querySelector('.cancel-button')).toBeTruthy() > replacing `toBeInTheDOM` to read through the documentation of the proposed > alternatives to see which use case works better for your needs. +### `toHaveDescription` + +> This custom matcher is deprecated. Prefer +> [`toHaveAccessibleDescription`](#tohaveaccessibledescription) instead, which +> is more comprehensive in implementing the official spec. + +```typescript +toHaveDescription(text: string | RegExp) +``` + +This allows you to check whether the given element has a description or not. + +An element gets its description via the +[`aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute). +Set this to the `id` of one or more other elements. These elements may be nested +inside, be outside, or a sibling of the passed in element. + +Whitespace is normalized. Using multiple ids will +[join the referenced elements’ text content separated by a space](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description). + +When a `string` argument is passed through, it will perform a whole +case-sensitive match to the description text. + +To perform a case-insensitive match, you can use a `RegExp` with the `/i` +modifier. + +To perform a partial match, you can pass a `RegExp` or use +`expect.stringContaining("partial string")`. + +#### Examples + +```html + +
+ Closing will discard any changes +
+ + +``` + +```javascript +const closeButton = getByRole('button', {name: 'Close'}) + +expect(closeButton).toHaveDescription('Closing will discard any changes') +expect(closeButton).toHaveDescription(/will discard/) // to partially match +expect(closeButton).toHaveDescription(expect.stringContaining('will discard')) // to partially match +expect(closeButton).toHaveDescription(/^closing/i) // to use case-insensitive match +expect(closeButton).not.toHaveDescription('Other description') + +const deleteButton = getByRole('button', {name: 'Delete'}) +expect(deleteButton).not.toHaveDescription() +expect(deleteButton).toHaveDescription('') // Missing or empty description always becomes a blank string +``` + ## Inspiration This whole library was extracted out of Kent C. Dodds' [DOM Testing diff --git a/src/__tests__/to-have-accessible-description.js b/src/__tests__/to-have-accessible-description.js index 97527e52..49c7f20d 100644 --- a/src/__tests__/to-have-accessible-description.js +++ b/src/__tests__/to-have-accessible-description.js @@ -56,4 +56,54 @@ describe('.toHaveAccessibleDescription', () => { expect(logo).not.toHaveAccessibleDescription('The logo of Our Company') }).toThrow(/expected element not to have accessible description/i) }) + + it('handles multiple ids', () => { + const {queryByTestId} = render(` +
+
First description
+
Second description
+
Third description
+ +
+
+ `) + + expect(queryByTestId('multiple')).toHaveAccessibleDescription( + 'First description Second description Third description', + ) + expect(queryByTestId('multiple')).toHaveAccessibleDescription( + /Second description Third/, + ) + expect(queryByTestId('multiple')).toHaveAccessibleDescription( + expect.stringContaining('Second description Third'), + ) + expect(queryByTestId('multiple')).toHaveAccessibleDescription( + expect.stringMatching(/Second description Third/), + ) + expect(queryByTestId('multiple')).not.toHaveAccessibleDescription( + 'Something else', + ) + expect(queryByTestId('multiple')).not.toHaveAccessibleDescription('First') + }) + + it('normalizes whitespace', () => { + const {queryByTestId} = render(` +
+ Step + 1 + of + 4 +
+
+ And + extra + description +
+
+ `) + + expect(queryByTestId('target')).toHaveAccessibleDescription( + 'Step 1 of 4 And extra description', + ) + }) }) diff --git a/src/__tests__/to-have-description.js b/src/__tests__/to-have-description.js index ffb10032..d1dbdcd4 100644 --- a/src/__tests__/to-have-description.js +++ b/src/__tests__/to-have-description.js @@ -1,6 +1,16 @@ import {render} from './helpers/test-utils' describe('.toHaveDescription', () => { + let spy + beforeAll(() => { + // @deprecated intentionally hiding warnings for test clarity + spy = jest.spyOn(console, 'warn').mockImplementation(() => {}) + }) + + afterAll(() => { + spy.mockRestore() + }) + test('handles positive test cases', () => { const {queryByTestId} = render(`
The description
diff --git a/src/to-have-description.js b/src/to-have-description.js index 61419dc7..bc9138ab 100644 --- a/src/to-have-description.js +++ b/src/to-have-description.js @@ -1,7 +1,12 @@ -import {checkHtmlElement, getMessage, normalize} from './utils' +import {checkHtmlElement, getMessage, normalize, deprecate} from './utils' // See algoritm: https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description export function toHaveDescription(htmlElement, checkWith) { + deprecate( + 'toBeInTheDOM', + 'Please use toBeInTheDocument for searching the entire document and toContainElement for searching a specific container.', + ) + checkHtmlElement(htmlElement, toHaveDescription, this) const expectsDescription = checkWith !== undefined