Skip to content
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
6 changes: 1 addition & 5 deletions src/__tests__/within.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Text, TextInput, View } from 'react-native';

import { getQueriesForElement, render, within } from '..';
import { render, within } from '..';

test('within() exposes basic queries', async () => {
const rootQueries = await render(
Expand Down Expand Up @@ -79,7 +79,3 @@ test('within() exposes a11y queries', async () => {
await expect(secondQueries.findAllByLabelText('Same Label')).resolves.toHaveLength(1);
await expect(secondQueries.findAllByA11yHint('Same Hint')).resolves.toHaveLength(1);
});

test('getQueriesForElement is alias to within', () => {
expect(getQueriesForElement).toBe(within);
});
4 changes: 2 additions & 2 deletions src/matchers/__tests__/to-be-on-the-screen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ test('toBeOnTheScreen() example test', async () => {
const child = screen.getByTestId('child');
expect(child).toBeOnTheScreen();

await screen.update(<View />);
await screen.rerender(<View />);
expect(child).not.toBeOnTheScreen();
});

Expand Down Expand Up @@ -47,7 +47,7 @@ test('toBeOnTheScreen() on detached element', async () => {

const element = screen.getByTestId('text');
// Next line will unmount the element, yet `element` variable will still hold reference to it.
await screen.update(<ShowChildren show={false} />);
await screen.rerender(<ShowChildren show={false} />);

expect(element).toBeTruthy();
expect(element).not.toBeOnTheScreen();
Expand Down
6 changes: 3 additions & 3 deletions src/matchers/__tests__/to-be-visible.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ test('toBeVisible() on inaccessible view', async () => {
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();

await screen.update(<View testID="test" />);
await screen.rerender(<View testID="test" />);
expect(test).toBeVisible();
});

Expand All @@ -190,7 +190,7 @@ test('toBeVisible() on inaccessible view (iOS)', async () => {
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();

await screen.update(<View testID="test" accessibilityElementsHidden={false} />);
await screen.rerender(<View testID="test" accessibilityElementsHidden={false} />);
expect(test).toBeVisible();
});

Expand All @@ -211,7 +211,7 @@ test('toBeVisible() on inaccessible view (Android)', async () => {
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();

await screen.update(<View testID="test" importantForAccessibility="auto" />);
await screen.rerender(<View testID="test" importantForAccessibility="auto" />);
expect(test).toBeVisible();
});

Expand Down
2 changes: 1 addition & 1 deletion src/pure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export { fireEvent } from './fire-event';
export { render } from './render';
export { waitFor } from './wait-for';
export { waitForElementToBeRemoved } from './wait-for-element-to-be-removed';
export { within, getQueriesForElement } from './within';
export { within } from './within';

export { configure, resetToDefaults } from './config';
export { isHiddenFromAccessibility, isInaccessible } from './helpers/accessibility';
Expand Down
1 change: 0 additions & 1 deletion src/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ export async function render<T>(element: React.ReactElement<T>, options: RenderO
const result = {
...getQueriesForElement(renderer.container),
rerender,
update: rerender, // alias for `rerender`
unmount,
toJSON,
debug: makeDebug(renderer),
Expand Down
1 change: 0 additions & 1 deletion src/screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const defaultScreen: Screen = {
},
debug: notImplemented,
rerender: notImplemented,
update: notImplemented,
unmount: notImplemented,
toJSON: notImplemented,
getByLabelText: notImplemented,
Expand Down
4 changes: 2 additions & 2 deletions website/docs/14.x/docs/advanced/understanding-act.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ So far we learned that `act` function allows tests to wait for all pending React
Therefore, we should use `act` whenever there is some action that causes element tree to render, particularly:

- initial render call - `ReactTestRenderer.create` call
- re-rendering of component -`renderer.update` call
- re-rendering of component -`renderer.rerender` call
- triggering any event handlers that cause component tree render

Thankfully, for these basic cases RNTL has got you covered as our `render`, `update` and `fireEvent` methods already wrap their calls in `act` so that you do not have to do it explicitly.
Thankfully, for these basic cases RNTL has got you covered as our `render`, `rerender` and `fireEvent` methods already wrap their calls in `act` so that you do not have to do it explicitly.

Note that `act` calls can be safely nested and internally form a stack of calls. However, overlapping `act` calls, which can be achieved using async version of `act`, [are not supported](https://github.com/facebook/react/blob/main/packages/react/src/ReactAct.js#L161).

Expand Down
10 changes: 4 additions & 6 deletions website/docs/14.x/docs/api/misc/other.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# Other helpers

## `within`, `getQueriesForElement` {#within}
## `within` {#within}

```jsx
function within(element: HostElement): Queries {}

function getQueriesForElement(element: HostElement): Queries {}
```

`within` (also available as `getQueriesForElement` alias) performs [queries](docs/api/queries) scoped to given element.
`within` performs [queries](docs/api/queries) scoped to given element.

:::note
Please note that additional `render` specific operations like `update`, `unmount`, `debug`, `toJSON` are _not_ included.
Please note that additional `render` specific operations like `rerender`, `unmount`, `debug`, `toJSON` are _not_ included.
:::

```jsx
Expand All @@ -33,7 +31,7 @@ Use cases for scoped queries include:
function act<T>(callback: () => T | Promise<T>): Promise<T>;
```

Useful function to help testing components that use hooks API. By default any `render`, `update`, `fireEvent`, and `waitFor` calls are wrapped by this function, so there is no need to wrap it manually.
Useful function to help testing components that use hooks API. By default any `render`, `rerender`, `fireEvent`, and `waitFor` calls are wrapped by this function, so there is no need to wrap it manually.

**In v14, `act` is now async by default and always returns a Promise**, making it compatible with React 19, React Suspense, and `React.use()`. This ensures all pending React updates are executed before the Promise resolves.

Expand Down
2 changes: 1 addition & 1 deletion website/docs/14.x/docs/api/render.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ See [this article](https://kentcdodds.com/blog/common-mistakes-with-react-testin

:::warning Async lifecycle methods

When using `render`, the lifecycle methods `rerender`, `update`, and `unmount` are async and must be awaited.
When using `render`, the lifecycle methods `rerender` and `unmount` are async and must be awaited.

:::
2 changes: 0 additions & 2 deletions website/docs/14.x/docs/api/screen.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ test('example', async () => {

### `rerender`

_Also available under `update` alias_

```ts
function rerender(element: React.Element<unknown>): Promise<void>;
```
Expand Down
80 changes: 78 additions & 2 deletions website/docs/14.x/docs/migration/v14.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,25 @@ screen.rerender(<MyComponent />);
await screen.rerender(<MyComponent />);
```

##### 4. Update `unmount` calls to await
##### 4. Replace `update` alias with `rerender`

The `update` alias for `rerender` has been removed in v14. If you were using `screen.update()` or `renderer.update()`, replace it with `rerender()`:

```ts
// Before (v13)
screen.update(<MyComponent />);
// or
const { update } = render(<MyComponent />);
update(<MyComponent />);

// After (v14)
await screen.rerender(<MyComponent />);
// or
const { rerender } = await render(<MyComponent />);
await rerender(<MyComponent />);
```

##### 5. Update `unmount` calls to await

```ts
// Before
Expand Down Expand Up @@ -216,6 +234,64 @@ it('should update component', async () => {

For more details, see the [`render` API documentation](/docs/api/render).

### `update` alias removed

In v14, the `update` alias for `rerender` has been removed. You must use `rerender` instead.

**What changed:**

- `screen.update()` has been removed
- `renderer.update()` has been removed
- Only `rerender` is now available

**Migration:**

Replace all `update` calls with `rerender`:

```ts
// Before (v13)
screen.update(<MyComponent />);
// or
const { update } = render(<MyComponent />);
update(<MyComponent />);

// After (v14)
await screen.rerender(<MyComponent />);
// or
const { rerender } = await render(<MyComponent />);
await rerender(<MyComponent />);
```

**Note:** This change is included in the step-by-step migration guide for async `render` above.

### `getQueriesForElement` export removed

In v14, the `getQueriesForElement` export alias for `within` has been removed. You must use `within` instead.

**What changed:**

- `getQueriesForElement` is no longer exported from the main package
- `within` is the only exported function for scoped queries
- `getQueriesForElement` remains available internally but is not part of the public API

**Migration:**

Replace all `getQueriesForElement` imports and usage with `within`:

```ts
// Before (v13)
import { getQueriesForElement } from '@testing-library/react-native';

const queries = getQueriesForElement(element);

// After (v14)
import { within } from '@testing-library/react-native';

const queries = within(element);
```

**Note:** `getQueriesForElement` was just an alias for `within`, so the functionality is identical - only the import needs to change.

### `renderHook` is now async by default

In v14, `renderHook` is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and `React.use()`.
Expand Down Expand Up @@ -290,7 +366,7 @@ unmount();
await unmount();
```

##### 5. Update `act` calls to use async `act`
##### 6. Update `act` calls to use async `act`

```ts
// Before
Expand Down