Skip to content
This repository has been archived by the owner on Jul 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #177 from ictsc/feature/add_problem_test
Browse files Browse the repository at this point in the history
add: Problem の hooks テストを追加
  • Loading branch information
K-shir0 authored Jul 6, 2023
2 parents 0ec0b62 + 110e20c commit a1023ff
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 19 deletions.
98 changes: 98 additions & 0 deletions __test__/hooks/problem.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { renderHook } from "@testing-library/react";
import matter from "gray-matter";
import { Mock, vi } from "vitest";

import useProblem from "@/hooks/problem";
import useProblems from "@/hooks/problems";
import { Problem, testProblem } from "@/types/Problem";
import { Result } from "@/types/_api";

vi.mock("@/hooks/problems");
vi.mock("gray-matter");

beforeEach(() => {
// toHaveBeenCalledTimes がテストごとにリセットされるようにする
vi.clearAllMocks();
});

describe("useProblem", () => {
test("問題が取得できる", () => {
// setup
const mockProblemsResult: Result<Problem[]> = {
code: 200,
data: [testProblem],
};

(useProblems as Mock).mockReturnValue({
problems: mockProblemsResult.data,
});
(matter as unknown as Mock).mockReturnValue({
data: { title: "テスト", body: "テスト本文" },
});

// when
renderHook(() => useProblem("test"));

// then
expect(matter).toBeCalledWith(testProblem.body);

// verify
expect(useProblems).toBeCalledTimes(1);
expect(matter).toBeCalledTimes(1);
});

test("問題が見つからない時", () => {
// setup
const mockProblemsResult: Result<Problem[]> = {
code: 200,
data: [testProblem],
};

(useProblems as Mock).mockReturnValue({
problems: mockProblemsResult.data,
});
(matter as unknown as Mock).mockReturnValue({
data: { title: "テスト" },
});

// when
const { result } = renderHook(() => useProblem("unknownId"));

// then
expect(result.current.matter).toBeNull();
expect(result.current.problem).toBeNull();
expect(result.current.isLoading).toBeFalsy();

// verify
expect(useProblems).toBeCalledTimes(1);
expect(matter).toBeCalledTimes(0);
});

test("問題の body が Null の時に matter が Null で返されるか", () => {
// setup
const bodyEmptyProblem = { ...testProblem, body: undefined };
const mockProblemsResult: Result<Problem[]> = {
code: 200,
data: [bodyEmptyProblem],
};
(useProblems as Mock).mockReturnValue({
problems: mockProblemsResult.data,
});
(matter as unknown as Mock).mockReturnValue({
data: null,
});

// when
const { result } = renderHook(() => useProblem("test"));

// then
expect(matter).toBeCalledWith("");
expect(result.current.matter).toBeNull();
expect(result.current.problem).toEqual({ ...bodyEmptyProblem, body: "" });
expect(result.current.isLoading).toBeFalsy();

// verify
expect(useProblems).toBeCalledTimes(1);
expect(matter).toBeCalledTimes(1);
});
});
59 changes: 59 additions & 0 deletions __test__/hooks/problems.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { renderHook } from "@testing-library/react";
import useSWR from "swr";
import { Mock, vi } from "vitest";

import useProblems from "@/hooks/problems";
import { Problem } from "@/types/Problem";
import { Result } from "@/types/_api";

vi.mock("swr");

beforeEach(() => {
// toHaveBeenCalledTimes がテストごとにリセットされるようにする
vi.clearAllMocks();
});

describe("useProblems", () => {
it("問題一覧が取得できる", () => {
// setup
const mockProblemResult: Result<Problem[]> = {
code: 200,
data: [],
};

(useSWR as Mock).mockReturnValue({
data: mockProblemResult,
isLoading: false,
});

// when
const { result } = renderHook(() => useProblems());

// then
expect(result.current.problems).toEqual(mockProblemResult.data);

// verify
expect(useSWR).toBeCalledTimes(1);
});

it("問題一覧が取得できない", () => {
// setup
const mockProblemResult: Result<Problem[]> = {
code: 200,
data: null,
};

(useSWR as Mock).mockReturnValue({
data: mockProblemResult,
});

// when
const { result } = renderHook(() => useProblems());

// then
expect(result.current.problems).toEqual([]);

// verify
expect(useSWR).toBeCalledTimes(1);
});
});
24 changes: 5 additions & 19 deletions hooks/problem.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
import matter from "gray-matter";
import useSWR from "swr";

import useApi from "@/hooks/api";
import useProblems from "@/hooks/problems";
import { Matter } from "@/types/Problem";
import { ProblemResult } from "@/types/_api";

export const useProblems = () => {
const { client } = useApi();

const fetcher = (url: string) => client.get<ProblemResult>(url);

const { data, mutate, isLoading } = useSWR("problems", fetcher);

return {
problems: data?.data?.problems ?? [],
mutate,
isLoading,
};
};

export const useProblem = (code: string | null) => {
const useProblem = (code: string | null) => {
const { problems } = useProblems();

const problem = problems.find((prob) => prob.code === code) ?? null;
Expand All @@ -34,11 +18,13 @@ export const useProblem = (code: string | null) => {

const matterResult = matter(problem.body ?? "");
const matterData = matterResult.data as Matter;
const newProblem = { ...problem, body: matterResult.content };
const newProblem = { ...problem, body: matterResult.content ?? "" };

return {
matter: matterData,
problem: newProblem,
isLoading: false,
};
};

export default useProblem;
20 changes: 20 additions & 0 deletions hooks/problems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import useSWR from "swr";

import useApi from "@/hooks/api";
import { ProblemResult } from "@/types/_api";

const useProblems = () => {
const { client } = useApi();

const fetcher = (url: string) => client.get<ProblemResult>(url);

const { data, mutate, isLoading } = useSWR("problems", fetcher);

return {
problems: data?.data?.problems ?? [],
mutate,
isLoading,
};
};

export default useProblems;
16 changes: 16 additions & 0 deletions types/Problem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,19 @@ interface ConnectionInfo {
password?: string;
command?: string;
}

export const testProblem: Problem = {
id: "id",
code: "test",
title: "テスト",
body: "---\ntitle: テスト\n---\n# テスト本文",
point: 100,
solved_criterion: 100,
previous_problem_id: null,
author_id: "author_id",
unchecked: null,
unchecked_near_overdue: null,
unchecked_overdue: null,
current_point: 100,
is_solved: false,
};

0 comments on commit a1023ff

Please sign in to comment.