diff --git a/src/input.js b/src/input.js index 394c674..fbfc410 100644 --- a/src/input.js +++ b/src/input.js @@ -408,9 +408,10 @@ function getMutationsContainer( mutations ) { .find( element => element.is( 'containerElement' ) || element.is( 'rootElement' ) ); } -// Returns true if container children have mutated and more than a single text node was changed. Single text node -// child insertion is handled in {@link module:typing/input~MutationHandler#_handleTextNodeInsertion} and text -// mutation is handled in {@link module:typing/input~MutationHandler#_handleTextMutation}. +// Returns true if container children have mutated or more than a single text node was changed. +// +// Single text node child insertion is handled in {@link module:typing/input~MutationHandler#_handleTextNodeInsertion} +// while text mutation is handled in {@link module:typing/input~MutationHandler#_handleTextMutation}. // // @private // @param {Array. { return VirtualTestEditor .create( { - plugins: [ Input, Paragraph ] + plugins: [ Input, Paragraph, Bold ] } ) .then( newEditor => { // Mock image feature. @@ -126,6 +126,50 @@ describe( 'Input feature', () => { expect( getViewData( view ) ).to.equal( '

x{}

' ); } ); + it( 'should handle multiple text mutations', () => { + editor.setData( '

foobar

' ); + + view.fire( 'mutations', [ + { + type: 'text', + oldText: 'foo', + newText: 'foob', + node: viewRoot.getChild( 0 ).getChild( 0 ) + }, + { + type: 'text', + oldText: 'bar', + newText: 'ar', + node: viewRoot.getChild( 0 ).getChild( 1 ).getChild( 0 ) + } + ] ); + + expect( getModelData( model ) ).to.equal( 'foob[]<$text bold="true">ar' ); + expect( getViewData( view ) ).to.equal( '

foob{}ar

' ); + } ); + + it( 'should handle multiple text node insertion', () => { + editor.setData( '

' ); + + view.fire( 'mutations', [ + { + type: 'children', + oldChildren: [], + newChildren: [ new ViewText( 'x' ) ], + node: viewRoot.getChild( 0 ) + }, + { + type: 'children', + oldChildren: [], + newChildren: [ new ViewText( 'y' ) ], + node: viewRoot.getChild( 1 ) + } + ] ); + + expect( getModelData( model ) ).to.equal( 'xy[]' ); + expect( getViewData( view ) ).to.equal( '

x

y{}

' ); + } ); + it( 'should do nothing when two nodes were inserted', () => { editor.setData( '

' ); @@ -947,6 +991,36 @@ describe( 'Input feature', () => { expect( getModelData( model ) ).to.equal( '<$text bold="true">[]textx' ); expect( getViewData( view ) ).to.equal( '

{}textx

' ); } ); + + // #117. + it( 'should handle mixed mutations', () => { + setModelData( model, '<$text bold="true">Foo bar aple' ); + + const paragraph = viewRoot.getChild( 0 ); + const strong = paragraph.getChild( 0 ); + const viewSelection = new ViewSelection(); + viewSelection.setCollapsedAt( paragraph, 0 ); + + // Simulate mutations and DOM change. + domRoot.childNodes[ 0 ].innerHTML = 'Foo bar apple'; + view.fire( 'mutations', [ + { + type: 'text', + oldText: 'Foo bar aple', + newText: 'Foo bar ', + node: viewRoot.getChild( 0 ).getChild( 0 ) + }, + { + type: 'children', + oldChildren: [ strong ], + newChildren: [ strong, new ViewElement( 'b', null, new ViewText( 'apple' ) ) ], + node: paragraph + } + ], viewSelection ); + + expect( getModelData( model ) ).to.equal( '<$text bold="true">[]Foo bar apple' ); + expect( getViewData( view ) ).to.equal( '

{}Foo bar apple

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