Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
199 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { pagePath, underWorkspace, workspacePage, workspaceRedirect } from "./workspace-nav.ts";
5
6test("a path is one of the workspace's pages, or none", () => {
7 assert.equal(workspacePage("/acme", "acme"), "overview");
8 assert.equal(workspacePage("/Acme/", "acme"), "overview");
9 assert.equal(workspacePage("/acme.data", "acme"), "overview");
10 assert.equal(workspacePage("/acme/-/projects", "acme"), "projects");
11 assert.equal(workspacePage("/acme/-/people", "acme"), "people");
12 assert.equal(workspacePage("/acme/-/packages", "acme"), "packages");
13 assert.equal(workspacePage("/acme/-/teams", "acme"), "teams");
14 assert.equal(workspacePage("/acme/-/insights", "acme"), "insights");
15 // One package or team has a page of its own; settings and the rest have headings.
16 assert.equal(workspacePage("/acme/-/packages/npm/web", "acme"), null);
17 assert.equal(workspacePage("/acme/-/teams/web", "acme"), null);
18 assert.equal(workspacePage("/acme/-/settings", "acme"), null);
19 assert.equal(workspacePage("/acme/-/agents", "acme"), null);
20 assert.equal(workspacePage("/acme/web", "acme"), null);
21 assert.equal(workspacePage("/other", "acme"), null);
22});
23
24test("old addresses go to where their pages are now", () => {
25 // Members and invites is a page of People's again.
26 assert.equal(workspaceRedirect("/acme/-/members"), null);
27 assert.equal(workspaceRedirect("/acme/-/today", "?x=1"), "/acme/-/home?x=1");
28 // Home is the front page itself: not an old address.
29 assert.equal(workspaceRedirect("/acme/-/home"), null);
30 // Code's Overview lives at -/overview now: not an old address.
31 assert.equal(workspaceRedirect("/acme/-/overview"), null);
32 assert.equal(workspaceRedirect("/acme/-/soon/teams"), "/acme/-/teams");
33 // The Marketplace, Customize and Agents are gone: their old addresses lead nowhere.
34 assert.equal(workspaceRedirect("/acme/-/marketplace/agents"), null);
35 assert.equal(workspaceRedirect("/acme/-/marketplace/extensions"), null);
36 assert.equal(workspaceRedirect("/acme/-/agents/skills"), null);
37 assert.equal(workspaceRedirect("/acme/-/soon/insights", "?x=1"), "/acme/-/insights?x=1");
38 assert.equal(workspaceRedirect("/acme/-/soon/uptime"), null);
39 assert.equal(workspaceRedirect("/acme/-/people"), null);
40 assert.equal(workspaceRedirect("/acme/web"), null);
41});
42
43test("?tab= opens that page, keeping the rest of the query", () => {
44 assert.equal(workspaceRedirect("/acme", "?tab=repositories"), "/acme/-/projects");
45 assert.equal(workspaceRedirect("/acme", "?tab=projects&q=api"), "/acme/-/projects?q=api");
46 assert.equal(workspaceRedirect("/acme", "?tab=members"), "/acme/-/members");
47 assert.equal(workspaceRedirect("/acme", "?tab=people"), "/acme/-/people");
48 assert.equal(workspaceRedirect("/acme", "?tab=overview"), "/acme");
49 assert.equal(workspaceRedirect("/acme", "?tab=settings"), "/acme/-/settings");
50 assert.equal(workspaceRedirect("/acme", "?tab=nonsense"), null);
51 assert.equal(workspaceRedirect("/acme", ""), null);
52});
53
54test("a click's data request is for the same page as a full load", () => {
55 assert.equal(pagePath("/acme/-/insights.data"), "/acme/-/insights");
56 assert.equal(pagePath("/acme/-/insights/"), "/acme/-/insights");
57 assert.equal(workspaceRedirect("/acme/-/today.data", "?_routes=routes%2Fworkspace%2Fmoved-today"), "/acme/-/home");
58 assert.equal(workspaceRedirect("/acme/-/today.data", "?_routes=x&q=ada"), "/acme/-/home?q=ada");
59});
60
61test("an alias or old name leads to the same page under the workspace", () => {
62 assert.equal(underWorkspace("/g1t", "", "flagon-io"), "/flagon-io");
63 assert.equal(underWorkspace("/g1t/g1t/issues", "?q=is%3Aopen", "flagon-io"), "/flagon-io/g1t/issues?q=is%3Aopen");
64 assert.equal(underWorkspace("/g1t/g1t/blob/main/README.md", "", "flagon-io"), "/flagon-io/g1t/blob/main/README.md");
65 assert.equal(underWorkspace("/g1t/-/people/", "", "flagon-io"), "/flagon-io/-/people");
66});
67
68test("a click's data request for an alias leads to the page, not its data", () => {
69 assert.equal(underWorkspace("/g1t.data", "?_routes=routes%2Fworkspace%2Flayout", "flagon-io"), "/flagon-io");
70 assert.equal(
71 underWorkspace("/g1t/g1t/pulls.data", "?_routes=routes%2Frepo%2Flayout&state=closed", "flagon-io"),
72 "/flagon-io/g1t/pulls?state=closed",
73 );
74});
75
76test("the rail's mode follows the address", async () => {
77 const { modeOf, modeHome, homePath } = await import("./workspace-nav.ts");
78 assert.equal(modeOf("/", "acme"), "home");
79 assert.equal(modeOf("/acme", "acme"), "home");
80 assert.equal(modeOf("/acme/-/home", "acme"), "home");
81 // g1t's own public pages light no mode.
82 assert.equal(modeOf("/explore", "acme"), "site");
83 assert.equal(modeOf("/u/ada", "acme"), "site");
84 assert.equal(modeOf("/search.data", "acme"), "site");
85 assert.equal(modeOf("/notifications", "acme"), "notifications");
86 assert.equal(modeOf("/settings/emails", "acme"), "account");
87 assert.equal(modeOf("/acme/-/chat/general", "acme"), "chat");
88 assert.equal(modeOf("/acme/-/chat/dm/c1.data", "acme"), "chat");
89 // Agents mode is gone: its old addresses fall to Code's not-found page; Memory is Code's.
90 assert.equal(modeOf("/acme/-/agents", "acme"), "code");
91 assert.equal(modeOf("/acme/-/memory", "acme"), "code");
92 assert.equal(modeOf("/acme/-/artifacts", "acme"), "artifacts");
93 assert.equal(modeOf("/acme/-/artifacts/spaces/general", "acme"), "artifacts");
94 // Docs mode is gone: its old addresses are nobody's mode, so they fall to Code's not-found page.
95 assert.equal(modeOf("/acme/-/docs", "acme"), "code");
96 assert.equal(modeOf("/acme/-/overview", "acme"), "code");
97 assert.equal(modeOf("/acme/-/projects", "acme"), "code");
98 assert.equal(modeOf("/acme/-/security", "acme"), "code");
99 assert.equal(modeOf("/acme/-/security/settings", "acme"), "workspace");
100 assert.equal(modeOf("/acme/-/people", "acme"), "people");
101 assert.equal(modeOf("/acme/-/teams/web", "acme"), "people");
102 assert.equal(modeOf("/acme/-/people/ana", "acme"), "people");
103 // Members, invitations and permissions are the workspace's settings.
104 assert.equal(modeOf("/acme/-/members", "acme"), "workspace");
105 assert.equal(modeOf("/acme/-/members/invitations", "acme"), "workspace");
106 assert.equal(modeOf("/acme/-/permissions", "acme"), "workspace");
107 assert.equal(modeOf("/acme/-/apps", "acme"), "apps");
108 assert.equal(modeOf("/acme/-/billing", "acme"), "workspace");
109 assert.equal(modeOf("/acme/-/tokens", "acme"), "workspace");
110 assert.equal(modeOf("/acme/-/workspace", "acme"), "workspace");
111 assert.equal(modeOf("/acme/web/pulls", "acme"), "code");
112 assert.equal(modeOf("/new", "acme"), "code");
113 // Another workspace's chat is not this one's mode; its repositories are Code's.
114 assert.equal(modeOf("/other/-/chat", "acme"), "code");
115 assert.equal(modeHome("home", "acme"), "/acme/-/home");
116 assert.equal(modeHome("notifications", "acme"), "/notifications");
117 assert.equal(modeHome("people", "acme"), "/acme/-/people");
118 assert.equal(modeHome("apps", "acme"), "/acme/-/apps");
119 assert.equal(modeHome("code", "acme"), "/acme/-/overview");
120 assert.equal(modeHome("workspace", "acme"), "/acme/-/workspace");
121 assert.equal(homePath("acme"), "/acme/-/home");
122 assert.equal(homePath("acme", "?tab=landed&_routes=x"), "/acme/-/overview?tab=landed");
123});
124
125test("Workspace mode's sidebar knows which group and page an address is", async () => {
126 const { WORKSPACE_SETTINGS_GROUPS, modeOf, workspaceSettingsPage } = await import("./workspace-nav.ts");
127 assert.deepEqual(workspaceSettingsPage("/acme/-/settings", "acme"), { group: "general", page: "settings" });
128 assert.deepEqual(workspaceSettingsPage("/acme/-/settings/chat", "acme"), { group: "chat", page: "chat-settings" });
129 assert.deepEqual(workspaceSettingsPage("/acme/-/members", "acme"), { group: "access", page: "members" });
130 assert.deepEqual(workspaceSettingsPage("/acme/-/members/invitations.data", "acme"), { group: "access", page: "invitations" });
131 assert.deepEqual(workspaceSettingsPage("/acme/-/permissions", "acme"), { group: "access", page: "permissions" });
132 assert.deepEqual(workspaceSettingsPage("/acme/-/rules/rs_1", "acme"), { group: "security", page: "rules" });
133 assert.deepEqual(workspaceSettingsPage("/acme/-/security/settings", "acme"), { group: "security", page: "security-settings" });
134 assert.deepEqual(workspaceSettingsPage("/acme/-/usage", "acme"), { group: "money", page: "usage" });
135 // The overview, Code's security page and another workspace are no settings page.
136 assert.equal(workspaceSettingsPage("/acme/-/workspace", "acme"), null);
137 assert.equal(workspaceSettingsPage("/acme/-/security", "acme"), null);
138 assert.equal(workspaceSettingsPage("/other/-/settings", "acme"), null);
139 // Every real page is in Workspace mode, and every key is unique.
140 const keys = new Set<string>();
141 for (const group of WORKSPACE_SETTINGS_GROUPS) {
142 for (const page of group.pages) {
143 assert.ok(!keys.has(page.key), `${page.key} twice`);
144 keys.add(page.key);
145 if (!page.soon) assert.equal(modeOf(`/acme/-/${page.path}`, "acme"), "workspace", page.path);
146 }
147 }
148});
149
150test("a member without Code access is sent around Code's pages", async () => {
151 const { codeGate } = await import("./workspace-nav.ts");
152 const none = ["acme"];
153 assert.equal(codeGate("/", "", none, "acme"), "/acme/-/home");
154 assert.equal(codeGate("/", "", none, "other"), null);
155 assert.equal(codeGate("/acme", "", none, "acme"), "/acme/-/home");
156 assert.equal(codeGate("/acme/web/pull/3", "?x=1", none, "acme"), "/acme/-/code-access?from=%2Facme%2Fweb%2Fpull%2F3%3Fx%3D1");
157 assert.equal(codeGate("/acme/-/projects", "", none, "acme"), "/acme/-/code-access?from=%2Facme%2F-%2Fprojects");
158 assert.equal(codeGate("/acme/-/chat/general", "", none, "acme"), null);
159 assert.equal(codeGate("/acme/-/code-access", "", none, "acme"), null);
160 assert.equal(codeGate("/other/web", "", none, "acme"), null);
161 assert.equal(codeGate("/acme/web", "", [], "acme"), null);
162});
163
164test("g1t beyond your workspaces is browsed, and whose it is", async () => {
165 const { browsingOf, shellMode } = await import("./workspace-nav.ts");
166 const viewer = { slug: "acme", memberships: ["acme", "Side-Co"], shared: [{ namespace: "friend", name: "notes" }], username: "ada" };
167 // Explore and search are nobody's.
168 assert.deepEqual(browsingOf("/explore", viewer), { owner: null });
169 assert.deepEqual(browsingOf("/explore.data", viewer), { owner: null });
170 assert.deepEqual(browsingOf("/search", viewer), { owner: null });
171 // Someone's profile is theirs; your own is no one's being browsed.
172 assert.deepEqual(browsingOf("/u/grace", viewer), { owner: { kind: "person", name: "grace" } });
173 assert.deepEqual(browsingOf("/u/Ada", viewer), { owner: null });
174 // Another workspace, its pages and its projects.
175 assert.deepEqual(browsingOf("/other", viewer), { owner: { kind: "workspace", name: "other", repo: null } });
176 assert.deepEqual(browsingOf("/other/-/projects", viewer), { owner: { kind: "workspace", name: "other", repo: null } });
177 assert.deepEqual(browsingOf("/other/site/pulls/3", viewer), { owner: { kind: "workspace", name: "other", repo: "site" } });
178 // Your workspaces are never browsed, the one you are in or another (the shell switches to it).
179 assert.equal(browsingOf("/acme/web", viewer), null);
180 assert.equal(browsingOf("/acme/-/projects", viewer), null);
181 assert.equal(browsingOf("/side-co/api", viewer), null);
182 // A project shared with you is Code's; the rest of its workspace is browsed.
183 assert.equal(browsingOf("/friend/notes/issues", viewer), null);
184 assert.deepEqual(browsingOf("/friend/other", viewer), { owner: { kind: "workspace", name: "friend", repo: "other" } });
185 // g1t's own pages and files are no one's.
186 for (const path of ["/", "/settings/emails", "/notifications", "/new", "/policies/terms", "/workspaces/new", "/invitations", "/robots.txt", "/.well-known/g1t.json", "/u"]) {
187 assert.equal(browsingOf(path, viewer), null, path);
188 }
189 // Without a workspace there is no rail, and nothing is browsed.
190 assert.equal(browsingOf("/explore", { slug: null, memberships: [] }), null);
191 // The shell's mode: browse beyond your workspaces, the address's mode otherwise.
192 assert.equal(shellMode("/explore", viewer), "browse");
193 assert.equal(shellMode("/u/grace", viewer), "browse");
194 assert.equal(shellMode("/other/site", viewer), "browse");
195 assert.equal(shellMode("/acme/web", viewer), "code");
196 assert.equal(shellMode("/friend/notes", viewer), "code");
197 assert.equal(shellMode("/acme/-/chat", viewer), "chat");
198 assert.equal(shellMode("/policies", viewer), "site");
199});