Skip to content

Commit 90b2038

Browse files
tarunrajputmdjastrzebski
authored andcommitted
feat: add toHaveAccessibilityValue matcher
1 parent 328466d commit 90b2038

File tree

5 files changed

+192
-0
lines changed

5 files changed

+192
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import * as React from 'react';
2+
import { View } from 'react-native';
3+
import { render, screen } from '../..';
4+
import '../extend-expect';
5+
6+
function renderViewsWithAccessibilityValue() {
7+
return render(
8+
<>
9+
<View testID="min" accessibilityValue={{ min: 0 }} />
10+
<View testID="max" accessibilityValue={{ max: 100 }} />
11+
<View testID="now" accessibilityValue={{ now: 65 }} />
12+
<View testID="min-max" accessibilityValue={{ min: 0, max: 100 }} />
13+
<View
14+
testID="min-max-now"
15+
accessibilityValue={{ min: 0, max: 100, now: 65 }}
16+
/>
17+
<View
18+
testID="min-max-now-text"
19+
accessibilityValue={{ text: 'test', min: 0, max: 100, now: 65 }}
20+
/>
21+
<View
22+
testID="text"
23+
accessibilityValue={{ text: 'accessibility value' }}
24+
/>
25+
</>
26+
);
27+
}
28+
29+
test('toHaveAccessibilityValue() on matching accessibility value', () => {
30+
renderViewsWithAccessibilityValue();
31+
32+
const min = screen.getByTestId('min');
33+
const max = screen.getByTestId('max');
34+
const now = screen.getByTestId('now');
35+
const text = screen.getByTestId('text');
36+
const minMax = screen.getByTestId('min-max');
37+
const minMaxNow = screen.getByTestId('min-max-now');
38+
const minMaxNowText = screen.getByTestId('min-max-now-text');
39+
40+
expect(min).toHaveAccessibilityValue({ min: 0 });
41+
expect(max).toHaveAccessibilityValue({ max: 100 });
42+
expect(now).toHaveAccessibilityValue({ now: 65 });
43+
expect(minMax).toHaveAccessibilityValue({ min: 0, max: 100 });
44+
expect(minMaxNowText).toHaveAccessibilityValue({
45+
min: 0,
46+
max: 100,
47+
now: 65,
48+
text: 'test',
49+
});
50+
expect(minMaxNow).toHaveAccessibilityValue({ min: 0, max: 100, now: 65 });
51+
expect(text).toHaveAccessibilityValue({ text: 'accessibility value' });
52+
expect(text).toHaveAccessibilityValue({ text: /accessibility/i });
53+
54+
expect(() => expect(min).not.toHaveAccessibilityValue({ min: 0 }))
55+
.toThrowErrorMatchingInlineSnapshot(`
56+
"expect(element).not.toHaveAccessibilityValue({"min": 0})
57+
58+
Expected the element not to have accessibility value:
59+
{"min": 0}
60+
Received element with accessibility value:
61+
{"max": undefined, "min": 0, "now": undefined, "text": undefined}"
62+
`);
63+
64+
expect(() => expect(text).toHaveAccessibilityValue({ text: 'value' }))
65+
.toThrowErrorMatchingInlineSnapshot(`
66+
"expect(element).toHaveAccessibilityValue({"text": "value"})
67+
68+
Expected the element to have accessibility value:
69+
{"text": "value"}
70+
Received element with accessibility value:
71+
{"max": undefined, "min": undefined, "now": undefined, "text": "accessibility value"}"
72+
`);
73+
74+
expect(() => expect(text).toHaveAccessibilityValue({ text: /test/i }))
75+
.toThrowErrorMatchingInlineSnapshot(`
76+
"expect(element).toHaveAccessibilityValue({"text": /test/i})
77+
78+
Expected the element to have accessibility value:
79+
{"text": /test/i}
80+
Received element with accessibility value:
81+
{"max": undefined, "min": undefined, "now": undefined, "text": "accessibility value"}"
82+
`);
83+
});
84+
85+
test('toHaveAccessibilityValue() on non-matching accessibility value', () => {
86+
renderViewsWithAccessibilityValue();
87+
88+
const min = screen.getByTestId('min');
89+
const max = screen.getByTestId('max');
90+
const now = screen.getByTestId('now');
91+
const text = screen.getByTestId('text');
92+
const minMax = screen.getByTestId('min-max');
93+
const minMaxNow = screen.getByTestId('min-max-now');
94+
const minMaxNowText = screen.getByTestId('min-max-now-text');
95+
96+
expect(min).not.toHaveAccessibilityValue({ min: 100 });
97+
expect(max).not.toHaveAccessibilityValue({ max: 0 });
98+
expect(now).not.toHaveAccessibilityValue({ now: 0 });
99+
expect(text).not.toHaveAccessibilityValue({ text: 'accessibility' });
100+
expect(minMax).not.toHaveAccessibilityValue({ min: 100, max: 0 });
101+
expect(minMaxNow).not.toHaveAccessibilityValue({ min: 100, max: 0, now: 0 });
102+
expect(minMaxNowText).not.toHaveAccessibilityValue({
103+
min: 100,
104+
max: 0,
105+
now: 0,
106+
text: 'accessibility',
107+
});
108+
109+
expect(() => expect(min).toHaveAccessibilityValue({ min: 100 }))
110+
.toThrowErrorMatchingInlineSnapshot(`
111+
"expect(element).toHaveAccessibilityValue({"min": 100})
112+
113+
Expected the element to have accessibility value:
114+
{"min": 100}
115+
Received element with accessibility value:
116+
{"max": undefined, "min": 0, "now": undefined, "text": undefined}"
117+
`);
118+
});
119+
120+
test('toHaveAccessibilityValue() when no accessibilityValue prop is provided', () => {
121+
render(<View testID="view" />);
122+
123+
const view = screen.getByTestId('view');
124+
125+
expect(() => expect(view).toHaveAccessibilityValue({ min: 0 }))
126+
.toThrowErrorMatchingInlineSnapshot(`
127+
"expect(element).toHaveAccessibilityValue({"min": 0})
128+
129+
Expected the element to have accessibility value:
130+
{"min": 0}
131+
Received element with accessibility value:
132+
undefined"
133+
`);
134+
});
135+
136+
test('toHaveAccessibilityValue() on partially matching accessibility value', () => {
137+
renderViewsWithAccessibilityValue();
138+
139+
const minMax = screen.getByTestId('min-max');
140+
const minMaxNow = screen.getByTestId('min-max-now');
141+
const minMaxNowText = screen.getByTestId('min-max-now-text');
142+
143+
expect(minMax).toHaveAccessibilityValue({ min: 0 });
144+
expect(minMax).toHaveAccessibilityValue({ max: 100 });
145+
expect(minMaxNow).toHaveAccessibilityValue({ now: 65 });
146+
expect(minMaxNow).toHaveAccessibilityValue({ min: 0, max: 100 });
147+
expect(minMaxNowText).toHaveAccessibilityValue({ text: 'test' });
148+
expect(minMaxNowText).toHaveAccessibilityValue({ text: /te/i });
149+
});

