Files
svg-tools/tests/commands/history.test.ts
T

80 lines
2.2 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { CommandHistory, createTransaction } from "../../src/commands/history";
describe("source transaction history", () => {
it("undoes and redoes exact source without normalization", () => {
const history = new CommandHistory();
const transaction = createTransaction({
label: "Set fill",
baseRevision: 1,
sourceBefore: "<svg><path/></svg>\r\n",
sourceAfter: '<svg><path fill="red"/></svg>\r\n',
});
history.commit(transaction);
expect(history.undo(transaction.sourceAfter)?.sourceBefore).toBe(
transaction.sourceBefore,
);
expect(history.redo(transaction.sourceBefore)?.sourceAfter).toBe(
transaction.sourceAfter,
);
});
it("coalesces rapid source-editor transactions with a shared merge key", () => {
vi.spyOn(Date, "now").mockReturnValueOnce(100).mockReturnValueOnce(200);
const history = new CommandHistory();
history.commit(
createTransaction({
label: "Type",
baseRevision: 0,
sourceBefore: "a",
sourceAfter: "ab",
mergeKey: "typing",
}),
);
history.commit(
createTransaction({
label: "Type",
baseRevision: 1,
sourceBefore: "ab",
sourceAfter: "abc",
mergeKey: "typing",
}),
);
expect(history.snapshot.past).toHaveLength(1);
expect(history.snapshot.past[0]).toMatchObject({
sourceBefore: "a",
sourceAfter: "abc",
});
});
it("rejects stale undo and bounds history", () => {
const history = new CommandHistory(2, 10_000);
history.commit(
createTransaction({
label: "one",
baseRevision: 0,
sourceBefore: "a",
sourceAfter: "b",
}),
);
expect(() => history.undo("not-b")).toThrow(/stale/u);
history.commit(
createTransaction({
label: "two",
baseRevision: 1,
sourceBefore: "b",
sourceAfter: "c",
}),
);
history.commit(
createTransaction({
label: "three",
baseRevision: 2,
sourceBefore: "c",
sourceAfter: "d",
}),
);
expect(history.snapshot.past).toHaveLength(2);
});
});