import { beforeEach, context, describe, it } from '@ephox/bedrock-client'; import { Arr, Fun } from '@ephox/katamari'; import { Hierarchy, Insert, SugarElement } from '@ephox/sugar'; import { TinyAssertions, TinyDom, TinyHooks, TinySelections } from '@ephox/wrap-mcagar'; import Editor from 'tinymce/core/api/Editor'; describe('browser.tinymce.core.keyboard.InsertKeysTest', () => { const hook = TinyHooks.bddSetupLight({ indent: false, base_url: '/project/tinymce/js/tinymce' }, []); const fireInsert = (editor: Editor) => { editor.dispatch('input', { isComposing: false } as InputEvent); }; const insertEmptyTextNodesAt = (editor: Editor, count: number, path: number[], insert: (marker: SugarElement, element: SugarElement) => void) => { const elm = Hierarchy.follow(TinyDom.body(editor), path).getOrDie('Could not follow path'); Arr.each(Arr.range(count, Fun.identity), () => { insert(elm, SugarElement.fromDom(document.createTextNode(''))); }); }; const prependEmptyTextNodesAt = (editor: Editor, count: number, path: number[]) => insertEmptyTextNodesAt(editor, count, path, Insert.before); const appendEmptyTextNodesAt = (editor: Editor, count: number, path: number[]) => insertEmptyTextNodesAt(editor, count, path, Insert.after); beforeEach(() => { hook.editor().focus(); }); context('Insert key in text with in nbsp text node', () => { context('Nbsp at first character position', () => { it('Insert in text node with nbsp at start of block', () => { const editor = hook.editor(); editor.setContent('

 a

'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '

 a

'); }); it('Insert in text in node with leading nbsp after inline with trailing space', () => { const editor = hook.editor(); editor.setContent('

ab  c

'); TinySelections.setCursor(editor, [ 0, 2 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 2 ], 2, [ 0, 2 ], 2); TinyAssertions.assertContent(editor, '

ab  c

'); }); it('Insert in text in node with leading nbsp after inline', () => { const editor = hook.editor(); editor.setContent('

ab c

'); TinySelections.setCursor(editor, [ 0, 2 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 2 ], 2, [ 0, 2 ], 2); TinyAssertions.assertContent(editor, '

ab c

'); }); it('Insert in text in node with leading nbsp after inline with trailing nbsp', () => { const editor = hook.editor(); editor.setContent('

a c

'); TinySelections.setCursor(editor, [ 0, 2 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 2 ], 2, [ 0, 2 ], 2); TinyAssertions.assertContent(editor, '

a c

'); }); it('Insert at beginning of text node with leading nbsp after a br', () => { const editor = hook.editor(); editor.setContent('

a
 b

'); TinySelections.setCursor(editor, [ 0, 2 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 2 ], 0, [ 0, 2 ], 0); TinyAssertions.assertContent(editor, '

a
 b

'); }); it('Insert at beginning of text node with leading nbsp within inline element followed by br', () => { const editor = hook.editor(); editor.setContent('

a
 b

'); TinySelections.setCursor(editor, [ 0, 2, 0 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 2, 0 ], 0, [ 0, 2, 0 ], 0); TinyAssertions.assertContent(editor, '

a
 b

'); }); }); context('Nbsp at last character position', () => { it('Insert in text node with nbsp at end of block', () => { const editor = hook.editor(); editor.setContent('

'); TinySelections.setCursor(editor, [ 0, 0 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 0); TinyAssertions.assertContent(editor, '

'); }); it('Insert in text in node with leading nbsp after inline with trailing space', () => { const editor = hook.editor(); editor.setContent('

bc

'); TinySelections.setCursor(editor, [ 0, 0 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 0); TinyAssertions.assertContent(editor, '

bc

'); }); it('Insert in text in node with trailing nbsp before inline', () => { const editor = hook.editor(); editor.setContent('

bc

'); TinySelections.setCursor(editor, [ 0, 0 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 0); TinyAssertions.assertContent(editor, '

a bc

'); }); it('Insert in text in node with trailing nbsp before inline with leading nbsp', () => { const editor = hook.editor(); editor.setContent('

 bc

'); TinySelections.setCursor(editor, [ 0, 0 ], 0); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 0, [ 0, 0 ], 0); TinyAssertions.assertContent(editor, '

a  bc

'); }); it('Insert in text in node with single middle nbsp', () => { const editor = hook.editor(); editor.setContent('

a b

'); TinySelections.setCursor(editor, [ 0, 0 ], 3); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 3, [ 0, 0 ], 3); TinyAssertions.assertContent(editor, '

a b

'); }); it('Insert in text in node with multiple middle nbsp', () => { const editor = hook.editor(); editor.setContent('

a b c d

'); TinySelections.setCursor(editor, [ 0, 0 ], 7); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 7, [ 0, 0 ], 7); TinyAssertions.assertContent(editor, '

a b c d

'); }); it('Insert in text node multiple nbsps between inline elements', () => { const editor = hook.editor(); editor.setContent('

a  b

'); TinySelections.setCursor(editor, [ 0, 1 ], 1); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 1 ], 1, [ 0, 1 ], 1); TinyAssertions.assertContent(editor, '

a  b

'); }); }); context('Nbsp at fragmented text', () => { it('Insert nbsp at end of text block with leading empty text nodes should retain the nbsp', () => { const editor = hook.editor(); editor.setContent('

 a

'); prependEmptyTextNodesAt(editor, 3, [ 0, 0 ]); TinySelections.setCursor(editor, [ 0, 3 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 3 ], 2, [ 0, 3 ], 2); TinyAssertions.assertContent(editor, '

 a

'); }); it('Insert nbsp at end of text block with trailing empty text nodes should retain the nbsp', () => { const editor = hook.editor(); editor.setContent('

'); appendEmptyTextNodesAt(editor, 3, [ 0, 0 ]); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '

'); }); }); context('Nbsp at img', () => { it('Insert nbsp before an image at start of a block should not remove the nbsp', () => { const editor = hook.editor(); editor.setContent('

 

'); TinySelections.setCursor(editor, [ 0, 0 ], 1); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 1, [ 0, 0 ], 1); TinyAssertions.assertContent(editor, '

 

'); }); it('Insert nbsp between two images should remove nbsp', () => { const editor = hook.editor(); editor.setContent('

 

'); TinySelections.setCursor(editor, [ 0, 1 ], 1); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 1 ], 1, [ 0, 1 ], 1); TinyAssertions.assertContent(editor, '

'); }); it('Insert nbsp after an image at the end of a block should not remove the nbsp', () => { const editor = hook.editor(); editor.setContent('

 

'); TinySelections.setCursor(editor, [ 0, 1 ], 1); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 1 ], 1, [ 0, 1 ], 1); TinyAssertions.assertContent(editor, '

 

'); }); }); context('Nbsp in pre', () => { it('Trim nbsp at beginning of text in pre element', () => { const editor = hook.editor(); editor.setContent('
 a
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
 a
'); }); it('Trim nbsp at end of text in pre element', () => { const editor = hook.editor(); editor.setContent('
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
a 
'); }); it('Trim nbsp middle of text in pre element', () => { const editor = hook.editor(); editor.setContent('
a b
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
a b
'); }); }); context('Nbsp in pre: white-space: pre-wrap', () => { it('Trim nbsp at start of text in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
 a
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
 a
'); }); it('Trim nbsp at end of text in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
a 
'); }); it('Trim nbsp in middle of text in in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
a b
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
a b
'); }); }); describe('Nbsp in pre: white-space: pre-line', () => { it('Do not trim nbsp at beginning of text in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
 a
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
 a
'); }); it('Do not trim nbsp at end of text in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
'); }); it('Trim nbsp in middle of text in in white-space: pre-line element', () => { const editor = hook.editor(); editor.setContent('
a b
'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '
a b
'); }); }); context('Nbsp before/after block', () => { it('Do not trim nbsp before a block element', () => { const editor = hook.editor(); editor.setContent('

b

'); TinySelections.setCursor(editor, [ 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0 ], 2, [ 0, 0 ], 2); TinyAssertions.assertContent(editor, '

b

'); }); it('Do not trim nbsp after a block element', () => { const editor = hook.editor(); editor.setContent('

b

 a
'); TinySelections.setCursor(editor, [ 0, 1 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 1 ], 2, [ 0, 1 ], 2); TinyAssertions.assertContent(editor, '

b

 a
'); }); it('Do not trim nbsp in an inline before a block element', () => { const editor = hook.editor(); editor.setContent('

b

'); TinySelections.setCursor(editor, [ 0, 0, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 0, 0 ], 2, [ 0, 0, 0 ], 2); TinyAssertions.assertContent(editor, '

b

'); }); it('Do not trim nbsp in an inline after a block element', () => { const editor = hook.editor(); editor.setContent('

b

 a
'); TinySelections.setCursor(editor, [ 0, 1, 0 ], 2); fireInsert(editor); TinyAssertions.assertSelection(editor, [ 0, 1, 0 ], 2, [ 0, 1, 0 ], 2); TinyAssertions.assertContent(editor, '

b

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