CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
sponsors.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.
| 08420cd | 1 | /** |
| 2 | * Block I6 — Sponsors tests. | |
| 3 | * | |
| 4 | * Pure tests for formatCents + route auth smoke for the maintainer settings | |
| 5 | * routes (public sponsor page is intentionally ungated for reading). | |
| 6 | */ | |
| 7 | ||
| 8 | import { describe, it, expect } from "bun:test"; | |
| 9 | import app from "../app"; | |
| 10 | import { __internal } from "../routes/sponsors"; | |
| 11 | ||
| 12 | const { formatCents } = __internal; | |
| 13 | ||
| 14 | describe("sponsors — formatCents", () => { | |
| 15 | it("prints 'Any amount' for 0 cents", () => { | |
| 16 | expect(formatCents(0)).toBe("Any amount"); | |
| 17 | }); | |
| 18 | ||
| 19 | it("formats 500 cents as $5.00", () => { | |
| 20 | expect(formatCents(500)).toBe("$5.00"); | |
| 21 | }); | |
| 22 | ||
| 23 | it("formats 1234 cents as $12.34", () => { | |
| 24 | expect(formatCents(1234)).toBe("$12.34"); | |
| 25 | }); | |
| 26 | }); | |
| 27 | ||
| 28 | describe("sponsors — route auth", () => { | |
| 29 | it("GET /settings/sponsors without auth → 302 /login", async () => { | |
| 30 | const res = await app.request("/settings/sponsors"); | |
| 31 | expect(res.status).toBe(302); | |
| 32 | expect(res.headers.get("location") || "").toContain("/login"); | |
| 33 | }); | |
| 34 | ||
| 35 | it("POST /settings/sponsors/tiers/new without auth → 302 /login", async () => { | |
| 36 | const res = await app.request("/settings/sponsors/tiers/new", { | |
| 37 | method: "POST", | |
| 38 | body: new URLSearchParams({ name: "Silver", monthly_cents: "500" }), | |
| 39 | headers: { "content-type": "application/x-www-form-urlencoded" }, | |
| 40 | }); | |
| 41 | expect(res.status).toBe(302); | |
| 42 | expect(res.headers.get("location") || "").toContain("/login"); | |
| 43 | }); | |
| 44 | ||
| 45 | it("POST /sponsors/:username without auth → 302 /login", async () => { | |
| 46 | const res = await app.request("/sponsors/alice", { | |
| 47 | method: "POST", | |
| 48 | body: new URLSearchParams({ amount_cents: "500" }), | |
| 49 | headers: { "content-type": "application/x-www-form-urlencoded" }, | |
| 50 | }); | |
| 51 | expect(res.status).toBe(302); | |
| 52 | expect(res.headers.get("location") || "").toContain("/login"); | |
| 53 | }); | |
| 54 | }); | |
| 55 | ||
| 56 | describe("sponsors — public page", () => { | |
| 57 | it("GET /sponsors/:unknown-user is handled (not swallowed)", async () => { | |
| 58 | // Without a DB connection the handler 500s. With a DB it 404s via the | |
| 59 | // global notFound handler. Either proves the route was reached. | |
| 60 | const res = await app.request("/sponsors/__does_not_exist_12345__"); | |
| 61 | expect([404, 500]).toContain(res.status); | |
| 62 | }); | |
| 63 | }); |