| <!DOCTYPE html> | 
| <html> | 
| <head> | 
|   <link rel='stylesheet' href='qunit/qunit.css' type='text/css'/> | 
|   <script src='../editor/lib/jquery.js'></script> | 
|   <script type='text/javascript' src='../editor/src/history.js'></script> | 
|   <script type='text/javascript' src='qunit/qunit.js'></script>   | 
|   <script type='text/javascript'> | 
|   $(function() { | 
|     // TODO(codedread): Write tests for handling history events. | 
|   | 
|     // Mocked out methods. | 
|     svgedit.transformlist = {}; | 
|     svgedit.transformlist.removeElementFromListMap = function(elem) {}; | 
|     svgedit.utilities = {}; | 
|     svgedit.utilities.getHref = function(elem) { return '#foo'; }; | 
|     svgedit.utilities.setHref = function(elem, val) {}; | 
|     svgedit.utilities.getRotationAngle = function(elem) { return 0; }; | 
|   | 
|       // log function | 
|       QUnit.log = function(result, message) { | 
|         if (window.console && window.console.log) { | 
|             window.console.log(result +' :: '+ message); | 
|         } | 
|     }; | 
|   | 
|     var svgns = 'http://www.w3.org/2000/svg'; | 
|     var svg = document.createElementNS(svgns, 'svg'); | 
|     var undoMgr = null; | 
|     var divparent = document.getElementById('divparent'); | 
|     var div1 = document.getElementById('div1'); | 
|     var div2 = document.getElementById('div2'); | 
|     var div3 = document.getElementById('div3'); | 
|     var div4 = document.getElementById('div4'); | 
|     var div5 = document.getElementById('div5'); | 
|   | 
|     module('svgedit.history'); | 
|   | 
|     var MockCommand = function(opt_text) { this.text_ = opt_text; }; | 
|     MockCommand.prototype.apply = function() {}; | 
|     MockCommand.prototype.unapply = function() {}; | 
|     MockCommand.prototype.getText = function() { return this.text_; }; | 
|     MockCommand.prototype.elements = function() { return []; }; | 
|   | 
|     var MockHistoryEventHandler = function() {}; | 
|     MockHistoryEventHandler.prototype.handleHistoryEvent = function(eventType, command) {}; | 
|   | 
|     function setUp() { | 
|         undoMgr = new svgedit.history.UndoManager(); | 
|     } | 
|     function tearDown() { | 
|         undoMgr = null; | 
|     } | 
|   | 
|     test('Test svgedit.history package', function() { | 
|         expect(13); | 
|          | 
|         ok(svgedit.history); | 
|         ok(svgedit.history.MoveElementCommand); | 
|         ok(svgedit.history.InsertElementCommand); | 
|         ok(svgedit.history.ChangeElementCommand); | 
|         ok(svgedit.history.RemoveElementCommand); | 
|         ok(svgedit.history.BatchCommand); | 
|         ok(svgedit.history.UndoManager); | 
|         equals(typeof svgedit.history.MoveElementCommand, typeof function(){}); | 
|         equals(typeof svgedit.history.InsertElementCommand, typeof function(){}); | 
|         equals(typeof svgedit.history.ChangeElementCommand, typeof function(){}); | 
|         equals(typeof svgedit.history.RemoveElementCommand, typeof function(){}); | 
|         equals(typeof svgedit.history.BatchCommand, typeof function(){}); | 
|         equals(typeof svgedit.history.UndoManager, typeof function(){}); | 
|     }); | 
|      | 
|     test('Test UndoManager methods', function() { | 
|         expect(14); | 
|         setUp(); | 
|          | 
|         ok(undoMgr); | 
|         ok(undoMgr.addCommandToHistory); | 
|         ok(undoMgr.getUndoStackSize); | 
|         ok(undoMgr.getRedoStackSize); | 
|         ok(undoMgr.resetUndoStack); | 
|         ok(undoMgr.getNextUndoCommandText); | 
|         ok(undoMgr.getNextRedoCommandText); | 
|   | 
|         equals(typeof undoMgr, typeof {}); | 
|         equals(typeof undoMgr.addCommandToHistory, typeof function(){}); | 
|         equals(typeof undoMgr.getUndoStackSize, typeof function(){}); | 
|         equals(typeof undoMgr.getRedoStackSize, typeof function(){}); | 
|         equals(typeof undoMgr.resetUndoStack, typeof function(){}); | 
|         equals(typeof undoMgr.getNextUndoCommandText, typeof function(){}); | 
|         equals(typeof undoMgr.getNextRedoCommandText, typeof function(){}); | 
|              | 
|         tearDown(); | 
|     }); | 
|      | 
|     test('Test UndoManager.addCommandToHistory() function', function() { | 
|         expect(3); | 
|          | 
|         setUp(); | 
|   | 
|         equals(undoMgr.getUndoStackSize(), 0); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         equals(undoMgr.getUndoStackSize(), 1); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         equals(undoMgr.getUndoStackSize(), 2); | 
|   | 
|         tearDown(); | 
|     }); | 
|      | 
|     test('Test UndoManager.getUndoStackSize() and getRedoStackSize() functions', function() { | 
|         expect(18); | 
|          | 
|         setUp(); | 
|   | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|   | 
|         equals(undoMgr.getUndoStackSize(), 3); | 
|         equals(undoMgr.getRedoStackSize(), 0); | 
|          | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getUndoStackSize(), 2); | 
|         equals(undoMgr.getRedoStackSize(), 1); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getUndoStackSize(), 1); | 
|         equals(undoMgr.getRedoStackSize(), 2); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getUndoStackSize(), 0); | 
|         equals(undoMgr.getRedoStackSize(), 3); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getUndoStackSize(), 0); | 
|         equals(undoMgr.getRedoStackSize(), 3); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getUndoStackSize(), 1); | 
|         equals(undoMgr.getRedoStackSize(), 2); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getUndoStackSize(), 2); | 
|         equals(undoMgr.getRedoStackSize(), 1); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getUndoStackSize(), 3); | 
|         equals(undoMgr.getRedoStackSize(), 0); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getUndoStackSize(), 3); | 
|         equals(undoMgr.getRedoStackSize(), 0); | 
|          | 
|         tearDown(); | 
|     }); | 
|      | 
|     test('Test UndoManager.resetUndoStackSize() function', function() { | 
|         expect(4); | 
|          | 
|         setUp(); | 
|   | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         undoMgr.addCommandToHistory(new MockCommand()); | 
|         undoMgr.undo(); | 
|          | 
|         equals(undoMgr.getUndoStackSize(), 2); | 
|         equals(undoMgr.getRedoStackSize(), 1); | 
|          | 
|         undoMgr.resetUndoStack(); | 
|   | 
|         equals(undoMgr.getUndoStackSize(), 0); | 
|         equals(undoMgr.getRedoStackSize(), 0); | 
|          | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test UndoManager.getNextUndoCommandText() function', function() { | 
|         expect(9); | 
|   | 
|         setUp(); | 
|   | 
|         equals(undoMgr.getNextUndoCommandText(), ''); | 
|   | 
|         undoMgr.addCommandToHistory(new MockCommand('First')); | 
|         undoMgr.addCommandToHistory(new MockCommand('Second')); | 
|         undoMgr.addCommandToHistory(new MockCommand('Third')); | 
|   | 
|         equals(undoMgr.getNextUndoCommandText(), 'Third'); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'Second'); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'First'); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextUndoCommandText(), ''); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'First'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'Second'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'Third'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextUndoCommandText(), 'Third'); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test UndoManager.getNextRedoCommandText() function', function() { | 
|         expect(8); | 
|   | 
|         setUp(); | 
|   | 
|         equals(undoMgr.getNextRedoCommandText(), ''); | 
|   | 
|         undoMgr.addCommandToHistory(new MockCommand('First')); | 
|         undoMgr.addCommandToHistory(new MockCommand('Second')); | 
|         undoMgr.addCommandToHistory(new MockCommand('Third')); | 
|   | 
|         equals(undoMgr.getNextRedoCommandText(), ''); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextRedoCommandText(), 'Third'); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextRedoCommandText(), 'Second'); | 
|   | 
|         undoMgr.undo(); | 
|         equals(undoMgr.getNextRedoCommandText(), 'First'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextRedoCommandText(), 'Second'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextRedoCommandText(), 'Third'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(undoMgr.getNextRedoCommandText(), ''); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test UndoManager.undo() and redo() functions', function() { | 
|         expect(10); | 
|   | 
|         setUp(); | 
|   | 
|         var lastCalled = null; | 
|         var cmd1 = new MockCommand(); | 
|         var cmd2 = new MockCommand(); | 
|         var cmd3 = new MockCommand(); | 
|         cmd1.apply = function() { lastCalled = 'cmd1.apply'; }; | 
|         cmd2.apply = function() { lastCalled = 'cmd2.apply'; }; | 
|         cmd3.apply = function() { lastCalled = 'cmd3.apply'; }; | 
|         cmd1.unapply = function() { lastCalled = 'cmd1.unapply'; }; | 
|         cmd2.unapply = function() { lastCalled = 'cmd2.unapply'; }; | 
|         cmd3.unapply = function() { lastCalled = 'cmd3.unapply'; }; | 
|   | 
|         undoMgr.addCommandToHistory(cmd1); | 
|         undoMgr.addCommandToHistory(cmd2); | 
|         undoMgr.addCommandToHistory(cmd3); | 
|   | 
|         ok(!lastCalled); | 
|   | 
|         undoMgr.undo(); | 
|         equals(lastCalled, 'cmd3.unapply'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(lastCalled, 'cmd3.apply'); | 
|   | 
|         undoMgr.undo(); | 
|         undoMgr.undo(); | 
|         equals(lastCalled, 'cmd2.unapply'); | 
|          | 
|         undoMgr.undo(); | 
|         equals(lastCalled, 'cmd1.unapply'); | 
|         lastCalled = null; | 
|   | 
|         undoMgr.undo(); | 
|         ok(!lastCalled); | 
|   | 
|         undoMgr.redo(); | 
|         equals(lastCalled, 'cmd1.apply'); | 
|          | 
|         undoMgr.redo(); | 
|         equals(lastCalled, 'cmd2.apply'); | 
|   | 
|         undoMgr.redo(); | 
|         equals(lastCalled, 'cmd3.apply'); | 
|         lastCalled = null; | 
|   | 
|         undoMgr.redo(); | 
|         ok(!lastCalled); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test MoveElementCommand', function() { | 
|         expect(26); | 
|   | 
|         setUp(); | 
|   | 
|         var move = new svgedit.history.MoveElementCommand(div3, div1, divparent); | 
|         ok(move.unapply); | 
|         ok(move.apply); | 
|         equals(typeof move.unapply, typeof function(){}); | 
|         equals(typeof move.apply, typeof function(){}); | 
|   | 
|         move.unapply(); | 
|         equals(divparent.firstElementChild, div3); | 
|         equals(divparent.firstElementChild.nextElementSibling, div1); | 
|         equals(divparent.lastElementChild, div2); | 
|   | 
|         move.apply(); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(divparent.firstElementChild.nextElementSibling, div2); | 
|         equals(divparent.lastElementChild, div3); | 
|   | 
|         move = new svgedit.history.MoveElementCommand(div1, null, divparent); | 
|   | 
|         move.unapply(); | 
|         equals(divparent.firstElementChild, div2); | 
|         equals(divparent.firstElementChild.nextElementSibling, div3); | 
|         equals(divparent.lastElementChild, div1); | 
|   | 
|         move.apply(); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(divparent.firstElementChild.nextElementSibling, div2); | 
|         equals(divparent.lastElementChild, div3); | 
|   | 
|         move = new svgedit.history.MoveElementCommand(div2, div5, div4); | 
|   | 
|         move.unapply(); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(divparent.firstElementChild.nextElementSibling, div3); | 
|         equals(divparent.lastElementChild, div3); | 
|         equals(div4.firstElementChild, div2); | 
|         equals(div4.firstElementChild.nextElementSibling, div5); | 
|   | 
|         move.apply(); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(divparent.firstElementChild.nextElementSibling, div2); | 
|         equals(divparent.lastElementChild, div3); | 
|         equals(div4.firstElementChild, div5); | 
|         equals(div4.lastElementChild, div5); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test InsertElementCommand', function() { | 
|         expect(20); | 
|   | 
|         setUp(); | 
|   | 
|         var insert = new svgedit.history.InsertElementCommand(div3); | 
|         ok(insert.unapply); | 
|         ok(insert.apply); | 
|         equals(typeof insert.unapply, typeof function(){}); | 
|         equals(typeof insert.apply, typeof function(){}); | 
|   | 
|         insert.unapply(); | 
|         equals(divparent.childElementCount, 2); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(divparent.lastElementChild, div2); | 
|   | 
|         insert.apply(); | 
|         equals(divparent.childElementCount, 3); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|   | 
|         insert = new svgedit.history.InsertElementCommand(div2); | 
|   | 
|         insert.unapply(); | 
|         equals(divparent.childElementCount, 2); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div3); | 
|         equals(divparent.lastElementChild, div3); | 
|   | 
|         insert.apply(); | 
|         equals(divparent.childElementCount, 3); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test RemoveElementCommand', function() { | 
|         expect(22); | 
|   | 
|         setUp(); | 
|   | 
|         var div6 = document.createElement('div'); | 
|         div6.id = 'div6'; | 
|   | 
|         var remove = new svgedit.history.RemoveElementCommand(div6, null, divparent); | 
|         ok(remove.unapply); | 
|         ok(remove.apply); | 
|         equals(typeof remove.unapply, typeof function(){}); | 
|         equals(typeof remove.apply, typeof function(){}); | 
|   | 
|         remove.unapply(); | 
|         equals(divparent.childElementCount, 4); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|         equals(div3.nextElementSibling, div6); | 
|   | 
|         remove.apply(); | 
|         equals(divparent.childElementCount, 3); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|   | 
|         remove = new svgedit.history.RemoveElementCommand(div6, div2, divparent); | 
|   | 
|         remove.unapply(); | 
|         equals(divparent.childElementCount, 4); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div6); | 
|         equals(div6.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|   | 
|         remove.apply(); | 
|         equals(divparent.childElementCount, 3); | 
|         equals(divparent.firstElementChild, div1); | 
|         equals(div1.nextElementSibling, div2); | 
|         equals(div2.nextElementSibling, div3); | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test ChangeElementCommand', function() { | 
|         expect(26); | 
|   | 
|         setUp(); | 
|   | 
|         div1.setAttribute('title', 'new title'); | 
|         var change = new svgedit.history.ChangeElementCommand(div1, | 
|             {'title': 'old title', 'class': 'foo'}); | 
|         ok(change.unapply); | 
|         ok(change.apply); | 
|         equals(typeof change.unapply, typeof function(){}); | 
|         equals(typeof change.apply, typeof function(){}); | 
|   | 
|         change.unapply(); | 
|         equals(div1.getAttribute('title'), 'old title'); | 
|         equals(div1.getAttribute('class'), 'foo'); | 
|   | 
|         change.apply(); | 
|         equals(div1.getAttribute('title'), 'new title'); | 
|         ok(!div1.getAttribute('class')); | 
|   | 
|         div1.textContent = 'inner text'; | 
|         change = new svgedit.history.ChangeElementCommand(div1, | 
|             {'#text': null}); | 
|   | 
|         change.unapply(); | 
|         ok(!div1.textContent); | 
|   | 
|         change.apply(); | 
|         equals(div1.textContent, 'inner text'); | 
|   | 
|         div1.textContent = ''; | 
|         change = new svgedit.history.ChangeElementCommand(div1, | 
|             {'#text': 'old text'}); | 
|   | 
|         change.unapply(); | 
|         equals(div1.textContent, 'old text'); | 
|   | 
|         change.apply(); | 
|         ok(!div1.textContent); | 
|   | 
|         // TODO(codedread): Refactor this #href stuff in history.js and svgcanvas.js | 
|         var rect = document.createElementNS(svgns, 'rect'); | 
|         var justCalled = null; | 
|         var gethrefvalue = null; | 
|         var sethrefvalue = null; | 
|         svgedit.utilities.getHref = function(elem) { | 
|             equals(elem, rect); | 
|             justCalled = 'getHref'; | 
|             return gethrefvalue; | 
|         }; | 
|         svgedit.utilities.setHref = function(elem, val) { | 
|             equals(elem, rect); | 
|             equals(val, sethrefvalue); | 
|             justCalled = 'setHref'; | 
|         }; | 
|   | 
|         gethrefvalue = '#newhref'; | 
|         change = new svgedit.history.ChangeElementCommand(rect, | 
|             {'#href': '#oldhref'}); | 
|         equals(justCalled, 'getHref'); | 
|   | 
|         justCalled = null; | 
|         sethrefvalue = '#oldhref'; | 
|         change.unapply(); | 
|         equals(justCalled, 'setHref'); | 
|   | 
|         justCalled = null; | 
|         sethrefvalue = '#newhref'; | 
|         change.apply(); | 
|         equals(justCalled, 'setHref'); | 
|   | 
|         var line = document.createElementNS(svgns,'line'); | 
|         line.setAttributeNS(null, 'class', 'newClass'); | 
|         change = new svgedit.history.ChangeElementCommand(line,{class:'oldClass'}); | 
|          | 
|         ok(change.unapply); | 
|         ok(change.apply); | 
|         equals(typeof change.unapply, typeof function(){}); | 
|         equals(typeof change.apply, typeof function(){}); | 
|   | 
|         change.unapply(); | 
|         equals(line.getAttributeNS(null, 'class'), 'oldClass'); | 
|   | 
|         change.apply(); | 
|         equals(line.getAttributeNS(null, 'class'), 'newClass'); | 
|          | 
|         tearDown(); | 
|     }); | 
|   | 
|     test('Test BatchCommand', function() { | 
|         expect(13); | 
|   | 
|         setUp(); | 
|   | 
|         var concatResult = ''; | 
|         MockCommand.prototype.apply = function() { concatResult += this.text_; }; | 
|   | 
|         var batch = new svgedit.history.BatchCommand(); | 
|         ok(batch.unapply); | 
|         ok(batch.apply); | 
|         ok(batch.addSubCommand); | 
|         ok(batch.isEmpty); | 
|         equals(typeof batch.unapply, typeof function(){}); | 
|         equals(typeof batch.apply, typeof function(){}); | 
|         equals(typeof batch.addSubCommand, typeof function(){}); | 
|         equals(typeof batch.isEmpty, typeof function(){}); | 
|   | 
|         ok(batch.isEmpty()); | 
|   | 
|         batch.addSubCommand(new MockCommand('a')); | 
|         ok(!batch.isEmpty()); | 
|         batch.addSubCommand(new MockCommand('b')); | 
|         batch.addSubCommand(new MockCommand('c')); | 
|   | 
|         ok(!concatResult); | 
|         batch.apply(); | 
|         equals(concatResult, 'abc'); | 
|   | 
|         MockCommand.prototype.apply = function() {}; | 
|         MockCommand.prototype.unapply = function() { concatResult += this.text_; }; | 
|         concatResult = ''; | 
|         batch.unapply(); | 
|         equals(concatResult, 'cba'); | 
|   | 
|         MockCommand.prototype.unapply = function() {}; | 
|   | 
|         tearDown(); | 
|     }); | 
|   | 
|   | 
|   }); | 
|   </script> | 
| </head>   | 
| <body>   | 
|   <h1 id='qunit-header'>Unit Tests for history.js</h1> | 
|   <h2 id='qunit-banner'></h2> | 
|   <h2 id='qunit-userAgent'></h2> | 
|   <ol id='qunit-tests'> | 
|   </ol> | 
|   <div id='divparent' style='visibility:hidden'> | 
|     <div id='div1'></div> | 
|     <div id='div2'></div> | 
|     <div id='div3'></div> | 
|   </div> | 
|   <div id='div4' style='visibility:hidden'> | 
|     <div id='div5'></div> | 
|   </div> | 
|   | 
| </body>   | 
| </html> |