106 lines
3.0 KiB
TypeScript
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);
|
|
});
|
|
});
|