Skip to content
This repository was archived by the owner on Aug 1, 2020. It is now read-only.

Revise in preparation for 3.0.0 release #5

Merged
merged 7 commits into from
May 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions docs/api-async.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
id: api-async
title: Async
sidebar_label: Async
title: Async Utilities
sidebar_label: Async Utilities
---

Several utilities are provided for dealing with asynchronous code. These can be useful to wait for
Expand All @@ -26,8 +26,8 @@ expectations to pass. The `wait` function is a small wrapper around the
example:

```javascript
await wait(() => getByLabelText(container, 'username'));
getByLabelText(container, 'username').value = 'chucknorris';
await wait(() => getByLabelText('username'));
getByLabelText('username').value = 'chucknorris';
```

This can be useful if you have a unit test that mocks API calls and you need to wait for your mock
Expand All @@ -49,38 +49,60 @@ the event loop (in a `setTimeout`) before starting the intervals.
function waitForElement<T>(
callback: () => T,
options?: {
container?: ReactTestInstance;
timeout?: number;
interval?: number;
},
): Promise<T>;
```

When in need to wait for DOM elements to appear, disappear, or change you can use `waitForElement`.
The `waitForElement` function is a similar to `wait`, but is a helper specifically intended to wait
for an element.
When you need to wait for elements to appear, you can use `waitForElement`. The `waitForElement`
function is a similar to `wait`, but is specifically intended to wait for an element to appear.
Additionally, the result is returned for you to use.

Here's a simple example:

```javascript
const usernameElement = await waitForElement(() => getByA11yLabel(container, 'username'), {
container,
});
expect(usernameElement.props.children).toBe('chucknorris');
const usernameElement = await waitForElement(() => getByLabelText('username'));
expect(usernameElement).toHaveTextContent('chucknorris');
```

You can also wait for multiple elements at once:

```javascript
const [usernameElement, passwordElement] = await waitForElement(
() => [getByA11yLabel(container, 'username'), getByA11yLabel(container, 'password')],
{ container },
);
const [usernameElement, passwordElement] = await waitForElement(() => [
getByLabelText('username'),
getByLabelText('password'),
]);
```

The default `container` is the root `ReactTestInstance` that is the result of `render`. Make sure
the elements you wait for will be attached to it, or set a different `ReactTestInstance` as a
container.
The default `timeout` is `4500ms` which will keep you under
[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).

The default `interval` is `50ms`. However it will run your callback immediately on the next tick of
the event loop (in a `setTimeout`) before starting the intervals.

## `waitForElementToBeRemoved`

```typescript
function waitForElementToBeRemoved<T>(
callback: () => T,
options?: {
timeout?: number;
interval?: number;
},
): Promise<T>;
```

When you need to wait for elements to be removed, or you can use `waitForElementToBeRemoved`. The
`waitForElementToBeRemoved` function is a similar to `wait`, but is a helper specifically intended
to wait for an element to be removed from the tree. Similarly to `waitForElement` the result of the
callback is returned as a Promise, but in most cases you won't need it.

Here's a simple example:

```javascript
await waitForElementToBeRemoved(() => queryAllByLabelText('list-item'));
```

The default `timeout` is `4500ms` which will keep you under
[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
Expand Down
19 changes: 11 additions & 8 deletions docs/api-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ sidebar_label: Firing Events
## Basic example

```javascript
import { fireEvent, NativeEvent, render } from 'native-testing-library';
import { fireEvent, NativeTestEvent, render } from 'native-testing-library';

const { getByText } = render(<Button title="Submit" />);
fireEvent(getByText(container, 'Submit'), new NativeEvent('press'));
fireEvent(getByText(container, 'Submit'), new NativeTestEvent('press'));
```

## `fireEvent[eventName]`

```typescript
fireEvent[eventName](node: FiberRoot, eventProperties: NativeEvent)
fireEvent[eventName](node: FiberRoot, eventProperties: NativeTestEvent)
```

Convenience methods for firing events. Check out
[src/events.js](https://github.com/testing-library/native-testing-library/blob/master/src/events.js) for
a full list as well as `validTargets` for every event type.
[src/events.js](https://github.com/testing-library/native-testing-library/blob/master/src/events.js)
for a full list as well as `validTargets` for every event type.

```javascript
import { fireEvent, render } from 'native-testing-library';
Expand All @@ -35,19 +35,22 @@ called nativeEvent. When you fire an event using this library, you will have to
config. You will use this particularly for events like a change event:

