109 lines · 4.1 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest"; import {  acknowledgeComposerNativeEvent,  isComposerNativeEcho,  pruneAcknowledgedComposerNativeEvents,  resolveComposerControlledEventCount,} from "./composerEditorRevision"; describe("acknowledgeComposerNativeEvent", () => {  it("advances to newer native text revisions", () => {    expect(acknowledgeComposerNativeEvent(4, 5)).toBe(5);  });   it("accepts a duplicate event from the current native revision", () => {    expect(acknowledgeComposerNativeEvent(5, 5)).toBe(5);  });   it("rejects events older than the latest native text revision", () => {    expect(acknowledgeComposerNativeEvent(5, 4)).toBeNull();  });   it("rejects malformed revision counters", () => {    expect(acknowledgeComposerNativeEvent(5, Number.NaN)).toBeNull();    expect(acknowledgeComposerNativeEvent(5, 5.5)).toBeNull();  });}); describe("isComposerNativeEcho", () => {  const snapshots = [{ eventCount: 3, value: "native", selection: { start: 6, end: 6 } }];   it("matches the exact native text revision and selection", () => {    expect(isComposerNativeEcho("native", { start: 6, end: 6 }, 3, snapshots)).toBe(true);  });   it("does not claim parent-driven selection or repeated-text updates", () => {    expect(isComposerNativeEcho("native", { start: 2, end: 2 }, 3, snapshots)).toBe(false);    expect(isComposerNativeEcho("native", { start: 6, end: 6 }, 4, snapshots)).toBe(false);    expect(isComposerNativeEcho("parent edit", { start: 6, end: 6 }, 3, snapshots)).toBe(false);  });   it("matches value and revision when selection is uncontrolled", () => {    expect(isComposerNativeEcho("native", null, 3, snapshots)).toBe(true);  });}); describe("resolveComposerControlledEventCount", () => {  const snapshots = [    { eventCount: 0, value: "", selection: { start: 0, end: 0 } },    { eventCount: 2, value: "a", selection: { start: 1, end: 1 } },    { eventCount: 4, value: "ab", selection: { start: 2, end: 2 } },  ];   it("tags a delayed parent value with the native revision that produced it", () => {    expect(resolveComposerControlledEventCount("a", { start: 1, end: 1 }, 4, snapshots)).toBe(2);  });   it("does not acknowledge the pre-edit parent value as the latest revision", () => {    expect(resolveComposerControlledEventCount("", { start: 0, end: 0 }, 4, snapshots)).toBe(0);  });   it("acknowledges the latest native value at the latest revision", () => {    expect(resolveComposerControlledEventCount("ab", { start: 2, end: 2 }, 4, snapshots)).toBe(4);  });   it("allows an unmatched parent-driven edit at the latest native revision", () => {    expect(resolveComposerControlledEventCount("/plan ", { start: 6, end: 6 }, 4, snapshots)).toBe(      4,    );  });   it("uses the newest revision when selection events repeat the same value", () => {    expect(      resolveComposerControlledEventCount("ab", { start: 1, end: 1 }, 5, [        ...snapshots,        { eventCount: 5, value: "ab", selection: { start: 1, end: 1 } },      ]),    ).toBe(5);  });   it("keeps a stale selection paired with current text behind the native revision", () => {    expect(resolveComposerControlledEventCount("ab", { start: 1, end: 1 }, 4, snapshots)).toBe(3);  });   it("does not control selection when no selection prop is provided", () => {    expect(resolveComposerControlledEventCount("ab", null, 4, snapshots)).toBe(4);  });}); describe("pruneAcknowledgedComposerNativeEvents", () => {  it("releases an arbitrarily long acknowledged backlog without a fixed-size cliff", () => {    const snapshots = Array.from({ length: 1_000 }, (_, eventCount) => ({      eventCount,      value: `value-${eventCount}`,      selection: { start: eventCount, end: eventCount },    }));     expect(pruneAcknowledgedComposerNativeEvents(snapshots, 999)).toEqual([]);  });   it("retains native events that arrive after the acknowledged render", () => {    const snapshots = [      { eventCount: 40, value: "a", selection: { start: 1, end: 1 } },      { eventCount: 41, value: "ab", selection: { start: 2, end: 2 } },    ];     expect(pruneAcknowledgedComposerNativeEvents(snapshots, 40)).toEqual([snapshots[1]]);  });});