1 // ========================================================================== 2 // SC.UndoManager Unit Test 3 // ========================================================================== 4 /*globals SC */ 5 6 module("SC.UndoManager"); 7 8 test("simple undo case", function () { 9 var undoManager = SC.UndoManager.create(), 10 obj = SC.Object.create({ 11 undoManager: undoManager, 12 13 value: null, 14 15 actionName: 0, 16 17 _undoAction: function(value) { 18 this.set('value', value); 19 }, 20 21 valDidChange: function() { 22 var that = this, 23 value = this._value; 24 25 undoManager.registerUndoAction(this, this._undoAction, value, this.actionName); 26 27 this._value = this.get('value'); 28 }.observes('value') 29 }); 30 31 obj.actionName = 'group1'; 32 obj.set('value', 'a'); 33 ok(undoManager.get('canUndo'), "We should be able to undo"); 34 equals(undoManager.get('undoActionName'), 'group1', "The name of the undo stack should be 'group1'"); 35 36 obj.actionName = 'group2'; 37 obj.set('value', 'ab'); 38 39 obj.actionName = 'group3'; 40 obj.set('value', 'abc'); 41 equals(undoManager.get('undoActionName'), 'group3', "The name of the undo stack should be 'group3'"); 42 43 undoManager.undo(); 44 equals(obj.get('value'), 'ab', "val should be 'ab'"); 45 ok(undoManager.get('canRedo'), "We should be able to redo"); 46 equals(undoManager.get('undoActionName'), 'group2', "The name of the undo stack should be 'group2'"); 47 equals(undoManager.get('redoActionName'), 'group3', "The name of the redo stack should be 'group3'"); 48 49 undoManager.undo(); 50 equals(obj.get('value'), 'a', "val should be 'a'"); 51 equals(undoManager.get('undoActionName'), 'group1', "The name of the undo stack should be 'group1'"); 52 equals(undoManager.get('redoActionName'), 'group2', "The name of the redo stack should be 'group2'"); 53 54 undoManager.redo(); 55 equals(obj.get('value'), 'ab', "val should be 'ab'"); 56 equals(undoManager.get('undoActionName'), 'group2', "The name of the undo stack should be 'group2'"); 57 equals(undoManager.get('redoActionName'), 'group3', "The name of the redo stack should be 'group3'"); 58 59 undoManager.undo(); 60 equals(obj.get('value'), 'a', "val should be 'a'"); 61 62 undoManager.undo(); 63 equals(obj.get('value'), null, "val should be 'null'"); 64 ok(!undoManager.get('canUndo'), "We shouldn't be able to undo"); 65 equals(undoManager.get('undoActionName'), null, "The name of the undo stack should be 'null'"); 66 67 undoManager.redo(); 68 equals(obj.get('value'), 'a', "val should be 'a'"); 69 70 undoManager.redo(); 71 equals(obj.get('value'), 'ab', "val should be 'ab'"); 72 73 undoManager.redo(); 74 equals(obj.get('value'), 'abc', "val should be 'abc'"); 75 ok(!undoManager.get('canRedo'), "We shouldn't be able to redo"); 76 77 undoManager.undo(); 78 undoManager.undo(); 79 equals(obj.get('value'), 'a', "val should be 'a'"); 80 81 obj.set('value', 'ad'); 82 ok(!undoManager.get('canRedo'), "We shouldn't be able to redo"); 83 84 undoManager.undo(); 85 ok(undoManager.get('canUndo'), "We should be able to undo"); 86 ok(undoManager.get('canRedo'), "We should be able to redo"); 87 88 undoManager.reset(); 89 90 ok(!undoManager.get('canUndo'), "We shouldn't be able to undo"); 91 ok(!undoManager.get('canRedo'), "We shouldn't be able to redo"); 92 }); 93 94 95 test("grouped undo case", function () { 96 var undoManager = SC.UndoManager.create(), 97 obj = SC.Object.create({ 98 undoManager: undoManager, 99 100 value: null, 101 102 actionName: 0, 103 104 _undoAction: function(value) { 105 this.set('value', value) 106 }, 107 108 valDidChange: function() { 109 var value = this._value, 110 actionName = this.actionName; 111 112 if (actionName === this._actionName) { 113 undoManager.registerGroupedUndoAction(this, this._undoAction, value); 114 } 115 else { 116 undoManager.registerUndoAction(this, this._undoAction, value, actionName); 117 } 118 119 this._value = this.get('value'); 120 this._actionName = actionName; 121 }.observes('value') 122 }); 123 124 obj.actionName = 'group1'; 125 obj.set('value', 'a'); 126 ok(undoManager.get('canUndo'), "We should be able to undo"); 127 equals(undoManager.get('undoActionName'), 'group1', "The name of the undo stack should be 'group1'"); 128 129 obj.actionName = 'group2'; 130 obj.set('value', 'ab'); 131 obj.set('value', 'abc'); 132 equals(undoManager.get('undoActionName'), 'group2', "The name of the undo stack should be 'group2'"); 133 134 obj.actionName = 'group3'; 135 obj.set('value', 'abcd'); 136 137 undoManager.undo(); 138 equals(obj.get('value'), 'abc', "val should be 'abc'"); 139 ok(undoManager.get('canRedo'), "We should be able to redo"); 140 equals(undoManager.get('undoActionName'), 'group2', "The name of the undo stack should be 'group2'"); 141 equals(undoManager.get('redoActionName'), 'group3', "The name of the redo stack should be 'group3'"); 142 143 undoManager.undo(); 144 equals(obj.get('value'), 'a', "val should be 'a'"); 145 146 undoManager.redo(); 147 equals(obj.get('value'), 'abc', "val should be 'abc'"); 148 149 undoManager.undo(); 150 equals(obj.get('value'), 'a', "val should be 'a'"); 151 152 undoManager.undo(); 153 equals(obj.get('value'), null, "val should be 'null'"); 154 ok(!undoManager.get('canUndo'), "We shouldn't be able to undo"); 155 156 undoManager.redo(); 157 equals(obj.get('value'), 'a', "val should be 'a'"); 158 159 undoManager.redo(); 160 equals(obj.get('value'), 'abc', "val should be 'abc'"); 161 162 undoManager.redo(); 163 equals(obj.get('value'), 'abcd', "val should be 'abcd'"); 164 ok(!undoManager.get('canRedo'), "We shouldn't be able to redo"); 165 166 undoManager.redo(); 167 }); 168 169 test("set action name", function () { 170 var undoManager = SC.UndoManager.create(); 171 172 undoManager.setActionName('group1'); 173 undoManager.registerUndoAction(); 174 175 equals(undoManager.get('undoActionName'), null, "The name of the undo stack should be null"); 176 177 undoManager.setActionName('group1'); 178 179 equals(undoManager.get('undoActionName'), 'group1', "The name of the undo stack should be 'group1'"); 180 }); 181 182 test("restrict number of groups", function () { 183 var undoManager = SC.UndoManager.create({ 184 maxStackLength: 2 185 }), 186 obj = SC.Object.create({ 187 undoManager: undoManager, 188 value: 0, 189 _undoAction: function(value) { 190 this.set('value', value); 191 }, 192 valDidChange: function() { 193 var value = this.get('value') - 1; 194 undoManager.registerUndoAction(this, this._undoAction, value); 195 }.observes('value') 196 }), 197 computeStackLength = function(stack) { 198 var length = 1; 199 while(stack = stack.prev) { 200 length++; 201 } 202 return length; 203 }, 204 length; 205 206 obj.incrementProperty('value'); 207 obj.incrementProperty('value'); 208 obj.incrementProperty('value'); 209 obj.incrementProperty('value'); 210 obj.incrementProperty('value'); 211 212 equals(obj.get('value'), 5, "value should be 5"); 213 214 length = computeStackLength(undoManager.undoStack); 215 equals(length, 3, "The undo stack length should be 3"); 216 217 undoManager.endUndoGroup(); 218 219 length = computeStackLength(undoManager.undoStack); 220 equals(length, 2, "The undo stack length should be 2"); 221 222 undoManager.undo(); 223 undoManager.undo(); 224 225 ok(!undoManager.get('canUndo'), "We shouldn't be able to undo"); 226 227 length = computeStackLength(undoManager.redoStack); 228 equals(length, 2, "The redo stack length should be 2"); 229 }); 230 231 232