module("tinymce.UndoManager", {
setupModule: function() {
QUnit.stop();
tinymce.init({
selector: "textarea",
add_unload_trigger: false,
skin: false,
init_instance_callback: function(ed) {
window.editor = ed;
QUnit.start();
}
});
}
});
test('Initial states', function() {
expect(3);
ok(!editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('One undo level', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.focus();
editor.execCommand('SelectAll');
editor.execCommand('Bold');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('Two undo levels', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.execCommand('SelectAll');
editor.execCommand('Italic');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('No undo levels and one redo', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.undoManager.undo();
ok(!editor.undoManager.hasUndo());
ok(editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('One undo levels and one redo', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.execCommand('SelectAll');
editor.execCommand('Italic');
editor.undoManager.undo();
ok(editor.undoManager.hasUndo());
ok(editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('Typing state', function() {
var selectAllFlags;
editor.undoManager.clear();
editor.setContent('test');
ok(!editor.undoManager.typing);
editor.dom.fire(editor.getBody(), 'keydown', {keyCode: 65});
ok(editor.undoManager.typing);
editor.dom.fire(editor.getBody(), 'keyup', {keyCode: 13});
ok(!editor.undoManager.typing);
selectAllFlags = {keyCode: 65, ctrlKey: false, altKey: false, shiftKey: false};
if (tinymce.Env.mac) {
selectAllFlags.metaKey = true;
} else {
selectAllFlags.ctrlKey = true;
}
editor.dom.fire(editor.getBody(), 'keydown', selectAllFlags);
ok(!editor.undoManager.typing);
});
test('Undo and add new level', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.undoManager.undo();
editor.execCommand('SelectAll');
editor.execCommand('Italic');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing);
});
test('Events', function() {
var add, undo, redo;
editor.undoManager.clear();
editor.setContent('test');
expect(6);
editor.on('AddUndo', function(e) {
add = e.level;
});
editor.on('Undo', function(e) {
undo = e.level;
});
editor.on('Redo', function(e) {
redo = e.level;
});
editor.execCommand('SelectAll');
editor.execCommand('Bold');
ok(add.content);
ok(add.bookmark);
editor.undoManager.undo();
ok(undo.content);
ok(undo.bookmark);
editor.undoManager.redo();
ok(redo.content);
ok(redo.bookmark);
});
test('No undo/redo cmds on Undo/Redo shortcut', function() {
var evt, commands = [], added = false;
editor.undoManager.clear();
editor.setContent('test');
editor.on('BeforeExecCommand', function(e) {
commands.push(e.command);
});
editor.on('BeforeAddUndo', function() {
added = true;
});
evt = {
keyCode: 90,
metaKey: tinymce.Env.mac,
ctrlKey: !tinymce.Env.mac,
shiftKey: false,
altKey: false
};
editor.dom.fire(editor.getBody(), 'keydown', evt);
editor.dom.fire(editor.getBody(), 'keypress', evt);
editor.dom.fire(editor.getBody(), 'keyup', evt);
strictEqual(added, false);
deepEqual(commands, ["Undo"]);
});
test('Transact', function() {
var count = 0;
editor.undoManager.clear();
editor.on('BeforeAddUndo', function() {
count++;
});
editor.undoManager.transact(function() {
editor.undoManager.add();
editor.undoManager.add();
});
equal(count, 1);
});
test('Transact nested', function() {
var count = 0;
editor.undoManager.clear();
editor.on('BeforeAddUndo', function() {
count++;
});
editor.undoManager.transact(function() {
editor.undoManager.add();
editor.undoManager.transact(function() {
editor.undoManager.add();
});
});
equal(count, 1);
});
test('Transact exception', function() {
var count = 0;
editor.undoManager.clear();
editor.on('BeforeAddUndo', function() {
count++;
});
throws(
function() {
editor.undoManager.transact(function() {
throw new Error("Test");
});
},
"Test"
);
editor.undoManager.add();
equal(count, 1);
});
test('Exclude internal elements', function() {
var count = 0, lastLevel;
editor.undoManager.clear();
equal(count, 0);
editor.on('AddUndo', function() {
count++;
});
editor.on('BeforeAddUndo', function(e) {
lastLevel = e.level;
});
editor.getBody().innerHTML = (
'test' +
'' +
'
x |
x |
x |
x |
some text
"); Utils.setSelection('p', 4, 'p', 9); Utils.type('\b'); equal(Utils.cleanHtml(lastLevel.content), "some text
"); editor.fire('blur'); equal(Utils.cleanHtml(lastLevel.content), "some
"); editor.execCommand('FormatBlock', false, 'h1'); editor.undoManager.undo(); equal(editor.getContent(), "some
"); }); test('BeforeAddUndo event', function() { var lastEvt, addUndoEvt; function blockEvent(e) { e.preventDefault(); } editor.on('BeforeAddUndo', function(e) { lastEvt = e; }); editor.undoManager.clear(); editor.setContent("a
"); editor.undoManager.add(); equal(lastEvt.lastLevel, null); equal(Utils.cleanHtml(lastEvt.level.content), "a
"); editor.setContent("b
"); editor.undoManager.add(); equal(Utils.cleanHtml(lastEvt.lastLevel.content), "a
"); equal(Utils.cleanHtml(lastEvt.level.content), "b
"); editor.on('BeforeAddUndo', blockEvent); editor.on('AddUndo', function(e) { addUndoEvt = e; }); editor.setContent("c
"); editor.undoManager.add(null, {data: 1}); equal(Utils.cleanHtml(lastEvt.lastLevel.content), "b
"); equal(Utils.cleanHtml(lastEvt.level.content), "c
"); equal(lastEvt.originalEvent.data, 1); ok(!addUndoEvt, "Event level produced when it should be blocked"); editor.off('BeforeAddUndo', blockEvent); }); test('Dirty state type letter', function() { editor.undoManager.clear(); editor.setDirty(false); editor.setContent("a
"); Utils.setSelection('p', 1); ok(!editor.isDirty(), "Dirty state should be false"); Utils.type('b'); equal(editor.getContent(), "ab
"); ok(editor.isDirty(), "Dirty state should be true"); }); test('Dirty state type shift+letter', function() { editor.undoManager.clear(); editor.setDirty(false); editor.setContent("a
"); Utils.setSelection('p', 1); ok(!editor.isDirty(), "Dirty state should be false"); Utils.type({keyCode: 65, charCode: 66, shiftKey: true}); equal(editor.getContent(), "aB
"); ok(editor.isDirty(), "Dirty state should be true"); }); test('Dirty state type AltGr+letter', function() { editor.undoManager.clear(); editor.setDirty(false); editor.setContent("a
"); Utils.setSelection('p', 1); ok(!editor.isDirty(), "Dirty state should be false"); Utils.type({keyCode: 65, charCode: 66, ctrlKey: true, altKey: true}); equal(editor.getContent(), "aB
"); ok(editor.isDirty(), "Dirty state should be true"); });