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.

149 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { ReviewAssignment } from "@g1t/contracts";
5
6import { filterTeams, newTeamFromForm, parentChoices, reviewAssignmentFromForm, splitTeams, teamChangesFromForm, teamCounts, teamPath } from "./teams.ts";
7
8const team = (slug: string, extra: Record<string, unknown> = {}) => ({
9 slug,
10 name: slug[0].toUpperCase() + slug.slice(1),
11 description: null as string | null,
12 visibility: "visible" as "visible" | "secret",
13 parent: null as { slug: string; name: string } | null,
14 viewer_role: null as "member" | "maintainer" | null,
15 ...extra,
16});
17
18const form = (fields: Record<string, string | string[]>) => {
19 const data = new FormData();
20 for (const [key, value] of Object.entries(fields)) {
21 for (const one of Array.isArray(value) ? value : [value]) data.append(key, one);
22 }
23 return data;
24};
25
26const DEFAULTS: ReviewAssignment = {
27 enabled: false,
28 algorithm: "round_robin",
29 count: 1,
30 skip_busy: false,
31 busy_at: 5,
32 include_child_teams: false,
33 excluded: [],
34 notify_team: false,
35};
36
37test("team pages live under the workspace's teams", () => {
38 assert.equal(teamPath("acme", "backend"), "/acme/-/teams/backend");
39 assert.equal(teamPath("acme", "backend", "settings"), "/acme/-/teams/backend/settings");
40});
41
42test("teams are found by every word of the search", () => {
43 const teams = [team("backend", { description: "APIs and data" }), team("web"), team("platform", { description: "Shared backend tools" })];
44 assert.deepEqual(
45 filterTeams(teams, "").map((t) => t.slug),
46 ["backend", "web", "platform"],
47 );
48 assert.deepEqual(
49 filterTeams(teams, "BACKEND").map((t) => t.slug),
50 ["backend", "platform"],
51 );
52 assert.deepEqual(
53 filterTeams(teams, "backend tools").map((t) => t.slug),
54 ["platform"],
55 );
56 assert.deepEqual(filterTeams(teams, "nothing"), []);
57});
58
59test("your teams come first", () => {
60 const { mine, others } = splitTeams([team("a"), team("b", { viewer_role: "member" }), team("c", { viewer_role: "maintainer" })]);
61 assert.deepEqual(
62 mine.map((t) => t.slug),
63 ["b", "c"],
64 );
65 assert.deepEqual(
66 others.map((t) => t.slug),
67 ["a"],
68 );
69});
70
71test("a team can go under any visible team but itself and those below it", () => {
72 const teams = [
73 team("eng"),
74 team("backend", { parent: { slug: "eng", name: "Eng" } }),
75 team("api", { parent: { slug: "backend", name: "Backend" } }),
76 team("web", { parent: { slug: "eng", name: "Eng" } }),
77 team("secret", { visibility: "secret" }),
78 ];
79 assert.deepEqual(
80 parentChoices(teams, "backend").map((t) => t.slug),
81 ["eng", "web"],
82 );
83 assert.deepEqual(
84 parentChoices(teams, "eng").map((t) => t.slug),
85 [],
86 );
87 assert.deepEqual(
88 parentChoices(teams, null).map((t) => t.slug),
89 ["eng", "backend", "api", "web"],
90 );
91});
92
93test("a new team reads its form", () => {
94 assert.deepEqual(newTeamFromForm(form({ name: " Backend ", slug: "", description: "", visibility: "secret", parent: "", members: "@ana, bo cy" })), {
95 name: "Backend",
96 slug: null,
97 description: null,
98 visibility: "secret",
99 parent: null,
100 members: ["ana", "bo", "cy"],
101 });
102 assert.equal(newTeamFromForm(form({ name: "x", visibility: "weird" })).visibility, "visible");
103});
104
105test("settings change only what their form has", () => {
106 assert.deepEqual(teamChangesFromForm(form({ name: "Web", description: " UI " })), { name: "Web", description: "UI" });
107 assert.deepEqual(teamChangesFromForm(form({ parent: "" })), { parent: "" });
108 assert.deepEqual(teamChangesFromForm(form({ "notify-shown": "1" })), { notify: false });
109 assert.deepEqual(teamChangesFromForm(form({ "notify-shown": "1", notify: "on" })), { notify: true });
110 assert.deepEqual(teamChangesFromForm(form({ visibility: "secret" })), { visibility: "secret" });
111});
112
113test("review assignment is read within bounds", () => {
114 const read = reviewAssignmentFromForm(
115 form({ enabled: "on", algorithm: "load_balance", count: "40", skip_busy: "on", busy_at: "0", excluded: "@Ana, bo ana" }),
116 DEFAULTS,
117 );
118 assert.deepEqual(read, {
119 enabled: true,
120 algorithm: "load_balance",
121 count: 10,
122 skip_busy: true,
123 busy_at: 1,
124 include_child_teams: false,
125 excluded: ["ana", "bo"],
126 notify_team: false,
127 });
128 // Off, and nonsense kept as it was.
129 const off = reviewAssignmentFromForm(form({ algorithm: "random", count: "many" }), { ...DEFAULTS, count: 3 });
130 assert.equal(off.enabled, false);
131 assert.equal(off.algorithm, "round_robin");
132 assert.equal(off.count, 3);
133});
134
135test("counts leave out what is none", () => {
136 assert.equal(teamCounts({ members_count: 1, repos_count: 0, child_teams_count: 2 }), "1 member · 2 child teams");
137 assert.equal(teamCounts({ members_count: 0, repos_count: 0, child_teams_count: 0 }), "No members yet");
138 assert.equal(teamCounts({ members_count: 2, repos_count: 1, child_teams_count: 0 }), "2 members · 1 repository");
139});
140
141test("who may create teams follows the workspace's setting", async () => {
142 // From the contracts' source: the Teams page and the + menu decide with it.
143 const { mayCreateTeams } = await import("../../../../packages/contracts/src/teams.ts");
144 assert.equal(mayCreateTeams(undefined, "member"), true);
145 assert.equal(mayCreateTeams("members", "member"), true);
146 assert.equal(mayCreateTeams("owners", "member"), false);
147 assert.equal(mayCreateTeams("owners", "owner"), true);
148 assert.equal(mayCreateTeams("members", null), false);
149});