Skip to content
Closed
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
57 changes: 57 additions & 0 deletions src/lib/__tests__/githubViewer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { fetchViewerLogin } from "../githubViewer";
import { GitHubApiError } from "../types";

const mockFetch = vi.fn();

describe("fetchViewerLogin", () => {
beforeEach(() => {
vi.stubGlobal("fetch", mockFetch);
mockFetch.mockReset();
});

afterEach(() => {
vi.unstubAllGlobals();
});

it("should return login on successful fetch", async () => {
mockFetch.mockResolvedValue({
ok: true,
json: async () => ({ login: "testuser" }),
});

const login = await fetchViewerLogin("test-token");
expect(login).toBe("testuser");

expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith("https://api.github.com/user", {
headers: {
Accept: "application/vnd.github+json",
Authorization: "Bearer test-token",
"User-Agent": "github-user-summary",
},
cache: "no-store",
});
});

it("should throw GitHubApiError when fetch is not ok", async () => {
mockFetch.mockResolvedValue({
ok: false,
status: 401,
json: async () => ({ message: "Bad credentials" }),
});

await expect(fetchViewerLogin("invalid-token")).rejects.toThrow(GitHubApiError);

// We can also check specific properties on the error
try {
await fetchViewerLogin("invalid-token");
} catch (e) {
expect(e).toBeInstanceOf(GitHubApiError);
expect((e as GitHubApiError).status).toBe(401);
expect((e as GitHubApiError).message).toBe("Failed to resolve current GitHub user");
}

expect(mockFetch).toHaveBeenCalledTimes(2);
Comment on lines +44 to +55

Choose a reason for hiding this comment

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

medium

This test case calls fetchViewerLogin twice: once with expect.rejects and again inside a try...catch block. This is redundant and leads to the assertion that mockFetch was called twice, which is not representative of a single test scenario.

A cleaner and more efficient approach is to use a single try...catch block to both verify that an error is thrown and inspect its properties. This ensures the function under test is only called once.

Suggested change
await expect(fetchViewerLogin("invalid-token")).rejects.toThrow(GitHubApiError);
// We can also check specific properties on the error
try {
await fetchViewerLogin("invalid-token");
} catch (e) {
expect(e).toBeInstanceOf(GitHubApiError);
expect((e as GitHubApiError).status).toBe(401);
expect((e as GitHubApiError).message).toBe("Failed to resolve current GitHub user");
}
expect(mockFetch).toHaveBeenCalledTimes(2);
try {
await fetchViewerLogin("invalid-token");
// The test should fail if no error is thrown.
fail("Expected fetchViewerLogin to throw, but it did not.");
} catch (e) {
expect(e).toBeInstanceOf(GitHubApiError);
expect((e as GitHubApiError).status).toBe(401);
expect((e as GitHubApiError).message).toBe("Failed to resolve current GitHub user");
}
expect(mockFetch).toHaveBeenCalledTimes(1);

});
});
Loading