Skip to content

Commit

Permalink
test: Sidebar 및 createNewTodo 테스트 파일 작성
Browse files Browse the repository at this point in the history
  • Loading branch information
deipanema committed Oct 14, 2024
1 parent 21acc78 commit 48a4556
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 141 deletions.
37 changes: 0 additions & 37 deletions setupTests.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/api/todoAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const postFile = async (file: File) => {
}
};

export const PostTodos = async (
export const postTodos = async (
title: string,
fileUrl: string | null,
linkUrl: string | null,
Expand Down
15 changes: 15 additions & 0 deletions src/app/dashboard/components/ProgressTracker.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";

import ProgressTracker from "./ProgressTracker";

describe("ProgressTracker 컴포넌트 테스트", () => {
it("렌더링 확인", () => {
const setprogressValue = vi.fn();
render(<ProgressTracker ratio={70} progressValue={50} setProgressValue={setprogressValue} />);

const progressText = screen.getByText("내 진행 상황");

expect(progressText).toBeInTheDocument();
});
});
127 changes: 127 additions & 0 deletions src/app/dashboard/components/Sidebar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { useRouter } from "next/navigation";
import { expect, vi } from "vitest";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import { useAuthStore } from "@/store/authStore";
import { GoalType, useGoalStore } from "@/store/goalStore";
import CreateNewTodo from "@/components/CreateNewTodo";
import { logout } from "@/utils/authUtils";

import SideBar from "./Sidebar";

export const mockGoals: GoalType[] = [
{
id: 1,
teamId: "FESI3-5",
title: "스타벅스 가기",
userId: 1,
createdAt: "",
updatedAt: "",
},
{
id: 2,
teamId: "FESI3-5",
title: "이삭 토스트 가기",
userId: 1,
createdAt: "",
updatedAt: "",
},
];

// Next.js의 navigation과 Image 컴포넌트 모킹
vi.mock("next/navigation", () => ({
useRouter: vi.fn(() => ({
push: vi.fn(),
})),
usePathname: () => "/mocked/path",
}));

vi.mock("next/image", () => ({
default: vi.fn(() => null),
}));

// 스토어와 유틸리티 함수 모킹
vi.mock("@/store/goalStore", () => ({
useGoalStore: vi.fn(),
}));

vi.mock("@/store/authStore", () => ({
useAuthStore: vi.fn(),
}));

vi.mock("@/utils/authUtils", () => ({
logout: vi.fn(),
}));

describe("SideBar 컴포넌트", () => {
const mockPush = vi.fn();
const mockRefreshGoals = vi.fn();
const mockAddGoal = vi.fn();
const mockUser = { name: "테스트 사용자", email: "[email protected]" };

beforeEach(() => {
vi.clearAllMocks();
useRouter.mockReturnValue({
push: mockPush,
});
useGoalStore.mockReturnValue({
goals: [{ id: 1, title: "오늘의 할 일" }],
refreshGoals: mockRefreshGoals,
addGoal: mockAddGoal,
});
useAuthStore.mockReturnValue({ user: mockUser });
render(<CreateNewTodo closeCreateNewTodo={() => {}} goal={mockGoals[0]} />);
});

it("사이드바가 렌더링됩니다", async () => {
render(<SideBar />);
expect(screen.getByText("대시보드")).toBeInTheDocument();
expect(screen.getByText("+ 새 할 일")).toBeInTheDocument();
expect(screen.getByTestId("sidebar-goal-heading")).toBeInTheDocument();

// 목표가 비동기로 로드되므로 findByText 사용
expect(await screen.findByText("스타벅스 가기")).toBeInTheDocument();
});

it("로그아웃 클릭 시 로그아웃되어 / 경로로 갑니다.", async () => {
logout.mockResolvedValue(true);
render(<SideBar />);

const logoutButton = screen.getByText("로그아웃");
await fireEvent.click(logoutButton);

expect(logout).toHaveBeenCalled();

await waitFor(() => {
expect(mockPush).toHaveBeenCalledWith("/");
});
});

it("새 목표 추가 기능이 작동합니다", async () => {
render(<SideBar />);

const newGoalButton = screen.getByText("+ 새 목표");
await userEvent.click(newGoalButton);

const input = screen.getByRole("textbox", { name: "새목표" });
await userEvent.type(input, "cypress까지 달리기");
fireEvent.submit(input);

expect(mockAddGoal).toHaveBeenCalledWith("cypress까지 달리기");
});

it("사이드바 토글 기능이 작동합니다", async () => {
render(<SideBar />);

const toggleButton = screen.getByTestId("main-sidebar-button");
await userEvent.click(toggleButton);

expect(screen.getByTestId("slim-sidebar-button")).toBeInTheDocument();
});

it("컴포넌트 마운트 시 목표 새로고침합니다", () => {
render(<SideBar />);
expect(mockRefreshGoals).toHaveBeenCalled();
});
});
51 changes: 31 additions & 20 deletions src/app/dashboard/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default function SideBar() {
>
<Image src="/hamburger.svg" width={0} height={0} alt="hamburger-button" className="h-auto w-auto" />
</div>
<h2 className="cursor-pointer text-[18px] font-semibold">대시보드</h2>
{/* <h2 className="cursor-pointer text-[18px] font-semibold">대시보드</h2> */}
</div>
<div
className={`sticky top-0 float-left hidden h-screen w-[280px] transform border-r bg-white py-3 transition-transform duration-500 ease-in-out ${
Expand All @@ -86,8 +86,12 @@ export default function SideBar() {
<Link href="/">
<Image src="/brand.webp" width={106} height={0} className="h-auto w-auto" alt="brand" priority />
</Link>
<button className="rounded-lg border-2 p-2" onClick={() => setIsOpen((prev) => !prev)}>
<Image src="/sidebar-hide.svg" width={0} height={0} className="h-auto w-2" alt="sidebar-button" />
<button
className="rounded-lg border-2 p-2"
data-testid="main-sidebar-button"
onClick={() => setIsOpen((prev) => !prev)}
>
<Image src="/sidebar-hide.svg" width={0} height={0} className="h-auto w-2" alt="main-sidebar-button" />
</button>
</div>
<div className="mb-6 flex gap-3 px-6">
Expand All @@ -98,24 +102,24 @@ export default function SideBar() {
<AnimatedText text="로그아웃" onClick={handleLogout} />
</div>
</div>
<div className="border-b border-b-slate-200 px-6 pb-6">
<h2 className="border-b border-b-slate-200 px-6 pb-6">
<button
onClick={() => openModal("CREATE_NEW_TODO")}
className="w-full rounded-lg bg-blue-500 py-3 text-white outline-none"
>
+ 새 할 일
</button>
</div>
</h2>
<div className="flex gap-2 border-b border-b-slate-200 px-6 py-4">
<Image src="/sidebar-home.svg" width={0} height={0} className="ml-1.5 h-auto w-[13px]" alt="sidebar-home" />
<Link href="/">
<span>대시보드</span>
<h2>대시보드</h2>
</Link>
</div>
<div className="px-6 py-4">
<div className="flex gap-2">
<Image src="/sidebar-flag.svg" width={24} height={24} alt="sidebar-flag" />
<span>목표</span>
<h2 data-testid="sidebar-goal-heading">목표</h2>
</div>
<div className="mb-6 max-h-[350px] overflow-y-auto pt-4">
<ul className="flex flex-col gap-4">
Expand All @@ -127,19 +131,22 @@ export default function SideBar() {
</ul>
{inputVisible && (
<form onSubmit={handleSubmit}>
<input
type="text"
ref={inputRef}
value={goalInput}
onChange={(e) => {
setGoalInput(e.target.value);
}}
className="block w-full border-b border-gray-300 focus:border-blue-500 focus:outline-none"
/>
<label className="sr-only">
새목표
<input
type="text"
ref={inputRef}
value={goalInput}
onChange={(e) => {
setGoalInput(e.target.value);
}}
className="block w-full border-b border-gray-300 focus:border-blue-500 focus:outline-none"
/>
</label>
</form>
)}
</div>
<div>
<h2>
<button
onClick={() => {
setInputVisible((prev) => !prev);
Expand All @@ -148,7 +155,7 @@ export default function SideBar() {
>
+ 새 목표
</button>
</div>
</h2>
</div>
</div>
</aside>
Expand All @@ -157,8 +164,12 @@ export default function SideBar() {
<Link href="/">
<Image src="/sidebar-logo.png" width={21} height={20} alt="sidebar-brand-hide" />
</Link>
<button className="rounded-lg border-2 p-2" onClick={() => setIsOpen((prev) => !prev)}>
<Image src="/sidebar-hide-R.svg" width={8} height={8} alt="sidebar-button" />
<button
className="rounded-lg border-2 p-2"
data-testid="slim-sidebar-button"
onClick={() => setIsOpen((prev) => !prev)}
>
<Image src="/sidebar-hide-R.svg" width={8} height={8} alt="slim-sidebar-button" />
</button>
</div>
)}
Expand Down
79 changes: 0 additions & 79 deletions src/app/sentry-example-page/page.tsx

This file was deleted.

Loading

0 comments on commit 48a4556

Please sign in to comment.