var assert = require("assert") var UndoStack = require("./undo.js") UndoStack.debug = false describe('undo', function(){ var state = "zero" describe('#register()', function(){ UndoStack.register({ type: "demo", undo: function(myState){ state = myState }, redo: function(myState){ state = myState }, }) it('registers undoable actions', function(){ assert( UndoStack.types.hasOwnProperty("demo") ) }) }) describe('#push()', function(){ it('starts empty', function(){ assert.equal(0, UndoStack.stack.length) assert.equal(-1, UndoStack.pointer) }) it('pushes some actions', function(){ UndoStack.push({ type: "demo", undo: state, redo: "one" }) state = "one" UndoStack.push({ type: "demo", undo: state, redo: "two" }) state = "two" UndoStack.push({ type: "demo", undo: state, redo: "three" }) state = "three" assert.equal(3, UndoStack.stack.length) assert.equal(2, UndoStack.pointer) }) }) describe('#undo()', function(){ it('retrieves old state', function(){ assert.equal("three", state) UndoStack.undo() assert.equal("two", state) assert.equal(1, UndoStack.pointer) }) it('can only undo so far', function(){ var canUndo canUndo = UndoStack.undo() assert.equal("one", state) assert.equal(0, UndoStack.pointer) assert.equal(true, canUndo) canUndo = UndoStack.undo() assert.equal("zero", state) assert.equal(-1, UndoStack.pointer) assert.equal(false, canUndo) canUndo = UndoStack.undo() assert.equal("zero", state) assert.equal(-1, UndoStack.pointer) assert.equal(false, canUndo) }) }) describe('#redo()', function(){ it('reassigns new state', function(){ UndoStack.redo() assert.equal("one", state) }) it('can only redo so far', function(){ var canRedo canRedo = UndoStack.redo() assert.equal("two", state) assert.equal(true, canRedo) canRedo = UndoStack.redo() assert.equal("three", state) assert.equal(false, canRedo) canRedo = UndoStack.redo() assert.equal("three", state) assert.equal(false, canRedo) }) it('clobbers old state if we undo then do something else', function(){ UndoStack.undo() assert.equal("two", state) assert.equal(1, UndoStack.pointer) UndoStack.undo() assert.equal("one", state) assert.equal(0, UndoStack.pointer) assert.equal(3, UndoStack.stack.length) UndoStack.push({ type: "demo", undo: state, redo: "four" }) state = "four" assert.equal(1, UndoStack.pointer) assert.equal(2, UndoStack.stack.length) UndoStack.undo() assert.equal("one", state) assert.equal(0, UndoStack.pointer) assert.equal(2, UndoStack.stack.length) UndoStack.redo() assert.equal("four", state) assert.equal(1, UndoStack.pointer) assert.equal(2, UndoStack.stack.length) }) }) }) // 1) push action // 2) push action // 3) push action // undo 3 // undo 2 // undo 1 // undo * can't undo anymore // redo 1 // redo 2 // redo 3 // redo * can't redo anymore // undo 3 // 4) push action (clobbers action 3) // undo 4 // undo 2 // redo 2 // redo 4