-
Notifications
You must be signed in to change notification settings - Fork 399
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add
toHaveDisplayValue()
matcher (#223)
* Introduce .toHaveDisplay() custom matcher * Improve docs by showing getByLabelText usage * Apply suggestions from code review * Add input and textarea examples to readme * Add support for input and textarea elements * Update README.md * Update docs description to match the new elements supported * Add value change expects for input, select and textarea Co-authored-by: Toni Villena <[email protected]> Co-authored-by: Ernesto García <[email protected]>
- Loading branch information
1 parent
779448f
commit 840414f
Showing
4 changed files
with
224 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import {render} from './helpers/test-utils' | ||
|
||
test('it should work as expected', () => { | ||
const {queryByTestId} = render(` | ||
<select id="fruits" data-testid="select"> | ||
<option value="">Select a fruit...</option> | ||
<option value="ananas">Ananas</option> | ||
<option value="banana">Banana</option> | ||
<option value="avocado">Avocado</option> | ||
</select> | ||
`) | ||
|
||
expect(queryByTestId('select')).toHaveDisplayValue('Select a fruit...') | ||
expect(queryByTestId('select')).not.toHaveDisplayValue('Banana') | ||
expect(() => | ||
expect(queryByTestId('select')).not.toHaveDisplayValue('Select a fruit...'), | ||
).toThrow() | ||
expect(() => | ||
expect(queryByTestId('select')).toHaveDisplayValue('Ananas'), | ||
).toThrow() | ||
|
||
queryByTestId('select').value = 'banana' | ||
expect(queryByTestId('select')).toHaveDisplayValue('Banana') | ||
}) | ||
|
||
test('it should work with select multiple', () => { | ||
const {queryByTestId} = render(` | ||
<select id="fruits" data-testid="select" multiple> | ||
<option value="">Select a fruit...</option> | ||
<option value="ananas" selected>Ananas</option> | ||
<option value="banana">Banana</option> | ||
<option value="avocado" selected>Avocado</option> | ||
</select> | ||
`) | ||
|
||
expect(queryByTestId('select')).toHaveDisplayValue(['Ananas', 'Avocado']) | ||
expect(() => | ||
expect(queryByTestId('select')).not.toHaveDisplayValue([ | ||
'Ananas', | ||
'Avocado', | ||
]), | ||
).toThrow() | ||
|
||
expect(queryByTestId('select')).not.toHaveDisplayValue('Ananas') | ||
expect(() => | ||
expect(queryByTestId('select')).toHaveDisplayValue('Ananas'), | ||
).toThrow() | ||
|
||
Array.from(queryByTestId('select').options).forEach(option => { | ||
option.selected = ['ananas', 'banana'].includes(option.value) | ||
}) | ||
|
||
expect(queryByTestId('select')).toHaveDisplayValue(['Ananas', 'Banana']) | ||
}) | ||
|
||
test('it should work with input elements', () => { | ||
const {queryByTestId} = render(` | ||
<input type="text" data-testid="input" value="Luca" /> | ||
`) | ||
|
||
expect(queryByTestId('input')).toHaveDisplayValue('Luca') | ||
|
||
queryByTestId('input').value = 'Piero' | ||
expect(queryByTestId('input')).toHaveDisplayValue('Piero') | ||
}) | ||
|
||
test('it should work with textarea elements', () => { | ||
const {queryByTestId} = render( | ||
'<textarea data-testid="textarea-example">An example description here.</textarea>', | ||
) | ||
|
||
expect(queryByTestId('textarea-example')).toHaveDisplayValue( | ||
'An example description here.', | ||
) | ||
|
||
queryByTestId('textarea-example').value = 'Another example' | ||
expect(queryByTestId('textarea-example')).toHaveDisplayValue( | ||
'Another example', | ||
) | ||
}) | ||
|
||
test('it should throw if element is not valid', () => { | ||
const {queryByTestId} = render(` | ||
<div data-testid="div">Banana</div> | ||
<input type="radio" data-testid="radio" value="Something" /> | ||
<input type="checkbox" data-testid="checkbox" /> | ||
`) | ||
|
||
let errorMessage | ||
try { | ||
expect(queryByTestId('div')).toHaveDisplayValue('Banana') | ||
} catch (err) { | ||
errorMessage = err.message | ||
} | ||
|
||
expect(errorMessage).toMatchInlineSnapshot( | ||
`".toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead."`, | ||
) | ||
|
||
try { | ||
expect(queryByTestId('radio')).toHaveDisplayValue('Something') | ||
} catch (err) { | ||
errorMessage = err.message | ||
} | ||
|
||
expect(errorMessage).toMatchInlineSnapshot( | ||
`".toHaveDisplayValue() currently does not support input[type=\\"radio\\"], try with another matcher instead."`, | ||
) | ||
|
||
try { | ||
expect(queryByTestId('checkbox')).toHaveDisplayValue(true) | ||
} catch (err) { | ||
errorMessage = err.message | ||
} | ||
|
||
expect(errorMessage).toMatchInlineSnapshot( | ||
`".toHaveDisplayValue() currently does not support input[type=\\"checkbox\\"], try with another matcher instead."`, | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import {matcherHint} from 'jest-matcher-utils' | ||
|
||
import {checkHtmlElement, getMessage} from './utils' | ||
|
||
export function toHaveDisplayValue(htmlElement, expectedValue) { | ||
checkHtmlElement(htmlElement, toHaveDisplayValue, this) | ||
const tagName = htmlElement.tagName.toLowerCase() | ||
|
||
if (!['select', 'input', 'textarea'].includes(tagName)) { | ||
throw new Error( | ||
'.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.', | ||
) | ||
} | ||
|
||
if (tagName === 'input' && ['radio', 'checkbox'].includes(htmlElement.type)) { | ||
throw new Error( | ||
`.toHaveDisplayValue() currently does not support input[type="${htmlElement.type}"], try with another matcher instead.`, | ||
) | ||
} | ||
|
||
const value = | ||
tagName === 'select' | ||
? Array.from(htmlElement) | ||
.filter(option => option.selected) | ||
.map(option => option.textContent) | ||
.toString() | ||
: htmlElement.value | ||
|
||
return { | ||
pass: value === expectedValue.toString(), | ||
message: () => | ||
getMessage( | ||
matcherHint( | ||
`${this.isNot ? '.not' : ''}.toHaveDisplayValue`, | ||
'element', | ||
'', | ||
), | ||
`Expected element ${this.isNot ? 'not ' : ''}to have display value`, | ||
expectedValue, | ||
'Received', | ||
value, | ||
), | ||
} | ||
} |