init
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
import { RawAssertions } from '@ephox/agar';
|
||||
import FragmentParser from 'tinymce/plugins/paste/core/FragmentParser';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
|
||||
UnitTest.test('atomic.tinymce.plugins.paste.FragmentParserTest', function () {
|
||||
const testGetFragmentInfo = function () {
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string and context body',
|
||||
{
|
||||
html: 'abc',
|
||||
context: 'body'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('abc')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and context body', {
|
||||
html: 'abc',
|
||||
context: 'body'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<!-- StartFragment -->abc<!-- EndFragment -->')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and context body', {
|
||||
html: 'abc',
|
||||
context: 'body'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<!--StartFragment-->abc<!--EndFragment-->')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after fragment markers', {
|
||||
html: 'abc',
|
||||
context: 'body'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('X<!--StartFragment-->abc<!--EndFragment-->Y')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after fragment markers',
|
||||
{
|
||||
html: '<B>bold</B><I><B>abc</B>This</I>',
|
||||
context: 'body'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<!DOCTYPE html><BODY><!-- StartFragment --><B>bold</B><I><B>abc</B>This</I><!-- EndFragment --></BODY></HTML>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after them but with the ul context',
|
||||
{
|
||||
html: '<LI>abc</LI>',
|
||||
context: 'ul'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<BODY><UL><!--StartFragment--><LI>abc</LI><!--EndFragment--></UL></BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after them but with the ul context',
|
||||
{
|
||||
html: '\n<LI>abc</LI>\n',
|
||||
context: 'ul'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<BODY>\n<UL>\n<!--StartFragment-->\n<LI>abc</LI>\n<!--EndFragment-->\n</UL>\n</BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after them but with the p context',
|
||||
{
|
||||
html: '<B>abc</B>',
|
||||
context: 'p'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<BODY><P><!--StartFragment--><B>abc</B><!--EndFragment--></P></BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and contents before/after them but with the h1 context',
|
||||
{
|
||||
html: '<B>abc</B>',
|
||||
context: 'h1'
|
||||
},
|
||||
FragmentParser.getFragmentInfo('<BODY><H1><!--StartFragment--><B>abc</B><!--EndFragment--></H1></BODY>')
|
||||
);
|
||||
};
|
||||
|
||||
const testGetFragmentHtml = function () {
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string',
|
||||
'abc',
|
||||
FragmentParser.getFragmentHtml('abc')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input without fragment markers',
|
||||
'abc',
|
||||
FragmentParser.getFragmentHtml('<!-- StartFragment -->abc<!-- EndFragment -->')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers',
|
||||
'abc',
|
||||
FragmentParser.getFragmentHtml('<!--StartFragment-->abc<!--EndFragment-->')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and suffix/prefix contents',
|
||||
'abc',
|
||||
FragmentParser.getFragmentHtml('X<!--StartFragment-->abc<!--EndFragment-->Y')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and suffix/prefix contents',
|
||||
'<B>bold</B><I><B>abc</B>This</I>',
|
||||
FragmentParser.getFragmentHtml('<!DOCTYPE html><BODY><!-- StartFragment --><B>bold</B><I><B>abc</B>This</I><!-- EndFragment --></BODY></HTML>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and suffix/prefix contents',
|
||||
'<LI>abc</LI>',
|
||||
FragmentParser.getFragmentHtml('<BODY><UL><!--StartFragment--><LI>abc</LI><!--EndFragment--></UL></BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string without fragment markers and suffix/prefix contents',
|
||||
'\n<LI>abc</LI>\n',
|
||||
FragmentParser.getFragmentHtml('<BODY>\n<UL>\n<!--StartFragment-->\n<LI>abc</LI>\n<!--EndFragment-->\n</UL>\n</BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string with body element removed',
|
||||
'<UL><LI>abc</LI></UL>',
|
||||
FragmentParser.getFragmentHtml('<!DOCTYPE html><HTML><BODY><UL><LI>abc</LI></UL></BODY></HTML>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string with body element removed',
|
||||
'<UL><LI>abc</LI></UL>',
|
||||
FragmentParser.getFragmentHtml('<BODY CLASS="x"><UL><LI>abc</LI></UL></BODY>')
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'Should be the input string with fragments and body element removed',
|
||||
'<UL><LI>abc</LI></UL>',
|
||||
FragmentParser.getFragmentHtml('<BODY CLASS="x"><!--StartFragment--><UL><LI>abc</LI></UL><!--EndFragment--></BODY>')
|
||||
);
|
||||
};
|
||||
|
||||
testGetFragmentInfo();
|
||||
testGetFragmentHtml();
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import InternalHtml from 'tinymce/plugins/paste/core/InternalHtml';
|
||||
import { UnitTest, assert } from '@ephox/bedrock';
|
||||
|
||||
UnitTest.test('atomic.tinymce.plugins.paste.InternalHtmlTest', function () {
|
||||
const testMark = function () {
|
||||
assert.eq('<!-- x-tinymce/html -->abc', InternalHtml.mark('abc'));
|
||||
};
|
||||
|
||||
const testUnmark = function () {
|
||||
assert.eq('abc', InternalHtml.unmark('<!-- x-tinymce/html -->abc'));
|
||||
assert.eq('abc', InternalHtml.unmark('abc<!-- x-tinymce/html -->'));
|
||||
};
|
||||
|
||||
const testIsMarked = function () {
|
||||
assert.eq(true, InternalHtml.isMarked('<!-- x-tinymce/html -->abc'));
|
||||
assert.eq(true, InternalHtml.isMarked('abc<!-- x-tinymce/html -->'));
|
||||
assert.eq(false, InternalHtml.isMarked('abc'));
|
||||
};
|
||||
|
||||
const testInternalHtmlMime = function () {
|
||||
assert.eq('x-tinymce/html', InternalHtml.internalHtmlMime());
|
||||
};
|
||||
|
||||
testMark();
|
||||
testUnmark();
|
||||
testIsMarked();
|
||||
testInternalHtmlMime();
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
import { Pipeline, Step } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Arr, Cell } from '@ephox/katamari';
|
||||
import { LegacyUnit, TinyLoader } from '@ephox/mcagar';
|
||||
import { Blob, Uint8Array, Window } from '@ephox/sand';
|
||||
|
||||
import Delay from 'tinymce/core/api/util/Delay';
|
||||
import Promise from 'tinymce/core/api/util/Promise';
|
||||
import { Clipboard } from 'tinymce/plugins/paste/api/Clipboard';
|
||||
import Plugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
const suite = LegacyUnit.createSuite();
|
||||
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
const base64ImgSrc = [
|
||||
'R0lGODdhZABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgAAACwAAAAAZABkAIEAAAD78jY/',
|
||||
'P3SsMjIC/4SPqcvtD6OctNqLs968+w+G4kiW5ommR8C27gvHrxrK9g3TIM7f+tcL5n4doZFFLB6F',
|
||||
'Sc6SCRFIp9SqVTp6BiPXbjer5XG95Ck47IuWy2e0bLz2tt3DR5w8p7vgd2tej6TW5ycCGMM3aFZo',
|
||||
'OCOYqFjDuOf4KPAHiPh4qZeZuEnXOfjpFto3ilZ6dxqWGreq1br2+hTLtigZaFcJuYOb67DLC+Qb',
|
||||
'UIt3i2sshyzZtEFc7JwBLT1NXI2drb3N3e39DR4uPk5ebn6Onq6+zu488A4fLz9P335Aj58fb2+g',
|
||||
'71/P759AePwADBxY8KDAhAr9MWyY7yFEgPYmRgxokWK7jEYa2XGcJ/HjgJAfSXI0mRGlRZUTWUJ0',
|
||||
'2RCmQpkHaSLEKPKdzYU4c+78VzCo0KFEixo9ijSp0qVMmzp9CjWq1KlUq1q9eqEAADs='
|
||||
].join('');
|
||||
const base64ImgSrc2 = [
|
||||
'R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='
|
||||
].join('');
|
||||
|
||||
const sTeardown = function (editor) {
|
||||
return Step.sync(function () {
|
||||
delete editor.settings.paste_data_images;
|
||||
delete editor.settings.images_dataimg_filter;
|
||||
editor.editorUpload.destroy();
|
||||
});
|
||||
};
|
||||
|
||||
const appendTeardown = function (editor, steps) {
|
||||
return Arr.bind(steps, function (step) {
|
||||
return [step, sTeardown(editor)];
|
||||
});
|
||||
};
|
||||
|
||||
const base64ToBlob = function (base64, type) {
|
||||
const buff = Window.atob(base64);
|
||||
const bytes = Uint8Array(buff.length);
|
||||
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = buff.charCodeAt(i);
|
||||
}
|
||||
|
||||
return Blob([bytes], { type });
|
||||
};
|
||||
|
||||
const noop = function () {
|
||||
};
|
||||
|
||||
const mockEvent = function (type, files) {
|
||||
let event, transferName;
|
||||
|
||||
event = {
|
||||
type,
|
||||
preventDefault: noop
|
||||
};
|
||||
|
||||
transferName = type === 'drop' ? 'dataTransfer' : 'clipboardData';
|
||||
event[transferName] = {
|
||||
files
|
||||
};
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
const setupContent = function (editor) {
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0);
|
||||
return editor.selection.getRng();
|
||||
};
|
||||
|
||||
const waitFor = function (predicate) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const check = function (time, count) {
|
||||
if (predicate()) {
|
||||
resolve();
|
||||
} else {
|
||||
if (count === 0) {
|
||||
reject(new Error('Waited for predicate to be true'));
|
||||
} else {
|
||||
Delay.setTimeout(function () {
|
||||
check(time, count - 1);
|
||||
}, time);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
check(10, 100);
|
||||
});
|
||||
};
|
||||
|
||||
const waitForSelector = function (editor, selector) {
|
||||
return waitFor(() => editor.dom.select(selector).length > 0);
|
||||
};
|
||||
|
||||
suite.asyncTest('pasteImages should set unique id in blobcache', function (editor, done, die) {
|
||||
let rng, event;
|
||||
const clipboard = Clipboard(editor, Cell('html'));
|
||||
|
||||
const hasCachedItem = (name) => !!editor.editorUpload.blobCache.get(name);
|
||||
|
||||
editor.settings.paste_data_images = true;
|
||||
rng = setupContent(editor);
|
||||
|
||||
event = mockEvent('paste', [
|
||||
base64ToBlob(base64ImgSrc, 'image/gif'),
|
||||
base64ToBlob(base64ImgSrc2, 'image/gif')
|
||||
]);
|
||||
clipboard.pasteImageData(event, rng);
|
||||
|
||||
waitForSelector(editor, 'img').then(function () {
|
||||
waitFor((editor) => hasCachedItem('mceclip0') && hasCachedItem('mceclip1')).then(() => {
|
||||
const cachedBlob1 = editor.editorUpload.blobCache.get('mceclip0');
|
||||
const cachedBlob2 = editor.editorUpload.blobCache.get('mceclip1');
|
||||
LegacyUnit.equal(base64ImgSrc, cachedBlob1.base64());
|
||||
LegacyUnit.equal(base64ImgSrc2, cachedBlob2.base64());
|
||||
|
||||
done();
|
||||
}).catch(die);
|
||||
}).catch(die);
|
||||
});
|
||||
|
||||
suite.asyncTest('dropImages', function (editor, done, die) {
|
||||
let rng, event;
|
||||
const clipboard = Clipboard(editor, Cell('html'));
|
||||
|
||||
editor.settings.paste_data_images = true;
|
||||
rng = setupContent(editor);
|
||||
|
||||
event = mockEvent('drop', [
|
||||
base64ToBlob(base64ImgSrc, 'image/gif')
|
||||
]);
|
||||
clipboard.pasteImageData(event, rng);
|
||||
|
||||
waitForSelector(editor, 'img').then(function () {
|
||||
LegacyUnit.equal(editor.getContent(), '<p><img src=\"data:image/gif;base64,' + base64ImgSrc + '" />a</p>');
|
||||
LegacyUnit.strictEqual(editor.dom.select('img')[0].src.indexOf('blob:'), 0);
|
||||
|
||||
done();
|
||||
}).catch(die);
|
||||
});
|
||||
|
||||
suite.asyncTest('pasteImages', function (editor, done, die) {
|
||||
let rng, event;
|
||||
const clipboard = Clipboard(editor, Cell('html'));
|
||||
|
||||
editor.settings.paste_data_images = true;
|
||||
rng = setupContent(editor);
|
||||
|
||||
event = mockEvent('paste', [
|
||||
base64ToBlob(base64ImgSrc, 'image/gif')
|
||||
]);
|
||||
clipboard.pasteImageData(event, rng);
|
||||
|
||||
waitForSelector(editor, 'img').then(function () {
|
||||
LegacyUnit.equal(editor.getContent(), '<p><img src=\"data:image/gif;base64,' + base64ImgSrc + '" />a</p>');
|
||||
LegacyUnit.strictEqual(editor.dom.select('img')[0].src.indexOf('blob:'), 0);
|
||||
|
||||
done();
|
||||
}).catch(die);
|
||||
});
|
||||
|
||||
suite.asyncTest('dropImages - images_dataimg_filter', function (editor, done, die) {
|
||||
let rng, event;
|
||||
const clipboard = Clipboard(editor, Cell('html'));
|
||||
|
||||
editor.settings.paste_data_images = true;
|
||||
editor.settings.images_dataimg_filter = function (img) {
|
||||
LegacyUnit.strictEqual(img.src, 'data:image/gif;base64,' + base64ImgSrc);
|
||||
return false;
|
||||
};
|
||||
rng = setupContent(editor);
|
||||
|
||||
event = mockEvent('drop', [
|
||||
base64ToBlob(base64ImgSrc, 'image/gif')
|
||||
]);
|
||||
clipboard.pasteImageData(event, rng);
|
||||
|
||||
waitForSelector(editor, 'img').then(function () {
|
||||
LegacyUnit.equal(editor.getContent(), '<p><img src=\"data:image/gif;base64,' + base64ImgSrc + '" />a</p>');
|
||||
LegacyUnit.strictEqual(editor.dom.select('img')[0].src.indexOf('data:'), 0);
|
||||
|
||||
done();
|
||||
}).catch(die);
|
||||
});
|
||||
|
||||
suite.asyncTest('pasteImages - images_dataimg_filter', function (editor, done, die) {
|
||||
let rng, event;
|
||||
const clipboard = Clipboard(editor, Cell('html'));
|
||||
|
||||
editor.settings.paste_data_images = true;
|
||||
editor.settings.images_dataimg_filter = function (img) {
|
||||
LegacyUnit.strictEqual(img.src, 'data:image/gif;base64,' + base64ImgSrc);
|
||||
return false;
|
||||
};
|
||||
rng = setupContent(editor);
|
||||
|
||||
event = mockEvent('paste', [
|
||||
base64ToBlob(base64ImgSrc, 'image/gif')
|
||||
]);
|
||||
clipboard.pasteImageData(event, rng);
|
||||
|
||||
waitForSelector(editor, 'img').then(function () {
|
||||
LegacyUnit.equal(editor.getContent(), '<p><img src=\"data:image/gif;base64,' + base64ImgSrc + '" />a</p>');
|
||||
LegacyUnit.strictEqual(editor.dom.select('img')[0].src.indexOf('data:'), 0);
|
||||
|
||||
done();
|
||||
}).catch(die);
|
||||
});
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
Pipeline.async({}, appendTeardown(editor, suite.toSteps(editor)), onSuccess, onFailure);
|
||||
}, {
|
||||
add_unload_trigger: false,
|
||||
disable_nodechange: true,
|
||||
entities: 'raw',
|
||||
indent: false,
|
||||
automatic_uploads: false,
|
||||
plugins: 'paste',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,240 @@
|
||||
import { GeneralSteps, Logger, Pipeline, RawAssertions, Step, Waiter } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import InternalHtml from 'tinymce/plugins/paste/core/InternalHtml';
|
||||
import Utils from 'tinymce/plugins/paste/core/Utils';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import TablePlugin from 'tinymce/plugins/table/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import MockDataTransfer from '../module/test/MockDataTransfer';
|
||||
|
||||
UnitTest.asynctest('browser.tinymce.plugins.paste.InternalClipboardTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
let dataTransfer, lastPreProcessEvent, lastPostProcessEvent;
|
||||
|
||||
PastePlugin();
|
||||
TablePlugin();
|
||||
Theme();
|
||||
|
||||
const sResetProcessEvents = Step.sync(function () {
|
||||
lastPreProcessEvent = null;
|
||||
lastPostProcessEvent = null;
|
||||
});
|
||||
|
||||
const sCutCopyDataTransferEvent = function (editor, type) {
|
||||
return Step.sync(function () {
|
||||
dataTransfer = MockDataTransfer.create({});
|
||||
editor.fire(type, { clipboardData: dataTransfer });
|
||||
});
|
||||
};
|
||||
|
||||
const sPasteDataTransferEvent = function (editor, data) {
|
||||
return Step.sync(function () {
|
||||
dataTransfer = MockDataTransfer.create(data);
|
||||
editor.fire('paste', { clipboardData: dataTransfer });
|
||||
});
|
||||
};
|
||||
|
||||
const sAssertClipboardData = function (expectedHtml, expectedText) {
|
||||
return Step.sync(function () {
|
||||
RawAssertions.assertEq('text/html data should match', expectedHtml, dataTransfer.getData('text/html'));
|
||||
RawAssertions.assertEq('text/plain data should match', expectedText, dataTransfer.getData('text/plain'));
|
||||
});
|
||||
};
|
||||
|
||||
const sCopy = function (editor, tinyApis, html, spath, soffset, fpath, foffset) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(html),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sCutCopyDataTransferEvent(editor, 'copy')
|
||||
]);
|
||||
};
|
||||
|
||||
const sCut = function (editor, tinyApis, html, spath, soffset, fpath, foffset) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(html),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sCutCopyDataTransferEvent(editor, 'cut')
|
||||
]);
|
||||
};
|
||||
|
||||
const sPaste = function (editor, tinyApis, startHtml, pasteData, spath, soffset, fpath, foffset) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(startHtml),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sResetProcessEvents,
|
||||
sPasteDataTransferEvent(editor, pasteData)
|
||||
]);
|
||||
};
|
||||
|
||||
const sTestCopy = function (editor, tinyApis) {
|
||||
return Logger.t('Copy tests', GeneralSteps.sequence([
|
||||
Logger.t('Copy simple text', GeneralSteps.sequence([
|
||||
sCopy(editor, tinyApis, '<p>text</p>', [0, 0], 0, [0, 0], 4),
|
||||
sAssertClipboardData('text', 'text'),
|
||||
tinyApis.sAssertContent('<p>text</p>'),
|
||||
tinyApis.sAssertSelection([0, 0], 0, [0, 0], 4)
|
||||
])),
|
||||
|
||||
Logger.t('Copy inline elements', GeneralSteps.sequence([
|
||||
sCopy(editor, tinyApis, '<p>te<em>x</em>t</p>', [0, 0], 0, [0, 2], 1),
|
||||
sAssertClipboardData('te<em>x</em>t', 'text'),
|
||||
tinyApis.sAssertContent('<p>te<em>x</em>t</p>'),
|
||||
tinyApis.sAssertSelection([0, 0], 0, [0, 2], 1)
|
||||
])),
|
||||
|
||||
Logger.t('Copy partialy selected inline elements', GeneralSteps.sequence([
|
||||
sCopy(editor, tinyApis, '<p>a<em>cd</em>e</p>', [0, 0], 0, [0, 1, 0], 1),
|
||||
sAssertClipboardData('a<em>c</em>', 'ac'),
|
||||
tinyApis.sAssertContent('<p>a<em>cd</em>e</p>'),
|
||||
tinyApis.sAssertSelection([0, 0], 0, [0, 1, 0], 1)
|
||||
])),
|
||||
|
||||
Logger.t('Copy collapsed selection', GeneralSteps.sequence([
|
||||
sCopy(editor, tinyApis, '<p>abc</p>', [0, 0], 1, [0, 0], 1),
|
||||
sAssertClipboardData('', ''),
|
||||
tinyApis.sAssertContent('<p>abc</p>'),
|
||||
tinyApis.sAssertSelection([0, 0], 1, [0, 0], 1)
|
||||
])),
|
||||
|
||||
Logger.t('Copy collapsed selection with table selection', GeneralSteps.sequence([
|
||||
sCopy(editor, tinyApis,
|
||||
'<table data-mce-selected="1">' +
|
||||
'<tbody>' +
|
||||
'<tr>' +
|
||||
'<td data-mce-first-selected="1" data-mce-selected="1">a</td>' +
|
||||
'<td data-mce-last-selected="1" data-mce-selected="1">b</td>' +
|
||||
'</tr>' +
|
||||
'</tbody>' +
|
||||
'</table>',
|
||||
[0, 0, 0, 1, 0], 0, [0, 0, 0, 1, 0], 0),
|
||||
sAssertClipboardData(
|
||||
'<table>\n' +
|
||||
'<tbody>\n' +
|
||||
'<tr>\n' +
|
||||
'<td>a</td>\n' +
|
||||
'<td>b</td>\n' +
|
||||
'</tr>\n' +
|
||||
'</tbody>\n' +
|
||||
'</table>', 'ab'),
|
||||
tinyApis.sAssertSelection([0, 0, 0, 1, 0], 0, [0, 0, 0, 1, 0], 0)
|
||||
]))
|
||||
]));
|
||||
};
|
||||
|
||||
const sTestCut = function (editor, tinyApis) {
|
||||
const sWaitUntilAssertContent = function (expected) {
|
||||
return Waiter.sTryUntil('Cut is async now, so need to wait for content', tinyApis.sAssertContent(expected), 100, 1000);
|
||||
};
|
||||
|
||||
return Logger.t('Cut tests', GeneralSteps.sequence([
|
||||
Logger.t('Cut simple text', GeneralSteps.sequence([
|
||||
sCut(editor, tinyApis, '<p>text</p>', [0, 0], 0, [0, 0], 4),
|
||||
sAssertClipboardData('text', 'text'),
|
||||
sWaitUntilAssertContent(''),
|
||||
tinyApis.sAssertSelection([0], 0, [0], 0)
|
||||
])),
|
||||
|
||||
Logger.t('Cut inline elements', GeneralSteps.sequence([
|
||||
sCut(editor, tinyApis, '<p>te<em>x</em>t</p>', [0, 0], 0, [0, 2], 1),
|
||||
sAssertClipboardData('te<em>x</em>t', 'text'),
|
||||
sWaitUntilAssertContent(''),
|
||||
tinyApis.sAssertSelection([0], 0, [0], 0)
|
||||
])),
|
||||
|
||||
Logger.t('Cut partialy selected inline elements', GeneralSteps.sequence([
|
||||
sCut(editor, tinyApis, '<p>a<em>cd</em>e</p>', [0, 0], 0, [0, 1, 0], 1),
|
||||
sAssertClipboardData('a<em>c</em>', 'ac'),
|
||||
sWaitUntilAssertContent('<p><em>d</em>e</p>'),
|
||||
tinyApis.sAssertSelection([0, 0, 0], 0, [0, 0, 0], 0)
|
||||
])),
|
||||
|
||||
Logger.t('Cut collapsed selection', GeneralSteps.sequence([
|
||||
sCut(editor, tinyApis, '<p>abc</p>', [0, 0], 1, [0, 0], 1),
|
||||
sAssertClipboardData('', ''),
|
||||
sWaitUntilAssertContent('<p>abc</p>'),
|
||||
tinyApis.sAssertSelection([0, 0], 1, [0, 0], 1)
|
||||
]))
|
||||
]));
|
||||
};
|
||||
|
||||
const sAssertLastPreProcessEvent = function (expectedData) {
|
||||
return Step.sync(function () {
|
||||
RawAssertions.assertEq('Internal property should be equal', expectedData.internal, lastPreProcessEvent.internal);
|
||||
RawAssertions.assertEq('Content property should be equal', expectedData.content, lastPreProcessEvent.content);
|
||||
});
|
||||
};
|
||||
|
||||
const sAssertLastPostProcessEvent = function (expectedData) {
|
||||
return Step.sync(function () {
|
||||
RawAssertions.assertEq('Internal property should be equal', expectedData.internal, lastPostProcessEvent.internal);
|
||||
RawAssertions.assertEq('Content property should be equal', expectedData.content, lastPostProcessEvent.node.innerHTML);
|
||||
});
|
||||
};
|
||||
|
||||
const sWaitForProcessEvents = Waiter.sTryUntil('Did not get any events fired', Step.sync(function () {
|
||||
RawAssertions.assertEq('PastePreProcess event object', lastPreProcessEvent !== null, true);
|
||||
RawAssertions.assertEq('PastePostProcess event object', lastPostProcessEvent !== null, true);
|
||||
}), 100, 100);
|
||||
|
||||
const sTestPaste = function (editor, tinyApis) {
|
||||
return Logger.t('Paste tests', GeneralSteps.sequence([
|
||||
Logger.t('Paste external content', GeneralSteps.sequence([
|
||||
sPaste(editor, tinyApis, '<p>abc</p>', { 'text/plain': 'X', 'text/html': '<p>X</p>' }, [0, 0], 0, [0, 0], 3),
|
||||
sWaitForProcessEvents,
|
||||
sAssertLastPreProcessEvent({ internal: false, content: 'X' }),
|
||||
sAssertLastPostProcessEvent({ internal: false, content: 'X' })
|
||||
])),
|
||||
|
||||
Logger.t('Paste external content treated as plain text', GeneralSteps.sequence([
|
||||
sPaste(editor, tinyApis, '<p>abc</p>', { 'text/html': '<p>X</p>' }, [0, 0], 0, [0, 0], 3),
|
||||
sWaitForProcessEvents,
|
||||
sAssertLastPreProcessEvent({ internal: false, content: 'X' }),
|
||||
sAssertLastPostProcessEvent({ internal: false, content: 'X' })
|
||||
])),
|
||||
|
||||
Logger.t('Paste internal content with mark', GeneralSteps.sequence([
|
||||
sPaste(editor, tinyApis, '<p>abc</p>', { 'text/plain': 'X', 'text/html': InternalHtml.mark('<p>X</p>') }, [0, 0], 0, [0, 0], 3),
|
||||
sWaitForProcessEvents,
|
||||
sAssertLastPreProcessEvent({ internal: true, content: '<p>X</p>' }),
|
||||
sAssertLastPostProcessEvent({ internal: true, content: '<p>X</p>' })
|
||||
])),
|
||||
|
||||
Logger.t('Paste internal content with mime', GeneralSteps.sequence([
|
||||
sPaste(editor, tinyApis, '<p>abc</p>',
|
||||
{ 'text/plain': 'X', 'text/html': '<p>X</p>', 'x-tinymce/html': '<p>X</p>' },
|
||||
[0, 0], 0, [0, 0], 3
|
||||
),
|
||||
sWaitForProcessEvents,
|
||||
sAssertLastPreProcessEvent({ internal: true, content: '<p>X</p>' }),
|
||||
sAssertLastPostProcessEvent({ internal: true, content: '<p>X</p>' })
|
||||
]))
|
||||
]));
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const tinyApis = TinyApis(editor);
|
||||
|
||||
// Disabled tests on Edge 15 due to broken clipboard API
|
||||
Pipeline.async({}, Utils.isMsEdge() ? [ ] : [
|
||||
sTestCopy(editor, tinyApis),
|
||||
sTestCut(editor, tinyApis),
|
||||
sTestPaste(editor, tinyApis)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
plugins: 'paste table',
|
||||
init_instance_callback (editor) {
|
||||
editor.on('PastePreProcess', function (evt) {
|
||||
lastPreProcessEvent = evt;
|
||||
});
|
||||
|
||||
editor.on('PastePostProcess', function (evt) {
|
||||
lastPostProcessEvent = evt;
|
||||
});
|
||||
},
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Assertions } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Arr } from '@ephox/katamari';
|
||||
|
||||
import Newlines from 'tinymce/plugins/paste/core/Newlines';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
UnitTest.test('tinymce.plugins.paste.browser.NewlinesTest', function () {
|
||||
Theme();
|
||||
PastePlugin();
|
||||
|
||||
// testing Newlines.isPlainText()
|
||||
const textCases = [
|
||||
{
|
||||
label: 'Basic Chrome markup (including span-wrapped tab)',
|
||||
content: '<div><span style="white-space:pre"> </span>a</div><div><br></div><div>b</div>',
|
||||
isText: true
|
||||
},
|
||||
{
|
||||
label: 'Case shouldn\'t matter',
|
||||
content: '<DIV>a</DIV><DIV><BR></DIV>',
|
||||
isText: true
|
||||
},
|
||||
{
|
||||
label: 'Support all BR types',
|
||||
content: '<br><br />',
|
||||
isText: true
|
||||
},
|
||||
{
|
||||
label: 'Basic IE markup',
|
||||
content: '<p>a</p><p><br></p><p>b</p>',
|
||||
isText: true
|
||||
},
|
||||
{
|
||||
label: 'White-space wrapper (Chrome)',
|
||||
content: '<div><span style="white-space: pre;"> </span>a</div>',
|
||||
isText: true
|
||||
},
|
||||
{
|
||||
label: 'White-space wrapper (Chrome) with additional styles',
|
||||
content: '<div><span style="white-space: pre; color: red;"> </span>a</div>',
|
||||
isText: false
|
||||
},
|
||||
{
|
||||
label: 'Allowed tag but with attributes qualifies string as not a plain text',
|
||||
content: '<br data-mce-bogus="all" />',
|
||||
isText: false
|
||||
}
|
||||
];
|
||||
|
||||
// only DIV,P,BR and SPAN[style="white-space:pre"] tags are allowed in "plain text" string
|
||||
Arr.each('a,abbr,address,article,aside,audio,b,bdi,bdo,blockquote,button,cite,code,del,details,dfn,dl,em,embed,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,i,ins,label,menu,nav,noscript,object,ol,pre,q,s,script,section,select,small,strong,style,sub,sup,svg,table,textarea,time,u,ul,var,video,wbr'.split(','),
|
||||
function (tag) {
|
||||
const content = '<p>a</p><' + tag + '>b</' + tag + '><p>c<br>d</p>';
|
||||
textCases.push({
|
||||
label: tag.toUpperCase() + ' tag should qualify content (' + content + ') as not a plain text',
|
||||
content,
|
||||
isText: false
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Arr.each(textCases, function (c) {
|
||||
Assertions.assertEq(c.label || 'Asserting: ' + c.content, c.isText, Newlines.isPlainText(c.content));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import { Assertions, Chain, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Id, Merger, Obj } from '@ephox/katamari';
|
||||
|
||||
import EditorManager from 'tinymce/core/api/EditorManager';
|
||||
import { PasteBin, getPasteBinParent } from 'tinymce/plugins/paste/core/PasteBin';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import ViewBlock from '../module/test/ViewBlock';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.PasteBin', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
|
||||
Theme();
|
||||
PastePlugin();
|
||||
|
||||
const cases = [
|
||||
{
|
||||
label: 'TINY-1162: testing nested paste bins',
|
||||
content: '<div id="mcepastebin" contenteditable="true" data-mce-bogus="all" data-mce-style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0" style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0"><div id="mcepastebin" data-mce-bogus="all" data-mce-style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0" style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0">a</div><div id="mcepastebin" data-mce-bogus="all" data-mce-style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0" style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0">b</div></div>',
|
||||
result: '<div>a</div><div>b</div>'
|
||||
},
|
||||
{
|
||||
label: 'TINY-1162: testing adjacent paste bins',
|
||||
content: '<div id="mcepastebin" contenteditable="true" data-mce-bogus="all" data-mce-style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0" style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0"><p>a</p><p>b</p></div><div id="mcepastebin" contenteditable="true" data-mce-bogus="all" data-mce-style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0" style="position: absolute; top: 0.40000057220458984px;width: 10px; height: 10px; overflow: hidden; opacity: 0"><p>c</p></div>',
|
||||
result: '<p>a</p><p>b</p><p>c</p>'
|
||||
}
|
||||
];
|
||||
|
||||
const viewBlock = ViewBlock();
|
||||
|
||||
const cCreateEditorFromSettings = function (settings?, html?) {
|
||||
return Chain.async(function (viewBlock: any, next, die) {
|
||||
const randomId = Id.generate('tiny');
|
||||
html = html || '<textarea></textarea>';
|
||||
|
||||
viewBlock.update(html);
|
||||
viewBlock.get().firstChild.id = randomId;
|
||||
|
||||
EditorManager.init(Merger.merge(settings || {}, {
|
||||
selector: '#' + randomId,
|
||||
add_unload_trigger: false,
|
||||
indent: false,
|
||||
plugins: 'paste',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray',
|
||||
setup (editor) {
|
||||
editor.on('SkinLoaded', function () {
|
||||
setTimeout(function () {
|
||||
next(editor);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
const cCreateEditorFromHtml = function (html, settings) {
|
||||
return cCreateEditorFromSettings(settings, html);
|
||||
};
|
||||
|
||||
const cRemoveEditor = function () {
|
||||
return Chain.op(function (editor: any) {
|
||||
editor.remove();
|
||||
});
|
||||
};
|
||||
|
||||
const cAssertCases = function (cases) {
|
||||
return Chain.op(function (editor: any) {
|
||||
const pasteBin = PasteBin(editor);
|
||||
Obj.each(cases, function (c, i) {
|
||||
getPasteBinParent(editor).appendChild(editor.dom.createFragment(c.content));
|
||||
Assertions.assertEq(c.label || 'Asserting paste bin case ' + i, c.result, pasteBin.getHtml());
|
||||
pasteBin.remove();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
viewBlock.attach();
|
||||
|
||||
Pipeline.async({}, [
|
||||
Chain.asStep(viewBlock, [
|
||||
cCreateEditorFromSettings(),
|
||||
cAssertCases(cases),
|
||||
cRemoveEditor()
|
||||
]),
|
||||
|
||||
// TINY-1208/TINY-1209: same cases, but for inline editor
|
||||
Chain.asStep(viewBlock, [
|
||||
cCreateEditorFromHtml('<div>some text</div>', { inline: true }),
|
||||
cAssertCases(cases),
|
||||
cRemoveEditor()
|
||||
])
|
||||
], function () {
|
||||
viewBlock.detach();
|
||||
success();
|
||||
}, failure);
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { GeneralSteps, Logger, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import Env from 'tinymce/core/api/Env';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import ModernTheme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import Paste from '../module/test/Paste';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.PasteFormatToggleTest', (success, failure) => {
|
||||
ModernTheme();
|
||||
PastePlugin();
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const tinyApis = TinyApis(editor);
|
||||
const steps = Env.webkit ? [
|
||||
Logger.t('paste plain text',
|
||||
GeneralSteps.sequence([
|
||||
tinyApis.sExecCommand('mceTogglePlainTextPaste'),
|
||||
Paste.sPaste(editor, { 'text/html': '<p><strong>test</strong></p>'}),
|
||||
tinyApis.sAssertContent('<p>test</p>'),
|
||||
tinyApis.sSetContent(''),
|
||||
tinyApis.sExecCommand('mceTogglePlainTextPaste'),
|
||||
Paste.sPaste(editor, { 'text/html': '<p><strong>test</strong></p>'}),
|
||||
tinyApis.sAssertContent('<p><strong>test</strong></p>')
|
||||
])
|
||||
)
|
||||
] : [];
|
||||
|
||||
Pipeline.async({}, steps, onSuccess, onFailure);
|
||||
}, {
|
||||
plugins: 'paste',
|
||||
toolbar: '',
|
||||
valid_styles: 'font-family,color',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Assertions, Chain, Logger, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Merger } from '@ephox/katamari';
|
||||
|
||||
import EditorManager from 'tinymce/core/api/EditorManager';
|
||||
import Plugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import ViewBlock from '../module/test/ViewBlock';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.PasteSettingsTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
const viewBlock = ViewBlock();
|
||||
|
||||
Theme();
|
||||
Plugin();
|
||||
|
||||
const cCreateInlineEditor = function (settings) {
|
||||
return Chain.async(function (viewBlock: any, next, die) {
|
||||
viewBlock.update('<div id="inline-tiny"></div>');
|
||||
|
||||
EditorManager.init(Merger.merge({
|
||||
selector: '#inline-tiny',
|
||||
inline: true,
|
||||
skin_url: '/project/js/tinymce/skins/lightgray',
|
||||
setup (editor) {
|
||||
editor.on('SkinLoaded', function () {
|
||||
next(editor);
|
||||
});
|
||||
}
|
||||
}, settings));
|
||||
});
|
||||
};
|
||||
|
||||
const cRemoveEditor = Chain.op(function (editor: any) {
|
||||
editor.remove();
|
||||
});
|
||||
|
||||
viewBlock.attach();
|
||||
Pipeline.async({}, [
|
||||
Logger.t('paste_as_text setting', Chain.asStep(viewBlock, [
|
||||
cCreateInlineEditor({
|
||||
paste_as_text: true,
|
||||
plugins: 'paste'
|
||||
}),
|
||||
Chain.op(function (editor) {
|
||||
Assertions.assertEq('Should be text format', 'text', editor.plugins.paste.clipboard.pasteFormat.get());
|
||||
}),
|
||||
cRemoveEditor
|
||||
]))
|
||||
], function () {
|
||||
viewBlock.detach();
|
||||
success();
|
||||
}, failure);
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { GeneralSteps, Logger, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import Env from 'tinymce/core/api/Env';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import ModernTheme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import Paste from '../module/test/Paste';
|
||||
|
||||
UnitTest.asynctest('Browser Test: .PasteStylesTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
|
||||
ModernTheme();
|
||||
PastePlugin();
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const tinyApis = TinyApis(editor);
|
||||
const steps = Env.webkit ? [
|
||||
Logger.t('Paste span with encoded style attribute, paste_webkit_styles: font-family',
|
||||
GeneralSteps.sequence([
|
||||
tinyApis.sSetSetting('paste_webkit_styles', 'font-family'),
|
||||
tinyApis.sSetContent('<p>test</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 4),
|
||||
Paste.sPaste(editor, { 'text/html': '<span style="font-family: "a b";color:green;">b</span>' }),
|
||||
tinyApis.sAssertContent('<p><span style="font-family: \'a b\';">b</span></p>')
|
||||
])
|
||||
),
|
||||
|
||||
Logger.t('Paste span with encoded style attribute, paste_webkit_styles: all',
|
||||
GeneralSteps.sequence([
|
||||
tinyApis.sSetSetting('paste_webkit_styles', 'all'),
|
||||
tinyApis.sSetContent('<p>test</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 4),
|
||||
Paste.sPaste(editor, { 'text/html': '<span style="font-family: "a b"; color: green;">b</span>' }),
|
||||
tinyApis.sAssertContent('<p><span style="font-family: \'a b\'; color: green;">b</span></p>')
|
||||
])
|
||||
),
|
||||
|
||||
Logger.t('Paste span with encoded style attribute, paste_webkit_styles: none',
|
||||
GeneralSteps.sequence([
|
||||
tinyApis.sSetSetting('paste_webkit_styles', 'none'),
|
||||
tinyApis.sSetContent('<p>test</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 4),
|
||||
Paste.sPaste(editor, { 'text/html': '<span style="font-family: "a b";">b</span>' }),
|
||||
tinyApis.sAssertContent('<p>b</p>')
|
||||
])
|
||||
),
|
||||
|
||||
Logger.t('Paste span with encoded style attribute, paste_remove_styles_if_webkit: false',
|
||||
GeneralSteps.sequence([
|
||||
tinyApis.sSetSetting('paste_remove_styles_if_webkit', false),
|
||||
tinyApis.sSetContent('<p>test</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 4),
|
||||
Paste.sPaste(editor, { 'text/html': '<span style="font-family: "a b";">b</span>' }),
|
||||
tinyApis.sAssertContent('<p><span style="font-family: \'a b\';">b</span></p>')
|
||||
])
|
||||
)
|
||||
] : [];
|
||||
|
||||
Pipeline.async({}, steps, onSuccess, onFailure);
|
||||
}, {
|
||||
plugins: 'paste',
|
||||
toolbar: '',
|
||||
valid_styles: 'font-family,color',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
879
public/tinymce/src/plugins/paste/test/ts/browser/PasteTest.ts
Normal file
879
public/tinymce/src/plugins/paste/test/ts/browser/PasteTest.ts
Normal file
@@ -0,0 +1,879 @@
|
||||
import { Pipeline, Step } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Arr } from '@ephox/katamari';
|
||||
import { LegacyUnit, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import Env from 'tinymce/core/api/Env';
|
||||
import Utils from 'tinymce/plugins/paste/core/Utils';
|
||||
import Plugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import Strings from '../module/test/Strings';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
const suite = LegacyUnit.createSuite();
|
||||
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
const sTeardown = function (editor) {
|
||||
return Step.sync(function () {
|
||||
delete editor.settings.paste_remove_styles_if_webkit;
|
||||
delete editor.settings.paste_retain_style_properties;
|
||||
delete editor.settings.paste_enable_default_filters;
|
||||
delete editor.settings.paste_data_images;
|
||||
delete editor.settings.paste_webkit_styles;
|
||||
});
|
||||
};
|
||||
|
||||
const appendTeardown = function (editor, steps) {
|
||||
return Arr.bind(steps, function (step) {
|
||||
return [step, sTeardown(editor)];
|
||||
});
|
||||
};
|
||||
|
||||
const trimContent = function (content) {
|
||||
return content.replace(/^<p> <\/p>\n?/, '').replace(/\n?<p> <\/p>$/, '');
|
||||
};
|
||||
|
||||
suite.test('Plain text toggle event', function (editor) {
|
||||
const events = [];
|
||||
|
||||
editor.on('PastePlainTextToggle', function (e) {
|
||||
events.push({ state: e.state });
|
||||
});
|
||||
|
||||
editor.execCommand('mceTogglePlainTextPaste');
|
||||
LegacyUnit.deepEqual(events, [
|
||||
{ state: true }
|
||||
], 'Should be enabled');
|
||||
|
||||
editor.execCommand('mceTogglePlainTextPaste');
|
||||
LegacyUnit.deepEqual(events, [
|
||||
{ state: true },
|
||||
{ state: false }
|
||||
], 'Should be disabled');
|
||||
|
||||
editor.execCommand('mceTogglePlainTextPaste');
|
||||
LegacyUnit.deepEqual(events, [
|
||||
{ state: true },
|
||||
{ state: false },
|
||||
{ state: true }
|
||||
], 'Should be enabled again');
|
||||
});
|
||||
|
||||
suite.test('Paste simple text content', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
editor.focus();
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 1);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 3);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: 'TEST' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1TEST4</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste text with meta and nbsp', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1 </p>');
|
||||
editor.focus();
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 2);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 2);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<meta charset="utf-8">TEST' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1 TEST</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste styled text content', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.settings.paste_remove_styles_if_webkit = false;
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 1);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 3);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<strong><em><span style="color: red;">TEST</span></em></strong>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1<strong><em><span style="color: red;">TEST</span></em></strong>4</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste paragraph in paragraph', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 1);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 3);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p>TEST</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1</p><p>TEST</p><p>4</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste paragraphs in complex paragraph', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p><strong><em>1234</em></strong></p>');
|
||||
rng.setStart(editor.dom.select('em,i')[0].firstChild, 1);
|
||||
rng.setEnd(editor.dom.select('em,i')[0].firstChild, 3);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p>TEST 1</p><p>TEST 2</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><strong><em>1</em></strong></p><p>TEST 1</p><p>TEST 2</p><p><strong><em>4</em></strong></p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word fake list', function (editor) {
|
||||
let rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: Strings.wordList2 });
|
||||
LegacyUnit.equal(editor.getContent(), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul>');
|
||||
|
||||
editor.settings.paste_retain_style_properties = 'border';
|
||||
|
||||
rng = editor.dom.createRng();
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="ListStyle" style="margin-top:0cm;margin-right:0cm;margin-bottom:3.0pt;margin-left:18.0pt;mso-add-space:auto;text-align:justify;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 18.0pt"><span lang="DE" style="font-family:Verdana;mso-fareast-font-family:Verdana;mso-bidi-font-family:Verdana;color:black"><span style="mso-list:Ignore">\u25CF<span style="font:7.0pt "Times New Roman""> </span></span></span><span lang="DE" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black">Item Spaces.<o:p></o:p></span></p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<ul><li>Item Spaces.</li></ul>');
|
||||
|
||||
rng = editor.dom.createRng();
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="ListStyle" style="margin-left:36.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"><span lang="EN-US" style="color:black;mso-ansi-language:EN-US"><span style="mso-list:Ignore">1.<span style="font:7.0pt "Times New Roman""> </span></span></span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">Version 7.0</span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">:<o:p></o:p></span></p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<ol><li>Version 7.0:</li></ol>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word fake list before BR', function (editor) {
|
||||
let rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertContent', false, '<br>a');
|
||||
|
||||
rng = editor.dom.createRng();
|
||||
rng.setStart(editor.getBody().firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild, 0);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: Strings.wordList1 });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul><p><br />a</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word fake lists interrupted by header', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class=MsoListParagraphCxSpFirst style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family: Symbol\'><span style=\'mso-list:Ignore\'>·<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>List before heading A<o:p></o:p></p> <p class=MsoListParagraphCxSpLast style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family: Symbol\'><span style=\'mso-list:Ignore\'>·<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>List before heading B<o:p></o:p></p> <h1>heading<o:p></o:p></h1> <p class=MsoListParagraphCxSpFirst style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family: Symbol\'><span style=\'mso-list:Ignore\'>·<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>List after heading A<o:p></o:p></p> <p class=MsoListParagraphCxSpLast style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family: Symbol\'><span style=\'mso-list:Ignore\'>·<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>List after heading B<o:p></o:p></p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<ul><li>List before heading A</li><li>List before heading B</li></ul><h1>heading</h1><ul><li>List after heading A</li><li>List after heading B</li></ul>');
|
||||
});
|
||||
|
||||
suite.test('Paste list like paragraph and list', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: '<p class=MsoNormal><span style=\'font-size:10.0pt;line-height:115%;font-family:"Trebuchet MS","sans-serif";color:#666666\'>ABC. X<o:p></o:p></span></p><p class=MsoListParagraph style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>1.<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>Y</p>'
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>ABC. X</p><ol><li>Y</li></ol>');
|
||||
});
|
||||
|
||||
suite.test('Paste list like paragraph and list (disabled)', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.settings.paste_convert_word_fake_lists = false;
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: '<p class=MsoNormal><span style=\'font-size:10.0pt;line-height:115%;font-family:"Trebuchet MS","sans-serif";color:#666666\'>ABC. X<o:p></o:p></span></p><p class=MsoListParagraph style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>1.<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>Y</p>'
|
||||
});
|
||||
|
||||
delete editor.settings.paste_convert_word_fake_lists;
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>ABC. X</p><p>1. Y</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word table', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: Strings.table });
|
||||
LegacyUnit.equal(editor.getContent(), '<table><tbody><tr><td width="307"><p>Cell 1</p></td><td width="307"><p>Cell 2</p></td></tr><tr><td width="307"><p>Cell 3</p></td><td width="307"><p>Cell 4</p></td></tr></tbody></table><p> </p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Office 365', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<div class="OutlineElement Ltr SCX195156559">Test</div>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>Test</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Google Docs 1', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span id="docs-internal-guid-94e46f1a-1c88-b42b-d502-1d19da30dde7"></span><p dir="ltr>Test</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>Test</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Google Docs 2', function (editor) {
|
||||
const rng = editor.dom.createRng();
|
||||
|
||||
editor.setContent('<p>1234</p>');
|
||||
rng.setStart(editor.getBody().firstChild.firstChild, 0);
|
||||
rng.setEnd(editor.getBody().firstChild.firstChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<meta charset="utf-8">' +
|
||||
'<b style="font-weight:normal;" id="docs-internal-guid-adeb6845-fec6-72e6-6831-5e3ce002727c">' +
|
||||
'<p dir="ltr">a</p>' +
|
||||
'<p dir="ltr">b</p>' +
|
||||
'<p dir="ltr">c</p>' +
|
||||
'</b>' +
|
||||
'<br class="Apple-interchange-newline">'
|
||||
)
|
||||
});
|
||||
LegacyUnit.equal(editor.getContent(), '<p>a</p><p>b</p><p>c</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word without mso markings', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<font face="Times New Roman" size="3"></font>' +
|
||||
'<p style="margin: 0in 0in 10pt;">' +
|
||||
'<span style=\'line-height: 115%; font-family: "Comic Sans MS"; font-size: 22pt;\'>Comic Sans MS</span>' +
|
||||
'</p>' +
|
||||
'<font face="Times New Roman" size="3"></font>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), (
|
||||
'<p>Comic Sans MS</p>'
|
||||
));
|
||||
});
|
||||
|
||||
suite.test('Paste Word links', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class="MsoNormal">' +
|
||||
'<a href="file:///C:/somelocation/filename.doc#_Toc238571849">1</a>' +
|
||||
'<a href="#_Toc238571849">2</a>' +
|
||||
'<a name="Toc238571849">3</a>' +
|
||||
'<a name="_Toc238571849">4</a>' +
|
||||
'<a href="#_ftn238571849" name="_ftnref238571849">[5]</a>' +
|
||||
'<a href="#_ftnref238571849" name="_ftn238571849">[5]</a>' +
|
||||
'<a href="#_edn238571849" name="_ednref238571849">[6]</a>' +
|
||||
'<a href="#_ednref238571849" name="_edn238571849">[7]</a>' +
|
||||
'<a href="http://domain.tinymce.com/someurl">8</a>' +
|
||||
'<a name="#unknown">9</a>' +
|
||||
'<a href="http://domain.tinymce.com/someurl" name="named_link">named_link</a>' +
|
||||
'<a>5</a>' +
|
||||
'</p>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), (
|
||||
'<p>' +
|
||||
'<a href="#_Toc238571849">1</a>' +
|
||||
'<a href="#_Toc238571849">2</a>' +
|
||||
'<a name="Toc238571849"></a>3' +
|
||||
'<a name="_Toc238571849"></a>4' +
|
||||
'<a href="#_ftn238571849" name="_ftnref238571849">[5]</a>' +
|
||||
'<a href="#_ftnref238571849" name="_ftn238571849">[5]</a>' +
|
||||
'<a href="#_edn238571849" name="_ednref238571849">[6]</a>' +
|
||||
'<a href="#_ednref238571849" name="_edn238571849">[7]</a>' +
|
||||
'<a href="http://domain.tinymce.com/someurl">8</a>' +
|
||||
'9' +
|
||||
'named_link' +
|
||||
'5' +
|
||||
'</p>'
|
||||
));
|
||||
});
|
||||
|
||||
suite.test('Paste Word retain styles', function (editor) {
|
||||
editor.settings.paste_retain_style_properties = 'color,background-color,font-family';
|
||||
|
||||
// Test color
|
||||
editor.setContent('');
|
||||
editor.execCommand('SelectAll');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="MsoNormal" style="color: #ff0000">Test</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p style=\"color: #ff0000;\">Test</p>');
|
||||
|
||||
// Test background-color
|
||||
editor.setContent('');
|
||||
editor.execCommand('SelectAll');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="MsoNormal" style="background-color: #ff0000">Test</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p style=\"background-color: #ff0000;\">Test</p>');
|
||||
});
|
||||
|
||||
suite.test('Paste Word retain bold/italic styles to elements', function (editor) {
|
||||
editor.settings.paste_retain_style_properties = 'color';
|
||||
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class="MsoNormal">' +
|
||||
'<span style="font-weight: bold">bold</span>' +
|
||||
'<span style="font-style: italic">italic</span>' +
|
||||
'<span style="font-weight: bold; font-style: italic">bold + italic</span>' +
|
||||
'<span style="font-weight: bold; color: red">bold + color</span>' +
|
||||
'</p>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p><strong>bold</strong><em>italic</em><strong><em>bold + italic</em></strong><strong><span style="color: red;">bold + color</span></strong></p>');
|
||||
});
|
||||
|
||||
suite.test('paste track changes comment', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class="MsoNormal">1</p>' +
|
||||
'<div style="mso-element: comment;">2</div>' +
|
||||
'<span class="msoDel">3</span>' +
|
||||
'<del>4</del>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1</p>');
|
||||
});
|
||||
|
||||
suite.test('paste nested (UL) word list', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class=MsoListParagraphCxSpFirst style=\'text-indent:-18.0pt;mso-list:l0 level1 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:Symbol\'>' +
|
||||
'<span style=\'mso-list:Ignore\'>·<span style=\'font:7.0pt "Times New Roman"\'> ' +
|
||||
'</span></span></span><![endif]>a</p>' +
|
||||
|
||||
'<p class=MsoListParagraphCxSpMiddle style=\'margin-left:72.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level2 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'font-family:"Courier New";mso-fareast-font-family:"Courier New"\'>' +
|
||||
'<span style=\'mso-list:Ignore\'>o<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>b</p>' +
|
||||
|
||||
'<p class=MsoListParagraphCxSpLast style=\'margin-left:108.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level3 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'font-family:Wingdings;mso-fareast-font-family:Wingdings;mso-bidi-font-family:Wingdings\'>' +
|
||||
'<span style=\'mso-list:Ignore\'>§<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>c 1. x</p>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(
|
||||
editor.getContent(),
|
||||
'<ul>' +
|
||||
'<li>a' +
|
||||
'<ul>' +
|
||||
'<li>b' +
|
||||
'<ul>' +
|
||||
'<li>c 1. x</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
});
|
||||
|
||||
suite.test('paste nested (OL) word list', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class=MsoListParagraphCxSpFirst style=\'text-indent:-18.0pt;mso-list:l0 level1 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'>' +
|
||||
'<span style=\'mso-list:Ignore\'>1.<span style=\'font:7.0pt "Times New Roman"\'> </span>' +
|
||||
'</span></span><![endif]>a</p>' +
|
||||
|
||||
'<p class=MsoListParagraphCxSpMiddle style=\'margin-left:72.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level2 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>a.' +
|
||||
'<span style=\'font:7.0pt "Times New Roman"\'> </span></span></span><![endif]>b</p>' +
|
||||
|
||||
'<p class=MsoListParagraphCxSpLast style=\'margin-left:108.0pt;mso-add-space:auto;text-indent:-108.0pt;mso-text-indent-alt:-9.0pt;mso-list:l0 level3 lfo1\'>' +
|
||||
'<![if !supportLists]><span style=\'mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>' +
|
||||
'<span style=\'font:7.0pt "Times New Roman"\'> ' +
|
||||
' ' +
|
||||
' ' +
|
||||
' </span>i.<span style=\'font:7.0pt "Times New Roman"\'>' +
|
||||
' </span></span></span><![endif]>c</p>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(
|
||||
editor.getContent(),
|
||||
'<ol>' +
|
||||
'<li>a' +
|
||||
'<ol>' +
|
||||
'<li>b' +
|
||||
'<ol>' +
|
||||
'<li>c</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'</ol>'
|
||||
);
|
||||
});
|
||||
|
||||
suite.test('Paste list start index', function (editor) {
|
||||
editor.settings.paste_merge_formats = true;
|
||||
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<p class=MsoListParagraphCxSpMiddle style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">' +
|
||||
'<![if !supportLists]><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;' +
|
||||
'mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin"><span style="mso-list:Ignore">10.' +
|
||||
'<span style="font:7.0pt Times> </span></span></span><![endif]>J<o:p></o:p></p>'
|
||||
)
|
||||
});
|
||||
LegacyUnit.equal(editor.getContent(), '<ol start="10"><li>J</li></ol>');
|
||||
});
|
||||
|
||||
suite.test('Paste paste_merge_formats: true', function (editor) {
|
||||
editor.settings.paste_merge_formats = true;
|
||||
|
||||
editor.setContent('<p><strong>a</strong></p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 1);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em><strong>b</strong></em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><strong>a<em>b</em></strong></p>');
|
||||
});
|
||||
|
||||
suite.test('Paste paste_merge_formats: false', function (editor) {
|
||||
editor.settings.paste_merge_formats = false;
|
||||
|
||||
editor.setContent('<p><strong>a</strong></p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 1);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em><strong>b</strong></em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><strong>a<em><strong>b</strong></em></strong></p>');
|
||||
});
|
||||
|
||||
suite.test('Paste word DIV as P', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('SelectAll');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="MsoNormal">1</p><div>2</div>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>1</p><p>2</p>');
|
||||
});
|
||||
|
||||
if (Env.ie) {
|
||||
suite.test('Paste part of list from IE', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('SelectAll');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<li>item2</li><li>item3</li>' });
|
||||
LegacyUnit.equal(trimContent(editor.getContent()), '<ul><li>item2</li><li>item3</li></ul>', 'List tags are inferred when pasting LI');
|
||||
});
|
||||
}
|
||||
|
||||
suite.test('Disable default filters', function (editor) {
|
||||
editor.settings.paste_enable_default_filters = false;
|
||||
|
||||
// Test color
|
||||
editor.setContent('');
|
||||
editor.execCommand('SelectAll');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p class="MsoNormal" style="color: #ff0000;">Test</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p class="MsoNormal" style="color: #ff0000;">Test</p>');
|
||||
});
|
||||
|
||||
suite.test('paste invalid content with spans on page', function (editor) {
|
||||
const startingContent = '<p>123 testing <span id="x">span later in document</span></p>',
|
||||
insertedContent = '<ul><li>u</li><li>l</li></ul>';
|
||||
editor.setContent(startingContent);
|
||||
const rng = editor.dom.createRng();
|
||||
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
|
||||
rng.setEnd(editor.dom.select('p')[0].firstChild, 0);
|
||||
editor.selection.setRng(rng);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: insertedContent });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), insertedContent + startingContent);
|
||||
});
|
||||
|
||||
suite.test('paste plain text with space', function (editor) {
|
||||
editor.setContent('<p>text</p>');
|
||||
const 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('mceInsertClipboardContent', false, { text: ' a ' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>t a xt</p>');
|
||||
});
|
||||
|
||||
suite.test('paste plain text with linefeeds', function (editor) {
|
||||
editor.setContent('<p>text</p>');
|
||||
const 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('mceInsertClipboardContent', false, { text: 'a\nb\nc ' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>ta<br />b<br />c xt</p>');
|
||||
});
|
||||
|
||||
suite.test('paste plain text with double linefeeds', function (editor) {
|
||||
editor.setContent('<p>text</p>');
|
||||
const 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('mceInsertClipboardContent', false, { text: 'a\n\nb\n\nc' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>t</p><p>a</p><p>b</p><p>c</p><p>xt</p>');
|
||||
});
|
||||
|
||||
suite.test('paste plain text with entities', function (editor) {
|
||||
editor.setContent('<p>text</p>');
|
||||
const 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('mceInsertClipboardContent', false, { text: '< & >' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>t< & >xt</p>');
|
||||
});
|
||||
|
||||
suite.test('paste plain text with paragraphs', function (editor) {
|
||||
editor.setContent('<p>text</p>');
|
||||
const 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('mceInsertClipboardContent', false, { text: 'a\n<b>b</b>\n\nc' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>t</p><p>a<br /><b>b</b></p><p>c</p><p>xt</p>');
|
||||
});
|
||||
|
||||
suite.test('paste data image with paste_data_images: false', function (editor) {
|
||||
editor.setContent('');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<img src="data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==">' });
|
||||
LegacyUnit.equal(editor.getContent(), '');
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<img alt="alt" src="data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==">' });
|
||||
LegacyUnit.equal(editor.getContent(), '');
|
||||
});
|
||||
|
||||
suite.test('paste data image with paste_data_images: true', function (editor) {
|
||||
editor.settings.paste_data_images = true;
|
||||
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<img src="data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==">' });
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p><img src="data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" /></p>');
|
||||
});
|
||||
|
||||
suite.test('paste pre process text (event)', function (editor) {
|
||||
function callback(e) {
|
||||
e.content = 'PRE:' + e.content;
|
||||
}
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.on('PastePreProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { text: 'b\n2' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>PRE:b<br />2</p>');
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.off('PastePreProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { text: 'c' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>c</p>');
|
||||
});
|
||||
|
||||
suite.test('paste pre process html (event)', function (editor) {
|
||||
function callback(e) {
|
||||
e.content = 'PRE:' + e.content;
|
||||
}
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.on('PastePreProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em>b</em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>PRE:<em>b</em></p>');
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.off('PastePreProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em>c</em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><em>c</em></p>');
|
||||
});
|
||||
|
||||
suite.test('paste post process (event)', function (editor) {
|
||||
function callback(e) {
|
||||
e.node.innerHTML += ':POST';
|
||||
}
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.on('PastePostProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em>b</em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><em>b</em>:POST</p>');
|
||||
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 1);
|
||||
editor.off('PastePostProcess', callback);
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<em>c</em>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><em>c</em></p>');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of conditional comments', function () {
|
||||
LegacyUnit.equal(Utils.innerText('<![if !supportLists]>X<![endif]>'), 'X');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of single P', function (editor) {
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of single P with whitespace wrapped content', function (editor) {
|
||||
editor.setContent('<p> a </p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of two P', function (editor) {
|
||||
editor.setContent('<p>a</p><p>b</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a\n\nb');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of H1 and P', function (editor) {
|
||||
editor.setContent('<h1>a</h1><p>b</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a\nb');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of P with BR', function (editor) {
|
||||
editor.setContent('<p>a<br>b</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a\nb');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of P with WBR', function (editor) {
|
||||
editor.setContent('<p>a<wbr>b</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'ab');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of P with VIDEO', function (editor) {
|
||||
editor.setContent('<p>a<video>b<br>c</video>d</p>');
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML), 'a d');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of PRE', function (editor) {
|
||||
editor.getBody().innerHTML = '<pre>a\nb\n</pre>';
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().innerHTML).replace(/\r\n/g, '\n'), 'a\nb\n');
|
||||
});
|
||||
|
||||
suite.test('paste innerText of textnode with whitespace', function (editor) {
|
||||
editor.getBody().innerHTML = '<pre> a </pre>';
|
||||
LegacyUnit.equal(Utils.innerText(editor.getBody().firstChild.innerHTML), ' a ');
|
||||
});
|
||||
|
||||
suite.test('trim html from clipboard fragments', function () {
|
||||
LegacyUnit.equal(Utils.trimHtml('<!--StartFragment-->a<!--EndFragment-->'), 'a');
|
||||
LegacyUnit.equal(Utils.trimHtml('a\n<body>\n<!--StartFragment-->\nb\n<!--EndFragment-->\n</body>\nc'), '\nb\n');
|
||||
LegacyUnit.equal(Utils.trimHtml('a<!--StartFragment-->b<!--EndFragment-->c'), 'abc');
|
||||
LegacyUnit.equal(Utils.trimHtml('a<body>b</body>c'), 'b');
|
||||
LegacyUnit.equal(Utils.trimHtml('<HTML><HEAD><TITLE>a</TITLE></HEAD><BODY>b</BODY></HTML>'), 'b');
|
||||
LegacyUnit.equal(Utils.trimHtml('a<span class="Apple-converted-space">\u00a0<\/span>b'), 'a b');
|
||||
LegacyUnit.equal(Utils.trimHtml('<span class="Apple-converted-space">\u00a0<\/span>b'), ' b');
|
||||
LegacyUnit.equal(Utils.trimHtml('a<span class="Apple-converted-space">\u00a0<\/span>'), 'a ');
|
||||
LegacyUnit.equal(Utils.trimHtml('<span class="Apple-converted-space">\u00a0<\/span>'), ' ');
|
||||
});
|
||||
|
||||
if (Env.ie) {
|
||||
suite.test('paste font and u in anchor', function (editor) {
|
||||
editor.setContent('<p>a</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 1);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: '<p><a href="#"><font size="3"><u>b</u></font></a></p>'
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p>a</p><p><a href="#">b</a></p>');
|
||||
});
|
||||
}
|
||||
|
||||
if (Env.webkit) {
|
||||
suite.test('paste webkit retains text styles runtime styles internal', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'color';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color:red"><span data-mce-style="color:red">' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="color:red"><span data-mce-style="color:red"></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles internal', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'color';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color:red; font-size: 42px" data-mce-style="color: red;">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="color: red;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (color)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'color';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color:red; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="color: red;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles keep before attr', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span class="c" style="color:red; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span class="c">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles keep after attr', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color:red; text-indent: 10px" title="t">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span title="t">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles keep before/after attr', function (editor) {
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span class="c" style="color:red; text-indent: 10px" title="t">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span class="c" title="t">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (background-color)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'background-color';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="background-color:red; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="background-color: red;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (font-size)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'font-size';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="font-size:42px; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="font-size: 42px;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (font-family)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'font-family';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="font-family:Arial; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="font-family: Arial;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles font-family allowed but not specified', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'font-family';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<p title="x" style="text-indent: 10px">Test</p>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p title="x">Test</p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (custom styles)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'color font-style';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color: red; font-style: italic; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style="color: red; font-style: italic;">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (all)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'all';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color: red; font-style: italic; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><span style=\"color: red; font-style: italic; text-indent: 10px;\">Test</span></p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (none)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'none';
|
||||
editor.setContent('');
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: '<span style="color: red; font-style: italic; text-indent: 10px">Test</span>' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>Test</p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (color) in the same (color) (named)', function (editor) {
|
||||
editor.settings.paste_webkit_styles = 'color';
|
||||
|
||||
editor.setContent('<p style="color:red">Test</span>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 4);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<span style="color:#ff0000; text-indent: 10px">a</span>' +
|
||||
'<span style="color:rgb(255, 0, 0); text-indent: 10px">b</span>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p style="color: red;">ab</p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (color) in the same (color) (hex)', function (editor) {
|
||||
editor.setContent('<p style="color:#ff0000">Test</span>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 4);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<span style="color:red; text-indent: 10px">a</span>' +
|
||||
'<span style="color:#ff0000; text-indent: 10px">b</span>' +
|
||||
'<span style="color:rgb(255, 0, 0); text-indent: 10px">c</span>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p style="color: #ff0000;">abc</p>');
|
||||
});
|
||||
|
||||
suite.test('paste webkit remove runtime styles (color) in the same (color) (rgb)', function (editor) {
|
||||
editor.setContent('<p style="color:rgb(255, 0, 0)">Test</span>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 4);
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, {
|
||||
content: (
|
||||
'<span style="color:red; text-indent: 10px">a</span>' +
|
||||
'<span style="color:#ff0000; text-indent: 10px">b</span>' +
|
||||
'<span style="color:rgb(255, 0, 0); text-indent: 10px">c</span>'
|
||||
)
|
||||
});
|
||||
|
||||
LegacyUnit.equal(editor.getContent(), '<p style="color: #ff0000;">abc</p>');
|
||||
});
|
||||
}
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
Pipeline.async({}, appendTeardown(editor, suite.toSteps(editor)), onSuccess, onFailure);
|
||||
}, {
|
||||
add_unload_trigger: false,
|
||||
indent: false,
|
||||
plugins: 'paste',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,147 @@
|
||||
import { Assertions, Chain, Guard, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Id, Merger, Obj } from '@ephox/katamari';
|
||||
|
||||
import EditorManager from 'tinymce/core/api/EditorManager';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import MockDataTransfer from '../module/test/MockDataTransfer';
|
||||
import ViewBlock from '../module/test/ViewBlock';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.PlainTextPaste', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
|
||||
const viewBlock = ViewBlock();
|
||||
|
||||
const cCreateEditorFromSettings = function (settings, html?) {
|
||||
return Chain.async(function (viewBlock: any, next, die) {
|
||||
const randomId = Id.generate('tiny-');
|
||||
html = html || '<textarea></textarea>';
|
||||
|
||||
viewBlock.update(html);
|
||||
viewBlock.get().firstChild.id = randomId;
|
||||
|
||||
EditorManager.init(Merger.merge(settings, {
|
||||
selector: '#' + randomId,
|
||||
skin_url: '/project/js/tinymce/skins/lightgray',
|
||||
indent: false,
|
||||
setup (editor) {
|
||||
editor.on('SkinLoaded', function () {
|
||||
setTimeout(function () {
|
||||
next(editor);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
const cRemoveEditor = function () {
|
||||
return Chain.op(function (editor: any) {
|
||||
editor.remove();
|
||||
});
|
||||
};
|
||||
|
||||
const cClearEditor = function () {
|
||||
return Chain.async(function (editor: any, next, die) {
|
||||
editor.setContent('');
|
||||
next(editor);
|
||||
});
|
||||
};
|
||||
|
||||
const cFireFakePasteEvent = function (data) {
|
||||
return Chain.async(function (editor: any, next, die) {
|
||||
editor.fire('paste', { clipboardData: MockDataTransfer.create(data) });
|
||||
next(editor);
|
||||
});
|
||||
};
|
||||
|
||||
const cAssertEditorContent = function (label, expected) {
|
||||
return Chain.async(function (editor: any, next, die) {
|
||||
Assertions.assertHtml(label || 'Asserting editors content', expected, editor.getContent());
|
||||
next(editor);
|
||||
});
|
||||
};
|
||||
|
||||
const cAssertClipboardPaste = function (expected, data) {
|
||||
const chains = [];
|
||||
|
||||
Obj.each(data, function (data, label) {
|
||||
chains.push(
|
||||
cFireFakePasteEvent(data),
|
||||
Chain.control(
|
||||
cAssertEditorContent(label, expected),
|
||||
Guard.tryUntil('Wait for paste to succeed.', 100, 1000)
|
||||
),
|
||||
cClearEditor()
|
||||
);
|
||||
});
|
||||
|
||||
return Chain.fromChains(chains);
|
||||
};
|
||||
|
||||
const srcText = 'one\r\ntwo\r\n\r\nthree\r\n\r\n\r\nfour\r\n\r\n\r\n\r\n.';
|
||||
|
||||
const pasteData = {
|
||||
Firefox: {
|
||||
'text/plain': srcText,
|
||||
'text/html': 'one<br>two<br><br>three<br><br><br>four<br><br><br><br>.'
|
||||
},
|
||||
Chrome: {
|
||||
'text/plain': srcText,
|
||||
'text/html': '<div>one</div><div>two</div><div><br></div><div>three</div><div><br></div><div><br></div><div>four</div><div><br></div><div><br></div><div><br></div><div>.'
|
||||
},
|
||||
Edge: {
|
||||
'text/plain': srcText,
|
||||
'text/html': '<div>one<br>two</div><div>three</div><div><br>four</div><div><br></div><div>.</div>'
|
||||
},
|
||||
IE: {
|
||||
'text/plain': srcText,
|
||||
'text/html': '<p>one<br>two</p><p>three</p><p><br>four</p><p><br></p><p>.</p>'
|
||||
}
|
||||
};
|
||||
|
||||
const expectedWithRootBlock = '<p>one<br />two</p><p>three</p><p><br />four</p><p> </p><p>.</p>';
|
||||
const expectedWithRootBlockAndAttrs = '<p class="attr">one<br />two</p><p class="attr">three</p><p class="attr"><br />four</p><p class="attr"> </p><p class="attr">.</p>';
|
||||
const expectedWithoutRootBlock = 'one<br />two<br /><br />three<br /><br /><br />four<br /><br /><br /><br />.';
|
||||
|
||||
Theme();
|
||||
PastePlugin();
|
||||
|
||||
viewBlock.attach();
|
||||
|
||||
Pipeline.async({}, [
|
||||
Chain.asStep(viewBlock, [
|
||||
cCreateEditorFromSettings({
|
||||
plugins: 'paste',
|
||||
forced_root_block: 'p' // default
|
||||
}),
|
||||
cAssertClipboardPaste(expectedWithRootBlock, pasteData),
|
||||
cRemoveEditor()
|
||||
]),
|
||||
Chain.asStep(viewBlock, [
|
||||
cCreateEditorFromSettings({
|
||||
plugins: 'paste',
|
||||
forced_root_block: 'p',
|
||||
forced_root_block_attrs: {
|
||||
class: 'attr'
|
||||
}
|
||||
}),
|
||||
cAssertClipboardPaste(expectedWithRootBlockAndAttrs, pasteData),
|
||||
cRemoveEditor()
|
||||
]),
|
||||
Chain.asStep(viewBlock, [
|
||||
cCreateEditorFromSettings({
|
||||
plugins: 'paste',
|
||||
forced_root_block: false
|
||||
}),
|
||||
cAssertClipboardPaste(expectedWithoutRootBlock, pasteData),
|
||||
cRemoveEditor()
|
||||
])
|
||||
], function () {
|
||||
viewBlock.detach();
|
||||
success();
|
||||
}, failure);
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
import { Assertions, Chain, Logger, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { Fun } from '@ephox/katamari';
|
||||
import { TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import ProcessFilters from 'tinymce/plugins/paste/core/ProcessFilters';
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.ProcessFiltersTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
|
||||
Theme();
|
||||
PastePlugin();
|
||||
|
||||
const cProcessPre = function (html, internal, preProcess) {
|
||||
return Chain.mapper(function (editor: any) {
|
||||
editor.on('PastePreProcess', preProcess);
|
||||
|
||||
const result = ProcessFilters.process(editor, html, internal);
|
||||
|
||||
editor.off('PastePreProcess', preProcess);
|
||||
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
const cProcessPrePost = function (html, internal, preProcess, postProcess) {
|
||||
return Chain.mapper(function (editor: any) {
|
||||
editor.on('PastePreProcess', preProcess);
|
||||
editor.on('PastePostProcess', postProcess);
|
||||
|
||||
const result = ProcessFilters.process(editor, html, internal);
|
||||
|
||||
editor.off('PastePreProcess', preProcess);
|
||||
editor.off('PastePostProcess', postProcess);
|
||||
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
const preventHandler = function (e) {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
const preProcessHandler = function (e) {
|
||||
e.content += 'X';
|
||||
};
|
||||
|
||||
const postProcessHandler = function (editor) {
|
||||
return function (e) {
|
||||
editor.dom.remove(editor.dom.select('b', e.node), true);
|
||||
};
|
||||
};
|
||||
|
||||
const assertInternal = function (expectedFlag) {
|
||||
return function (e) {
|
||||
Assertions.assertEq('Should be expected internal flag', expectedFlag, e.internal);
|
||||
};
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
Pipeline.async({}, [
|
||||
Logger.t('Paste pre process only', Chain.asStep(editor, [
|
||||
cProcessPre('a', true, preProcessHandler),
|
||||
Assertions.cAssertEq('Should be preprocessed by adding a X', { content: 'aX', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process passthough as is', Chain.asStep(editor, [
|
||||
cProcessPrePost('a', true, Fun.noop, Fun.noop),
|
||||
Assertions.cAssertEq('Should be unchanged', { content: 'a', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process assert internal false', Chain.asStep(editor, [
|
||||
cProcessPrePost('a', false, assertInternal(false), assertInternal(false)),
|
||||
Assertions.cAssertEq('Should be unchanged', { content: 'a', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process assert internal true', Chain.asStep(editor, [
|
||||
cProcessPrePost('a', true, assertInternal(true), assertInternal(true)),
|
||||
Assertions.cAssertEq('Should be unchanged', { content: 'a', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process alter on preprocess', Chain.asStep(editor, [
|
||||
cProcessPrePost('a', true, preProcessHandler, Fun.noop),
|
||||
Assertions.cAssertEq('Should be preprocessed by adding a X', { content: 'aX', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process alter on postprocess', Chain.asStep(editor, [
|
||||
cProcessPrePost('a<b>b</b>c', true, Fun.noop, postProcessHandler(editor)),
|
||||
Assertions.cAssertEq('Should have all b elements removed', { content: 'abc', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process alter on preprocess/postprocess', Chain.asStep(editor, [
|
||||
cProcessPrePost('a<b>b</b>c', true, preProcessHandler, postProcessHandler(editor)),
|
||||
Assertions.cAssertEq('Should have all b elements removed and have a X added', { content: 'abcX', cancelled: false })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process prevent default on preProcess', Chain.asStep(editor, [
|
||||
cProcessPrePost('a<b>b</b>c', true, preventHandler, postProcessHandler(editor)),
|
||||
Assertions.cAssertEq('Should have all b elements removed and be cancelled', { content: 'a<b>b</b>c', cancelled: true })
|
||||
])),
|
||||
|
||||
Logger.t('Paste pre/post process prevent default on postProcess', Chain.asStep(editor, [
|
||||
cProcessPrePost('a<b>b</b>c', true, preProcessHandler, preventHandler),
|
||||
Assertions.cAssertEq('Should have a X added and be cancelled', { content: 'a<b>b</b>cX', cancelled: true })
|
||||
]))
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
add_unload_trigger: false,
|
||||
indent: false,
|
||||
plugins: 'paste',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import { Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { LegacyUnit, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import SmartPaste from 'tinymce/plugins/paste/core/SmartPaste';
|
||||
import Plugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.browser.ImagePasteTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
const suite = LegacyUnit.createSuite();
|
||||
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
suite.test('isAbsoluteUrl', function () {
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('http://www.site.com'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('https://www.site.com'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('http://www.site.com/dir-name/file.gif?query=%42'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('https://www.site.com/dir-name/file.gif?query=%42'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('https://www.site.com/dir-name/file.gif?query=%42#a'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('https://www.site.com/~abc'), true);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl('file.gif'), false);
|
||||
LegacyUnit.equal(SmartPaste.isAbsoluteUrl(''), false);
|
||||
});
|
||||
|
||||
suite.test('isImageUrl', function () {
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('http://www.site.com'), false);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('https://www.site.com'), false);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.jpeg'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.jpg'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.png'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.gif'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.gif'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('https://www.site.com/~dir-name/file.gif'), true);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.gif?query=%42'), false);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.html?query=%42'), false);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl('file.gif'), false);
|
||||
LegacyUnit.equal(SmartPaste.isImageUrl(''), false);
|
||||
});
|
||||
|
||||
suite.test('smart paste url on selection', function (editor) {
|
||||
editor.focus();
|
||||
editor.undoManager.clear();
|
||||
editor.setContent('<p>abc</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 0, 'p', 3);
|
||||
editor.undoManager.add();
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: 'http://www.site.com' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p><a href="http://www.site.com">abc</a></p>');
|
||||
LegacyUnit.equal(editor.undoManager.data.length, 3);
|
||||
});
|
||||
|
||||
suite.test('smart paste image url', function (editor) {
|
||||
editor.focus();
|
||||
editor.undoManager.clear();
|
||||
editor.setContent('<p>abc</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 1);
|
||||
editor.undoManager.add();
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: 'http://www.site.com/my.jpg' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>a<img src="http://www.site.com/my.jpg" />bc</p>');
|
||||
LegacyUnit.equal(editor.undoManager.data.length, 3);
|
||||
});
|
||||
|
||||
suite.test('smart paste option disabled', function (editor) {
|
||||
editor.focus();
|
||||
editor.undoManager.clear();
|
||||
editor.setContent('<p>abc</p>');
|
||||
LegacyUnit.setSelection(editor, 'p', 1);
|
||||
editor.undoManager.add();
|
||||
editor.settings.smart_paste = false;
|
||||
|
||||
editor.execCommand('mceInsertClipboardContent', false, { content: 'http://www.site.com/my.jpg' });
|
||||
LegacyUnit.equal(editor.getContent(), '<p>ahttp://www.site.com/my.jpgbc</p>');
|
||||
LegacyUnit.equal(editor.undoManager.data.length, 2);
|
||||
});
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
Pipeline.async({}, suite.toSteps(editor), onSuccess, onFailure);
|
||||
}, {
|
||||
add_unload_trigger: false,
|
||||
indent: false,
|
||||
plugins: 'paste',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Assertions } from '@ephox/agar';
|
||||
import { Editor } from 'tinymce/core/api/Editor';
|
||||
import EditorManager from 'tinymce/core/api/EditorManager';
|
||||
import PluginManager from 'tinymce/core/api/PluginManager';
|
||||
import DetectProPlugin from 'tinymce/plugins/paste/alien/DetectProPlugin';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
|
||||
UnitTest.test('browser.tinymce.plugins.paste.alien.DetectProPluginTest', function () {
|
||||
// Fake loading of powerpaste
|
||||
PluginManager.add('powerpaste', function () { });
|
||||
|
||||
Assertions.assertEq('Should not have pro plugin', false, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'paste' }, EditorManager)));
|
||||
Assertions.assertEq('Should not have pro plugin', false, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: '' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'powerpaste' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'paste powerpaste' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'powerpaste paste' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'paste powerpaste paste' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'paste,powerpaste,paste' }, EditorManager)));
|
||||
Assertions.assertEq('Should have pro plugin', true, DetectProPlugin.hasProPlugin(new Editor('id', { plugins: 'paste powerpaste paste' }, EditorManager)));
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Arr, Obj } from '@ephox/katamari';
|
||||
|
||||
const notImplemented = function () {
|
||||
throw new Error('Mockup function is not implemented.');
|
||||
};
|
||||
|
||||
const createDataTransferItem = function (mime, content) {
|
||||
return {
|
||||
kind: 'string',
|
||||
type: mime,
|
||||
getAsFile: notImplemented,
|
||||
getAsString () {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const create = function (inputData) {
|
||||
let data = {}, result;
|
||||
|
||||
const clearData = function () {
|
||||
data = {};
|
||||
result.items = [];
|
||||
result.types = [];
|
||||
};
|
||||
|
||||
const getData = function (mime) {
|
||||
return mime in data ? data[mime] : '';
|
||||
};
|
||||
|
||||
const setData = function (mime, content) {
|
||||
data[mime] = content;
|
||||
result.types = Obj.keys(data);
|
||||
result.items = Arr.map(result.types, function (type) {
|
||||
return createDataTransferItem(type, data[type]);
|
||||
});
|
||||
};
|
||||
|
||||
result = {
|
||||
dropEffect: '',
|
||||
effectAllowed: 'all',
|
||||
files: [],
|
||||
items: [],
|
||||
types: [],
|
||||
clearData,
|
||||
getData,
|
||||
setData,
|
||||
setDragImage: notImplemented,
|
||||
addElement: notImplemented
|
||||
};
|
||||
|
||||
Obj.each(inputData, function (value, key) {
|
||||
setData(key, value);
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export default {
|
||||
create
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Step } from '@ephox/agar';
|
||||
import MockDataTransfer from './MockDataTransfer';
|
||||
|
||||
const sPaste = function (editor, data) {
|
||||
return Step.sync(function () {
|
||||
const dataTransfer = MockDataTransfer.create(data);
|
||||
editor.fire('paste', { clipboardData: dataTransfer });
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
sPaste
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
|
||||
import DOMUtils from 'tinymce/core/api/dom/DOMUtils';
|
||||
import { document, HTMLElement } from '@ephox/dom-globals';
|
||||
|
||||
export default function () {
|
||||
const domElm: HTMLElement = DOMUtils.DOM.create('div', {
|
||||
style: 'position: absolute; right: 10px; top: 10px;'
|
||||
});
|
||||
|
||||
const attach = function (preventDuplicates?) {
|
||||
if (preventDuplicates && domElm.parentNode === document.body) {
|
||||
detach();
|
||||
}
|
||||
document.body.appendChild(domElm);
|
||||
};
|
||||
|
||||
const detach = function () {
|
||||
DOMUtils.DOM.remove(domElm);
|
||||
};
|
||||
|
||||
const update = function (html) {
|
||||
DOMUtils.DOM.setHTML(domElm, html);
|
||||
};
|
||||
|
||||
const get = function () {
|
||||
return domElm;
|
||||
};
|
||||
|
||||
return {
|
||||
attach,
|
||||
update,
|
||||
detach,
|
||||
get
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Pipeline, RealMouse, Waiter } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader, TinyUi } from '@ephox/mcagar';
|
||||
import { PlatformDetection } from '@ephox/sand';
|
||||
|
||||
import PastePlugin from 'tinymce/plugins/paste/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
import { window } from '@ephox/dom-globals';
|
||||
|
||||
UnitTest.asynctest('tinymce.plugins.paste.webdriver.CutTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
|
||||
Theme();
|
||||
PastePlugin();
|
||||
|
||||
const platform = PlatformDetection.detect();
|
||||
|
||||
/* Test does not work on Phantom */
|
||||
if (window.navigator.userAgent.indexOf('PhantomJS') > -1) {
|
||||
return success();
|
||||
}
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const api = TinyApis(editor);
|
||||
const ui = TinyUi(editor);
|
||||
|
||||
// Cut doesn't seem to work in webdriver mode on ie, firefox is producing moveto not supported, edge fails if it's not observed
|
||||
Pipeline.async({}, (platform.browser.isIE() || platform.browser.isFirefox() || platform.browser.isEdge()) ? [] : [
|
||||
api.sSetContent('<p>abc</p>'),
|
||||
api.sSetSelection([0, 0], 1, [0, 0], 2),
|
||||
ui.sClickOnMenu('Click Edit menu', 'button:contains("Edit")'),
|
||||
ui.sWaitForUi('Wait for dropdown', '.mce-floatpanel[role="application"]'),
|
||||
RealMouse.sClickOn('.mce-i-cut'),
|
||||
Waiter.sTryUntil('Cut is async now, so need to wait for content', api.sAssertContent('<p>ac</p>'), 100, 1000)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
skin_url: '/project/js/tinymce/skins/lightgray',
|
||||
plugins: 'paste'
|
||||
}, success, failure);
|
||||
});
|
||||
Reference in New Issue
Block a user