/** * Editor.spec.js * (c) 2015~ Summernote Team * summernote may be freely distributed under the MIT license./ */ import chai from 'chai'; import spies from 'chai-spies'; import chaidom from '../../../chaidom'; import $ from 'jquery'; import env from '../../../../src/js/base/core/env'; import range from '../../../../src/js/base/core/range'; import Context from '../../../../src/js/base/Context'; describe('Editor', () => { var expect = chai.expect; chai.use(spies); chai.use(chaidom); var editor, context, $editable; function expectContents(context, markup) { expect(context.layoutInfo.editable.html()).to.equalsIgnoreCase(markup); } function expectToHaveBeenCalled(context, customEvent, handler) { const $note = context.layoutInfo.note; const spy = chai.spy(); $note.on(customEvent, spy); handler(); expect(spy).to.have.been.called(); } beforeEach(function() { $('body').empty(); // important ! var $note = $('

hello

'); var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); context = new Context($note, options); editor = context.modules.editor; $editable = context.layoutInfo.editable; // [workaround] // - Firefox need setTimeout for applying contents // - IE8-11 can't create range in headless mode if (env.isFF || env.isMSIE || env.isEdge) { this.skip(); } }); describe('initialize', () => { it('should bind custom events', () => { [ 'keydown', 'keyup', 'blur', 'mousedown', 'mouseup', 'scroll', 'focusin', 'focusout' ].forEach((eventName) => { expectToHaveBeenCalled(context, 'summernote.' + eventName, () => { $editable.trigger(eventName); }); }); expectToHaveBeenCalled(context, 'summernote.change', () => { editor.insertText('hello'); }); }); }); if (env.isWebkit) { describe('undo and redo', () => { it('should control history', () => { editor.insertText(' world'); expectContents(context, '

hello world

'); editor.undo(); expectContents(context, '

hello

'); editor.redo(); expectContents(context, '

hello world

'); }); }); } describe('tab', () => { it('should insert tab', () => { editor.tab(); expectContents(context, '

hello    

'); }); }); describe('insertParagraph', () => { it('should insert paragraph', () => { editor.insertParagraph(); expectContents(context, '

hello


'); editor.insertParagraph(); expectContents(context, '

hello



'); }); }); if (env.isWebkit) { describe('insertImage', () => { it('should insert image', () => { var source = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAF0lEQVQYGWP8////fwYsgAmLGFiIHhIAT+oECGHuN2UAAAAASUVORK5CYII='; return editor.insertImage(source, 'image').then(() => { expectContents(context, '

hello

'); }); }); }); } describe('insertOrderedList and insertUnorderedList', () => { it('should toggle paragraph to list', () => { editor.insertOrderedList(); expectContents(context, '
  1. hello
'); editor.insertUnorderedList(); expectContents(context, ''); editor.insertUnorderedList(); expectContents(context, '

hello

'); }); }); describe('indent and outdent', () => { // [workaround] style is different by browser if (env.isPhantom) { it('should indent and outdent paragraph', () => { editor.indent(); expectContents(context, '

hello

'); editor.outdent(); expectContents(context, '

hello

'); }); } it('should indent and outdent list', () => { editor.insertOrderedList(); expectContents(context, '
  1. hello
'); editor.indent(); expectContents(context, '
    1. hello
'); editor.indent(); expectContents(context, '
      1. hello
'); editor.outdent(); expectContents(context, '
    1. hello
'); editor.outdent(); expectContents(context, '
  1. hello
'); }); }); describe('insertNode', () => { it('should insert node', () => { editor.insertNode($(' world')[0]); expectContents(context, '

hello world

'); }); it('should be limited', () => { var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); options.maxTextLength = 5; context = new Context($('

hello

'), options); editor = context.modules.editor; editor.insertNode($(' world')[0]); expectContents(context, '

hello

'); }); }); describe('insertText', () => { it('should insert text', () => { editor.insertText(' world'); expectContents(context, '

hello world

'); }); it('should be limited', () => { var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); options.maxTextLength = 5; context = new Context($('

hello

'), options); editor = context.modules.editor; editor.insertText(' world'); expectContents(context, '

hello

'); }); }); describe('pasteHTML', () => { it('should paste html', () => { editor.pasteHTML(' world'); expectContents(context, '

hello world

'); }); it('should not call change change event more than once per paste event', () => { var generateLargeHtml = () => { var html = '
'; for (var i = 0; i < 1000; i++) { html += '

HTML element #' + i + '

'; } html += '
'; return html; }; var $note = context.layoutInfo.note; var spy = chai.spy(); $note.on('summernote.change', spy); var html = generateLargeHtml(); editor.pasteHTML(html); expect(spy).to.have.been.called.once; }); it('should be limited', () => { var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); options.maxTextLength = 5; context = new Context($('

hello

'), options); editor = context.modules.editor; editor.pasteHTML(' world'); expectContents(context, '

hello

'); }); }); describe('insertHorizontalRule', () => { it('should insert horizontal rule', () => { editor.insertHorizontalRule(); expectContents(context, '

hello



'); }); }); describe('insertTable', () => { it('should insert table', () => { var markup = [ '

hello

', '', '', '', '




', '


' ].join(''); editor.insertTable('2x2'); expectContents(context, markup); }); }); describe('empty', () => { it('should make contents empty', () => { editor.empty(); expect(editor.isEmpty()).to.be.true; }); }); describe('formatBlock', () => { it('should apply formatBlock', () => { $editable.appendTo('body'); editor.formatBlock('blockquote'); // start

hello

=>
hello
expectContents(context, '
hello
'); }); it('should apply multi formatBlock', () => { // set multi block html var codes = [ '

hello world

', '

hello world

', '

hello world

' ]; context.invoke('code', codes.join('')); // run formatBlock $editable.appendTo('body'); editor.formatBlock('blockquote'); // check current range position in blockquote element var nodeName = $editable.children()[0].nodeName; expect(nodeName).to.equalsIgnoreCase('blockquote'); }); it('should apply multi test 2 - formatBlock', () => { var codes = [ '

hello world

', '

hello world

', '

hello world

' ]; context.invoke('code', codes.join('')); $editable.appendTo('body'); var startNode = $editable.find('p').first()[0]; var endNode = $editable.find('p').last()[0]; // all p tags is wrapped range.create(startNode, 1, endNode, 1).normalize().select(); editor.formatBlock('blockquote'); var nodeName = $editable.children()[0].nodeName; expect(nodeName).to.equalsIgnoreCase('blockquote'); // p -> blockquote, p is none expect($editable.find('p').length).to.equals(0); }); it('should apply custom className in formatBlock', () => { var $target = $('
'); $editable.appendTo('body'); editor.formatBlock('blockquote', $target); // start

hello

=>
hello
expectContents(context, '
hello
'); }); }); describe('createLink', () => { it('should create normal link', () => { var text = 'hello'; var pNode = $editable.find('p')[0]; var textNode = pNode.childNodes[0]; var startIndex = textNode.wholeText.indexOf(text); var endIndex = startIndex + text.length; range.create(textNode, startIndex, textNode, endIndex).normalize().select(); // check creation normal link editor.createLink({ url: 'http://summernote.org', text: 'summernote' }); expectContents(context, '

hellosummernote

'); }); it('should create a link with range', () => { var text = 'hello'; var pNode = $editable.find('p')[0]; var textNode = pNode.childNodes[0]; var startIndex = textNode.wholeText.indexOf(text); var endIndex = startIndex + text.length; var rng = range.create(textNode, startIndex, textNode, endIndex); editor.createLink({ url: 'http://summernote.org', text: 'summernote', range: rng }); expectContents(context, '

summernote

'); }); it('should create a link with isNewWindow', () => { var text = 'hello'; var pNode = $editable.find('p')[0]; var textNode = pNode.childNodes[0]; var startIndex = textNode.wholeText.indexOf(text); var endIndex = startIndex + text.length; var rng = range.create(textNode, startIndex, textNode, endIndex); editor.createLink({ url: 'http://summernote.org', text: 'summernote', range: rng, isNewWindow: true }); expectContents(context, '

summernote

'); }); it('should create a relative link without scheme', () => { var text = 'hello'; var pNode = $editable.find('p')[0]; var textNode = pNode.childNodes[0]; var startIndex = textNode.wholeText.indexOf(text); var endIndex = startIndex + text.length; var rng = range.create(textNode, startIndex, textNode, endIndex); editor.createLink({ url: '/relative/url', text: 'summernote', range: rng, isNewWindow: true }); expectContents(context, '

summernote

'); }); it('should modify a link', () => { context.invoke('code', '

hello world

'); var anchorNode = $editable.find('a')[0]; var rng = range.createFromNode(anchorNode); editor.createLink({ url: 'http://wow.summernote.org', text: 'summernote wow', range: rng }); expectContents(context, '

summernote wow

'); }); it('should be limited when creating a link', () => { var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); options.maxTextLength = 5; context = new Context($('

hello

'), options); editor = context.modules.editor; editor.createLink({ url: 'http://summernote.org', text: 'summernote' }); expectContents(context, '

hello

'); }); it('should be limited when modifying a link', () => { var options = $.extend({}, $.summernote.options); options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]); options.maxTextLength = 5; context = new Context($('

hello

'), options); var editable = context.layoutInfo.editable; var anchorNode = editable.find('a')[0]; var rng = range.createFromNode(anchorNode); editor = context.modules.editor; editor.createLink({ url: 'http://summernote.org', text: 'hello world', range: rng }); expectContents(context, 'hello'); }); }); });