examples/live-notes Public
import assert from "node:assert/strict";import { describe, test } from "node:test";import { insert, type Op } from "../src/ops.ts";import { Room, SNAPSHOT_EVERY } from "../src/room.ts";import { PAGE, listSnapshots, readSnapshot, saveSnapshot, snapshotKey } from "../src/snapshots.ts";import { memoryBucket } from "./helpers/memory-bucket.ts";import { MemoryStore } from "./helpers/memory-store.ts";const send = (base: number, op: Op) => JSON.stringify({ type: "op", base, op });const ID = "a1b2c3";describe("when the room asks for a snapshot", () => { test("every SNAPSHOT_EVERY versions, with the note as it is at that version", () => { const room = new Room(new MemoryStore()); for (let v = 0; v < SNAPSHOT_EVERY - 1; v++) assert.equal(room.receive(send(v, insert(v, "x"))).saveSnapshot, undefined); const due = room.receive(send(SNAPSHOT_EVERY - 1, insert(0, "y"))); assert.deepEqual(due.saveSnapshot, { text: "y" + "x".repeat(SNAPSHOT_EVERY - 1), version: SNAPSHOT_EVERY }); // The reply and the broadcast are the same as for any other edit. assert.deepEqual(due.reply, { type: "ack", version: SNAPSHOT_EVERY }); assert.equal(due.broadcast?.type, "op"); }); test("not again until another SNAPSHOT_EVERY versions after a recorded save", () => { const store = new MemoryStore({ text: "", version: SNAPSHOT_EVERY - 1 }); const room = new Room(store); room.snapshotSaved(room.receive(send(SNAPSHOT_EVERY - 1, insert(0, "a"))).saveSnapshot!.version); assert.equal(store.snapshot, SNAPSHOT_EVERY); assert.equal(room.receive(send(SNAPSHOT_EVERY, insert(0, "b"))).saveSnapshot, undefined); }); test("on the next edit again when a save was never recorded", () => { const room = new Room(new MemoryStore({ text: "", version: SNAPSHOT_EVERY - 1 })); assert.equal(room.receive(send(SNAPSHOT_EVERY - 1, insert(0, "a"))).saveSnapshot?.version, SNAPSHOT_EVERY); assert.equal(room.receive(send(SNAPSHOT_EVERY, insert(0, "b"))).saveSnapshot?.version, SNAPSHOT_EVERY + 1); }); test("never for an edit that changed nothing or was refused", () => { const room = new Room(new MemoryStore({ text: "abc", version: 2 * SNAPSHOT_EVERY })); assert.equal(room.receive(send(2 * SNAPSHOT_EVERY, insert(0, ""))).saveSnapshot, undefined); assert.equal(room.receive(send(2 * SNAPSHOT_EVERY, insert(9, "x"))).saveSnapshot, undefined); }); test("a recorded save survives the room waking from hibernation", () => { const store = new MemoryStore({ text: "", version: SNAPSHOT_EVERY - 1 }); const room = new Room(store); room.snapshotSaved(room.receive(send(SNAPSHOT_EVERY - 1, insert(0, "a"))).saveSnapshot!.version); const woken = new Room(store); assert.equal(woken.receive(send(SNAPSHOT_EVERY, insert(0, "b"))).saveSnapshot, undefined); }); test("an older save never moves the recorded version back", () => { const store = new MemoryStore(); const room = new Room(store); room.snapshotSaved(300); room.snapshotSaved(200); assert.equal(store.snapshot, 300); });});describe("snapshots in R2", () => { test("keys sort in version order", () => { assert.equal(snapshotKey(ID, 100), "snapshots/a1b2c3/000000000100.txt"); assert.ok(snapshotKey(ID, 900) < snapshotKey(ID, 1000)); }); test("saves a note and reads it back by version", async () => { const bucket = memoryBucket(); await saveSnapshot(bucket, ID, { text: "milk\neggs\n", version: 100 }); assert.equal(await readSnapshot(bucket, ID, 100), "milk\neggs\n"); assert.equal(await readSnapshot(bucket, ID, 200), null); assert.equal(await readSnapshot(bucket, "another-note", 100), null); }); test("lists a note's snapshots oldest first, a page at a time", async () => { const bucket = memoryBucket(() => new Date("2026-10-15T09:00:00Z")); for (let v = 1; v <= PAGE + 2; v++) await saveSnapshot(bucket, ID, { text: "é".repeat(v), version: v * SNAPSHOT_EVERY }); await saveSnapshot(bucket, "another-note", { text: "", version: SNAPSHOT_EVERY }); const first = await listSnapshots(bucket, ID); assert.equal(first.snapshots.length, PAGE); assert.deepEqual(first.snapshots[0], { version: SNAPSHOT_EVERY, saved_at: "2026-10-15T09:00:00.000Z", size: 2 }); assert.equal(first.next, PAGE * SNAPSHOT_EVERY); const second = await listSnapshots(bucket, ID, first.next!); assert.deepEqual(second.snapshots.map((s) => s.version), [(PAGE + 1) * SNAPSHOT_EVERY, (PAGE + 2) * SNAPSHOT_EVERY]); assert.equal(second.next, null); });});