```javascript
fireEvent.change(getByA11yLabel(/username/i), { nativeEvent: { text: 'a' } });
fireEvent.change(getByLabelText(/username/i), { nativeEvent: { text: 'a' } });
```

**changeText**: `Text` has a method for value updating called `onChangeText`. Since this is such a
commonly used method, there is a special case in the library for this method.

```javascript
fireEvent.changeText(getByA11yLabel(/username/i), 'a');
fireEvent.changeText(getByLabelText(/username/i), 'a');
```

**customEvent**: You may be using a library that has custom event listeners that you want to be able
to fire. This is how you would fire one of these events:

```javascript
fireEvent(getByTestId('swiper'), new NativeEvent('myEvent', { nativeEvent: { value: 'testing' } }));
fireEvent(
getByTestId('swiper'),
new NativeTestEvent('myEvent', { nativeEvent: { value: 'testing' } }),
);
```
59 changes: 22 additions & 37 deletions docs/api-helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ sidebar_label: Helpers

## Custom Queries

`native-testing-library` exposes many of the helper functions that are used to implement the default
`native-testing-library` exposes some of the helper functions that are used to implement the default
queries. You can use the helpers to build custom queries. For example, the code below shows a way to
query your TestInstance by a `style` prop. Note: test files would need to now import `test-utils.js`
instead of using `native-testing-library` directly. Also note, please never actually implement this
helper, it's just an example of what's possible.

```js
```javascript
// test-utils.js
import * as nativeTestingLib from 'native-testing-library';

Expand Down Expand Up @@ -54,61 +54,46 @@ export {
getNodeText(node: React.ReactElement<any>)
```

Returns the complete text content of a html element, removing any extra whitespace, and joining
children that are an array. The intention is to treat text in nodes exactly as how it is perceived
by users in a browser, where any extra whitespace within words in the html code is not meaningful
when the text is rendered, and all text appears as one cohesive string regardless of the code.
Returns the complete text content of an element, removing any extra whitespace, and joining children
that are an array. The intention is to treat text in nodes exactly as how it is perceived by users
in a browser, where any extra whitespace within words in the html code is not meaningful when the
text is rendered, and all text appears as one cohesive string regardless of the code.

```javascript
const inputNode = <TextInput value="words" />;
const textNode = (
getNodeText(
<Text>
{`
Hello
World !
`}
</Text>
);

getNodeText(node); // "Hello World !"
```

This function is also used internally when querying nodes by their text content. This enables
functions like `getByText` and `queryByText` to work as expected, finding elements in the tree
similarly to how users would do.

The function works for for input elements as well:

```javascript
const inputNode = <TextInput value="words" />;

getNodeText(inputNode); // "words"
Hello
World !
`}
</Text>,
); // "Hello World !"
```

## `getQueriesForElement` APIs
## `within` and `getQueriesForElement` APIs

`getQueriesForElement` takes a FiberRoot and binds it to the raw query functions, allowing them to
be used without specifying a container.
`within` (an alias to `getQueriesForElement`) takes a `NativeTestInstance` and binds it to the raw
query functions, allowing them to be used without manually specifying a container.

Example: To get the username input of a login form within a `<LoginModal />`, you could do:

```js
import { render, getQueriesForElement } from 'react-testing-library';
import { render, within } from 'native-testing-library';

const { getByA11yLabel } = render(<LoginModal />);
const loginForm = getByA11yLabel('login-form');
const { getByLabelText } = render(<LoginModal />);
const loginForm = getByLabelText('login-form');

getQueriesForElement(loginForm).getByPlaceholder('Username');
within(loginForm).getByPlaceholderText('Username');
```

## Debugging

When you use any `get` calls in your test cases, the current state of the `container` (React tree)
gets printed on the console. For example:
When you use any `get` calls in your test cases, the current contents of the `baseElement` get
printed on the console. For example:

```javascript
// <Text>Hello world</Text>
getByText(container, 'Goodbye world'); // will fail by throwing error
getByText('Goodbye world'); // will fail by throwing error
```

The above test case will fail, however it prints the state of your React tree being tested, so you
Expand Down
Loading