Testing React Native Components
In order to test whether a button click works in a React Native app using Jest, you can use the fireEvent
method from the @testing-library/react-native
library.
Debug()
When retrieving an element fails, use debug()
to inspect the rendered screen in code
<RNCSafeAreaProvider
onInsetsChange={[Function anonymous]}
style={
Array [
Object {
"flex": 1,
},
undefined,
]
}
>
<View
style={
Object {
"backgroundColor": "background",
"elevation": 1,
...
Sometimes, adding an intentional delay helps in debugging the issue.
await new Promise((r) => setTimeout(r, 2000))
Button
Here is an example of how you might test a button click:
import React from "react"
import { fireEvent, render } from "@testing-library/react-native"
import CommonButton from "../../src/components/CommonButton"
import wrapper from "../wrapper.helper"
describe("CommonButton", () => {
it('renders correctly', () => {
expect(true).toBe(true)
const { getByText } = render(
<CommonButton title="Test Button" onPress={() => {}} />,
{wrapper}
)
expect(getByText("Test Button")).toBeTruthy()
})
it('calls onPress when pressed', () => {
const onPress = jest.fn()
const { getByTestId } = render(
<CommonButton title="Test Button" onPress={onPress} />,
{wrapper}
)
fireEvent.press(getByTestId("common-button"))
expect(onPress).toHaveBeenCalled()
})
})
In this example, we first import the render
and fireEvent
methods from the @testing-library/react-native
library. Next, we import the component we want to test, CommonButton
in this case. Then we use the render
method to render the component in a way that we can test.
After that, we use the getByTestId
to fetch the button element from the render tree and store it in a variable named button, then we use fireEvent.press(button)
to simulate the button click. Finally, we use expect(onPress).toHaveBeenCalled()
to check if the onPress
callback was called during the simulation.
Mocking
Manual mock
A manual mock in Jest is a custom implementation of a module that you want to use in place of the real module in your tests. The purpose of using a manual mock is to isolate your tests from the implementation details of the module and control its behavior in a way that is relevant to your test cases.
A manual mock is created by creating a mock file in a __mocks__
directory and defining the mock implementation for the module. When you import the module in your test file, Jest will automatically use the mock implementation instead of the actual module.
Here’s an example of how you can create a manual mock for a module named moduleA
:
-
Create a
__mocks__
directory in the same folder as your test file. -
In the
__mocks__
directory, create a file namedmoduleA.js
To mock a scoped module called @scope/project-name
, create a file at __mocks__/@scope/project-name.js
, creating the @scope/
directory accordingly.
root
| -- node_modules
| -- __mocks__
| -- react-native-keyboard-aware-scroll-view.ts
export const KeyboardAwareScrollView = () =>
jest.fn().mockImplementation(
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
({ children }) => children
)
KeyboardAwareScrollView Issue
render()
doesn’t render KeyboardAwareScrollView
very well. Mock it so that it just render the children.
export const KeyboardAwareScrollView = ({ children }) => children
Comments