2026-05-12 21:33:24 +00:00
|
|
|
import { describe, expect, test } from "bun:test";
|
|
|
|
|
import { buildDiscordPayload, notifyDiscord, parseDiscordConfig } from "../src/discord";
|
2026-05-12 22:37:26 +00:00
|
|
|
import type { FeedSignal, GitWebhookEvent } from "../src/types";
|
2026-05-12 21:33:24 +00:00
|
|
|
|
|
|
|
|
const pushEvent: GitWebhookEvent = {
|
|
|
|
|
provider: "jojo",
|
|
|
|
|
event: "push",
|
|
|
|
|
providerEvent: "push",
|
|
|
|
|
deliveryId: "delivery-1",
|
|
|
|
|
receivedAt: "2026-05-12T21:00:00.000Z",
|
|
|
|
|
repo: {
|
|
|
|
|
owner: "peezy-tech",
|
2026-05-12 23:18:13 +00:00
|
|
|
name: "patchbay",
|
|
|
|
|
fullName: "peezy-tech/patchbay",
|
2026-05-12 21:33:24 +00:00
|
|
|
},
|
|
|
|
|
sender: {
|
|
|
|
|
username: "matamune",
|
|
|
|
|
},
|
|
|
|
|
ref: "refs/heads/main",
|
|
|
|
|
after: "0123456789abcdef",
|
|
|
|
|
raw: {
|
|
|
|
|
head_commit: {
|
2026-05-12 23:18:13 +00:00
|
|
|
url: "https://jojo.build/peezy-tech/patchbay/commit/0123456789abcdef",
|
2026-05-12 21:33:24 +00:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-12 22:37:26 +00:00
|
|
|
const feedSignal: FeedSignal = {
|
|
|
|
|
sourceId: "github-openai-codex-main",
|
|
|
|
|
provider: "github",
|
|
|
|
|
event: "push",
|
|
|
|
|
entryId: "tag:github.com,2008:Grit::Commit/0123456789abcdef0123456789abcdef01234567",
|
|
|
|
|
title: "Tighten sandbox setup",
|
|
|
|
|
url: "https://github.com/openai/codex/commit/0123456789abcdef0123456789abcdef01234567",
|
|
|
|
|
author: "bookholt-oai",
|
|
|
|
|
publishedAt: "2026-05-12T21:00:00.000Z",
|
|
|
|
|
repo: {
|
|
|
|
|
owner: "openai",
|
|
|
|
|
name: "codex",
|
|
|
|
|
fullName: "openai/codex",
|
|
|
|
|
webUrl: "https://github.com/openai/codex",
|
|
|
|
|
defaultBranch: "main",
|
|
|
|
|
},
|
|
|
|
|
ref: "refs/heads/main",
|
|
|
|
|
sha: "0123456789abcdef0123456789abcdef01234567",
|
|
|
|
|
target: {
|
|
|
|
|
provider: "github",
|
|
|
|
|
repoFullName: "peezy-tech/codex",
|
|
|
|
|
branch: "main",
|
|
|
|
|
mode: "notify_only",
|
|
|
|
|
},
|
|
|
|
|
raw: {},
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-12 21:33:24 +00:00
|
|
|
describe("discord notifications", () => {
|
|
|
|
|
test("parses default notify events", () => {
|
|
|
|
|
const config = parseDiscordConfig({});
|
|
|
|
|
expect(config.notifyEvents.has("push")).toBe(true);
|
|
|
|
|
expect(config.notifyEvents.has("pull_request")).toBe(true);
|
|
|
|
|
expect(config.notifyEvents.has("release")).toBe(true);
|
|
|
|
|
expect(config.notifyEvents.has("ping")).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("builds readable push embeds", () => {
|
|
|
|
|
const payload = buildDiscordPayload({
|
|
|
|
|
event: pushEvent,
|
|
|
|
|
job: {
|
|
|
|
|
id: "jojo:delivery-1:main_push",
|
|
|
|
|
kind: "main_push",
|
|
|
|
|
provider: "jojo",
|
2026-05-12 23:18:13 +00:00
|
|
|
repoFullName: "peezy-tech/patchbay",
|
2026-05-12 21:33:24 +00:00
|
|
|
ref: "refs/heads/main",
|
|
|
|
|
sha: "0123456789abcdef",
|
|
|
|
|
deliveryId: "delivery-1",
|
|
|
|
|
createdAt: "2026-05-12T21:00:00.000Z",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-12 23:18:13 +00:00
|
|
|
expect(payload.username).toBe("patchbay");
|
|
|
|
|
expect(payload.embeds[0].title).toBe("[jojo] peezy-tech/patchbay push to main");
|
|
|
|
|
expect(payload.embeds[0].url).toBe("https://jojo.build/peezy-tech/patchbay/commit/0123456789abcdef");
|
2026-05-12 21:33:24 +00:00
|
|
|
expect(payload.embeds[0].fields).toContainEqual({ name: "Queued", value: "main_push", inline: true });
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-12 22:37:26 +00:00
|
|
|
test("builds readable feed embeds", () => {
|
|
|
|
|
const payload = buildDiscordPayload({ signal: feedSignal });
|
|
|
|
|
expect(payload.embeds[0].title).toBe("[github] openai/codex upstream update on main");
|
|
|
|
|
expect(payload.embeds[0].description).toBe("Tighten sandbox setup");
|
|
|
|
|
expect(payload.embeds[0].url).toBe("https://github.com/openai/codex/commit/0123456789abcdef0123456789abcdef01234567");
|
|
|
|
|
expect(payload.embeds[0].footer.text).toBe("feed watcher");
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-12 21:33:24 +00:00
|
|
|
test("does nothing without a webhook URL", async () => {
|
|
|
|
|
let calls = 0;
|
|
|
|
|
await notifyDiscord(parseDiscordConfig({}), { event: pushEvent }, async () => {
|
|
|
|
|
calls += 1;
|
|
|
|
|
return new Response(null, { status: 204 });
|
|
|
|
|
});
|
|
|
|
|
expect(calls).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("skips unconfigured events", async () => {
|
|
|
|
|
let calls = 0;
|
|
|
|
|
await notifyDiscord(parseDiscordConfig({ webhookUrl: "https://discord.example/webhook", notifyEvents: "release" }), { event: pushEvent }, async () => {
|
|
|
|
|
calls += 1;
|
|
|
|
|
return new Response(null, { status: 204 });
|
|
|
|
|
});
|
|
|
|
|
expect(calls).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("posts configured events", async () => {
|
|
|
|
|
let body = "";
|
|
|
|
|
await notifyDiscord(parseDiscordConfig({ webhookUrl: "https://discord.example/webhook", notifyEvents: "push" }), { event: pushEvent }, async (_url, init) => {
|
|
|
|
|
body = String(init?.body);
|
|
|
|
|
return new Response(null, { status: 204 });
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-12 23:18:13 +00:00
|
|
|
expect(JSON.parse(body).embeds[0].title).toBe("[jojo] peezy-tech/patchbay push to main");
|
2026-05-12 21:33:24 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("throws on Discord failure", async () => {
|
|
|
|
|
await expect(notifyDiscord(parseDiscordConfig({ webhookUrl: "https://discord.example/webhook" }), { event: pushEvent }, async () => {
|
|
|
|
|
return new Response("bad", { status: 500 });
|
|
|
|
|
})).rejects.toThrow("Discord webhook returned 500");
|
|
|
|
|
});
|
|
|
|
|
});
|