Blame · Line-by-line history
pinned-repos.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.
| 8ec29ff | 1 | /** |
| 2 | * Block J13 — Pinned repos. Pure helpers + route smoke. | |
| 3 | */ | |
| 4 | ||
| 5 | import { describe, it, expect } from "bun:test"; | |
| 6 | import app from "../app"; | |
| 7 | import { MAX_PINS, __internal } from "../lib/pinned-repos"; | |
| 8 | ||
| 9 | describe("pinned-repos — MAX_PINS", () => { | |
| 10 | it("is capped at 6 (GitHub parity)", () => { | |
| 11 | expect(MAX_PINS).toBe(6); | |
| 12 | }); | |
| 13 | }); | |
| 14 | ||
| 15 | describe("pinned-repos — sanitisePinIds", () => { | |
| 16 | const { sanitisePinIds } = __internal; | |
| 17 | ||
| 18 | it("returns empty for no input", () => { | |
| 19 | expect(sanitisePinIds([])).toEqual([]); | |
| 20 | }); | |
| 21 | ||
| 22 | it("drops null / undefined / empty / whitespace-only", () => { | |
| 23 | expect(sanitisePinIds([null, undefined, "", " ", "a"])).toEqual(["a"]); | |
| 24 | }); | |
| 25 | ||
| 26 | it("preserves first-seen order and de-dupes", () => { | |
| 27 | expect(sanitisePinIds(["a", "b", "a", "c", "b"])).toEqual(["a", "b", "c"]); | |
| 28 | }); | |
| 29 | ||
| 30 | it("clamps to MAX_PINS", () => { | |
| 31 | const many = Array.from({ length: 20 }, (_, i) => `id-${i}`); | |
| 32 | const out = sanitisePinIds(many); | |
| 33 | expect(out.length).toBe(MAX_PINS); | |
| 34 | expect(out[0]).toBe("id-0"); | |
| 35 | expect(out[MAX_PINS - 1]).toBe(`id-${MAX_PINS - 1}`); | |
| 36 | }); | |
| 37 | ||
| 38 | it("trims whitespace but preserves interior case", () => { | |
| 39 | expect(sanitisePinIds([" Abc ", "abc"])).toEqual(["Abc", "abc"]); | |
| 40 | }); | |
| 41 | }); | |
| 42 | ||
| 43 | describe("pinned-repos — routes", () => { | |
| 44 | it("GET /settings/pins requires auth (redirects)", async () => { | |
| 45 | const res = await app.request("/settings/pins"); | |
| 46 | expect([302, 401].includes(res.status)).toBe(true); | |
| 47 | }); | |
| 48 | ||
| 49 | it("POST /settings/pins requires auth", async () => { | |
| 50 | const res = await app.request("/settings/pins", { | |
| 51 | method: "POST", | |
| 52 | body: "", | |
| 53 | }); | |
| 54 | expect([302, 401].includes(res.status)).toBe(true); | |
| 55 | }); | |
| 56 | ||
| 57 | it("POST with invalid bearer → 401", async () => { | |
| 58 | const res = await app.request("/settings/pins", { | |
| 59 | method: "POST", | |
| 60 | headers: { authorization: "Bearer glc_garbage" }, | |
| 61 | body: "", | |
| 62 | }); | |
| 63 | expect(res.status).toBe(401); | |
| 64 | }); | |
| 65 | }); |