Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

discussions.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.

discussions.test.tsBlame75 lines · 1 contributor
1e162a8Claude1/**
2 * Block E2 — Discussions smoke tests.
3 *
4 * Route integration paths against a real repo would require a seeded test DB;
5 * we stick to category validation + public route behaviour (anon access,
6 * auth redirects) which exercise middleware + mounting.
7 */
8
9import { describe, it, expect } from "bun:test";
10import app from "../app";
11import { isValidCategory } from "../routes/discussions";
12
13describe("discussions — isValidCategory", () => {
14 it("accepts the five canonical categories", () => {
15 expect(isValidCategory("general")).toBe(true);
16 expect(isValidCategory("q-and-a")).toBe(true);
17 expect(isValidCategory("ideas")).toBe(true);
18 expect(isValidCategory("announcements")).toBe(true);
19 expect(isValidCategory("show-and-tell")).toBe(true);
20 });
21
22 it("rejects unknown categories", () => {
23 expect(isValidCategory("")).toBe(false);
24 expect(isValidCategory("random")).toBe(false);
25 expect(isValidCategory("Q-AND-A")).toBe(false);
26 expect(isValidCategory("sql injection'--")).toBe(false);
27 });
28});
29
30describe("discussions — route smoke", () => {
31 it("GET /:owner/:repo/discussions on missing repo → 404 HTML", async () => {
32 const res = await app.request("/nobody/missing/discussions");
33 expect(res.status).toBe(404);
34 const body = await res.text();
35 expect(body).toContain("Repository not found");
36 });
37
38 it("GET /:owner/:repo/discussions/new without auth → 302 /login", async () => {
39 const res = await app.request("/any/repo/discussions/new");
40 expect(res.status).toBe(302);
41 const loc = res.headers.get("location") || "";
42 expect(loc.startsWith("/login")).toBe(true);
43 });
44
45 it("POST /:owner/:repo/discussions without auth → 302 /login", async () => {
46 const res = await app.request("/any/repo/discussions", {
47 method: "POST",
48 body: new URLSearchParams({ title: "x", body: "y" }),
49 headers: { "content-type": "application/x-www-form-urlencoded" },
50 });
51 expect(res.status).toBe(302);
52 const loc = res.headers.get("location") || "";
53 expect(loc.startsWith("/login")).toBe(true);
54 });
55
56 it("POST /:owner/:repo/discussions/1/comment without auth → 302 /login", async () => {
57 const res = await app.request("/any/repo/discussions/1/comment", {
58 method: "POST",
59 body: new URLSearchParams({ body: "hi" }),
60 headers: { "content-type": "application/x-www-form-urlencoded" },
61 });
62 expect(res.status).toBe(302);
63 const loc = res.headers.get("location") || "";
64 expect(loc.startsWith("/login")).toBe(true);
65 });
66
67 it("POST /:owner/:repo/discussions/1/lock without auth → 302 /login", async () => {
68 const res = await app.request("/any/repo/discussions/1/lock", {
69 method: "POST",
70 });
71 expect(res.status).toBe(302);
72 const loc = res.headers.get("location") || "";
73 expect(loc.startsWith("/login")).toBe(true);
74 });
75});