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

[ Feature/dev 80 ] 워크북 하단 버튼 기능 구현 #140

Merged
merged 4 commits into from
Aug 4, 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
13 changes: 11 additions & 2 deletions src/app/workbook/[id]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { createMetadata } from "@shared/utils/metadata";

import queryClient from "@api/queryClient";
import { getWorkbookQueryOptions } from "@workbook/remotes/getWorkbookQueryOptions";
import TopBar from "@shared/components/TopBar";


export async function generateMetadata({
params,
Expand All @@ -30,5 +32,12 @@ interface WorkbookLayoutProps {
}

export default function WorkbookLayout({ children }: WorkbookLayoutProps) {
return <section className="w-full">{children}</section>;
}
return (
<section className="flex h-auto w-full flex-col justify-between">
<div className="mx-[20px] mb-[10px] flex flex-col">
<TopBar />
{children}
</div>
</section>
)
}
16 changes: 9 additions & 7 deletions src/app/workbook/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
"use client";

import dynamic from "next/dynamic";
import { usePathname } from "next/navigation";

import { useEffect } from "react";

import { useQuery } from "@tanstack/react-query";

import { getWorkbookQueryOptions } from "@workbook/remotes/getWorkbookQueryOptions";
import { getWorkbookId } from "@workbook/utils";
import { EVENT_NAME } from "@shared/constants/mixpanel";
import { Mixpanel } from "@shared/utils/mixpanel";

import WorkbookButton from "@workbook/components/WorkbookButton";
import WorkbookSkeleton from "@workbook/components/WorkbookSkeleton";
import WriterInfo from "@workbook/components/WriterInfo";
import dynamic from "next/dynamic";
import { getWorkbookQueryOptions } from "@workbook/remotes/getWorkbookQueryOptions";
import { getWorkbookId } from "@workbook/utils";

import { EVENT_NAME } from "@shared/constants/mixpanel";
import { Mixpanel } from "@shared/utils/mixpanel";
import { useEffect } from "react";

const TitleSection = dynamic(() => import("@shared/components/TitleSection"), {
loading: () => <WorkbookSkeleton.TitleSkeleton />,
Expand Down Expand Up @@ -92,7 +94,7 @@ export default function WorkbookPage() {

<OverviewSection overview={workbookInfo.description} />
<CurriculumSection curriculumItems={workbookInfo.articles} />
{/* <SubscribeBottomBar /> */}
<WorkbookButton />
</>
)}
</article>
Expand Down
4 changes: 2 additions & 2 deletions src/auth/components/EmailForm/EmailForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ describe("이메일 폼 컴포넌트", () => {
it("성공적인 제출 후 검증 페이지로 이동해야 한다", async () => {
const email = "[email protected]"
mockOnSubmit.mockImplementationOnce((values) => {
const response = { data: { data: { sendAuth: true } } };
response.data?.data?.sendAuth &&
const response = { data: { data: { isSendAuth: true } } };
response.data?.data?.isSendAuth &&
mockPush(`/auth/validation?email=${email}`);
});

Expand Down
4 changes: 2 additions & 2 deletions src/auth/hooks/useEmailForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export const useEmailForm = () => {
try {
memberSave(values, {
onSuccess: (response: ApiResponse<memberSaveResponse>) => {
console.log('res', response);
console.log('res', response.data?.data);

if (response.data?.data?.sendAuth) {
if (response.data?.data?.isSendAuth) {
// redirect to validation page
router.push(`/auth/validation?email=${values.email}`)
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/auth/types/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export type memberSaveBody = {
}

export type memberSaveResponse = {
sendAuth: boolean
isSendAuth: boolean
}

export type tokenResponse = {
Expand Down
2 changes: 1 addition & 1 deletion src/mocks/response/members.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"data": {
"sendAuth": true
"isSendAuth": true
},
"message": "성공"
}
18 changes: 18 additions & 0 deletions src/workbook/components/WorkbookButtonItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Button } from "@shared/components/ui/button"
import { cn } from "@shared/utils/cn"

interface WorkbookButtonItemProps {
title: string
handleClick: () => void
}

export default function WorkbookButtonItem ({ title, handleClick }: WorkbookButtonItemProps) {
return (
<Button onClick={handleClick} className={cn(
"w-full h-14 px-[98px] pt-[18px] pb-[17px] bg-black justify-center items-center rounded-none",
"text-white text-sm font-medium"
)}>
{title}
</Button>
)
}
129 changes: 129 additions & 0 deletions src/workbook/components/WorkbookButton/WorkbookButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";

import queryClient from "@api/queryClient";

import { WORKBOOK_BTNS } from "@workbook/constants/buttons";

import WorkbookButton from ".";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

const mockRouterPush = vi.fn();
const mockPostSubscribeWorkbook = vi.fn();

describe("WorkbookButton 컴포넌트 테스트", () => {
const renderWithClient = () => {
const queryClient = new QueryClient();
return render(
<QueryClientProvider client={queryClient}>
<WorkbookButton />
</QueryClientProvider>,
);
};
Comment on lines +17 to +24
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queryClientProviders 컴포넌트 활용할 수 있습니다!


beforeAll(() => {
vi.mock("next/navigation", async () => {
const actual =
await vi.importActual<typeof import("next/navigation")>(
"next/navigation",
);
return {
...actual,
useRouter: vi.fn(() => ({
push: mockRouterPush,
})),
useSearchParams: vi.fn(() => ({
get: vi.fn().mockReturnValueOnce(() => "1"),
})),
};
});

vi.mock("@common/hooks/useSusbscribeWorkbook", () => ({
default: () => ({
postSubscribeWorkbook: mockPostSubscribeWorkbook,
}),
}));
});

beforeEach(() => {
mockRouterPush.mockClear();
mockPostSubscribeWorkbook.mockClear();

vi.resetModules();
});

// it("로그인한 사용자의 경우 구독 버튼이 렌더링되어야 한다", async () => {
// vi.doMock("@shared/hooks/useIsLogin", () => ({
// default: () => true,
// }));

// renderWithClient();

// await waitFor(() => {
// expect(screen.getByText(WORKBOOK_BTNS.SUB)).toBeInTheDocument();
// })
// });

it("로그인하지 않은 사용자의 경우 로그인 및 구독 버튼이 렌더링되어야 한다", async () => {
vi.doMock("@shared/hooks/useIsLogin", () => ({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

찾아보니까 doMock은 테스트 코드 내에서 특정 시점에 모킹을 설정할 때 사용된다고 하네요!! 항상 최상단에서 모킹했는데
위 방법도 좋은것같네요! 배워갑니다!!

default: () => false,
}));

renderWithClient();

await waitFor(() => {
expect(screen.getByText(WORKBOOK_BTNS.LOGIN_AND_SUB)).toBeInTheDocument();
});
});

// it("로그인한 사용자가 구독 버튼을 클릭하면 postSubscribeWorkbook이 호출되고 쿼리가 다시 패치되어야 한다", async () => {
// vi.doMock("@shared/hooks/useIsLogin", () => ({
// default: () => true,
// }));

// renderWithClient();

// const user = userEvent.setup();
// const subscribeButton = screen.getByText(WORKBOOK_BTNS.SUB);
// await user.click(subscribeButton);

// await waitFor(() => {
// expect(mockPostSubscribeWorkbook).toHaveBeenCalledWith({
// workbookId: "1",
// handleSucess: expect.any(Function),
// });

// const handleSuccess =
// mockPostSubscribeWorkbook.mock.calls[0][0].handleSucess;
// handleSuccess();

// expect(queryClient.refetchQueries).toHaveBeenCalledWith({
// queryKey: ["GET_SUBSCRIBE_WORKBOOKS"],
// });
// expect(queryClient.refetchQueries).toHaveBeenCalledWith({
// queryKey: ["GET_WORKBOOKS_WITH_CATEGORY"],
// });
// });
// });

it("로그인하지 않은 사용자가 로그인 및 구독 버튼을 클릭하면 인증 페이지로 리다이렉트 되어야 한다", async () => {
vi.doMock("@shared/hooks/useIsLogin", () => ({
default: () => false,
}));

renderWithClient();

const user = userEvent.setup();
const loginAndSubscribeButton = screen.getByText(
WORKBOOK_BTNS.LOGIN_AND_SUB,
);

await user.click(loginAndSubscribeButton);

await waitFor(() => {
expect(mockRouterPush).toHaveBeenCalledWith("/auth");
});
});
});
55 changes: 55 additions & 0 deletions src/workbook/components/WorkbookButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useRouter, useSearchParams } from "next/navigation";

import queryClient from "@api/queryClient";

import useIsLogin from "@shared/hooks/useIsLogin";

import { WORKBOOK_BTNS } from "@workbook/constants/buttons";

import { QUERY_KEY } from "@main/remotes";

import WorkbookButtonItem from "../\bWorkbookButtonItem";
import useSusbscribeWorkbook from "@common/hooks/useSusbscribeWorkbook";

export default function WorkbookButton() {
const isLogin = useIsLogin();
const { postSubscribeWorkbook } = useSusbscribeWorkbook();
const router = useRouter();

const parms = useSearchParams();
const workbookId = parms.get("workbookId") as string;

const handleLoginClick = () => {
postSubscribeWorkbook({
workbookId: workbookId,
handleSucess: () => {
queryClient.refetchQueries({
queryKey: [QUERY_KEY.GET_SUBSCRIBE_WORKBOOKS],
});
queryClient.refetchQueries({
queryKey: [QUERY_KEY.GET_WORKBOOKS_WITH_CATEGORY],
});
},
});
};

const handleWithoutLoginClick = () => {
router.push("/auth");
};

return (
<section className="px-[20px] pb-[44px]">
{isLogin ? (
<WorkbookButtonItem
title={WORKBOOK_BTNS.SUB}
handleClick={handleLoginClick}
/>
) : (
<WorkbookButtonItem
title={WORKBOOK_BTNS.LOGIN_AND_SUB}
handleClick={handleWithoutLoginClick}
/>
)}
</section>
);
}
4 changes: 4 additions & 0 deletions src/workbook/constants/buttons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const WORKBOOK_BTNS = {
LOGIN_AND_SUB: "로그인하고 학습 시작하기",
SUB: "구독하기"
}
Loading