CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /**
* Block J4 — User following route-auth smokes + pure-helper tests.
*
* Graph mutations (followUser, etc.) are DB-bound so they're only exercised
* via integration. Here we cover the describeAction verb table and
* verify route guards redirect anonymous users.
*/
import { describe, it, expect } from "bun:test";
import app from "../app";
import { describeAction } from "../lib/follows";
describe("follows — describeAction", () => {
it("maps known actions", () => {
expect(describeAction("push")).toBe("pushed to");
expect(describeAction("issue_open")).toBe("opened an issue in");
expect(describeAction("issue_close")).toBe("closed an issue in");
expect(describeAction("pr_open")).toBe("opened a pull request in");
expect(describeAction("pr_merge")).toBe("merged a pull request in");
expect(describeAction("pr_close")).toBe("closed a pull request in");
expect(describeAction("star")).toBe("starred");
expect(describeAction("comment")).toBe("commented in");
});
it("falls back to underscore-stripped action for unknown tokens", () => {
expect(describeAction("release_publish")).toBe("release publish");
expect(describeAction("custom")).toBe("custom");
});
});
describe("follows — route auth", () => {
it("POST /:user/follow without auth → 302 /login", async () => {
const res = await app.request("/alice/follow", { method: "POST" });
expect(res.status).toBe(302);
expect(res.headers.get("location") || "").toContain("/login");
});
it("POST /:user/unfollow without auth → 302 /login", async () => {
const res = await app.request("/alice/unfollow", { method: "POST" });
expect(res.status).toBe(302);
expect(res.headers.get("location") || "").toContain("/login");
});
it("GET /feed without auth → 302 /login", async () => {
const res = await app.request("/feed");
expect(res.status).toBe(302);
expect(res.headers.get("location") || "").toContain("/login");
});
it("GET /:user/followers is public (404 or 500 for unknown user)", async () => {
const res = await app.request("/nobody-x/followers");
expect([404, 500]).toContain(res.status);
});
it("GET /:user/following is public (404 or 500 for unknown user)", async () => {
const res = await app.request("/nobody-x/following");
expect([404, 500]).toContain(res.status);
});
it("reserved name /login/followers is not a profile route", async () => {
const res = await app.request("/login/followers");
expect([404, 405, 200, 302]).toContain(res.status);
});
});
|