undo-manager
Version:
Simple undo manager to provide undo and redo actions in JavaScript applications.
265 lines (208 loc) • 5.67 kB
JavaScript
describe('UndoManager Suite', function () {
let undoManager, items;
function addItem(item) {
items.push(item);
}
function removeItem() {
items.pop();
}
function addItemToUndo(item, groupId) {
undoManager.add({
groupId,
undo: function () {
removeItem();
},
redo: function () {
addItem(item);
},
});
}
beforeEach(function () {
// Always start with a clean slate
items = [];
undoManager = new window.UndoManager();
});
it('Create the undo manager', function () {
undoManager = new UndoManager();
expect(undoManager).not.toBe(null);
expect(undoManager.getCommands().length).toBe(0);
expect(undoManager.getIndex()).toBe(-1);
});
it('Adding a command', function () {
let item = 'A';
addItem(item);
addItemToUndo(item);
expect(undoManager.getCommands().length).toBe(1);
expect(undoManager.getIndex()).toBe(0);
expect(undoManager.hasUndo()).toBe(true);
expect(undoManager.hasRedo()).toBe(false);
});
it('Adding a callback', function () {
let callbackCalled = 0;
addItemToUndo('A');
undoManager.setCallback(function () {
callbackCalled++;
});
undoManager.undo();
undoManager.redo();
expect(callbackCalled).toBe(2);
undoManager.setCallback(undefined);
undoManager.undo();
undoManager.redo();
expect(callbackCalled).toBe(2);
});
it('Calling redo', function () {
let item1 = 'A',
item2 = 'B';
addItem(item1);
addItemToUndo(item1);
addItem(item2);
addItemToUndo(item2);
undoManager.undo();
undoManager.redo();
expect(items.length).toBe(2);
expect(undoManager.hasUndo()).toBe(true);
expect(undoManager.getCommands().length).toBe(2);
expect(undoManager.getIndex()).toBe(1);
});
it('Calling redo that is not a function', function () {
let item1 = 'A',
item2 = 'B';
addItem(item1);
undoManager.add({
undo: function () {
removeItem();
},
redo: undefined,
});
addItem(item2);
undoManager.add({
undo: function () {
removeItem();
},
redo: undefined,
});
undoManager.undo();
undoManager.redo();
expect(items.length).toBe(1);
expect(undoManager.hasUndo()).toBe(true);
expect(undoManager.getCommands().length).toBe(2);
expect(undoManager.getIndex()).toBe(1);
});
it('Calling undo without redo', function () {
addItem('A');
addItem('B');
undoManager.add({
undo: function () {
removeItem();
},
redo: undefined,
});
undoManager.undo();
undoManager.undo();
expect(items.length).toBe(1);
expect(undoManager.hasUndo()).toBe(false);
expect(undoManager.getCommands().length).toBe(1);
expect(undoManager.getIndex()).toBe(-1);
});
it('Calling clear', function () {
addItemToUndo('A');
addItemToUndo('B');
undoManager.clear();
expect(undoManager.getCommands().length).toBe(0);
expect(undoManager.getIndex()).toBe(-1);
expect(undoManager.hasUndo()).toBe(false);
expect(undoManager.hasRedo()).toBe(false);
});
it('Calling undo with limit set', function () {
undoManager.setLimit(5);
addItem('1');
addItemToUndo('1');
addItem('2');
addItemToUndo('2');
addItem('3');
addItemToUndo('3');
addItem('4');
addItemToUndo('4');
addItem('5');
addItemToUndo('5');
addItem('6');
addItemToUndo('6');
addItem('7');
addItemToUndo('7');
undoManager.undo();
undoManager.undo();
undoManager.undo();
undoManager.undo();
undoManager.undo();
expect(undoManager.hasUndo()).toBe(false);
expect(undoManager.hasRedo()).toBe(true);
expect(undoManager.getCommands().length).toBe(5);
});
it('Calling undo with limit set to 1', function () {
undoManager.setLimit(1);
let item1 = 'A',
item2 = 'B',
item3 = 'C';
addItem(item1);
addItemToUndo(item1);
addItem(item2);
addItemToUndo(item2);
addItem(item3);
addItemToUndo(item3);
undoManager.undo();
undoManager.undo();
undoManager.undo();
expect(undoManager.hasUndo()).toBe(false);
expect(undoManager.hasRedo()).toBe(true);
expect(undoManager.getCommands().length).toBe(1);
});
it('Calling undo with limit set to 0', function () {
undoManager.setLimit(0);
let item1 = 'A',
item2 = 'B',
item3 = 'C';
addItem(item1);
addItemToUndo(item1);
addItem(item2);
addItemToUndo(item2);
addItem(item3);
addItemToUndo(item3);
undoManager.undo();
undoManager.undo();
expect(undoManager.hasUndo()).toBe(true);
expect(undoManager.hasRedo()).toBe(true);
expect(undoManager.getCommands().length).toBe(3);
});
it('Calling undo/redo/clear with group ID', function () {
let groupId;
addItem('A');
addItemToUndo('A');
addItem('B');
addItemToUndo('B');
groupId = 'CDE';
addItem('C');
addItemToUndo('C', groupId);
addItem('D');
addItemToUndo('D', groupId);
addItem('E');
addItemToUndo('E', groupId);
addItem('F');
addItemToUndo('F');
// Undo
expect(items.length).toBe(6);
undoManager.undo();
expect(items.length).toBe(5);
undoManager.undo();
expect(items.length).toBe(2);
expect(undoManager.getCommands(groupId).length).toBe(3);
// Redo
undoManager.redo();
expect(items.length).toBe(5);
undoManager.redo();
expect(items.length).toBe(6);
// Clear
undoManager.clear();
expect(undoManager.getCommands(groupId).length).toBe(0);
});
});