import { afterEach, before, beforeEach, context, describe, it } from '@ephox/bedrock-client'; import { PlatformDetection } from '@ephox/sand'; import { TinyAssertions, TinyHooks, TinySelections } from '@ephox/wrap-mcagar'; import { assert } from 'chai'; import Editor from 'tinymce/core/api/Editor'; import { PastePostProcessEvent, PastePreProcessEvent } from 'tinymce/core/api/EventTypes'; import { EditorEvent } from 'tinymce/core/api/util/EventDispatcher'; import * as PasteUtils from 'tinymce/core/paste/PasteUtils'; describe('browser.tinymce.core.paste.PasteTest', () => { const browser = PlatformDetection.detect().browser; const hook = TinyHooks.bddSetupLight({ add_unload_trigger: false, indent: false, base_url: '/project/tinymce/js/tinymce' }, [], true); beforeEach(() => { const editor = hook.editor(); editor.setContent(''); }); afterEach(() => { const editor = hook.editor(); editor.options.unset('paste_remove_styles_if_webkit'); editor.options.unset('paste_data_images'); editor.options.unset('paste_webkit_styles'); }); it('TBA: Plain text toggle event', () => { const editor = hook.editor(); const events: Array<{ state: boolean }> = []; editor.on('PastePlainTextToggle', (e) => { events.push({ state: e.state }); }); editor.execCommand('mceTogglePlainTextPaste'); assert.deepEqual(events, [ { state: true } ], 'Should be enabled'); editor.execCommand('mceTogglePlainTextPaste'); assert.deepEqual(events, [ { state: true }, { state: false } ], 'Should be disabled'); editor.execCommand('mceTogglePlainTextPaste'); assert.deepEqual(events, [ { state: true }, { state: false }, { state: true } ], 'Should be enabled again'); }); it('TBA: Paste simple text content', () => { const editor = hook.editor(); editor.setContent('

1234

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 3); editor.execCommand('mceInsertClipboardContent', false, { html: 'TEST' }); TinyAssertions.assertContent(editor, '

1TEST4

'); }); it('TBA: Paste text with meta and nbsp', () => { const editor = hook.editor(); editor.setContent('

'); TinySelections.setCursor(editor, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { html: 'TEST' }); TinyAssertions.assertContent(editor, '

1 TEST

'); }); it('TBA: Paste styled text content', () => { const editor = hook.editor(); editor.options.set('paste_remove_styles_if_webkit', false); editor.setContent('

1234

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 3); editor.execCommand('mceInsertClipboardContent', false, { html: 'TEST' }); TinyAssertions.assertContent(editor, '

1TEST4

'); }); it('TBA: Paste paragraph in paragraph', () => { const editor = hook.editor(); editor.setContent('

1234

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 3); editor.execCommand('mceInsertClipboardContent', false, { html: '

TEST

' }); TinyAssertions.assertContent(editor, '

1

TEST

4

'); }); it('TBA: Paste paragraphs in complex paragraph', () => { const editor = hook.editor(); editor.setContent('

1234

'); TinySelections.setSelection(editor, [ 0, 0, 0, 0 ], 1, [ 0, 0, 0, 0 ], 3); editor.execCommand('mceInsertClipboardContent', false, { html: '

TEST 1

TEST 2

' }); TinyAssertions.assertContent(editor, '

1

TEST 1

TEST 2

4

'); }); it('TBA: Paste Google Docs sanity test', () => { const editor = hook.editor(); editor.setContent('

1234

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 4); editor.execCommand('mceInsertClipboardContent', false, { html: '

Test

' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: Paste paste_merge_formats: true', () => { const editor = hook.editor(); editor.options.set('paste_merge_formats', true); editor.setContent('

a

'); TinySelections.setCursor(editor, [ 0, 0 ], 1); editor.execCommand('mceInsertClipboardContent', false, { html: 'b' }); TinyAssertions.assertContent(editor, '

ab

'); }); it('TBA: Paste paste_merge_formats: false', () => { const editor = hook.editor(); editor.options.set('paste_merge_formats', false); editor.setContent('

a

'); TinySelections.setCursor(editor, [ 0, 0 ], 1); editor.execCommand('mceInsertClipboardContent', false, { html: 'b' }); TinyAssertions.assertContent(editor, '

ab

'); }); it('TBA: paste invalid content with spans on page', () => { const editor = hook.editor(); const startingContent = '

123 testing span later in document

'; const insertedContent = ''; editor.setContent(startingContent); TinySelections.setCursor(editor, [ 0, 0 ], 0); editor.execCommand('mceInsertClipboardContent', false, { html: insertedContent }); TinyAssertions.assertContent(editor, insertedContent + startingContent); }); it('TBA: paste plain text with space', () => { const editor = hook.editor(); editor.setContent('

text

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { text: ' a ' }); TinyAssertions.assertContent(editor, '

t a xt

'); }); it('TBA: paste plain text with linefeeds', () => { const editor = hook.editor(); editor.setContent('

text

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { text: 'a\nb\nc ' }); TinyAssertions.assertContent(editor, '

ta
b
c xt

'); }); it('TBA: paste plain text with double linefeeds', () => { const editor = hook.editor(); editor.setContent('

text

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { text: 'a\n\nb\n\nc' }); TinyAssertions.assertContent(editor, '

t

a

b

c

xt

'); }); it('TBA: paste plain text with entities', () => { const editor = hook.editor(); editor.setContent('

text

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { text: '< & >' }); TinyAssertions.assertContent(editor, '

t< & >xt

'); }); it('TBA: paste plain text with paragraphs', () => { const editor = hook.editor(); editor.setContent('

text

'); TinySelections.setSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 2); editor.execCommand('mceInsertClipboardContent', false, { text: 'a\nb\n\nc' }); TinyAssertions.assertContent(editor, '

t

a
<b>b</b>

c

xt

'); }); it('TBA: paste data image with paste_data_images: false', () => { const editor = hook.editor(); editor.options.set('paste_data_images', false); editor.execCommand('mceInsertClipboardContent', false, { html: '' }); TinyAssertions.assertContent(editor, ''); editor.execCommand('mceInsertClipboardContent', false, { html: 'alt' }); TinyAssertions.assertContent(editor, ''); }); it('TBA: paste data image with paste_data_images: true', () => { const editor = hook.editor(); editor.options.set('paste_data_images', true); editor.execCommand('mceInsertClipboardContent', false, { html: '' }); TinyAssertions.assertContent(editor, '

'); }); it('TBA: paste data with script', () => { const editor = hook.editor(); editor.execCommand('mceInsertClipboardContent', false, { html: `

` }); TinyAssertions.assertContent(editor, '

'); }); it('TBA: paste pre process text (event)', () => { const editor = hook.editor(); const callback = (e: EditorEvent) => { e.content = 'PRE:' + e.content; }; editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.on('PastePreProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { text: 'b\n2' }); TinyAssertions.assertContent(editor, '

PRE:b
2

'); editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.off('PastePreProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { text: 'c' }); TinyAssertions.assertContent(editor, '

c

'); }); it('TBA: paste pre process html (event)', () => { const editor = hook.editor(); const callback = (e: EditorEvent) => { e.content = 'PRE:' + e.content; }; editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.on('PastePreProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { html: 'b' }); TinyAssertions.assertContent(editor, '

PRE:b

'); editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.off('PastePreProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { html: 'c' }); TinyAssertions.assertContent(editor, '

c

'); }); it('TBA: paste post process (event)', () => { const editor = hook.editor(); const callback = (e: EditorEvent) => { e.node.innerHTML += ':POST'; }; editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.on('PastePostProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { html: 'b' }); TinyAssertions.assertContent(editor, '

b:POST

'); editor.setContent('

a

'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 1); editor.off('PastePostProcess', callback); editor.execCommand('mceInsertClipboardContent', false, { html: 'c' }); TinyAssertions.assertContent(editor, '

c

'); }); it('TBA: paste innerText of conditional comments', () => { assert.equal(PasteUtils.innerText('X'), 'X'); }); it('TBA: paste innerText of single P', () => { const editor = hook.editor(); editor.setContent('

a

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a'); }); it('TBA: paste innerText of single P with whitespace wrapped content', () => { const editor = hook.editor(); editor.setContent('

a

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a'); }); it('TBA: paste innerText of two P', () => { const editor = hook.editor(); editor.setContent('

a

b

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a\n\nb'); }); it('TBA: paste innerText of H1 and P', () => { const editor = hook.editor(); editor.setContent('

a

b

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a\nb'); }); it('TBA: paste innerText of P with BR', () => { const editor = hook.editor(); editor.setContent('

a
b

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a\nb'); }); it('TBA: paste innerText of P with WBR', () => { const editor = hook.editor(); editor.setContent('

ab

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'ab'); }); it('TBA: paste innerText of P with VIDEO', () => { const editor = hook.editor(); editor.setContent('

ad

'); assert.equal(PasteUtils.innerText(editor.getBody().innerHTML), 'a d'); }); it('TBA: paste innerText of PRE', () => { const editor = hook.editor(); editor.getBody().innerHTML = '
a\nb\n
'; assert.equal(PasteUtils.innerText(editor.getBody().innerHTML).replace(/\r\n/g, '\n'), 'a\nb\n'); }); it('TBA: paste innerText of textnode with whitespace', () => { const editor = hook.editor(); editor.getBody().innerHTML = '
 a 
'; assert.equal(PasteUtils.innerText((editor.getBody().firstChild as HTMLElement).innerHTML), ' a '); }); it('TBA: trim html from clipboard fragments', () => { assert.equal(PasteUtils.trimHtml('a'), 'a'); assert.equal(PasteUtils.trimHtml('a\n\n\nb\n\n\nc'), '\nb\n'); assert.equal(PasteUtils.trimHtml('abc'), 'abc'); assert.equal(PasteUtils.trimHtml('abc'), 'b'); assert.equal(PasteUtils.trimHtml('ab'), 'b'); assert.equal(PasteUtils.trimHtml('a\u00a0<\/span>b'), 'a b'); assert.equal(PasteUtils.trimHtml('\u00a0<\/span>b'), ' b'); assert.equal(PasteUtils.trimHtml('a\u00a0<\/span>'), 'a '); assert.equal(PasteUtils.trimHtml('\u00a0<\/span>'), ' '); }); context('paste_webkit_styles', () => { before(function () { if (!browser.isChromium() && !browser.isSafari()) { this.skip(); } }); it('TBA: paste webkit retains text styles runtime styles internal', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'color'); editor.execCommand('mceInsertClipboardContent', false, { html: '<span style="color:red"><span data-mce-style="color:red">' }); TinyAssertions.assertContent(editor, '

<span style="color:red"><span data-mce-style="color:red">

'); }); it('TBA: paste webkit remove runtime styles internal', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'color'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (color)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'color'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles keep before attr', () => { const editor = hook.editor(); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles keep after attr', () => { const editor = hook.editor(); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles keep before/after attr', () => { const editor = hook.editor(); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (background-color)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'background-color'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (font-size)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'font-size'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (font-family)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'font-family'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles font-family allowed but not specified', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'font-family'); editor.execCommand('mceInsertClipboardContent', false, { html: '

Test

' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (custom styles)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'color font-style'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (all)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'all'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (none)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'none'); editor.execCommand('mceInsertClipboardContent', false, { html: 'Test' }); TinyAssertions.assertContent(editor, '

Test

'); }); it('TBA: paste webkit remove runtime styles (color) in the same (color) (named)', () => { const editor = hook.editor(); editor.options.set('paste_webkit_styles', 'color'); editor.setContent('

Test'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 4); editor.execCommand('mceInsertClipboardContent', false, { html: ( 'a' + 'b' ) }); TinyAssertions.assertContent(editor, '

ab

'); }); it('TBA: paste webkit remove runtime styles (color) in the same (color) (hex)', () => { const editor = hook.editor(); editor.setContent('

Test'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 4); editor.execCommand('mceInsertClipboardContent', false, { html: ( 'a' + 'b' + 'c' ) }); TinyAssertions.assertContent(editor, '

abc

'); }); it('TBA: paste webkit remove runtime styles (color) in the same (color) (rgb)', () => { const editor = hook.editor(); editor.setContent('

Test'); TinySelections.setSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 4); editor.execCommand('mceInsertClipboardContent', false, { html: ( 'a' + 'b' + 'c' ) }); TinyAssertions.assertContent(editor, '

abc

'); }); }); });