Reputation: 833
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
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