import { Pipeline } from '@ephox/agar'; import { LegacyUnit, TinyLoader } from '@ephox/mcagar'; import JSON from 'tinymce/core/api/util/JSON'; import Theme from 'tinymce/themes/modern/Theme'; import { UnitTest } from '@ephox/bedrock'; UnitTest.asynctest('browser.tinymce.core.InsertContentCommandTest', function () { const success = arguments[arguments.length - 2]; const failure = arguments[arguments.length - 1]; const suite = LegacyUnit.createSuite(); Theme(); const normalizeRng = function (rng) { if (rng.startContainer.nodeType === 3) { if (rng.startOffset === 0) { rng.setStartBefore(rng.startContainer); } else if (rng.startOffset >= rng.startContainer.nodeValue.length - 1) { rng.setStartAfter(rng.startContainer); } } if (rng.endContainer.nodeType === 3) { if (rng.endOffset === 0) { rng.setEndBefore(rng.endContainer); } else if (rng.endOffset >= rng.endContainer.nodeValue.length - 1) { rng.setEndAfter(rng.endContainer); } } return rng; }; const ok = function (value, label?) { return LegacyUnit.equal(value, true, label); }; const getContent = function (editor) { return editor.getContent(); }; suite.test('mceInsertContent - p inside text of p', function (editor) { let rng; editor.setContent('
1234
'); editor.focus(); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('p')[0].firstChild, 1); rng.setEnd(editor.dom.select('p')[0].firstChild, 3); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, 'abc
'); LegacyUnit.equal(getContent(editor), '1
abc
4
'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent before HR', function (editor) { let rng; editor.setContent('x
def
'); LegacyUnit.setSelection(editor, 'h1', 3); editor.execCommand('mceInsertContent', false, 'def
'); }); suite.test('mceInsertContent HR at end of H1 with inline elements with P sibling', function (editor) { editor.setContent('def
'); LegacyUnit.setSelection(editor, 'strong', 3); editor.execCommand('mceInsertContent', false, 'def
'); }); suite.test('mceInsertContent empty block', function (editor) { editor.setContent('\u00a0
def
'); LegacyUnit.setSelection(editor, 'h1', 3); editor.execCommand('mceInsertContent', false, '| \u00a0 |
def
'); }); suite.test('mceInsertContent - p inside whole p', function (editor) { let rng; editor.setContent('1234
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('p')[0].firstChild, 0); rng.setEnd(editor.dom.select('p')[0].firstChild, 4); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, 'abc
'); LegacyUnit.equal(getContent(editor), 'abc
'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent - pre in text of pre', function (editor) { let rng; editor.setContent('1234'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('pre')[0].firstChild, 1); rng.setEnd(editor.dom.select('pre')[0].firstChild, 3); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, '
abc'); LegacyUnit.equal(getContent(editor), '
1
abc
4'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'PRE'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'PRE'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent - h1 in text of h1', function (editor) { let rng; editor.setContent('
abc
'); LegacyUnit.equal(getContent(editor), 'abc
'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent - text inside empty p', function (editor) { let rng; editor.getBody().innerHTML = ''; LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('mceInsertContent', false, 'abc'); LegacyUnit.equal( editor.getBody().innerHTML.toLowerCase().replace(/^abc
' ); // Opera inserts a BR at the beginning of contents if the P is empty rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent - text inside empty p with br caret node', function (editor) { let rng; editor.getBody().innerHTML = 'abc
'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 1); LegacyUnit.equal(rng.startContainer.innerHTML, 'abc'); }); suite.test('mceInsertContent - image inside p', function (editor) { let rng; editor.setContent('1
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('p')[0].firstChild, 0); rng.setEnd(editor.dom.select('p')[0].firstChild, 1); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, '1
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('p')[0].firstChild, 0); rng.setEnd(editor.dom.select('p')[0].firstChild, 1); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, 'strikefont
' ); }); suite.test('mceInsertContent - hr', function (editor) { let rng; editor.setContent('123
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('p')[0].firstChild, 1); rng.setEnd(editor.dom.select('p')[0].firstChild, 2); editor.selection.setRng(rng); editor.execCommand('mceInsertContent', false, '1
3
'); rng = normalizeRng(editor.selection.getRng(true)); ok(rng.collapsed); LegacyUnit.equalDom(rng.startContainer, editor.getBody().lastChild); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, 0); LegacyUnit.equal(rng.endContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, 0); }); suite.test('mceInsertContent - forced root block', function (editor) { // Forced root block editor.getBody().innerHTML = ''; editor.execCommand('mceInsertContent', false, 'test123'); // Opera adds an extra paragraph since it adds a BR at the end of the contents pass though this for now since it's an minority browser LegacyUnit.equal(editor.getContent().replace(/\u00a0<\/p>/g, ''), '
test123
'); }); suite.test('mceInsertContent - mixed inline content inside td', function (editor) { // Forced root block editor.getBody().innerHTML = '| X |
| test123X |
123 testing span later in document
', insertedContent = 'a
'; LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('mceInsertContent', false, ' b'); LegacyUnit.equal(editor.getContent(), '\u00a0ba
'); }); suite.test('mceInsertContent - text with space after at end of block', function (editor) { editor.getBody().innerHTML = 'a
'; LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('mceInsertContent', false, 'b '); LegacyUnit.equal(editor.getContent(), 'ab\u00a0
'); }); suite.test('mceInsertContent - text with space before/after at middle of block', function (editor) { editor.getBody().innerHTML = 'ac
'; LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('mceInsertContent', false, ' b '); LegacyUnit.equal(editor.getContent(), 'a b c
'); }); suite.test('mceInsertContent - inline element with space before/after at middle of block', function (editor) { editor.getBody().innerHTML = 'ac
'; LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('mceInsertContent', false, ' b '); LegacyUnit.equal(editor.getContent(), 'a b c
'); }); suite.test('mceInsertContent - block element with space before/after at middle of block', function (editor) { editor.getBody().innerHTML = 'ac
'; LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('mceInsertContent', false, 'b
'); LegacyUnit.equal(editor.getContent(), 'a
b
c
'); }); suite.test('mceInsertContent - strong in strong', function (editor) { editor.getBody().innerHTML = 'ac'; LegacyUnit.setSelection(editor, 'strong', 1); editor.execCommand('mceInsertContent', false, { content: 'b', merge: true }); LegacyUnit.equal(editor.getContent(), 'abc
'); }); suite.test('mceInsertContent - span in span same style color', function (editor) { editor.getBody().innerHTML = 'ac'; LegacyUnit.setSelection(editor, 'span', 1); editor.execCommand('mceInsertContent', false, { content: 'b', merge: true }); LegacyUnit.equal(editor.getContent(), 'abc
'); }); suite.test('mceInsertContent - span in span different style color', function (editor) { editor.getBody().innerHTML = 'ac'; LegacyUnit.setSelection(editor, 'span', 1); editor.execCommand('mceInsertContent', false, { content: 'b', merge: true }); LegacyUnit.equal(editor.getContent(), 'abc
'); }); suite.test('mceInsertContent - select with option element', function (editor) { editor.getBody().innerHTML = '1
'; LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('mceInsertContent', false, '2'); LegacyUnit.equal(editor.getContent(), '12
'); }); suite.test('mceInsertContent - insert P in span style element #7090', function (editor) { editor.setContent('1
3
'); LegacyUnit.setSelection(editor, 'span', 1); editor.execCommand('mceInsertContent', false, '2
'); LegacyUnit.equal(editor.getContent(), '1
2
3
'); }); suite.test('mceInsertContent - insert char at char surrounded by spaces', function (editor) { editor.setContent('a b c
'); LegacyUnit.setSelection(editor, 'p', 2, 'p', 3); editor.execCommand('mceInsertContent', false, 'X'); LegacyUnit.equal(JSON.serialize(editor.getContent()), '"a X c
"'); }); TinyLoader.setup(function (editor, onSuccess, onFailure) { Pipeline.async({}, suite.toSteps(editor), onSuccess, onFailure); }, { add_unload_trigger: false, disable_nodechange: true, indent: false, entities: 'raw', convert_urls: false, valid_styles: { '*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,' + 'float,margin,margin-top,margin-right,margin-bottom,margin-left,padding-left,text-align,display' }, skin_url: '/project/js/tinymce/skins/lightgray' }, success, failure); });