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.

60 linesCodeBlameRaw
1import { test } from "node:test";
2import assert from "node:assert/strict";
3
4import { dmTitle, isUnread, sidebarOrder, tally } from "./unread.ts";
5
6test("unread is what others wrote after your last read", () => {
7 assert.equal(isUnread({ id: "msg_2", author: "user:b" }, "user:a", "msg_1"), true);
8 assert.equal(isUnread({ id: "msg_1", author: "user:b" }, "user:a", "msg_1"), false);
9 assert.equal(isUnread({ id: "msg_2", author: "user:a" }, "user:a", "msg_1"), false);
10 assert.equal(isUnread({ id: "msg_0", author: "agent:x" }, "user:a", null), true);
11});
12
13test("counts per channel, replies included, with mentions of the viewer", () => {
14 const rows = [
15 { channel_id: "c1", id: "m1", author: "user:b", mentions: "" },
16 { channel_id: "c1", id: "m2", author: "agent:x", mentions: " syntaqx " },
17 { channel_id: "c1", id: "m3", author: "user:a", mentions: " syntaqx " },
18 { channel_id: "c2", id: "m4", author: "user:b", mentions: " syntaqxx " },
19 { channel_id: "c2", id: "m0", author: "user:b", mentions: " syntaqx " },
20 ];
21 const counts = tally(
22 rows,
23 "user:a",
24 "syntaqx",
25 new Map([
26 ["c1", null],
27 ["c2", "m1"],
28 ]),
29 );
30 assert.deepEqual(counts.get("c1"), { unread: 2, mentions: 1 });
31 // m0 was read already, and @syntaqxx is someone else.
32 assert.deepEqual(counts.get("c2"), { unread: 1, mentions: 0 });
33 assert.equal(counts.get("c3"), undefined);
34});
35
36test("the sidebar puts starred first, then the most recently active", () => {
37 const entry = (title: string, starred: boolean, at: string | null) => ({
38 title,
39 starred,
40 channel: { last_message_at: at, created_at: "2026-10-01T00:00:00.000Z" },
41 });
42 const ordered = sidebarOrder([
43 entry("quiet", false, null),
44 entry("busy", false, "2026-10-08T10:00:00.000Z"),
45 entry("pinned", true, "2026-10-02T00:00:00.000Z"),
46 entry("older", false, "2026-10-05T00:00:00.000Z"),
47 ]);
48 assert.deepEqual(
49 ordered.map((e) => e.title),
50 ["pinned", "busy", "older", "quiet"],
51 );
52});
53
54test("a direct message is titled by the others, or by you for notes", () => {
55 const p = (display_name: string) => ({ display_name });
56 assert.equal(dmTitle([p("Ada")], p("Me")), "Ada");
57 assert.equal(dmTitle([p("Ada"), p("Ship")], p("Me")), "Ada, Ship");
58 assert.equal(dmTitle([p("A"), p("B"), p("C"), p("D"), p("E")], p("Me")), "A, B, C and 2 more");
59 assert.equal(dmTitle([], p("Chase")), "Chase (you)");
60});