CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
issues-ai-retriage.test.ts
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| 58915a9 | 1 | /** |
| 2 | * Smoke tests for the on-demand issue re-triage endpoint: | |
| 3 | * POST /:owner/:repo/issues/:number/ai-retriage | |
| 4 | * | |
| 5 | * Write-access only. Verifies auth-guard contracts and the | |
| 6 | * triggerIssueTriage `force` parameter never-throws contract. | |
| 7 | */ | |
| 8 | ||
| 9 | import { describe, it, expect } from "bun:test"; | |
| 10 | import app from "../app"; | |
| 11 | ||
| 12 | describe("POST /:owner/:repo/issues/:number/ai-retriage — auth guard", () => { | |
| 13 | it("redirects to /login when unauthenticated", async () => { | |
| 14 | const res = await app.request( | |
| 15 | "/alice/demo/issues/1/ai-retriage", | |
| 16 | { | |
| 17 | method: "POST", | |
| 18 | headers: { "content-type": "application/x-www-form-urlencoded" }, | |
| 19 | body: "", | |
| 20 | redirect: "manual", | |
| 21 | } | |
| 22 | ); | |
| 23 | expect([301, 302, 303, 307, 401, 403, 404, 503]).toContain(res.status); | |
| 24 | if (res.status === 302 || res.status === 303 || res.status === 307) { | |
| 25 | const loc = res.headers.get("location") || ""; | |
| 26 | expect(loc).toContain("/login"); | |
| 27 | } | |
| 28 | }); | |
| 29 | ||
| 30 | it("rejects bogus bearer tokens", async () => { | |
| 31 | const res = await app.request( | |
| 32 | "/alice/demo/issues/1/ai-retriage", | |
| 33 | { | |
| 34 | method: "POST", | |
| 35 | headers: { | |
| 36 | "content-type": "application/x-www-form-urlencoded", | |
| 37 | authorization: "Bearer glct_definitely-not-valid", | |
| 38 | }, | |
| 39 | body: "", | |
| 40 | } | |
| 41 | ); | |
| 42 | expect([401, 403, 404, 503]).toContain(res.status); | |
| 43 | }); | |
| 44 | }); | |
| 45 | ||
| 46 | describe("triggerIssueTriage — force option (idempotency bypass)", () => { | |
| 47 | it("accepts and propagates the force flag without throwing", async () => { | |
| 48 | const { triggerIssueTriage } = await import("../lib/issue-triage"); | |
| 49 | let threw = false; | |
| 50 | try { | |
| 51 | await triggerIssueTriage( | |
| 52 | { | |
| 53 | ownerName: "alice", | |
| 54 | repoName: "demo", | |
| 55 | repositoryId: "00000000-0000-0000-0000-000000000000", | |
| 56 | issueId: "00000000-0000-0000-0000-000000000000", | |
| 57 | issueNumber: 1, | |
| 58 | authorId: "00000000-0000-0000-0000-000000000000", | |
| 59 | title: "Test", | |
| 60 | body: "", | |
| 61 | }, | |
| 62 | { force: true } | |
| 63 | ); | |
| 64 | } catch { | |
| 65 | threw = true; | |
| 66 | } | |
| 67 | expect(threw).toBe(false); | |
| 68 | }); | |
| 69 | }); |