Files
pdf-tools/src/workspace/workspaceCommands.test.ts

106 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { WorkspaceCommandState } from "./workspaceCommands";
import {
cloneCommandState,
createSnapshotCommand,
reviveWorkspaceCommand,
toWorkspaceCommandRecord,
} from "./workspaceCommands";
function makeState(pageIds: string[]): WorkspaceCommandState {
return {
pages: pageIds.map((id, index) => ({
id,
sourcePageIndex: index,
rotation: index * 90,
})),
selectedPageIds: pageIds.slice(0, 1),
lastSelectedVisualIndex: pageIds.length > 0 ? 0 : null,
};
}
describe("workspaceCommands", () => {
it("clones command state deeply enough for page and selection changes", () => {
const original = makeState(["a", "b"]);
const cloned = cloneCommandState(original);
original.pages[0].rotation = 270;
original.selectedPageIds.push("b");
original.lastSelectedVisualIndex = 1;
expect(cloned).toEqual({
pages: [
{ id: "a", sourcePageIndex: 0, rotation: 0 },
{ id: "b", sourcePageIndex: 1, rotation: 90 },
],
selectedPageIds: ["a"],
lastSelectedVisualIndex: 0,
});
});
it("creates snapshot commands that are stable after source states mutate", () => {
const before = makeState(["a", "b"]);
const after = makeState(["b", "a"]);
after.selectedPageIds = ["b"];
after.lastSelectedVisualIndex = 0;
const command = createSnapshotCommand({
id: "cmd-1",
type: "reorder-pages",
label: "Move page",
timestamp: "2026-05-17T10:00:00.000Z",
before,
after,
details: { moved: 1 },
});
before.pages.length = 0;
after.pages[0].rotation = 180;
after.selectedPageIds.push("a");
expect(command.undo(makeState(["ignored"]))).toEqual({
pages: [
{ id: "a", sourcePageIndex: 0, rotation: 0 },
{ id: "b", sourcePageIndex: 1, rotation: 90 },
],
selectedPageIds: ["a"],
lastSelectedVisualIndex: 0,
});
expect(command.do(makeState(["ignored"]))).toEqual({
pages: [
{ id: "b", sourcePageIndex: 0, rotation: 0 },
{ id: "a", sourcePageIndex: 1, rotation: 90 },
],
selectedPageIds: ["b"],
lastSelectedVisualIndex: 0,
});
});
it("round-trips commands through serializable records", () => {
const before = makeState(["a", "b", "c"]);
const after: WorkspaceCommandState = {
pages: [before.pages[2], before.pages[0], before.pages[1]],
selectedPageIds: ["c"],
lastSelectedVisualIndex: 0,
};
const command = createSnapshotCommand({
id: "cmd-2",
type: "copy-pages",
label: "Copy pages",
timestamp: "2026-05-17T10:05:00.000Z",
before,
after,
});
const record = toWorkspaceCommandRecord(command);
const revived = reviveWorkspaceCommand(record);
expect(record).not.toHaveProperty("do");
expect(record).not.toHaveProperty("undo");
expect(revived.do(before)).toEqual(after);
expect(revived.undo(after)).toEqual(before);
});
});