diff --git a/frontend/src/components/MyApplicationItem/MyMissionItem/__tests__/useMission.test.ts b/frontend/src/components/MyApplicationItem/MyMissionItem/__tests__/useMission.test.ts new file mode 100644 index 000000000..d5d94e113 --- /dev/null +++ b/frontend/src/components/MyApplicationItem/MyMissionItem/__tests__/useMission.test.ts @@ -0,0 +1,127 @@ +import { renderHook, act } from "@testing-library/react"; +import useMission from "../useMission"; +import useRefresh from "../useRefresh"; +import useMissionJudgment from "../useMissionJudgment"; +import { generatePath, useNavigate } from "react-router-dom"; +import { BUTTON_LABEL } from "../../../../constants/recruitment"; +import { Mission } from "../../../../../types/domains/recruitments"; + +jest.mock("../useRefresh"); +jest.mock("../useMissionJudgment"); +jest.mock("react-router-dom", () => ({ + generatePath: jest.fn(), + useNavigate: jest.fn(), +})); + +describe("useMission", () => { + const mockMission: Mission = { + id: 1, + title: "Test Mission", + description: "Test Description", + submittable: true, + submitted: false, + startDateTime: "2023-01-01T00:00:00", + endDateTime: "2023-12-31T23:59:59", + status: "SUBMITTING", + runnable: true, + judgment: null, + }; + + const mockRecruitmentId = "123"; + + beforeEach(() => { + // useRefresh 훅의 반환값을 실제 사용 사례에 맞게 모킹 + (useRefresh as jest.Mock).mockReturnValue({ + isRefreshAvailable: true, + fetchRefreshedResultData: jest + .fn() + .mockResolvedValue({ ...mockMission, title: "Refreshed Mission" }), + }); + + // useMissionJudgment 훅의 반환값을 실제 사용 사례에 맞게 모킹 + (useMissionJudgment as jest.Mock).mockReturnValue({ + isJudgmentAvailable: true, + fetchJudgmentMissionResult: jest + .fn() + .mockResolvedValue({ ...mockMission, title: "Judged Mission" }), + }); + + // react-router-dom 함수들을 실제 사용 사례에 맞게 모킹 + const mockNavigate = jest.fn(); + (useNavigate as jest.Mock).mockReturnValue(mockNavigate); + (generatePath as jest.Mock).mockImplementation((path, params) => { + // 간단한 구현. 실제 상황에 맞게 조정 필요 + return path.replace(/:(\w+)/g, (_, key) => params[key]); + }); + }); + + it("초기 상태를 올바르게 설정해야 한다", () => { + const { result } = renderHook(() => + useMission({ mission: mockMission, recruitmentId: mockRecruitmentId }) + ); + + expect(result.current.getter.missionItem).toEqual(mockMission); + expect(result.current.getter.applyButtonLabel).toBe(BUTTON_LABEL.SUBMIT); + expect(result.current.getter.formattedStartDateTime).toBe("2023-01-01 00:00"); + expect(result.current.getter.formattedEndDateTime).toBe("2023-12-31 23:59"); + expect(result.current.getter.isJudgmentAvailable).toBe(true); + expect(result.current.getter.isRefreshAvailable).toBe(true); + }); + + it("mission prop이 변경되면 missionItem 상태를 업데이트해야 한다", () => { + const { result, rerender } = renderHook( + ({ mission }) => useMission({ mission, recruitmentId: mockRecruitmentId }), + { initialProps: { mission: mockMission } } + ); + + const updatedMission = { ...mockMission, title: "Updated Mission" }; + rerender({ mission: updatedMission }); + + expect(result.current.getter.missionItem).toEqual(updatedMission); + }); + + it("routeToAssignmentSubmit 함수가 올바르게 동작해야 한다", () => { + const mockNavigate = jest.fn(); + (useNavigate as jest.Mock).mockReturnValue(mockNavigate); + + const { result } = renderHook(() => + useMission({ mission: mockMission, recruitmentId: mockRecruitmentId }) + ); + + act(() => { + result.current.routeToAssignmentSubmit({ + recruitmentId: mockRecruitmentId, + mission: mockMission, + })(); + }); + + expect(mockNavigate).toHaveBeenCalledWith( + { pathname: expect.any(String) }, + { state: { recruitmentId: mockRecruitmentId, currentMission: mockMission } } + ); + }); + + it("requestRefresh 함수가 올바르게 동작해야 한다", async () => { + const { result } = renderHook(() => + useMission({ mission: mockMission, recruitmentId: mockRecruitmentId }) + ); + + await act(async () => { + await result.current.requestRefresh(); + }); + + expect(result.current.getter.missionItem.title).toBe("Refreshed Mission"); + }); + + it("requestMissionJudgment 함수가 올바르게 동작해야 한다", async () => { + const { result } = renderHook(() => + useMission({ mission: mockMission, recruitmentId: mockRecruitmentId }) + ); + + await act(async () => { + await result.current.requestMissionJudgment(); + }); + + expect(result.current.getter.missionItem.title).toBe("Judged Mission"); + }); +});