import assert from "node:assert/strict"; import test from "node:test"; import { beginSessionPageLoad, groupSessionsByRecency, mergeSessionPage, recencyKeyFor, sortSessions, } from "../src/lib/session-groups.ts"; function session(id: string, updatedAt: number, pinned = false) { return { id, pinned, updatedAt }; } test("sortSessions puts pinned ahead of a newer unpinned row", () => { const olderPinned = session("pin", 100, true); const newer = session("new", 500); assert.deepEqual(sortSessions([newer, olderPinned]).map((item) => item.id), ["pin", "new"]); }); test("sortSessions orders same pin state by updatedAt descending", () => { const early = session("early", 100); const late = session("late", 400); assert.deepEqual(sortSessions([early, late]).map((item) => item.id), ["late", "early"]); }); test("sortSessions keeps the original order when pin and time are equal", () => { const first = session("a", 200); const second = session("b", 200); assert.deepEqual(sortSessions([first, second]).map((item) => item.id), ["a", "b"]); }); test("sortSessions does not drop archived rows", () => { const archived = { ...session("arc", 50), archivedAt: "2026-09-01T00:00:00.000Z" }; const live = session("live", 80); assert.deepEqual(sortSessions([archived, live]).map((item) => item.id), ["live", "arc"]); }); test("groupSessionsByRecency uses local midnight for yesterday across 23:59 to 00:01", () => { const now = new Date(2026, 8, 6, 0, 1, 0).getTime(); const justYesterday = new Date(2026, 8, 5, 23, 59, 0).getTime(); const justToday = new Date(2026, 8, 6, 0, 0, 0).getTime(); assert.equal(recencyKeyFor(justYesterday, now), "yesterday"); assert.equal(recencyKeyFor(justToday, now), "today"); }); test("groupSessionsByRecency splits day 7 and day 8, and day 30 and day 31", () => { const now = new Date(2026, 8, 6, 12, 0, 0).getTime(); const todayStart = new Date(2026, 8, 6).getTime(); const dayMs = 24 * 60 * 60 * 1000; const day7 = todayStart - 6 * dayMs + 12 * 60 * 60 * 1000; const day8 = todayStart - 7 * dayMs + 12 * 60 * 60 * 1000; const day30 = todayStart - 29 * dayMs + 12 * 60 * 60 * 1000; const day31 = todayStart - 30 * dayMs + 12 * 60 * 60 * 1000; assert.equal(recencyKeyFor(day7, now), "week"); assert.equal(recencyKeyFor(day8, now), "month"); assert.equal(recencyKeyFor(day30, now), "month"); assert.equal(recencyKeyFor(day31, now), "older"); const groups = groupSessionsByRecency([ session("today", now), session("week", day7), session("older", day31), ], now); assert.deepEqual(groups.map((group) => group.label), ["今天", "最近 7 天", "更早"]); }); test("mergeSessionPage keeps the local row and skips a duplicate id", () => { const local = session("keep", 900); const incoming = [session("keep", 100), session("next", 80)]; assert.deepEqual(mergeSessionPage([local], incoming).map((item) => item.id), ["keep", "next"]); assert.equal(mergeSessionPage([local], incoming)[0]?.updatedAt, 900); }); test("beginSessionPageLoad only starts one in-flight request", () => { const inFlight = { current: false }; assert.equal(beginSessionPageLoad(inFlight, "cursor"), true); assert.equal(beginSessionPageLoad(inFlight, "cursor"), false); assert.equal(beginSessionPageLoad({ current: false }, null), false); });