src/matchers/extend-expect.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { StyleProp } from 'react-native';
22
import type { ReactTestInstance } from 'react-test-renderer';
33
import type { TextMatch, TextMatchOptions } from '../matches';
4+
import type { AccessibilityValueMatcher } from '../helpers/matchers/accessibilityValue';
45
import type { Style } from './to-have-style';
56

67
export interface JestNativeMatchers<R> {
@@ -20,6 +21,7 @@ export interface JestNativeMatchers<R> {
2021
toHaveProp(name: string, expectedValue?: unknown): R;
2122
toHaveStyle(style: StyleProp<Style>): R;
2223
toHaveTextContent(expectedText: TextMatch, options?: TextMatchOptions): R;
24+
toHaveAccessibilityValue(expectedValue: AccessibilityValueMatcher): R;
2325
}
2426

2527
// Implicit Jest global `expect`.

src/matchers/extend-expect.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { toHaveDisplayValue } from './to-have-display-value';
1515
import { toHaveProp } from './to-have-prop';
1616
import { toHaveStyle } from './to-have-style';
1717
import { toHaveTextContent } from './to-have-text-content';
18+
import { toHaveAccessibilityValue } from './to-have-accessibility-value';
1819

1920
expect.extend({
2021
toBeOnTheScreen,
@@ -33,4 +34,5 @@ expect.extend({
3334
toHaveProp,
3435
toHaveStyle,
3536
toHaveTextContent,
37+
toHaveAccessibilityValue,
3638
});

src/matchers/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export { toBePartiallyChecked } from './to-be-partially-checked';
99
export { toBeSelected } from './to-be-selected';
1010
export { toBeVisible } from './to-be-visible';
1111
export { toContainElement } from './to-contain-element';
12+
export { toHaveAccessibilityValue } from './to-have-accessibility-value';
1213
export { toHaveDisplayValue } from './to-have-display-value';
1314
export { toHaveProp } from './to-have-prop';
1415
export { toHaveStyle } from './to-have-style';
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { ReactTestInstance } from 'react-test-renderer';
2+
import { matcherHint, stringify } from 'jest-matcher-utils';
3+
import { getAccessibilityValue } from '../helpers/accessiblity';
4+
import {
5+
AccessibilityValueMatcher,
6+
matchAccessibilityValue,
7+
} from '../helpers/matchers/accessibilityValue';
8+
import { checkHostElement, formatMessage } from './utils';
9+
10+
export function toHaveAccessibilityValue(
11+
this: jest.MatcherContext,
12+
element: ReactTestInstance,
13+
expectedValue: AccessibilityValueMatcher
14+
) {
15+
checkHostElement(element, toHaveAccessibilityValue, this);
16+
17+
const value = getAccessibilityValue(element);
18+
19+
return {
20+
pass: matchAccessibilityValue(element, expectedValue),
21+
message: () => {
22+
const matcher = matcherHint(
23+
`${this.isNot ? '.not' : ''}.toHaveAccessibilityValue`,
24+
'element',
25+
stringify(expectedValue)
26+
);
27+
return formatMessage(
28+
matcher,
29+
`Expected the element ${
30+
this.isNot ? 'not to' : 'to'
31+
} have accessibility value`,
32+
stringify(expectedValue),
33+
'Received element with accessibility value',
34+
stringify(value)
35+
);
36+
},
37+
};
38+
}

0 commit comments

Comments
 (0)