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

web-routes.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.

web-routes.test.tsBlame153 lines · 2 contributors
06d5ffeClaude1import { describe, it, expect, beforeAll, afterAll } from "bun:test";
2import { join } from "path";
3import { rm, mkdir } from "fs/promises";
4import app from "../app";
5import { initBareRepo, getRepoPath } from "../git/repository";
6
7const TEST_REPOS = join(import.meta.dir, "../../.test-repos-web-" + Date.now());
8
9beforeAll(async () => {
10 await rm(TEST_REPOS, { recursive: true, force: true });
11 await mkdir(TEST_REPOS, { recursive: true });
12 process.env.GIT_REPOS_PATH = TEST_REPOS;
13
14 // Create a test repo with content
15 await initBareRepo("testuser", "myrepo");
16 const cloneDir = join(TEST_REPOS, "_clone");
17 await mkdir(cloneDir, { recursive: true });
18 const repoPath = getRepoPath("testuser", "myrepo");
19 const workDir = join(cloneDir, "work");
20
21 const run = async (cmd: string[], cwd: string) => {
22 const proc = Bun.spawn(cmd, { cwd, stdout: "pipe", stderr: "pipe" });
23 await proc.exited;
24 };
25
26 await run(["git", "clone", repoPath, workDir], TEST_REPOS);
27 await run(["git", "config", "user.email", "test@test.com"], workDir);
28 await run(["git", "config", "user.name", "Test"], workDir);
29
30 await mkdir(join(workDir, "src"), { recursive: true });
31 await Bun.write(join(workDir, "README.md"), "# My Repo\nHello");
32 await Bun.write(
33 join(workDir, "src/index.ts"),
34 'const x: number = 42;\nconsole.log(x);'
35 );
36
37 await run(["git", "add", "-A"], workDir);
38 await run(["git", "commit", "-m", "Initial commit"], workDir);
39 await run(["git", "branch", "-M", "main"], workDir);
40 await run(["git", "push", "-u", "origin", "main"], workDir);
41
42 // Create a second branch
43 await run(["git", "checkout", "-b", "feature"], workDir);
44 await Bun.write(join(workDir, "src/feature.ts"), "export const y = 1;");
45 await run(["git", "add", "-A"], workDir);
46 await run(["git", "commit", "-m", "Add feature"], workDir);
47 await run(["git", "push", "-u", "origin", "feature"], workDir);
48
49 await rm(cloneDir, { recursive: true, force: true });
50});
51
52afterAll(async () => {
53 await rm(TEST_REPOS, { recursive: true, force: true });
54});
55
56describe("web routes", () => {
57 it("GET / returns landing page", async () => {
58 const res = await app.request("/");
59 expect(res.status).toBe(200);
60 const html = await res.text();
61 expect(html).toContain("gluecron");
62 });
63
64 it("GET /login returns login form", async () => {
65 const res = await app.request("/login");
66 expect(res.status).toBe(200);
67 const html = await res.text();
68 expect(html).toContain("Sign in");
cf21786ccanty labs69 expect(html).toContain("Continue with GitHub");
70 expect(html).toContain("Email me a link");
06d5ffeClaude71 });
72
73 it("GET /register returns registration form", async () => {
74 const res = await app.request("/register");
75 expect(res.status).toBe(200);
76 const html = await res.text();
77 expect(html).toContain("Create account");
78 expect(html).toContain('name="username"');
79 expect(html).toContain('name="email"');
80 });
81
82 it("GET /new redirects to login without auth", async () => {
83 const res = await app.request("/new", { redirect: "manual" });
84 expect(res.status).toBe(302);
85 expect(res.headers.get("location")).toContain("/login");
86 });
87
88 it("GET /settings redirects to login without auth", async () => {
89 const res = await app.request("/settings", { redirect: "manual" });
90 expect(res.status).toBe(302);
91 expect(res.headers.get("location")).toContain("/login");
92 });
93
94 it("GET /:owner/:repo shows repo page", async () => {
95 const res = await app.request("/testuser/myrepo");
96 expect(res.status).toBe(200);
97 const html = await res.text();
98 expect(html).toContain("testuser");
99 expect(html).toContain("myrepo");
100 expect(html).toContain("README.md");
101 expect(html).toContain("src");
102 });
103
104 it("GET /:owner/:repo returns 404 for missing repo", async () => {
105 const res = await app.request("/nobody/nope");
106 expect(res.status).toBe(404);
107 });
108
109 it("GET /:owner/:repo/tree/:ref shows tree", async () => {
110 const res = await app.request("/testuser/myrepo/tree/main/src");
111 expect(res.status).toBe(200);
112 const html = await res.text();
113 expect(html).toContain("index.ts");
114 });
115
116 it("GET /:owner/:repo/blob/:ref/:path shows file with syntax highlighting", async () => {
117 const res = await app.request("/testuser/myrepo/blob/main/src/index.ts");
118 expect(res.status).toBe(200);
119 const html = await res.text();
120 // Should contain highlighted code
121 expect(html).toContain("hljs-");
122 expect(html).toContain("42");
123 });
124
125 it("GET /:owner/:repo/commits shows commits", async () => {
126 const res = await app.request("/testuser/myrepo/commits");
127 expect(res.status).toBe(200);
128 const html = await res.text();
129 expect(html).toContain("Initial commit");
130 });
131
132 it("supports branch switching — feature branch", async () => {
133 const res = await app.request("/testuser/myrepo/tree/feature");
134 expect(res.status).toBe(200);
135 const html = await res.text();
136 expect(html).toContain("feature");
137 });
138
139 it("feature branch has feature.ts", async () => {
140 const res = await app.request("/testuser/myrepo/tree/feature/src");
141 expect(res.status).toBe(200);
142 const html = await res.text();
143 expect(html).toContain("feature.ts");
144 });
145
146 it("shows branch dropdown when multiple branches", async () => {
147 const res = await app.request("/testuser/myrepo");
148 const html = await res.text();
149 expect(html).toContain("branch-dropdown");
150 expect(html).toContain("main");
151 expect(html).toContain("feature");
152 });
153});