import { describe, expect, it } from "bun:test"; import { HistoryCursorError, sessionHistoryPage, sessionMessagePage } from "../../src/sessions/history-page.js"; describe("scoped history pagination", () => { const records = Array.from({ length: 65 }, (_, i) => ({ sessionId: `session-${String(i).padStart(3, "0")}`, updatedAt: "2026-10-22T01:00:00Z", title: i === 0 ? "城南压力复核" : `对话 ${i}` })); it("continues equal timestamps deterministically and searches beyond the first page", () => { const first = sessionHistoryPage(records, { scope: "owner-project", limit: 30 }); const second = sessionHistoryPage(records, { scope: "owner-project", limit: 30, cursor: first.next_cursor! }); const last = sessionHistoryPage(records, { scope: "owner-project", limit: 30, cursor: second.next_cursor! }); expect(first.sessions).toHaveLength(30); expect(last.has_more).toBe(false); expect(new Set([...first.sessions, ...second.sessions, ...last.sessions].map((item) => item.sessionId)).size).toBe(65); expect(sessionHistoryPage(records, { scope: "owner-project", limit: 30, q: "压力" }).sessions[0]?.sessionId).toBe("session-000"); expect(() => sessionHistoryPage(records, { scope: "another-project", limit: 30, cursor: first.next_cursor! })).toThrow(HistoryCursorError); expect(() => sessionHistoryPage(records, { scope: "owner-project", q: "压力", limit: 30, cursor: first.next_cursor! })).toThrow(HistoryCursorError); }); it("pages older messages without truncating the store or moving when messages arrive", () => { const messages = Array.from({ length: 105 }, (_, i) => ({ id: `message-${i}` })); const latest = sessionMessagePage(messages, { scope: "owner-session", limit: 40 }); expect(latest.messages).toEqual(messages.slice(65)); messages.push({ id: "message-105" }); const older = sessionMessagePage(messages, { scope: "owner-session", limit: 40, before: latest.message_page.before_cursor! }); expect(older.messages).toEqual(messages.slice(25, 65)); const oldest = sessionMessagePage(messages, { scope: "owner-session", limit: 40, before: older.message_page.before_cursor! }); expect(oldest.messages).toEqual(messages.slice(0, 25)); expect(oldest.message_page.has_more).toBe(false); expect(messages).toHaveLength(106); expect(() => sessionMessagePage(messages, { scope: "another-session", limit: 40, before: latest.message_page.before_cursor! })).toThrow(HistoryCursorError); messages.splice(0, 1); expect(() => sessionMessagePage(messages, { scope: "owner-session", limit: 40, before: latest.message_page.before_cursor! })).toThrow("history changed"); }); });