Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test state management(Recoil) using react jest?

Tags:

reactjs

jestjs

How do I test recoil using react jest?
I expect below test is going to be success but it gives me fail.
Any way to render the status of isLogin: false using jest?

// src/state/user.ts

import { atom } from "recoil";

export type UserType = {
  isLogin: boolean;
};

const userState = atom<UserType>({
  key: "user",
  default: {
    isLogin: true,
  },
});

export default userState;

// src/pages/user/User.tsx

import { useNavigate, useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import userState from "../../state/user";

export default function User() {
  const navigate = useNavigate();
  const { id } = useParams();
  const { isLogin } = useRecoilValue(userState);

  if (!isLogin) {
    return <div>Login 후 이용 가능합니다.</div>;
  }

  return (
    <div>
      {id}
      <button
        type="button"
        onClick={() => {
          navigate("/");
        }}
      >
        Go to Home
      </button>
    </div>
  );
}

// src/pages/user/User.test.tsx

import { MemoryRouter } from "react-router-dom";
import { render, screen, renderHook, act } from "@testing-library/react";
import { RecoilRoot, useSetRecoilState } from "recoil";
import User from "./User";
import type { UserType } from "../../state/user";
import userState from "../../state/user";

const userStateMock = (user: UserType) => {
  const { result } = renderHook(() => useSetRecoilState(userState), {
    wrapper: RecoilRoot,
  });

  act(() => {
    result.current(user);
  });

  return result;
};

describe("<User />", () => {
  const renderUserComponent = () =>
    render(
      <RecoilRoot>
        <MemoryRouter>
          <User />
        </MemoryRouter>
      </RecoilRoot>
    );

  describe("When user hasn't logged in", () => {
    it("Should render warning message", () => {
      userStateMock({
        isLogin: false,
      });

      renderUserComponent();

      expect(screen.getByText(/Login 후 이용 가능합니다./)).toBeDefined();
    });
  });
});

Result of the test Result of the test

like image 513
Jewoo Ham Avatar asked Aug 31 '25 11:08

Jewoo Ham


1 Answers

You should use the initializeState prop in the RecoilRoot component to pass a function that initializes the state of the atoms present in the MutableSnapshot instance. This way you can mock Recoil state data in your tests.

const mockedState = { isLogin: false }
const renderUserComponent = () =>
  render(
    <RecoilRoot initializeState={(snapshot) => snapshot.set(userState, mockedState)}>
      <MemoryRouter>
        <User />
      </MemoryRouter>
    </RecoilRoot>
  );

Edit: Misspelled mockedState, the original example would throw an error. Fixed.

like image 146
Joao Vitor Avatar answered Sep 03 '25 00:09

Joao Vitor