Skip to content

Commit 5c9e8e5

Browse files
lourencignapse
andauthoredMay 7, 2020
feat: Allow to use regex on toHaveDisplayValue (#242)
* Allow to use regex on non-multiple value on toHaveDisplayValue * Allow to use regex on multiple value on toHaveDisplayValue * Do some refactor * Split specs in contexts * Update docs to describe the unordered multiple match * Add review Co-authored-by: Ernesto García <gnapse@gmail.com>
1 parent 17787f3 commit 5c9e8e5

File tree

3 files changed

+94
-35
lines changed

3 files changed

+94
-35
lines changed
 

‎README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ clear to read and to maintain.
4646
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
4747
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
4848

49+
4950
- [Installation](#installation)
5051
- [Usage](#usage)
5152
- [Custom matchers](#custom-matchers)
@@ -781,7 +782,7 @@ expect(selectInput).not.toHaveValue(['second', 'third'])
781782
### `toHaveDisplayValue`
782783

783784
```typescript
784-
toHaveDisplayValue(value: string | string[])
785+
toHaveDisplayValue(value: string | RegExp | (string|RegExp)[])
785786
```
786787

787788
This allows you to check whether the given form element has the specified
@@ -826,9 +827,12 @@ const selectSingle = screen.getByLabelText('Fruit')
826827
const selectMultiple = screen.getByLabelText('Fruits')
827828

828829
expect(input).toHaveDisplayValue('Luca')
830+
expect(input).toHaveDisplayValue(/Luc/)
829831
expect(textarea).toHaveDisplayValue('An example description here.')
832+
expect(textarea).toHaveDisplayValue(/example/)
830833
expect(selectSingle).toHaveDisplayValue('Select a fruit...')
831-
expect(selectMultiple).toHaveDisplayValue(['Banana', 'Avocado'])
834+
expect(selectSingle).toHaveDisplayValue(/Select/)
835+
expect(selectMultiple).toHaveDisplayValue([/Avocado/, 'Banana'])
832836
```
833837

834838
<hr />
@@ -1084,6 +1088,7 @@ Thanks goes to these people ([emoji key][emojis]):
10841088

10851089
<!-- markdownlint-enable -->
10861090
<!-- prettier-ignore-end -->
1091+
10871092
<!-- ALL-CONTRIBUTORS-LIST:END -->
10881093

10891094
This project follows the [all-contributors][all-contributors] specification.

‎src/__tests__/to-have-display-value.js

+56-22
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,68 @@ test('it should work as expected', () => {
2121

2222
queryByTestId('select').value = 'banana'
2323
expect(queryByTestId('select')).toHaveDisplayValue('Banana')
24+
expect(queryByTestId('select')).toHaveDisplayValue(/[bB]ana/)
2425
})
2526

26-
test('it should work with select multiple', () => {
27-
const {queryByTestId} = render(`
28-
<select id="fruits" data-testid="select" multiple>
29-
<option value="">Select a fruit...</option>
30-
<option value="ananas" selected>Ananas</option>
31-
<option value="banana">Banana</option>
32-
<option value="avocado" selected>Avocado</option>
33-
</select>
34-
`)
27+
describe('with multiple select', () => {
28+
function mount() {
29+
return render(`
30+
<select id="fruits" data-testid="select" multiple>
31+
<option value="">Select a fruit...</option>
32+
<option value="ananas" selected>Ananas</option>
33+
<option value="banana">Banana</option>
34+
<option value="avocado" selected>Avocado</option>
35+
</select>
36+
`)
37+
}
3538

36-
expect(queryByTestId('select')).toHaveDisplayValue(['Ananas', 'Avocado'])
37-
expect(() =>
38-
expect(queryByTestId('select')).not.toHaveDisplayValue([
39+
it('matches only when all the multiple selected values are equal to all the expected values', () => {
40+
const subject = mount()
41+
expect(subject.queryByTestId('select')).toHaveDisplayValue([
3942
'Ananas',
4043
'Avocado',
41-
]),
42-
).toThrow()
43-
44-
expect(queryByTestId('select')).not.toHaveDisplayValue('Ananas')
45-
expect(() =>
46-
expect(queryByTestId('select')).toHaveDisplayValue('Ananas'),
47-
).toThrow()
44+
])
45+
expect(() =>
46+
expect(subject.queryByTestId('select')).not.toHaveDisplayValue([
47+
'Ananas',
48+
'Avocado',
49+
]),
50+
).toThrow()
51+
expect(subject.queryByTestId('select')).not.toHaveDisplayValue([
52+
'Ananas',
53+
'Avocado',
54+
'Orange',
55+
])
56+
expect(subject.queryByTestId('select')).not.toHaveDisplayValue('Ananas')
57+
expect(() =>
58+
expect(subject.queryByTestId('select')).toHaveDisplayValue('Ananas'),
59+
).toThrow()
60+
61+
Array.from(subject.queryByTestId('select').options).forEach(option => {
62+
option.selected = ['ananas', 'banana'].includes(option.value)
63+
})
64+
65+
expect(subject.queryByTestId('select')).toHaveDisplayValue([
66+
'Ananas',
67+
'Banana',
68+
])
69+
})
4870

49-
Array.from(queryByTestId('select').options).forEach(option => {
50-
option.selected = ['ananas', 'banana'].includes(option.value)
71+
it('matches even when the expected values are unordered', () => {
72+
const subject = mount()
73+
expect(subject.queryByTestId('select')).toHaveDisplayValue([
74+
'Avocado',
75+
'Ananas',
76+
])
5177
})
5278

53-
expect(queryByTestId('select')).toHaveDisplayValue(['Ananas', 'Banana'])
79+
it('matches with regex expected values', () => {
80+
const subject = mount()
81+
expect(subject.queryByTestId('select')).toHaveDisplayValue([
82+
/[Aa]nanas/,
83+
'Avocado',
84+
])
85+
})
5486
})
5587

5688
test('it should work with input elements', () => {
@@ -59,6 +91,7 @@ test('it should work with input elements', () => {
5991
`)
6092

6193
expect(queryByTestId('input')).toHaveDisplayValue('Luca')
94+
expect(queryByTestId('input')).toHaveDisplayValue(/Luc/)
6295

6396
queryByTestId('input').value = 'Piero'
6497
expect(queryByTestId('input')).toHaveDisplayValue('Piero')
@@ -72,6 +105,7 @@ test('it should work with textarea elements', () => {
72105
expect(queryByTestId('textarea-example')).toHaveDisplayValue(
73106
'An example description here.',
74107
)
108+
expect(queryByTestId('textarea-example')).toHaveDisplayValue(/example/)
75109

76110
queryByTestId('textarea-example').value = 'Another example'
77111
expect(queryByTestId('textarea-example')).toHaveDisplayValue(

‎src/to-have-display-value.js

+31-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {matcherHint} from 'jest-matcher-utils'
2-
3-
import {checkHtmlElement, getMessage} from './utils'
2+
import {matches, checkHtmlElement, getMessage} from './utils'
43

54
export function toHaveDisplayValue(htmlElement, expectedValue) {
65
checkHtmlElement(htmlElement, toHaveDisplayValue, this)
@@ -18,16 +17,19 @@ export function toHaveDisplayValue(htmlElement, expectedValue) {
1817
)
1918
}
2019

21-
const value =
22-
tagName === 'select'
23-
? Array.from(htmlElement)
24-
.filter(option => option.selected)
25-
.map(option => option.textContent)
26-
.toString()
27-
: htmlElement.value
20+
const values = getValues(tagName, htmlElement)
21+
const expectedValues = getExpectedValues(expectedValue)
22+
const numberOfMatchesWithValues = getNumberOfMatchesBetweenArrays(
23+
values,
24+
expectedValues,
25+
)
26+
27+
const matchedWithAllValues = numberOfMatchesWithValues === values.length
28+
const matchedWithAllExpectedValues =
29+
numberOfMatchesWithValues === expectedValues.length
2830

2931
return {
30-
pass: value === expectedValue.toString(),
32+
pass: matchedWithAllValues && matchedWithAllExpectedValues,
3133
message: () =>
3234
getMessage(
3335
matcherHint(
@@ -38,7 +40,25 @@ export function toHaveDisplayValue(htmlElement, expectedValue) {
3840
`Expected element ${this.isNot ? 'not ' : ''}to have display value`,
3941
expectedValue,
4042
'Received',
41-
value,
43+
values,
4244
),
4345
}
4446
}
47+
48+
function getValues(tagName, htmlElement) {
49+
return tagName === 'select'
50+
? Array.from(htmlElement)
51+
.filter(option => option.selected)
52+
.map(option => option.textContent)
53+
: [htmlElement.value]
54+
}
55+
56+
function getExpectedValues(expectedValue) {
57+
return expectedValue instanceof Array ? expectedValue : [expectedValue]
58+
}
59+
60+
function getNumberOfMatchesBetweenArrays(arrayBase, array) {
61+
return array.filter(
62+
expected => arrayBase.filter(value => matches(value, expected)).length,
63+
).length
64+
}

0 commit comments

Comments
 (0)
Please sign in to comment.