import React, { PropsWithChildren } from "react";
import { render as rtlRender } from "@testing-library/react";
import { Provider } from "react-redux";
import { BrowserRouter as Router } from "react-router-dom";
import setupStore, { AppStore, RootState } from "../store/store";
import type { RenderOptions } from "@testing-library/react";
import type { PreloadedState } from "@reduxjs/toolkit";
interface ExtendedRenderOptions extends Omit<RenderOptions, "queries"> {
preloadedState?: PreloadedState<RootState>;
store?: AppStore;
}
function render(
ui: React.ReactElement,
{
preloadedState = {},
store = setupStore(preloadedState),
...renderOptions
}: ExtendedRenderOptions = {}
) {
function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element {
return (
<Provider store={store}>
<Router>{children}</Router>
</Provider>
);
}
return rtlRender(ui, { wrapper: Wrapper, ...renderOptions });
}
export * from "@testing-library/react";
export { render };
import { IUserState } from "../../interfaces";
import {
userReducer,
toggleSidebar,
logoutUser,
initialState,
} from "../../reducers/userSlice";
test("initial state를 리턴한다.", () => {
expect(userReducer(undefined, { type: undefined })).toEqual({
isLoading: false,
isSidebarOpen: false,
user: null,
});
});
test("toggleSidebar action은 isSidebarOpen 상태를 토글 한다.", () => {
expect(userReducer(initialState, toggleSidebar())).toEqual({
isLoading: false,
isSidebarOpen: true,
user: null,
});
});
test("logoutUser action", () => {
const previousState: IUserState = {
isLoading: false,
isSidebarOpen: true,
user: {
email: "sangbin@gmail.com",
lastName: "sangbin",
location: "seoul",
name: "sangbin",
token: "some token",
},
};
expect(userReducer(previousState, logoutUser())).toEqual({
isLoading: false,
isSidebarOpen: false,
user: null,
});
});
api request는 msw를 이용하여 모킹 하였다.
test("registerUser action test", async () => {
const store = setupStore();
const result = await store.dispatch(
registerUser({ email: "mosangbin@gmai1l.com", password: "123" })
);
const response = result.payload;
expect(response).toEqual({
user: {
email: "mosangbin@gmai1l.com",
lastName: "lastName",
location: "my city",
name: "redux",
token: "eyJhbGciOiJIUzI1NiIsInR",
},
});
const state = store.getState().user;
expect(state.user?.name).toBe("redux");
});
test("loginUser action test", async () => {
const store = setupStore();
const result = await store.dispatch(
loginUser({ email: "sangbin@gmail.com", password: "123" })
);
const response = result.payload;
expect(response).toEqual({
user: {
email: "testUser@test.com",
lastName: "shake and bake",
location: "vegan food truck",
name: "toolkit",
token: "eyJhbGciOiJIUzI1NiIsInR5cC",
},
});
const state = store.getState().user;
expect(state.user?.name).toBe("toolkit");
});
describe("Navbar Component", () => {
it("user의 이름에 맞게 button의 텍스트가 변경된다.", () => {
const state = {
user: {
isLoading: false,
isSidebarOpen: false,
user: {
email: "asd",
lastName: "asd",
location: "asd",
name: "sangbin",
token: "asdasd",
},
},
};
render(<Navbar />, {
preloadedState: state,
});
const button = screen.getByTestId("user-button");
expect(button).toHaveTextContent("sangbin");
});