user2278842
user2278842

Reputation: 65

Jest unit tests with useRoute from react-navigation

We recently upgraded our react native codebase to version 5 of React Navigation and along the way we refactored a couple components from class components to functional components. This means we are using hooks like useNavigation() and useRoute().

I am having a difficult time figuring out how to get around an issue that I am facing when we are doing unit testing. It would appear that the state of the navigation and route props aren't available to the test when it runs. For example, I get the following error from Jest:

● <EULA /> › Rendering › should match to snapshot

    TypeError: Cannot read property 'name' of undefined

      27 |   const route = useRoute();
      28 |   const authContext = useContext(AuthContext);
    > 29 |   const isAcceptPP: boolean = route.name === "AcceptEULA";
         |                                     ^

This error leads me to believe that when line 27 runs in the context of the unit test it isn't actually returning a route object from useRoute(). This error shows up on all of my tests for the file.

This is what the test looks like currently and I tried mocking the useRoute and just making route part of props, but these didn't seem to do much of anything:

import React from "react";
import { render, fireEvent, waitFor } from "@testing-library/react-native";
import { WebView } from "react-native-webview";
import { Alert } from "react-native";

import EULA from "../src/screens/EULA";
import { alertSpy } from "../src/jest/spies";

describe("<EULA />", () => {
  let props;
  let useRoute: jest.Mock;
  beforeEach(() => {
    useRoute = jest.fn();
    props = { navigation: { state: { routeName: "AcceptEULA" }, navigate: navigate }, route: { name: "AcceptEULA" } };
  });

  describe("Rendering", () => {
    it("should match to snapshot when accept EULA", async () => {
      const { toJSON, getByType } = render(<EULA {...props} />);
      await waitFor(() => getByType(WebView));
      expect(toJSON()).toMatchSnapshot();
    });

I am still a bit new to Jest and I'm not really sure how I am supposed to go about with this because route isn't really part of navigation prop anymore, but I may just be overthinking this.

Upvotes: 6

Views: 8073

Answers (1)

mabahamo
mabahamo

Reputation: 783

I think the issue is that your passing the mock route as a prop, while your test is trying to capture the route using a hook.

I think this can help you:

import { useRoute } from "@react-navigation/core";
jest.mock("@react-navigation/core");
import EULA from "../src/screens/EULA";

describe("Rendering", () => {
  it("should match to snapshot when accept EULA", async () => {
    useRoute.mockReturnValue({
      name: "AcceptEULA"
    });
    const { toJSON, getByType } = render(<EULA />);
    ...
  });
});

Upvotes: 8

Related Questions