diff --git a/codemods/v14-async-functions/tests/fixtures/skip-variants/expected.tsx b/codemods/v14-async-functions/tests/fixtures/skip-variants/expected.tsx
index d5f15efa2..96c73ea28 100644
--- a/codemods/v14-async-functions/tests/fixtures/skip-variants/expected.tsx
+++ b/codemods/v14-async-functions/tests/fixtures/skip-variants/expected.tsx
@@ -2,8 +2,6 @@ import {
render,
act,
renderHook,
- unsafe_act,
- unsafe_renderHookSync,
} from '@testing-library/react-native';
test('skips unsafe variants', async () => {
@@ -13,13 +11,7 @@ test('skips unsafe variants', async () => {
// Should be transformed
});
- unsafe_act(() => {
- // Should NOT be transformed
- });
-
const { result } = await renderHook(() => ({ value: 42 }));
- unsafe_renderHookSync(() => ({ value: 43 }));
-
await render();
});
diff --git a/codemods/v14-async-functions/tests/fixtures/skip-variants/input.tsx b/codemods/v14-async-functions/tests/fixtures/skip-variants/input.tsx
index d44c68977..897274e7b 100644
--- a/codemods/v14-async-functions/tests/fixtures/skip-variants/input.tsx
+++ b/codemods/v14-async-functions/tests/fixtures/skip-variants/input.tsx
@@ -2,8 +2,6 @@ import {
render,
act,
renderHook,
- unsafe_act,
- unsafe_renderHookSync,
renderAsync,
} from '@testing-library/react-native';
@@ -14,13 +12,7 @@ test('skips unsafe variants', async () => {
// Should be transformed
});
- unsafe_act(() => {
- // Should NOT be transformed
- });
-
const { result } = renderHook(() => ({ value: 42 }));
- unsafe_renderHookSync(() => ({ value: 43 }));
-
await renderAsync();
});
diff --git a/src/__tests__/__snapshots__/unsafe-render-sync.test.tsx.snap b/src/__tests__/__snapshots__/unsafe-render-sync.test.tsx.snap
deleted file mode 100644
index 5a844c697..000000000
--- a/src/__tests__/__snapshots__/unsafe-render-sync.test.tsx.snap
+++ /dev/null
@@ -1,39 +0,0 @@
-// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
-
-exports[`toJSON renders host output 1`] = `
-
-
- press me
-
-
-`;
diff --git a/src/__tests__/cleanup.test.tsx b/src/__tests__/cleanup.test.tsx
index f6036d028..13f57b91c 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 { cleanup, render, unsafe_renderSync } from '../pure';
+import { cleanup, render } from '../pure';
class Test extends React.Component<{ onUnmount: () => void }> {
componentWillUnmount() {
@@ -24,14 +24,3 @@ test('cleanup after render', async () => {
await cleanup();
expect(fn).toHaveBeenCalledTimes(2);
});
-
-test('cleanup after unsafe_renderSync', async () => {
- const fn = jest.fn();
-
- unsafe_renderSync();
- unsafe_renderSync();
- expect(fn).not.toHaveBeenCalled();
-
- await cleanup();
- expect(fn).toHaveBeenCalledTimes(2);
-});
diff --git a/src/__tests__/unsafe-fire-event-sync.test.tsx b/src/__tests__/unsafe-fire-event-sync.test.tsx
deleted file mode 100644
index 7a696ad2a..000000000
--- a/src/__tests__/unsafe-fire-event-sync.test.tsx
+++ /dev/null
@@ -1,581 +0,0 @@
-import * as React from 'react';
-import {
- PanResponder,
- Pressable,
- ScrollView,
- Text,
- TextInput,
- TouchableOpacity,
- View,
-} from 'react-native';
-
-import { screen, unsafe_fireEventSync, unsafe_renderSync } from '..';
-
-type OnPressComponentProps = {
- onPress: () => void;
- text: string;
-};
-const OnPressComponent = ({ onPress, text }: OnPressComponentProps) => (
-
-
- {text}
-
-
-);
-
-type CustomEventComponentProps = {
- onCustomEvent: () => void;
-};
-const CustomEventComponent = ({ onCustomEvent }: CustomEventComponentProps) => (
-
- Custom event component
-
-);
-
-type MyCustomButtonProps = {
- handlePress: () => void;
- text: string;
-};
-
-const MyCustomButton = ({ handlePress, text }: MyCustomButtonProps) => (
-
-);
-
-type CustomEventComponentWithCustomNameProps = {
- handlePress: () => void;
-};
-
-const CustomEventComponentWithCustomName = ({
- handlePress,
-}: CustomEventComponentWithCustomNameProps) => (
-
-);
-
-describe('unsafe_fireEventSync', () => {
- test('should invoke specified event', () => {
- const onPressMock = jest.fn();
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByText('Press me'), 'press');
-
- expect(onPressMock).toHaveBeenCalled();
- });
-
- test('should invoke specified event on parent element', () => {
- const onPressMock = jest.fn();
- const text = 'New press text';
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByText(text), 'press');
- expect(onPressMock).toHaveBeenCalled();
- });
-
- test('should invoke event with custom name', () => {
- const handlerMock = jest.fn();
- const EVENT_DATA = 'event data';
-
- unsafe_renderSync(
-
-
- ,
- );
-
- unsafe_fireEventSync(screen.getByText('Custom event component'), 'customEvent', EVENT_DATA);
-
- expect(handlerMock).toHaveBeenCalledWith(EVENT_DATA);
- });
-});
-
-test('unsafe_fireEventSync.press', () => {
- const onPressMock = jest.fn();
- const text = 'Fireevent press';
- const eventData = {
- nativeEvent: {
- pageX: 20,
- pageY: 30,
- },
- };
- unsafe_renderSync();
-
- unsafe_fireEventSync.press(screen.getByText(text), eventData);
-
- expect(onPressMock).toHaveBeenCalledWith(eventData);
-});
-
-test('unsafe_fireEventSync.scroll', () => {
- const onScrollMock = jest.fn();
- const eventData = {
- nativeEvent: {
- contentOffset: {
- y: 200,
- },
- },
- };
-
- unsafe_renderSync(
-
- XD
- ,
- );
-
- unsafe_fireEventSync.scroll(screen.getByText('XD'), eventData);
-
- expect(onScrollMock).toHaveBeenCalledWith(eventData);
-});
-
-test('unsafe_fireEventSync.changeText', () => {
- const onChangeTextMock = jest.fn();
-
- unsafe_renderSync(
-
-
- ,
- );
-
- const input = screen.getByPlaceholderText('Customer placeholder');
- unsafe_fireEventSync.changeText(input, 'content');
- expect(onChangeTextMock).toHaveBeenCalledWith('content');
-});
-
-it('sets native state value for unmanaged text inputs', () => {
- unsafe_renderSync();
-
- const input = screen.getByTestId('input');
- expect(input).toHaveDisplayValue('');
-
- unsafe_fireEventSync.changeText(input, 'abc');
- expect(input).toHaveDisplayValue('abc');
-});
-
-test('custom component with custom event name', () => {
- const handlePress = jest.fn();
-
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByText('Custom component'), 'handlePress');
-
- expect(handlePress).toHaveBeenCalled();
-});
-
-test('event with multiple handler parameters', () => {
- const handlePress = jest.fn();
-
- unsafe_renderSync();
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- unsafe_fireEventSync.press(screen.getByText('Trigger'));
- expect(handlePress).not.toHaveBeenCalled();
-});
-
-test('should not fire on disabled Pressable', () => {
- const handlePress = jest.fn();
- unsafe_renderSync(
-
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Trigger
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
-
- Trigger
-
-
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
-
- Trigger
-
-
- ,
- );
-
- 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();
- unsafe_renderSync();
-
- 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();
- unsafe_renderSync(
- ,
- );
-
- 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();
- unsafe_renderSync();
-
- 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();
- unsafe_renderSync(
- ,
- );
-
- unsafe_fireEventSync(screen.getByTestId('view'), 'layout');
- expect(onLayout).toHaveBeenCalled();
-});
-
-// This test if pointerEvents="box-only" on composite `Pressable` is blocking
-// the 'press' event on host View rendered by pressable.
-test('should fire on Pressable with pointerEvents="box-only" in props', () => {
- const onPress = jest.fn();
- unsafe_renderSync();
-
- unsafe_fireEventSync.press(screen.getByTestId('pressable'));
- expect(onPress).toHaveBeenCalled();
-});
-
-test('should fire on Pressable with pointerEvents="box-only" in styles', () => {
- const onPress = jest.fn();
- unsafe_renderSync(
- ,
- );
-
- 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();
- unsafe_renderSync(
-
-
- Inner Trigger
-
- ,
- );
-
- unsafe_fireEventSync.press(screen.getByText('Inner Trigger'));
- expect(handleInnerPress).not.toHaveBeenCalled();
- expect(handleOuterPress).toHaveBeenCalledTimes(1);
-});
-
-test('should pass event up on disabled Pressable', () => {
- const handleInnerPress = jest.fn();
- const handleOuterPress = jest.fn();
- unsafe_renderSync(
-
-
- Inner Trigger
-
- ,
- );
-
- unsafe_fireEventSync.press(screen.getByText('Inner Trigger'));
- expect(handleInnerPress).not.toHaveBeenCalled();
- expect(handleOuterPress).toHaveBeenCalledTimes(1);
-});
-
-type TestComponentProps = {
- onPress: () => void;
- disabled?: boolean;
-};
-const TestComponent = ({ onPress }: TestComponentProps) => {
- return (
-
- Trigger Test
-
- );
-};
-
-test('is not fooled by non-native disabled prop', () => {
- const handlePress = jest.fn();
- unsafe_renderSync();
-
- unsafe_fireEventSync.press(screen.getByText('Trigger Test'));
- expect(handlePress).toHaveBeenCalledTimes(1);
-});
-
-type TestChildTouchableComponentProps = {
- onPress: () => void;
- someProp: boolean;
-};
-
-function TestChildTouchableComponent({ onPress, someProp }: TestChildTouchableComponentProps) {
- return (
-
-
- Trigger
-
-
- );
-}
-
-test('is not fooled by non-responder wrapping host elements', () => {
- const handlePress = jest.fn();
-
- unsafe_renderSync(
-
-
- ,
- );
-
- unsafe_fireEventSync.press(screen.getByText('Trigger'));
- expect(handlePress).not.toHaveBeenCalled();
-});
-
-type TestDraggableComponentProps = { onDrag: () => void };
-
-function TestDraggableComponent({ onDrag }: TestDraggableComponentProps) {
- const responderHandlers = PanResponder.create({
- onMoveShouldSetPanResponder: (_evt, _gestureState) => true,
- onPanResponderMove: onDrag,
- }).panHandlers;
-
- return (
-
- Trigger
-
- );
-}
-
-test('has only onMove', () => {
- const handleDrag = jest.fn();
-
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByText('Trigger'), 'responderMove', {
- touchHistory: { mostRecentTimeStamp: '2', touchBank: [] },
- });
- expect(handleDrag).toHaveBeenCalled();
-});
-
-// 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();
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByTestId('test-id'), 'onScrollBeginDrag');
- expect(onScrollBeginDragSpy).toHaveBeenCalled();
- });
-
- test('triggers onScrollEndDrag', () => {
- const onScrollEndDragSpy = jest.fn();
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByTestId('test-id'), 'onScrollEndDrag');
- expect(onScrollEndDragSpy).toHaveBeenCalled();
- });
-
- test('triggers onMomentumScrollBegin', () => {
- const onMomentumScrollBeginSpy = jest.fn();
- unsafe_renderSync(
- ,
- );
-
- unsafe_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollBegin');
- expect(onMomentumScrollBeginSpy).toHaveBeenCalled();
- });
-
- test('triggers onMomentumScrollEnd', () => {
- const onMomentumScrollEndSpy = jest.fn();
- unsafe_renderSync();
-
- unsafe_fireEventSync(screen.getByTestId('test-id'), 'onMomentumScrollEnd');
- expect(onMomentumScrollEndSpy).toHaveBeenCalled();
- });
-});
-
-test('should handle unmounted elements gracefully', () => {
- const onPress = jest.fn();
- const { rerender } = unsafe_renderSync(
-
- Test
- ,
- );
-
- const element = screen.getByText('Test');
- rerender();
-
- // Firing event on unmounted element should not crash
- unsafe_fireEventSync.press(element);
- expect(onPress).not.toHaveBeenCalled();
-});
diff --git a/src/__tests__/unsafe-render-hook-sync.test.tsx b/src/__tests__/unsafe-render-hook-sync.test.tsx
deleted file mode 100644
index fd95f491d..000000000
--- a/src/__tests__/unsafe-render-hook-sync.test.tsx
+++ /dev/null
@@ -1,135 +0,0 @@
-import type { ReactNode } from 'react';
-import * as React from 'react';
-
-import { unsafe_renderHookSync } from '../pure';
-
-test('renders hook and returns committed result', () => {
- const { result } = unsafe_renderHookSync(() => {
- const [state, setState] = React.useState(1);
-
- React.useEffect(() => {
- setState(2);
- }, []);
-
- return [state, setState];
- });
-
- expect(result.current).toEqual([2, expect.any(Function)]);
-});
-
-test('works with wrapper option', () => {
- const Context = React.createContext('default');
- function Wrapper({ children }: { children: ReactNode }) {
- return {children};
- }
- const { result } = unsafe_renderHookSync(
- () => {
- return React.useContext(Context);
- },
- {
- wrapper: Wrapper,
- },
- );
-
- expect(result.current).toEqual('provided');
-});
-
-test('works with initialProps option', () => {
- const { result } = unsafe_renderHookSync(
- (props: { branch: 'left' | 'right' }) => {
- const [left, setLeft] = React.useState('left');
- const [right, setRight] = React.useState('right');
-
- switch (props.branch) {
- case 'left':
- return [left, setLeft];
- case 'right':
- return [right, setRight];
- default:
- throw new Error('No Props passed. This is a bug in the implementation');
- }
- },
- { initialProps: { branch: 'left' } },
- );
-
- expect(result.current).toEqual(['left', expect.any(Function)]);
-});
-
-test('works without initialProps option', () => {
- function useTestHook() {
- const [count, setCount] = React.useState(0);
- return { count, setCount };
- }
-
- const { result } = unsafe_renderHookSync(useTestHook);
- expect(result.current.count).toBe(0);
-});
-
-test('rerender updates hook with new props', () => {
- const { result, rerender } = unsafe_renderHookSync(
- (props: { branch: 'left' | 'right' }) => {
- const [left, setLeft] = React.useState('left');
- const [right, setRight] = React.useState('right');
-
- switch (props.branch) {
- case 'left':
- return [left, setLeft];
- case 'right':
- return [right, setRight];
- default:
- throw new Error('No Props passed. This is a bug in the implementation');
- }
- },
- { initialProps: { branch: 'left' } },
- );
-
- expect(result.current).toEqual(['left', expect.any(Function)]);
-
- rerender({ branch: 'right' });
- expect(result.current).toEqual(['right', expect.any(Function)]);
-});
-
-test('unmount triggers cleanup effects', () => {
- let cleanupCalled = false;
-
- function useTestHook() {
- React.useEffect(() => {
- return () => {
- cleanupCalled = true;
- };
- }, []);
-
- return 'test';
- }
-
- const { unmount } = unsafe_renderHookSync(useTestHook);
- expect(cleanupCalled).toBe(false);
-
- unmount();
- expect(cleanupCalled).toBe(true);
-});
-
-function useMyHook(param: T) {
- return { param };
-}
-
-test('props type is inferred correctly when initial props is defined', () => {
- const { result, rerender } = unsafe_renderHookSync((num: number) => useMyHook(num), {
- initialProps: 5,
- });
- expect(result.current.param).toBe(5);
-
- rerender(6);
- expect(result.current.param).toBe(6);
-});
-
-test('props type is inferred correctly when initial props is explicitly undefined', () => {
- const { result, rerender } = unsafe_renderHookSync((num: number | undefined) => useMyHook(num), {
- initialProps: undefined,
- });
-
- expect(result.current.param).toBeUndefined();
-
- rerender(6);
- expect(result.current.param).toBe(6);
-});
diff --git a/src/__tests__/unsafe-render-sync.test.tsx b/src/__tests__/unsafe-render-sync.test.tsx
deleted file mode 100644
index 38596dd94..000000000
--- a/src/__tests__/unsafe-render-sync.test.tsx
+++ /dev/null
@@ -1,185 +0,0 @@
-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/act.ts b/src/act.ts
index 404e5c643..29c7a6e86 100644
--- a/src/act.ts
+++ b/src/act.ts
@@ -66,10 +66,10 @@ function withGlobalActEnvironment(actImplementation: ReactAct) {
};
}
-export const unsafe_act = withGlobalActEnvironment(reactAct) as ReactAct;
+const _act = withGlobalActEnvironment(reactAct) as ReactAct;
export function act(callback: () => T | Promise): Promise {
- return unsafe_act(async () => await callback());
+ return _act(async () => await callback());
}
export { getIsReactActEnvironment, setIsReactActEnvironment as setReactActEnvironment };
diff --git a/src/fire-event.ts b/src/fire-event.ts
index c069c7944..96276643d 100644
--- a/src/fire-event.ts
+++ b/src/fire-event.ts
@@ -7,7 +7,7 @@ import type {
} from 'react-native';
import type { Fiber, HostElement } from 'test-renderer';
-import { act, unsafe_act } from './act';
+import { act } from './act';
import type { EventHandler } from './event-handler';
import { getEventHandlerFromProps } from './event-handler';
import { isElementMounted, isHostElement } from './helpers/component-tree';
@@ -155,40 +155,7 @@ fireEvent.changeText = async (element: HostElement, ...data: unknown[]) =>
fireEvent.scroll = async (element: HostElement, ...data: unknown[]) =>
await fireEvent(element, 'scroll', ...data);
-/** @deprecated - Use async `fireEvent` instead. */
-function unsafe_fireEventSync(element: HostElement, eventName: EventName, ...data: unknown[]) {
- if (!isElementMounted(element)) {
- return;
- }
-
- setNativeStateIfNeeded(element, eventName, data[0]);
-
- const handler = findEventHandler(element, eventName);
- if (!handler) {
- return;
- }
-
- let returnValue;
- void unsafe_act(() => {
- returnValue = handler(...data);
- });
-
- return returnValue;
-}
-
-/** @deprecated - Use async `fireEvent.press` instead. */
-unsafe_fireEventSync.press = (element: HostElement, ...data: unknown[]) =>
- unsafe_fireEventSync(element, 'press', ...data);
-
-/** @deprecated - Use async `fireEvent.changeText` instead. */
-unsafe_fireEventSync.changeText = (element: HostElement, ...data: unknown[]) =>
- unsafe_fireEventSync(element, 'changeText', ...data);
-
-/** @deprecated - Use async `fireEvent.scroll` instead. */
-unsafe_fireEventSync.scroll = (element: HostElement, ...data: unknown[]) =>
- unsafe_fireEventSync(element, 'scroll', ...data);
-
-export { fireEvent, unsafe_fireEventSync };
+export { fireEvent };
const scrollEventNames = new Set([
'scroll',
diff --git a/src/pure.ts b/src/pure.ts
index 8ae817104..cdc62704c 100644
--- a/src/pure.ts
+++ b/src/pure.ts
@@ -1,8 +1,7 @@
-export { act, unsafe_act } from './act';
+export { act } from './act';
export { cleanup } from './cleanup';
-export { fireEvent, unsafe_fireEventSync } from './fire-event';
+export { fireEvent } 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';
@@ -10,12 +9,11 @@ export { within, getQueriesForElement } from './within';
export { configure, resetToDefaults } from './config';
export { isHiddenFromAccessibility, isInaccessible } from './helpers/accessibility';
export { getDefaultNormalizer } from './matches';
-export { renderHook, unsafe_renderHookSync } from './render-hook';
+export { renderHook } from './render-hook';
export { screen } from './screen';
export { userEvent } from './user-event';
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 { RenderHookOptions, RenderHookResult } from './render-hook';
export type { Config } from './config';
export type { UserEventConfig } from './user-event';
diff --git a/src/render-hook.tsx b/src/render-hook.tsx
index b04e61dae..564530c35 100644
--- a/src/render-hook.tsx
+++ b/src/render-hook.tsx
@@ -2,7 +2,6 @@ import * as React from 'react';
import { render } from './render';
import type { RefObject } from './types';
-import { unsafe_renderSync } from './unsafe-render-sync';
export type RenderHookResult = {
result: RefObject;
@@ -10,13 +9,6 @@ export type RenderHookResult = {
unmount: () => Promise;
};
-/** @deprecated - Use `renderHook` and `RenderHookResult` instead. */
-export type RenderHookSyncResult = {
- result: RefObject;
- rerender: (props: Props) => void;
- unmount: () => void;
-};
-
export type RenderHookOptions = {
/**
* The initial props to pass to the hook.
@@ -59,33 +51,3 @@ export async function renderHook(
unmount,
};
}
-
-/** @deprecated - Use async `renderHook` instead. */
-export function unsafe_renderHookSync(
- hookToRender: (props: Props) => Result,
- options?: RenderHookOptions>,
-): RenderHookSyncResult {
- const result = React.createRef() as RefObject;
-
- function HookContainer({ hookProps }: { hookProps: Props }) {
- const renderResult = hookToRender(hookProps);
- React.useEffect(() => {
- result.current = renderResult;
- });
-
- return null;
- }
-
- const { initialProps, ...renderOptions } = options ?? {};
- const { rerender: rerenderComponent, unmount } = unsafe_renderSync(
- // @ts-expect-error since option can be undefined, initialProps can be undefined when it should'nt
- ,
- renderOptions,
- );
-
- return {
- result: result,
- rerender: (hookProps: Props) => rerenderComponent(),
- unmount,
- };
-}
diff --git a/src/unsafe-render-sync.tsx b/src/unsafe-render-sync.tsx
deleted file mode 100644
index 7966cf2a9..000000000
--- a/src/unsafe-render-sync.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import * as React from 'react';
-import {
- createRoot,
- type HostElement,
- type JsonElement,
- type Root,
- type RootOptions,
-} from 'test-renderer';
-
-import { act, unsafe_act } from './act';
-import { addToCleanupQueue } from './cleanup';
-import { getConfig } from './config';
-import type { DebugOptions } from './helpers/debug';
-import { debug } from './helpers/debug';
-import { HOST_TEXT_NAMES } from './helpers/host-component-names';
-import { setRenderResult } from './screen';
-import { getQueriesForElement } from './within';
-
-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.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- wrapper?: React.ComponentType;
-
- createNodeMock?: (element: React.ReactElement) => object;
-}
-
-/**
- * @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 function unsafe_renderSync(
- component: React.ReactElement,
- options: RenderSyncOptions = {},
-) {
- return renderInternal(component, options);
-}
-
-export type RenderSyncResult = ReturnType;
-
-export function renderInternal(component: React.ReactElement, options?: RenderSyncOptions) {
- const { wrapper: Wrapper, createNodeMock } = options || {};
-
- const rendererOptions: RootOptions = {
- textComponentTypes: HOST_TEXT_NAMES,
- publicTextComponentTypes: ['Text'],
- createNodeMock,
- };
-
- const wrap = (element: React.ReactElement) => (Wrapper ? {element} : element);
-
- const renderer = createRoot(rendererOptions);
-
- unsafe_act(() => {
- renderer.render(wrap(component));
- });
-
- const rerender = (component: React.ReactElement) => {
- unsafe_act(() => {
- renderer.render(wrap(component));
- });
- };
-
- const rerenderAsync = async (component: React.ReactElement) => {
- await act(() => {
- renderer.render(wrap(component));
- });
- };
-
- const unmount = () => {
- unsafe_act(() => {
- renderer.unmount();
- });
- };
-
- const unmountAsync = async () => {
- await act(() => {
- renderer.unmount();
- });
- };
-
- 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,
- update: rerender, // alias for 'rerender'
- unmount,
- toJSON,
- debug: makeDebug(renderer),
- get container(): HostElement {
- return renderer.container;
- },
- get root(): HostElement | null {
- 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.',
- );
- }
-
- return firstChild;
- },
- };
-
- setRenderResult({
- ...result,
- rerender: rerenderAsync,
- update: rerenderAsync,
- unmount: unmountAsync,
- });
-
- return result;
-}
-
-export type DebugFunction = (options?: DebugOptions) => void;
-
-function makeDebug(renderer: Root): DebugFunction {
- function debugImpl(options?: DebugOptions) {
- const { defaultDebugOptions } = getConfig();
- const debugOptions = { ...defaultDebugOptions, ...options };
- const json = renderer.container.toJSON();
- if (json) {
- return debug(json, debugOptions);
- }
- }
- return debugImpl;
-}
diff --git a/website/docs/14.x/docs/api/events/fire-event.mdx b/website/docs/14.x/docs/api/events/fire-event.mdx
index 0feee2dda..287b99cd0 100644
--- a/website/docs/14.x/docs/api/events/fire-event.mdx
+++ b/website/docs/14.x/docs/api/events/fire-event.mdx
@@ -167,12 +167,3 @@ render(
await fireEvent.scroll(screen.getByText('scroll-view'), eventData);
```
-
-## `unsafe_fireEventSync` {#unsafe-fire-event-sync}
-
-```ts
-function unsafe_fireEventSync(element: HostElement, eventName: string, ...data: unknown[]): void;
-```
-
-Synchronous version of `fireEvent`. Deprecated and will be removed in future versions.
-Use only if you cannot use `await fireEvent` for some reason.
diff --git a/website/docs/14.x/docs/api/misc/other.mdx b/website/docs/14.x/docs/api/misc/other.mdx
index b6e1a1cb3..24c808049 100644
--- a/website/docs/14.x/docs/api/misc/other.mdx
+++ b/website/docs/14.x/docs/api/misc/other.mdx
@@ -52,28 +52,6 @@ it('should update state', async () => {
Consult our [Understanding Act function](docs/advanced/understanding-act.md) document for more understanding of its intricacies.
-## `unsafe_act`
-
-```ts
-function unsafe_act(callback: () => T | Promise): T | Thenable;
-```
-
-**⚠️ Deprecated**: This function is provided for migration purposes only. Use async `act` instead.
-
-The synchronous version of `act` that maintains the same behavior as v13. It returns immediately for sync callbacks or a thenable for async callbacks. This is not recommended for new code as it doesn't work well with React 19's async features.
-
-```ts
-// Deprecated - use act instead
-import { unsafe_act } from '@testing-library/react-native';
-
-it('should update state', () => {
- unsafe_act(() => {
- setState('new value');
- });
- expect(state).toBe('new value');
-});
-```
-
## `cleanup`
```ts
diff --git a/website/docs/14.x/docs/api/misc/render-hook.mdx b/website/docs/14.x/docs/api/misc/render-hook.mdx
index a590d3bfa..1afde0486 100644
--- a/website/docs/14.x/docs/api/misc/render-hook.mdx
+++ b/website/docs/14.x/docs/api/misc/render-hook.mdx
@@ -167,11 +167,3 @@ it('handles hook with suspense', async () => {
expect(result.current).toBe('resolved');
});
```
-
-## Migration from v13
-
-If you're migrating from React Native Testing Library v13, you may have existing tests using the synchronous `renderHook` API. To ease migration, we provide `unsafe_renderHookSync` which maintains the same synchronous behavior.
-
-**⚠️ Deprecated**: `unsafe_renderHookSync` is provided for migration purposes only. Use async `renderHook` instead.
-
-For detailed migration instructions, see the [v14 migration guide](../../migration/v14).
diff --git a/website/docs/14.x/docs/api/render.mdx b/website/docs/14.x/docs/api/render.mdx
index 7c1b7608f..5dd514c3e 100644
--- a/website/docs/14.x/docs/api/render.mdx
+++ b/website/docs/14.x/docs/api/render.mdx
@@ -66,43 +66,3 @@ See [this article](https://kentcdodds.com/blog/common-mistakes-with-react-testin
When using `render`, the lifecycle methods `rerender`, `update`, and `unmount` are async and must be awaited.
:::
-
-## `unsafe_renderSync` function {#unsafe-render-sync}
-
-:::warning Deprecated
-
-This function is deprecated and provided for migration purposes only. Use async `render` instead.
-
-:::
-
-```tsx
-function unsafe_renderSync(
- component: React.Element,
- options?: RenderSyncOptions
-): RenderSyncResult;
-```
-
-The `unsafe_renderSync` function is the synchronous version of [`render`](#render). It was the default `render` function in previous versions but is now deprecated in favor of the async `render` function.
-
-```jsx
-import { unsafe_renderSync, screen } from '@testing-library/react-native';
-
-test('sync component test', () => {
- unsafe_renderSync();
- expect(screen.getAllByRole('button', { name: 'start' })).toBeOnTheScreen();
-});
-```
-
-### Options
-
-`unsafe_renderSync` accepts the same options as `render`.
-
-### Result
-
-The `unsafe_renderSync` function returns the same queries and utilities as the [`screen`](docs/api/screen) object. We recommended using the `screen` object as more developer-friendly way.
-
-:::note Migration
-
-To migrate from `unsafe_renderSync` to `render`, see the [migration guide](../migration/v14#render-async-default).
-
-:::
diff --git a/website/docs/14.x/docs/guides/react-19.mdx b/website/docs/14.x/docs/guides/react-19.mdx
index c04b96f0c..c899b6cda 100644
--- a/website/docs/14.x/docs/guides/react-19.mdx
+++ b/website/docs/14.x/docs/guides/react-19.mdx
@@ -36,12 +36,6 @@ The main change is using [`render`](docs/api/render#render) which is now async b
2. Adding `await` before `render`
```tsx
-// Synchronous approach (deprecated in v14)
-test('my component', () => {
- unsafe_renderSync();
- expect(screen.getByText('Hello')).toBeOnTheScreen();
-});
-
// Async approach (React 19 ready, default in v14)
test('my component', async () => {
await render();
@@ -67,10 +61,10 @@ Use the async-ready APIs (`render`, User Event, Jest Matchers, etc.) from the st
You can migrate gradually:
-- **Existing tests** can use `unsafe_renderSync` for backward compatibility
+- **Existing tests** should be migrated to use async `render` (see migration guide)
- **New tests** should use async `render` (default in v14)
- **Tests with Suspense/`React.use()`** must use async `render`
### Migration
-See the [v14 migration guide](../migration/v14#render-async-default) for detailed migration steps from `unsafe_renderSync` to `render`.
+See the [v14 migration guide](../migration/v14#render-async-default) for detailed migration steps.
diff --git a/website/docs/14.x/docs/migration/v14.mdx b/website/docs/14.x/docs/migration/v14.mdx
index 8f05d0cc4..71aef82c6 100644
--- a/website/docs/14.x/docs/migration/v14.mdx
+++ b/website/docs/14.x/docs/migration/v14.mdx
@@ -105,7 +105,7 @@ For more details, see the [`screen` API documentation](/docs/api/screen#containe
### `render` is now async by default {#render-async-default}
-In v14, `render` is now async by default and returns a Promise. The previous synchronous `render` function has been renamed to `unsafe_renderSync`. This change makes it compatible with React 19, React Suspense, and `React.use()`.
+In v14, `render` is now async by default and returns a Promise. This change makes it compatible with React 19, React Suspense, and `React.use()`.
**Before (v13):**
@@ -129,44 +129,17 @@ it('should render component', async () => {
});
```
-#### Migration path
-
-To ease migration, we provide `unsafe_renderSync` which maintains the same synchronous behavior as v13. This allows you to migrate gradually.
-
-##### `unsafe_renderSync` {#unsafe-render-sync}
-
-```ts
-function unsafe_renderSync(
- component: React.Element,
- options?: RenderSyncOptions
-): RenderSyncResult;
-```
-
-**⚠️ Deprecated**: This function is provided for migration purposes only. Use async `render` instead.
-
-The synchronous version of `render` that returns immediately without awaiting React updates. This maintains backward compatibility with v13 tests but is not recommended for new code.
-
-```ts
-// Old v13 code (still works but deprecated)
-import { unsafe_renderSync } from '@testing-library/react-native';
-
-it('should render component', () => {
- unsafe_renderSync();
- expect(screen.getByText('Hello')).toBeOnTheScreen();
-});
-```
-
#### Step-by-step migration guide
-To migrate from `unsafe_renderSync` to `render`:
+To migrate from v13 `render` to v14 `render`:
##### 1. Add `async` to your test function
```ts
-// Before
+// Before (v13)
it('should render component', () => {
-// After
+// After (v14)
it('should render component', async () => {
```
@@ -273,67 +246,9 @@ it('should test hook', async () => {
});
```
-#### Migration path
-
-To ease migration, we provide `unsafe_renderHookSync` which maintains the same synchronous behavior as v13. This allows you to migrate gradually.
-
-##### `unsafe_renderHookSync` {#unsafe-render-hook-sync}
-
-```ts
-function unsafe_renderHookSync(
- hookFn: (props?: Props) => Result,
- options?: RenderHookOptions
-): RenderHookSyncResult;
-```
-
-**⚠️ Deprecated**: This function is provided for migration purposes only. Use async `renderHook` instead.
-
-The synchronous version of `renderHook` that returns immediately without awaiting React updates. This maintains backward compatibility with v13 tests but is not recommended for new code.
-
-```ts
-// Old v13 code (still works but deprecated)
-import { unsafe_renderHookSync } from '@testing-library/react-native';
-
-it('should increment count', () => {
- const { result, rerender } = unsafe_renderHookSync(() => useCount());
-
- expect(result.current.count).toBe(0);
- act(() => {
- result.current.increment();
- });
- expect(result.current.count).toBe(1);
-
- rerender();
-});
-```
-
-##### Result types
-
-**v13 (deprecated):**
-
-```ts
-interface RenderHookSyncResult {
- result: { current: Result };
- rerender: (props: Props) => void;
- unmount: () => void;
-}
-```
-
-**v14 (default):**
-
-```ts
-interface RenderHookResult {
- result: { current: Result };
- rerender: (props: Props) => Promise;
- unmount: () => Promise;
-}
-```
-
-**Note**: Both `RenderHookSyncResult` and `RenderHookResult` use `rerender` and `unmount` methods. The difference is that `RenderHookSyncResult` methods are synchronous (return `void`), while `RenderHookResult` methods are async (return `Promise`).
-
#### Step-by-step migration guide
-To migrate from `unsafe_renderHookSync` to `renderHook`:
+To migrate from v13 `renderHook` to v14 `renderHook`:
##### 1. Add `async` to your test function
@@ -348,10 +263,10 @@ it('should test hook', async () => {
##### 2. Await `renderHook`
```ts
-// Before
-const { result } = unsafe_renderHookSync(() => useMyHook());
+// Before (v13)
+const { result } = renderHook(() => useMyHook());
-// After
+// After (v14)
const { result } = await renderHook(() => useMyHook());
```
@@ -472,31 +387,6 @@ it('should press button', async () => {
});
```
-#### Migration path
-
-To ease migration, we provide `unsafe_fireEventSync` which maintains the same synchronous behavior as v13. This allows you to migrate gradually.
-
-##### `unsafe_fireEventSync` {#unsafe-fire-event-sync}
-
-```ts
-function unsafe_fireEventSync(element: HostElement, eventName: string, ...data: unknown[]): void;
-```
-
-**⚠️ Deprecated**: This function is provided for migration purposes only. Use async `fireEvent` instead.
-
-The synchronous version of `fireEvent` that returns immediately without awaiting React updates. This maintains backward compatibility with v13 tests but is not recommended for new code.
-
-```ts
-// Old v13 code (still works but deprecated)
-import { unsafe_fireEventSync } from '@testing-library/react-native';
-
-it('should press button', () => {
- render();
- unsafe_fireEventSync.press(screen.getByText('Press me'));
- expect(onPress).toHaveBeenCalled();
-});
-```
-
### Text string validation now enforced by default
In v14, Test Renderer automatically enforces React Native's requirement that text strings must be rendered within a `` component. This means the `unstable_validateStringsRenderedWithinText` option has been removed from `RenderOptions`, as this validation is now always enabled.
@@ -526,13 +416,12 @@ If you were relying on the previous behavior where strings could be rendered out
### `act` is now async by default
-In v14, `act` is now async by default and always returns a Promise. The previous synchronous `act` function has been renamed to `unsafe_act`. This change makes it compatible with React 19, React Suspense, and `React.use()`.
+In v14, `act` is now async by default and always returns a Promise. This change makes it compatible with React 19, React Suspense, and `React.use()`.
**What changed:**
- `act` now always returns a `Promise` instead of `T | Thenable`
-- `unsafe_act` is available for the old behavior (direct React.act wrapper)
-- Both `act` and `unsafe_act` are now named exports (no default export)
+- `act` is now a named export (no default export)
**Before (v13):**
@@ -564,35 +453,9 @@ it('should update state', async () => {
});
```
-#### Migration path
-
-To ease migration, we provide `unsafe_act` which maintains the same behavior as v13. This allows you to migrate gradually.
-
-##### `unsafe_act` {#unsafe-act}
-
-```ts
-function unsafe_act(callback: () => T | Promise): T | Thenable;
-```
-
-**⚠️ Deprecated**: This function is provided for migration purposes only. Use async `act` instead.
-
-The synchronous version of `act` that returns immediately for sync callbacks or a thenable for async callbacks. This maintains backward compatibility with v13 tests but is not recommended for new code.
-
-```ts
-// Old v13 code (still works but deprecated)
-import { unsafe_act } from '@testing-library/react-native';
-
-it('should update state', () => {
- unsafe_act(() => {
- setState('new value');
- });
- expect(state).toBe('new value');
-});
-```
-
#### Step-by-step migration guide
-To migrate from `unsafe_act` to `act`:
+To migrate from v13 `act` to v14 `act`:
##### 1. Update import statement