diff --git a/src/components/Leaderboard/Leaderboard.stories.tsx b/src/components/Leaderboard/Leaderboard.stories.tsx new file mode 100644 index 0000000..fbb5e57 --- /dev/null +++ b/src/components/Leaderboard/Leaderboard.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { MemoryRouter, Route, Routes } from "react-router-dom"; +import Leaderboard from "./Leaderboard"; + +const pathname = `/leaderboard`; + +const meta = { + component: Leaderboard, + decorators: [ + (Story) => ( + + + } /> + + + ), + ], +} satisfies Meta; + +export default meta; + +export const Default: StoryObj = {}; diff --git a/src/components/Leaderboard/Leaderboard.test.tsx b/src/components/Leaderboard/Leaderboard.test.tsx new file mode 100644 index 0000000..cd1752d --- /dev/null +++ b/src/components/Leaderboard/Leaderboard.test.tsx @@ -0,0 +1,83 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { MemoryRouter, Route, Routes } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import Leaderboard from "./Leaderboard"; + +const queryClient = new QueryClient(); + +describe("", () => { + beforeEach(() => + render( + + + + } /> + + + , + ), + ); + + it("renders the members list section", () => { + expect( + screen.getByRole("region", { name: /members list/i }), + ).toBeInTheDocument(); + }); + + it("renders the title", () => { + const heading = screen.getByRole("heading", { level: 1 }); + expect(heading).toHaveTextContent("Leaderboard"); + }); + + it("renders the member information", () => { + const members = [ + { name: "DaleSeo", solved: 71, rank: "새싹" }, + { name: "sounmind", solved: 69, rank: "나무" }, + { name: "yolophg", solved: 65, rank: "새싹" }, + { name: "Sunjae95", solved: 63, rank: "나무" }, + { name: "HC-kang", solved: 62, rank: "나무" }, + { name: "SamTheKorean", solved: 60, rank: "나무" }, + ]; + + const memberItems = screen.getAllByRole("listitem"); + + expect(memberItems).toHaveLength(members.length); + + members.forEach((member, index) => { + const memberItem = memberItems[index]; + expect(memberItem).toHaveTextContent(`등급: ${member.rank}`); + expect(memberItem).toHaveTextContent(`진행 상황: ${member.solved}`); + }); + }); + + it("renders the links for members", () => { + const members = [ + { name: "DaleSeo" }, + { name: "sounmind" }, + { name: "yolophg" }, + { name: "Sunjae95" }, + { name: "HC-kang" }, + { name: "SamTheKorean" }, + ]; + + const progressLinks = screen.getAllByRole("link", { name: "풀이 보기" }); + const certificateLinks = screen.getAllByRole("link", { + name: "수료증 보기", + }); + + expect(progressLinks).toHaveLength(members.length); + expect(certificateLinks).toHaveLength(members.length); + + members.forEach((member, index) => { + expect(progressLinks[index]).toHaveAttribute( + "href", + `/progress?member=${member.name}`, + ); + expect(certificateLinks[index]).toHaveAttribute( + "href", + `/certificate?member=${member.name}`, + ); + }); + }); +}); diff --git a/src/components/Leaderboard/Leaderboard.tsx b/src/components/Leaderboard/Leaderboard.tsx new file mode 100644 index 0000000..cb3f95a --- /dev/null +++ b/src/components/Leaderboard/Leaderboard.tsx @@ -0,0 +1,36 @@ +export default function Leaderboard() { + const members = [ + { name: "DaleSeo", solved: 71, rank: "새싹" }, + { name: "sounmind", solved: 69, rank: "나무" }, + { name: "yolophg", solved: 65, rank: "새싹" }, + { name: "Sunjae95", solved: 63, rank: "나무" }, + { name: "HC-kang", solved: 62, rank: "나무" }, + { name: "SamTheKorean", solved: 60, rank: "나무" }, + ]; + + return ( +
+

Leaderboard

+ +
+

Members List

+ +
+
+ ); +}