Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions tests/components/list/ListItem.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { render, screen } from "@testing-library/react";
import ListItem from "@/components/common/list/list-item/ListItem";

jest.mock("@/components/common/list/list-item/ListItemRow", () =>
jest.fn(() => <li data-testid="list-item-row" />),
);

describe("ListItem μ»΄ν¬λ„ŒνŠΈ", () => {
it("items 개수만큼 ListItemRowλ₯Ό λ Œλ”λ§ν•œλ‹€", () => {
render(
<ListItem
items={[
{ id: 1, label: "ν•  일 1", checked: false },
{ id: 2, label: "ν•  일 2", checked: true },
]}
onToggleChecked={jest.fn()}
/>,
);

expect(screen.getAllByTestId("list-item-row")).toHaveLength(2);
});

it("itemsκ°€ λΉ„μ–΄ μžˆμ–΄λ„ μ—λŸ¬ 없이 λ Œλ”λ§λœλ‹€", () => {
render(
<ListItem
items={[]}
onToggleChecked={jest.fn()}
/>,
);

expect(screen.queryAllByTestId("list-item-row")).toHaveLength(0);
});
});
22 changes: 22 additions & 0 deletions tests/components/list/ListItemButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import ListItemButton from "@/components/common/list/list-button/ListItemButton";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("ListItemButton", () => {
it("λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ onClick이 ν˜ΈμΆœλœλ‹€", async () => {
const user = userEvent.setup();
const handleClick = jest.fn();

render(
<ListItemButton
icon={<span>icon</span>}
ariaLabel="ν…ŒμŠ€νŠΈ λ²„νŠΌ"
onClick={handleClick}
/>,
);

await user.click(screen.getByRole("button", { name: "ν…ŒμŠ€νŠΈ λ²„νŠΌ" }));

expect(handleClick).toHaveBeenCalledTimes(1);
});
});
80 changes: 80 additions & 0 deletions tests/components/list/ListItemRow.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import ListItemRow from "@/components/common/list/list-item/ListItemRow";
import { ListActionType } from "@/components/common/list/list-item-actions/types";

jest.mock("@/components/common/checkbox/Checkbox", () => {
const MockListToggleChecked = ({
checked,
onToggleChecked,
}: {
checked: boolean;
onToggleChecked: (checked: boolean) => void;
}) => (
<input
type="checkbox"
data-testid="checkbox"
checked={checked}
onChange={(e) => onToggleChecked(e.target.checked)}
/>
);

MockListToggleChecked.displayName = "MockListToggleChecked";

return MockListToggleChecked;
});

jest.mock("@/components/common/list/list-item-actions/ListItemActions", () => {
const MockListItemActions = ({
actions = [],
}: {
actions?: ListActionType[];
}) => (
<div data-testid="actions">
{actions.map((action) => action.type).join(",")}
</div>
);

MockListItemActions.displayName = "MockListItemActions";

return MockListItemActions;
});
describe("ListItemRow μ»΄ν¬λ„ŒνŠΈ", () => {
it("μ²΄ν¬λ°•μŠ€λ₯Ό ν΄λ¦­ν•˜λ©΄ onToggleCheckedκ°€ ν˜ΈμΆœλœλ‹€", async () => {
const user = userEvent.setup();
const onToggleChecked = jest.fn();

render(
<ListItemRow
item={{ id: 1, label: "ν•  일", checked: false }}
onToggleChecked={onToggleChecked}
variant="default"
/>,
);

await user.click(screen.getByTestId("checkbox"));

expect(onToggleChecked).toHaveBeenCalledWith(1, true);
});

it("item에 link, file, noteκ°€ 있으면 actionsκ°€ μƒμ„±λœλ‹€", () => {
render(
<ListItemRow
item={{
id: 1,
label: "ν•  일",
checked: false,
link: true,
file: true,
note: true,
}}
onToggleChecked={jest.fn()}
variant="default"
/>,
);

expect(screen.getByTestId("actions")).toHaveTextContent(
"link,file,note,more",
);
});
});
119 changes: 119 additions & 0 deletions tests/unit/dashboard/dashboard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { screen } from "@testing-library/react";
import ProgressContent from "@/app/(protected)/dashboard/_components/todos/progress/ProgressContent";
import RecentTodosContent from "@/app/(protected)/dashboard/_components/todos/recent/RecentTodosContent";
import GoalList from "@/app/(protected)/dashboard/_components/goal/GoalList";
import { useProgressTodosSuspense } from "@/hooks/queries/todos/useProgressTodosSuspense";
import { useTodosSuspense } from "@/hooks/queries/todos/useTodosSuspense";
import { useGoalsInfiniteQuery } from "@/hooks/queries/goals/useGoalsInfiniteQuery";
import { renderWithQueryClient } from "tests/test-utils";

jest.mock("@/app/(protected)/_components/AsyncBoundary", () => {
const MockAsyncBoundary = ({ children }: { children: React.ReactNode }) => (
<>{children}</>
);
MockAsyncBoundary.displayName = "MockAsyncBoundary";
return MockAsyncBoundary;
});

