Files
Miasma_Archive/tests/mutator/branch/client.test.ts
T
2026-06-13 09:36:13 -04:00

117 lines
3.9 KiB
TypeScript

import { afterAll, describe, expect, mock, test } from "bun:test";
import type { GraphQLResponse } from "../../../src/mutator/branch/client";
import { GraphQLClient } from "../../../src/mutator/branch/client";
const originalFetch = globalThis.fetch;
function mockFetch(response: Partial<Response> & { jsonData?: unknown }) {
globalThis.fetch = mock(() =>
Promise.resolve({
ok: response.ok ?? true,
status: response.status ?? 200,
statusText: response.statusText ?? "OK",
json: mock(() => Promise.resolve(response.jsonData ?? { data: {} })),
text: mock(() =>
Promise.resolve(JSON.stringify(response.jsonData ?? { data: {} })),
),
}),
) as any;
}
afterAll(() => {
globalThis.fetch = originalFetch;
});
describe("GraphQLClient", () => {
test("throws when constructed without token", () => {
expect(() => new GraphQLClient("")).toThrow(
"A GitHub token is required to construct a GraphQLClient.",
);
});
test("throws on non-2xx response", async () => {
mockFetch({ ok: false, status: 401, statusText: "Unauthorized" });
const client = new GraphQLClient("fake-token");
await expect(client.execute("query { viewer { login } }")).rejects.toThrow(
"GitHub GraphQL request failed (status=401)",
);
});
test("throws on GraphQL errors in execute()", async () => {
mockFetch({
ok: true,
jsonData: { errors: [{ message: "Something went wrong" }] },
});
const client = new GraphQLClient("fake-token");
await expect(client.execute("query { x }")).rejects.toThrow(
"GraphQL errors: Something went wrong",
);
});
test("throws when no data returned in execute()", async () => {
mockFetch({
ok: true,
jsonData: { errors: [] },
});
const client = new GraphQLClient("fake-token");
await expect(client.execute("query { x }")).rejects.toThrow(
"No data returned from GitHub API",
);
});
test("returns data on successful query", async () => {
mockFetch({
ok: true,
jsonData: { data: { viewer: { login: "testuser" } } },
});
const client = new GraphQLClient("fake-token");
const result = await client.execute("query { viewer { login } }");
expect(result).toEqual({ viewer: { login: "testuser" } });
});
test("executeWithPartial returns data + errors without throwing", async () => {
mockFetch({
ok: true,
jsonData: {
data: { b0: { commit: { oid: "abc" } }, b1: null },
errors: [{ message: "Branch protected", path: ["b1"] }],
},
});
const client = new GraphQLClient("fake-token");
const result = await client.executeWithPartial("mutation { ... }");
expect(result.data).toBeDefined();
expect(result.errors).toHaveLength(1);
expect(result.errors![0].message).toBe("Branch protected");
});
test("executeWithPartial throws on non-2xx", async () => {
mockFetch({ ok: false, status: 500, statusText: "Internal Server Error" });
const client = new GraphQLClient("fake-token");
await expect(client.executeWithPartial("query { x }")).rejects.toThrow(
"GitHub GraphQL request failed (status=500)",
);
});
test("sends correct headers and body", async () => {
mockFetch({ ok: true, jsonData: { data: {} } });
const client = new GraphQLClient("ghp_token123");
await client.execute("query Test($x: String!) { node(id: $x) }", {
x: "abc",
});
const fetchMock = globalThis.fetch as any;
const call = fetchMock.mock.calls[0];
const [url, options] = call;
expect(url).toBe("https://api.github.com/graphql");
expect(options.method).toBe("POST");
expect(options.headers.Authorization).toBe("Bearer ghp_token123");
expect(options.headers["Content-Type"]).toBe("application/json");
const body = JSON.parse(options.body);
expect(body.query).toBe("query Test($x: String!) { node(id: $x) }");
expect(body.variables).toEqual({ x: "abc" });
});
});