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.

114 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { AccountSummary, AdminWorkspace, Limit, Terms } from "@g1t/contracts";
5
6import { STANDARD_TERMS, joinWorkspaces, legacyAccountPath, paginate } from "./workspaces.ts";
7
8function limit(workspace: string, account: string, exposureMicros = 0): Limit {
9 return {
10 workspace,
11 account,
12 accountName: account,
13 trust: "new",
14 exposureMicros,
15 ceilingMicros: 10_000_000,
16 trustCeilingMicros: 10_000_000,
17 spendLimitMicros: null,
18 state: "ok",
19 message: null,
20 };
21}
22
23function workspace(slug: string, owner = `${slug}-owner`): AdminWorkspace {
24 return {
25 slug,
26 name: slug.toUpperCase(),
27 createdAt: "2026-10-01T00:00:00Z",
28 owners: [{ username: owner, email: `${owner}@example.com` }],
29 memberCount: 1,
30 };
31}
32
33const COMPED: Terms = { ...STANDARD_TERMS, kind: "comped", note: "g1t's own" };
34
35const OWN: AccountSummary = {
36 account: { id: "ws_syntaqx", kind: "workspace", name: "syntaqx", terms: COMPED, workspaces: ["syntaqx"], createdAt: "2026-10-05T00:00:00Z" },
37 limit: limit("syntaqx", "ws_syntaqx", 3_000_000),
38 chargedMicros: 0,
39 costMicros: 3_000_000,
40 paidMicros: 0,
41 byWorkspace: [{ workspace: "syntaqx", chargedMicros: 0, costMicros: 3_000_000, paidMicros: 0 }],
42};
43
44const ACME: AccountSummary = {
45 account: {
46 id: "ent_acme",
47 kind: "enterprise",
48 name: "Acme Corp",
49 terms: STANDARD_TERMS,
50 workspaces: ["acme", "acme-labs"],
51 createdAt: "2026-10-02T00:00:00Z",
52 },
53 limit: limit("acme", "ent_acme", 9_000_000),
54 chargedMicros: 12_000_000,
55 costMicros: 6_000_000,
56 paidMicros: 0,
57 byWorkspace: [
58 { workspace: "acme", chargedMicros: 12_000_000, costMicros: 6_000_000, paidMicros: 0 },
59 { workspace: "acme-labs", chargedMicros: 0, costMicros: 0, paidMicros: 0 },
60 ],
61};
62
63test("every workspace is listed, with or without billing", () => {
64 const rows = joinWorkspaces([workspace("syntaqx"), workspace("quiet")], [OWN]);
65 assert.deepEqual(
66 rows.map((row) => row.slug),
67 ["syntaqx", "quiet"],
68 );
69 const [syntaqx, quiet] = rows;
70 assert.equal(syntaqx.billing.terms.kind, "comped");
71 assert.equal(syntaqx.billing.costMicros, 3_000_000);
72 assert.equal(syntaqx.billing.billedTo, null);
73 assert.equal(quiet.billing.terms.kind, "standard");
74 assert.equal(quiet.billing.limit, null);
75 assert.equal(quiet.billing.chargedMicros, 0);
76});
77
78test("a workspace on an enterprise shows the enterprise and only its own share", () => {
79 const rows = joinWorkspaces([workspace("acme"), workspace("acme-labs")], [ACME]);
80 const labs = rows.find((row) => row.slug === "acme-labs");
81 assert.deepEqual(labs?.billing.billedTo, { id: "ent_acme", name: "Acme Corp" });
82 assert.equal(labs?.billing.chargedMicros, 0);
83 assert.equal(labs?.billing.limit?.exposureMicros, 9_000_000);
84 assert.equal(rows.find((row) => row.slug === "acme")?.billing.chargedMicros, 12_000_000);
85});
86
87test("a page lists only its own workspaces, not the rest of an enterprise", () => {
88 const rows = joinWorkspaces([workspace("acme")], [ACME]);
89 assert.deepEqual(
90 rows.map((row) => row.slug),
91 ["acme"],
92 );
93});
94
95test("pages stay within the list", () => {
96 const items = Array.from({ length: 120 }, (_, i) => i);
97 assert.deepEqual(paginate(items, null).items.slice(0, 2), [0, 1]);
98 const third = paginate(items, "3");
99 assert.equal(third.page, 3);
100 assert.equal(third.pages, 3);
101 assert.equal(third.items.length, 20);
102 assert.equal(paginate(items, "99").page, 3);
103 assert.equal(paginate(items, "-4").page, 1);
104 assert.equal(paginate(items, "abc").page, 1);
105 assert.deepEqual(paginate([], "2"), { page: 1, pages: 1, items: [] });
106});
107
108test("old account links go to the workspace or the enterprise", () => {
109 assert.equal(legacyAccountPath("ws_syntaqx"), "/workspaces/syntaqx");
110 assert.equal(legacyAccountPath("syntaqx"), "/workspaces/syntaqx");
111 assert.equal(legacyAccountPath("ent_01abc"), "/enterprises/ent_01abc");
112 assert.equal(legacyAccountPath("ws_"), null);
113 assert.equal(legacyAccountPath("../etc"), null);
114});