RNTL v14: Make render(), act(), renderHook(), and fireEvent() calls async
This codemod migrates your test files from React Native Testing Library v13 to v14 by transforming synchronous render(), act(), renderHook(), and fireEvent() calls to their async versions (await render(), await act(), await renderHook(), await fireEvent(), etc.) and making test functions async when needed.
What it does
- ✅ Transforms render() calls to await render() in test functions
- ✅ Transforms act() calls to await act() in test functions
- ✅ Transforms renderHook() calls to await renderHook() in test functions
- ✅ Transforms fireEvent() calls to await fireEvent() in test functions
- ✅ Transforms fireEvent.press(), fireEvent.changeText(), and fireEvent.scroll() calls to await fireEvent.press(), etc.
- ✅ Transforms screen.rerender() and screen.unmount() calls to await screen.rerender(), etc.
- ✅ Transforms renderer.rerender() and renderer.unmount() calls (where renderer is the return value from render()) to await renderer.rerender(), etc.
- ✅ Transforms hookResult.rerender() and hookResult.unmount() calls (where hookResult is the return value from renderHook()) to await hookResult.rerender(), etc.
- ✅ Makes test functions async if they're not already
- ✅ Handles test(), it(), test.skip(), it.skip(), test.only(), it.only(), test.each(), and it.each() patterns
- ✅ Handles beforeEach(), afterEach(), beforeAll(), and afterAll() hooks
- ✅ Does NOT make describe() block callbacks async (they are just grouping mechanisms)
- ✅ Preserves already-awaited function calls
- ✅ Skips function calls in helper functions (not inside test callbacks)
- ✅ Only transforms calls imported from @testing-library/react-native
- ✅ Skips variants like renderAsync, unsafe_act, and unsafe_renderHookSync
What it doesn't do
- ❌ Does not transform function calls in helper functions (like renderWithProviders) - unless specified via CUSTOM_RENDER_FUNCTIONS
- ❌ Does not transform function calls from other libraries
- ❌ Does not handle namespace imports (e.g., import * as RNTL from '@testing-library/react-native')
- ❌ Does not transform unsafe variants (unsafe_act, unsafe_renderHookSync) or renderAsync
- ❌ Does not make describe() block callbacks async (they are grouping mechanisms, not test functions)
Usage
Running the codemod
bash
Example transformations
Basic sync test
Before:
typescript
After:
typescript
Already async test
Before:
typescript
After:
typescript
Multiple render calls
Before:
typescript
After:
typescript
Render with options
Before:
typescript
After:
typescript
Using act()
Before:
typescript
After:
typescript
Using renderHook()
Before:
typescript
After:
typescript
Combined usage
Before:
typescript
After:
typescript
Using fireEvent()
Before:
typescript
After:
typescript
Using fireEvent methods
Before:
typescript
After:
typescript
Skipping unsafe variants
Before:
typescript
After:
typescript
Helper functions (not transformed by default)
Before:
typescript
After (without CUSTOM_RENDER_FUNCTIONS):
typescript
Custom render functions (with CUSTOM_RENDER_FUNCTIONS)
When you specify custom render function names via the CUSTOM_RENDER_FUNCTIONS environment variable, those functions will be transformed:
Before:
typescript
After (with CUSTOM_RENDER_FUNCTIONS="renderWithProviders,renderWithTheme"):
typescript
Describe blocks (not made async)
describe() blocks are grouping mechanisms and their callbacks are not made async, even if they contain render calls in helper functions. However, test() callbacks inside describe blocks are still made async.
Before:
typescript
After:
typescript
Note: The describe callback remains synchronous. The test callback that directly calls render() is made async, but the test callback that only calls a helper function (not in CUSTOM_RENDER_FUNCTIONS) remains synchronous.
Testing
Run the test suite:
bash
Limitations
-
Helper functions: Function calls (render, act, renderHook, fireEvent) inside helper functions (not directly in test callbacks) are not transformed by default. You can specify custom render function names via the --param customRenderFunctions=... flag or CUSTOM_RENDER_FUNCTIONS environment variable to have them automatically transformed. For other helper functions, you'll need to manually update them to be async and await their calls.
-
Namespace imports: The codemod currently doesn't handle namespace imports like import * as RNTL from '@testing-library/react-native'. If you use this pattern, you'll need to manually update those calls.
-
Semantic analysis: The codemod uses pattern matching rather than semantic analysis, so it may transform function calls that aren't from RNTL if they match the pattern. Always review the changes.
-
fireEvent methods: Only fireEvent.press, fireEvent.changeText, and fireEvent.scroll are transformed. Other fireEvent methods are not automatically transformed.
Migration Guide
- Run the codemod on your test files
- If you have custom render functions (like renderWithProviders, renderWithTheme, etc.), run the codemod with the --param flag:
Or use the environment variable:bashbash - Review the changes to ensure all transformations are correct
- Manually update helper functions that contain render, act, renderHook, or fireEvent calls (if not specified in CUSTOM_RENDER_FUNCTIONS)
- Manually update other fireEvent methods if you use methods other than press, changeText, or scroll
- Update your RNTL version to v14
- Run your tests to verify everything works
Contributing
If you find issues or have suggestions for improvements, please open an issue or submit a pull request to the React Native Testing Library repository.