Skip to content

Commit 38792e9

Browse files
Feat(breaking): unify wait for element signature with testing library (#327)
* Change argument to options object * Renamed `waitForElement` to `waitFor` * Migration guide entry * Fixed typescript check * Update src/helpers/a11yAPI.js Co-authored-by: Michał Pierzchała <thymikee@gmail.com> * (Nearly) Empty migration doc for ver. 2.0 (#326) * Added migration docs section * Added to docosaurus side bar * Updated README * Increased async test timeout * Update website/docs/Migration20.md Co-authored-by: Michał Pierzchała <thymikee@gmail.com> * feat(breaking): remove legacy `debug` export (#328) * Removed global `debug` functions * Removed global `debug` from docs * Cleanup * Added migration section Co-authored-by: Michał Pierzchała <thymikee@gmail.com> Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
1 parent 6a6e614 commit 38792e9

File tree

12 files changed

+84
-55
lines changed

12 files changed

+84
-55
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ The [public API](https://callstack.github.io/react-native-testing-library/docs/a
118118

119119
- [`render`](https://callstack.github.io/react-native-testing-library/docs/api#render) – deeply renders given React element and returns helpers to query the output components.
120120
- [`fireEvent`](https://callstack.github.io/react-native-testing-library/docs/api#fireevent) - invokes named event handler on the element.
121-
- [`waitForElement`](https://callstack.github.io/react-native-testing-library/docs/api#waitforelement) - waits for non-deterministic periods of time until your element appears or times out.
121+
- [`waitFor`](https://callstack.github.io/react-native-testing-library/docs/api#waitfor) - waits for non-deterministic periods of time until your element appears or times out.
122122
- [`within`](https://callstack.github.io/react-native-testing-library/docs/api#within) - creates a queries object scoped for given element.
123123
- [`flushMicrotasksQueue`](https://callstack.github.io/react-native-testing-library/docs/api#flushmicrotasksqueue) - waits for microtasks queue to flush.
124124

src/__tests__/waitForElement.test.js renamed to src/__tests__/waitFor.test.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @flow
22
import React from 'react';
33
import { View, Text, TouchableOpacity } from 'react-native';
4-
import { render, fireEvent, waitForElement } from '..';
4+
import { render, fireEvent, waitFor } from '..';
55

66
class Banana extends React.Component<any> {
77
changeFresh = () => {
@@ -42,7 +42,7 @@ test('waits for element until it stops throwing', async () => {
4242

4343
expect(queryByText('Fresh')).toBeNull();
4444

45-
const freshBananaText = await waitForElement(() => getByText('Fresh'));
45+
const freshBananaText = await waitFor(() => getByText('Fresh'));
4646

4747
expect(freshBananaText.props.children).toBe('Fresh');
4848
});
@@ -52,7 +52,9 @@ test('waits for element until timeout is met', async () => {
5252

5353
fireEvent.press(getByName('TouchableOpacity'));
5454

55-
await expect(waitForElement(() => getByText('Fresh'), 100)).rejects.toThrow();
55+
await expect(
56+
waitFor(() => getByText('Fresh'), { timeout: 100 })
57+
).rejects.toThrow();
5658
});
5759

5860
test('waits for element with custom interval', async () => {
@@ -61,7 +63,7 @@ test('waits for element with custom interval', async () => {
6163
});
6264

6365
try {
64-
await waitForElement(() => mockFn(), 400, 200);
66+
await waitFor(() => mockFn(), { timeout: 400, interval: 200 });
6567
} catch (e) {
6668
// suppress
6769
}
@@ -77,7 +79,7 @@ test('works with fake timers', async () => {
7779
});
7880

7981
try {
80-
waitForElement(() => mockFn(), 400, 200);
82+
waitFor(() => mockFn(), { timeout: 400, interval: 200 });
8183
} catch (e) {
8284
// suppress
8385
}

src/helpers/a11yAPI.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow
22
import type { A11yRole, A11yStates, A11yState, A11yValue } from '../types.flow';
3-
import type { WaitForOptions } from './findByAPI';
3+
import type { WaitForOptions } from '../waitFor';
44
import makeQuery from './makeQuery';
55

66
type GetReturn = ReactTestInstance;

src/helpers/findByAPI.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @flow
2-
import waitForElement from '../waitForElement';
2+
import waitFor from '../waitFor';
3+
import type { WaitForOptions } from '../waitFor';
34
import {
45
getByTestId,
56
getAllByTestId,
@@ -11,22 +12,12 @@ import {
1112
getAllByDisplayValue,
1213
} from './getByAPI';
1314

14-
export type WaitForOptions = {
15-
timeout?: number,
16-
interval?: number,
17-
};
18-
1915
const makeFindQuery = <Text, Result>(
2016
instance: ReactTestInstance,
2117
getQuery: (instance: ReactTestInstance) => (text: Text) => Result,
2218
text: Text,
2319
waitForOptions: WaitForOptions
24-
): Promise<Result> =>
25-
waitForElement(
26-
() => getQuery(instance)(text),
27-
waitForOptions.timeout,
28-
waitForOptions.interval
29-
);
20+
): Promise<Result> => waitFor(() => getQuery(instance)(text), waitForOptions);
3021

3122
export const findByTestId = (instance: ReactTestInstance) => (
3223
testId: string,

src/helpers/makeQuery.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// @flow
2-
import waitForElement from '../waitForElement';
2+
import waitFor from '../waitFor';
3+
import type { WaitForOptions } from '../waitFor';
34
import {
45
ErrorWithStack,
56
prepareErrorMessage,
67
createQueryByError,
78
} from './errors';
8-
import type { WaitForOptions } from './findByAPI';
99

1010
function isNodeValid(node: ReactTestInstance) {
1111
return typeof node.type === 'string';
@@ -70,19 +70,11 @@ const makeQuery = <P: mixed, M: mixed>(
7070
};
7171

7272
const findBy = (matcher: M, waitForOptions?: WaitForOptions) => {
73-
return waitForElement(
74-
() => getBy(matcher),
75-
waitForOptions?.timeout,
76-
waitForOptions?.interval
77-
);
73+
return waitFor(() => getBy(matcher), waitForOptions);
7874
};
7975

8076
const findAllBy = (matcher: M, waitForOptions?: WaitForOptions) => {
81-
return waitForElement(
82-
() => getAllBy(matcher),
83-
waitForOptions?.timeout,
84-
waitForOptions?.interval
85-
);
77+
return waitFor(() => getAllBy(matcher), waitForOptions);
8678
};
8779

8880
return {

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import fireEvent from './fireEvent';
55
import flushMicrotasksQueue from './flushMicrotasksQueue';
66
import render from './render';
77
import shallow from './shallow';
8-
import waitForElement from './waitForElement';
8+
import waitFor from './waitFor';
99
import within from './within';
1010

1111
export { act };
@@ -14,5 +14,5 @@ export { fireEvent };
1414
export { flushMicrotasksQueue };
1515
export { render };
1616
export { shallow };
17-
export { waitForElement };
17+
export { waitFor };
1818
export { within };

src/waitForElement.js renamed to src/waitFor.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
// @flow
2-
export default function waitForElement<T>(
2+
3+
const DEFAULT_TIMEOUT = 4500;
4+
const DEFAULT_INTERVAL = 50;
5+
6+
export type WaitForOptions = {
7+
timeout?: number,
8+
interval?: number,
9+
};
10+
11+
export default function waitFor<T>(
312
expectation: () => T,
4-
timeout: number = 4500,
5-
interval: number = 50
13+
options?: WaitForOptions
614
): Promise<T> {
15+
const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
16+
const interval = options?.interval ?? DEFAULT_INTERVAL;
717
const startTime = Date.now();
18+
819
return new Promise((resolve, reject) => {
920
const rejectOrRerun = (error) => {
1021
if (Date.now() - startTime >= timeout) {

typings/__tests__/index.test.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
fireEvent,
77
shallow,
88
flushMicrotasksQueue,
9-
waitForElement,
9+
waitFor,
1010
act,
1111
within,
1212
} from '../..';
@@ -250,12 +250,13 @@ const shallowTree: { output: React.ReactElement<any> } = shallow(
250250

251251
const waitForFlush: Promise<any> = flushMicrotasksQueue();
252252

253-
const waitBy: Promise<ReactTestInstance> = waitForElement<ReactTestInstance>(
254-
() => tree.getByName('View')
253+
const waitBy: Promise<ReactTestInstance> = waitFor<ReactTestInstance>(() =>
254+
tree.getByName('View')
255+
);
256+
const waitByAll: Promise<ReactTestInstance[]> = waitFor<ReactTestInstance[]>(
257+
() => tree.getAllByName('View'),
258+
{ timeout: 1000, interval: 50 }
255259
);
256-
const waitByAll: Promise<Array<ReactTestInstance>> = waitForElement<
257-
Array<ReactTestInstance>
258-
>(() => tree.getAllByName('View'), 1000, 50);
259260

260261
act(() => {
261262
render(<TestComponent />);

typings/index.d.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,14 @@ export type FireEventAPI = FireEventFunction & {
224224
scroll: (element: ReactTestInstance, ...data: Array<any>) => any;
225225
};
226226

227-
export type WaitForElementFunction = <T = any>(
227+
type WaitForOptions = {
228+
timeout?: number;
229+
interval?: number;
230+
};
231+
232+
export type WaitForFunction = <T = any>(
228233
expectation: () => T,
229-
timeout?: number,
230-
interval?: number
234+
options?: WaitForOptions
231235
) => Promise<T>;
232236

233237
export declare const render: (
@@ -240,6 +244,6 @@ export declare const shallow: <P = {}>(
240244
export declare const flushMicrotasksQueue: () => Promise<any>;
241245
export declare const cleanup: () => void;
242246
export declare const fireEvent: FireEventAPI;
243-
export declare const waitForElement: WaitForElementFunction;
247+
export declare const waitFor: WaitForFunction;
244248
export declare const act: (callback: () => void) => Thenable;
245249
export declare const within: (instance: ReactTestInstance) => Queries;

website/docs/API.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,29 +313,28 @@ fireEvent.scroll(getByType(ScrollView), eventData);
313313
expect(onEndReached).toHaveBeenCalled();
314314
```
315315

316-
## `waitForElement`
316+
## `waitFor`
317317

318-
- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitForElement.test.js)
318+
- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitFor.test.js)
319319

320320
Defined as:
321321

322322
```jsx
323-
function waitForElement<T>(
323+
function waitFor<T>(
324324
expectation: () => T,
325-
timeout: number = 4500,
326-
interval: number = 50
325+
{ timeout: number = 4500, interval: number = 50 }
327326
): Promise<T> {}
328327
```
329328

330-
Waits for non-deterministic periods of time until your element appears or times out. `waitForElement` periodically calls `expectation` every `interval` milliseconds to determine whether the element appeared or not.
329+
Waits for non-deterministic periods of time until your element appears or times out. `waitFor` periodically calls `expectation` every `interval` milliseconds to determine whether the element appeared or not.
331330

332331
```jsx
333-
import { render, waitForElement } from 'react-testing-library';
332+
import { render, waitFor } from 'react-testing-library';
334333

335334
test('waiting for an Banana to be ready', async () => {
336335
const { getByText } = render(<Banana />);
337336

338-
await waitForElement(() => getByText('Banana ready'));
337+
await waitFor(() => getByText('Banana ready'));
339338
});
340339
```
341340

website/docs/Migration20.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@ title: Migration to 2.0
55

66
This guides describes major steps involved in migrating your testing code from using React Native Testing Library version `1.x` to version `2.0`.
77

8+
## WaitFor API changes
9+
10+
`waitForElement` function has been renamed to `waitFor` for consistency with React Testing Library. Additionally the signature has slightly changed from:
11+
12+
```jsx
13+
export default function waitForElement<T>(
14+
expectation: () => T,
15+
timeout?: number,
16+
interval?: number
17+
: Promise<T> {
18+
```
19+
20+
to:
21+
22+
```jsx
23+
export default function waitFor<T>(
24+
expectation: () => T,
25+
{
26+
timeout?: number,
27+
interval?: number
28+
}
29+
): Promise<T> {
30+
```
31+
32+
Both changes should improve code readibility.
33+
34+
:::note
35+
Please note that in many cases `waitFor` call can be replaced by proper use of `findBy` asynchonous queries resulting in more streamlined test code.
36+
:::
837
938
## Removed global `debug` function
1039

website/docs/Queries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ title: Queries
3333
`findAllBy` queries return a promise which resolves to an array when any matching elements are found. The promise is rejected if no elements match after a default timeout of 4500ms.
3434

3535
:::info
36-
`findBy` and `findAllBy` queries accept optional `waitForOptions` object argument which can contain `timeout` and `interval` properies which have the same meaning as respective arguments to [`waitForElement`](https://callstack.github.io/react-native-testing-library/docs/api#waitforelement) function.
36+
`findBy` and `findAllBy` queries accept optional `waitForOptions` object argument which can contain `timeout` and `interval` properies which have the same meaning as respective options for [`waitFor`](https://callstack.github.io/react-native-testing-library/docs/api#waitfor) function.
3737
:::
3838

3939
## Queries

0 commit comments

Comments
 (0)