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

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

admin.test.tsBlame98 lines · 1 contributor
8f50ed0Claude1/**
2 * Block F3 — Admin panel smoke tests.
3 *
4 * Exercises the auth gate on every admin route + the lib exports. Doesn't
5 * mutate DB; `isSiteAdmin(null)` and `getFlag` against a non-existent key
6 * degrade gracefully and are safe to call in any environment.
7 */
8
9import { describe, it, expect } from "bun:test";
10import app from "../app";
11import {
12 isSiteAdmin,
13 KNOWN_FLAGS,
14 getFlag,
15} from "../lib/admin";
16
17describe("admin — auth gate", () => {
18 it("GET /admin without auth → 302 /login", async () => {
19 const res = await app.request("/admin");
20 expect(res.status).toBe(302);
21 expect(res.headers.get("location") || "").toContain("/login");
22 });
23
24 it("GET /admin/users without auth → 302 /login", async () => {
25 const res = await app.request("/admin/users");
26 expect(res.status).toBe(302);
27 expect(res.headers.get("location") || "").toContain("/login");
28 });
29
30 it("GET /admin/repos without auth → 302 /login", async () => {
31 const res = await app.request("/admin/repos");
32 expect(res.status).toBe(302);
33 expect(res.headers.get("location") || "").toContain("/login");
34 });
35
36 it("GET /admin/flags without auth → 302 /login", async () => {
37 const res = await app.request("/admin/flags");
38 expect(res.status).toBe(302);
39 expect(res.headers.get("location") || "").toContain("/login");
40 });
41
42 it("POST /admin/flags without auth → 302 /login", async () => {
43 const res = await app.request("/admin/flags", {
44 method: "POST",
45 body: new URLSearchParams({ registration_locked: "1" }),
46 headers: { "content-type": "application/x-www-form-urlencoded" },
47 });
48 expect(res.status).toBe(302);
49 expect(res.headers.get("location") || "").toContain("/login");
50 });
51});
52
53describe("admin — isSiteAdmin", () => {
54 it("returns false for null/undefined user", async () => {
55 expect(await isSiteAdmin(null)).toBe(false);
56 expect(await isSiteAdmin(undefined)).toBe(false);
57 expect(await isSiteAdmin("")).toBe(false);
58 });
59
60 it("returns false for non-existent user id", async () => {
61 const result = await isSiteAdmin("00000000-0000-0000-0000-000000000000");
62 expect(typeof result).toBe("boolean");
63 });
64});
65
66describe("admin — KNOWN_FLAGS", () => {
67 it("exposes registration_locked, site_banner_text, site_banner_level, read_only_mode", () => {
68 expect(KNOWN_FLAGS).toHaveProperty("registration_locked");
69 expect(KNOWN_FLAGS).toHaveProperty("site_banner_text");
70 expect(KNOWN_FLAGS).toHaveProperty("site_banner_level");
71 expect(KNOWN_FLAGS).toHaveProperty("read_only_mode");
72 });
73
74 it("defaults registration_locked to '0' (unlocked)", () => {
75 expect(KNOWN_FLAGS.registration_locked).toBe("0");
76 });
77});
78
79describe("admin — getFlag", () => {
80 it("returns null for unknown keys and never throws", async () => {
81 const v = await getFlag("nonexistent_flag_xyz");
82 expect(v === null || typeof v === "string").toBe(true);
83 });
84});
85
86describe("admin — lib exports", () => {
87 it("exports full admin surface", async () => {
88 const mod = await import("../lib/admin");
89 expect(typeof mod.isSiteAdmin).toBe("function");
90 expect(typeof mod.listSiteAdmins).toBe("function");
91 expect(typeof mod.grantSiteAdmin).toBe("function");
92 expect(typeof mod.revokeSiteAdmin).toBe("function");
93 expect(typeof mod.getFlag).toBe("function");
94 expect(typeof mod.setFlag).toBe("function");
95 expect(typeof mod.listFlags).toBe("function");
96 expect(mod.KNOWN_FLAGS).toBeDefined();
97 });
98});