Skip to content
133 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { RepoMirror } from "@g1t/contracts";
5
6import { frameOf, hiddenOnMirror, projectPageAt, projectPages } from "./chrome.ts";
7
8const visitor = { signedIn: false, workspace: false };
9const mirror = (state: RepoMirror["state"], warm = false): RepoMirror => ({
10 state,
11 remote: "github.com/acme/web",
12 url: "https://github.com/acme/web",
13 since: "2026-10-08T10:00:00Z",
14 warm,
15});
16const member = { signedIn: true, workspace: true };
17const newcomer = { signedIn: true, workspace: false };
18
19test("signing in, signing up and choosing a workspace stand alone, for everyone", () => {
20 for (const path of [
21 "/login",
22 "/login/two-factor",
23 "/register",
24 "/register/",
25 "/invite/abc123",
26 "/verify",
27 "/confirm-email",
28 "/forgot",
29 "/reset",
30 "/device",
31 "/oauth/authorize",
32 "/auth/github/callback",
33 "/auth/github/username",
34 "/workspaces/new",
35 "/workspaces/new.data",
36 ]) {
37 for (const viewer of [visitor, member, newcomer]) assert.equal(frameOf(path, viewer), "standalone", path);
38 }
39});
40
41test("answering an invitation stands alone until you belong to a workspace", () => {
42 assert.equal(frameOf("/invitations", newcomer), "standalone");
43 assert.equal(frameOf("/invitations", member), "app");
44});
45
46test("someone signed in gets the app everywhere else, public pages included", () => {
47 for (const path of ["/", "/explore", "/u/ada", "/other/web", "/acme/-/home", "/notifications", "/pricing", "/does/not/exist"]) {
48 assert.equal(frameOf(path, member), "app", path);
49 assert.equal(frameOf(path, newcomer), "app", path);
50 }
51});
52
53test("a visitor gets the public frame everywhere else", () => {
54 for (const path of ["/", "/explore", "/search", "/u/ada", "/acme", "/acme/web", "/acme/web/issues/4", "/policies/privacy", "/nothing/here/at/all"]) {
55 assert.equal(frameOf(path, visitor), "public", path);
56 }
57 // A workspace named like a page is still a workspace, and still public to a visitor.
58 assert.equal(frameOf("/loginx", visitor), "public");
59});
60
61test("a project's menu hides member-only pages from everyone else", () => {
62 const visitor = projectPages(false);
63 assert.deepEqual(visitor.slice(0, 5), ["code", "issues", "pulls", "agents", "actions"]);
64 for (const page of ["security", "settings"] as const) {
65 assert.ok(!visitor.includes(page), page);
66 assert.ok(projectPages(true).includes(page), page);
67 }
68 // Security needs push once the role is known: Read and Triage do not see it.
69 assert.ok(!projectPages(true, { push: false }).includes("security"));
70 assert.ok(projectPages(true, { push: true }).includes("security"));
71 // Anyone who can read a repository sees its deployments.
72 assert.ok(visitor.includes("deployments") && projectPages(true).includes("deployments"));
73});
74
75test("a mirror's menu lists what it offers: a read-only copy until it is taken over", () => {
76 const can = { push: true };
77 const all = projectPages(true, can);
78 assert.deepEqual(projectPages(true, can, null), all);
79 assert.deepEqual(projectPages(true, can, mirror("takeover")), all);
80 // Standing by: code, security, insights and settings. Nothing that works or runs.
81 assert.deepEqual(projectPages(true, can, mirror("standby")), ["code", "security", "insights", "settings"]);
82 assert.deepEqual(projectPages(false, undefined, mirror("standby")), ["code", "insights"]);
83 // Workflows show when they run here: CI failover, or a standby kept warm.
84 assert.deepEqual(projectPages(true, can, mirror("ci")), ["code", "actions", "security", "insights", "settings"]);
85 assert.ok(projectPages(true, can, mirror("standby", true)).includes("actions"));
86 assert.ok(!projectPages(true, can, mirror("handing_back", true)).includes("actions"));
87 assert.ok(!projectPages(true, can, mirror("handing_back")).includes("issues"));
88});
89
90test("a page a mirror does not offer stands behind the read-only note, by its name", () => {
91 const standby = mirror("standby");
92 assert.deepEqual(hiddenOnMirror("issues", standby), { page: "issues", what: "issues" });
93 assert.deepEqual(hiddenOnMirror("issues/new", standby), { page: "issues", what: "issues" });
94 assert.deepEqual(hiddenOnMirror("pulls", standby), { page: "pulls", what: "pull requests" });
95 assert.deepEqual(hiddenOnMirror("queue", standby), { page: "pulls", what: "pull requests" });
96 assert.deepEqual(hiddenOnMirror("agents/runs/9", standby), { page: "agents", what: "agents" });
97 assert.deepEqual(hiddenOnMirror("sessions", standby), { page: "agents", what: "agents" });
98 assert.deepEqual(hiddenOnMirror("memory", standby), { page: "agents", what: "agents" });
99 assert.deepEqual(hiddenOnMirror("deployments/d1", standby), { page: "deployments", what: "deployments" });
100 assert.deepEqual(hiddenOnMirror("labels", standby), { page: "issues", what: "issues" });
101 assert.deepEqual(hiddenOnMirror("milestones/2", standby), { page: "issues", what: "issues" });
102 assert.deepEqual(hiddenOnMirror("plans", standby), { page: "issues", what: "issues" });
103 assert.deepEqual(hiddenOnMirror("actions", standby), { page: "actions", what: "workflows" });
104 assert.deepEqual(hiddenOnMirror("releases/new", standby), { page: "code", what: "releases" });
105 // What a read-only copy still shows.
106 for (const path of ["", "code", "tree/main/src", "commits", "branches", "releases", "compare", "security/vulnerabilities", "contributors", "settings/mirroring", "issues/12", "pull/3/files"]) {
107 assert.equal(hiddenOnMirror(path, standby), null, path);
108 }
109 // Workflows stay when they run here; everything stays once g1t leads.
110 assert.equal(hiddenOnMirror("actions", mirror("ci")), null);
111 assert.equal(hiddenOnMirror("actions", mirror("standby", true)), null);
112 assert.equal(hiddenOnMirror("issues", mirror("takeover")), null);
113 assert.equal(hiddenOnMirror("issues", null), null);
114 assert.ok(hiddenOnMirror("pulls", mirror("handing_back")));
115});
116
117test("the phone's project strip lights the page a path is under", () => {
118 assert.equal(projectPageAt(""), "overview");
119 assert.equal(projectPageAt("blob/main/README.md"), "code");
120 assert.equal(projectPageAt("commit/abc123"), "code");
121 assert.equal(projectPageAt("issues/12"), "issues");
122 assert.equal(projectPageAt("milestones"), "issues");
123 assert.equal(projectPageAt("pull/3/files"), "pulls");
124 assert.equal(projectPageAt("queue"), "pulls");
125 assert.equal(projectPageAt("sessions/abc"), "agents");
126 assert.equal(projectPageAt("actions/runs/9"), "actions");
127 assert.equal(projectPageAt("security/secret-scanning"), "security");
128 assert.equal(projectPageAt("stargazers"), "insights");
129 assert.equal(projectPageAt("settings/branches"), "settings");
130 assert.equal(projectPageAt("soon/logs", { logs: "observability" }), "observability");
131 assert.equal(projectPageAt("soon/boards", { boards: "issues" }), "issues");
132 assert.equal(projectPageAt("pulse"), null);
133});