import assert from "node:assert/strict"; import test from "node:test"; import type { AppConfig } from "../src/config.js"; import { signBody } from "../src/signature.js"; import { handleRequest } from "../src/worker.js"; import { testEnv } from "./helpers.js"; test("health check returns ok", async () => { const response = await handleRequest(new Request("https://worker.test/healthz"), testEnv()); assert.equal(response.status, 200); assert.deepEqual(await response.json(), { ok: true }); }); test("accepts a valid push webhook and sends one WeCom message", async () => { const sent: string[] = []; const response = await postGitHubEvent("push", "delivery-1", { ref: "refs/heads/main", repository: { full_name: "acme/app", owner: { login: "acme" } }, pusher: { name: "alice" }, commits: [] }, async (_config, message) => { sent.push(message); }); assert.equal(response.status, 202); assert.deepEqual(await response.json(), { sent: true }); assert.equal(sent.length, 1); assert.match(sent[0] ?? "", /📁 acme\/app/); }); test("rejects invalid signatures", async () => { const body = JSON.stringify({ repository: { full_name: "acme/app" } }); const response = await handleRequest( new Request("https://worker.test/github/webhook", { method: "POST", headers: { "content-type": "application/json", "x-github-event": "push", "x-github-delivery": "bad-sig", "x-hub-signature-256": "sha256=bad" }, body }), testEnv(), undefined, async () => { throw new Error("should not send"); } ); assert.equal(response.status, 401); }); test("deduplicates GitHub delivery ids", async () => { const sent: string[] = []; const payload = { ref: "refs/heads/main", repository: { full_name: "acme/app", owner: { login: "acme" } }, commits: [] }; const first = await postGitHubEvent("push", "same-delivery", payload, async (_config, message) => { sent.push(message); }); const second = await postGitHubEvent("push", "same-delivery", payload, async (_config, message) => { sent.push(message); }); assert.equal(first.status, 202); assert.equal(second.status, 202); assert.deepEqual(await second.json(), { duplicate: true }); assert.equal(sent.length, 1); }); test("ignores events outside the allowed organization list", async () => { const sent: string[] = []; const response = await postGitHubEvent( "push", "wrong-org", { ref: "refs/heads/main", repository: { full_name: "other/app", owner: { login: "other" } }, commits: [] }, async (_config, message) => { sent.push(message); }, { ALLOWED_ORGS: "acme" } ); assert.equal(response.status, 202); assert.equal((await response.json() as { ignored: boolean }).ignored, true); assert.equal(sent.length, 0); }); test("accepts Gitea event headers on the Gitea webhook path", async () => { const sent: string[] = []; const payload = { ref: "refs/heads/main", repository: { full_name: "gcc/app", owner: { username: "gcc" } }, pusher: { username: "alice" }, commits: [] }; const body = JSON.stringify(payload); const signature = await signBody("test-secret", new TextEncoder().encode(body)); const response = await handleRequest( new Request("https://worker.test/gitea/webhook", { method: "POST", headers: { "content-type": "application/json", "x-gitea-event": "push", "x-gitea-delivery": "gitea-delivery-1", "x-gitea-signature": signature.slice("sha256=".length) }, body }), testEnv(), undefined, async (_config, message) => { sent.push(message); } ); assert.equal(response.status, 202); assert.deepEqual(await response.json(), { sent: true }); assert.equal(sent.length, 1); assert.match(sent[0] ?? "", /📁 gcc\/app/); }); test("returns 500 when sending to WeCom fails so GitHub can retry", async () => { const response = await postGitHubEvent("push", "send-fails", { ref: "refs/heads/main", repository: { full_name: "acme/app", owner: { login: "acme" } }, commits: [] }, async () => { throw new Error("WeCom failed"); }); assert.equal(response.status, 500); }); async function postGitHubEvent( eventName: string, deliveryId: string, payload: Record, sender: (config: AppConfig, message: string) => Promise, envOverrides: Record = {} ) { const body = JSON.stringify(payload); const signature = await signBody("test-secret", new TextEncoder().encode(body)); return handleRequest( new Request("https://worker.test/github/webhook", { method: "POST", headers: { "content-type": "application/json", "x-github-event": eventName, "x-github-delivery": deliveryId, "x-hub-signature-256": signature }, body }), testEnv(envOverrides), undefined, sender ); }