Rebasely Beta: data may be purged

examples/live-notes Public

TypeScript · 87 lines · 4.1 KiB · at bd4f325

import assert from "node:assert/strict";import { describe, test } from "node:test";import { del, insert, type Op } from "../src/ops.ts";import { LOG_SIZE, MAX_LENGTH, Room } from "../src/room.ts";import { MemoryStore } from "./helpers/memory-store.ts";const send = (base: number, op: Op) => JSON.stringify({ type: "op", base, op });describe("Room", () => {  test("a new note is empty at version 0", () => {    const room = new Room(new MemoryStore());    assert.deepEqual(room.snapshot(), { type: "snapshot", text: "", version: 0 });  });  test("applies an op, acks the sender and broadcasts it to the others", () => {    const store = new MemoryStore();    const room = new Room(store);    const out = room.receive(send(0, insert(0, "milk")));    assert.deepEqual(out.reply, { type: "ack", version: 1 });    assert.deepEqual(out.broadcast, { type: "op", version: 1, op: insert(0, "milk") });    assert.deepEqual(store.note, { text: "milk", version: 1 });  });  test("transforms an op past the ops its sender had not seen", () => {    const room = new Room(new MemoryStore({ text: "milk\n", version: 0 }));    // Two editors at version 0: one adds a line at the top, the other appends.    room.receive(send(0, insert(0, "eggs\n")));    const out = room.receive(send(0, insert(5, "bread\n")));    assert.deepEqual(out.broadcast, { type: "op", version: 2, op: insert(10, "bread\n") });    assert.equal(room.note.text, "eggs\nmilk\nbread\n");  });  test("acks an op that another edit already made pointless without bumping the version", () => {    const room = new Room(new MemoryStore({ text: "milk eggs", version: 0 }));    room.receive(send(0, del(4, 5)));    const out = room.receive(send(0, del(5, 4)));    assert.deepEqual(out, { reply: { type: "ack", version: 1 } });    assert.equal(room.note.text, "milk");  });  test("sends a snapshot to an editor further behind than the log reaches", () => {    const room = new Room(new MemoryStore());    for (let v = 0; v < LOG_SIZE + 1; v++) room.receive(send(v, insert(v, "x")));    const out = room.receive(send(0, insert(0, "late")));    assert.equal(out.reply.type, "snapshot");    assert.equal(out.broadcast, undefined);    // One version less behind is still within the log.    assert.equal(room.receive(send(1, insert(0, "y"))).reply.type, "ack");  });  test("sends a snapshot for a base version from the future", () => {    const room = new Room(new MemoryStore());    assert.deepEqual(room.receive(send(3, insert(0, "x"))).reply, { type: "snapshot", text: "", version: 0 });  });  test("sends a snapshot when an op does not fit the note", () => {    const store = new MemoryStore({ text: "abc", version: 4 });    const room = new Room(store);    assert.equal(room.receive(send(4, del(2, 5))).reply.type, "snapshot");    assert.deepEqual(store.note, { text: "abc", version: 4 });  });  test("refuses an op that would make the note too long", () => {    const store = new MemoryStore({ text: "x".repeat(MAX_LENGTH - 2), version: 7 });    const room = new Room(store);    assert.equal(room.receive(send(7, insert(0, "ab"))).reply.type, "ack");    const out = room.receive(send(8, insert(0, "c")));    assert.deepEqual(out.reply, { type: "snapshot", text: "ab" + "x".repeat(MAX_LENGTH - 2), version: 8, reason: "notes are limited to 100,000 characters" });    assert.equal(out.broadcast, undefined);    assert.equal(store.note.version, 8);  });  test("answers a malformed frame with an error", () => {    const room = new Room(new MemoryStore());    assert.equal(room.receive("{").reply.type, "error");    assert.equal(room.receive(JSON.stringify({ type: "op", base: 0, op: { type: "upsert", pos: 0 } })).reply.type, "error");  });  test("picks up where it left off from the store", () => {    const store = new MemoryStore();    new Room(store).receive(send(0, insert(0, "kept")));    // A Durable Object woken from hibernation builds a new Room over the same storage.    const woken = new Room(store);    assert.deepEqual(woken.note, { text: "kept", version: 1 });    assert.deepEqual(woken.receive(send(1, insert(0, "> "))).broadcast, { type: "op", version: 2, op: insert(0, "> ") });  });});