g1t/apps/sudo/app/lib/signals.test.ts
Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import type { Signal } from "@g1t/contracts"; | |
| 5 | ||
| sudo: Invoices, Audit log, and follow-ups due | 6 | import { bySignalUrgency, countByKind, filterSignals, followUpsDue, isFollowUpDue, isSignalKind, parseWho, reachOutHref, signalMeta, stageMeta, today } from "./signals.ts"; |
| A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales | 7 | |
| 8 | function signal(workspace: string, kind: string, valueMicros = 0, owner: string | null = null): Signal { | |
| 9 | return { workspace, kind: kind as Signal["kind"], detail: `${workspace} ${kind}`, valueMicros, stage: null, owner }; | |
| 10 | } | |
| 11 | ||
| 12 | test("most urgent first: by kind, then the larger figure, else as billing sent them", () => { | |
| 13 | const sorted = bySignalUrgency([ | |
| 14 | signal("a", "growing", 10), | |
| 15 | signal("b", "first_payment", 99), | |
| 16 | signal("c", "near_ceiling", 5), | |
| 17 | signal("d", "at_limit", 1), | |
| 18 | signal("e", "near_ceiling", 50), | |
| 19 | signal("f", "something_new", 1000), | |
| 20 | signal("g", "declined", 0), | |
| 21 | signal("h", "growing", 10), | |
| 22 | ]); | |
| 23 | assert.deepEqual( | |
| 24 | sorted.map((s) => s.workspace), | |
| 25 | ["d", "g", "e", "c", "a", "h", "b", "f"], | |
| 26 | ); | |
| 27 | }); | |
| 28 | ||
| 29 | test("sorting leaves the input alone", () => { | |
| 30 | const input = [signal("a", "growing"), signal("b", "at_limit")]; | |
| 31 | bySignalUrgency(input); | |
| 32 | assert.equal(input[0].workspace, "a"); | |
| 33 | }); | |
| 34 | ||
| 35 | test("filter by kind, and by whose they are", () => { | |
| 36 | const all = [ | |
| 37 | signal("a", "at_limit", 0, "Me@g1t.sh"), | |
| 38 | signal("b", "at_limit", 0, null), | |
| 39 | signal("c", "growing", 0, "other@g1t.sh"), | |
| 40 | signal("d", "growing", 0, ""), | |
| 41 | ]; | |
| 42 | const me = "me@g1t.sh"; | |
| 43 | assert.deepEqual(filterSignals(all, { kind: null, who: "all", me }).map((s) => s.workspace), ["a", "b", "c", "d"]); | |
| 44 | assert.deepEqual(filterSignals(all, { kind: "at_limit", who: "all", me }).map((s) => s.workspace), ["a", "b"]); | |
| 45 | assert.deepEqual(filterSignals(all, { kind: null, who: "unassigned", me }).map((s) => s.workspace), ["b", "d"]); | |
| 46 | assert.deepEqual(filterSignals(all, { kind: null, who: "mine", me }).map((s) => s.workspace), ["a"]); | |
| 47 | assert.deepEqual(filterSignals(all, { kind: "growing", who: "mine", me }), []); | |
| 48 | }); | |
| 49 | ||
| 50 | test("counts by kind", () => { | |
| 51 | assert.deepEqual(countByKind([signal("a", "at_limit"), signal("b", "at_limit"), signal("c", "growing")]), { at_limit: 2, growing: 1 }); | |
| 52 | }); | |
| 53 | ||
| 54 | test("query values are checked", () => { | |
| 55 | assert.equal(parseWho("mine"), "mine"); | |
| 56 | assert.equal(parseWho("unassigned"), "unassigned"); | |
| 57 | assert.equal(parseWho("everyone"), "all"); | |
| 58 | assert.equal(parseWho(null), "all"); | |
| 59 | assert.ok(isSignalKind("near_ceiling")); | |
| 60 | assert.ok(!isSignalKind("nearly")); | |
| 61 | assert.ok(!isSignalKind(null)); | |
| 62 | }); | |
| 63 | ||
| 64 | test("links into the queue leave out the defaults", () => { | |
| 65 | assert.equal(reachOutHref({}), "/reach-out"); | |
| 66 | assert.equal(reachOutHref({ kind: "at_limit" }), "/reach-out?kind=at_limit"); | |
| 67 | assert.equal(reachOutHref({ kind: "declined", who: "mine" }), "/reach-out?kind=declined&who=mine"); | |
| 68 | assert.equal(reachOutHref({ kind: null, who: "all" }), "/reach-out"); | |
| 69 | }); | |
| 70 | ||
| 71 | test("names for kinds and stages, and for ones sudo does not know", () => { | |
| 72 | assert.equal(signalMeta("at_limit").label, "At limit"); | |
| 73 | assert.equal(signalMeta("at_limit").tone, "danger"); | |
| 74 | assert.equal(signalMeta("brand_new").label, "brand new"); | |
| 75 | assert.equal(stageMeta(null).label, "No stage"); | |
| 76 | assert.equal(stageMeta("churn_risk").label, "Churn risk"); | |
| 77 | assert.equal(stageMeta("odd").label, "odd"); | |
| 78 | }); | |
| sudo: Invoices, Audit log, and follow-ups due | 79 | |
| 80 | test("follow-ups due: today or earlier, open deals only, one per workspace, oldest first", () => { | |
| 81 | const s = (workspace: string, nextAt: string | null, stage: string | null = "contacted", kind = "growing"): Signal => ({ | |
| 82 | ...signal(workspace, kind), | |
| 83 | nextAt, | |
| 84 | stage, | |
| 85 | nextStep: nextAt ? "Call" : null, | |
| 86 | }); | |
| 87 | const on = "2026-10-04"; | |
| 88 | assert.ok(isFollowUpDue(s("a", "2026-10-04"), on)); | |
| 89 | assert.ok(isFollowUpDue(s("a", "2026-10-01"), on)); | |
| 90 | assert.ok(!isFollowUpDue(s("a", "2026-10-05"), on)); | |
| 91 | assert.ok(!isFollowUpDue(s("a", null), on)); | |
| 92 | assert.ok(!isFollowUpDue(s("a", "2026-10-01", "won"), on)); | |
| 93 | assert.ok(!isFollowUpDue(s("a", "2026-10-01", "lost"), on)); | |
| 94 | assert.ok(isFollowUpDue(s("a", "2026-10-01", null), on)); | |
| 95 | const due = followUpsDue([s("b", "2026-10-03"), s("a", "2026-09-30", "contacted", "at_limit"), s("a", "2026-09-30", "contacted", "high_spend"), s("c", "2026-10-09")], on); | |
| 96 | assert.deepEqual(due.map((x) => `${x.workspace}:${x.kind}`), ["a:at_limit", "b:growing"]); | |
| 97 | assert.equal(today(new Date("2026-10-04T23:59:00Z")), "2026-10-04"); | |
| 98 | assert.equal(reachOutHref({ due: true }), "/reach-out?due=1"); | |
| 99 | assert.equal(reachOutHref({ due: true, who: "mine" }), "/reach-out?due=1&who=mine"); | |
| 100 | }); |