Skip to content

Commit

Permalink
[Fix] 컴포넌트 테스트에서 act console.error 발생하는 이슈를 수정하라
Browse files Browse the repository at this point in the history
- 컴포넌트 관련 테스트에서 react-query hooks로 인해 act console.error 발생
- react-query hooks를 jest mocking
- dynamic import 전역 mocking 추가
- 추후 msw로 변경
  • Loading branch information
saseungmin committed May 4, 2022
1 parent 6bce4ec commit bc5e8d6
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 21 deletions.
18 changes: 18 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ import 'jest-plugin-context/setup';
import 'given2/setup';

jest.mock('@/utils/rehypePrism');
jest.mock('next/dynamic', () => ({
__esModule: true,
default: (...props) => {
const dynamicModule = jest.requireActual('next/dynamic');
const dynamicActualComp = dynamicModule.default;
const RequiredComponent = dynamicActualComp(props[0]);

if (RequiredComponent.preload) {
RequiredComponent.preload();

return RequiredComponent;
}

RequiredComponent.render.preload();

return RequiredComponent;
},
}));

setLogger({
log: console.log,
Expand Down
34 changes: 22 additions & 12 deletions src/components/common/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import { fireEvent, render, screen } from '@testing-library/react';

import ReactQueryWrapper from '@/test/ReactQueryWrapper';
import useFetchAlertAlarms from '@/hooks/api/alarm/useFetchAlertAlarms';

import FIXTURE_ALARM from '../../../fixtures/alarm';

import Header from './Header';

jest.mock('@/hooks/api/alarm/useFetchAlertAlarms');

describe('Header', () => {
const handleClick = jest.fn();

beforeEach(() => {
jest.clearAllMocks();

(useFetchAlertAlarms as jest.Mock).mockImplementation(() => ({
data: [FIXTURE_ALARM],
}));
});

const renderHeader = () => render((
<ReactQueryWrapper>
<Header
signOut={jest.fn()}
isScrollTop
user={given.user}
onClick={handleClick}
hasBackground
isLoading={given.isLoading}
hasOnlyLogo={given.hasOnlyLogo}
/>
</ReactQueryWrapper>
<Header
signOut={jest.fn()}
isScrollTop
user={given.user}
onClick={handleClick}
hasBackground
isLoading={given.isLoading}
hasOnlyLogo={given.hasOnlyLogo}
/>
));

context('signup 페이지인 경우', () => {
Expand Down
7 changes: 7 additions & 0 deletions src/components/detail/WriterStatusButtons.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { useRouter } from 'next/router';

import useFetchApplicants from '@/hooks/api/applicant/useFetchApplicants';
import useRemoveGroup from '@/hooks/api/group/useRemoveGroup';
import useRemoveGroupThumbnail from '@/hooks/api/storage/useRemoveGroupThumbnail';
import InjectMockProviders from '@/test/InjectMockProviders';

import FIXTURE_APPLICANT from '../../../fixtures/applicant';
import FIXTURE_GROUP from '../../../fixtures/group';

import WriterStatusButtons from './WriterStatusButtons';

jest.mock('@/hooks/api/group/useRemoveGroup');
jest.mock('@/hooks/api/storage/useRemoveGroupThumbnail');
jest.mock('@/hooks/api/applicant/useFetchApplicants');
jest.mock('next/router', () => ({
useRouter: jest.fn(),
}));
Expand Down Expand Up @@ -38,6 +41,10 @@ describe('WriterStatusButtons', () => {
(useRemoveGroupThumbnail as jest.Mock).mockImplementation(() => ({
mutate: removeGroupThumbnailMutate,
}));

(useFetchApplicants as jest.Mock).mockImplementation(() => ({
data: [FIXTURE_APPLICANT],
}));
});

const renderWriterStatusButtons = (isCompleted = false) => render((
Expand Down
36 changes: 36 additions & 0 deletions src/components/myInfo/MyInfoLayout.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
import { render } from '@testing-library/react';

import useFetchAlertAlarms from '@/hooks/api/alarm/useFetchAlertAlarms';
import useFetchUserProfile from '@/hooks/api/auth/useFetchUserProfile';
import useSignOut from '@/hooks/api/auth/useSignOut';
import useFetchUserAppliedGroups from '@/hooks/api/group/useFetchUserAppliedGroups';
import useFetchUserRecruitedGroups from '@/hooks/api/group/useFetchUserRecruitedGroups';
import InjectMockProviders from '@/test/InjectMockProviders';

import FIXTURE_ALARM from '../../../fixtures/alarm';
import FIXTURE_GROUP from '../../../fixtures/group';
import FIXTURE_PROFILE from '../../../fixtures/profile';

import getMyInfoLayout from './MyInfoLayout';

jest.mock('@/hooks/api/auth/useFetchUserProfile');
jest.mock('@/hooks/api/group/useFetchUserAppliedGroups');
jest.mock('@/hooks/api/group/useFetchUserRecruitedGroups');
jest.mock('@/hooks/api/alarm/useFetchAlertAlarms');
jest.mock('@/hooks/api/auth/useSignOut');
jest.mock('next/router', () => ({
useRouter: jest.fn().mockImplementation(() => ({
pathname: '/',
})),
}));

describe('MyInfoLayout', () => {
beforeEach(() => {
(useFetchUserProfile as jest.Mock).mockImplementation(() => ({
data: FIXTURE_PROFILE,
}));

(useFetchUserAppliedGroups as jest.Mock).mockImplementation(() => ({
data: FIXTURE_GROUP,
}));

(useFetchUserRecruitedGroups as jest.Mock).mockImplementation(() => ({
data: FIXTURE_GROUP,
}));

(useSignOut as jest.Mock).mockImplementation(() => ({
mutate: jest.fn(),
}));

(useFetchAlertAlarms as jest.Mock).mockImplementation(() => ({
data: [FIXTURE_ALARM],
}));
});

const GetLayout = getMyInfoLayout('setting');
function MockComponent(): JSX.Element {
return <>Test</>;
Expand Down
4 changes: 2 additions & 2 deletions src/containers/home/StatusBarContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { groupsConditionState } from '@/recoil/group/atom';
import Divider from '@/styles/Divider';
import { body1Font } from '@/styles/fontStyles';

const DynamicComponentWithNoSSR = dynamic(
const SwitchButton = dynamic(
() => import('@/components/common/SwitchButton'),
{ ssr: false },
);
Expand Down Expand Up @@ -67,7 +67,7 @@ function StatusBarContainer(): ReactElement {
</div>
<RecruitmentDeadline>
<span>모집 마감 안보기</span>
<DynamicComponentWithNoSSR
<SwitchButton
defaultChecked={!!initFilterCompleted}
onChange={() => onToggle(!isFilterCompleted)}
/>
Expand Down
29 changes: 25 additions & 4 deletions src/containers/myInfo/MyInfoTabContainer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
import { render } from '@testing-library/react';

import InjectMockProviders from '@/test/InjectMockProviders';
import useFetchUserProfile from '@/hooks/api/auth/useFetchUserProfile';
import useFetchUserAppliedGroups from '@/hooks/api/group/useFetchUserAppliedGroups';
import useFetchUserRecruitedGroups from '@/hooks/api/group/useFetchUserRecruitedGroups';

import FIXTURE_GROUP from '../../../fixtures/group';
import FIXTURE_PROFILE from '../../../fixtures/profile';

import MyInfoTabContainer from './MyInfoTabContainer';

jest.mock('@/hooks/api/auth/useFetchUserProfile');
jest.mock('@/hooks/api/group/useFetchUserAppliedGroups');
jest.mock('@/hooks/api/group/useFetchUserRecruitedGroups');

describe('MyInfoTabContainer', () => {
beforeEach(() => {
(useFetchUserProfile as jest.Mock).mockImplementation(() => ({
data: FIXTURE_PROFILE,
}));

(useFetchUserAppliedGroups as jest.Mock).mockImplementation(() => ({
data: FIXTURE_GROUP,
}));

(useFetchUserRecruitedGroups as jest.Mock).mockImplementation(() => ({
data: FIXTURE_GROUP,
}));
});

const renderMyInfoTabContainer = () => render((
<InjectMockProviders>
<MyInfoTabContainer activeTab="setting" />
</InjectMockProviders>
<MyInfoTabContainer activeTab="setting" />
));

it('내 정보 탭에 대한 내용이 나타나야만 한다', () => {
Expand Down
33 changes: 30 additions & 3 deletions src/pages/detail/[id].test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,28 @@ import { QueryClient } from 'react-query';
import { render } from '@testing-library/react';
import { GetServerSidePropsContext } from 'next';

import useFetchAlertAlarms from '@/hooks/api/alarm/useFetchAlertAlarms';
import useApplyGroup from '@/hooks/api/applicant/useApplyGroup';
import useCancelApply from '@/hooks/api/applicant/useCancelApply';
import useFetchApplicants from '@/hooks/api/applicant/useFetchApplicants';
import useFetchUserProfile from '@/hooks/api/auth/useFetchUserProfile';
import useGetUser from '@/hooks/api/auth/useGetUser';
import useSignOut from '@/hooks/api/auth/useSignOut';
import useAddComment from '@/hooks/api/comment/useAddComment';
import useDeleteComment from '@/hooks/api/comment/useDeleteComment';
import useFetchComments from '@/hooks/api/comment/useFetchComments';
import useFetchGroup from '@/hooks/api/group/useFetchGroup';
import useRemoveGroup from '@/hooks/api/group/useRemoveGroup';
import useRemoveGroupThumbnail from '@/hooks/api/storage/useRemoveGroupThumbnail';
import { getGroupDetail } from '@/services/api/group';
import InjectMockProviders from '@/test/InjectMockProviders';
import InjectTestingRecoilState from '@/test/InjectTestingRecoilState';
import { filteredWithSanitizeHtml } from '@/utils/filter';

import FIXTURE_ALARM from '../../../fixtures/alarm';
import APPLICANT_FIXTURE from '../../../fixtures/applicant';
import COMMENT_FIXTURE from '../../../fixtures/comment';
import GROUP_FIXTURE from '../../../fixtures/group';
import FIXTURE_PROFILE from '../../../fixtures/profile';

import DetailPage, { getServerSideProps } from './[id].page';

Expand All @@ -32,6 +40,12 @@ jest.mock('@/hooks/api/comment/useFetchComments');
jest.mock('@/hooks/api/group/useFetchGroup');
jest.mock('@/utils/filter');
jest.mock('@/hooks/api/group/useIncreaseView');
jest.mock('@/hooks/api/alarm/useFetchAlertAlarms');
jest.mock('@/hooks/api/auth/useGetUser');
jest.mock('@/hooks/api/auth/useFetchUserProfile');
jest.mock('@/hooks/api/auth/useSignOut');
jest.mock('@/hooks/api/group/useRemoveGroup');
jest.mock('@/hooks/api/storage/useRemoveGroupThumbnail');

jest.mock('next/router', () => ({
useRouter: jest.fn().mockImplementation(() => ({
Expand Down Expand Up @@ -60,16 +74,29 @@ describe('DetailPage', () => {
data: [APPLICANT_FIXTURE],
isLoading: false,
}));
(useFetchAlertAlarms as jest.Mock).mockImplementation(() => ({
data: [FIXTURE_ALARM],
}));
(useGetUser as jest.Mock).mockImplementation(() => ({
data: FIXTURE_PROFILE,
}));
(useFetchUserProfile as jest.Mock).mockImplementation(() => ({
data: FIXTURE_PROFILE,
}));

(useRemoveGroupThumbnail as jest.Mock).mockImplementation(() => ({ mutate }));
(useRemoveGroup as jest.Mock).mockImplementation(() => ({ mutate }));
(useSignOut as jest.Mock).mockImplementation(() => ({ mutate }));
(useApplyGroup as jest.Mock).mockImplementation(() => ({ mutate }));
(useCancelApply as jest.Mock).mockImplementation(() => ({ mutate }));
(useAddComment as jest.Mock).mockImplementation(() => ({ mutate }));
(useDeleteComment as jest.Mock).mockImplementation(() => ({ mutate }));
});

const renderDetailPage = () => render((
<InjectMockProviders>
<InjectTestingRecoilState>
<DetailPage />
</InjectMockProviders>
</InjectTestingRecoilState>
));

it('detail 페이지에 대한 내용이 나타나야만 한다', () => {
Expand Down
22 changes: 22 additions & 0 deletions src/test/InjectResponsiveContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
PropsWithChildren, ReactElement, useMemo,
} from 'react';
import { Context as ResponsiveContext } from 'react-responsive';

interface Props {
width?: number;
}

function InjectResponsiveContext({
width = 700, children,
}: PropsWithChildren<Props>): ReactElement {
const value = useMemo(() => ({ width }), []);

return (
<ResponsiveContext.Provider value={value}>
{children}
</ResponsiveContext.Provider>
);
}

export default InjectResponsiveContext;

0 comments on commit bc5e8d6

Please sign in to comment.