import { afterAll, describe, expect, test } from "bun:test"; import { getDb } from "../../../../src/server/db/index.ts"; import { getCursor, setCursor, } from "../../../../src/server/db/queries/cursor.ts"; afterAll(() => { // Clean up cursor row getDb().run("DELETE FROM firehose_cursor WHERE id = 1"); }); describe("firehose cursor", () => { test("getCursor returns null when no cursor is set", () => { getDb().run("DELETE FROM firehose_cursor WHERE id = 1"); expect(getCursor()).toBeNull(); }); test("setCursor stores and getCursor retrieves the value", () => { setCursor(12345); expect(getCursor()).toBe(12345); }); test("setCursor upserts (overwrites previous value)", () => { setCursor(100); expect(getCursor()).toBe(100); setCursor(200); expect(getCursor()).toBe(200); }); }); // With validateEvents off, time_us reaches the subscription's cursor unchecked, and // the subscription assigns it before we ever see the event. We cannot stop the // in-memory jump — refusing to persist it is what keeps the damage to one session // instead of surviving the restart that would otherwise recover. describe("setCursor plausibility", () => { const nowUs = Date.now() * 1000; test.each([ ["far-future", nowUs + 30 * 24 * 60 * 60 * 1_000_000], ["beyond safe-integer range", Number.MAX_SAFE_INTEGER + 2], ["not a number", Number.NaN], ["negative", -1], ["zero", 0], ])("keeps the last good cursor when given a %s value", (_label, bad) => { setCursor(nowUs); setCursor(bad); expect(getCursor()).toBe(nowUs); }); // Jetstream's clock is not ours; a cursor slightly ahead is normal operation. test("allows small clock skew", () => { const skewed = nowUs + 60 * 1_000_000; setCursor(skewed); expect(getCursor()).toBe(skewed); }); });