CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
wikis.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.
| 1e162a8 | 1 | /** |
| 2 | * Block E3 — Wikis smoke tests. | |
| 3 | */ | |
| 4 | ||
| 5 | import { describe, it, expect } from "bun:test"; | |
| 6 | import app from "../app"; | |
| 7 | import { slugifyTitle } from "../routes/wikis"; | |
| 8 | ||
| 9 | describe("wikis — slugifyTitle", () => { | |
| 10 | it("lowercases and dashes simple titles", () => { | |
| 11 | expect(slugifyTitle("Home")).toBe("home"); | |
| 12 | expect(slugifyTitle("Getting Started")).toBe("getting-started"); | |
| 13 | }); | |
| 14 | ||
| 15 | it("strips punctuation", () => { | |
| 16 | expect(slugifyTitle("Hello, World!")).toBe("hello-world"); | |
| 17 | expect(slugifyTitle("What's up?")).toBe("whats-up"); | |
| 18 | }); | |
| 19 | ||
| 20 | it("collapses consecutive spaces/dashes", () => { | |
| 21 | expect(slugifyTitle("a b")).toBe("a-b"); | |
| 22 | expect(slugifyTitle("a---b")).toBe("a-b"); | |
| 23 | }); | |
| 24 | ||
| 25 | it("trims leading/trailing dashes", () => { | |
| 26 | expect(slugifyTitle(" hi ")).toBe("hi"); | |
| 27 | expect(slugifyTitle("-hi-")).toBe("hi"); | |
| 28 | }); | |
| 29 | ||
| 30 | it("returns empty string when nothing usable", () => { | |
| 31 | expect(slugifyTitle("")).toBe(""); | |
| 32 | expect(slugifyTitle("***")).toBe(""); | |
| 33 | }); | |
| 34 | }); | |
| 35 | ||
| 36 | describe("wikis — route smoke", () => { | |
| 37 | it("GET /:owner/:repo/wiki on missing repo → 404", async () => { | |
| 38 | const res = await app.request("/nobody/missing/wiki"); | |
| 39 | expect(res.status).toBe(404); | |
| 40 | }); | |
| 41 | ||
| 42 | it("GET /:owner/:repo/wiki/new without auth → 302 /login", async () => { | |
| 43 | const res = await app.request("/any/repo/wiki/new"); | |
| 44 | expect(res.status).toBe(302); | |
| 45 | expect(res.headers.get("location") || "").toMatch(/^\/login/); | |
| 46 | }); | |
| 47 | ||
| 48 | it("POST /:owner/:repo/wiki without auth → 302 /login", async () => { | |
| 49 | const res = await app.request("/any/repo/wiki", { | |
| 50 | method: "POST", | |
| 51 | body: new URLSearchParams({ title: "Home", body: "welcome" }), | |
| 52 | headers: { "content-type": "application/x-www-form-urlencoded" }, | |
| 53 | }); | |
| 54 | expect(res.status).toBe(302); | |
| 55 | expect(res.headers.get("location") || "").toMatch(/^\/login/); | |
| 56 | }); | |
| 57 | ||
| 58 | it("POST edit without auth → 302 /login", async () => { | |
| 59 | const res = await app.request("/any/repo/wiki/home/edit", { | |
| 60 | method: "POST", | |
| 61 | body: new URLSearchParams({ title: "x", body: "y" }), | |
| 62 | headers: { "content-type": "application/x-www-form-urlencoded" }, | |
| 63 | }); | |
| 64 | expect(res.status).toBe(302); | |
| 65 | expect(res.headers.get("location") || "").toMatch(/^\/login/); | |
| 66 | }); | |
| 67 | ||
| 68 | it("POST delete without auth → 302 /login", async () => { | |
| 69 | const res = await app.request("/any/repo/wiki/home/delete", { | |
| 70 | method: "POST", | |
| 71 | }); | |
| 72 | expect(res.status).toBe(302); | |
| 73 | expect(res.headers.get("location") || "").toMatch(/^\/login/); | |
| 74 | }); | |
| 75 | ||
| 76 | it("POST revert without auth → 302 /login", async () => { | |
| 77 | const res = await app.request("/any/repo/wiki/home/revert/1", { | |
| 78 | method: "POST", | |
| 79 | }); | |
| 80 | expect(res.status).toBe(302); | |
| 81 | expect(res.headers.get("location") || "").toMatch(/^\/login/); | |
| 82 | }); | |
| 83 | }); |