Skip to content

Commit

Permalink
test: 캐릭터 상세 헤더 테스트 작성
Browse files Browse the repository at this point in the history
  • Loading branch information
stakbucks committed Mar 10, 2024
1 parent dd18769 commit c1c6bda
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"tailwindcss": "^3.3.0",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"typescript": "^5",
"vite-plugin-magical-svg": "^1.2.1",
"vite-tsconfig-paths": "^4.3.1",
"vitest": "^1.3.1",
"vitest-canvas-mock": "^0.3.3"
Expand Down
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 81 additions & 2 deletions src/__tests__/character.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,85 @@
import CharacterDetailPage from '@/app/(routes)/character/[id]/page';
import render from './setups/render';
import getCharacterDetail from '@/services/character/getCharacterDetail';
import { getCharacterMemos } from '@/services/character/getCharacterMemos';
import getCharacterSpecialty from '@/services/character/getCharacterSpecialty';
import getMember, { IsLoggedIn, checkIsLoggedIn } from '@/services/auth/getMember';
import { redirect } from 'next/navigation';
import { act, renderHook, screen, waitFor } from '@testing-library/react';
import Header from '@/app/(routes)/character/[id]/_components/header';
import { Suspense } from 'react';

it('', async () => {
render(await CharacterDetailPage({ params: { id: 2 } }));
vi.mock('@/services/auth/getMember');
vi.mock('@/services/character/getCharacterDetail');
vi.mock('@/services/character/getCharacterMemos');
vi.mock('@/services/character/getCharacterSpecialty');

vi.mock('next/navigation', async () => {
const actual = await vi.importActual('next/navigation');
return {
...actual,
useRouter: vi.fn(),
usePathname: () => 'chracter/5',
redirect: vi.fn(),
useSearchParams: () => ({ get: () => vi.fn() }),
};
});

vi.mocked(getMember).mockResolvedValue({ memberId: 2, characterCount: 3, memoCount: 5 });
vi.mocked(getCharacterDetail).mockResolvedValue({
id: 5,
name: '테스트 캐릭터',
level: 4,
totalExp: 2,
currentExp: 2,
nextExp: 12,
characterImage:
'https://anotherme.today/_next/image?url=https%3A%2F%2Fkr.object.ncloudstorage.com%2Fkekeche-character%2Fitem%2F0.webp&w=750&q=100',
itemImage:
'https://anotherme.today/_next/image?url=https%3A%2F%2Fkr.object.ncloudstorage.com%2Fkekeche-character%2Fitem%2F0.webp&w=750&q=100', // NOTE: 아이템 선택 안한 경우, 해당 필드가 없을 수 있음.
keywords: [1, 2, 3],
});
vi.mocked(getCharacterSpecialty).mockResolvedValue({
specialties: [{ id: 1, content: '테스트하기', memoCnt: 3 }],
});
vi.mocked(getCharacterMemos).mockResolvedValue({
memos: [],
totalPages: 1,
totalCount: 1,
page: 1,
size: 1,
has_next: false,
has_previous: false,
isFirstPage: true,
isLastPage: true,
});

describe('로그인 안한 경우', () => {
it('홈 페이지로 리다이렉트 합니다.', async () => {
vi.mocked(checkIsLoggedIn).mockResolvedValue({ isLoggedIn: false });
await act(async () => {
render(<Suspense>{await CharacterDetailPage({ params: { id: 2 } })}</Suspense>);
});
expect(redirect).toHaveBeenNthCalledWith(1, '/');
});
});

describe('Header', () => {
it('헤더가 올바르게 렌더링 됩니다.', async () => {
vi.mocked(getMember).mockResolvedValue({ memberId: 2, characterCount: 3, memoCount: 5 });
vi.mocked(getCharacterDetail).mockResolvedValue({
id: 5,
name: '테스트 캐릭터',
level: 4,
totalExp: 2,
currentExp: 2,
nextExp: 12,
characterImage: '',
itemImage: '', // NOTE: 아이템 선택 안한 경우, 해당 필드가 없을 수 있음.
keywords: [1, 2, 3],
});
render(<Header />);
const text = await screen.findByText('성장 기록지');
expect(text).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion src/__tests__/home.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ vi.mock('@/services/auth/getMember');

describe('홈 페이지 테스트', () => {
it('로그인 안했을 때 홈 페이지를 렌더링 합니다.', async () => {
vi.mocked(checkIsLoggedIn).mockReturnValue(Promise.resolve({ isLoggedIn: true }));
vi.mocked(checkIsLoggedIn).mockReturnValue(Promise.resolve({ isLoggedIn: false }));
render(await Home());
const button = screen.getByText('로그인하기');

Expand Down
4 changes: 2 additions & 2 deletions src/app/(routes)/character/[id]/_components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { getCookie } from 'cookies-next';
import { usePathname, useRouter } from 'next/navigation';
import React, { useState } from 'react';

export default React.memo(function Header() {
export default function Header() {
const router = useRouter();
const pathname = usePathname();

Expand Down Expand Up @@ -120,4 +120,4 @@ export default React.memo(function Header() {
/>
</>
);
});
}
22 changes: 22 additions & 0 deletions src/app/(routes)/character/[id]/hooks/useHeaderQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import getMember from '@/services/auth/getMember';
import getCharacterDetail from '@/services/character/getCharacterDetail';
import { useQueries } from '@tanstack/react-query';
import { getCookie } from 'cookies-next';

export default function useHeaderQueries(characterId: number) {
const [{ data: member }, { data: character }] = useQueries({
queries: [
{
queryKey: ['auth'],
queryFn: () => getMember({ accessToken: `${getCookie('accessToken')}` }),
},
{
queryKey: ['character', 'detail', characterId],
queryFn: () => getCharacterDetail({ accessToken: `${getCookie('accessToken')}`, characterId }),
staleTime: 1000 * 60 * 5,
},
],
});

return { member, character };
}
2 changes: 1 addition & 1 deletion src/app/(routes)/character/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default async function CharacterDetailPage({ params: { id } }: { params:
<Link href={`?write=${characterId}`}>
<CTAButton>
<div className=" flex w-full items-center justify-center gap-[8px]">
<NoteEditIcon /> <span>먹이주기</span>
<NoteEditIcon /> <span>{'먹이주기'}</span>
</div>
</CTAButton>
</Link>
Expand Down
2 changes: 1 addition & 1 deletion src/components/character-detail/character-image.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BubbleTexts } from '@/constants/bubble-texts';
import { Character } from '@/types/character';
import Image from 'next/image';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import Polygon from '@/assets/icons/polygon.svg';
import { AnimatePresence, AnimationProps, motion } from 'framer-motion';

Expand Down
3 changes: 2 additions & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import path from 'path';
import magicalSvg from 'vite-plugin-magical-svg';

export default defineConfig({
plugins: [react()],
plugins: [react(), magicalSvg({ target: 'react' })],
test: {
environment: 'jsdom',
globals: true,
Expand Down

0 comments on commit c1c6bda

Please sign in to comment.