From 5e5335b24aa6aa5a0ef70af7bd7e93ee1582b6cf Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 06:46:23 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20[testing=20improvement]=20/api/d?= =?UTF-8?q?ashboard/summary=20=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/app/api/dashboard/summary/route.test.ts を作成 - 認証エラー (401)、正常系 (200)、および各種データ取得エラー (500) のテストケースを実装 - next-auth および GitHub API 関連のライブラリ関数をモックして検証するように構成 Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com> --- src/app/api/dashboard/summary/route.test.ts | 138 ++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/app/api/dashboard/summary/route.test.ts diff --git a/src/app/api/dashboard/summary/route.test.ts b/src/app/api/dashboard/summary/route.test.ts new file mode 100644 index 0000000..8a7311f --- /dev/null +++ b/src/app/api/dashboard/summary/route.test.ts @@ -0,0 +1,138 @@ +import { describe, expect, it, vi, beforeEach } from "vitest"; +import { getServerSession } from "next-auth"; +import { fetchUserSummary } from "@/lib/github"; +import { fetchViewerLogin } from "@/lib/githubViewer"; + +vi.mock("next-auth", () => ({ + getServerSession: vi.fn(), +})); + +vi.mock("@/lib/github", () => ({ + fetchUserSummary: vi.fn(), +})); + +vi.mock("@/lib/githubViewer", () => ({ + fetchViewerLogin: vi.fn(), +})); + +describe("GET /api/dashboard/summary", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("returns 401 if no session exists", async () => { + vi.mocked(getServerSession).mockResolvedValueOnce(null); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(401); + expect(data.error).toBe("Unauthorized"); + }); + + it("returns 401 if no access token exists", async () => { + vi.mocked(getServerSession).mockResolvedValueOnce({ user: { login: "testuser" } }); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(401); + expect(data.error).toBe("Unauthorized"); + }); + + it("returns 200 and summary if session has login", async () => { + const mockSession = { + accessToken: "fake-token", + user: { login: "testuser" }, + }; + const mockSummary = { profile: { login: "testuser" } }; + + vi.mocked(getServerSession).mockResolvedValueOnce(mockSession); + vi.mocked(fetchUserSummary).mockResolvedValueOnce(mockSummary as any); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.username).toBe("testuser"); + expect(data.summary).toEqual(mockSummary); + expect(fetchViewerLogin).not.toHaveBeenCalled(); + expect(fetchUserSummary).toHaveBeenCalledWith("testuser", "fake-token"); + }); + + it("returns 200 and fetches login if missing from session", async () => { + const mockSession = { + accessToken: "fake-token", + user: { name: "Test User" }, // login missing + }; + const mockSummary = { profile: { login: "testuser" } }; + + vi.mocked(getServerSession).mockResolvedValueOnce(mockSession); + vi.mocked(fetchViewerLogin).mockResolvedValueOnce("testuser"); + vi.mocked(fetchUserSummary).mockResolvedValueOnce(mockSummary as any); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.username).toBe("testuser"); + expect(data.summary).toEqual(mockSummary); + expect(fetchViewerLogin).toHaveBeenCalledWith("fake-token"); + expect(fetchUserSummary).toHaveBeenCalledWith("testuser", "fake-token"); + }); + + it("returns 500 if fetchViewerLogin fails", async () => { + const mockSession = { + accessToken: "fake-token", + user: { name: "Test User" }, // login missing + }; + + vi.mocked(getServerSession).mockResolvedValueOnce(mockSession); + vi.mocked(fetchViewerLogin).mockRejectedValueOnce(new Error("Viewer login failed")); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(500); + expect(data.error).toBe("Viewer login failed"); + }); + + it("returns 500 if fetchUserSummary fails", async () => { + const mockSession = { + accessToken: "fake-token", + user: { login: "testuser" }, + }; + + vi.mocked(getServerSession).mockResolvedValueOnce(mockSession); + vi.mocked(fetchUserSummary).mockRejectedValueOnce(new Error("Summary fetch failed")); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(500); + expect(data.error).toBe("Summary fetch failed"); + }); + + it("returns 500 with 'Unknown error' if error is not an Error instance", async () => { + const mockSession = { + accessToken: "fake-token", + user: { login: "testuser" }, + }; + + vi.mocked(getServerSession).mockResolvedValueOnce(mockSession); + vi.mocked(fetchUserSummary).mockRejectedValueOnce("Something went wrong"); + + const { GET } = await import("./route"); + const response = await GET(); + const data = await response.json(); + + expect(response.status).toBe(500); + expect(data.error).toBe("Unknown error"); + }); +});