How to Use the Custom Test Renderer
This guide shows you how to use the custom render utilities provided by Ledger Wallet to test components and hooks with all necessary providers pre-configured.
Always prefer the custom render utilities over raw @testing-library render functions.
How to render a component (Mobile)
Import from @tests/test-renderer:
import { render, screen } from "@tests/test-renderer";
import { State } from "~/reducers/types";
const { user, store } = render(<MyComponent />, {
overrideInitialState: (state: State) => ({
...state,
accounts: {
...state.accounts,
active: [mockAccount],
},
}),
});
// Use screen queries
expect(screen.getByText("Hello")).toBeTruthy();
// Simulate user interactions
await user.press(screen.getByText("Submit"));How to render a component (Desktop)
Import from tests/testSetup:
import { render, screen } from "tests/testSetup";
const { user, store, i18n } = render(<MyComponent />, {
initialState: {
accounts: { active: [mockAccount] },
},
initialRoute: "/accounts", // Optional: set initial route
});
// Use screen queries
expect(screen.getByText("Hello")).toBeInTheDocument();
// Simulate user interactions
await user.click(screen.getByRole("button", { name: "Submit" }));How to render a hook
Mobile
import { renderHook } from "@tests/test-renderer";
const { result, store } = renderHook(() => useMyCustomHook(), {
overrideInitialState: (state) => ({
...state,
settings: { ...state.settings, theme: "dark" },
}),
});
expect(result.current.value).toBe(expectedValue);Desktop
import { renderHook } from "tests/testSetup";
const { result, store } = renderHook(() => useMyCustomHook(), {
initialState: {
settings: { theme: "dark" },
},
});
expect(result.current.value).toBe(expectedValue);How to customize initial state
Use overrideInitialState (Mobile) or initialState (Desktop) to set up Redux state for your tests:
- Mobile: Pass a function that receives the full default state and returns the modified state. You must spread the existing state to avoid replacing reducer defaults.
- Desktop: Pass a partial state object that is merged into the default state.
// Mobile - function-based override
render(<MyComponent />, {
overrideInitialState: (state: State) => ({
...state,
settings: { ...state.settings, theme: "dark" },
}),
});
// Desktop - object-based override
render(<MyComponent />, {
initialState: {
settings: { theme: "dark" },
},
});Before vs After: why use the custom renderer
Before (manual provider setup)
🚫
This approach requires manually wrapping components with many providers:
import { render } from "@testing-library/react-native";
import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components";
import { NavigationContainer } from "@react-navigation/native";
import { FirebaseFeatureFlagsProvider } from "~/components/FirebaseFeatureFlags";
// ... many more imports
const mockStore = createMockStore({ accounts: [mockAccount] });
render(
<Provider store={mockStore}>
<FirebaseFeatureFlagsProvider getFeature={getFeature}>
<NavigationContainer>
<ThemeProvider theme={theme}>
<I18nextProvider i18n={i18n}>
<MyComponent />
</I18nextProvider>
</ThemeProvider>
</NavigationContainer>
</FirebaseFeatureFlagsProvider>
</Provider>
);After (using custom renderer)
The custom renderer handles all provider setup automatically:
import { render, screen } from "@tests/test-renderer";
const { user, store } = render(<MyComponent />, {
overrideInitialState: (state) => ({
...state,
accounts: { ...state.accounts, active: [mockAccount] },
}),
});Mocks you no longer need
When using the custom render utilities, remove these commonly unnecessary mocks:
// ❌ No need to mock react-i18next - I18nextProvider is included
jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => key,
}),
}));
// ❌ No need to mock react-redux - Provider with real store is included
jest.mock("react-redux", () => ({
useSelector: jest.fn(),
useStore: jest.fn(() => ({})),
}));
// ❌ No need to mock theme-related hooks
jest.mock("~/hooks/useTheme", () => ({
useTheme: () => ({ colors: { /* ... */ } }),
}));See also
- How to Write Tests — Integration tests, component tests, debugging tips
- Testing reference — Full render function API, providers included, coverage targets
- Testing Strategy — Why we built the custom renderer