Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test : custom hooks test #162

Merged
merged 10 commits into from
Aug 16, 2024
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
2 changes: 2 additions & 0 deletions components/FrameEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,15 @@ const FrameEditor = ({
</td>
))}
<td
// eslint-disable-next-line
onClick={() => addTd(rowIndex)}
className={styles.SetRow}
aria-label="add button"
>
+
</td>
<td
// eslint-disable-next-line
onClick={() => removeLastTd(rowIndex)}
className={styles.SetRow}
aria-label="remove button"
Expand Down
74 changes: 74 additions & 0 deletions hooks/useDate.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import useDate from "./useDate";

describe("useDate", () => {
const { fromNow, formatDate, getValidYearList } = useDate();

it("fromNow를 호출하면 주입된 시간은 현재 시간을 기점으로 얼마나 전인지를 반환한다.", () => {
const createSometimesAgo = (ago: number) => new Date(new Date().getTime() - ago);

const SECONDS = 1_000;
const MINUTES = 60 * SECONDS;
const HOURS = 60 * MINUTES;
const DAYS = 24 * HOURS;
const MONTHS = 30 * DAYS;
const YEARS = 12 * MONTHS;

const threeSecondsAgo = createSometimesAgo(3 * SECONDS);
expect(fromNow(threeSecondsAgo)).toBe("몇 초 전");

const threeMinutesAgo = createSometimesAgo(3 * MINUTES);
expect(fromNow(threeMinutesAgo)).toBe("3분 전");

const threeHoursAgo = createSometimesAgo(3 * HOURS);
expect(fromNow(threeHoursAgo)).toBe("3시간 전");

const threeDaysAgo = createSometimesAgo(3 * DAYS);
expect(fromNow(threeDaysAgo)).toBe("3일 전");

const threeMonthsAgo = createSometimesAgo(3 * MONTHS);
expect(fromNow(threeMonthsAgo)).toBe("3달 전");

const threeYearsAgo = createSometimesAgo(3 * YEARS);
expect(fromNow(threeYearsAgo)).toBe("3년 전");
});

it("formatDate를 호출하면 지정된 형식과 같이 format된 날짜를 반환한다.", () => {
/**
* JavaScript의 month index는 0부터 시작한다.
* 따라서 7을 입력하면 6월을 반환한다.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getMonth
*/
const MONTH = (month: number) => month - 1;

const DATE_20240716 = new Date(2024, MONTH(8), 16, 14, 30); // 2024년 8월 16일 14시 30분
expect(formatDate(DATE_20240716)).toBe("2024년 8월 16일 PM 2시 30분");

const DATE_20241103 = new Date(2024, MONTH(11), 3, 6, 8);
expect(formatDate(DATE_20241103)).toBe("2024년 11월 3일 AM 6시 8분");
});

it("getValidYear가 반환하는 Array의 첫 요소는 현재 연도여야 한다", () => {
const CURRENT_YEAR = new Date().getFullYear();
const validYearList = getValidYearList();

expect(validYearList[0]).toBe(CURRENT_YEAR);
});

it("getValidYear가 반환하는 Array의 끝 요소는 2021이어야 한다", () => {
const FIRST_YEAR = 2021;
const validYearList = getValidYearList();
const last = validYearList.length - 1;

expect(validYearList[last]).toBe(FIRST_YEAR);
});

it("getValidYear는 시작 연도부터 끝 연도 내 포함되는 모든 연도를 담고 있어야 한다", () => {
const validYearList = getValidYearList();
const FIRST_YEAR = 2021;
const CURRENT_YEAR = new Date().getFullYear();

for (let year = FIRST_YEAR; year <= CURRENT_YEAR; year += 1) {
expect(validYearList.includes(year)).toBe(true);
}
});
});
40 changes: 40 additions & 0 deletions hooks/useModal.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import "@testing-library/jest-dom";
import Modal from "@/components/(modal)/Modal";
import { render, screen, fireEvent } from "@testing-library/react";
import useModal from "./useModal";

