diff --git a/README.md b/README.md index 72655a7a7..2cf3dcc68 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ The [public API](https://callstack.github.io/react-native-testing-library/docs/a - [`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. - [`fireEvent`](https://callstack.github.io/react-native-testing-library/docs/api#fireevent) - invokes named event handler on the element. -- [`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. +- [`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. - [`within`](https://callstack.github.io/react-native-testing-library/docs/api#within) - creates a queries object scoped for given element. - [`flushMicrotasksQueue`](https://callstack.github.io/react-native-testing-library/docs/api#flushmicrotasksqueue) - waits for microtasks queue to flush. diff --git a/src/__tests__/waitForElement.test.js b/src/__tests__/waitFor.test.js similarity index 83% rename from src/__tests__/waitForElement.test.js rename to src/__tests__/waitFor.test.js index 8867a4a5e..b05f1fe93 100644 --- a/src/__tests__/waitForElement.test.js +++ b/src/__tests__/waitFor.test.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; -import { render, fireEvent, waitForElement } from '..'; +import { render, fireEvent, waitFor } from '..'; class Banana extends React.Component { changeFresh = () => { @@ -42,7 +42,7 @@ test('waits for element until it stops throwing', async () => { expect(queryByText('Fresh')).toBeNull(); - const freshBananaText = await waitForElement(() => getByText('Fresh')); + const freshBananaText = await waitFor(() => getByText('Fresh')); expect(freshBananaText.props.children).toBe('Fresh'); }); @@ -52,7 +52,9 @@ test('waits for element until timeout is met', async () => { fireEvent.press(getByName('TouchableOpacity')); - await expect(waitForElement(() => getByText('Fresh'), 100)).rejects.toThrow(); + await expect( + waitFor(() => getByText('Fresh'), { timeout: 100 }) + ).rejects.toThrow(); }); test('waits for element with custom interval', async () => { @@ -61,7 +63,7 @@ test('waits for element with custom interval', async () => { }); try { - await waitForElement(() => mockFn(), 400, 200); + await waitFor(() => mockFn(), { timeout: 400, interval: 200 }); } catch (e) { // suppress } @@ -77,7 +79,7 @@ test('works with fake timers', async () => { }); try { - waitForElement(() => mockFn(), 400, 200); + waitFor(() => mockFn(), { timeout: 400, interval: 200 }); } catch (e) { // suppress } diff --git a/src/helpers/a11yAPI.js b/src/helpers/a11yAPI.js index 40598b9b5..77f1b063e 100644 --- a/src/helpers/a11yAPI.js +++ b/src/helpers/a11yAPI.js @@ -1,6 +1,6 @@ // @flow import type { A11yRole, A11yStates, A11yState, A11yValue } from '../types.flow'; -import type { WaitForOptions } from './findByAPI'; +import type { WaitForOptions } from '../waitFor'; import makeQuery from './makeQuery'; type GetReturn = ReactTestInstance; diff --git a/src/helpers/findByAPI.js b/src/helpers/findByAPI.js index ea4fb1a7a..058f51fda 100644 --- a/src/helpers/findByAPI.js +++ b/src/helpers/findByAPI.js @@ -1,5 +1,6 @@ // @flow -import waitForElement from '../waitForElement'; +import waitFor from '../waitFor'; +import type { WaitForOptions } from '../waitFor'; import { getByTestId, getAllByTestId, @@ -11,22 +12,12 @@ import { getAllByDisplayValue, } from './getByAPI'; -export type WaitForOptions = { - timeout?: number, - interval?: number, -}; - const makeFindQuery = ( instance: ReactTestInstance, getQuery: (instance: ReactTestInstance) => (text: Text) => Result, text: Text, waitForOptions: WaitForOptions -): Promise => - waitForElement( - () => getQuery(instance)(text), - waitForOptions.timeout, - waitForOptions.interval - ); +): Promise => waitFor(() => getQuery(instance)(text), waitForOptions); export const findByTestId = (instance: ReactTestInstance) => ( testId: string, diff --git a/src/helpers/makeQuery.js b/src/helpers/makeQuery.js index facda0fc3..04e41a18d 100644 --- a/src/helpers/makeQuery.js +++ b/src/helpers/makeQuery.js @@ -1,11 +1,11 @@ // @flow -import waitForElement from '../waitForElement'; +import waitFor from '../waitFor'; +import type { WaitForOptions } from '../waitFor'; import { ErrorWithStack, prepareErrorMessage, createQueryByError, } from './errors'; -import type { WaitForOptions } from './findByAPI'; function isNodeValid(node: ReactTestInstance) { return typeof node.type === 'string'; @@ -70,19 +70,11 @@ const makeQuery = ( }; const findBy = (matcher: M, waitForOptions?: WaitForOptions) => { - return waitForElement( - () => getBy(matcher), - waitForOptions?.timeout, - waitForOptions?.interval - ); + return waitFor(() => getBy(matcher), waitForOptions); }; const findAllBy = (matcher: M, waitForOptions?: WaitForOptions) => { - return waitForElement( - () => getAllBy(matcher), - waitForOptions?.timeout, - waitForOptions?.interval - ); + return waitFor(() => getAllBy(matcher), waitForOptions); }; return { diff --git a/src/index.js b/src/index.js index 1d73981f5..8500b3b26 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import fireEvent from './fireEvent'; import flushMicrotasksQueue from './flushMicrotasksQueue'; import render from './render'; import shallow from './shallow'; -import waitForElement from './waitForElement'; +import waitFor from './waitFor'; import within from './within'; export { act }; @@ -14,5 +14,5 @@ export { fireEvent }; export { flushMicrotasksQueue }; export { render }; export { shallow }; -export { waitForElement }; +export { waitFor }; export { within }; diff --git a/src/waitForElement.js b/src/waitFor.js similarity index 62% rename from src/waitForElement.js rename to src/waitFor.js index 5072a99b9..e947f8631 100644 --- a/src/waitForElement.js +++ b/src/waitFor.js @@ -1,10 +1,21 @@ // @flow -export default function waitForElement( + +const DEFAULT_TIMEOUT = 4500; +const DEFAULT_INTERVAL = 50; + +export type WaitForOptions = { + timeout?: number, + interval?: number, +}; + +export default function waitFor( expectation: () => T, - timeout: number = 4500, - interval: number = 50 + options?: WaitForOptions ): Promise { + const timeout = options?.timeout ?? DEFAULT_TIMEOUT; + const interval = options?.interval ?? DEFAULT_INTERVAL; const startTime = Date.now(); + return new Promise((resolve, reject) => { const rejectOrRerun = (error) => { if (Date.now() - startTime >= timeout) { diff --git a/typings/__tests__/index.test.tsx b/typings/__tests__/index.test.tsx index 209102b3e..2417ae8eb 100644 --- a/typings/__tests__/index.test.tsx +++ b/typings/__tests__/index.test.tsx @@ -6,7 +6,7 @@ import { fireEvent, shallow, flushMicrotasksQueue, - waitForElement, + waitFor, act, within, } from '../..'; @@ -250,12 +250,13 @@ const shallowTree: { output: React.ReactElement } = shallow( const waitForFlush: Promise = flushMicrotasksQueue(); -const waitBy: Promise = waitForElement( - () => tree.getByName('View') +const waitBy: Promise = waitFor(() => + tree.getByName('View') +); +const waitByAll: Promise = waitFor( + () => tree.getAllByName('View'), + { timeout: 1000, interval: 50 } ); -const waitByAll: Promise> = waitForElement< - Array ->(() => tree.getAllByName('View'), 1000, 50); act(() => { render(); diff --git a/typings/index.d.ts b/typings/index.d.ts index ef4895f1a..4fd91e76d 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -224,10 +224,14 @@ export type FireEventAPI = FireEventFunction & { scroll: (element: ReactTestInstance, ...data: Array) => any; }; -export type WaitForElementFunction = ( +type WaitForOptions = { + timeout?: number; + interval?: number; +}; + +export type WaitForFunction = ( expectation: () => T, - timeout?: number, - interval?: number + options?: WaitForOptions ) => Promise; export declare const render: ( @@ -240,6 +244,6 @@ export declare const shallow:

( export declare const flushMicrotasksQueue: () => Promise; export declare const cleanup: () => void; export declare const fireEvent: FireEventAPI; -export declare const waitForElement: WaitForElementFunction; +export declare const waitFor: WaitForFunction; export declare const act: (callback: () => void) => Thenable; export declare const within: (instance: ReactTestInstance) => Queries; diff --git a/website/docs/API.md b/website/docs/API.md index 5a7bca6c8..3e0f31d3f 100644 --- a/website/docs/API.md +++ b/website/docs/API.md @@ -313,29 +313,28 @@ fireEvent.scroll(getByType(ScrollView), eventData); expect(onEndReached).toHaveBeenCalled(); ``` -## `waitForElement` +## `waitFor` -- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitForElement.test.js) +- [`Example code`](https://github.com/callstack/react-native-testing-library/blob/master/src/__tests__/waitFor.test.js) Defined as: ```jsx -function waitForElement( +function waitFor( expectation: () => T, - timeout: number = 4500, - interval: number = 50 + { timeout: number = 4500, interval: number = 50 } ): Promise {} ``` -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. +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. ```jsx -import { render, waitForElement } from 'react-testing-library'; +import { render, waitFor } from 'react-testing-library'; test('waiting for an Banana to be ready', async () => { const { getByText } = render(); - await waitForElement(() => getByText('Banana ready')); + await waitFor(() => getByText('Banana ready')); }); ``` diff --git a/website/docs/Migration20.md b/website/docs/Migration20.md index d4f69eb58..d68745445 100644 --- a/website/docs/Migration20.md +++ b/website/docs/Migration20.md @@ -5,6 +5,35 @@ title: Migration to 2.0 This guides describes major steps involved in migrating your testing code from using React Native Testing Library version `1.x` to version `2.0`. +## WaitFor API changes + +`waitForElement` function has been renamed to `waitFor` for consistency with React Testing Library. Additionally the signature has slightly changed from: + +```jsx +export default function waitForElement( + expectation: () => T, + timeout?: number, + interval?: number + : Promise { +``` + +to: + +```jsx +export default function waitFor( + expectation: () => T, + { + timeout?: number, + interval?: number + } +): Promise { +``` + +Both changes should improve code readibility. + +:::note +Please note that in many cases `waitFor` call can be replaced by proper use of `findBy` asynchonous queries resulting in more streamlined test code. +::: ## Removed global `debug` function diff --git a/website/docs/Queries.md b/website/docs/Queries.md index 3a7af6774..a4b8992a9 100644 --- a/website/docs/Queries.md +++ b/website/docs/Queries.md @@ -33,7 +33,7 @@ title: Queries `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. :::info -`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. +`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. ::: ## Queries