I am starting using jest to test simple component SysError.js
in my React Native 0.68 app. SysError
displays some message on screen when it is called (routed by react-navigation 6.x) and the jest test is to check if the page view does contain the message. The @testing-library/react-native used is v11.0.0
Here is the SysError.js
:
import React, {useState, useContext, Component} from 'react';
import {Platform, Button, Text, TouchableOpacity, View } from 'react-native';
export default function SysError({route}) { //<<== routed by react-navigation
const message = route.params.message ? JSON.stringify(route.params.message) : "";
return (
<View styles={{marginTop: 32, paddingHorizontal: 24, alignItems:"center", alignContent:"center"}}>
<Text>{route.params.message} System NOT available right now. Try again later</Text>
</View>
)
};
Here is the jest test:
import React from 'react';
import { render, cleanup } from "@testing-library/react-native";
import SysError from './SysError';
afterEach(cleanup);
it ('describe SysError page view with a message', () => {
const route = {params: {message:"nnmm"}};
const {toJSON, getByText} = render(<SysError route={route} />);
const foundmsg = getByText("System NOT available right now"); //<<==this throws error
expect(toJSON()).toMatchSnapshot();
expect(foundmsg.props.children).toEqual("System NOT available right now");
})
To my surprise, there is an error:
FAIL src/components/app/SysError.test.js
● describe SysError page view with a message
Unable to find an element with text: System NOT available right now
9 | const route = {params: {message:"nnmm"}};
10 | const {toJSON, getByText} = render(<SysError route={route} />);
> 11 | const foundmsg = getByText("System NOT available right now");
| ^
12 | expect(toJSON()).toMatchSnapshot();
13 | expect(foundmsg.props.children).toEqual("System NOT available right now");
14 |
at Object.getByText (src/components/app/SysError.test.js:11:22)
However if the test code is changed to reg expression:
const foundmsg = getByText(/System NOT available right now/i);
Then the error becomes:
expect(received).toEqual(expected) // deep equality
Expected: "System NOT available right now"
Received: ["nnmm", " System NOT available right now. Try again later"]
11 | const foundmsg = getByText(/System NOT available right now/i);
12 | expect(toJSON()).toMatchSnapshot();
> 13 | expect(foundmsg.props.children).toEqual("System NOT available right now");
Is there way re-code expect(foundmsg.props.children).toEqual("System NOT available right now");
and make it pass? I tried toEqual(/System NOT available right now/i)
and it didn't work.
As the react-native testing library shows in the documentation examples the getByText
query, if provided a string, will look for the exact match.
That's the reason why on your first attempt the query is unable to find the element. As you found out, you can also provide a regex to look for partial match so on your second attempt the query is capable of finding the element.
Now that you have the element:
<Text>{route.params.message} System NOT available right now. Try again later</Text>
You can see that it actually has two children: One for the dynamic part that prints the route.params.message
and the other one for the static part.
You can check both values in your test with:
expect(foundmsg.props.children).toEqual(["nnmm", "System NOT available right now"]);
If you only want to check that the static part is present you could also do:
expect(foundmsg.props.children).toContain("System NOT available right now");