function TestComponent() {
const { openModal, openToast, openConfirm, closeModal } = useModal();

return (
<div>
<button onClick={() => openModal({ component: <>@ubinquitous</> })}>openModal</button>
<button onClick={() => openConfirm({ content: "@ubinquitous", onConfirm: () => null })}>
openConfirm
</button>
<button onClick={() => openToast("@ubinquitous")}>openToast</button>
<button onClick={closeModal}>closeModal</button>
<Modal />
</div>
);
}

describe("useModal", () => {
it("아무런 동작을 하지 않을 때 아무런 모달도 뜨지 않는다", () => {
render(<TestComponent />);
expect(screen.queryByText("@ubinquitous")).not.toBeInTheDocument();
});

it("openModal을 호출하면 모달이 사용자 화면에 노출된다", () => {
render(<TestComponent />);
fireEvent.click(screen.getByText("openModal"));
expect(screen.queryByText("@ubinquitous")).toBeInTheDocument();
});

it("openModal 호출 후 closeModal을 호출하면 모달이 사라져야 한다", () => {
render(<TestComponent />);
fireEvent.click(screen.getByText("openModal"));
fireEvent.click(screen.getByText("closeModal"));
expect(screen.queryByText("@ubinquitous")).not.toBeInTheDocument();
});
});
42 changes: 42 additions & 0 deletions hooks/useUser.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { act, renderHook, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Provider } from "jotai";
import { getMyInformation } from "@/services/user/user.api";
import { Storage } from "@/storage";
import { PropsWithChildren } from "react";
import useUser from "./useUser";

jest.mock("../services/user/user.api.ts", () => ({ getMyInformation: jest.fn() }));
jest.mock("../storage", () => ({ Storage: { getItem: jest.fn() } }));

const TestWrapper = ({ children }: PropsWithChildren) => (
<Provider>
<QueryClientProvider client={new QueryClient()}>{children}</QueryClientProvider>
</Provider>
);

describe("useUser", () => {
it("액세스 토큰을 소유하지 않은 유저는 로그인이 되지 않은 유저로 간주한다", async () => {
const emptyUser = {
authority: "",
contributeDocs: [],
email: "",
id: 0,
isLogin: false,
name: "",
nickName: "",
};

(getMyInformation as jest.Mock).mockResolvedValue(null);
(Storage.getItem as jest.Mock).mockReturnValue(null);
const { result } = renderHook(() => useUser(), { wrapper: TestWrapper });

await act(async () => {
await waitFor(() => {
expect(result.current.user).toStrictEqual(emptyUser);
expect(result.current.isLoggedIn).toBe(false);
expect(result.current.isAdmin).toBe(false);
});
});
});
});
12 changes: 12 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import nextJest from "next/jest";

const createJestConfig = nextJest({
dir: "./",
});

/** @type {import('jest').Config} */
const config = {
testEnvironment: "jest-environment-jsdom",
};

export default createJestConfig(config);
1 change: 1 addition & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "@testing-library/jest-dom";
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
"start": "next start",
"postinstall": "husky install",
"format": "prettier --cache --write .",
"lint": "eslint --cache ."
"lint": "eslint --cache .",
"test": "jest"
},
"dependencies": {
"@next/third-parties": "^14.1.4",
"@tanstack/react-query": "^5.24.6",
"@types/jest": "^29.5.12",
"@types/react-beautiful-dnd": "^13.1.8",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
Expand Down Expand Up @@ -48,13 +50,19 @@
},
"devDependencies": {
"@stylexjs/babel-plugin": "^0.5.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@vanilla-extract/next-plugin": "^2.3.6",
"eslint": "^8",
"eslint-config-next": "14.1.1",
"husky": "^9.0.11",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"ts-node": "^10.9.2",
"typescript": "^5"
}
}
Loading