Kai021195
Kai021195

Reputation: 833

How do I add some state to redux state when try to write unit test in jest/RTL?

I wanted to start testing with Redux-toolkit, according to the article I found.

https://redux.js.org/usage/writing-tests#setting-up

The right practice is to write integration test. But right now I want to test a sign out button which is controlled by authstate,in order to set it's value I have to sign in first. What I want to do is I can give some state to the authstate in the test file instead of having to login. So I can actually write unit test on my sign out button.

Here's the code and the test

const Navbar = () => {
  const cart = useAppSelector((state) => state.cart);
  const user = useAppSelector((state) => state.auth);
  const dispatch = useAppDispatch();
  const handleLogout = () => {
    localStorage.removeItem("persist:root");
    window.location.reload();
  };
  return(
     {user.user !== null ? (
            <>
              <MenuItem>Hello {user.user?.username} </MenuItem>{" "}
              <ExitToApp
                style={{ cursor: "pointer", marginLeft: "10px" }}
                onClick={() => handleLogout()}
              />
              <Link to="/order">
                <MenuItem>Order</MenuItem>
              </Link>
            </>
          ) : (
            <>
              <Link to="/register">
                <MenuItem>REGISTER</MenuItem>
              </Link>
              <Link to="/login">
                <MenuItem>SIGN IN</MenuItem>
              </Link>
            </>
          )}
  )

Authslice

const slice = createSlice({
  name: "auth",
  initialState: { user: null, token: null } as {
    user: null | UserDataInterface;
    token: null | string;
  },
  reducers: {
    setCredentials: (state,{ payload: { user, token } }: PayloadAction<{ user: UserDataInterface; token: string }>) => {
      state.user = user;
      state.token = token;
    }
  },
  extraReducers: (builder) => {}
});

test file

test("When click on logoutk,it will trigger handle logout", () => {
   //TODO: should let the user state to not be empty first 
   await store.dispatch(setCredentials())
   //TODO: then we can track if logout label exist
   //TODO: click on logout button and mock localstorage maybe ?
});

What should I do with this kind of unit test, if it involves prerequisites for redux-state ?

Upvotes: 2

Views: 4193

Answers (1)

Kai021195
Kai021195

Reputation: 833

After some research, I found out how to do this. It might not be the best practice. But I think it could be useful in a lot of scenario if you don't want to write integration test.

test("When click on logout,it will trigger handle logout", async () => {
    //TODO: should let the user state to not be empty first
    store.dispatch(
      setCredentials({
        user: {
          username: "Kai",
          _id: "efekfjefke",
          email: "dfdkdfkdf@gmail.com",
          createdAt: new Date(2013, 13, 1),
          updatedAt: new Date(2013, 13, 1),
          img: "223232",
        },
        token: "test12345",
      })
    );
    //TODO: then we can track if logout label exist
    await waitFor(() =>
      expect(screen.queryByRole("userTitle")).toBeInTheDocument()
    );
    await waitFor(() =>
      expect(screen.queryByTestId("logout")).toBeInTheDocument()
    );
    //TODO: click on logout button and mock localstorage maybe ?
    const userLogout = screen.getByTestId("logout");
    fireEvent.click(userLogout);
    // should not be able to query the userTitle since it's logout
    await waitFor(() =>
      expect(screen.queryByRole("userTitle")).not.toBeInTheDocument()
    );
  });

I found out you can directly dispatch state through the store. which is really convenient.

Cause for me. What's tricky is I don't know how to write integration test across two components or pages

Right now if I can directly dispatch some state first. I can unit-test the function in single page or components to see if it does what I needed.

I am pretty new to testing, so if there's any better approach at this, please let me know!

Hope this can help someone who is struggling!!

Upvotes: 4

Related Questions