Skip to content

Commit

Permalink
Merge pull request #162 from Team-INSERT/test/hooks
Browse files Browse the repository at this point in the history
test : custom hooks test
  • Loading branch information
Ubinquitous authored Aug 16, 2024
2 parents 93f5c0e + 0e4cab2 commit a60df8c
Show file tree
Hide file tree
Showing 8 changed files with 2,424 additions and 32 deletions.
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

0 comments on commit a60df8c

Please sign in to comment.