swadhinbiswas test(integrations): add provider-specific webhook route coverage · 2/18/2026
60296a7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { beforeEach, describe, expect, it, vi } from "vitest";
const { issueWebhookHandler, qualityWebhookHandler } = vi.hoisted(() => ({
issueWebhookHandler: vi.fn(async () => true),
qualityWebhookHandler: vi.fn(async () => true),
}));
vi.mock("@/lib/air-gapped", () => ({
isAirGappedMode: () => false,
}));
vi.mock("@/lib/issue-trackers", () => ({
ISSUE_PROVIDERS: {
jira: { name: "Jira" },
linear: { name: "Linear" },
trello: { name: "Trello" },
clickup: { name: "ClickUp" },
},
handleIssueTrackerWebhook: issueWebhookHandler,
}));
vi.mock("@/lib/code-quality", () => ({
QUALITY_PROVIDERS: {
codecov: { name: "Codecov" },
coveralls: { name: "Coveralls" },
sonarqube: { name: "SonarQube" },
snyk: { name: "Snyk" },
},
handleQualityWebhook: qualityWebhookHandler,
}));
import { POST as issueWebhookPost } from "@/pages/api/repos/[owner]/[repo]/integrations/issue-trackers/[provider]/webhook";
import { POST as qualityWebhookPost } from "@/pages/api/repos/[owner]/[repo]/integrations/code-quality/webhooks/[provider]";
async function json(response: Response): Promise<any> {
return response.json();
}
describe("provider webhook routes", () => {
beforeEach(() => {
issueWebhookHandler.mockClear();
qualityWebhookHandler.mockClear();
});
it("accepts all supported issue tracker providers and forwards payload", async () => {
for (const provider of ["jira", "linear", "trello", "clickup"]) {
const response = await issueWebhookPost({
params: { provider },
url: new URL(`http://localhost/api/repos/acme/demo/integrations/issue-trackers/${provider}/webhook?secret=sec`),
request: new Request(`http://localhost/api/repos/acme/demo/integrations/issue-trackers/${provider}/webhook?secret=sec`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ event: "update", provider }),
}),
} as any);
const body = await json(response);
expect(response.status).toBe(200);
expect(body?.success).toBe(true);
expect(issueWebhookHandler).toHaveBeenCalledWith(provider, "sec", { event: "update", provider });
}
});
it("rejects unsupported issue tracker provider", async () => {
const response = await issueWebhookPost({
params: { provider: "unknown" },
url: new URL("http://localhost/api/repos/acme/demo/integrations/issue-trackers/unknown/webhook?secret=sec"),
request: new Request("http://localhost/api/repos/acme/demo/integrations/issue-trackers/unknown/webhook?secret=sec", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({}),
}),
} as any);
const body = await json(response);
expect(response.status).toBe(400);
expect(body?.error?.code).toBe("BAD_REQUEST");
});
it("accepts all supported code quality providers and forwards payload", async () => {
for (const provider of ["codecov", "coveralls", "sonarqube", "snyk"]) {
const response = await qualityWebhookPost({
params: { provider },
url: new URL(`http://localhost/api/repos/acme/demo/integrations/code-quality/webhooks/${provider}?secret=sec`),
request: new Request(`http://localhost/api/repos/acme/demo/integrations/code-quality/webhooks/${provider}?secret=sec`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ event: "report", provider }),
}),
} as any);
const body = await json(response);
expect(response.status).toBe(200);
expect(body?.success).toBe(true);
expect(qualityWebhookHandler).toHaveBeenCalledWith(provider, "sec", { event: "report", provider });
}
});
it("rejects unsupported code quality provider", async () => {
const response = await qualityWebhookPost({
params: { provider: "unknown" },
url: new URL("http://localhost/api/repos/acme/demo/integrations/code-quality/webhooks/unknown?secret=sec"),
request: new Request("http://localhost/api/repos/acme/demo/integrations/code-quality/webhooks/unknown?secret=sec", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({}),
}),
} as any);
const body = await json(response);
expect(response.status).toBe(400);
expect(body?.error?.code).toBe("BAD_REQUEST");
});
});