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
62 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { debugReport, describeError, developerCookie, readDeveloperMode, wantsServerErrors } from "./developer-mode.ts";
5
6const request = (cookie: string | null, authorization?: string) =>
7 new Request("https://g1t.sh/acme", { headers: { ...(cookie ? { cookie } : {}), ...(authorization ? { authorization } : {}) } });
8
9test("developer mode is on only for the cookie's own value", () => {
10 assert.equal(readDeveloperMode("1"), true);
11 for (const junk of ["", "true", "0", null, undefined]) assert.equal(readDeveloperMode(junk), false);
12});
13
14test("the cookie keeps the choice for a year, and turning it off forgets it", () => {
15 assert.equal(developerCookie(true, true), "g1t_dev=1; Path=/; Max-Age=31536000; SameSite=Lax; Secure");
16 assert.equal(developerCookie(false, false), "g1t_dev=; Path=/; Max-Age=0; SameSite=Lax");
17});
18
19test("the server's own errors go only to someone signed in who turned it on", () => {
20 assert.equal(wantsServerErrors(request("g1t_session=abc; g1t_dev=1")), true);
21 assert.equal(wantsServerErrors(request("g1t_dev=1; g1t_theme=dark", "Bearer g1t_x")), true);
22 assert.equal(wantsServerErrors(request("g1t_dev=1")), false);
23 assert.equal(wantsServerErrors(request("g1t_session=abc")), false);
24 assert.equal(wantsServerErrors(request("g1t_session=abc; g1t_dev=10")), false);
25 assert.equal(wantsServerErrors(request("g1t_session=abc; not_g1t_dev=1")), false);
26});
27
28test("whatever was thrown is described", () => {
29 const thrown = describeError(new TypeError("x is undefined"));
30 assert.equal(thrown.kind, "TypeError");
31 assert.equal(thrown.message, "x is undefined");
32 const response = describeError({ status: 500, statusText: "Internal Server Error", data: "the sidebar could not be read" });
33 assert.deepEqual([response.kind, response.status, response.message, response.data], ["Response", 500, "500 Internal Server Error", "the sidebar could not be read"]);
34 assert.deepEqual([describeError("plain").kind, describeError("plain").message], ["string", "plain"]);
35});
36
37test("one report says what failed, where, when and on which build", () => {
38 const error = new Error("Cannot read properties of undefined (reading 'slug')");
39 error.stack = "Error: Cannot read properties of undefined\n at Integrations (integrations.tsx:10:5)";
40 const report = debugReport({
41 url: "https://g1t.sh/flagon-io/-/integrations",
42 at: new Date("2026-10-12T23:00:00Z"),
43 error,
44 routes: ["root", "routes/workspace/integrations"],
45 build: "app-Ab12Cd.css",
46 userAgent: "Chrome",
47 desktop: "0.3.6",
48 navigation: "client",
49 });
50 for (const line of [
51 "URL: https://g1t.sh/flagon-io/-/integrations",
52 "Time: 2026-10-12T23:00:00.000Z",
53 "Loaded: a navigation in the browser",
54 "Routes: root > routes/workspace/integrations",
55 "Desktop app: 0.3.6",
56 "Error: Cannot read properties of undefined (reading 'slug')",
57 " at Integrations (integrations.tsx:10:5)",
58 ]) {
59 assert.ok(report.includes(line), `${line} in:\n${report}`);
60 }
61 assert.ok(debugReport({ url: "/", at: null, error, routes: [], build: "b", userAgent: "", navigation: "document" }).includes("Time: (not yet in the browser)"));
62});