Skip to content

Commit 701433c

Browse files
Hugo Dupratmdjastrzebski
Hugo Duprat
andauthored
feat: toBeBusy() matcher (#1493)
* feat: create always passing toBeBusy() matcher * test: prepare toBeBusy() tests * feat: implement toBeBusy() passing condition * feat: implement error message * test: update error message snapshots to correct format * refactor: use screen variable * refactor: tweaks * refactor: cleanup * refactor: clean up * refactor: finishing touches --------- Co-authored-by: Maciej Jastrzębski <mdjastrzebski@gmail.com>
1 parent 1592d35 commit 701433c

File tree

8 files changed

+146
-11
lines changed

8 files changed

+146
-11
lines changed

src/helpers/accessiblity.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,6 @@ export function getAccessibilityCheckedState(
176176
return ariaChecked ?? accessibilityState?.checked;
177177
}
178178

179-
export function getAccessibilitySelectedState(
180-
element: ReactTestInstance
181-
): NonNullable<AccessibilityState['selected']> {
182-
const { accessibilityState, 'aria-selected': ariaSelected } = element.props;
183-
return ariaSelected ?? accessibilityState?.selected ?? false;
184-
}
185-
186179
export function getAccessibilityValue(
187180
element: ReactTestInstance
188181
): AccessibilityValue | undefined {
@@ -212,3 +205,17 @@ export function getAccessibilityValue(
212205
text: ariaValueText ?? accessibilityValue?.text,
213206
};
214207
}
208+
209+
export function isElementBusy(
210+
element: ReactTestInstance
211+
): NonNullable<AccessibilityState['busy']> {
212+
const { accessibilityState, 'aria-busy': ariaBusy } = element.props;
213+
return ariaBusy ?? accessibilityState?.busy ?? false;
214+
}
215+
216+
export function isElementSelected(
217+
element: ReactTestInstance
218+
): NonNullable<AccessibilityState['selected']> {
219+
const { accessibilityState, 'aria-selected': ariaSelected } = element.props;
220+
return ariaSelected ?? accessibilityState?.selected ?? false;
221+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import * as React from 'react';
2+
import { View } from 'react-native';
3+
import { render, screen } from '../..';
4+
import '../extend-expect';
5+
6+
test('toBeBusy() basic case', () => {
7+
render(
8+
<>
9+
<View testID="busy" accessibilityState={{ busy: true }} />
10+
<View testID="busy-aria" aria-busy />
11+
<View testID="not-busy" accessibilityState={{ busy: false }} />
12+
<View testID="not-busy-aria" aria-busy={false} />
13+
<View testID="default" />
14+
</>
15+
);
16+
17+
expect(screen.getByTestId('busy')).toBeBusy();
18+
expect(screen.getByTestId('busy-aria')).toBeBusy();
19+
expect(screen.getByTestId('not-busy')).not.toBeBusy();
20+
expect(screen.getByTestId('not-busy-aria')).not.toBeBusy();
21+
expect(screen.getByTestId('default')).not.toBeBusy();
22+
});
23+
24+
test('toBeBusy() error messages', () => {
25+
render(
26+
<>
27+
<View testID="busy" accessibilityState={{ busy: true }} />
28+
<View testID="busy-aria" aria-busy />
29+
<View testID="not-busy" accessibilityState={{ busy: false }} />
30+
<View testID="not-busy-aria" aria-busy={false} />
31+
<View testID="default" />
32+
</>
33+
);
34+
35+
expect(() => expect(screen.getByTestId('busy')).not.toBeBusy())
36+
.toThrowErrorMatchingInlineSnapshot(`
37+
"expect(element).not.toBeBusy()
38+
39+
Received element is busy:
40+
<View
41+
accessibilityState={
42+
{
43+
"busy": true,
44+
}
45+
}
46+
testID="busy"
47+
/>"
48+
`);
49+
50+
expect(() => expect(screen.getByTestId('busy-aria')).not.toBeBusy())
51+
.toThrowErrorMatchingInlineSnapshot(`
52+
"expect(element).not.toBeBusy()
53+
54+
Received element is busy:
55+
<View
56+
aria-busy={true}
57+
testID="busy-aria"
58+
/>"
59+
`);
60+
61+
expect(() => expect(screen.getByTestId('not-busy')).toBeBusy())
62+
.toThrowErrorMatchingInlineSnapshot(`
63+
"expect(element).toBeBusy()
64+
65+
Received element is not busy:
66+
<View
67+
accessibilityState={
68+
{
69+
"busy": false,
70+
}
71+
}
72+
testID="not-busy"
73+
/>"
74+
`);
75+
76+
expect(() => expect(screen.getByTestId('not-busy-aria')).toBeBusy())
77+
.toThrowErrorMatchingInlineSnapshot(`
78+
"expect(element).toBeBusy()
79+
80+
Received element is not busy:
81+
<View
82+
aria-busy={false}
83+
testID="not-busy-aria"
84+
/>"
85+
`);
86+
87+
expect(() => expect(screen.getByTestId('default')).toBeBusy())
88+
.toThrowErrorMatchingInlineSnapshot(`
89+
"expect(element).toBeBusy()
90+
91+
Received element is not busy:
92+
<View
93+
testID="default"
94+
/>"
95+
`);
96+
});

src/matchers/__tests__/to-be-selected.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { View } from 'react-native';
33
import { render, screen } from '../..';
44
import '../extend-expect';
55

6-
test('.toBeSelected() basic case', () => {
6+
test('toBeSelected() basic case', () => {
77
render(
88
<>
99
<View testID="selected" accessibilityState={{ selected: true }} />
@@ -21,7 +21,7 @@ test('.toBeSelected() basic case', () => {
2121
expect(screen.getByTestId('default')).not.toBeSelected();
2222
});
2323

24-
test('.toBeSelected() error messages', () => {
24+
test('toBeSelected() error messages', () => {
2525
render(
2626
<>
2727
<View testID="selected" accessibilityState={{ selected: true }} />

src/matchers/extend-expect.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export interface JestNativeMatchers<R> {
44
toBeOnTheScreen(): R;
55
toBeChecked(): R;
66
toBeDisabled(): R;
7+
toBeBusy(): R;
78
toBeEmptyElement(): R;
89
toBeEnabled(): R;
910
toBePartiallyChecked(): R;

src/matchers/extend-expect.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { toBeOnTheScreen } from './to-be-on-the-screen';
44
import { toBeChecked } from './to-be-checked';
55
import { toBeDisabled, toBeEnabled } from './to-be-disabled';
6+
import { toBeBusy } from './to-be-busy';
67
import { toBeEmptyElement } from './to-be-empty-element';
78
import { toBePartiallyChecked } from './to-be-partially-checked';
89
import { toBeSelected } from './to-be-selected';
@@ -15,6 +16,7 @@ expect.extend({
1516
toBeOnTheScreen,
1617
toBeChecked,
1718
toBeDisabled,
19+
toBeBusy,
1820
toBeEmptyElement,
1921
toBeEnabled,
2022
toBePartiallyChecked,

src/matchers/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export { toBeOnTheScreen } from './to-be-on-the-screen';
22
export { toBeChecked } from './to-be-checked';
33
export { toBeDisabled, toBeEnabled } from './to-be-disabled';
4+
export { toBeBusy } from './to-be-busy';
45
export { toBeEmptyElement } from './to-be-empty-element';
56
export { toBePartiallyChecked } from './to-be-partially-checked';
67
export { toBeVisible } from './to-be-visible';

src/matchers/to-be-busy.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { ReactTestInstance } from 'react-test-renderer';
2+
import { matcherHint } from 'jest-matcher-utils';
3+
import { isElementBusy } from '../helpers/accessiblity';
4+
import { checkHostElement, formatElement } from './utils';
5+
6+
export function toBeBusy(
7+
this: jest.MatcherContext,
8+
element: ReactTestInstance
9+
) {
10+
checkHostElement(element, toBeBusy, this);
11+
12+
return {
13+
pass: isElementBusy(element),
14+
message: () => {
15+
const matcher = matcherHint(
16+
`${this.isNot ? '.not' : ''}.toBeBusy`,
17+
'element',
18+
''
19+
);
20+
return [
21+
matcher,
22+
'',
23+
`Received element is ${this.isNot ? '' : 'not '}busy:`,
24+
formatElement(element),
25+
].join('\n');
26+
},
27+
};
28+
}

src/matchers/to-be-selected.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ReactTestInstance } from 'react-test-renderer';
22
import { matcherHint } from 'jest-matcher-utils';
3-
import { getAccessibilitySelectedState } from '../helpers/accessiblity';
3+
import { isElementSelected } from '../helpers/accessiblity';
44
import { checkHostElement, formatElement } from './utils';
55

66
export function toBeSelected(
@@ -10,7 +10,7 @@ export function toBeSelected(
1010
checkHostElement(element, toBeSelected, this);
1111

1212
return {
13-
pass: getAccessibilitySelectedState(element),
13+
pass: isElementSelected(element),
1414
message: () => {
1515
const is = this.isNot ? 'is' : 'is not';
1616
return [

0 commit comments

Comments
 (0)