diff --git a/package.json b/package.json
index 9e4b84bff..dbbb2dbce 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"typecheck": "tsc",
"lint": "eslint src --cache",
"validate": "yarn prettier && yarn lint && yarn typecheck && yarn test",
+ "validate:write": "yarn prettier:write && yarn lint --fix && yarn typecheck && yarn test -u",
"build:js": "babel src --out-dir build --extensions \".js,.ts,.jsx,.tsx\" --source-maps --ignore \"**/__tests__/**\"",
"build:ts": "tsc --build tsconfig.release.json",
"build": "yarn clean && yarn build:js && yarn build:ts",
diff --git a/src/__tests__/__snapshots__/render.test.tsx.snap b/src/__tests__/__snapshots__/unsafe-render-sync.test.tsx.snap
similarity index 100%
rename from src/__tests__/__snapshots__/render.test.tsx.snap
rename to src/__tests__/__snapshots__/unsafe-render-sync.test.tsx.snap
diff --git a/src/__tests__/act.test.tsx b/src/__tests__/act.test.tsx
index 036b80a14..c54e35c38 100644
--- a/src/__tests__/act.test.tsx
+++ b/src/__tests__/act.test.tsx
@@ -16,23 +16,23 @@ const Counter = () => {
return setCount(count + 1)}>{text};
};
-test('render should trigger useEffect', () => {
+test('render should trigger useEffect', async () => {
const effectCallback = jest.fn();
- render();
+ await render();
expect(effectCallback).toHaveBeenCalledTimes(1);
});
-test('rerender should trigger useEffect', () => {
+test('rerender should trigger useEffect', async () => {
const effectCallback = jest.fn();
- render();
- screen.rerender();
+ await render();
+ await screen.rerender();
expect(effectCallback).toHaveBeenCalledTimes(2);
});
test('fireEvent should trigger useState', async () => {
- render();
+ await render();
const counter = screen.getByText(/Total count/i);
expect(counter.props.children).toEqual('Total count: 0');
diff --git a/src/__tests__/auto-cleanup-skip.test.tsx b/src/__tests__/auto-cleanup-skip.test.tsx
index d6d51c50f..1bf6c419a 100644
--- a/src/__tests__/auto-cleanup-skip.test.tsx
+++ b/src/__tests__/auto-cleanup-skip.test.tsx
@@ -29,9 +29,9 @@ class Test extends React.Component<{ onUnmount?(): void }> {
// This just verifies that by importing RNTL in pure mode in an environment which supports
// afterEach (like jest) we won't get automatic cleanup between tests.
-test('component is mounted, but not umounted before test ends', () => {
+test('component is mounted, but not umounted before test ends', async () => {
const fn = jest.fn();
- render();
+ await render();
expect(fn).not.toHaveBeenCalled();
});
diff --git a/src/__tests__/auto-cleanup.test.tsx b/src/__tests__/auto-cleanup.test.tsx
index 75453c93c..a4a3a6202 100644
--- a/src/__tests__/auto-cleanup.test.tsx
+++ b/src/__tests__/auto-cleanup.test.tsx
@@ -27,9 +27,9 @@ afterEach(() => {
// This just verifies that by importing RNTL in an environment which supports afterEach (like jest)
// we'll get automatic cleanup between tests.
-test('component is mounted, but not umounted before test ends', () => {
+test('component is mounted, but not umounted before test ends', async () => {
const fn = jest.fn();
- render();
+ await render();
expect(isMounted).toEqual(true);
expect(fn).not.toHaveBeenCalled();
});
@@ -38,14 +38,14 @@ test('component is automatically umounted after first test ends', () => {
expect(isMounted).toEqual(false);
});
-test('does not time out with legacy fake timers', () => {
+test('does not time out with legacy fake timers', async () => {
jest.useFakeTimers({ legacyFakeTimers: true });
- render();
+ await render();
expect(isMounted).toEqual(true);
});
-test('does not time out with fake timers', () => {
+test('does not time out with fake timers', async () => {
jest.useFakeTimers();
- render();
+ await render();
expect(isMounted).toEqual(true);
});
diff --git a/src/__tests__/cleanup.test.tsx b/src/__tests__/cleanup.test.tsx
index e09f3ce9b..f6036d028 100644
--- a/src/__tests__/cleanup.test.tsx
+++ b/src/__tests__/cleanup.test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { View } from 'react-native';
-import { cleanupAsync, render, renderAsync } from '../pure';
+import { cleanup, render, unsafe_renderSync } from '../pure';
class Test extends React.Component<{ onUnmount: () => void }> {
componentWillUnmount() {
@@ -17,21 +17,21 @@ class Test extends React.Component<{ onUnmount: () => void }> {
test('cleanup after render', async () => {
const fn = jest.fn();
- render();
- render();
+ await render();
+ await render();
expect(fn).not.toHaveBeenCalled();
- await cleanupAsync();
+ await cleanup();
expect(fn).toHaveBeenCalledTimes(2);
});
-test('cleanup after renderAsync', async () => {
+test('cleanup after unsafe_renderSync', async () => {
const fn = jest.fn();
- await renderAsync();
- await renderAsync();
+ unsafe_renderSync();
+ unsafe_renderSync();
expect(fn).not.toHaveBeenCalled();
- await cleanupAsync();
+ await cleanup();
expect(fn).toHaveBeenCalledTimes(2);
});
diff --git a/src/__tests__/event-handler.test.tsx b/src/__tests__/event-handler.test.tsx
index 2c7f5ac43..0b200d7ca 100644
--- a/src/__tests__/event-handler.test.tsx
+++ b/src/__tests__/event-handler.test.tsx
@@ -4,11 +4,11 @@ import { Text, View } from 'react-native';
import { render, screen } from '..';
import { getEventHandlerFromProps } from '../event-handler';
-test('getEventHandler strict mode', () => {
+test('getEventHandler strict mode', async () => {
const onPress = jest.fn();
const testOnlyOnPress = jest.fn();
- render(
+ await render(
{/* @ts-expect-error Intentionally passing such props */}
@@ -31,11 +31,11 @@ test('getEventHandler strict mode', () => {
expect(getEventHandlerFromProps(both.props, 'onPress')).toBe(undefined);
});
-test('getEventHandler loose mode', () => {
+test('getEventHandler loose mode', async () => {
const onPress = jest.fn();
const testOnlyOnPress = jest.fn();
- render(
+ await render(
{/* @ts-expect-error Intentionally passing such props */}
diff --git a/src/__tests__/fire-event-textInput.test.tsx b/src/__tests__/fire-event-textInput.test.tsx
index 9e9f2ccb9..7223b1b21 100644
--- a/src/__tests__/fire-event-textInput.test.tsx
+++ b/src/__tests__/fire-event-textInput.test.tsx
@@ -20,7 +20,7 @@ test('should fire only non-touch-related events on non-editable TextInput', asyn
const onSubmitEditing = jest.fn();
const onLayout = jest.fn();
- render(
+ await render(
{
test('should invoke specified event', async () => {
const onPressMock = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByText('Press me'), 'press');
@@ -62,7 +62,7 @@ describe('fireEvent', () => {
test('should invoke specified event on parent element', async () => {
const onPressMock = jest.fn();
const text = 'New press text';
- render();
+ await render();
await fireEvent(screen.getByText(text), 'press');
expect(onPressMock).toHaveBeenCalled();
@@ -72,7 +72,7 @@ describe('fireEvent', () => {
const handlerMock = jest.fn();
const EVENT_DATA = 'event data';
- render(
+ await render(
,
@@ -93,7 +93,7 @@ test('fireEvent.press', async () => {
pageY: 30,
},
};
- render();
+ await render();
await fireEvent.press(screen.getByText(text), eventData);
@@ -110,7 +110,7 @@ test('fireEvent.scroll', async () => {
},
};
- render(
+ await render(
XD
,
@@ -124,7 +124,7 @@ test('fireEvent.scroll', async () => {
test('fireEvent.changeText', async () => {
const onChangeTextMock = jest.fn();
- render(
+ await render(
,
@@ -136,7 +136,7 @@ test('fireEvent.changeText', async () => {
});
it('sets native state value for unmanaged text inputs', async () => {
- render();
+ await render();
const input = screen.getByTestId('input');
expect(input).toHaveDisplayValue('');
@@ -148,7 +148,7 @@ it('sets native state value for unmanaged text inputs', async () => {
test('custom component with custom event name', async () => {
const handlePress = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByText('Custom component'), 'handlePress');
@@ -158,7 +158,7 @@ test('custom component with custom event name', async () => {
test('event with multiple handler parameters', async () => {
const handlePress = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByText('Custom component'), 'handlePress', 'param1', 'param2');
@@ -167,7 +167,7 @@ test('event with multiple handler parameters', async () => {
test('should not fire on disabled TouchableOpacity', async () => {
const handlePress = jest.fn();
- render(
+ await render(
Trigger
@@ -181,7 +181,7 @@ test('should not fire on disabled TouchableOpacity', async () => {
test('should not fire on disabled Pressable', async () => {
const handlePress = jest.fn();
- render(
+ await render(
Trigger
@@ -195,7 +195,7 @@ test('should not fire on disabled Pressable', async () => {
test('should not fire inside View with pointerEvents="none"', async () => {
const onPress = jest.fn();
- render(
+ await render(
Trigger
@@ -210,7 +210,7 @@ test('should not fire inside View with pointerEvents="none"', async () => {
test('should not fire inside View with pointerEvents="box-only"', async () => {
const onPress = jest.fn();
- render(
+ await render(
Trigger
@@ -225,7 +225,7 @@ test('should not fire inside View with pointerEvents="box-only"', async () => {
test('should fire inside View with pointerEvents="box-none"', async () => {
const onPress = jest.fn();
- render(
+ await render(
Trigger
@@ -240,7 +240,7 @@ test('should fire inside View with pointerEvents="box-none"', async () => {
test('should fire inside View with pointerEvents="auto"', async () => {
const onPress = jest.fn();
- render(
+ await render(
Trigger
@@ -255,7 +255,7 @@ test('should fire inside View with pointerEvents="auto"', async () => {
test('should not fire deeply inside View with pointerEvents="box-only"', async () => {
const onPress = jest.fn();
- render(
+ await render(
@@ -272,7 +272,7 @@ test('should not fire deeply inside View with pointerEvents="box-only"', async (
test('should fire non-pointer events inside View with pointerEvents="box-none"', async () => {
const onTouchStart = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('view'), 'touchStart');
expect(onTouchStart).toHaveBeenCalled();
@@ -280,7 +280,7 @@ test('should fire non-pointer events inside View with pointerEvents="box-none"',
test('should fire non-touch events inside View with pointerEvents="box-none"', async () => {
const onLayout = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('view'), 'layout');
expect(onLayout).toHaveBeenCalled();
@@ -290,7 +290,7 @@ test('should fire non-touch events inside View with pointerEvents="box-none"', a
// the 'press' event on host View rendered by pressable.
test('should fire on Pressable with pointerEvents="box-only', async () => {
const onPress = jest.fn();
- render();
+ await render();
await fireEvent.press(screen.getByTestId('pressable'));
expect(onPress).toHaveBeenCalled();
@@ -299,7 +299,7 @@ test('should fire on Pressable with pointerEvents="box-only', async () => {
test('should pass event up on disabled TouchableOpacity', async () => {
const handleInnerPress = jest.fn();
const handleOuterPress = jest.fn();
- render(
+ await render(
Inner Trigger
@@ -315,7 +315,7 @@ test('should pass event up on disabled TouchableOpacity', async () => {
test('should pass event up on disabled Pressable', async () => {
const handleInnerPress = jest.fn();
const handleOuterPress = jest.fn();
- render(
+ await render(
Inner Trigger
@@ -342,7 +342,7 @@ const TestComponent = ({ onPress }: TestComponentProps) => {
test('is not fooled by non-native disabled prop', async () => {
const handlePress = jest.fn();
- render();
+ await render();
await fireEvent.press(screen.getByText('Trigger Test'));
expect(handlePress).toHaveBeenCalledTimes(1);
@@ -366,7 +366,7 @@ function TestChildTouchableComponent({ onPress, someProp }: TestChildTouchableCo
test('is not fooled by non-responder wrapping host elements', async () => {
const handlePress = jest.fn();
- render(
+ await render(
,
@@ -394,7 +394,7 @@ function TestDraggableComponent({ onDrag }: TestDraggableComponentProps) {
test('has only onMove', async () => {
const handleDrag = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByText('Trigger'), 'responderMove', {
touchHistory: { mostRecentTimeStamp: '2', touchBank: [] },
@@ -407,7 +407,7 @@ test('has only onMove', async () => {
describe('native events', () => {
test('triggers onScrollBeginDrag', async () => {
const onScrollBeginDragSpy = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('test-id'), 'onScrollBeginDrag');
expect(onScrollBeginDragSpy).toHaveBeenCalled();
@@ -415,7 +415,7 @@ describe('native events', () => {
test('triggers onScrollEndDrag', async () => {
const onScrollEndDragSpy = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('test-id'), 'onScrollEndDrag');
expect(onScrollEndDragSpy).toHaveBeenCalled();
@@ -423,7 +423,7 @@ describe('native events', () => {
test('triggers onMomentumScrollBegin', async () => {
const onMomentumScrollBeginSpy = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('test-id'), 'onMomentumScrollBegin');
expect(onMomentumScrollBeginSpy).toHaveBeenCalled();
@@ -431,7 +431,7 @@ describe('native events', () => {
test('triggers onMomentumScrollEnd', async () => {
const onMomentumScrollEndSpy = jest.fn();
- render();
+ await render();
await fireEvent(screen.getByTestId('test-id'), 'onMomentumScrollEnd');
expect(onMomentumScrollEndSpy).toHaveBeenCalled();
@@ -472,7 +472,7 @@ describe('React.Suspense integration', () => {
test('should handle events after Suspense resolves', async () => {
const onPressMock = jest.fn();
- render(
+ await render(
,
@@ -483,8 +483,8 @@ describe('React.Suspense integration', () => {
// Resolve the promise
resolveMockPromise('loaded');
- await waitFor(() => {
- screen.rerender(
+ await waitFor(async () => {
+ await screen.rerender(
,
@@ -512,7 +512,7 @@ describe('React.Suspense integration', () => {
);
}
- render(
+ await render(
}>
,
@@ -547,7 +547,7 @@ describe('React.Suspense integration', () => {
);
}
- const { rerender } = render(
+ const { rerender } = await render(
Outer Loading...}>
Inner Loading...}>
@@ -566,8 +566,8 @@ describe('React.Suspense integration', () => {
// Resolve inner component
resolveMockPromise('inner-loaded');
- await waitFor(() => {
- rerender(
+ await waitFor(async () => {
+ await rerender(
Outer Loading...}>
Inner Loading...}>
@@ -611,7 +611,7 @@ describe('React.Suspense integration', () => {
);
}
- render(
+ await render(
Loading data...}>
@@ -628,7 +628,7 @@ describe('React.Suspense integration', () => {
expect(onPressMock).toHaveBeenCalled();
// Rerender - now DataComponent should suspend
- screen.rerender(
+ await screen.rerender(
Loading data...}>
@@ -644,14 +644,14 @@ describe('React.Suspense integration', () => {
test('should handle unmounted elements gracefully in async mode', async () => {
const onPress = jest.fn();
- render(
+ await render(
Test
,
);
const element = screen.getByText('Test');
- screen.unmount();
+ await screen.unmount();
// Firing async event on unmounted element should not crash
await fireEvent.press(element);
diff --git a/src/__tests__/host-component-names.test.tsx b/src/__tests__/host-component-names.test.tsx
index 3e89dd84b..3fbf5fdf2 100644
--- a/src/__tests__/host-component-names.test.tsx
+++ b/src/__tests__/host-component-names.test.tsx
@@ -11,39 +11,39 @@ import {
isHostTextInput,
} from '../helpers/host-component-names';
-test('detects host Text component', () => {
- render(Hello);
+test('detects host Text component', async () => {
+ await render(Hello);
expect(isHostText(screen.root)).toBe(true);
});
// Some users might use the raw RCTText component directly for performance reasons.
// See: https://blog.theodo.com/2023/10/native-views-rn-performance/
-test('detects raw RCTText component', () => {
- render(React.createElement('RCTText', { testID: 'text' }, 'Hello'));
+test('detects raw RCTText component', async () => {
+ await render(React.createElement('RCTText', { testID: 'text' }, 'Hello'));
expect(isHostText(screen.root)).toBe(true);
});
-test('detects host TextInput component', () => {
- render();
+test('detects host TextInput component', async () => {
+ await render();
expect(isHostTextInput(screen.root)).toBe(true);
});
-test('detects host Image component', () => {
- render();
+test('detects host Image component', async () => {
+ await render();
expect(isHostImage(screen.root)).toBe(true);
});
-test('detects host Switch component', () => {
- render();
+test('detects host Switch component', async () => {
+ await render();
expect(isHostSwitch(screen.root)).toBe(true);
});
-test('detects host ScrollView component', () => {
- render();
+test('detects host ScrollView component', async () => {
+ await render();
expect(isHostScrollView(screen.root)).toBe(true);
});
-test('detects host Modal component', () => {
- render();
+test('detects host Modal component', async () => {
+ await render();
expect(isHostModal(screen.root)).toBe(true);
});
diff --git a/src/__tests__/host-text-nesting.test.tsx b/src/__tests__/host-text-nesting.test.tsx
index 6e5b11915..c15c480d4 100644
--- a/src/__tests__/host-text-nesting.test.tsx
+++ b/src/__tests__/host-text-nesting.test.tsx
@@ -4,19 +4,19 @@ import { Pressable, Text, View } from 'react-native';
import { render, screen } from '../pure';
describe('nested text handling', () => {
- test('basic', () => {
- render(Hello);
+ test('basic', async () => {
+ await render(Hello);
expect(screen.getByText('Hello')).toBeTruthy();
});
- test('role with direct text children', () => {
- render(About);
+ test('role with direct text children', async () => {
+ await render(About);
expect(screen.getByRole('header', { name: 'About' })).toBeTruthy();
});
- test('nested text with child with role', () => {
- render(
+ test('nested text with child with role', async () => {
+ await render(
About
@@ -27,8 +27,8 @@ describe('nested text handling', () => {
expect(screen.getByRole('header', { name: 'About' }).props.testID).toBe('child');
});
- test('pressable within View, with text child', () => {
- render(
+ test('pressable within View, with text child', async () => {
+ await render(
Save
@@ -39,8 +39,8 @@ describe('nested text handling', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('pressable');
});
- test('pressable within View, with text child within view', () => {
- render(
+ test('pressable within View, with text child within view', async () => {
+ await render(
@@ -53,8 +53,8 @@ describe('nested text handling', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('pressable');
});
- test('Text within pressable', () => {
- render(
+ test('Text within pressable', async () => {
+ await render(
Save
,
@@ -63,8 +63,8 @@ describe('nested text handling', () => {
expect(screen.getByText('Save').props.testID).toBe('text');
});
- test('Text within view within pressable', () => {
- render(
+ test('Text within view within pressable', async () => {
+ await render(
Save
diff --git a/src/__tests__/questionsBoard.test.tsx b/src/__tests__/questionsBoard.test.tsx
index c8be45eed..1eb97dcbb 100644
--- a/src/__tests__/questionsBoard.test.tsx
+++ b/src/__tests__/questionsBoard.test.tsx
@@ -44,7 +44,7 @@ test('form submits two answers', async () => {
const onSubmit = jest.fn();
const user = userEvent.setup();
- render();
+ await render();
const answerInputs = screen.getAllByLabelText('answer input');
await user.type(answerInputs[0], 'a1');
diff --git a/src/__tests__/react-native-animated.test.tsx b/src/__tests__/react-native-animated.test.tsx
index 8d617fedd..87f3f582b 100644
--- a/src/__tests__/react-native-animated.test.tsx
+++ b/src/__tests__/react-native-animated.test.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import type { ViewStyle } from 'react-native';
-import { Animated } from 'react-native';
+import { Animated, Text } from 'react-native';
import { act, render, screen } from '..';
@@ -44,9 +44,9 @@ describe('AnimatedView', () => {
});
it('should use native driver when useNativeDriver is true', async () => {
- render(
+ await render(
- Test
+ Test
,
);
expect(screen.root).toHaveStyle({ opacity: 0 });
@@ -57,9 +57,9 @@ describe('AnimatedView', () => {
});
it('should not use native driver when useNativeDriver is false', async () => {
- render(
+ await render(
- Test
+ Test
,
);
expect(screen.root).toHaveStyle({ opacity: 0 });
diff --git a/src/__tests__/react-native-api.test.tsx b/src/__tests__/react-native-api.test.tsx
index b4926ccc9..76c2f0c03 100644
--- a/src/__tests__/react-native-api.test.tsx
+++ b/src/__tests__/react-native-api.test.tsx
@@ -10,8 +10,8 @@ import { getReactNativeVersion } from '../test-utils/version';
* changed in a way that may impact our code like queries or event handling.
*/
-test('React Native API assumption: renders a single host element', () => {
- render();
+test('React Native API assumption: renders a single host element', async () => {
+ await render();
expect(screen).toMatchInlineSnapshot(`
renders a single host element', () =>
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render(Hello);
+test('React Native API assumption: renders a single host element', async () => {
+ await render(Hello);
expect(screen).toMatchInlineSnapshot(`
renders a single host element', () =>
`);
});
-test('React Native API assumption: nested renders a single host element', () => {
- render(
+test('React Native API assumption: nested renders a single host element', async () => {
+ await render(
Before
Hello
@@ -66,8 +66,8 @@ test('React Native API assumption: nested renders a single host element',
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render(
+test('React Native API assumption: renders a single host element', async () => {
+ await render(
renders a single host element', (
`);
});
-test('React Native API assumption: with nested Text renders single host element', () => {
- render(
+test('React Native API assumption: with nested Text renders single host element', async () => {
+ await render(
Hello
,
@@ -105,8 +105,8 @@ test('React Native API assumption: with nested Text renders single h
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render();
+test('React Native API assumption: renders a single host element', async () => {
+ await render();
expect(
mapJsonProps(screen.toJSON(), {
@@ -125,8 +125,10 @@ test('React Native API assumption: renders a single host element', () =
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render();
+test('React Native API assumption: renders a single host element', async () => {
+ await render(
+ ,
+ );
expect(screen).toMatchInlineSnapshot(`
renders a single host element', () =>
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render(
+test('React Native API assumption: renders a single host element', async () => {
+ await render(
,
@@ -161,8 +163,8 @@ test('React Native API assumption: renders a single host element',
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render(
+test('React Native API assumption: renders a single host element', async () => {
+ await render(
{item}} />,
);
@@ -215,8 +217,8 @@ test('React Native API assumption: renders a single host
`);
});
-test('React Native API assumption: renders a single host element', () => {
- render(
+test('React Native API assumption: renders a single host element', async () => {
+ await render(
Modal Content
,
@@ -250,8 +252,8 @@ test('React Native API assumption: renders a single host element', () =>
}
});
-test('React Native API assumption: aria-* props render directly on host View', () => {
- render(
+test('React Native API assumption: aria-* props render directly on host View', async () => {
+ await render(
{
- render(
+test('React Native API assumption: aria-* props render directly on host Text', async () => {
+ await render(
{
- render(
+test('React Native API assumption: aria-* props render directly on host TextInput', async () => {
+ await render(
{
const onPressOut = jest.fn();
const onLongPress = jest.fn();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
- state = {
- fresh: false,
- };
-
- componentDidUpdate() {
- if (this.props.onUpdate) {
- this.props.onUpdate();
- }
- }
-
- componentWillUnmount() {
- if (this.props.onUnmount) {
- this.props.onUnmount();
- }
- }
-
- changeFresh = () => {
- this.setState((state) => ({
- fresh: !state.fresh,
- }));
- };
-
- render() {
- return (
-
- Is the banana fresh?
- {this.state.fresh ? 'fresh' : 'not fresh'}
-
- );
- }
-}
-
-test('renderAsync renders component asynchronously', async () => {
- await renderAsync();
- expect(screen.getByTestId('test')).toBeOnTheScreen();
-});
-
-test('renderAsync with wrapper option', async () => {
- const WrapperComponent = ({ children }: { children: React.ReactNode }) => (
- {children}
- );
-
- await renderAsync(, {
- wrapper: WrapperComponent,
- });
-
- expect(screen.getByTestId('wrapper')).toBeTruthy();
- expect(screen.getByTestId('inner')).toBeTruthy();
-});
-
-test('rerender function throws error when used with renderAsync', async () => {
- await renderAsync();
-
- expect(() => screen.rerender()).toThrowErrorMatchingInlineSnapshot(
- `""rerender(...)" is not supported when using "renderAsync" use "await rerenderAsync(...)" instead"`,
- );
-});
-
-test('rerenderAsync function updates component asynchronously', async () => {
- const fn = jest.fn();
- await renderAsync();
- expect(fn).toHaveBeenCalledTimes(0);
-
- await screen.rerenderAsync();
- expect(fn).toHaveBeenCalledTimes(1);
-});
-
-test('unmount function throws error when used with renderAsync', async () => {
- await renderAsync();
-
- expect(() => screen.unmount()).toThrowErrorMatchingInlineSnapshot(
- `""unmount()" is not supported when using "renderAsync" use "await unmountAsync()" instead"`,
- );
-});
-
-test('unmountAsync function unmounts component asynchronously', async () => {
- const fn = jest.fn();
- await renderAsync();
-
- await screen.unmountAsync();
- expect(fn).toHaveBeenCalled();
-});
diff --git a/src/__tests__/render-debug.test.tsx b/src/__tests__/render-debug.test.tsx
index 544c2e45a..21b37deb3 100644
--- a/src/__tests__/render-debug.test.tsx
+++ b/src/__tests__/render-debug.test.tsx
@@ -90,8 +90,8 @@ class Banana extends React.Component {
}
}
-test('debug', () => {
- render();
+test('debug', async () => {
+ await render();
screen.debug();
screen.debug({ message: 'another custom message' });
@@ -104,7 +104,7 @@ test('debug', () => {
});
test('debug changing component', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByRole('button', { name: 'Change freshness!' }));
screen.debug({ mapProps: null });
@@ -113,16 +113,16 @@ test('debug changing component', async () => {
expect(mockCalls[0][0]).toMatchSnapshot('bananaFresh button message should now be "fresh"');
});
-test('debug with only children prop', () => {
- render();
+test('debug with only children prop', async () => {
+ await render();
screen.debug({ mapProps: () => ({}) });
const mockCalls = jest.mocked(logger.info).mock.calls;
expect(mockCalls[0][0]).toMatchSnapshot();
});
-test('debug with only prop whose value is bananaChef', () => {
- render();
+test('debug with only prop whose value is bananaChef', async () => {
+ await render();
screen.debug({
mapProps: (props) => {
const filterProps: Record = {};
@@ -139,10 +139,10 @@ test('debug with only prop whose value is bananaChef', () => {
expect(mockCalls[0][0]).toMatchSnapshot();
});
-test('debug should use debugOptions from config when no option is specified', () => {
+test('debug should use debugOptions from config when no option is specified', async () => {
configure({ defaultDebugOptions: { mapProps: () => ({}) } });
- render(
+ await render(
hello
,
@@ -153,17 +153,17 @@ test('debug should use debugOptions from config when no option is specified', ()
expect(mockCalls[0][0]).toMatchSnapshot();
});
-test('filtering out props through mapProps option should not modify component', () => {
- render();
+test('filtering out props through mapProps option should not modify component', async () => {
+ await render();
screen.debug({ mapProps: () => ({}) });
expect(screen.getByTestId('viewTestID')).toBeTruthy();
});
-test('debug should use given options over config debugOptions', () => {
+test('debug should use given options over config debugOptions', async () => {
configure({ defaultDebugOptions: { mapProps: () => ({}) } });
- render(
+ await render(
hello
,
diff --git a/src/__tests__/render-hook.test.tsx b/src/__tests__/render-hook.test.tsx
index 782fec0d1..ca1f3f828 100644
--- a/src/__tests__/render-hook.test.tsx
+++ b/src/__tests__/render-hook.test.tsx
@@ -203,10 +203,10 @@ test('handles hook with suspense', async () => {
});
class ErrorBoundary extends React.Component<
- { children: React.ReactNode; fallback: string },
+ { children: React.ReactNode; fallback: React.ReactNode },
{ hasError: boolean }
> {
- constructor(props: { children: React.ReactNode; fallback: string }) {
+ constructor(props: { children: React.ReactNode; fallback: React.ReactNode }) {
super(props);
this.state = { hasError: false };
}
@@ -233,7 +233,7 @@ test('handles hook suspense with error boundary', async () => {
const { result } = await renderHook(useSuspendingHook, {
initialProps: promise,
wrapper: ({ children }) => (
-
+ Error Fallback}>
Loading...}>{children}
),
diff --git a/src/__tests__/render.test.tsx b/src/__tests__/render.test.tsx
index ae5c8d350..97cd6c732 100644
--- a/src/__tests__/render.test.tsx
+++ b/src/__tests__/render.test.tsx
@@ -1,25 +1,7 @@
import * as React from 'react';
-import { Pressable, Text, TextInput, View } from 'react-native';
+import { Text, View } from 'react-native';
-import type { RenderAPI } from '..';
-import { fireEvent, render, screen } from '..';
-
-const PLACEHOLDER_FRESHNESS = 'Add custom freshness';
-const PLACEHOLDER_CHEF = 'Who inspected freshness?';
-const INPUT_FRESHNESS = 'Custom Freshie';
-const INPUT_CHEF = 'I inspected freshie';
-const DEFAULT_INPUT_CHEF = 'What did you inspect?';
-const DEFAULT_INPUT_CUSTOMER = 'What banana?';
-
-class MyButton extends React.Component {
- render() {
- return (
-
- {this.props.children}
-
- );
- }
-}
+import { render, screen } from '..';
class Banana extends React.Component {
state = {
@@ -45,169 +27,46 @@ class Banana extends React.Component {
};
render() {
- const test = 0;
return (
Is the banana fresh?
{this.state.fresh ? 'fresh' : 'not fresh'}
-
-
-
-
-
- Change freshness!
-
- First Text
- Second Text
- {test}
);
}
}
-test('supports basic rendering', () => {
- render();
- expect(screen.root).toBeOnTheScreen();
-});
-
-test('rerender', async () => {
- const fn = jest.fn();
- render();
- expect(fn).toHaveBeenCalledTimes(0);
-
- await fireEvent.press(screen.getByText('Change freshness!'));
- expect(fn).toHaveBeenCalledTimes(1);
-
- screen.rerender();
- expect(fn).toHaveBeenCalledTimes(2);
-});
-
-test('unmount', () => {
- const fn = jest.fn();
- render();
- screen.unmount();
- expect(fn).toHaveBeenCalled();
-});
-
-test('unmount should handle cleanup functions', () => {
- const cleanup = jest.fn();
- const Component = () => {
- React.useEffect(() => cleanup);
- return null;
- };
-
- render();
-
- screen.unmount();
-
- expect(cleanup).toHaveBeenCalledTimes(1);
-});
-
-test('toJSON renders host output', () => {
- render(press me);
- expect(screen).toMatchSnapshot();
+test('render renders component asynchronously', async () => {
+ await render();
+ expect(screen.getByTestId('test')).toBeOnTheScreen();
});
-test('renders options.wrapper around node', () => {
- type WrapperComponentProps = { children: React.ReactNode };
- const WrapperComponent = ({ children }: WrapperComponentProps) => (
+test('render with wrapper option', async () => {
+ const WrapperComponent = ({ children }: { children: React.ReactNode }) => (
{children}
);
- render(, {
+ await render(, {
wrapper: WrapperComponent,
});
expect(screen.getByTestId('wrapper')).toBeTruthy();
- expect(screen).toMatchInlineSnapshot(`
-
-
-
- `);
+ expect(screen.getByTestId('inner')).toBeTruthy();
});
-test('renders options.wrapper around updated node', () => {
- type WrapperComponentProps = { children: React.ReactNode };
- const WrapperComponent = ({ children }: WrapperComponentProps) => (
- {children}
- );
-
- render(, {
- wrapper: WrapperComponent,
- });
-
- screen.rerender();
-
- expect(screen.getByTestId('wrapper')).toBeTruthy();
- expect(screen).toMatchInlineSnapshot(`
-
-
-
- `);
-});
-
-test('returns host root', () => {
- render();
-
- expect(screen.root).toBeDefined();
- expect(screen.root?.type).toBe('View');
- expect(screen.root?.props.testID).toBe('inner');
-});
-
-test('RenderAPI type', () => {
- render() as RenderAPI;
- expect(true).toBeTruthy();
-});
-
-test('returned output can be spread using rest operator', () => {
- // Next line should not throw
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const { rerender, ...rest } = render();
- expect(rest).toBeTruthy();
-});
-
-test('rerenderAsync updates the component asynchronously', async () => {
+test('rerender function updates component asynchronously', async () => {
const fn = jest.fn();
- const result = render();
-
- await result.rerenderAsync();
-
- expect(fn).toHaveBeenCalledTimes(1);
-});
-
-test('updateAsync is an alias for rerenderAsync', async () => {
- const fn = jest.fn();
- const result = render();
-
- await result.updateAsync();
+ await render();
+ expect(fn).toHaveBeenCalledTimes(0);
+ await screen.rerender();
expect(fn).toHaveBeenCalledTimes(1);
});
-test('unmountAsync unmounts the component asynchronously', async () => {
+test('unmount function unmounts component asynchronously', async () => {
const fn = jest.fn();
- const result = render();
-
- await result.unmountAsync();
+ await render();
+ await screen.unmount();
expect(fn).toHaveBeenCalled();
});
diff --git a/src/__tests__/screen.test.tsx b/src/__tests__/screen.test.tsx
index d41bd4e29..59b95bf4b 100644
--- a/src/__tests__/screen.test.tsx
+++ b/src/__tests__/screen.test.tsx
@@ -3,8 +3,8 @@ import { Text, View } from 'react-native';
import { render, screen } from '..';
-test('screen has the same queries as render result', () => {
- const result = render(Mt. Everest);
+test('screen has the same queries as render result', async () => {
+ const result = await render(Mt. Everest);
expect(screen).toBe(result);
expect(screen.getByText('Mt. Everest')).toBeTruthy();
@@ -13,10 +13,10 @@ test('screen has the same queries as render result', () => {
expect(screen.queryAllByText('Mt. Everest')).toHaveLength(1);
});
-test('screen holds last render result', () => {
- render(Mt. Everest);
- render(Mt. Blanc);
- const finalResult = render(Śnieżka);
+test('screen holds last render result', async () => {
+ await render(Mt. Everest);
+ await render(Mt. Blanc);
+ const finalResult = await render(Śnieżka);
expect(screen).toBe(finalResult);
expect(screen.getByText('Śnieżka')).toBeTruthy();
@@ -24,24 +24,24 @@ test('screen holds last render result', () => {
expect(screen.queryByText('Mt. Blanc')).toBeFalsy();
});
-test('screen works with updating rerender', () => {
- const result = render(Mt. Everest);
+test('screen works with updating rerender', async () => {
+ const result = await render(Mt. Everest);
expect(screen).toBe(result);
- screen.rerender(Śnieżka);
+ await screen.rerender(Śnieżka);
expect(screen).toBe(result);
expect(screen.getByText('Śnieżka')).toBeTruthy();
});
-test('screen works with nested re-mounting rerender', () => {
- const result = render(
+test('screen works with nested re-mounting rerender', async () => {
+ const result = await render(
Mt. Everest
,
);
expect(screen).toBe(result);
- screen.rerender(
+ await screen.rerender(
Śnieżka
@@ -53,8 +53,8 @@ test('screen works with nested re-mounting rerender', () => {
});
test('screen throws without render', () => {
- expect(() => screen.container).toThrow('`render` method has not been called');
- expect(() => screen.root).toThrow('`render` method has not been called');
- expect(() => screen.debug()).toThrow('`render` method has not been called');
- expect(() => screen.getByText('Mt. Everest')).toThrow('`render` method has not been called');
+ expect(() => screen.container).toThrow('`render` function has not been called');
+ expect(() => screen.root).toThrow('`render` function has not been called');
+ expect(() => screen.debug()).toThrow('`render` function has not been called');
+ expect(() => screen.getByText('Mt. Everest')).toThrow('`render` function has not been called');
});
diff --git a/src/__tests__/suspense-fake-timers.test.tsx b/src/__tests__/suspense-fake-timers.test.tsx
index efb09a8ec..495971337 100644
--- a/src/__tests__/suspense-fake-timers.test.tsx
+++ b/src/__tests__/suspense-fake-timers.test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Text, View } from 'react-native';
-import { act, renderAsync, screen } from '..';
+import { act, render, screen } from '..';
import { excludeConsoleMessage } from '../test-utils/console';
jest.useFakeTimers();
@@ -26,7 +26,7 @@ test('resolves manually-controlled promise', async () => {
resolvePromise = resolve;
});
- await renderAsync(
+ await render(
Loading...}>
@@ -50,7 +50,7 @@ test('resolves timer-controlled promise', async () => {
setTimeout(() => resolve(null), 100);
});
- await renderAsync(
+ await render(
Loading...}>
@@ -96,7 +96,7 @@ test('handles promise rejection with error boundary', async () => {
rejectPromise = reject;
});
- await renderAsync(
+ await render(
Error occurred}>
Loading...}>
@@ -126,7 +126,7 @@ test('handles multiple suspending components', async () => {
resolvePromise2 = resolve;
});
- await renderAsync(
+ await render(
Loading...}>
@@ -163,7 +163,7 @@ test('handles multiple suspense boundaries independently', async () => {
resolvePromise2 = resolve;
});
- await renderAsync(
+ await render(
First Loading...}>
diff --git a/src/__tests__/suspense.test.tsx b/src/__tests__/suspense.test.tsx
index c84e93b12..eded69052 100644
--- a/src/__tests__/suspense.test.tsx
+++ b/src/__tests__/suspense.test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Text, View } from 'react-native';
-import { act, renderAsync, screen } from '..';
+import { act, render, screen } from '..';
import { excludeConsoleMessage } from '../test-utils/console';
// eslint-disable-next-line no-console
@@ -24,7 +24,7 @@ test('resolves manually-controlled promise', async () => {
resolvePromise = resolve;
});
- await renderAsync(
+ await render(
Loading...}>
@@ -48,7 +48,7 @@ test('resolves timer-controlled promise', async () => {
setTimeout(() => resolve(null), 100);
});
- await renderAsync(
+ await render(
Loading...}>
@@ -93,7 +93,7 @@ test('handles promise rejection with error boundary', async () => {
rejectPromise = reject;
});
- await renderAsync(
+ await render(
Error occurred}>
Loading...}>
@@ -123,7 +123,7 @@ test('handles multiple suspending components', async () => {
resolvePromise2 = resolve;
});
- await renderAsync(
+ await render(
Loading...}>
@@ -160,7 +160,7 @@ test('handles multiple suspense boundaries independently', async () => {
resolvePromise2 = resolve;
});
- await renderAsync(
+ await render(
First Loading...}>
diff --git a/src/__tests__/timers.test.ts b/src/__tests__/timers.test.ts
index acb9ec4c5..2c3a40a75 100644
--- a/src/__tests__/timers.test.ts
+++ b/src/__tests__/timers.test.ts
@@ -1,4 +1,4 @@
-import waitFor from '../wait-for';
+import { waitFor } from '../wait-for';
describe.each([false, true])('fake timers tests (legacyFakeTimers = %s)', (legacyFakeTimers) => {
beforeEach(() => {
diff --git a/src/__tests__/deprecated/fire-event-sync.test.tsx b/src/__tests__/unsafe-fire-event-sync.test.tsx
similarity index 67%
rename from src/__tests__/deprecated/fire-event-sync.test.tsx
rename to src/__tests__/unsafe-fire-event-sync.test.tsx
index d87f09c7f..c1fae505b 100644
--- a/src/__tests__/deprecated/fire-event-sync.test.tsx
+++ b/src/__tests__/unsafe-fire-event-sync.test.tsx
@@ -9,7 +9,7 @@ import {
View,
} from 'react-native';
-import { deprecated_fireEventSync, render, screen } from '../..';
+import { screen, unsafe_fireEventSync, unsafe_renderSync } from '..';
type OnPressComponentProps = {
onPress: () => void;
@@ -36,6 +36,7 @@ type MyCustomButtonProps = {
handlePress: () => void;
text: string;
};
+
const MyCustomButton = ({ handlePress, text }: MyCustomButtonProps) => (
);
@@ -43,18 +44,19 @@ const MyCustomButton = ({ handlePress, text }: MyCustomButtonProps) => (
type CustomEventComponentWithCustomNameProps = {
handlePress: () => void;
};
+
const CustomEventComponentWithCustomName = ({
handlePress,
}: CustomEventComponentWithCustomNameProps) => (
);
-describe('deprecated_fireEventSync', () => {
+describe('unsafe_fireEventSync', () => {
test('should invoke specified event', () => {
const onPressMock = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByText('Press me'), 'press');
+ unsafe_fireEventSync(screen.getByText('Press me'), 'press');
expect(onPressMock).toHaveBeenCalled();
});
@@ -62,9 +64,9 @@ describe('deprecated_fireEventSync', () => {
test('should invoke specified event on parent element', () => {
const onPressMock = jest.fn();
const text = 'New press text';
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByText(text), 'press');
+ unsafe_fireEventSync(screen.getByText(text), 'press');
expect(onPressMock).toHaveBeenCalled();
});
@@ -72,19 +74,19 @@ describe('deprecated_fireEventSync', () => {
const handlerMock = jest.fn();
const EVENT_DATA = 'event data';
- render(
+ unsafe_renderSync(
,
);
- deprecated_fireEventSync(screen.getByText('Custom event component'), 'customEvent', EVENT_DATA);
+ unsafe_fireEventSync(screen.getByText('Custom event component'), 'customEvent', EVENT_DATA);
expect(handlerMock).toHaveBeenCalledWith(EVENT_DATA);
});
});
-test('deprecated_fireEventSync.press', () => {
+test('unsafe_fireEventSync.press', () => {
const onPressMock = jest.fn();
const text = 'Fireevent press';
const eventData = {
@@ -93,14 +95,14 @@ test('deprecated_fireEventSync.press', () => {
pageY: 30,
},
};
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync.press(screen.getByText(text), eventData);
+ unsafe_fireEventSync.press(screen.getByText(text), eventData);
expect(onPressMock).toHaveBeenCalledWith(eventData);
});
-test('deprecated_fireEventSync.scroll', () => {
+test('unsafe_fireEventSync.scroll', () => {
const onScrollMock = jest.fn();
const eventData = {
nativeEvent: {
@@ -110,47 +112,47 @@ test('deprecated_fireEventSync.scroll', () => {
},
};
- render(
+ unsafe_renderSync(
XD
,
);
- deprecated_fireEventSync.scroll(screen.getByText('XD'), eventData);
+ unsafe_fireEventSync.scroll(screen.getByText('XD'), eventData);
expect(onScrollMock).toHaveBeenCalledWith(eventData);
});
-test('deprecated_fireEventSync.changeText', () => {
+test('unsafe_fireEventSync.changeText', () => {
const onChangeTextMock = jest.fn();
- render(
+ unsafe_renderSync(
,
);
const input = screen.getByPlaceholderText('Customer placeholder');
- deprecated_fireEventSync.changeText(input, 'content');
+ unsafe_fireEventSync.changeText(input, 'content');
expect(onChangeTextMock).toHaveBeenCalledWith('content');
});
it('sets native state value for unmanaged text inputs', () => {
- render();
+ unsafe_renderSync();
const input = screen.getByTestId('input');
expect(input).toHaveDisplayValue('');
- deprecated_fireEventSync.changeText(input, 'abc');
+ unsafe_fireEventSync.changeText(input, 'abc');
expect(input).toHaveDisplayValue('abc');
});
test('custom component with custom event name', () => {
const handlePress = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByText('Custom component'), 'handlePress');
+ unsafe_fireEventSync(screen.getByText('Custom component'), 'handlePress');
expect(handlePress).toHaveBeenCalled();
});
@@ -158,16 +160,16 @@ test('custom component with custom event name', () => {
test('event with multiple handler parameters', () => {
const handlePress = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByText('Custom component'), 'handlePress', 'param1', 'param2');
+ unsafe_fireEventSync(screen.getByText('Custom component'), 'handlePress', 'param1', 'param2');
expect(handlePress).toHaveBeenCalledWith('param1', 'param2');
});
test('should not fire on disabled TouchableOpacity', () => {
const handlePress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -175,13 +177,13 @@ test('should not fire on disabled TouchableOpacity', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
expect(handlePress).not.toHaveBeenCalled();
});
test('should not fire on disabled Pressable', () => {
const handlePress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -189,13 +191,13 @@ test('should not fire on disabled Pressable', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
expect(handlePress).not.toHaveBeenCalled();
});
test('should not fire inside View with pointerEvents="none" in props', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -203,14 +205,14 @@ test('should not fire inside View with pointerEvents="none" in props', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should not fire inside View with pointerEvents="none" in styles', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -218,14 +220,14 @@ test('should not fire inside View with pointerEvents="none" in styles', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should not fire inside View with pointerEvents="none" in styles array', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -233,14 +235,14 @@ test('should not fire inside View with pointerEvents="none" in styles array', ()
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should not fire inside View with pointerEvents="box-only" in props', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -248,14 +250,14 @@ test('should not fire inside View with pointerEvents="box-only" in props', () =>
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should not fire inside View with pointerEvents="box-only" in styles', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -263,14 +265,14 @@ test('should not fire inside View with pointerEvents="box-only" in styles', () =
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should fire inside View with pointerEvents="box-none" in props', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -278,14 +280,14 @@ test('should fire inside View with pointerEvents="box-none" in props', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).toHaveBeenCalledTimes(2);
});
test('should fire inside View with pointerEvents="box-none" in styles', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -293,14 +295,14 @@ test('should fire inside View with pointerEvents="box-none" in styles', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).toHaveBeenCalledTimes(2);
});
test('should fire inside View with pointerEvents="auto" in props', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -308,14 +310,14 @@ test('should fire inside View with pointerEvents="auto" in props', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).toHaveBeenCalledTimes(2);
});
test('should fire inside View with pointerEvents="auto" in styles', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
Trigger
@@ -323,14 +325,14 @@ test('should fire inside View with pointerEvents="auto" in styles', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).toHaveBeenCalledTimes(2);
});
test('should not fire deeply inside View with pointerEvents="box-only" in props', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
@@ -340,14 +342,14 @@ test('should not fire deeply inside View with pointerEvents="box-only" in props'
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should not fire deeply inside View with pointerEvents="box-only" in styles', () => {
const onPress = jest.fn();
- render(
+ unsafe_renderSync(
@@ -357,40 +359,44 @@ test('should not fire deeply inside View with pointerEvents="box-only" in styles
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
- deprecated_fireEventSync(screen.getByText('Trigger'), 'onPress');
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'onPress');
expect(onPress).not.toHaveBeenCalled();
});
test('should fire non-pointer events inside View with pointerEvents="box-none" in props', () => {
const onTouchStart = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByTestId('view'), 'touchStart');
+ unsafe_fireEventSync(screen.getByTestId('view'), 'touchStart');
expect(onTouchStart).toHaveBeenCalled();
});
test('should fire non-pointer events inside View with pointerEvents="box-none" in styles', () => {
const onTouchStart = jest.fn();
- render();
+ unsafe_renderSync(
+ ,
+ );
- deprecated_fireEventSync(screen.getByTestId('view'), 'touchStart');
+ unsafe_fireEventSync(screen.getByTestId('view'), 'touchStart');
expect(onTouchStart).toHaveBeenCalled();
});
test('should fire non-touch events inside View with pointerEvents="box-none" in props', () => {
const onLayout = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByTestId('view'), 'layout');
+ unsafe_fireEventSync(screen.getByTestId('view'), 'layout');
expect(onLayout).toHaveBeenCalled();
});
test('should fire non-touch events inside View with pointerEvents="box-none" in styles', () => {
const onLayout = jest.fn();
- render();
+ unsafe_renderSync(
+ ,
+ );
- deprecated_fireEventSync(screen.getByTestId('view'), 'layout');
+ unsafe_fireEventSync(screen.getByTestId('view'), 'layout');
expect(onLayout).toHaveBeenCalled();
});
@@ -398,24 +404,26 @@ test('should fire non-touch events inside View with pointerEvents="box-none" in
// the 'press' event on host View rendered by pressable.
test('should fire on Pressable with pointerEvents="box-only" in props', () => {
const onPress = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync.press(screen.getByTestId('pressable'));
+ unsafe_fireEventSync.press(screen.getByTestId('pressable'));
expect(onPress).toHaveBeenCalled();
});
test('should fire on Pressable with pointerEvents="box-only" in styles', () => {
const onPress = jest.fn();
- render();
+ unsafe_renderSync(
+ ,
+ );
- deprecated_fireEventSync.press(screen.getByTestId('pressable'));
+ unsafe_fireEventSync.press(screen.getByTestId('pressable'));
expect(onPress).toHaveBeenCalled();
});
test('should pass event up on disabled TouchableOpacity', () => {
const handleInnerPress = jest.fn();
const handleOuterPress = jest.fn();
- render(
+ unsafe_renderSync(
Inner Trigger
@@ -423,7 +431,7 @@ test('should pass event up on disabled TouchableOpacity', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Inner Trigger'));
+ unsafe_fireEventSync.press(screen.getByText('Inner Trigger'));
expect(handleInnerPress).not.toHaveBeenCalled();
expect(handleOuterPress).toHaveBeenCalledTimes(1);
});
@@ -431,7 +439,7 @@ test('should pass event up on disabled TouchableOpacity', () => {
test('should pass event up on disabled Pressable', () => {
const handleInnerPress = jest.fn();
const handleOuterPress = jest.fn();
- render(
+ unsafe_renderSync(
Inner Trigger
@@ -439,7 +447,7 @@ test('should pass event up on disabled Pressable', () => {
,
);
- deprecated_fireEventSync.press(screen.getByText('Inner Trigger'));
+ unsafe_fireEventSync.press(screen.getByText('Inner Trigger'));
expect(handleInnerPress).not.toHaveBeenCalled();
expect(handleOuterPress).toHaveBeenCalledTimes(1);
});
@@ -458,9 +466,9 @@ const TestComponent = ({ onPress }: TestComponentProps) => {
test('is not fooled by non-native disabled prop', () => {
const handlePress = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync.press(screen.getByText('Trigger Test'));
+ unsafe_fireEventSync.press(screen.getByText('Trigger Test'));
expect(handlePress).toHaveBeenCalledTimes(1);
});
@@ -482,13 +490,13 @@ function TestChildTouchableComponent({ onPress, someProp }: TestChildTouchableCo
test('is not fooled by non-responder wrapping host elements', () => {
const handlePress = jest.fn();
- render(
+ unsafe_renderSync(
,
);
- deprecated_fireEventSync.press(screen.getByText('Trigger'));
+ unsafe_fireEventSync.press(screen.getByText('Trigger'));
expect(handlePress).not.toHaveBeenCalled();
});
@@ -510,62 +518,64 @@ function TestDraggableComponent({ onDrag }: TestDraggableComponentProps) {
test('has only onMove', () => {
const handleDrag = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByText('Trigger'), 'responderMove', {
+ unsafe_fireEventSync(screen.getByText('Trigger'), 'responderMove', {
touchHistory: { mostRecentTimeStamp: '2', touchBank: [] },
});
expect(handleDrag).toHaveBeenCalled();
});
-// Those events ideally should be triggered through `deprecated_fireEventSync.scroll`, but they are handled at the
+// Those events ideally should be triggered through `unsafe_fireEventSync.scroll`, but they are handled at the
// native level, so we need to support manually triggering them
describe('native events', () => {
test('triggers onScrollBeginDrag', () => {
const onScrollBeginDragSpy = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByTestId('test-id'), 'onScrollBeginDrag');
+ unsafe_fireEventSync(screen.getByTestId('test-id'), 'onScrollBeginDrag');
expect(onScrollBeginDragSpy).toHaveBeenCalled();
});
test('triggers onScrollEndDrag', () => {
const onScrollEndDragSpy = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByTestId('test-id'), 'onScrollEndDrag');
+ unsafe_fireEventSync(screen.getByTestId('test-id'), 'onScrollEndDrag');
expect(onScrollEndDragSpy).toHaveBeenCalled();
});
test('triggers onMomentumScrollBegin', () => {
const onMomentumScrollBeginSpy = jest.fn();
- render();
+ unsafe_renderSync(
+ ,
+ );
- deprecated_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollBegin');
+ unsafe_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollBegin');
expect(onMomentumScrollBeginSpy).toHaveBeenCalled();
});
test('triggers onMomentumScrollEnd', () => {
const onMomentumScrollEndSpy = jest.fn();
- render();
+ unsafe_renderSync();
- deprecated_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollEnd');
+ unsafe_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollEnd');
expect(onMomentumScrollEndSpy).toHaveBeenCalled();
});
});
test('should handle unmounted elements gracefully', () => {
const onPress = jest.fn();
- render(
+ const { unmount } = unsafe_renderSync(
Test
,
);
const element = screen.getByText('Test');
- screen.unmount();
+ unmount();
// Firing event on unmounted element should not crash
- deprecated_fireEventSync.press(element);
+ unsafe_fireEventSync.press(element);
expect(onPress).not.toHaveBeenCalled();
});
diff --git a/src/__tests__/deprecated/render-hook-sync.test.tsx b/src/__tests__/unsafe-render-hook-sync.test.tsx
similarity index 82%
rename from src/__tests__/deprecated/render-hook-sync.test.tsx
rename to src/__tests__/unsafe-render-hook-sync.test.tsx
index 53a5e2ca8..fd95f491d 100644
--- a/src/__tests__/deprecated/render-hook-sync.test.tsx
+++ b/src/__tests__/unsafe-render-hook-sync.test.tsx
@@ -1,10 +1,10 @@
import type { ReactNode } from 'react';
import * as React from 'react';
-import { deprecated_renderHookSync } from '../../pure';
+import { unsafe_renderHookSync } from '../pure';
test('renders hook and returns committed result', () => {
- const { result } = deprecated_renderHookSync(() => {
+ const { result } = unsafe_renderHookSync(() => {
const [state, setState] = React.useState(1);
React.useEffect(() => {
@@ -22,7 +22,7 @@ test('works with wrapper option', () => {
function Wrapper({ children }: { children: ReactNode }) {
return {children};
}
- const { result } = deprecated_renderHookSync(
+ const { result } = unsafe_renderHookSync(
() => {
return React.useContext(Context);
},
@@ -35,7 +35,7 @@ test('works with wrapper option', () => {
});
test('works with initialProps option', () => {
- const { result } = deprecated_renderHookSync(
+ const { result } = unsafe_renderHookSync(
(props: { branch: 'left' | 'right' }) => {
const [left, setLeft] = React.useState('left');
const [right, setRight] = React.useState('right');
@@ -61,12 +61,12 @@ test('works without initialProps option', () => {
return { count, setCount };
}
- const { result } = deprecated_renderHookSync(useTestHook);
+ const { result } = unsafe_renderHookSync(useTestHook);
expect(result.current.count).toBe(0);
});
test('rerender updates hook with new props', () => {
- const { result, rerender } = deprecated_renderHookSync(
+ const { result, rerender } = unsafe_renderHookSync(
(props: { branch: 'left' | 'right' }) => {
const [left, setLeft] = React.useState('left');
const [right, setRight] = React.useState('right');
@@ -102,7 +102,7 @@ test('unmount triggers cleanup effects', () => {
return 'test';
}
- const { unmount } = deprecated_renderHookSync(useTestHook);
+ const { unmount } = unsafe_renderHookSync(useTestHook);
expect(cleanupCalled).toBe(false);
unmount();
@@ -114,7 +114,7 @@ function useMyHook(param: T) {
}
test('props type is inferred correctly when initial props is defined', () => {
- const { result, rerender } = deprecated_renderHookSync((num: number) => useMyHook(num), {
+ const { result, rerender } = unsafe_renderHookSync((num: number) => useMyHook(num), {
initialProps: 5,
});
expect(result.current.param).toBe(5);
@@ -124,12 +124,9 @@ test('props type is inferred correctly when initial props is defined', () => {
});
test('props type is inferred correctly when initial props is explicitly undefined', () => {
- const { result, rerender } = deprecated_renderHookSync(
- (num: number | undefined) => useMyHook(num),
- {
- initialProps: undefined,
- },
- );
+ const { result, rerender } = unsafe_renderHookSync((num: number | undefined) => useMyHook(num), {
+ initialProps: undefined,
+ });
expect(result.current.param).toBeUndefined();
diff --git a/src/__tests__/unsafe-render-sync.test.tsx b/src/__tests__/unsafe-render-sync.test.tsx
new file mode 100644
index 000000000..38596dd94
--- /dev/null
+++ b/src/__tests__/unsafe-render-sync.test.tsx
@@ -0,0 +1,185 @@
+import * as React from 'react';
+import { Pressable, Text, TextInput, View } from 'react-native';
+
+import { screen, unsafe_fireEventSync, unsafe_renderSync } from '..';
+
+const PLACEHOLDER_FRESHNESS = 'Add custom freshness';
+const PLACEHOLDER_CHEF = 'Who inspected freshness?';
+const INPUT_FRESHNESS = 'Custom Freshie';
+const INPUT_CHEF = 'I inspected freshie';
+const DEFAULT_INPUT_CHEF = 'What did you inspect?';
+const DEFAULT_INPUT_CUSTOMER = 'What banana?';
+
+class MyButton extends React.Component {
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+class Banana extends React.Component {
+ state = {
+ fresh: false,
+ };
+
+ componentDidUpdate() {
+ if (this.props.onUpdate) {
+ this.props.onUpdate();
+ }
+ }
+
+ componentWillUnmount() {
+ if (this.props.onUnmount) {
+ this.props.onUnmount();
+ }
+ }
+
+ changeFresh = () => {
+ this.setState((state) => ({
+ fresh: !state.fresh,
+ }));
+ };
+
+ render() {
+ const test = 0;
+ return (
+
+ Is the banana fresh?
+ {this.state.fresh ? 'fresh' : 'not fresh'}
+
+
+
+
+
+ Change freshness!
+
+ First Text
+ Second Text
+ {test}
+
+ );
+ }
+}
+
+test('supports basic rendering', () => {
+ unsafe_renderSync();
+ expect(screen.root).toBeOnTheScreen();
+});
+
+test('rerender', () => {
+ const fn = jest.fn();
+ const { rerender } = unsafe_renderSync();
+ expect(fn).toHaveBeenCalledTimes(0);
+
+ unsafe_fireEventSync.press(screen.getByText('Change freshness!'));
+ expect(fn).toHaveBeenCalledTimes(1);
+
+ rerender();
+ expect(fn).toHaveBeenCalledTimes(2);
+});
+
+test('unmount', () => {
+ const fn = jest.fn();
+ const { unmount } = unsafe_renderSync();
+ unmount();
+ expect(fn).toHaveBeenCalled();
+});
+
+test('unmount should handle cleanup functions', () => {
+ const cleanup = jest.fn();
+ const Component = () => {
+ React.useEffect(() => cleanup);
+ return null;
+ };
+
+ const { unmount } = unsafe_renderSync();
+
+ unmount();
+
+ expect(cleanup).toHaveBeenCalledTimes(1);
+});
+
+test('toJSON renders host output', () => {
+ unsafe_renderSync(press me);
+ expect(screen).toMatchSnapshot();
+});
+
+test('renders options.wrapper around node', () => {
+ type WrapperComponentProps = { children: React.ReactNode };
+ const WrapperComponent = ({ children }: WrapperComponentProps) => (
+ {children}
+ );
+
+ unsafe_renderSync(, {
+ wrapper: WrapperComponent,
+ });
+
+ expect(screen.getByTestId('wrapper')).toBeTruthy();
+ expect(screen).toMatchInlineSnapshot(`
+
+
+
+ `);
+});
+
+test('renders options.wrapper around updated node', () => {
+ type WrapperComponentProps = { children: React.ReactNode };
+ const WrapperComponent = ({ children }: WrapperComponentProps) => (
+ {children}
+ );
+
+ unsafe_renderSync(, {
+ wrapper: WrapperComponent,
+ });
+
+ void screen.rerender();
+
+ expect(screen.getByTestId('wrapper')).toBeTruthy();
+ expect(screen).toMatchInlineSnapshot(`
+
+
+
+ `);
+});
+
+test('returns host root', () => {
+ unsafe_renderSync();
+
+ expect(screen.root).toBeDefined();
+ expect(screen.root?.type).toBe('View');
+ expect(screen.root?.props.testID).toBe('inner');
+});
+
+test('RenderAPI type', () => {
+ // This test verifies that unsafe_renderSync returns a compatible type
+ // Note: unsafe_renderSync has different method signatures (sync vs async)
+ const result = unsafe_renderSync();
+ expect(result).toBeTruthy();
+});
+
+test('returned output can be spread using rest operator', () => {
+ // Next line should not throw
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { rerender, ...rest } = unsafe_renderSync();
+ expect(rest).toBeTruthy();
+});
diff --git a/src/__tests__/wait-for-element-to-be-removed.test.tsx b/src/__tests__/wait-for-element-to-be-removed.test.tsx
index 0dda4ae87..b40ab679b 100644
--- a/src/__tests__/wait-for-element-to-be-removed.test.tsx
+++ b/src/__tests__/wait-for-element-to-be-removed.test.tsx
@@ -30,7 +30,7 @@ afterEach(() => {
});
test('waits when using getBy query', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
const element = screen.getByText('Observed Element');
@@ -42,7 +42,7 @@ test('waits when using getBy query', async () => {
});
test('waits when using getAllBy query', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
const elements = screen.getAllByText('Observed Element');
@@ -54,7 +54,7 @@ test('waits when using getAllBy query', async () => {
});
test('waits when using queryBy query', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
const element = screen.getByText('Observed Element');
@@ -66,7 +66,7 @@ test('waits when using queryBy query', async () => {
});
test('waits when using queryAllBy query', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
const elements = screen.getAllByText('Observed Element');
@@ -78,7 +78,7 @@ test('waits when using queryAllBy query', async () => {
});
test('checks if elements exist at start', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
expect(screen.queryByText('Observed Element')).toBeNull();
@@ -91,7 +91,7 @@ test('checks if elements exist at start', async () => {
});
test('waits until timeout', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Remove Element'));
expect(screen.getByText('Observed Element')).toBeTruthy();
diff --git a/src/__tests__/wait-for.test.tsx b/src/__tests__/wait-for.test.tsx
index 4efd0253c..b9235b3e9 100644
--- a/src/__tests__/wait-for.test.tsx
+++ b/src/__tests__/wait-for.test.tsx
@@ -38,7 +38,7 @@ afterEach(() => {
});
test('waits for element until it stops throwing', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Change freshness!'));
@@ -50,7 +50,7 @@ test('waits for element until it stops throwing', async () => {
});
test('waits for element until timeout is met', async () => {
- render();
+ await render();
await fireEvent.press(screen.getByText('Change freshness!'));
@@ -63,7 +63,7 @@ test('waits for element until timeout is met', async () => {
test('waitFor defaults to asyncWaitTimeout config option', async () => {
configure({ asyncUtilTimeout: 100 });
- render();
+ await render();
await fireEvent.press(screen.getByText('Change freshness!'));
await expect(waitFor(() => screen.getByText('Fresh'))).rejects.toThrow();
@@ -75,7 +75,7 @@ test('waitFor defaults to asyncWaitTimeout config option', async () => {
test('waitFor timeout option takes precendence over `asyncWaitTimeout` config option', async () => {
configure({ asyncUtilTimeout: 2000 });
- render();
+ await render();
await fireEvent.press(screen.getByText('Change freshness!'));
await expect(waitFor(() => screen.getByText('Fresh'), { timeout: 100 })).rejects.toThrow();
@@ -125,7 +125,7 @@ const Comp = ({ onPress }: { onPress: () => void }) => {
test('waits for async event with fireEvent', async () => {
const spy = jest.fn();
- render();
+ await render();
await fireEvent.press(screen.getByText('Trigger'));
@@ -138,7 +138,7 @@ test.each([false, true])(
'waits for element until it stops throwing using fake timers (legacyFakeTimers = %s)',
async (legacyFakeTimers) => {
jest.useFakeTimers({ legacyFakeTimers });
- render();
+ await render();
await fireEvent.press(screen.getByText('Change freshness!'));
expect(screen.queryByText('Fresh')).toBeNull();
@@ -294,7 +294,7 @@ test.each([
}
const onPress = jest.fn();
- render();
+ await render();
// Required: this `waitFor` will succeed on first check, because the "root" view is there
// since the initial mount.
diff --git a/src/__tests__/within.test.tsx b/src/__tests__/within.test.tsx
index 105aa081d..bd6889d99 100644
--- a/src/__tests__/within.test.tsx
+++ b/src/__tests__/within.test.tsx
@@ -4,7 +4,7 @@ import { Text, TextInput, View } from 'react-native';
import { getQueriesForElement, render, within } from '..';
test('within() exposes basic queries', async () => {
- const rootQueries = render(
+ const rootQueries = await render(
Same Text
@@ -41,7 +41,7 @@ test('within() exposes basic queries', async () => {
});
test('within() exposes a11y queries', async () => {
- const rootQueries = render(
+ const rootQueries = await render(
void;
-type CleanUpFunctionAsync = () => Promise;
+type CleanUpFunction = () => Promise | void;
-const cleanupQueue = new Set();
+const cleanupQueue = new Set();
-export default function cleanup() {
- clearRenderResult();
-
- cleanupQueue.forEach((fn) => fn());
- cleanupQueue.clear();
-}
-
-export async function cleanupAsync() {
+export async function cleanup() {
clearRenderResult();
for (const fn of cleanupQueue) {
@@ -22,6 +14,6 @@ export async function cleanupAsync() {
cleanupQueue.clear();
}
-export function addToCleanupQueue(fn: CleanUpFunction | CleanUpFunctionAsync) {
+export function addToCleanupQueue(fn: CleanUpFunction) {
cleanupQueue.add(fn);
}
diff --git a/src/fire-event.ts b/src/fire-event.ts
index 17e1fb119..1fe38367c 100644
--- a/src/fire-event.ts
+++ b/src/fire-event.ts
@@ -157,7 +157,7 @@ fireEvent.scroll = async (element: HostElement, ...data: unknown[]) =>
await fireEvent(element, 'scroll', ...data);
/** @deprecated - Use async `fireEvent` instead. */
-function deprecated_fireEventSync(element: HostElement, eventName: EventName, ...data: unknown[]) {
+function unsafe_fireEventSync(element: HostElement, eventName: EventName, ...data: unknown[]) {
if (!isElementMounted(element)) {
return;
}
@@ -178,18 +178,18 @@ function deprecated_fireEventSync(element: HostElement, eventName: EventName, ..
}
/** @deprecated - Use async `fireEvent.press` instead. */
-deprecated_fireEventSync.press = (element: HostElement, ...data: unknown[]) =>
- deprecated_fireEventSync(element, 'press', ...data);
+unsafe_fireEventSync.press = (element: HostElement, ...data: unknown[]) =>
+ unsafe_fireEventSync(element, 'press', ...data);
/** @deprecated - Use async `fireEvent.changeText` instead. */
-deprecated_fireEventSync.changeText = (element: HostElement, ...data: unknown[]) =>
- deprecated_fireEventSync(element, 'changeText', ...data);
+unsafe_fireEventSync.changeText = (element: HostElement, ...data: unknown[]) =>
+ unsafe_fireEventSync(element, 'changeText', ...data);
/** @deprecated - Use async `fireEvent.scroll` instead. */
-deprecated_fireEventSync.scroll = (element: HostElement, ...data: unknown[]) =>
- deprecated_fireEventSync(element, 'scroll', ...data);
+unsafe_fireEventSync.scroll = (element: HostElement, ...data: unknown[]) =>
+ unsafe_fireEventSync(element, 'scroll', ...data);
-export { fireEvent, deprecated_fireEventSync };
+export { fireEvent, unsafe_fireEventSync };
const scrollEventNames = new Set([
'scroll',
diff --git a/src/helpers/__tests__/accessiblity.test.tsx b/src/helpers/__tests__/accessiblity.test.tsx
index dd277c596..64331884d 100644
--- a/src/helpers/__tests__/accessiblity.test.tsx
+++ b/src/helpers/__tests__/accessiblity.test.tsx
@@ -5,10 +5,10 @@ import { isHiddenFromAccessibility, isInaccessible, render, screen } from '../..
import { computeAriaDisabled, computeAriaLabel, isAccessibilityElement } from '../accessibility';
describe('isHiddenFromAccessibility', () => {
- test('returns false for accessible elements', () => {
+ test('returns false for accessible elements', async () => {
expect(
isHiddenFromAccessibility(
- render().getByTestId('subject', {
+ (await render()).getByTestId('subject', {
includeHiddenElements: true,
}),
),
@@ -16,7 +16,7 @@ describe('isHiddenFromAccessibility', () => {
expect(
isHiddenFromAccessibility(
- render(Hello).getByTestId('subject', {
+ (await render(Hello)).getByTestId('subject', {
includeHiddenElements: true,
}),
),
@@ -24,7 +24,7 @@ describe('isHiddenFromAccessibility', () => {
expect(
isHiddenFromAccessibility(
- render().getByTestId('subject', {
+ (await render()).getByTestId('subject', {
includeHiddenElements: true,
}),
),
@@ -35,8 +35,8 @@ describe('isHiddenFromAccessibility', () => {
expect(isHiddenFromAccessibility(null)).toBe(true);
});
- test('detects elements with aria-hidden prop', () => {
- render();
+ test('detects elements with aria-hidden prop', async () => {
+ await render();
expect(
isHiddenFromAccessibility(
screen.getByTestId('subject', {
@@ -46,8 +46,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects nested elements with aria-hidden prop', () => {
- render(
+ test('detects nested elements with aria-hidden prop', async () => {
+ await render(
,
@@ -61,8 +61,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects elements with accessibilityElementsHidden prop', () => {
- render();
+ test('detects elements with accessibilityElementsHidden prop', async () => {
+ await render();
expect(
isHiddenFromAccessibility(
screen.getByTestId('subject', {
@@ -72,8 +72,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects nested elements with accessibilityElementsHidden prop', () => {
- render(
+ test('detects nested elements with accessibilityElementsHidden prop', async () => {
+ await render(
,
@@ -87,8 +87,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects deeply nested elements with accessibilityElementsHidden prop', () => {
- render(
+ test('detects deeply nested elements with accessibilityElementsHidden prop', async () => {
+ await render(
@@ -106,8 +106,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects elements with importantForAccessibility="no-hide-descendants" prop', () => {
- render();
+ test('detects elements with importantForAccessibility="no-hide-descendants" prop', async () => {
+ await render();
expect(
isHiddenFromAccessibility(
screen.getByTestId('subject', {
@@ -117,8 +117,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects nested elements with importantForAccessibility="no-hide-descendants" prop', () => {
- render(
+ test('detects nested elements with importantForAccessibility="no-hide-descendants" prop', async () => {
+ await render(
,
@@ -132,8 +132,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects elements with display=none', () => {
- render();
+ test('detects elements with display=none', async () => {
+ await render();
expect(
isHiddenFromAccessibility(
screen.getByTestId('subject', {
@@ -143,8 +143,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects nested elements with display=none', () => {
- render(
+ test('detects nested elements with display=none', async () => {
+ await render(
,
@@ -158,8 +158,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects deeply nested elements with display=none', () => {
- render(
+ test('detects deeply nested elements with display=none', async () => {
+ await render(
@@ -177,8 +177,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects elements with display=none with complex style', () => {
- render(
+ test('detects elements with display=none with complex style', async () => {
+ await render(
{
).toBe(true);
});
- test('is not trigged by opacity = 0', () => {
- render();
+ test('is not trigged by opacity = 0', async () => {
+ await render();
expect(
isHiddenFromAccessibility(
screen.getByTestId('subject', {
@@ -204,8 +204,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(false);
});
- test('detects siblings of element with accessibilityViewIsModal prop', () => {
- render(
+ test('detects siblings of element with accessibilityViewIsModal prop', async () => {
+ await render(
@@ -220,8 +220,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects deeply nested siblings of element with accessibilityViewIsModal prop', () => {
- render(
+ test('detects deeply nested siblings of element with accessibilityViewIsModal prop', async () => {
+ await render(
@@ -236,8 +236,8 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('detects siblings of element with "aria-modal" prop', () => {
- render(
+ test('detects siblings of element with "aria-modal" prop', async () => {
+ await render(
@@ -248,13 +248,13 @@ describe('isHiddenFromAccessibility', () => {
).toBe(true);
});
- test('is not triggered for element with accessibilityViewIsModal prop', () => {
- render();
+ test('is not triggered for element with accessibilityViewIsModal prop', async () => {
+ await render();
expect(isHiddenFromAccessibility(screen.getByTestId('subject'))).toBe(false);
});
- test('is not triggered for child of element with accessibilityViewIsModal prop', () => {
- render(
+ test('is not triggered for child of element with accessibilityViewIsModal prop', async () => {
+ await render(
,
@@ -262,8 +262,8 @@ describe('isHiddenFromAccessibility', () => {
expect(isHiddenFromAccessibility(screen.getByTestId('subject'))).toBe(false);
});
- test('is not triggered for descendent of element with accessibilityViewIsModal prop', () => {
- render(
+ test('is not triggered for descendent of element with accessibilityViewIsModal prop', async () => {
+ await render(
@@ -279,15 +279,15 @@ describe('isHiddenFromAccessibility', () => {
expect(isInaccessible).toBe(isHiddenFromAccessibility);
});
- test('is not triggered for element with "aria-modal" prop', () => {
- render();
+ test('is not triggered for element with "aria-modal" prop', async () => {
+ await render();
expect(isHiddenFromAccessibility(screen.getByTestId('subject'))).toBe(false);
});
});
describe('isAccessibilityElement', () => {
- test('matches View component properly', () => {
- render(
+ test('matches View component properly', async () => {
+ await render(
@@ -299,8 +299,8 @@ describe('isAccessibilityElement', () => {
expect(isAccessibilityElement(screen.getByTestId('false'))).toBeFalsy();
});
- test('matches TextInput component properly', () => {
- render(
+ test('matches TextInput component properly', async () => {
+ await render(
@@ -312,8 +312,8 @@ describe('isAccessibilityElement', () => {
expect(isAccessibilityElement(screen.getByTestId('false'))).toBeFalsy();
});
- test('matches Text component properly', () => {
- render(
+ test('matches Text component properly', async () => {
+ await render(
Default
@@ -329,8 +329,8 @@ describe('isAccessibilityElement', () => {
expect(isAccessibilityElement(screen.getByTestId('false'))).toBeFalsy();
});
- test('matches Switch component properly', () => {
- render(
+ test('matches Switch component properly', async () => {
+ await render(
@@ -342,8 +342,8 @@ describe('isAccessibilityElement', () => {
expect(isAccessibilityElement(screen.getByTestId('false'))).toBeFalsy();
});
- test('matches Pressable component properly', () => {
- render(
+ test('matches Pressable component properly', async () => {
+ await render(
@@ -355,8 +355,8 @@ describe('isAccessibilityElement', () => {
expect(isAccessibilityElement(screen.getByTestId('false'))).toBeFalsy();
});
- test('matches TouchableOpacity component properly', () => {
- render(
+ test('matches TouchableOpacity component properly', async () => {
+ await render(
@@ -374,8 +374,8 @@ describe('isAccessibilityElement', () => {
});
describe('computeAriaLabel', () => {
- test('supports basic usage', () => {
- render(
+ test('supports basic usage', async () => {
+ await render(
@@ -395,8 +395,8 @@ describe('computeAriaLabel', () => {
expect(computeAriaLabel(screen.getByTestId('text-content'))).toBeUndefined();
});
- test('label priority', () => {
- render(
+ test('label priority', async () => {
+ await render(
@@ -410,8 +410,8 @@ describe('computeAriaLabel', () => {
});
describe('computeAriaDisabled', () => {
- test('supports basic usage', () => {
- render(
+ test('supports basic usage', async () => {
+ await render(
@@ -428,8 +428,8 @@ describe('computeAriaDisabled', () => {
expect(computeAriaDisabled(screen.getByTestId('disabled-false-by-state'))).toBe(false);
});
- test('supports TextInput', () => {
- render(
+ test('supports TextInput', async () => {
+ await render(
@@ -442,8 +442,8 @@ describe('computeAriaDisabled', () => {
expect(computeAriaDisabled(screen.getByTestId('editable-false'))).toBe(true);
});
- test('supports Button', () => {
- render(
+ test('supports Button', async () => {
+ await render(
Default Button
@@ -462,8 +462,8 @@ describe('computeAriaDisabled', () => {
expect(computeAriaDisabled(screen.getByTestId('disabled-false'))).toBe(false);
});
- test('supports Text', () => {
- render(
+ test('supports Text', async () => {
+ await render(
Default Text
Disabled Text
diff --git a/src/helpers/__tests__/component-tree.test.tsx b/src/helpers/__tests__/component-tree.test.tsx
index 8ec9715b2..18b8d2580 100644
--- a/src/helpers/__tests__/component-tree.test.tsx
+++ b/src/helpers/__tests__/component-tree.test.tsx
@@ -15,8 +15,8 @@ function MultipleHostChildren() {
}
describe('getHostSiblings()', () => {
- it('returns host siblings for host component', () => {
- render(
+ it('returns host siblings for host component', async () => {
+ await render(
@@ -39,8 +39,8 @@ describe('getHostSiblings()', () => {
});
describe('getContainerElement()', () => {
- it('returns container for mounted view', () => {
- render(
+ it('returns container for mounted view', async () => {
+ await render(
,
diff --git a/src/helpers/__tests__/format-element.test.tsx b/src/helpers/__tests__/format-element.test.tsx
index b27bde7a6..ffe8eaddc 100644
--- a/src/helpers/__tests__/format-element.test.tsx
+++ b/src/helpers/__tests__/format-element.test.tsx
@@ -4,8 +4,8 @@ import { Text, View } from 'react-native';
import { render, screen } from '../..';
import { formatElement } from '../format-element';
-test('formatElement', () => {
- render(
+test('formatElement', async () => {
+ await render(
Hello
diff --git a/src/helpers/__tests__/include-hidden-elements.test.tsx b/src/helpers/__tests__/include-hidden-elements.test.tsx
index cffa8d234..03c9ddd3a 100644
--- a/src/helpers/__tests__/include-hidden-elements.test.tsx
+++ b/src/helpers/__tests__/include-hidden-elements.test.tsx
@@ -3,36 +3,36 @@ import { View } from 'react-native';
import { configure, render, screen } from '../..';
-test('includeHiddenElements query option takes priority over hidden option and global config', () => {
+test('includeHiddenElements query option takes priority over hidden option and global config', async () => {
configure({ defaultHidden: true, defaultIncludeHiddenElements: true });
- render();
+ await render();
expect(screen.queryByTestId('view', { includeHiddenElements: false, hidden: true })).toBeFalsy();
});
-test('hidden option takes priority over global config when includeHiddenElements is not defined', () => {
+test('hidden option takes priority over global config when includeHiddenElements is not defined', async () => {
configure({ defaultHidden: true, defaultIncludeHiddenElements: true });
- render();
+ await render();
expect(screen.queryByTestId('view', { hidden: false })).toBeFalsy();
});
-test('global config defaultIncludeElements option takes priority over defaultHidden when set at the same time', () => {
+test('global config defaultIncludeElements option takes priority over defaultHidden when set at the same time', async () => {
configure({ defaultHidden: false, defaultIncludeHiddenElements: true });
- render();
+ await render();
expect(screen.getByTestId('view')).toBeTruthy();
});
-test('defaultHidden takes priority when it was set last', () => {
+test('defaultHidden takes priority when it was set last', async () => {
// also simulates the case when defaultIncludeHiddenElements is true by default in the config
configure({ defaultIncludeHiddenElements: true });
configure({ defaultHidden: false });
- render();
+ await render();
expect(screen.queryByTestId('view')).toBeFalsy();
});
-test('defaultIncludeHiddenElements takes priority when it was set last', () => {
+test('defaultIncludeHiddenElements takes priority when it was set last', async () => {
// also simulates the case when defaultHidden is true by default in the config
configure({ defaultHidden: true });
configure({ defaultIncludeHiddenElements: false });
- render();
+ await render();
expect(screen.queryByTestId('view')).toBeFalsy();
});
diff --git a/src/helpers/__tests__/text-content.test.tsx b/src/helpers/__tests__/text-content.test.tsx
index 42f4d3f1e..0c773f699 100644
--- a/src/helpers/__tests__/text-content.test.tsx
+++ b/src/helpers/__tests__/text-content.test.tsx
@@ -4,8 +4,8 @@ import { Text } from 'react-native';
import { render, screen } from '../..';
import { getTextContent } from '../text-content';
-test('getTextContent with simple content', () => {
- render(Hello world);
+test('getTextContent with simple content', async () => {
+ await render(Hello world);
expect(getTextContent(screen.root)).toBe('Hello world');
});
@@ -13,8 +13,8 @@ test('getTextContent with null element', () => {
expect(getTextContent(null)).toBe('');
});
-test('getTextContent with single nested content', () => {
- render(
+test('getTextContent with single nested content', async () => {
+ await render(
Hello world
,
@@ -22,8 +22,8 @@ test('getTextContent with single nested content', () => {
expect(getTextContent(screen.root)).toBe('Hello world');
});
-test('getTextContent with multiple nested content', () => {
- render(
+test('getTextContent with multiple nested content', async () => {
+ await render(
Hello world
,
@@ -31,8 +31,8 @@ test('getTextContent with multiple nested content', () => {
expect(getTextContent(screen.root)).toBe('Hello world');
});
-test('getTextContent with multiple number content', () => {
- render(
+test('getTextContent with multiple number content', async () => {
+ await render(
Hello world {100}
,
@@ -40,8 +40,8 @@ test('getTextContent with multiple number content', () => {
expect(getTextContent(screen.root)).toBe('Hello world 100');
});
-test('getTextContent with multiple boolean content', () => {
- render(
+test('getTextContent with multiple boolean content', async () => {
+ await render(
Hello{false} {true}world
,
diff --git a/src/helpers/__tests__/text-input.test.tsx b/src/helpers/__tests__/text-input.test.tsx
index 60534dbb8..b3a6f72cf 100644
--- a/src/helpers/__tests__/text-input.test.tsx
+++ b/src/helpers/__tests__/text-input.test.tsx
@@ -4,8 +4,8 @@ import { TextInput, View } from 'react-native';
import { render, screen } from '../..';
import { getTextInputValue, isEditableTextInput } from '../text-input';
-test('getTextInputValue basic test', () => {
- render(
+test('getTextInputValue basic test', async () => {
+ await render(
@@ -22,8 +22,8 @@ test('getTextInputValue basic test', () => {
);
});
-test('isEditableTextInput basic test', () => {
- render(
+test('isEditableTextInput basic test', async () => {
+ await render(
diff --git a/src/helpers/host-component-names.ts b/src/helpers/host-component-names.ts
index 7eea2e9c5..39dc31925 100644
--- a/src/helpers/host-component-names.ts
+++ b/src/helpers/host-component-names.ts
@@ -1,6 +1,6 @@
import type { HostElement } from 'universal-test-renderer';
-const HOST_TEXT_NAMES = ['Text', 'RCTText'];
+export const HOST_TEXT_NAMES = ['Text', 'RCTText'];
const HOST_TEXT_INPUT_NAMES = ['TextInput'];
const HOST_IMAGE_NAMES = ['Image'];
const HOST_SWITCH_NAMES = ['RCTSwitch'];
diff --git a/src/index.ts b/src/index.ts
index 6a2e4ec4e..01a8f8ee9 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,7 +2,7 @@ import './matchers/extend-expect';
import { getIsReactActEnvironment, setReactActEnvironment } from './act';
import { flushMicroTasks } from './flush-micro-tasks';
-import { cleanupAsync } from './pure';
+import { cleanup } from './pure';
if (!process?.env?.RNTL_SKIP_AUTO_CLEANUP) {
// If we're running in a test runner that supports afterEach
@@ -13,7 +13,7 @@ if (!process?.env?.RNTL_SKIP_AUTO_CLEANUP) {
if (typeof afterEach === 'function') {
afterEach(async () => {
await flushMicroTasks();
- await cleanupAsync();
+ await cleanup();
});
}
diff --git a/src/matchers/__tests__/to-be-busy.test.tsx b/src/matchers/__tests__/to-be-busy.test.tsx
index e6684c242..cdd00bc7d 100644
--- a/src/matchers/__tests__/to-be-busy.test.tsx
+++ b/src/matchers/__tests__/to-be-busy.test.tsx
@@ -3,8 +3,8 @@ import { View } from 'react-native';
import { render, screen } from '../..';
-test('toBeBusy() basic case', () => {
- render(
+test('toBeBusy() basic case', async () => {
+ await render(
<>
@@ -21,8 +21,8 @@ test('toBeBusy() basic case', () => {
expect(screen.getByTestId('default')).not.toBeBusy();
});
-test('toBeBusy() error messages', () => {
- render(
+test('toBeBusy() error messages', async () => {
+ await render(
<>
diff --git a/src/matchers/__tests__/to-be-checked.test.tsx b/src/matchers/__tests__/to-be-checked.test.tsx
index 2b0b3f22a..4020fa450 100644
--- a/src/matchers/__tests__/to-be-checked.test.tsx
+++ b/src/matchers/__tests__/to-be-checked.test.tsx
@@ -3,8 +3,8 @@ import { type AccessibilityRole, Switch, View } from 'react-native';
import { render, screen } from '../..';
-function renderViewsWithRole(role: AccessibilityRole) {
- render(
+async function renderViewsWithRole(role: AccessibilityRole) {
+ await render(
<>
{
- render(
+test('toBeCheck() with Switch', async () => {
+ await render(
<>
@@ -78,8 +78,8 @@ test('toBeCheck() with Switch', () => {
`);
});
-test('toBeCheck() with "checkbox" role', () => {
- renderViewsWithRole('checkbox');
+test('toBeCheck() with "checkbox" role', async () => {
+ await renderViewsWithRole('checkbox');
const checked = screen.getByTestId('checkbox-checked');
const unchecked = screen.getByTestId('checkbox-unchecked');
@@ -148,8 +148,8 @@ test('toBeCheck() with "checkbox" role', () => {
`);
});
-test('toBeCheck() with "radio" role', () => {
- renderViewsWithRole('radio');
+test('toBeCheck() with "radio" role', async () => {
+ await renderViewsWithRole('radio');
const checked = screen.getByTestId('radio-checked');
const unchecked = screen.getByTestId('radio-unchecked');
@@ -201,8 +201,8 @@ test('toBeCheck() with "radio" role', () => {
`);
});
-test('toBeCheck() with "switch" role', () => {
- renderViewsWithRole('switch');
+test('toBeCheck() with "switch" role', async () => {
+ await renderViewsWithRole('switch');
const checked = screen.getByTestId('switch-checked');
const unchecked = screen.getByTestId('switch-unchecked');
@@ -254,8 +254,8 @@ test('toBeCheck() with "switch" role', () => {
`);
});
-test('throws error for invalid role', () => {
- renderViewsWithRole('adjustable');
+test('throws error for invalid role', async () => {
+ await renderViewsWithRole('adjustable');
const checked = screen.getByTestId('adjustable-checked');
const unchecked = screen.getByTestId('adjustable-unchecked');
@@ -268,8 +268,8 @@ test('throws error for invalid role', () => {
);
});
-test('throws error for non-accessibility element', () => {
- render();
+test('throws error for non-accessibility element', async () => {
+ await render();
const view = screen.getByTestId('test');
expect(() => expect(view).toBeChecked()).toThrowErrorMatchingInlineSnapshot(
diff --git a/src/matchers/__tests__/to-be-disabled.test.tsx b/src/matchers/__tests__/to-be-disabled.test.tsx
index 9a3a6dedf..da7916665 100644
--- a/src/matchers/__tests__/to-be-disabled.test.tsx
+++ b/src/matchers/__tests__/to-be-disabled.test.tsx
@@ -13,8 +13,8 @@ import {
import { render, screen } from '../..';
-test('toBeDisabled()/toBeEnabled() supports basic case', () => {
- render(
+test('toBeDisabled()/toBeEnabled() supports basic case', async () => {
+ await render(
@@ -87,8 +87,8 @@ test('toBeDisabled()/toBeEnabled() supports basic case', () => {
`);
});
-test('toBeDisabled()/toBeEnabled() supports Pressable with "disabled" prop', () => {
- render(
+test('toBeDisabled()/toBeEnabled() supports Pressable with "disabled" prop', async () => {
+ await render(
Button
,
@@ -157,28 +157,31 @@ test.each([
['TouchableHighlight', TouchableHighlight],
['TouchableWithoutFeedback', TouchableWithoutFeedback],
['TouchableNativeFeedback', TouchableNativeFeedback],
-] as const)('toBeDisabled()/toBeEnabled() supports %s with "disabled" prop', (_, Component) => {
- render(
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore - JSX element type 'Component' does not have any construct or call signatures.
-
- Button
- ,
- );
+] as const)(
+ 'toBeDisabled()/toBeEnabled() supports %s with "disabled" prop',
+ async (_, Component) => {
+ await render(
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore - JSX element type 'Component' does not have any construct or call signatures.
+
+ Button
+ ,
+ );
- const touchable = screen.getByTestId('subject');
- expect(touchable).toBeDisabled();
- expect(touchable).not.toBeEnabled();
+ const touchable = screen.getByTestId('subject');
+ expect(touchable).toBeDisabled();
+ expect(touchable).not.toBeEnabled();
- const title = screen.getByText('Button');
- expect(title).toBeDisabled();
- expect(title).not.toBeEnabled();
+ const title = screen.getByText('Button');
+ expect(title).toBeDisabled();
+ expect(title).not.toBeEnabled();
- expect(() => expect(touchable).toBeEnabled()).toThrow();
- expect(() => expect(touchable).not.toBeDisabled()).toThrow();
- expect(() => expect(title).toBeEnabled()).toThrow();
- expect(() => expect(title).not.toBeDisabled()).toThrow();
-});
+ expect(() => expect(touchable).toBeEnabled()).toThrow();
+ expect(() => expect(touchable).not.toBeDisabled()).toThrow();
+ expect(() => expect(title).toBeEnabled()).toThrow();
+ expect(() => expect(title).not.toBeDisabled()).toThrow();
+ },
+);
test.each([
['View', View],
@@ -190,8 +193,8 @@ test.each([
['TouchableNativeFeedback', TouchableNativeFeedback],
] as const)(
'toBeDisabled()/toBeEnabled() supports %s with "aria-disabled" prop',
- (_, Component) => {
- render(
+ async (_, Component) => {
+ await render(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - JSX element type 'Component' does not have any construct or call signatures.
@@ -218,8 +221,8 @@ test.each([
['TouchableNativeFeedback', TouchableNativeFeedback],
] as const)(
'toBeDisabled()/toBeEnabled() supports %s with "accessibilityState.disabled" prop',
- (_, Component) => {
- render(
+ async (_, Component) => {
+ await render(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - JSX element type 'Component' does not have any construct or call signatures.
@@ -235,8 +238,8 @@ test.each([
},
);
-test('toBeDisabled()/toBeEnabled() supports "editable" prop on TextInput', () => {
- render(
+test('toBeDisabled()/toBeEnabled() supports "editable" prop on TextInput', async () => {
+ await render(
@@ -253,8 +256,8 @@ test('toBeDisabled()/toBeEnabled() supports "editable" prop on TextInput', () =>
expect(screen.getByTestId('disabled')).not.toBeEnabled();
});
-test('toBeDisabled()/toBeEnabled() supports "disabled" prop on Button', () => {
- render(
+test('toBeDisabled()/toBeEnabled() supports "disabled" prop on Button', async () => {
+ await render(
diff --git a/src/matchers/__tests__/to-be-empty-element.test.tsx b/src/matchers/__tests__/to-be-empty-element.test.tsx
index f38047db3..66942ab04 100644
--- a/src/matchers/__tests__/to-be-empty-element.test.tsx
+++ b/src/matchers/__tests__/to-be-empty-element.test.tsx
@@ -9,8 +9,8 @@ function DoNotRenderChildren({ children }: { children: React.ReactNode }) {
return null;
}
-test('toBeEmptyElement() base case', () => {
- render(
+test('toBeEmptyElement() base case', async () => {
+ await render(
,
@@ -37,8 +37,8 @@ test('toBeEmptyElement() base case', () => {
`);
});
-test('toBeEmptyElement() ignores composite-only children', () => {
- render(
+test('toBeEmptyElement() ignores composite-only children', async () => {
+ await render(
diff --git a/src/matchers/__tests__/to-be-expanded.test.tsx b/src/matchers/__tests__/to-be-expanded.test.tsx
index 489068e94..e24c77d5c 100644
--- a/src/matchers/__tests__/to-be-expanded.test.tsx
+++ b/src/matchers/__tests__/to-be-expanded.test.tsx
@@ -3,8 +3,8 @@ import { View } from 'react-native';
import { render, screen } from '../..';
-test('toBeExpanded() basic case', () => {
- render(
+test('toBeExpanded() basic case', async () => {
+ await render(
<>
@@ -21,8 +21,8 @@ test('toBeExpanded() basic case', () => {
expect(screen.getByTestId('default')).not.toBeExpanded();
});
-test('toBeExpanded() error messages', () => {
- render(
+test('toBeExpanded() error messages', async () => {
+ await render(
<>
@@ -95,8 +95,8 @@ test('toBeExpanded() error messages', () => {
`);
});
-test('toBeCollapsed() basic case', () => {
- render(
+test('toBeCollapsed() basic case', async () => {
+ await render(
<>
@@ -113,8 +113,8 @@ test('toBeCollapsed() basic case', () => {
expect(screen.getByTestId('default')).not.toBeCollapsed();
});
-test('toBeCollapsed() error messages', () => {
- render(
+test('toBeCollapsed() error messages', async () => {
+ await render(
<>
diff --git a/src/matchers/__tests__/to-be-on-the-screen.test.tsx b/src/matchers/__tests__/to-be-on-the-screen.test.tsx
index d5a9512c7..cc125c77e 100644
--- a/src/matchers/__tests__/to-be-on-the-screen.test.tsx
+++ b/src/matchers/__tests__/to-be-on-the-screen.test.tsx
@@ -3,8 +3,8 @@ import { Text, View } from 'react-native';
import { render, screen } from '../..';
-test('toBeOnTheScreen() example test', () => {
- render(
+test('toBeOnTheScreen() example test', async () => {
+ await render(
,
@@ -13,12 +13,12 @@ test('toBeOnTheScreen() example test', () => {
const child = screen.getByTestId('child');
expect(child).toBeOnTheScreen();
- screen.update();
+ await screen.update();
expect(child).not.toBeOnTheScreen();
});
-test('toBeOnTheScreen() on attached element', () => {
- render();
+test('toBeOnTheScreen() on attached element', async () => {
+ await render();
const element = screen.getByTestId('test');
expect(element).toBeOnTheScreen();
@@ -42,12 +42,12 @@ function ShowChildren({ show }: { show: boolean }) {
);
}
-test('toBeOnTheScreen() on detached element', () => {
- render();
+test('toBeOnTheScreen() on detached element', async () => {
+ await render();
const element = screen.getByTestId('text');
// Next line will unmount the element, yet `element` variable will still hold reference to it.
- screen.update();
+ await screen.update();
expect(element).toBeTruthy();
expect(element).not.toBeOnTheScreen();
diff --git a/src/matchers/__tests__/to-be-partially-checked.test.tsx b/src/matchers/__tests__/to-be-partially-checked.test.tsx
index 688bfb6ce..edb527094 100644
--- a/src/matchers/__tests__/to-be-partially-checked.test.tsx
+++ b/src/matchers/__tests__/to-be-partially-checked.test.tsx
@@ -29,8 +29,8 @@ function renderViewsWithRole(role: AccessibilityRole) {
);
}
-test('toBePartiallyCheck() with checkbox role', () => {
- renderViewsWithRole('checkbox');
+test('toBePartiallyCheck() with checkbox role', async () => {
+ await renderViewsWithRole('checkbox');
const checked = screen.getByTestId('checkbox-checked');
const unchecked = screen.getByTestId('checkbox-unchecked');
@@ -86,8 +86,8 @@ test('toBePartiallyCheck() with checkbox role', () => {
`);
});
-test('toBeCheck() with radio role', () => {
- renderViewsWithRole('radio');
+test('toBeCheck() with radio role', async () => {
+ await renderViewsWithRole('radio');
const checked = screen.getByTestId('radio-checked');
const mixed = screen.getByTestId('radio-mixed');
diff --git a/src/matchers/__tests__/to-be-selected.test.tsx b/src/matchers/__tests__/to-be-selected.test.tsx
index 3660bdf3a..107dc8f7a 100644
--- a/src/matchers/__tests__/to-be-selected.test.tsx
+++ b/src/matchers/__tests__/to-be-selected.test.tsx
@@ -3,8 +3,8 @@ import { View } from 'react-native';
import { render, screen } from '../..';
-test('toBeSelected() basic case', () => {
- render(
+test('toBeSelected() basic case', async () => {
+ await render(
<>
@@ -21,8 +21,8 @@ test('toBeSelected() basic case', () => {
expect(screen.getByTestId('default')).not.toBeSelected();
});
-test('toBeSelected() error messages', () => {
- render(
+test('toBeSelected() error messages', async () => {
+ await render(
<>
diff --git a/src/matchers/__tests__/to-be-visible.test.tsx b/src/matchers/__tests__/to-be-visible.test.tsx
index be4f82da6..fc39e855f 100644
--- a/src/matchers/__tests__/to-be-visible.test.tsx
+++ b/src/matchers/__tests__/to-be-visible.test.tsx
@@ -3,8 +3,8 @@ import { Modal, View } from 'react-native';
import { render, screen } from '../..';
-test('toBeVisible() on empty view', () => {
- render();
+test('toBeVisible() on empty view', async () => {
+ await render();
const view = screen.getByTestId('view');
expect(view).toBeVisible();
@@ -18,8 +18,8 @@ test('toBeVisible() on empty view', () => {
`);
});
-test('toBeVisible() on view with opacity', () => {
- render();
+test('toBeVisible() on view with opacity', async () => {
+ await render();
const view = screen.getByTestId('view');
expect(view).toBeVisible();
@@ -33,8 +33,8 @@ test('toBeVisible() on view with opacity', () => {
`);
});
-test('toBeVisible() on view with 0 opacity', () => {
- render();
+test('toBeVisible() on view with 0 opacity', async () => {
+ await render();
const view = screen.getByTestId('view');
expect(view).not.toBeVisible();
@@ -53,8 +53,8 @@ test('toBeVisible() on view with 0 opacity', () => {
`);
});
-test('toBeVisible() on view with display "none"', () => {
- render();
+test('toBeVisible() on view with display "none"', async () => {
+ await render();
const view = screen.getByTestId('view', { includeHiddenElements: true });
expect(view).not.toBeVisible();
@@ -73,8 +73,8 @@ test('toBeVisible() on view with display "none"', () => {
`);
});
-test('toBeVisible() on ancestor view with 0 opacity', () => {
- render(
+test('toBeVisible() on ancestor view with 0 opacity', async () => {
+ await render(
@@ -94,8 +94,8 @@ test('toBeVisible() on ancestor view with 0 opacity', () => {
`);
});
-test('toBeVisible() on ancestor view with display "none"', () => {
- render(
+test('toBeVisible() on ancestor view with display "none"', async () => {
+ await render(
@@ -115,8 +115,8 @@ test('toBeVisible() on ancestor view with display "none"', () => {
`);
});
-test('toBeVisible() on empty Modal', () => {
- render();
+test('toBeVisible() on empty Modal', async () => {
+ await render();
const modal = screen.getByTestId('modal');
expect(modal).toBeVisible();
@@ -130,8 +130,8 @@ test('toBeVisible() on empty Modal', () => {
`);
});
-test('toBeVisible() on view within Modal', () => {
- render(
+test('toBeVisible() on view within Modal', async () => {
+ await render(
@@ -141,8 +141,8 @@ test('toBeVisible() on view within Modal', () => {
expect(screen.getByTestId('view-within-modal')).toBeVisible();
});
-test('toBeVisible() on not visible Modal', () => {
- render(
+test('toBeVisible() on not visible Modal', async () => {
+ await render(
@@ -163,18 +163,18 @@ test('toBeVisible() on not visible Modal', () => {
`);
});
-test('toBeVisible() on inaccessible view', () => {
- render();
+test('toBeVisible() on inaccessible view', async () => {
+ await render();
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();
- screen.update();
+ await screen.update();
expect(test).toBeVisible();
});
-test('toBeVisible() on view within inaccessible view', () => {
- render(
+test('toBeVisible() on view within inaccessible view', async () => {
+ await render(
@@ -184,18 +184,18 @@ test('toBeVisible() on view within inaccessible view', () => {
expect(screen.getByTestId('test', { includeHiddenElements: true })).not.toBeVisible();
});
-test('toBeVisible() on inaccessible view (iOS)', () => {
- render();
+test('toBeVisible() on inaccessible view (iOS)', async () => {
+ await render();
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();
- screen.update();
+ await screen.update();
expect(test).toBeVisible();
});
-test('toBeVisible() on view within inaccessible view (iOS)', () => {
- render(
+test('toBeVisible() on view within inaccessible view (iOS)', async () => {
+ await render(
@@ -205,18 +205,18 @@ test('toBeVisible() on view within inaccessible view (iOS)', () => {
expect(screen.getByTestId('test', { includeHiddenElements: true })).not.toBeVisible();
});
-test('toBeVisible() on inaccessible view (Android)', () => {
- render();
+test('toBeVisible() on inaccessible view (Android)', async () => {
+ await render();
const test = screen.getByTestId('test', { includeHiddenElements: true });
expect(test).not.toBeVisible();
- screen.update();
+ await screen.update();
expect(test).toBeVisible();
});
-test('toBeVisible() on view within inaccessible view (Android)', () => {
- render(
+test('toBeVisible() on view within inaccessible view (Android)', async () => {
+ await render(
@@ -255,10 +255,10 @@ test('toBeVisible() on non-React elements', () => {
`);
});
-test('toBeVisible() does not throw on invalid style', () => {
+test('toBeVisible() does not throw on invalid style', async () => {
// @ts-expect-error: intentionally passing invalid style to
// trigger StyleSheet.flatten() returning undefined.
- render();
+ await render();
const view = screen.getByTestId('view');
expect(view).toBeVisible();
diff --git a/src/matchers/__tests__/to-contain-element.test.tsx b/src/matchers/__tests__/to-contain-element.test.tsx
index 9b6aa5a25..d041b8523 100644
--- a/src/matchers/__tests__/to-contain-element.test.tsx
+++ b/src/matchers/__tests__/to-contain-element.test.tsx
@@ -3,8 +3,8 @@ import { View } from 'react-native';
import { render, screen } from '../..';
-test('toContainElement() supports basic case', () => {
- render(
+test('toContainElement() supports basic case', async () => {
+ await render(
,
@@ -31,8 +31,8 @@ test('toContainElement() supports basic case', () => {
`);
});
-test('toContainElement() supports negative case', () => {
- render(
+test('toContainElement() supports negative case', async () => {
+ await render(
<>
@@ -61,8 +61,8 @@ test('toContainElement() supports negative case', () => {
`);
});
-test('toContainElement() handles null container', () => {
- render();
+test('toContainElement() handles null container', async () => {
+ await render();
const view = screen.getByTestId('view');
@@ -74,8 +74,8 @@ test('toContainElement() handles null container', () => {
`);
});
-test('toContainElement() handles null element', () => {
- render();
+test('toContainElement() handles null element', async () => {
+ await render();
const view = screen.getByTestId('view');
@@ -95,8 +95,8 @@ test('toContainElement() handles null element', () => {
`);
});
-test('toContainElement() handles non-element container', () => {
- render();
+test('toContainElement() handles non-element container', async () => {
+ await render();
const view = screen.getByTestId('view');
@@ -118,8 +118,8 @@ test('toContainElement() handles non-element container', () => {
`);
});
-test('toContainElement() handles non-element element', () => {
- render();
+test('toContainElement() handles non-element element', async () => {
+ await render();
const view = screen.getByTestId('view');
diff --git a/src/matchers/__tests__/to-have-accessibility-value.test.tsx b/src/matchers/__tests__/to-have-accessibility-value.test.tsx
index f700f2ada..5dab7cb9c 100644
--- a/src/matchers/__tests__/to-have-accessibility-value.test.tsx
+++ b/src/matchers/__tests__/to-have-accessibility-value.test.tsx
@@ -4,60 +4,60 @@ import { View } from 'react-native';
import { render, screen } from '../..';
describe('toHaveAccessibilityValue', () => {
- it('supports "accessibilityValue.min"', () => {
- render();
+ it('supports "accessibilityValue.min"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ min: 0 });
expect(screen.root).not.toHaveAccessibilityValue({ min: 1 });
});
- it('supports "accessibilityValue.max"', () => {
- render();
+ it('supports "accessibilityValue.max"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ max: 100 });
expect(screen.root).not.toHaveAccessibilityValue({ max: 99 });
});
- it('supports "accessibilityValue.now"', () => {
- render();
+ it('supports "accessibilityValue.now"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ now: 33 });
expect(screen.root).not.toHaveAccessibilityValue({ now: 34 });
});
- it('supports "accessibilityValue.text"', () => {
- render();
+ it('supports "accessibilityValue.text"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ text: 'Hello' });
expect(screen.root).toHaveAccessibilityValue({ text: /He/ });
expect(screen.root).not.toHaveAccessibilityValue({ text: 'Hi' });
expect(screen.root).not.toHaveAccessibilityValue({ text: /Hi/ });
});
- it('supports "aria-valuemin"', () => {
- render();
+ it('supports "aria-valuemin"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ min: 0 });
expect(screen.root).not.toHaveAccessibilityValue({ min: 1 });
});
- it('supports "aria-valuemax"', () => {
- render();
+ it('supports "aria-valuemax"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ max: 100 });
expect(screen.root).not.toHaveAccessibilityValue({ max: 99 });
});
- it('supports "aria-valuenow"', () => {
- render();
+ it('supports "aria-valuenow"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ now: 33 });
expect(screen.root).not.toHaveAccessibilityValue({ now: 34 });
});
- it('supports "aria-valuetext"', () => {
- render();
+ it('supports "aria-valuetext"', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ text: 'Hello' });
expect(screen.root).toHaveAccessibilityValue({ text: /He/ });
expect(screen.root).not.toHaveAccessibilityValue({ text: 'Hi' });
expect(screen.root).not.toHaveAccessibilityValue({ text: /Hi/ });
});
- it('supports multi-argument matching', () => {
- render();
+ it('supports multi-argument matching', async () => {
+ await render();
expect(screen.root).toHaveAccessibilityValue({ now: 5 });
expect(screen.root).toHaveAccessibilityValue({ now: 5, min: 1 });
@@ -83,8 +83,8 @@ describe('toHaveAccessibilityValue', () => {
});
});
- it('gives precedence to ARIA values', () => {
- render(
+ it('gives precedence to ARIA values', async () => {
+ await render(
{
expect(screen.root).not.toHaveAccessibilityValue({ text: 'Hi' });
});
- it('shows errors in expected format', () => {
- render(
+ it('shows errors in expected format', async () => {
+ await render(
{
`);
});
- it('shows errors in expected format with partial value', () => {
- render();
+ it('shows errors in expected format with partial value', async () => {
+ await render();
expect(() => expect(screen.root).toHaveAccessibilityValue({ min: 30 }))
.toThrowErrorMatchingInlineSnapshot(`
diff --git a/src/matchers/__tests__/to-have-accessible-name.test.tsx b/src/matchers/__tests__/to-have-accessible-name.test.tsx
index 1f433d857..406a8074c 100644
--- a/src/matchers/__tests__/to-have-accessible-name.test.tsx
+++ b/src/matchers/__tests__/to-have-accessible-name.test.tsx
@@ -3,22 +3,22 @@ import { Image, Text, TextInput, View } from 'react-native';
import { render, screen } from '../..';
-test('toHaveAccessibleName() handles view with "accessibilityLabel" prop', () => {
- render();
+test('toHaveAccessibleName() handles view with "accessibilityLabel" prop', async () => {
+ await render();
const element = screen.getByTestId('view');
expect(element).toHaveAccessibleName('Test label');
expect(element).not.toHaveAccessibleName('Other label');
});
-test('toHaveAccessibleName() handles view with "aria-label" prop', () => {
- render();
+test('toHaveAccessibleName() handles view with "aria-label" prop', async () => {
+ await render();
const element = screen.getByTestId('view');
expect(element).toHaveAccessibleName('Test label');
expect(element).not.toHaveAccessibleName('Other label');
});
-test('toHaveAccessibleName() handles view with "accessibilityLabelledBy" prop', () => {
- render(
+test('toHaveAccessibleName() handles view with "accessibilityLabelledBy" prop', async () => {
+ await render(
External label
@@ -30,8 +30,8 @@ test('toHaveAccessibleName() handles view with "accessibilityLabelledBy" prop',
expect(element).not.toHaveAccessibleName('Other label');
});
-test('toHaveAccessibleName() handles nested "accessibilityLabelledBy"', () => {
- render(
+test('toHaveAccessibleName() handles nested "accessibilityLabelledBy"', async () => {
+ await render(
<>
External label
@@ -45,8 +45,8 @@ test('toHaveAccessibleName() handles nested "accessibilityLabelledBy"', () => {
expect(element).not.toHaveAccessibleName('Other label');
});
-test('toHaveAccessibleName() handles view with nested "accessibilityLabelledBy" with no text', () => {
- render(
+test('toHaveAccessibleName() handles view with nested "accessibilityLabelledBy" with no text', async () => {
+ await render(
<>
@@ -59,8 +59,8 @@ test('toHaveAccessibleName() handles view with nested "accessibilityLabelledBy"
expect(element).not.toHaveAccessibleName();
});
-test('toHaveAccessibleName() handles view with "aria-labelledby" prop', () => {
- render(
+test('toHaveAccessibleName() handles view with "aria-labelledby" prop', async () => {
+ await render(
External label
@@ -72,24 +72,24 @@ test('toHaveAccessibleName() handles view with "aria-labelledby" prop', () => {
expect(element).not.toHaveAccessibleName('Other label');
});
-test('toHaveAccessibleName() handles Text with text content', () => {
- render(Text);
+test('toHaveAccessibleName() handles Text with text content', async () => {
+ await render(Text);
const element = screen.getByTestId('view');
expect(element).toHaveAccessibleName('Text');
expect(element).not.toHaveAccessibleName('Other text');
});
-test('toHaveAccessibleName() handles Image with "alt" prop', () => {
- render();
+test('toHaveAccessibleName() handles Image with "alt" prop', async () => {
+ await render();
const element = screen.getByTestId('image');
expect(element).toHaveAccessibleName('Test image');
expect(element).not.toHaveAccessibleName('Other text');
});
-test('toHaveAccessibleName() supports calling without expected name', () => {
- render();
+test('toHaveAccessibleName() supports calling without expected name', async () => {
+ await render();
const element = screen.getByTestId('view');
expect(element).toHaveAccessibleName();
@@ -103,8 +103,8 @@ test('toHaveAccessibleName() supports calling without expected name', () => {
`);
});
-test('toHaveAccessibleName() handles a view without name when called without expected name', () => {
- render();
+test('toHaveAccessibleName() handles a view without name when called without expected name', async () => {
+ await render();
const element = screen.getByTestId('view');
expect(element).not.toHaveAccessibleName();
diff --git a/src/matchers/__tests__/to-have-display-value.test.tsx b/src/matchers/__tests__/to-have-display-value.test.tsx
index 32b9f6245..e4d4cc7c4 100644
--- a/src/matchers/__tests__/to-have-display-value.test.tsx
+++ b/src/matchers/__tests__/to-have-display-value.test.tsx
@@ -3,15 +3,15 @@ import { TextInput, View } from 'react-native';
import { render, screen } from '../..';
-test('toHaveDisplayValue() example test', () => {
- render();
+test('toHaveDisplayValue() example test', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).toHaveDisplayValue('test');
});
-test('toHaveDisplayValue() on matching display value', () => {
- render();
+test('toHaveDisplayValue() on matching display value', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).toHaveDisplayValue('test');
@@ -27,8 +27,8 @@ test('toHaveDisplayValue() on matching display value', () => {
`);
});
-test('toHaveDisplayValue() on non-matching display value', () => {
- render();
+test('toHaveDisplayValue() on non-matching display value', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).not.toHaveDisplayValue('non-test');
@@ -44,8 +44,8 @@ test('toHaveDisplayValue() on non-matching display value', () => {
`);
});
-test("toHaveDisplayValue() on non-'TextInput' elements", () => {
- render();
+test("toHaveDisplayValue() on non-'TextInput' elements", async () => {
+ await render();
const view = screen.getByTestId('view');
expect(() => expect(view).toHaveDisplayValue('test')).toThrowErrorMatchingInlineSnapshot(
@@ -53,8 +53,8 @@ test("toHaveDisplayValue() on non-'TextInput' elements", () => {
);
});
-test('toHaveDisplayValue() performing partial match', () => {
- render();
+test('toHaveDisplayValue() performing partial match', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).toHaveDisplayValue('Hello World');
@@ -68,15 +68,15 @@ test('toHaveDisplayValue() performing partial match', () => {
expect(textInput).toHaveDisplayValue('world', { exact: false });
});
-test('toHaveDisplayValue() uses defaultValue', () => {
- render();
+test('toHaveDisplayValue() uses defaultValue', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).toHaveDisplayValue('default');
});
-test('toHaveDisplayValue() prioritizes value over defaultValue', () => {
- render();
+test('toHaveDisplayValue() prioritizes value over defaultValue', async () => {
+ await render();
const textInput = screen.getByTestId('text-input');
expect(textInput).toHaveDisplayValue('value');
diff --git a/src/matchers/__tests__/to-have-prop.test.tsx b/src/matchers/__tests__/to-have-prop.test.tsx
index a6c0fb3ee..da1ddd8de 100644
--- a/src/matchers/__tests__/to-have-prop.test.tsx
+++ b/src/matchers/__tests__/to-have-prop.test.tsx
@@ -3,8 +3,8 @@ import { Text, TextInput, View } from 'react-native';
import { render, screen } from '../..';
-test('toHaveProp() basic case', () => {
- render(
+test('toHaveProp() basic case', async () => {
+ await render(
Hello
@@ -30,8 +30,8 @@ test('toHaveProp() basic case', () => {
expect(input).not.toHaveProp('editable', false);
});
-test('toHaveProp() error messages', () => {
- render();
+test('toHaveProp() error messages', async () => {
+ await render();
const view = screen.getByTestId('view');
diff --git a/src/matchers/__tests__/to-have-style.test.tsx b/src/matchers/__tests__/to-have-style.test.tsx
index 83af29c22..436799bcf 100644
--- a/src/matchers/__tests__/to-have-style.test.tsx
+++ b/src/matchers/__tests__/to-have-style.test.tsx
@@ -7,8 +7,8 @@ const styles = StyleSheet.create({
container: { borderBottomColor: 'white' },
});
-test('toHaveStyle() handles basic cases', () => {
- render(
+test('toHaveStyle() handles basic cases', async () => {
+ await render(
{
});
});
-test('toHaveStyle error messages', () => {
- render(
+test('toHaveStyle error messages', async () => {
+ await render(
{
`);
});
-test('toHaveStyle() supports missing "style" prop', () => {
- render();
+test('toHaveStyle() supports missing "style" prop', async () => {
+ await render();
const view = screen.getByTestId('view');
expect(view).not.toHaveStyle({ fontWeight: 'bold' });
});
-test('toHaveStyle() supports undefined "transform" style', () => {
- render(
+test('toHaveStyle() supports undefined "transform" style', async () => {
+ await render(
{
`);
});
-test('toHaveStyle() supports Pressable with function "style" prop', () => {
- render( ({ backgroundColor: 'blue' })} />);
+test('toHaveStyle() supports Pressable with function "style" prop', async () => {
+ await render( ({ backgroundColor: 'blue' })} />);
expect(screen.getByTestId('view')).toHaveStyle({ backgroundColor: 'blue' });
});
-test('toHaveStyle() to differentiate number vs string values', () => {
- const screen = render(
+test('toHaveStyle() to differentiate number vs string values', async () => {
+ const screen = await render(
{
- render(
+test('toHaveTextContent() example test', async () => {
+ await render(
- Hello World
+ Hello
+
+ World
,
);
@@ -15,8 +17,8 @@ test('toHaveTextContent() example test', () => {
expect(view).not.toHaveTextContent('Hello there');
});
-test('toHaveTextContent() handles positive test cases', () => {
- render(Hello World);
+test('toHaveTextContent() handles positive test cases', async () => {
+ await render(Hello World);
const text = screen.getByTestId('text');
expect(text).toHaveTextContent('Hello World');
@@ -24,8 +26,8 @@ test('toHaveTextContent() handles positive test cases', () => {
expect(text).toHaveTextContent(/Hello World/);
});
-test('toHaveTextContent() does exact match by default', () => {
- render(Hello World);
+test('toHaveTextContent() does exact match by default', async () => {
+ await render(Hello World);
const text = screen.getByTestId('text');
expect(text).toHaveTextContent('Hello World');
@@ -33,8 +35,8 @@ test('toHaveTextContent() does exact match by default', () => {
expect(text).not.toHaveTextContent('World');
});
-test('toHaveTextContent() handles nested text', () => {
- render(
+test('toHaveTextContent() handles nested text', async () => {
+ await render(
Hello React
,
@@ -44,8 +46,8 @@ test('toHaveTextContent() handles nested text', () => {
expect(text).toHaveTextContent('Hello React');
});
-test('toHaveTextContent() negative test cases', () => {
- render(Hello World);
+test('toHaveTextContent() negative test cases', async () => {
+ await render(Hello World);
const text = screen.getByTestId('text');
expect(text).not.toHaveTextContent(/Hello React/);
diff --git a/src/matchers/__tests__/utils.test.tsx b/src/matchers/__tests__/utils.test.tsx
index def0c84c8..3fffe19e6 100644
--- a/src/matchers/__tests__/utils.test.tsx
+++ b/src/matchers/__tests__/utils.test.tsx
@@ -8,8 +8,8 @@ function fakeMatcher() {
return { pass: true, message: () => 'fake' };
}
-test('checkHostElement allows host element', () => {
- render();
+test('checkHostElement allows host element', async () => {
+ await render();
expect(() => {
// @ts-expect-error: intentionally passing wrong element shape
diff --git a/src/pure.ts b/src/pure.ts
index f36b153e6..9ea2b5419 100644
--- a/src/pure.ts
+++ b/src/pure.ts
@@ -1,26 +1,21 @@
export { default as act } from './act';
-export { default as cleanup, cleanupAsync } from './cleanup';
-export { fireEvent, deprecated_fireEventSync } from './fire-event';
-export { default as render } from './render';
-export { default as renderAsync } from './render-async';
-export { default as waitFor } from './wait-for';
-export { default as waitForElementToBeRemoved } from './wait-for-element-to-be-removed';
+export { cleanup } from './cleanup';
+export { fireEvent, unsafe_fireEventSync } from './fire-event';
+export { render } from './render';
+export { unsafe_renderSync } from './unsafe-render-sync';
+export { waitFor } from './wait-for';
+export { waitForElementToBeRemoved } from './wait-for-element-to-be-removed';
export { within, getQueriesForElement } from './within';
export { configure, resetToDefaults } from './config';
export { isHiddenFromAccessibility, isInaccessible } from './helpers/accessibility';
export { getDefaultNormalizer } from './matches';
-export { renderHook, deprecated_renderHookSync } from './render-hook';
+export { renderHook, unsafe_renderHookSync } from './render-hook';
export { screen } from './screen';
export { userEvent } from './user-event';
-export type {
- RenderOptions,
- RenderResult,
- RenderResult as RenderAPI,
- DebugFunction,
-} from './render';
-export type { RenderAsyncOptions, RenderAsyncResult } from './render-async';
+export type { RenderOptions, RenderResult, DebugFunction } from './render';
+export type { RenderSyncOptions, RenderSyncResult } from './unsafe-render-sync';
export type { RenderHookOptions, RenderHookResult, RenderHookSyncResult } from './render-hook';
export type { Config } from './config';
export type { UserEventConfig } from './user-event';
diff --git a/src/queries/__tests__/display-value.test.tsx b/src/queries/__tests__/display-value.test.tsx
index 97d51f0cf..af36452c8 100644
--- a/src/queries/__tests__/display-value.test.tsx
+++ b/src/queries/__tests__/display-value.test.tsx
@@ -28,8 +28,8 @@ const Banana = () => (
);
-test('getByDisplayValue, queryByDisplayValue', () => {
- render();
+test('getByDisplayValue, queryByDisplayValue', async () => {
+ await render();
const input = screen.getByDisplayValue(/custom/i);
expect(input).toHaveDisplayValue(INPUT_FRESHNESS);
@@ -47,8 +47,8 @@ test('getByDisplayValue, queryByDisplayValue', () => {
);
});
-test('getByDisplayValue, queryByDisplayValue get element by default value only when value is undefined', () => {
- render();
+test('getByDisplayValue, queryByDisplayValue get element by default value only when value is undefined', async () => {
+ await render();
expect(() => screen.getByDisplayValue(DEFAULT_INPUT_CHEF)).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with displayValue: What did you inspect?
@@ -105,8 +105,8 @@ test('getByDisplayValue, queryByDisplayValue get element by default value only w
expect(screen.queryByDisplayValue(DEFAULT_INPUT_CUSTOMER)).toBeTruthy();
});
-test('getAllByDisplayValue, queryAllByDisplayValue', () => {
- render();
+test('getAllByDisplayValue, queryAllByDisplayValue', async () => {
+ await render();
const inputs = screen.getAllByDisplayValue(/fresh/i);
expect(inputs).toHaveLength(2);
@@ -120,7 +120,7 @@ test('getAllByDisplayValue, queryAllByDisplayValue', () => {
test('findBy queries work asynchronously', async () => {
const options = { timeout: 10 }; // Short timeout so that this test runs quickly
- render();
+ await render();
await expect(screen.findByDisplayValue('Display Value', {}, options)).rejects.toBeTruthy();
await expect(screen.findAllByDisplayValue('Display Value', {}, options)).rejects.toBeTruthy();
@@ -139,8 +139,8 @@ test('findBy queries work asynchronously', async () => {
await expect(screen.findAllByDisplayValue('Display Value')).resolves.toHaveLength(1);
}, 20000);
-test('byDisplayValue queries support hidden option', () => {
- render();
+test('byDisplayValue queries support hidden option', async () => {
+ await render();
expect(screen.getByDisplayValue('hidden', { includeHiddenElements: true })).toBeTruthy();
@@ -161,14 +161,14 @@ test('byDisplayValue queries support hidden option', () => {
`);
});
-test('byDisplayValue should return host component', () => {
- render();
+test('byDisplayValue should return host component', async () => {
+ await render();
expect(screen.getByDisplayValue('value').type).toBe('TextInput');
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByDisplayValue('2')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with displayValue: 2
@@ -204,7 +204,7 @@ test('error message renders the element tree, preserving only helpful props', as
});
test('supports unmanaged TextInput element', async () => {
- render();
+ await render();
const input = screen.getByDisplayValue('');
expect(input).toHaveDisplayValue('');
diff --git a/src/queries/__tests__/find-by.test.tsx b/src/queries/__tests__/find-by.test.tsx
index 4b9c9d602..e5e86b279 100644
--- a/src/queries/__tests__/find-by.test.tsx
+++ b/src/queries/__tests__/find-by.test.tsx
@@ -5,7 +5,7 @@ import { render, screen } from '../..';
import { clearRenderResult } from '../../screen';
test('findByTestId detects screen being detached', async () => {
- render();
+ await render();
const promise = screen.findByTestId('not-exists', {}, { timeout: 50 });
diff --git a/src/queries/__tests__/hint-text.test.tsx b/src/queries/__tests__/hint-text.test.tsx
index ad8f9f743..9f2e715c7 100644
--- a/src/queries/__tests__/hint-text.test.tsx
+++ b/src/queries/__tests__/hint-text.test.tsx
@@ -34,7 +34,7 @@ const Section = () => (
);
test('getByA11yHint, queryByA11yHint, findByA11yHint', async () => {
- render();
+ await render();
expect(screen.getByA11yHint(BUTTON_HINT).props.accessibilityHint).toEqual(BUTTON_HINT);
const button = screen.queryByA11yHint(BUTTON_HINT);
@@ -64,7 +64,7 @@ test('getByA11yHint, queryByA11yHint, findByA11yHint', async () => {
});
test('getAllByA11yHint, queryAllByA11yHint, findAllByA11yHint', async () => {
- render();
+ await render();
expect(screen.getAllByA11yHint(TEXT_HINT)).toHaveLength(2);
expect(screen.queryAllByA11yHint(TEXT_HINT)).toHaveLength(2);
@@ -80,8 +80,8 @@ test('getAllByA11yHint, queryAllByA11yHint, findAllByA11yHint', async () => {
);
});
-test('getByHintText, getByHintText', () => {
- render(
+test('getByHintText, getByHintText', async () => {
+ await render(
@@ -91,8 +91,8 @@ test('getByHintText, getByHintText', () => {
expect(screen.getAllByHintText('test', { exact: false })).toHaveLength(2);
});
-test('getByHintText, getByHintText and exact = true', () => {
- render(
+test('getByHintText, getByHintText and exact = true', async () => {
+ await render(
@@ -102,8 +102,8 @@ test('getByHintText, getByHintText and exact = true', () => {
expect(screen.getAllByHintText('test', { exact: true })).toHaveLength(1);
});
-test('byHintText queries support hidden option', () => {
- render(
+test('byHintText queries support hidden option', async () => {
+ await render(
Hidden from accessiblity
,
@@ -131,7 +131,7 @@ test('byHintText queries support hidden option', () => {
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByHintText('FOO')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with accessibility hint: FOO
diff --git a/src/queries/__tests__/label-text.test.tsx b/src/queries/__tests__/label-text.test.tsx
index 04cb4967a..bc86fbe46 100644
--- a/src/queries/__tests__/label-text.test.tsx
+++ b/src/queries/__tests__/label-text.test.tsx
@@ -41,7 +41,7 @@ const Section = () => (
);
test('getByLabelText, queryByLabelText, findByLabelText', async () => {
- render();
+ await render();
expect(screen.getByLabelText(BUTTON_LABEL).props.accessibilityLabel).toEqual(BUTTON_LABEL);
const button = screen.queryByLabelText(/button/);
@@ -71,7 +71,7 @@ test('getByLabelText, queryByLabelText, findByLabelText', async () => {
});
test('getAllByLabelText, queryAllByLabelText, findAllByLabelText', async () => {
- render();
+ await render();
expect(screen.getAllByLabelText(TEXT_LABEL)).toHaveLength(2);
expect(screen.queryAllByLabelText(/cool/)).toHaveLength(3);
@@ -88,7 +88,7 @@ test('getAllByLabelText, queryAllByLabelText, findAllByLabelText', async () => {
});
test('getAllByLabelText, queryAllByLabelText, findAllByLabelText with exact as false', async () => {
- render();
+ await render();
expect(screen.getAllByLabelText(TEXT_LABEL, { exact: false })).toHaveLength(2);
expect(screen.queryAllByLabelText(/cool/, { exact: false })).toHaveLength(3);
@@ -116,7 +116,7 @@ describe('findBy options deprecations', () => {
test('findByText queries warn on deprecated use of WaitForOptions', async () => {
const options = { timeout: 10 };
// mock implementation to avoid warning in the test suite
- render();
+ await render();
await expect(screen.findByLabelText('Some Text', options)).rejects.toBeTruthy();
setTimeout(() => screen.rerender(), 20);
@@ -126,8 +126,8 @@ describe('findBy options deprecations', () => {
}, 20000);
});
-test('byLabelText queries support hidden option', () => {
- render(
+test('byLabelText queries support hidden option', async () => {
+ await render(
Hidden from accessibility
,
@@ -154,8 +154,8 @@ test('byLabelText queries support hidden option', () => {
`);
});
-test('getByLabelText supports aria-label', () => {
- render(
+test('getByLabelText supports aria-label', async () => {
+ await render(
<>
@@ -170,8 +170,8 @@ test('getByLabelText supports aria-label', () => {
expect(screen.getByLabelText('text-input-label')).toBe(screen.getByTestId('text-input'));
});
-test('getByLabelText supports accessibilityLabelledBy', () => {
- render(
+test('getByLabelText supports accessibilityLabelledBy', async () => {
+ await render(
<>
Label for input
@@ -182,8 +182,8 @@ test('getByLabelText supports accessibilityLabelledBy', () => {
expect(screen.getByLabelText(/input/)).toBe(screen.getByTestId('textInput'));
});
-test('getByLabelText supports nested accessibilityLabelledBy', () => {
- render(
+test('getByLabelText supports nested accessibilityLabelledBy', async () => {
+ await render(
<>
Label for input
@@ -196,8 +196,8 @@ test('getByLabelText supports nested accessibilityLabelledBy', () => {
expect(screen.getByLabelText(/input/)).toBe(screen.getByTestId('textInput'));
});
-test('getByLabelText supports aria-labelledby', () => {
- render(
+test('getByLabelText supports aria-labelledby', async () => {
+ await render(
<>
Text Label
@@ -208,8 +208,8 @@ test('getByLabelText supports aria-labelledby', () => {
expect(screen.getByLabelText(/text label/i)).toBe(screen.getByTestId('text-input'));
});
-test('getByLabelText supports nested aria-labelledby', () => {
- render(
+test('getByLabelText supports nested aria-labelledby', async () => {
+ await render(
<>
Nested Text Label
@@ -222,8 +222,8 @@ test('getByLabelText supports nested aria-labelledby', () => {
expect(screen.getByLabelText(/nested text label/i)).toBe(screen.getByTestId('text-input'));
});
-test('getByLabelText supports "Image"" with "alt" prop', () => {
- render(
+test('getByLabelText supports "Image"" with "alt" prop', async () => {
+ await render(
<>
>,
@@ -235,7 +235,7 @@ test('getByLabelText supports "Image"" with "alt" prop', () => {
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByLabelText('FOO')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with accessibility label: FOO
diff --git a/src/queries/__tests__/make-queries.test.tsx b/src/queries/__tests__/make-queries.test.tsx
index b00e800ca..60e1d3c65 100644
--- a/src/queries/__tests__/make-queries.test.tsx
+++ b/src/queries/__tests__/make-queries.test.tsx
@@ -4,8 +4,8 @@ import { Text, TextInput, View } from 'react-native';
import { render, screen } from '../..';
describe('printing element tree', () => {
- test('includes element tree on error with less-helpful props stripped', () => {
- render( null}>Some text);
+ test('includes element tree on error with less-helpful props stripped', async () => {
+ await render( null}>Some text);
expect(() => screen.getByText(/foo/)).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with text: /foo/
@@ -16,8 +16,8 @@ describe('printing element tree', () => {
`);
});
- test('prints helpful props but not others', () => {
- render(
+ test('prints helpful props but not others', async () => {
+ await render(
{
});
test('prints tree and filters props with getBy, getAllBy, findBy, findAllBy', async () => {
- render();
+ await render();
expect(() => screen.getByText(/foo/)).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with text: /foo/
@@ -126,7 +126,7 @@ describe('printing element tree', () => {
});
test('only appends element tree on last failure with findBy', async () => {
- render();
+ await render();
jest.spyOn(screen, 'toJSON');
@@ -136,7 +136,7 @@ describe('printing element tree', () => {
});
test('onTimeout with findBy receives error without element tree', async () => {
- render();
+ await render();
const onTimeout = jest.fn((_: Error) => new Error('Replacement error'));
@@ -152,7 +152,7 @@ describe('printing element tree', () => {
});
test('onTimeout with findAllBy receives error without element tree', async () => {
- render();
+ await render();
const onTimeout = jest.fn((_: Error) => new Error('Replacement error'));
@@ -167,8 +167,8 @@ describe('printing element tree', () => {
);
});
- test('does not strip display: none from "style" prop, but does strip other styles', () => {
- render(
+ test('does not strip display: none from "style" prop, but does strip other styles', async () => {
+ await render(
{
`);
});
- test('strips undefined values from accessibilityState', () => {
- render(
+ test('strips undefined values from accessibilityState', async () => {
+ await render(
,
@@ -221,8 +221,8 @@ describe('printing element tree', () => {
`);
});
- test('strips undefined values from accessibilityValue', () => {
- render(
+ test('strips undefined values from accessibilityValue', async () => {
+ await render(
,
@@ -243,8 +243,8 @@ describe('printing element tree', () => {
`);
});
- test('does not render element tree when toJSON() returns null', () => {
- render();
+ test('does not render element tree when toJSON() returns null', async () => {
+ await render();
jest.spyOn(screen, 'toJSON').mockImplementation(() => null);
expect(() => screen.getByText(/foo/)).toThrowErrorMatchingInlineSnapshot(
diff --git a/src/queries/__tests__/placeholder-text.test.tsx b/src/queries/__tests__/placeholder-text.test.tsx
index 47309b45f..94c11795f 100644
--- a/src/queries/__tests__/placeholder-text.test.tsx
+++ b/src/queries/__tests__/placeholder-text.test.tsx
@@ -25,8 +25,8 @@ const Banana = () => (
);
-test('getByPlaceholderText, queryByPlaceholderText', () => {
- render();
+test('getByPlaceholderText, queryByPlaceholderText', async () => {
+ await render();
const input = screen.getByPlaceholderText(/custom/i);
expect(input.props.placeholder).toBe(PLACEHOLDER_FRESHNESS);
@@ -45,8 +45,8 @@ test('getByPlaceholderText, queryByPlaceholderText', () => {
);
});
-test('getAllByPlaceholderText, queryAllByPlaceholderText', () => {
- render();
+test('getAllByPlaceholderText, queryAllByPlaceholderText', async () => {
+ await render();
const inputs = screen.getAllByPlaceholderText(/fresh/i);
expect(inputs).toHaveLength(2);
@@ -58,8 +58,8 @@ test('getAllByPlaceholderText, queryAllByPlaceholderText', () => {
expect(screen.queryAllByPlaceholderText('no placeholder')).toHaveLength(0);
});
-test('byPlaceholderText queries support hidden option', () => {
- render();
+test('byPlaceholderText queries support hidden option', async () => {
+ await render();
expect(screen.getByPlaceholderText('hidden', { includeHiddenElements: true })).toBeTruthy();
@@ -80,14 +80,14 @@ test('byPlaceholderText queries support hidden option', () => {
`);
});
-test('byPlaceHolderText should return host component', () => {
- render();
+test('byPlaceHolderText should return host component', async () => {
+ await render();
expect(screen.getByPlaceholderText('placeholder').type).toBe('TextInput');
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByPlaceholderText('FOO')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with placeholder: FOO
diff --git a/src/queries/__tests__/role-value.test.tsx b/src/queries/__tests__/role-value.test.tsx
index e327ae8b3..c2a1bb5ab 100644
--- a/src/queries/__tests__/role-value.test.tsx
+++ b/src/queries/__tests__/role-value.test.tsx
@@ -4,8 +4,8 @@ import { Text, View } from 'react-native';
import { render, screen } from '../..';
describe('accessibility value', () => {
- test('matches using all value props', () => {
- render(
+ test('matches using all value props', async () => {
+ await render(
{
).toBeFalsy();
});
- test('matches using single value', () => {
- render(
+ test('matches using single value', async () => {
+ await render(
{
expect(screen.queryByRole('adjustable', { value: { text: /no/ } })).toBeFalsy();
});
- test('matches using single value and other options', () => {
- render(
+ test('matches using single value and other options', async () => {
+ await render(
{
`);
});
- test('supports "aria-valuemax" prop', () => {
- render();
+ test('supports "aria-valuemax" prop', async () => {
+ await render();
expect(screen.getByRole('slider', { value: { max: 10 } })).toBeTruthy();
expect(screen.queryByRole('slider', { value: { max: 20 } })).toBeNull();
});
- test('supports "aria-valuemin" prop', () => {
- render();
+ test('supports "aria-valuemin" prop', async () => {
+ await render();
expect(screen.getByRole('slider', { value: { min: 20 } })).toBeTruthy();
expect(screen.queryByRole('slider', { value: { min: 30 } })).toBeNull();
});
- test('supports "aria-valuenow" prop', () => {
- render();
+ test('supports "aria-valuenow" prop', async () => {
+ await render();
expect(screen.getByRole('slider', { value: { now: 30 } })).toBeTruthy();
expect(screen.queryByRole('slider', { value: { now: 10 } })).toBeNull();
});
- test('supports "aria-valuetext" prop', () => {
- render();
+ test('supports "aria-valuetext" prop', async () => {
+ await render();
expect(screen.getByRole('slider', { value: { text: 'Hello World' } })).toBeTruthy();
expect(screen.getByRole('slider', { value: { text: /hello/i } })).toBeTruthy();
expect(screen.queryByRole('slider', { value: { text: 'Hello' } })).toBeNull();
expect(screen.queryByRole('slider', { value: { text: /salut/i } })).toBeNull();
});
- test('supports multiple "aria-value*" props', () => {
- render(
+ test('supports multiple "aria-value*" props', async () => {
+ await render(
,
);
expect(screen.getByRole('slider', { value: { now: 50, min: 0, max: 100 } })).toBeTruthy();
diff --git a/src/queries/__tests__/role.test.tsx b/src/queries/__tests__/role.test.tsx
index 6d0cbe641..7a112b5bd 100644
--- a/src/queries/__tests__/role.test.tsx
+++ b/src/queries/__tests__/role.test.tsx
@@ -44,7 +44,7 @@ const Section = () => (
);
test('getByRole, queryByRole, findByRole', async () => {
- render();
+ await render();
expect(screen.getByRole('button').props.accessibilityRole).toEqual('button');
const button = screen.queryByRole(/button/);
@@ -68,7 +68,7 @@ test('getByRole, queryByRole, findByRole', async () => {
});
test('getAllByRole, queryAllByRole, findAllByRole', async () => {
- render();
+ await render();
expect(screen.getAllByRole('link')).toHaveLength(2);
expect(screen.queryAllByRole(/ink/)).toHaveLength(2);
@@ -84,8 +84,8 @@ test('getAllByRole, queryAllByRole, findAllByRole', async () => {
);
});
-test('supports role prop', () => {
- render(
+test('supports role prop', async () => {
+ await render(
<>
@@ -108,24 +108,24 @@ test('supports role prop', () => {
expect(screen.getByRole('button')).toBeTruthy();
});
-test('supports default View component "none" role', () => {
- render();
+test('supports default View component "none" role', async () => {
+ await render();
expect(screen.getByRole('none').props.testID).toBe('view');
});
-test('supports default Text component "text" role', () => {
- render();
+test('supports default Text component "text" role', async () => {
+ await render();
expect(screen.getByRole('text').props.testID).toBe('text');
});
-test('supports default TextInput component "none" role', () => {
- render();
+test('supports default TextInput component "none" role', async () => {
+ await render();
expect(screen.getByRole('none').props.testID).toBe('text-input');
});
describe('supports name option', () => {
- test('returns an element that has the corresponding role and a children with the name', () => {
- render(
+ test('returns an element that has the corresponding role and a children with the name', async () => {
+ await render(
Save
,
@@ -135,8 +135,8 @@ describe('supports name option', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element that has the corresponding role when several children include the name', () => {
- render(
+ test('returns an element that has the corresponding role when several children include the name', async () => {
+ await render(
Save
Save
@@ -147,8 +147,8 @@ describe('supports name option', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element that has the corresponding role and a children with a matching accessibilityLabel', () => {
- render(
+ test('returns an element that has the corresponding role and a children with a matching accessibilityLabel', async () => {
+ await render(
,
@@ -158,8 +158,8 @@ describe('supports name option', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element that has the corresponding role and a matching accessibilityLabel', () => {
- render(
+ test('returns an element that has the corresponding role and a matching accessibilityLabel', async () => {
+ await render(
{
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element that has the corresponding role and a children with a matching aria-label', () => {
- render(
+ test('returns an element that has the corresponding role and a children with a matching aria-label', async () => {
+ await render(
,
@@ -182,8 +182,8 @@ describe('supports name option', () => {
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element that has the corresponding role and a matching aria-label', () => {
- render(
+ test('returns an element that has the corresponding role and a matching aria-label', async () => {
+ await render(
{
expect(screen.getByRole('button', { name: 'Save' }).props.testID).toBe('target-button');
});
- test('returns an element when the direct child is text', () => {
- render(
+ test('returns an element when the direct child is text', async () => {
+ await render(
About
,
@@ -207,8 +207,8 @@ describe('supports name option', () => {
expect(screen.getByRole('header', { name: 'About' }).props.testID).toBe('target-header');
});
- test('returns an element with nested Text as children', () => {
- render(
+ test('returns an element with nested Text as children', async () => {
+ await render(
About
,
@@ -219,16 +219,18 @@ describe('supports name option', () => {
expect(screen.getByRole('header', { name: 'About' }).props.testID).toBe('parent');
});
- test('returns a header with an accessibilityLabel', () => {
- render();
+ test('returns a header with an accessibilityLabel', async () => {
+ await render(
+ ,
+ );
// assert on the testId to be sure that the returned element is the one with the accessibilityRole
expect(screen.getByRole('header', { name: 'About' })).toBe(screen.getByTestId('target-header'));
expect(screen.getByRole('header', { name: 'About' }).props.testID).toBe('target-header');
});
- test('supports host Image element with "alt" prop', () => {
- render(
+ test('supports host Image element with "alt" prop', async () => {
+ await render(
<>
@@ -249,8 +251,8 @@ describe('supports name option', () => {
describe('supports accessibility states', () => {
describe('disabled', () => {
- test('returns a disabled element when required', () => {
- render(
+ test('returns a disabled element when required', async () => {
+ await render(
,
);
@@ -258,8 +260,8 @@ describe('supports accessibility states', () => {
expect(screen.queryByRole('button', { disabled: false })).toBe(null);
});
- test('returns the correct element when only one matches all the requirements', () => {
- render(
+ test('returns the correct element when only one matches all the requirements', async () => {
+ await render(
<>
{
).toBe('correct');
});
- test('returns an implicitly enabled element', () => {
- render();
+ test('returns an implicitly enabled element', async () => {
+ await render();
expect(screen.getByRole('button', { disabled: false })).toBeTruthy();
expect(screen.queryByRole('button', { disabled: true })).toBe(null);
});
- test('returns an explicitly enabled element', () => {
- render(
+ test('returns an explicitly enabled element', async () => {
+ await render(
{
expect(screen.queryByRole('button', { disabled: true })).toBe(null);
});
- test('does not return disabled elements when querying for non disabled', () => {
- render(
+ test('does not return disabled elements when querying for non disabled', async () => {
+ await render(
{
expect(screen.queryByRole('button', { disabled: false })).toBe(null);
});
- test('returns elements using the built-in disabled prop', () => {
- render(
+ test('returns elements using the built-in disabled prop', async () => {
+ await render(
<>
Pressable
@@ -340,35 +342,37 @@ describe('supports accessibility states', () => {
expect(screen.getByRole('button', { name: 'RNButton', disabled: true })).toBeTruthy();
});
- test('supports aria-disabled={true} prop', () => {
- render();
+ test('supports aria-disabled={true} prop', async () => {
+ await render();
expect(screen.getByRole('button', { disabled: true })).toBeTruthy();
expect(screen.queryByRole('button', { disabled: false })).toBeNull();
});
- test('supports aria-disabled={false} prop', () => {
- render();
+ test('supports aria-disabled={false} prop', async () => {
+ await render();
expect(screen.getByRole('button', { disabled: false })).toBeTruthy();
expect(screen.queryByRole('button', { disabled: true })).toBeNull();
});
- test('supports default aria-disabled prop', () => {
- render();
+ test('supports default aria-disabled prop', async () => {
+ await render();
expect(screen.getByRole('button', { disabled: false })).toBeTruthy();
expect(screen.queryByRole('button', { disabled: true })).toBeNull();
});
});
describe('selected', () => {
- test('returns a selected element when required', () => {
- render();
+ test('returns a selected element when required', async () => {
+ await render(
+ ,
+ );
expect(screen.getByRole('tab', { selected: true })).toBeTruthy();
expect(screen.queryByRole('tab', { selected: false })).toBe(null);
});
- test('returns the correct element when only one matches all the requirements', () => {
- render(
+ test('returns the correct element when only one matches all the requirements', async () => {
+ await render(
<>
{
);
});
- test('returns an implicitly non selected element', () => {
- render();
+ test('returns an implicitly non selected element', async () => {
+ await render();
expect(screen.getByRole('tab', { selected: false })).toBeTruthy();
expect(screen.queryByRole('tab', { selected: true })).toBe(null);
});
- test('returns an explicitly non selected element', () => {
- render(
+ test('returns an explicitly non selected element', async () => {
+ await render(
{
expect(screen.queryByRole('tab', { selected: true })).toBe(null);
});
- test('does not return selected elements when querying for non selected', () => {
- render(
+ test('does not return selected elements when querying for non selected', async () => {
+ await render(
{
expect(screen.queryByRole('tab', { selected: false })).toBe(null);
});
- test('supports aria-selected={true} prop', () => {
- render();
+ test('supports aria-selected={true} prop', async () => {
+ await render();
expect(screen.getByRole('button', { selected: true })).toBeTruthy();
expect(screen.queryByRole('button', { selected: false })).toBeNull();
});
- test('supports aria-selected={false} prop', () => {
- render();
+ test('supports aria-selected={false} prop', async () => {
+ await render();
expect(screen.getByRole('button', { selected: false })).toBeTruthy();
expect(screen.queryByRole('button', { selected: true })).toBeNull();
});
- test('supports default aria-selected prop', () => {
- render();
+ test('supports default aria-selected prop', async () => {
+ await render();
expect(screen.getByRole('button', { selected: false })).toBeTruthy();
expect(screen.queryByRole('button', { selected: true })).toBeNull();
});
});
describe('checked', () => {
- test('returns a checked element when required', () => {
- render(
+ test('returns a checked element when required', async () => {
+ await render(
,
);
@@ -448,8 +452,8 @@ describe('supports accessibility states', () => {
expect(screen.queryByRole('checkbox', { checked: 'mixed' })).toBe(null);
});
- test('returns `mixed` checkboxes', () => {
- render(
+ test('returns `mixed` checkboxes', async () => {
+ await render(
,
);
@@ -458,16 +462,16 @@ describe('supports accessibility states', () => {
expect(screen.queryByRole('checkbox', { checked: false })).toBe(null);
});
- it('does not return mixed checkboxes when querying for checked: true', () => {
- render(
+ it('does not return mixed checkboxes when querying for checked: true', async () => {
+ await render(
,
);
expect(screen.queryByRole('checkbox', { checked: false })).toBe(null);
});
- test('returns the correct element when only one matches all the requirements', () => {
- render(
+ test('returns the correct element when only one matches all the requirements', async () => {
+ await render(
<>
{
).toBe('correct');
});
- test('does not return return as non checked an element with checked: undefined', () => {
- render();
+ test('does not return return as non checked an element with checked: undefined', async () => {
+ await render();
expect(screen.queryByRole('checkbox', { checked: false })).toBe(null);
});
- test('returns an explicitly non checked element', () => {
- render(
+ test('returns an explicitly non checked element', async () => {
+ await render(
{
expect(screen.queryByRole('checkbox', { checked: true })).toBe(null);
});
- test('does not return checked elements when querying for non checked', () => {
- render(
+ test('does not return checked elements when querying for non checked', async () => {
+ await render(
{
expect(screen.queryByRole('checkbox', { checked: false })).toBe(null);
});
- test('does not return mixed elements when querying for non checked', () => {
- render(
+ test('does not return mixed elements when querying for non checked', async () => {
+ await render(
{
expect(screen.queryByRole('checkbox', { checked: false })).toBe(null);
});
- test('supports "Switch" component', () => {
- render();
+ test('supports "Switch" component', async () => {
+ await render();
expect(screen.getByRole('switch', { checked: true })).toBeTruthy();
expect(screen.queryByRole('switch', { checked: false })).toBe(null);
expect(screen.queryByRole('switch', { checked: 'mixed' })).toBe(null);
});
- test('supports aria-checked={true} prop', () => {
- render();
+ test('supports aria-checked={true} prop', async () => {
+ await render();
expect(screen.getByRole('checkbox', { checked: true })).toBeTruthy();
expect(screen.queryByRole('checkbox', { checked: false })).toBeNull();
expect(screen.queryByRole('checkbox', { checked: 'mixed' })).toBeNull();
});
- test('supports aria-checked={false} prop', () => {
- render();
+ test('supports aria-checked={false} prop', async () => {
+ await render();
expect(screen.getByRole('checkbox', { checked: false })).toBeTruthy();
expect(screen.queryByRole('checkbox', { checked: true })).toBeNull();
expect(screen.queryByRole('checkbox', { checked: 'mixed' })).toBeNull();
});
- test('supports aria-checked="mixed" prop', () => {
- render();
+ test('supports aria-checked="mixed" prop', async () => {
+ await render();
expect(screen.getByRole('checkbox', { checked: 'mixed' })).toBeTruthy();
expect(screen.queryByRole('checkbox', { checked: true })).toBeNull();
expect(screen.queryByRole('checkbox', { checked: false })).toBeNull();
});
- test('supports default aria-selected prop', () => {
- render();
+ test('supports default aria-selected prop', async () => {
+ await render();
expect(screen.getByRole('checkbox')).toBeTruthy();
expect(screen.queryByRole('checkbox', { checked: true })).toBeNull();
expect(screen.queryByRole('checkbox', { checked: false })).toBeNull();
@@ -569,15 +573,17 @@ describe('supports accessibility states', () => {
});
describe('busy', () => {
- test('returns a busy element when required', () => {
- render();
+ test('returns a busy element when required', async () => {
+ await render(
+ ,
+ );
expect(screen.getByRole('button', { busy: true })).toBeTruthy();
expect(screen.queryByRole('button', { busy: false })).toBe(null);
});
- test('returns the correct element when only one matches all the requirements', () => {
- render(
+ test('returns the correct element when only one matches all the requirements', async () => {
+ await render(
<>
{
expect(screen.getByRole('button', { name: 'Save', busy: true }).props.testID).toBe('correct');
});
- test('returns an implicitly non busy element', () => {
- render();
+ test('returns an implicitly non busy element', async () => {
+ await render();
expect(screen.getByRole('button', { busy: false })).toBeTruthy();
expect(screen.queryByRole('button', { busy: true })).toBe(null);
});
- test('returns an explicitly non busy element', () => {
- render(
+ test('returns an explicitly non busy element', async () => {
+ await render(
{
expect(screen.queryByRole('button', { busy: true })).toBe(null);
});
- test('does not return busy elements when querying for non busy', () => {
- render(
+ test('does not return busy elements when querying for non busy', async () => {
+ await render(
{
expect(screen.queryByRole('button', { selected: false })).toBe(null);
});
- test('supports aria-busy={true} prop', () => {
- render();
+ test('supports aria-busy={true} prop', async () => {
+ await render();
expect(screen.getByRole('button', { busy: true })).toBeTruthy();
expect(screen.queryByRole('button', { busy: false })).toBeNull();
});
- test('supports aria-busy={false} prop', () => {
- render();
+ test('supports aria-busy={false} prop', async () => {
+ await render();
expect(screen.getByRole('button', { busy: false })).toBeTruthy();
expect(screen.queryByRole('button', { busy: true })).toBeNull();
});
- test('supports default aria-busy prop', () => {
- render();
+ test('supports default aria-busy prop', async () => {
+ await render();
expect(screen.getByRole('button', { busy: false })).toBeTruthy();
expect(screen.queryByRole('button', { busy: true })).toBeNull();
});
});
describe('expanded', () => {
- test('returns a expanded element when required', () => {
- render(
+ test('returns a expanded element when required', async () => {
+ await render(
,
);
@@ -654,8 +660,8 @@ describe('supports accessibility states', () => {
expect(screen.queryByRole('button', { expanded: false })).toBe(null);
});
- test('returns the correct element when only one matches all the requirements', () => {
- render(
+ test('returns the correct element when only one matches all the requirements', async () => {
+ await render(
<>
{
).toBe('correct');
});
- test('does not return return as non expanded an element with expanded: undefined', () => {
- render();
+ test('does not return return as non expanded an element with expanded: undefined', async () => {
+ await render();
expect(screen.queryByRole('button', { expanded: false })).toBe(null);
});
- test('returns an explicitly non expanded element', () => {
- render(
+ test('returns an explicitly non expanded element', async () => {
+ await render(
{
expect(screen.queryByRole('button', { expanded: true })).toBe(null);
});
- test('does not return expanded elements when querying for non expanded', () => {
- render(
+ test('does not return expanded elements when querying for non expanded', async () => {
+ await render(
{
expect(screen.queryByRole('button', { expanded: false })).toBe(null);
});
- test('supports aria-expanded={true} prop', () => {
- render();
+ test('supports aria-expanded={true} prop', async () => {
+ await render();
expect(screen.getByRole('button', { expanded: true })).toBeTruthy();
expect(screen.queryByRole('button', { expanded: false })).toBeNull();
});
- test('supports aria-expanded={false} prop', () => {
- render();
+ test('supports aria-expanded={false} prop', async () => {
+ await render();
expect(screen.getByRole('button', { expanded: false })).toBeTruthy();
expect(screen.queryByRole('button', { expanded: true })).toBeNull();
});
- test('supports default aria-expanded prop', () => {
- render();
+ test('supports default aria-expanded prop', async () => {
+ await render();
expect(screen.getByRole('button')).toBeTruthy();
expect(screen.queryByRole('button', { expanded: true })).toBeNull();
expect(screen.queryByRole('button', { expanded: false })).toBeNull();
});
});
- test('ignores non queried accessibilityState', () => {
- render(
+ test('ignores non queried accessibilityState', async () => {
+ await render(
{
).toBe(null);
});
- test('matches an element combining all the options', () => {
- render(
+ test('matches an element combining all the options', async () => {
+ await render(
{
});
describe('error messages', () => {
- test('gives a descriptive error message when querying with a role', () => {
- render();
+ test('gives a descriptive error message when querying with a role', async () => {
+ await render();
expect(() => screen.getByRole('button')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with role: button
@@ -795,8 +801,8 @@ describe('error messages', () => {
`);
});
- test('gives a descriptive error message when querying with a role and a name', () => {
- render();
+ test('gives a descriptive error message when querying with a role and a name', async () => {
+ await render();
expect(() => screen.getByRole('button', { name: 'Save' })).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with role: button, name: Save
@@ -805,8 +811,8 @@ describe('error messages', () => {
`);
});
- test('gives a descriptive error message when querying with a role, a name and accessibility state', () => {
- render();
+ test('gives a descriptive error message when querying with a role, a name and accessibility state', async () => {
+ await render();
expect(() => screen.getByRole('button', { name: 'Save', disabled: true }))
.toThrowErrorMatchingInlineSnapshot(`
@@ -816,8 +822,8 @@ describe('error messages', () => {
`);
});
- test('gives a descriptive error message when querying with a role, a name and several accessibility state', () => {
- render();
+ test('gives a descriptive error message when querying with a role, a name and several accessibility state', async () => {
+ await render();
expect(() => screen.getByRole('button', { name: 'Save', disabled: true, selected: true }))
.toThrowErrorMatchingInlineSnapshot(`
@@ -827,8 +833,8 @@ describe('error messages', () => {
`);
});
- test('gives a descriptive error message when querying with a role and an accessibility state', () => {
- render();
+ test('gives a descriptive error message when querying with a role and an accessibility state', async () => {
+ await render();
expect(() => screen.getByRole('button', { disabled: true }))
.toThrowErrorMatchingInlineSnapshot(`
@@ -838,8 +844,8 @@ describe('error messages', () => {
`);
});
- test('gives a descriptive error message when querying with a role and an accessibility value', () => {
- render();
+ test('gives a descriptive error message when querying with a role and an accessibility value', async () => {
+ await render();
expect(() => screen.getByRole('adjustable', { value: { min: 1 } }))
.toThrowErrorMatchingInlineSnapshot(`
@@ -860,8 +866,8 @@ describe('error messages', () => {
});
});
-test('byRole queries support hidden option', () => {
- render(
+test('byRole queries support hidden option', async () => {
+ await render(
Hidden from accessibility
,
@@ -892,8 +898,8 @@ test('byRole queries support hidden option', () => {
});
describe('matches only accessible elements', () => {
- test('matches elements with accessible={true}', () => {
- render(
+ test('matches elements with accessible={true}', async () => {
+ await render(
Action
,
@@ -901,8 +907,8 @@ describe('matches only accessible elements', () => {
expect(screen.queryByRole('menu', { name: 'Action' })).toBeTruthy();
});
- test('ignores elements with accessible={false}', () => {
- render(
+ test('ignores elements with accessible={false}', async () => {
+ await render(
Action
,
@@ -910,8 +916,8 @@ describe('matches only accessible elements', () => {
expect(screen.queryByRole('button', { name: 'Action' })).toBeFalsy();
});
- test('ignores elements with accessible={undefined} and that are implicitly not accessible', () => {
- render(
+ test('ignores elements with accessible={undefined} and that are implicitly not accessible', async () => {
+ await render(
Action
,
@@ -921,7 +927,7 @@ describe('matches only accessible elements', () => {
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByRole('link')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with role: link
diff --git a/src/queries/__tests__/test-id.test.tsx b/src/queries/__tests__/test-id.test.tsx
index 79377ce57..e49fa54b6 100644
--- a/src/queries/__tests__/test-id.test.tsx
+++ b/src/queries/__tests__/test-id.test.tsx
@@ -25,8 +25,8 @@ const Banana = () => (
const MyComponent = (_props: { testID?: string }) => My Component;
-test('getByTestId returns only native elements', () => {
- render(
+test('getByTestId returns only native elements', async () => {
+ await render(
Text
@@ -54,8 +54,8 @@ test('getByTestId returns only native elements', () => {
);
});
-test('supports a regex matcher', () => {
- render(
+test('supports a regex matcher', async () => {
+ await render(
Text
@@ -69,8 +69,8 @@ test('supports a regex matcher', () => {
expect(screen.getAllByTestId(/text/)).toHaveLength(2);
});
-test('getByTestId, queryByTestId', () => {
- render();
+test('getByTestId, queryByTestId', async () => {
+ await render();
const component = screen.getByTestId('bananaFresh');
expect(component.props.children).toBe('not fresh');
@@ -89,8 +89,8 @@ test('getByTestId, queryByTestId', () => {
);
});
-test('getAllByTestId, queryAllByTestId', () => {
- render();
+test('getAllByTestId, queryAllByTestId', async () => {
+ await render();
const textElements = screen.getAllByTestId('duplicateText');
expect(textElements.length).toBe(2);
@@ -110,7 +110,7 @@ test('getAllByTestId, queryAllByTestId', () => {
test('findByTestId and findAllByTestId work asynchronously', async () => {
const options = { timeout: 10 }; // Short timeout so that this test runs quickly
- render();
+ await render();
await expect(screen.findByTestId('aTestId', {}, options)).rejects.toBeTruthy();
await expect(screen.findAllByTestId('aTestId', {}, options)).rejects.toBeTruthy();
@@ -130,8 +130,8 @@ test('findByTestId and findAllByTestId work asynchronously', async () => {
await expect(screen.findAllByTestId('aTestId')).resolves.toHaveLength(1);
}, 20000);
-test('byTestId queries support hidden option', () => {
- render(
+test('byTestId queries support hidden option', async () => {
+ await render(
Hidden from accessibility
,
@@ -159,7 +159,7 @@ test('byTestId queries support hidden option', () => {
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByTestId('FOO')).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with testID: FOO
diff --git a/src/queries/__tests__/text.test.tsx b/src/queries/__tests__/text.test.tsx
index 0dda7578d..28a3b16bc 100644
--- a/src/queries/__tests__/text.test.tsx
+++ b/src/queries/__tests__/text.test.tsx
@@ -3,13 +3,13 @@ import { Button, Image, Text, TextInput, TouchableOpacity, View } from 'react-na
import { getDefaultNormalizer, render, screen, within } from '../..';
-test('byText matches simple text', () => {
- render(Hello World);
+test('byText matches simple text', async () => {
+ await render(Hello World);
expect(screen.getByText('Hello World').props.testID).toBe('text');
});
-test('byText matches inner nested text', () => {
- render(
+test('byText matches inner nested text', async () => {
+ await render(
Hello World
,
@@ -17,8 +17,8 @@ test('byText matches inner nested text', () => {
expect(screen.getByText('Hello World').props.testID).toBe('inner');
});
-test('byText matches accross multiple texts', () => {
- render(
+test('byText matches accross multiple texts', async () => {
+ await render(
Hello World
,
@@ -53,8 +53,8 @@ const Banana = () => {
type ChildrenProps = { children: React.ReactNode };
-test('getByText, queryByText', () => {
- render();
+test('getByText, queryByText', async () => {
+ await render();
const button = screen.getByText(/change/i);
expect(button.props.children).toBe('Change freshness!');
@@ -74,7 +74,7 @@ test('getByText, queryByText', () => {
expect(screen.queryByText('0')).toBe(zeroText);
});
-test('getByText, screen.queryByText with children as Array', () => {
+test('getByText, screen.queryByText with children as Array', async () => {
type BananaCounterProps = { numBananas: number };
const BananaCounter = ({ numBananas }: BananaCounterProps) => (
There are {numBananas} bananas in the bunch
@@ -88,14 +88,14 @@ test('getByText, screen.queryByText with children as Array', () => {
);
- render();
+ await render();
const threeBananaBunch = screen.getByText('There are 3 bananas in the bunch');
expect(threeBananaBunch.props.children).toEqual(['There are ', 3, ' bananas in the bunch']);
});
-test('getAllByText, queryAllByText', () => {
- render();
+test('getAllByText, queryAllByText', async () => {
+ await render();
const buttons = screen.getAllByText(/fresh/i);
expect(buttons).toHaveLength(3);
@@ -109,7 +109,7 @@ test('getAllByText, queryAllByText', () => {
test('findByText queries work asynchronously', async () => {
const options = { timeout: 10 }; // Short timeout so that this test runs quickly
- render();
+ await render();
await expect(screen.findByText('Some Text', {}, options)).rejects.toBeTruthy();
await expect(screen.findAllByText('Some Text', {}, options)).rejects.toBeTruthy();
@@ -127,21 +127,23 @@ test('findByText queries work asynchronously', async () => {
await expect(screen.findAllByText('Some Text')).resolves.toHaveLength(1);
}, 20000);
-test('getByText works properly with custom text component', () => {
+test('getByText works properly with custom text component', async () => {
function BoldText({ children }: ChildrenProps) {
return {children};
}
expect(
- render(
-
- Hello
- ,
+ (
+ await render(
+
+ Hello
+ ,
+ )
).getByText('Hello'),
).toBeTruthy();
});
-test('getByText works properly with custom text container', () => {
+test('getByText works properly with custom text container', async () => {
function MyText({ children }: ChildrenProps) {
return {children};
}
@@ -151,61 +153,71 @@ test('getByText works properly with custom text container', () => {
}
expect(
- render(
-
- Hello
- ,
+ (
+ await render(
+
+ Hello
+ ,
+ )
).getByText('Hello'),
).toBeTruthy();
});
-test('queryByText nested in at start', () => {
+test('queryByText nested in at start', async () => {
expect(
- render(
-
-
- Hello
- ,
+ (
+ await render(
+
+
+ Hello
+ ,
+ )
).queryByText('Hello'),
).toBeTruthy();
});
-test('queryByText nested in at end', () => {
+test('queryByText nested in at end', async () => {
expect(
- render(
-
- Hello
-
- ,
+ (
+ await render(
+
+ Hello
+
+ ,
+ )
).queryByText('Hello'),
).toBeTruthy();
});
-test('queryByText nested in in middle', () => {
+test('queryByText nested in in middle', async () => {
expect(
- render(
-
- Hello
-
- World
- ,
+ (
+ await render(
+
+ Hello
+
+ World
+ ,
+ )
).queryByText('HelloWorld'),
).toBeTruthy();
});
-test('queryByText not found', () => {
+test('queryByText not found', async () => {
expect(
- render(
-
- Hello
-
- ,
+ (
+ await render(
+
+ Hello
+
+ ,
+ )
).queryByText('SomethingElse'),
).toBeFalsy();
});
-test('*ByText matches text across multiple nested Text', () => {
- render(
+test('*ByText matches text across multiple nested Text', async () => {
+ await render(
Hello{' '}
@@ -218,18 +230,18 @@ test('*ByText matches text across multiple nested Text', () => {
expect(screen.getByText('Hello World!')).toBeTruthy();
});
-test('queryByText with nested Text components return the closest Text', () => {
+test('queryByText with nested Text components return the closest Text', async () => {
const NestedTexts = () => (
My text
);
- render();
+ await render();
expect(screen.queryByText('My text', { exact: false })?.props.nativeID).toBe('2');
});
-test('queryByText with nested Text components each with text return the lowest one', () => {
+test('queryByText with nested Text components each with text return the lowest one', async () => {
const NestedTexts = () => (
bob
@@ -237,27 +249,29 @@ test('queryByText with nested Text components each with text return the lowest o
);
- render();
+ await render();
expect(screen.queryByText('My text', { exact: false })?.props.nativeID).toBe('2');
});
-test('queryByText nested deep in ', () => {
+test('queryByText nested deep in ', async () => {
const CustomText = ({ children }: ChildrenProps) => {
return {children};
};
expect(
- render(
-
- Hello World!
- ,
+ (
+ await render(
+
+ Hello World!
+ ,
+ )
).getByText('Hello World!'),
).toBeTruthy();
});
-test('queryByText with nested Text components: not-exact text match returns the most deeply nested common component', () => {
- render(
+test('queryByText with nested Text components: not-exact text match returns the most deeply nested common component', async () => {
+ await render(
bob
My
@@ -265,7 +279,7 @@ test('queryByText with nested Text components: not-exact text match returns the
,
);
- render(
+ await render(
bob
My text for test
@@ -276,32 +290,36 @@ test('queryByText with nested Text components: not-exact text match returns the
expect(screen.queryByText('My text', { exact: false })?.props.nativeID).toBe('2');
});
-test('queryAllByText does not match several times the same text', () => {
- const allMatched = render(
-
- Start
- This is a long text
- ,
+test('queryAllByText does not match several times the same text', async () => {
+ const allMatched = (
+ await render(
+
+ Start
+ This is a long text
+ ,
+ )
).queryAllByText('long text', { exact: false });
expect(allMatched.length).toBe(1);
expect(allMatched[0].props.nativeID).toBe('2');
});
-test('queryAllByText matches all the matching nodes', () => {
- const allMatched = render(
-
- Start
- This is a long text
- This is another long text
- ,
+test('queryAllByText matches all the matching nodes', async () => {
+ const allMatched = (
+ await render(
+
+ Start
+ This is a long text
+ This is another long text
+ ,
+ )
).queryAllByText('long text', { exact: false });
expect(allMatched.length).toBe(2);
expect(allMatched.map((node) => node.props.nativeID)).toEqual(['2', '3']);
});
describe('supports TextMatch options', () => {
- test('getByText, getAllByText', () => {
- render(
+ test('getByText, getAllByText', async () => {
+ await render(
Text and details
@@ -312,8 +330,8 @@ describe('supports TextMatch options', () => {
expect(screen.getAllByText('detail', { exact: false })).toHaveLength(2);
});
- test('getByPlaceholderText, getAllByPlaceholderText', () => {
- render(
+ test('getByPlaceholderText, getAllByPlaceholderText', async () => {
+ await render(
@@ -324,8 +342,8 @@ describe('supports TextMatch options', () => {
expect(screen.getAllByPlaceholderText('detail', { exact: false })).toHaveLength(2);
});
- test('getByDisplayValue, getAllByDisplayValue', () => {
- render(
+ test('getByDisplayValue, getAllByDisplayValue', async () => {
+ await render(
@@ -336,8 +354,8 @@ describe('supports TextMatch options', () => {
expect(screen.getAllByDisplayValue('detail', { exact: false })).toHaveLength(2);
});
- test('getByTestId, getAllByTestId', () => {
- render(
+ test('getByTestId, getAllByTestId', async () => {
+ await render(
@@ -347,8 +365,8 @@ describe('supports TextMatch options', () => {
expect(screen.getAllByTestId('test', { exact: false })).toHaveLength(2);
});
- test('with TextMatch option exact === false text search is NOT case sensitive', () => {
- render(
+ test('with TextMatch option exact === false text search is NOT case sensitive', async () => {
+ await render(
Text and details
@@ -361,8 +379,8 @@ describe('supports TextMatch options', () => {
});
describe('Supports normalization', () => {
- test('trims and collapses whitespace by default', () => {
- render(
+ test('trims and collapses whitespace by default', async () => {
+ await render(
{` Text and
@@ -373,11 +391,11 @@ describe('Supports normalization', () => {
expect(screen.getByText('Text and whitespace')).toBeTruthy();
});
- test('trim and collapseWhitespace is customizable by getDefaultNormalizer param', () => {
+ test('trim and collapseWhitespace is customizable by getDefaultNormalizer param', async () => {
const testTextWithWhitespace = ` Text and
whitespace`;
- render(
+ await render(
{testTextWithWhitespace}
,
@@ -393,10 +411,10 @@ describe('Supports normalization', () => {
).toBeTruthy();
});
- test('normalizer function is customisable', () => {
+ test('normalizer function is customisable', async () => {
const testText = 'A TO REMOVE text';
const normalizerFn = (textToNormalize: string) => textToNormalize.replace('TO REMOVE ', '');
- render(
+ await render(
{testText}
,
@@ -406,8 +424,8 @@ describe('Supports normalization', () => {
});
});
-test('getByText and queryByText work properly with text nested in React.Fragment', () => {
- render(
+test('getByText and queryByText work properly with text nested in React.Fragment', async () => {
+ await render(
<>Hello>
,
@@ -416,8 +434,8 @@ test('getByText and queryByText work properly with text nested in React.Fragment
expect(screen.queryByText('Hello')).not.toBeNull();
});
-test('getByText and queryByText work properly with text partially nested in React.Fragment', () => {
- render(
+test('getByText and queryByText work properly with text partially nested in React.Fragment', async () => {
+ await render(
He<>llo>
,
@@ -426,8 +444,8 @@ test('getByText and queryByText work properly with text partially nested in Reac
expect(screen.queryByText('Hello')).not.toBeNull();
});
-test('getByText and queryByText work properly with multiple nested fragments', () => {
- render(
+test('getByText and queryByText work properly with multiple nested fragments', async () => {
+ await render(
He
<>
@@ -439,28 +457,28 @@ test('getByText and queryByText work properly with multiple nested fragments', (
expect(screen.queryByText('Hello')).not.toBeNull();
});
-test('getByText and queryByText work with newlines', () => {
+test('getByText and queryByText work with newlines', async () => {
const textWithNewLines = 'Line 1\nLine 2';
- render({textWithNewLines});
+ await render({textWithNewLines});
expect(screen.getByText(textWithNewLines)).toBeTruthy();
expect(screen.queryByText(textWithNewLines)).toBeTruthy();
});
-test('getByText and queryByText work with tabs', () => {
+test('getByText and queryByText work with tabs', async () => {
const textWithTabs = 'Line 1\tLine 2';
- render({textWithTabs});
+ await render({textWithTabs});
expect(screen.getByText(textWithTabs)).toBeTruthy();
expect(screen.queryByText(textWithTabs)).toBeTruthy();
});
-test('getByText does not search for text within itself', () => {
- render(Hello);
+test('getByText does not search for text within itself', async () => {
+ await render(Hello);
const textNode = within(screen.getByText('Hello'));
expect(textNode.queryByText('Hello')).toBeNull();
});
-test('byText support hidden option', () => {
- render(Hidden from accessibility);
+test('byText support hidden option', async () => {
+ await render(Hidden from accessibility);
expect(screen.getByText(/hidden/i, { includeHiddenElements: true })).toBeTruthy();
@@ -483,7 +501,7 @@ test('byText support hidden option', () => {
});
test('error message renders the element tree, preserving only helpful props', async () => {
- render();
+ await render();
expect(() => screen.getByText(/foo/)).toThrowErrorMatchingInlineSnapshot(`
"Unable to find an element with text: /foo/
@@ -518,7 +536,7 @@ test('error message renders the element tree, preserving only helpful props', as
`);
});
-test('byText should return host component', () => {
- render(hello);
+test('byText should return host component', async () => {
+ await render(hello);
expect(screen.getByText('hello').type).toBe('Text');
});
diff --git a/src/queries/make-queries.ts b/src/queries/make-queries.ts
index 7aba2d35a..fa2868fc5 100644
--- a/src/queries/make-queries.ts
+++ b/src/queries/make-queries.ts
@@ -5,7 +5,7 @@ import { formatJson } from '../helpers/format-element';
import { logger } from '../helpers/logger';
import { screen } from '../screen';
import type { WaitForOptions } from '../wait-for';
-import waitFor from '../wait-for';
+import { waitFor } from '../wait-for';
export type GetByQuery = (
predicate: Predicate,
diff --git a/src/render-hook.tsx b/src/render-hook.tsx
index 2aaa18dfd..b04e61dae 100644
--- a/src/render-hook.tsx
+++ b/src/render-hook.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
-import render from './render';
-import renderAsync from './render-async';
+import { render } from './render';
import type { RefObject } from './types';
+import { unsafe_renderSync } from './unsafe-render-sync';
export type RenderHookResult = {
result: RefObject;
@@ -47,21 +47,21 @@ export async function renderHook(
}
const { initialProps, ...renderOptions } = options ?? {};
- const { rerenderAsync: rerenderComponentAsync, unmountAsync } = await renderAsync(
- // @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
+ const { rerender: rerenderComponent, unmount } = await render(
+ // @ts-expect-error since option can be undefined, initialProps can be undefined when it shouldn't be
,
renderOptions,
);
return {
result: result,
- rerender: (hookProps: Props) => rerenderComponentAsync(),
- unmount: unmountAsync,
+ rerender: (hookProps: Props) => rerenderComponent(),
+ unmount,
};
}
/** @deprecated - Use async `renderHook` instead. */
-export function deprecated_renderHookSync(
+export function unsafe_renderHookSync(
hookToRender: (props: Props) => Result,
options?: RenderHookOptions>,
): RenderHookSyncResult {
@@ -77,7 +77,7 @@ export function deprecated_renderHookSync(
}
const { initialProps, ...renderOptions } = options ?? {};
- const { rerender: rerenderComponent, unmount } = render(
+ const { rerender: rerenderComponent, unmount } = unsafe_renderSync(
// @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
,
renderOptions,
diff --git a/src/render.tsx b/src/render.tsx
index 9944904ff..cedff3e2a 100644
--- a/src/render.tsx
+++ b/src/render.tsx
@@ -6,7 +6,8 @@ import { addToCleanupQueue } from './cleanup';
import { getConfig } from './config';
import type { DebugOptions } from './helpers/debug';
import { debug } from './helpers/debug';
-import { renderWithAct } from './render-act';
+import { HOST_TEXT_NAMES } from './helpers/host-component-names';
+import { renderWithAsyncAct } from './render-act';
import { setRenderResult } from './screen';
import { getQueriesForElement } from './within';
@@ -18,27 +19,25 @@ export interface RenderOptions {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
wrapper?: React.ComponentType;
- createNodeMock?: (element: React.ReactElement) => unknown;
+ createNodeMock?: (element: React.ReactElement) => object;
}
-export type RenderResult = ReturnType;
+export type RenderResult = Awaited>;
/**
* Renders test component deeply using React Test Renderer and exposes helpers
* to assert on the output.
*/
-export default function render(component: React.ReactElement, options: RenderOptions = {}) {
- return renderInternal(component, options);
-}
-
-export function renderInternal(component: React.ReactElement, options?: RenderOptions) {
- const { wrapper: Wrapper } = options || {};
+export async function render(component: React.ReactElement, options: RenderOptions = {}) {
+ const { wrapper: Wrapper, createNodeMock } = options || {};
- // TODO allow passing some options
- const rendererOptions: RootOptions = {};
+ const rendererOptions: RootOptions = {
+ textComponents: HOST_TEXT_NAMES,
+ createNodeMock,
+ };
const wrap = (element: React.ReactElement) => (Wrapper ? {element} : element);
- const renderer = renderWithAct(wrap(component), rendererOptions);
+ const renderer = await renderWithAsyncAct(wrap(component), rendererOptions);
return buildRenderResult(renderer, wrap);
}
@@ -46,24 +45,16 @@ function buildRenderResult(
renderer: Root,
wrap: (element: React.ReactElement) => React.JSX.Element,
) {
- const rerender = (component: React.ReactElement) => {
- void act(() => {
- renderer.render(wrap(component));
- });
- };
- const rerenderAsync = async (component: React.ReactElement) => {
+ const container = renderer.container;
+
+ const rerender = async (component: React.ReactElement) => {
// eslint-disable-next-line require-await
await act(async () => {
renderer.render(wrap(component));
});
};
- const unmount = () => {
- void act(() => {
- renderer.unmount();
- });
- };
- const unmountAsync = async () => {
+ const unmount = async () => {
// eslint-disable-next-line require-await
await act(async () => {
renderer.unmount();
@@ -83,23 +74,20 @@ function buildRenderResult(
return json;
};
- addToCleanupQueue(unmountAsync);
+ addToCleanupQueue(unmount);
const result = {
...getQueriesForElement(renderer.container),
rerender,
- rerenderAsync,
- update: rerender, // alias for 'rerender'
- updateAsync: rerenderAsync, // alias for `rerenderAsync`
+ update: rerender, // alias for `rerender`
unmount,
- unmountAsync,
toJSON,
debug: makeDebug(renderer),
get container(): HostElement {
return renderer.container;
},
get root(): HostElement | null {
- const firstChild = renderer.container.children[0];
+ const firstChild = container.children[0];
if (typeof firstChild === 'string') {
throw new Error(
'Invariant Violation: Root element must be a host element. Detected attempt to render a string within the root element.',
diff --git a/src/screen.ts b/src/screen.ts
index fb3a01932..1fa86787a 100644
--- a/src/screen.ts
+++ b/src/screen.ts
@@ -2,7 +2,7 @@ import type { HostElement } from 'universal-test-renderer';
import type { RenderResult } from './render';
-const SCREEN_ERROR = '`render` method has not been called';
+const SCREEN_ERROR = '`render` function has not been called';
const notImplemented = () => {
throw new Error(SCREEN_ERROR);
@@ -22,11 +22,8 @@ const defaultScreen: Screen = {
},
debug: notImplemented,
rerender: notImplemented,
- rerenderAsync: notImplemented,
update: notImplemented,
- updateAsync: notImplemented,
unmount: notImplemented,
- unmountAsync: notImplemented,
toJSON: notImplemented,
getByLabelText: notImplemented,
getAllByLabelText: notImplemented,
diff --git a/src/render-async.tsx b/src/unsafe-render-sync.tsx
similarity index 59%
rename from src/render-async.tsx
rename to src/unsafe-render-sync.tsx
index 5ac031706..4b7959c55 100644
--- a/src/render-async.tsx
+++ b/src/unsafe-render-sync.tsx
@@ -1,17 +1,17 @@
import * as React from 'react';
-import type { HostElement, Root, RootOptions } from 'universal-test-renderer';
+import type { HostElement, JsonElement, Root, RootOptions } from 'universal-test-renderer';
import act from './act';
import { addToCleanupQueue } from './cleanup';
import { getConfig } from './config';
import type { DebugOptions } from './helpers/debug';
import { debug } from './helpers/debug';
-import { ErrorWithStack } from './helpers/errors';
-import { renderWithAsyncAct } from './render-act';
+import { HOST_TEXT_NAMES } from './helpers/host-component-names';
+import { renderWithAct } from './render-act';
import { setRenderResult } from './screen';
import { getQueriesForElement } from './within';
-export interface RenderAsyncOptions {
+export interface RenderSyncOptions {
/**
* Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating
* reusable custom render functions for common data providers.
@@ -19,26 +19,33 @@ export interface RenderAsyncOptions {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
wrapper?: React.ComponentType;
- createNodeMock?: (element: React.ReactElement) => unknown;
+ createNodeMock?: (element: React.ReactElement) => object;
}
-export type RenderAsyncResult = ReturnType;
-
/**
+ * @deprecated Use `render` (async) instead. This function is provided for migration purposes only.
* Renders test component deeply using React Test Renderer and exposes helpers
* to assert on the output.
*/
-export default async function renderAsync(
+export function unsafe_renderSync(
component: React.ReactElement,
- options: RenderAsyncOptions = {},
+ options: RenderSyncOptions = {},
) {
- const { wrapper: Wrapper } = options || {};
+ return renderInternal(component, options);
+}
+
+export type RenderSyncResult = ReturnType;
- // TODO allow passing some options
- const rendererOptions: RootOptions = {};
+export function renderInternal(component: React.ReactElement, options?: RenderSyncOptions) {
+ const { wrapper: Wrapper, createNodeMock } = options || {};
+
+ const rendererOptions: RootOptions = {
+ textComponents: HOST_TEXT_NAMES,
+ createNodeMock,
+ };
const wrap = (element: React.ReactElement) => (Wrapper ? {element} : element);
- const renderer = await renderWithAsyncAct(wrap(component), rendererOptions);
+ const renderer = renderWithAct(wrap(component), rendererOptions);
return buildRenderResult(renderer, wrap);
}
@@ -46,14 +53,12 @@ function buildRenderResult(
renderer: Root,
wrap: (element: React.ReactElement) => React.JSX.Element,
) {
- const container = renderer.container;
-
- const rerender = (_component: React.ReactElement) => {
- throw new ErrorWithStack(
- '"rerender(...)" is not supported when using "renderAsync" use "await rerenderAsync(...)" instead',
- rerender,
- );
+ const rerender = (component: React.ReactElement) => {
+ void act(() => {
+ renderer.render(wrap(component));
+ });
};
+
const rerenderAsync = async (component: React.ReactElement) => {
// eslint-disable-next-line require-await
await act(async () => {
@@ -62,11 +67,11 @@ function buildRenderResult(
};
const unmount = () => {
- throw new ErrorWithStack(
- '"unmount()" is not supported when using "renderAsync" use "await unmountAsync()" instead',
- unmount,
- );
+ void act(() => {
+ renderer.unmount();
+ });
};
+
const unmountAsync = async () => {
// eslint-disable-next-line require-await
await act(async () => {
@@ -74,23 +79,33 @@ function buildRenderResult(
});
};
+ const toJSON = (): JsonElement | null => {
+ const json = renderer.container.toJSON();
+ if (json?.children?.length === 0) {
+ return null;
+ }
+
+ if (json?.children?.length === 1 && typeof json.children[0] !== 'string') {
+ return json.children[0];
+ }
+
+ return json;
+ };
+
addToCleanupQueue(unmountAsync);
const result = {
...getQueriesForElement(renderer.container),
rerender,
- rerenderAsync,
- update: rerender, // alias for `rerender`
- updateAsync: rerenderAsync, // alias for `rerenderAsync`
+ update: rerender, // alias for 'rerender'
unmount,
- unmountAsync,
- toJSON: () => renderer.container.toJSON(),
+ toJSON,
debug: makeDebug(renderer),
get container(): HostElement {
return renderer.container;
},
get root(): HostElement | null {
- const firstChild = container.children[0];
+ const firstChild = renderer.container.children[0];
if (typeof firstChild === 'string') {
throw new Error(
'Invariant Violation: Root element must be a host element. Detected attempt to render a string within the root element.',
@@ -101,7 +116,12 @@ function buildRenderResult(
},
};
- setRenderResult(result);
+ setRenderResult({
+ ...result,
+ rerender: rerenderAsync,
+ update: rerenderAsync,
+ unmount: unmountAsync,
+ });
return result;
}
diff --git a/src/user-event/__tests__/clear.test.tsx b/src/user-event/__tests__/clear.test.tsx
index 712e73dfe..ecfeac203 100644
--- a/src/user-event/__tests__/clear.test.tsx
+++ b/src/user-event/__tests__/clear.test.tsx
@@ -9,10 +9,10 @@ beforeEach(() => {
jest.useRealTimers();
});
-function renderTextInputWithToolkit(props: TextInputProps = {}) {
+async function renderTextInputWithToolkit(props: TextInputProps = {}) {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
it('supports basic case', async () => {
jest.spyOn(Date, 'now').mockImplementation(() => 100100100100);
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello!',
});
@@ -64,7 +64,7 @@ describe('clear()', () => {
it.each(['modern', 'legacy'])('works with %s fake timers', async (type) => {
jest.useFakeTimers({ legacyFakeTimers: type === 'legacy' });
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello!',
});
@@ -84,7 +84,7 @@ describe('clear()', () => {
});
it('supports defaultValue prop', async () => {
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
defaultValue: 'Hello Default!',
});
@@ -106,7 +106,7 @@ describe('clear()', () => {
});
it('does respect editable prop', async () => {
- const { textInput } = renderTextInputWithToolkit({
+ const { textInput } = await renderTextInputWithToolkit({
value: 'Hello!',
editable: false,
});
@@ -118,7 +118,7 @@ describe('clear()', () => {
});
it('does respect pointer-events prop', async () => {
- const { textInput } = renderTextInputWithToolkit({
+ const { textInput } = await renderTextInputWithToolkit({
value: 'Hello!',
pointerEvents: 'none',
});
@@ -130,7 +130,7 @@ describe('clear()', () => {
});
it('supports multiline', async () => {
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello World!\nHow are you?',
multiline: true,
});
@@ -155,7 +155,7 @@ describe('clear()', () => {
it('works when not all events have handlers', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
});
it('does NOT work on View', async () => {
- render();
+ await render();
const user = userEvent.setup();
await expect(
@@ -187,7 +187,7 @@ describe('clear()', () => {
it('does NOT bubble up', async () => {
const parentHandler = jest.fn();
- render(
+ await render(
{
});
it('sets native state value for unmanaged text inputs', async () => {
- render();
+ await render();
const user = userEvent.setup();
const input = screen.getByTestId('input');
diff --git a/src/user-event/__tests__/paste.test.tsx b/src/user-event/__tests__/paste.test.tsx
index cf254a1ad..47534f39e 100644
--- a/src/user-event/__tests__/paste.test.tsx
+++ b/src/user-event/__tests__/paste.test.tsx
@@ -9,10 +9,10 @@ beforeEach(() => {
jest.useRealTimers();
});
-function renderTextInputWithToolkit(props: TextInputProps = {}) {
+async function renderTextInputWithToolkit(props: TextInputProps = {}) {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
it('paste on empty text input', async () => {
jest.spyOn(Date, 'now').mockImplementation(() => 100100100100);
- const { textInput, events } = renderTextInputWithToolkit();
+ const { textInput, events } = await renderTextInputWithToolkit();
const user = userEvent.setup();
await user.paste(textInput, 'Hi!');
@@ -61,7 +61,7 @@ describe('paste()', () => {
it('paste on filled text input', async () => {
jest.spyOn(Date, 'now').mockImplementation(() => 100100100100);
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello!',
});
@@ -83,7 +83,7 @@ describe('paste()', () => {
it.each(['modern', 'legacy'])('works with %s fake timers', async (type) => {
jest.useFakeTimers({ legacyFakeTimers: type === 'legacy' });
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello!',
});
@@ -102,7 +102,7 @@ describe('paste()', () => {
});
it('supports defaultValue prop', async () => {
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
defaultValue: 'Hello Default!',
});
@@ -123,7 +123,7 @@ describe('paste()', () => {
});
it('does respect editable prop', async () => {
- const { textInput } = renderTextInputWithToolkit({
+ const { textInput } = await renderTextInputWithToolkit({
value: 'Hello!',
editable: false,
});
@@ -135,7 +135,7 @@ describe('paste()', () => {
});
it('does respect pointer-events prop', async () => {
- const { textInput } = renderTextInputWithToolkit({
+ const { textInput } = await renderTextInputWithToolkit({
value: 'Hello!',
pointerEvents: 'none',
});
@@ -147,7 +147,7 @@ describe('paste()', () => {
});
it('supports multiline', async () => {
- const { textInput, events } = renderTextInputWithToolkit({
+ const { textInput, events } = await renderTextInputWithToolkit({
value: 'Hello World!\nHow are you?',
multiline: true,
});
@@ -171,7 +171,7 @@ describe('paste()', () => {
it('works when not all events have handlers', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
});
it('does NOT work on View', async () => {
- render();
+ await render();
const user = userEvent.setup();
await expect(
@@ -203,7 +203,7 @@ describe('paste()', () => {
it('does NOT bubble up', async () => {
const parentHandler = jest.fn();
- render(
+ await render(
{
});
it('sets native state value for unmanaged text inputs', async () => {
- render();
+ await render();
const user = userEvent.setup();
const input = screen.getByTestId('input');
diff --git a/src/user-event/press/__tests__/longPress.real-timers.test.tsx b/src/user-event/press/__tests__/longPress.real-timers.test.tsx
index 656fc3c0e..8f54cb22e 100644
--- a/src/user-event/press/__tests__/longPress.real-timers.test.tsx
+++ b/src/user-event/press/__tests__/longPress.real-timers.test.tsx
@@ -15,7 +15,7 @@ describe('userEvent.longPress with real timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
test('works on TouchableOpacity', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -45,7 +45,7 @@ describe('userEvent.longPress with real timers', () => {
test('works on TouchableHighlight', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -58,7 +58,7 @@ describe('userEvent.longPress with real timers', () => {
test('works on Text', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
const mockOnLongPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -92,7 +92,7 @@ describe('userEvent.longPress with real timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -111,7 +111,7 @@ describe('userEvent.longPress with real timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -127,7 +127,7 @@ describe('userEvent.longPress with real timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -141,7 +141,7 @@ describe('userEvent.longPress with real timers', () => {
test('longPress is accessible directly in userEvent', async () => {
const mockOnLongPress = jest.fn();
- render(
+ await render(
press me
,
diff --git a/src/user-event/press/__tests__/longPress.test.tsx b/src/user-event/press/__tests__/longPress.test.tsx
index 91267bb9d..23c31aae2 100644
--- a/src/user-event/press/__tests__/longPress.test.tsx
+++ b/src/user-event/press/__tests__/longPress.test.tsx
@@ -15,7 +15,7 @@ describe('userEvent.longPress with fake timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
test('works on TouchableOpacity', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -46,7 +46,7 @@ describe('userEvent.longPress with fake timers', () => {
test('works on TouchableHighlight', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -59,7 +59,7 @@ describe('userEvent.longPress with fake timers', () => {
test('works on Text', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
const { logEvent, events } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -93,7 +93,7 @@ describe('userEvent.longPress with fake timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -112,7 +112,7 @@ describe('userEvent.longPress with fake timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -128,7 +128,7 @@ describe('userEvent.longPress with fake timers', () => {
const mockOnPress = jest.fn();
const user = userEvent.setup();
- render(
+ await render(
press me
,
@@ -142,7 +142,7 @@ describe('userEvent.longPress with fake timers', () => {
test('longPress is accessible directly in userEvent', async () => {
const mockOnLongPress = jest.fn();
- render(
+ await render(
press me
,
@@ -157,7 +157,7 @@ describe('userEvent.longPress with fake timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
test('works on TouchableOpacity', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -58,7 +58,7 @@ describe('userEvent.press with real timers', () => {
test('works on TouchableHighlight', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -71,7 +71,7 @@ describe('userEvent.press with real timers', () => {
test('works on Text', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('works on TextInput', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('works on Button', async () => {
const { events, logEvent } = createEventLogger();
- render();
+ await render();
await userEvent.press(screen.getByText('press me'));
expect(getEventsNames(events)).toEqual(['press']);
@@ -114,7 +114,7 @@ describe('userEvent.press with real timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
test('crawls up in the tree to find an element that responds to touch events', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -227,7 +227,7 @@ describe('userEvent.press with real timers', () => {
test('does not call onLongPress', async () => {
const mockOnLongPress = jest.fn();
- render(
+ await render(
press me
,
@@ -240,7 +240,7 @@ describe('userEvent.press with real timers', () => {
test('does not trigger on disabled Text', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('does not trigger on Text with disabled pointer events', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('does not call onPressIn and onPressOut on non editable TextInput', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('does not call onPressIn and onPressOut on TextInput with pointer events disabled', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('press is accessible directly in userEvent', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
diff --git a/src/user-event/press/__tests__/press.test.tsx b/src/user-event/press/__tests__/press.test.tsx
index e4535ddbb..9b530f463 100644
--- a/src/user-event/press/__tests__/press.test.tsx
+++ b/src/user-event/press/__tests__/press.test.tsx
@@ -23,7 +23,7 @@ describe('userEvent.press with fake timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
test('works on TouchableOpacity', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -54,7 +54,7 @@ describe('userEvent.press with fake timers', () => {
test('works on TouchableHighlight', async () => {
const mockOnPress = jest.fn();
- render(
+ await render(
press me
,
@@ -67,7 +67,7 @@ describe('userEvent.press with fake timers', () => {
test('works on Text', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('works on TextInput', async () => {
const { events, logEvent } = createEventLogger();
- render(
+ await render(
{
test('works on Button', async () => {
const { events, logEvent } = createEventLogger();
- render();
+ await render();
await userEvent.press(screen.getByText('press me'));
expect(getEventsNames(events)).toEqual(['press']);
@@ -110,7 +110,7 @@ describe('userEvent.press with fake timers', () => {
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(
{
const { events, logEvent } = createEventLogger();
const user = userEvent.setup();
- render(
+ await render(