import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { runGateTestScan } from "../lib/gate";
import { config } from "../lib/config";
const origFetch = globalThis.fetch;
const origUrl = process.env.GATETEST_URL;
function mockFetch(responder: () => Response | Promise<Response>): void {
globalThis.fetch = async (): Promise<Response> => responder();
}
beforeEach(() => {
process.env.GATETEST_URL = "https://gatetest.example/api/events/push";
});
afterEach(() => {
globalThis.fetch = origFetch;
if (origUrl === undefined) delete process.env.GATETEST_URL;
else process.env.GATETEST_URL = origUrl;
});
describe("runGateTestScan — availability vs verdict", () => {
it("skips (does not block) when GateTest is not configured", async () => {
delete process.env.GATETEST_URL;
const result = await runGateTestScan("o", "r", "refs/heads/main", "a".repeat(40));
expect(result.skipped).toBe(true);
expect(result.passed).toBe(true);
});
it("skips (does not block) on a non-2xx response — e.g. GateTest itself is down", async () => {
mockFetch(() => new Response(JSON.stringify({ error: "GLUECRON_EMITTER_SECRET is not set" }), { status: 503 }));
const result = await runGateTestScan("o", "r", "refs/heads/main", "a".repeat(40));
expect(result.skipped).toBe(true);
expect(result.passed).toBe(true);
expect(result.details).toContain("503");
});
it("skips (does not block) when the request throws — network error / timeout", async () => {
mockFetch(() => {
throw new Error("ECONNREFUSED");
});
const result = await runGateTestScan("o", "r", "refs/heads/main", "a".repeat(40));
expect(result.skipped).toBe(true);
expect(result.passed).toBe(true);
expect(result.details).toContain("ECONNREFUSED");
});
it("blocks on a genuine 200 scan-fail verdict", async () => {
mockFetch(() => new Response(JSON.stringify({ passed: false, summary: "2 vulnerabilities found" }), { status: 200 }));
const result = await runGateTestScan("o", "r", "refs/heads/main", "a".repeat(40));
expect(result.skipped).toBeFalsy();
expect(result.passed).toBe(false);
expect(result.details).toBe("2 vulnerabilities found");
});
it("passes on a genuine 200 scan-pass verdict", async () => {
mockFetch(() => new Response(JSON.stringify({ passed: true, summary: "All checks passed" }), { status: 200 }));
const result = await runGateTestScan("o", "r", "refs/heads/main", "a".repeat(40));
expect(result.skipped).toBeFalsy();
expect(result.passed).toBe(true);
});
});
describe("config.gatetestUrl reflects GATETEST_URL for this suite", () => {
it("resolves to the mocked value while set", () => {
expect(config.gatetestUrl).toBe("https://gatetest.example/api/events/push");
});
});
|