svgedit/cypress/integration/unit/history.js

521 lines
17 KiB
JavaScript

import { NS } from '../../../instrumented/svgcanvas/namespaces.js'
import * as utilities from '../../../instrumented/svgcanvas/utilities.js'
import * as history from '../../../instrumented/svgcanvas/history.js'
describe('history', function () {
// TODO(codedread): Write tests for handling history events.
utilities.mock({
getHref () { return '#foo' },
setHref () { /* empty fn */ },
getRotationAngle () { return 0 }
})
// const svg = document.createElementNS(NS.SVG, 'svg');
let undoMgr = null
class MockCommand extends history.Command {
constructor (optText) {
super()
this.text = optText
}
apply (handler) {
super.apply(handler, () => { /* empty fn */ })
}
unapply (handler) {
super.unapply(handler, () => { /* empty fn */ })
}
elements () { return [] }
}
/*
class MockHistoryEventHandler {
handleHistoryEvent (eventType, command) {}
}
*/
/**
* Set up tests (with undo manager).
* @returns {void}
*/
beforeEach(function () {
undoMgr = new history.UndoManager()
document.body.textContent = ''
this.divparent = document.createElement('div')
this.divparent.id = 'divparent'
this.divparent.style.visibility = 'hidden'
for (let i = 1; i <= 5; i++) {
const div = document.createElement('div')
const id = `div${i}`
div.id = id
this[id] = div
}
this.divparent.append(this.div1, this.div2, this.div3)
this.div4.style.visibility = 'hidden'
this.div4.append(this.div5)
document.body.append(this.divparent, this.div)
})
/**
* Tear down tests, destroying undo manager.
* @returns {void}
*/
afterEach(() => {
undoMgr = null
})
it('Test svgedit.history package', function () {
assert.ok(history)
assert.ok(history.MoveElementCommand)
assert.ok(history.InsertElementCommand)
assert.ok(history.ChangeElementCommand)
assert.ok(history.RemoveElementCommand)
assert.ok(history.BatchCommand)
assert.ok(history.UndoManager)
assert.equal(typeof history.MoveElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.InsertElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.ChangeElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.RemoveElementCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.BatchCommand, typeof function () { /* empty fn */ })
assert.equal(typeof history.UndoManager, typeof function () { /* empty fn */ })
})
it('Test UndoManager methods', function () {
assert.ok(undoMgr)
assert.ok(undoMgr.addCommandToHistory)
assert.ok(undoMgr.getUndoStackSize)
assert.ok(undoMgr.getRedoStackSize)
assert.ok(undoMgr.resetUndoStack)
assert.ok(undoMgr.getNextUndoCommandText)
assert.ok(undoMgr.getNextRedoCommandText)
assert.equal(typeof undoMgr, typeof {})
assert.equal(typeof undoMgr.addCommandToHistory, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getUndoStackSize, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getRedoStackSize, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.resetUndoStack, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getNextUndoCommandText, typeof function () { /* empty fn */ })
assert.equal(typeof undoMgr.getNextRedoCommandText, typeof function () { /* empty fn */ })
})
it('Test UndoManager.addCommandToHistory() function', function () {
assert.equal(undoMgr.getUndoStackSize(), 0)
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 1)
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 2)
})
it('Test UndoManager.getUndoStackSize() and getRedoStackSize() functions', function () {
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 1)
assert.equal(undoMgr.getRedoStackSize(), 2)
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 3)
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 3)
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 1)
assert.equal(undoMgr.getRedoStackSize(), 2)
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
undoMgr.redo()
assert.equal(undoMgr.getUndoStackSize(), 3)
assert.equal(undoMgr.getRedoStackSize(), 0)
})
it('Test UndoManager.resetUndoStackSize() function', function () {
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.addCommandToHistory(new MockCommand())
undoMgr.undo()
assert.equal(undoMgr.getUndoStackSize(), 2)
assert.equal(undoMgr.getRedoStackSize(), 1)
undoMgr.resetUndoStack()
assert.equal(undoMgr.getUndoStackSize(), 0)
assert.equal(undoMgr.getRedoStackSize(), 0)
})
it('Test UndoManager.getNextUndoCommandText() function', function () {
assert.equal(undoMgr.getNextUndoCommandText(), '')
undoMgr.addCommandToHistory(new MockCommand('First'))
undoMgr.addCommandToHistory(new MockCommand('Second'))
undoMgr.addCommandToHistory(new MockCommand('Third'))
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Second')
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), 'First')
undoMgr.undo()
assert.equal(undoMgr.getNextUndoCommandText(), '')
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'First')
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Second')
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
undoMgr.redo()
assert.equal(undoMgr.getNextUndoCommandText(), 'Third')
})
it('Test UndoManager.getNextRedoCommandText() function', function () {
assert.equal(undoMgr.getNextRedoCommandText(), '')
undoMgr.addCommandToHistory(new MockCommand('First'))
undoMgr.addCommandToHistory(new MockCommand('Second'))
undoMgr.addCommandToHistory(new MockCommand('Third'))
assert.equal(undoMgr.getNextRedoCommandText(), '')
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Third')
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Second')
undoMgr.undo()
assert.equal(undoMgr.getNextRedoCommandText(), 'First')
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Second')
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), 'Third')
undoMgr.redo()
assert.equal(undoMgr.getNextRedoCommandText(), '')
})
it('Test UndoManager.undo() and redo() functions', function () {
let lastCalled = null
const cmd1 = new MockCommand()
const cmd2 = new MockCommand()
const 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)
assert.ok(!lastCalled)
undoMgr.undo()
assert.equal(lastCalled, 'cmd3.unapply')
undoMgr.redo()
assert.equal(lastCalled, 'cmd3.apply')
undoMgr.undo()
undoMgr.undo()
assert.equal(lastCalled, 'cmd2.unapply')
undoMgr.undo()
assert.equal(lastCalled, 'cmd1.unapply')
lastCalled = null
undoMgr.undo()
assert.ok(!lastCalled)
undoMgr.redo()
assert.equal(lastCalled, 'cmd1.apply')
undoMgr.redo()
assert.equal(lastCalled, 'cmd2.apply')
undoMgr.redo()
assert.equal(lastCalled, 'cmd3.apply')
lastCalled = null
undoMgr.redo()
assert.ok(!lastCalled)
})
it('Test MoveElementCommand', function () {
let move = new history.MoveElementCommand(this.div3, this.div1, this.divparent)
assert.ok(move.unapply)
assert.ok(move.apply)
assert.equal(typeof move.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof move.apply, typeof function () { /* empty fn */ })
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div3)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div1)
assert.equal(this.divparent.lastElementChild, this.div2)
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
move = new history.MoveElementCommand(this.div1, null, this.divparent)
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div2)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div1)
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
move = new history.MoveElementCommand(this.div2, this.div5, this.div4)
move.unapply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div3)
assert.equal(this.div4.firstElementChild, this.div2)
assert.equal(this.div4.firstElementChild.nextElementSibling, this.div5)
move.apply()
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.divparent.firstElementChild.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div3)
assert.equal(this.div4.firstElementChild, this.div5)
assert.equal(this.div4.lastElementChild, this.div5)
})
it('Test InsertElementCommand', function () {
let insert = new history.InsertElementCommand(this.div3)
assert.ok(insert.unapply)
assert.ok(insert.apply)
assert.equal(typeof insert.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof insert.apply, typeof function () { /* empty fn */ })
insert.unapply()
assert.equal(this.divparent.childElementCount, 2)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.divparent.lastElementChild, this.div2)
insert.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
insert = new history.InsertElementCommand(this.div2)
insert.unapply()
assert.equal(this.divparent.childElementCount, 2)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div3)
assert.equal(this.divparent.lastElementChild, this.div3)
insert.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
})
it('Test RemoveElementCommand', function () {
const div6 = document.createElement('div')
div6.id = 'div6'
let remove = new history.RemoveElementCommand(div6, null, this.divparent)
assert.ok(remove.unapply)
assert.ok(remove.apply)
assert.equal(typeof remove.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof remove.apply, typeof function () { /* empty fn */ })
remove.unapply()
assert.equal(this.divparent.childElementCount, 4)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
assert.equal(this.div3.nextElementSibling, div6)
remove.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
remove = new history.RemoveElementCommand(div6, this.div2, this.divparent)
remove.unapply()
assert.equal(this.divparent.childElementCount, 4)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, div6)
assert.equal(div6.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
remove.apply()
assert.equal(this.divparent.childElementCount, 3)
assert.equal(this.divparent.firstElementChild, this.div1)
assert.equal(this.div1.nextElementSibling, this.div2)
assert.equal(this.div2.nextElementSibling, this.div3)
})
it('Test ChangeElementCommand', function () {
this.div1.setAttribute('title', 'new title')
let change = new history.ChangeElementCommand(this.div1,
{ title: 'old title', class: 'foo' })
assert.ok(change.unapply)
assert.ok(change.apply)
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof change.apply, typeof function () { /* empty fn */ })
change.unapply()
assert.equal(this.div1.getAttribute('title'), 'old title')
assert.equal(this.div1.getAttribute('class'), 'foo')
change.apply()
assert.equal(this.div1.getAttribute('title'), 'new title')
assert.ok(!this.div1.getAttribute('class'))
this.div1.textContent = 'inner text'
change = new history.ChangeElementCommand(this.div1,
{ '#text': null })
change.unapply()
assert.ok(!this.div1.textContent)
change.apply()
assert.equal(this.div1.textContent, 'inner text')
this.div1.textContent = ''
change = new history.ChangeElementCommand(this.div1,
{ '#text': 'old text' })
change.unapply()
assert.equal(this.div1.textContent, 'old text')
change.apply()
assert.ok(!this.div1.textContent)
// TODO(codedread): Refactor this #href stuff in history.js and svgcanvas.js
const rect = document.createElementNS(NS.SVG, 'rect')
let justCalled = null
let gethrefvalue = null
let sethrefvalue = null
utilities.mock({
getHref (elem) {
assert.equal(elem, rect)
justCalled = 'getHref'
return gethrefvalue
},
setHref (elem, val) {
assert.equal(elem, rect)
assert.equal(val, sethrefvalue)
justCalled = 'setHref'
},
getRotationAngle () { return 0 }
})
gethrefvalue = '#newhref'
change = new history.ChangeElementCommand(rect,
{ '#href': '#oldhref' })
assert.equal(justCalled, 'getHref')
justCalled = null
sethrefvalue = '#oldhref'
change.unapply()
assert.equal(justCalled, 'setHref')
justCalled = null
sethrefvalue = '#newhref'
change.apply()
assert.equal(justCalled, 'setHref')
const line = document.createElementNS(NS.SVG, 'line')
line.setAttribute('class', 'newClass')
change = new history.ChangeElementCommand(line, { class: 'oldClass' })
assert.ok(change.unapply)
assert.ok(change.apply)
assert.equal(typeof change.unapply, typeof function () { /* empty fn */ })
assert.equal(typeof change.apply, typeof function () { /* empty fn */ })
change.unapply()
assert.equal(line.getAttribute('class'), 'oldClass')
change.apply()
assert.equal(line.getAttribute('class'), 'newClass')
})
it('Test BatchCommand', function () {
let concatResult = ''
MockCommand.prototype.apply = function () { concatResult += this.text }
const batch = new history.BatchCommand()
assert.ok(batch.unapply)
assert.ok(batch.apply)
assert.ok(batch.addSubCommand)
assert.ok(batch.isEmpty)
assert.equal(typeof batch.unapply, 'function')
assert.equal(typeof batch.apply, 'function')
assert.equal(typeof batch.addSubCommand, 'function')
assert.equal(typeof batch.isEmpty, 'function')
assert.ok(batch.isEmpty())
batch.addSubCommand(new MockCommand('a'))
assert.ok(!batch.isEmpty())
batch.addSubCommand(new MockCommand('b'))
batch.addSubCommand(new MockCommand('c'))
assert.ok(!concatResult)
batch.apply()
assert.equal(concatResult, 'abc')
MockCommand.prototype.apply = function () { /* empty fn */ }
MockCommand.prototype.unapply = function () { concatResult += this.text }
concatResult = ''
assert.ok(!concatResult)
batch.unapply()
assert.equal(concatResult, 'cba')
MockCommand.prototype.unapply = function () { /* empty fn */ }
})
})