jest.mock("@/hooks/queries/todos/useTodosSuspense", () => ({
useTodosSuspense: jest.fn(),
}));

jest.mock("@/hooks/queries/todos/useProgressTodosSuspense", () => ({
useProgressTodosSuspense: jest.fn(),
}));

jest.mock("@/hooks/queries/goals/useGoalsInfiniteQuery", () => ({
useGoalsInfiniteQuery: jest.fn(),
}));

jest.mock("@/hooks/queries/todos/useToggleTodo", () => ({
useToggleTodo: () => ({
handleToggle: jest.fn(),
}),
}));

jest.mock("@/components/common/list/list-item-actions/ListItemActions", () => {
const MockListItemActions = () => null;
MockListItemActions.displayName = "MockListItemActions";
return MockListItemActions;
});

afterEach(() => {
jest.clearAllMocks();
});

describe("λŒ€μ‹œλ³΄λ“œ - 졜근 λ“±λ‘ν•œ ν•  일", () => {
it("졜근 4개만 보여쀀닀", () => {
(useTodosSuspense as jest.Mock).mockReturnValue([
{ id: 1, label: "todo1", checked: false },
{ id: 2, label: "todo2", checked: false },
{ id: 3, label: "todo3", checked: false },
{ id: 4, label: "todo4", checked: false },
{ id: 5, label: "todo5", checked: false },
]);

renderWithQueryClient(<RecentTodosContent />);

expect(screen.getByText("todo5")).toBeInTheDocument();
expect(screen.getByText("todo4")).toBeInTheDocument();
expect(screen.getByText("todo3")).toBeInTheDocument();
expect(screen.getByText("todo2")).toBeInTheDocument();
expect(screen.queryByText("todo1")).not.toBeInTheDocument();
});

it("ν•  일이 μ—†μœΌλ©΄ μ•ˆλ‚΄ 문ꡬλ₯Ό 보여쀀닀", () => {
(useTodosSuspense as jest.Mock).mockReturnValue([]);

renderWithQueryClient(<RecentTodosContent />);

expect(
screen.getByText("μ΅œκ·Όμ— λ“±λ‘ν•œ ν•  일이 μ—†μ–΄μš”"),
).toBeInTheDocument();
});
});

describe("λŒ€μ‹œλ³΄λ“œ - 진행도", () => {
it("ν•  μΌλ“€μ˜ 진행도λ₯Ό 보여쀀닀", () => {
(useProgressTodosSuspense as jest.Mock).mockReturnValue({
progress: 80,
});

renderWithQueryClient(<ProgressContent nickname="λ‹€μŠ¬" />);

expect(screen.getByText(/80/)).toBeInTheDocument();
});

it("progressκ°€ μ—†μœΌλ©΄ 0%λ₯Ό 보여쀀닀", () => {
(useProgressTodosSuspense as jest.Mock).mockReturnValue({});

renderWithQueryClient(<ProgressContent nickname="λ‹€μŠ¬" />);

expect(screen.getByText(/0/)).toBeInTheDocument();
});
});

describe("λŒ€μ‹œλ³΄λ“œ - λͺ©ν‘œλ³„ ν•  일", () => {
it("λͺ©ν‘œκ°€ 잘 λ‚˜μ˜¨λ‹€", () => {
(useGoalsInfiniteQuery as jest.Mock).mockReturnValue({
data: {
pages: [
{
goals: [
{ id: 1, title: "μš΄λ™ λͺ©ν‘œ", todos: [] },
{ id: 2, title: "곡뢀 λͺ©ν‘œ", todos: [] },
],
},
],
},
hasNextPage: false,
fetchNextPage: jest.fn(),
isFetchingNextPage: false,
});

renderWithQueryClient(<GoalList />);

expect(screen.getByText("μš΄λ™ λͺ©ν‘œ")).toBeInTheDocument();
expect(screen.getByText("곡뢀 λͺ©ν‘œ")).toBeInTheDocument();
});
});
10 changes: 8 additions & 2 deletions tests/unit/goals/goals.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import GoalHeader from "@/app/(protected)/goals/[goalId]/_components/GoalHeader"
import GoalSection from "@/app/(protected)/goals/[goalId]/_components/GoalSection";
import { calcProgress } from "@/app/(protected)/goals/[goalId]/_utils/calcProgress";
import { EMPTY_MESSAGES } from "@/constants/messages";
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { renderWithQueryClient } from "tests/test-utils";

const push = jest.fn();
const replace = jest.fn();

jest.mock("next/navigation", () => ({
useRouter: () => ({ push }),
useRouter: () => ({ push, replace }),
useParams: () => ({ goalId: "1" }),
}));

Expand Down Expand Up @@ -97,6 +99,10 @@ describe("λͺ©ν‘œ μ˜μ—­", () => {
expect(screen.getByText("정말 μ‚­μ œν•˜μ‹œκ² μ–΄μš”?")).toBeInTheDocument();

await user.click(screen.getByText("확인"));
expect(replace).toHaveBeenCalledWith(
expect.stringContaining("dashboard"),
);

expect(deleteGoal).toHaveBeenCalled();
});
});
Expand Down