textangular
Version:
A radically powerful Text-Editor/Wysiwyg editor for Angular.js
297 lines (280 loc) • 9.38 kB
JavaScript
describe('taBind.undoManager', function () {
'use strict';
beforeEach(module('textAngular'));
afterEach(inject(function($document){
$document.find('body').html('');
}));
var $rootScope, element, first, second, third;
beforeEach(inject(function (_$compile_, _$rootScope_, $document) {
$rootScope = _$rootScope_;
$rootScope.html = '<p>Test Contents</p>';
element = _$compile_('<div ta-bind contenteditable="contenteditable" ng-model="html" id="Test"></div>')($rootScope);
$document.find('body').append(element);
$rootScope.$digest();
}));
describe('should attach functions to scope', function () {
it('attaches undoTaBind', function(){
expect($rootScope.$undoTaBindTest).not.toBeUndefined();
});
it('attaches redoTaBind', function(){
expect($rootScope.$redoTaBindTest).not.toBeUndefined();
});
});
describe('should push to undoStack', function () {
it('expect initial value to be pushed', function(){
expect($rootScope.$undoManagerTest._stack[0]).toBe($rootScope.html);
});
it('expect current to be the last pushed value', function(){
expect($rootScope.$undoManagerTest._stack[0]).toBe($rootScope.$undoManagerTest.current());
});
it('expect model changes to be pushed', function(){
$rootScope.html = '<p>Test Changed Contents</p>';
$rootScope.$digest();
expect($rootScope.$undoManagerTest.current()).toBe($rootScope.html);
});
it('expect push to truncate redo branch', function(){
$rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
$rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
$rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
$rootScope.$undoManagerTest._index = 1;
$rootScope.html = '<p>Test Changed Contents 4</p>';
$rootScope.$digest();
expect($rootScope.$undoManagerTest.current()).toBe($rootScope.html);
expect($rootScope.$undoManagerTest._stack.length).toBe(3);
expect($rootScope.$undoManagerTest._stack[2]).toBe('<p>Test Changed Contents 4</p>');
});
it('expect push to remove start if past max undo level', function(){
$rootScope.$undoManagerTest._max = 2;
$rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
$rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
$rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
expect($rootScope.$undoManagerTest._stack.length).toBe(2);
expect($rootScope.$undoManagerTest._stack[0]).toBe('<p>Test Changed Contents 2</p>');
});
});
describe('undo function', function () {
var first, second, third;
describe('should update', function(){
beforeEach(function(){
first = $rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
second = $rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
third = $rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
$rootScope.$undoTaBindTest();
});
it('model', function(){
expect($rootScope.$undoManagerTest.current()).toBe(second);
});
it('html', function(){
expect(element[0].innerHTML).toBe(second);
});
});
describe('should handle when no undo available', function(){
it('not error', function(){
expect(function(){
$rootScope.$undoTaBindTest();
}).not.toThrow();
});
it('not change html', function(){
$rootScope.$undoTaBindTest();
expect(element[0].innerHTML).toBe('<p>Test Contents</p>');
});
it('not change model', function(){
$rootScope.$undoTaBindTest();
expect($rootScope.html).toBe('<p>Test Contents</p>');
});
});
});
describe('redo function', function () {
beforeEach(function(){
first = $rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
second = $rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
third = $rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
});
describe('should update', function(){
beforeEach(inject(function($timeout){
$rootScope.$undoTaBindTest();
$rootScope.$undoTaBindTest();
$timeout.flush();
$rootScope.$redoTaBindTest();
$timeout.flush();
}));
it('model', function(){
expect($rootScope.$undoManagerTest.current()).toBe(second);
});
it('html', function(){
expect(element[0].innerHTML).toBe(second);
});
});
describe('should handle when no redo available', function(){
it('not error', function(){
expect(function(){
$rootScope.$redoTaBindTest();
$rootScope.$redoTaBindTest();
}).not.toThrow();
});
it('not change html', function(){
$rootScope.$redoTaBindTest();
expect(element[0].innerHTML).toBe(third);
});
it('not change model', function(){
$rootScope.$redoTaBindTest();
expect($rootScope.html).toBe(third);
});
});
});
describe('handles keyup', function () {
describe('trigger push on $timeout or trigger_key', function(){
beforeEach(function(){
element.html('<p>Test</p>');
});
it('should trigger timeout', inject(function($timeout){
element.triggerHandler('keyup');
expect($rootScope.$undoManagerTest.current()).not.toBe('<p>Test</p>');
expect(function(){ $timeout.flush(); }).not.toThrow();
expect($rootScope.$undoManagerTest.current()).toBe('<p>Test</p>');
}));
it('should re-create timeout on next keypress', inject(function($timeout){
element.triggerHandler('keyup');
element.triggerHandler('keyup');
expect($rootScope.$undoManagerTest.current()).not.toBe('<p>Test</p>');
$timeout.flush();
expect($rootScope.$undoManagerTest.current()).toBe('<p>Test</p>');
}));
});
});
describe('handles keydown', function () {
describe('should trigger undo on keydown', function(){
beforeEach(function(){
first = $rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
second = $rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
third = $rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
});
it('ctrl+z', inject(function($timeout){
if(angular.element === jQuery) {
event = jQuery.Event('keydown');
event.keyCode = 90;
event.ctrlKey = true;
element.triggerHandler(event);
}else{
event = {
keyCode: 90,
ctrlKey: true
};
element.triggerHandler('keydown', event);
}
expect($rootScope.html).toBe(second);
}));
it('command+z', inject(function($timeout){
if(angular.element === jQuery) {
event = jQuery.Event('keydown');
event.keyCode = 90;
event.metaKey = true;
element.triggerHandler(event);
}else{
event = {
keyCode: 90,
metaKey: true
};
element.triggerHandler('keydown', event);
}
expect($rootScope.html).toBe(second);
}));
it('not alt+ctrl+z #518', inject(function($timeout){
if(angular.element === jQuery) {
event = jQuery.Event('keydown');
event.keyCode = 90;
event.altKey = true;
event.ctrlKey = true;
element.triggerHandler(event);
}else{
event = {
keyCode: 90,
altKey: true,
ctrlKey: true
};
element.triggerHandler('keydown', event);
}
expect($rootScope.html).toBe(third);
}));
});
describe('should trigger redo on keydown', function(){
beforeEach(function(){
first = $rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
second = $rootScope.html = '<p>Test Changed Contents 2</p>';
$rootScope.$digest();
third = $rootScope.html = '<p>Test Changed Contents 3</p>';
$rootScope.$digest();
$rootScope.$undoTaBindTest();
$rootScope.$undoTaBindTest();
});
it('ctrl+y', inject(function($timeout){
if(angular.element === jQuery) {
event = jQuery.Event('keydown');
event.keyCode = 89;
event.ctrlKey = true;
element.triggerHandler(event);
}else{
event = {
keyCode: 89,
ctrlKey: true
};
element.triggerHandler('keydown', event);
}
expect($rootScope.html).toBe(second);
}));
it('command+shift+z', inject(function($timeout){
if(angular.element === jQuery) {
event = jQuery.Event('keydown');
event.keyCode = 90;
event.shiftKey = true;
event.metaKey = true;
element.triggerHandler(event);
}else{
event = {
keyCode: 90,
metaKey: true,
shiftKey: true
};
element.triggerHandler('keydown', event);
}
expect($rootScope.html).toBe(second);
}));
});
describe('should prevent default on match only', function(){
beforeEach(function(){
first = $rootScope.html = '<p>Test Changed Contents 1</p>';
$rootScope.$digest();
});
it('match prevents default', inject(function($timeout){
event = jasmine.createSpyObj('e', ['preventDefault']);
event.keyCode = 89;
event.ctrlKey = true;
element.triggerHandler('keydown', event);
expect(event.preventDefault).toHaveBeenCalled();
}));
it('no match allows pass', inject(function($timeout){
event = jasmine.createSpyObj('e', ['preventDefault']);
event.keyCode = 80;
event.ctrlKey = true;
element.triggerHandler('keydown', event);
expect(event.preventDefault).not.toHaveBeenCalled();
}));
});
});
});