Mmdjastrzebski

rntl-v14-async-functions

Codemod to migrate sync RNTL function and method calls to async for RNTL v14

transformationmigration
Public
0 executions
0 stars
How to Use
Run this codemod on your codebase using one of the following commands

The easiest way to run this codemod without installing anything globally:

Documentation

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

  1. 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.

  2. 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.

  3. 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.

  4. fireEvent methods: Only fireEvent.press, fireEvent.changeText, and fireEvent.scroll are transformed. Other fireEvent methods are not automatically transformed.

Migration Guide

  1. Run the codemod on your test files
  2. If you have custom render functions (like renderWithProviders, renderWithTheme, etc.), run the codemod with the --param flag:
    bash
    Or use the environment variable:
    bash
  3. Review the changes to ensure all transformations are correct
  4. Manually update helper functions that contain render, act, renderHook, or fireEvent calls (if not specified in CUSTOM_RENDER_FUNCTIONS)
  5. Manually update other fireEvent methods if you use methods other than press, changeText, or scroll
  6. Update your RNTL version to v14
  7. 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.

Ready to contribute?

Build your own codemod and share it with the community.