Selaa lähdekoodia

Mutation Observer tests.

Piotr Jasiun 9 vuotta sitten
vanhempi
sitoutus
58c9735089

+ 10 - 2
packages/ckeditor5-engine/src/treeview/domconverter.js

@@ -188,10 +188,10 @@ export default class DomConverter {
 		}
 
 		if ( domNode instanceof Text ) {
-			if ( this.isInlineFiller( domNode )  ) {
+			if ( this.isInlineFiller( domNode ) ) {
 				return null;
 			} else {
-				return new ViewText( domNode.data );
+				return new ViewText( this.getDataWithoutFiller( domNode ) );
 			}
 		} else {
 			if ( this.getCorrespondingView( domNode ) ) {
@@ -538,6 +538,14 @@ export default class DomConverter {
 		return domText.data.length == INLINE_FILLER_SIZE && this.startsWithFiller( domText );
 	}
 
+	getDataWithoutFiller( domText ) {
+		if ( this.startsWithFiller( domText ) ) {
+			return domText.data.slice( INLINE_FILLER_SIZE );
+		} else {
+			return domText.data;
+		}
+	}
+
 	isBlockFiller( domNode ) {
 		return domNode.isEqualNode( this._templateBlockFiller );
 	}

+ 1 - 1
packages/ckeditor5-engine/src/treeview/observer/mutationobserver.js

@@ -146,7 +146,7 @@ export default class MutationObserver extends Observer {
 					mutatedTexts.set( text, {
 						type: 'text',
 						oldText: text.data,
-						newText: mutation.target.data,
+						newText: domConverter.getDataWithoutFiller( mutation.target ),
 						node: text
 					} );
 				} else if ( !text && domConverter.startsWithFiller( mutation.target ) ) {

+ 7 - 1
packages/ckeditor5-engine/src/treeview/renderer.js

@@ -291,7 +291,13 @@ export default class Renderer {
 		const expectedDomChildren = Array.from( domConverter.viewChildrenToDom( viewElement, domDocument, { bind: true } ) );
 
 		if ( filler && filler.parent == viewElement ) {
-			expectedDomChildren.splice( filler.offset, 0, domDocument.createTextNode( INLINE_FILLER ) );
+			const expectedNoteAfterFiller = expectedDomChildren[ filler.offset ];
+
+			if ( expectedNoteAfterFiller instanceof Text ) {
+				expectedNoteAfterFiller.data = INLINE_FILLER + expectedNoteAfterFiller.data;
+			} else {
+				expectedDomChildren.splice( filler.offset, 0, domDocument.createTextNode( INLINE_FILLER ) );
+			}
 		}
 
 		const actions = diff( actualDomChildren, expectedDomChildren, sameNodes );

+ 76 - 10
packages/ckeditor5-engine/tests/treeview/observer/mutationobserver.js

@@ -8,9 +8,8 @@
 'use strict';
 
 import TreeView from '/ckeditor5/engine/treeview/treeview.js';
-import Element from '/ckeditor5/engine/treeview/element.js';
-import Text from '/ckeditor5/engine/treeview/text.js';
 import MutationObserver from '/ckeditor5/engine/treeview/observer/mutationobserver.js';
+import { parse } from '/tests/engine/_utils/view.js';
 
 describe( 'MutationObserver', () => {
 	let domEditor, treeView, viewRoot, mutationObserver, lastMutations;
@@ -21,6 +20,8 @@ describe( 'MutationObserver', () => {
 		lastMutations = null;
 
 		treeView.createRoot( domEditor, 'editor' );
+		treeView.selection.removeAllRanges();
+		document.getSelection().removeAllRanges();
 
 		treeView.addObserver( MutationObserver );
 		mutationObserver = treeView.getObserver( MutationObserver );
@@ -29,10 +30,7 @@ describe( 'MutationObserver', () => {
 
 		viewRoot = treeView.viewRoots.get( 'editor' );
 
-		viewRoot.insertChildren( 0, [
-			new Element( 'p', [], [ new Text( 'foo' ) ] ),
-			new Element( 'p', [], [ new Text( 'bar' ) ] )
-		] );
+		viewRoot.appendChildren( parse( '<container:p>foo</container:p><container:p>bar</container:p>' ) );
 
 		treeView.render();
 	} );
@@ -112,10 +110,8 @@ describe( 'MutationObserver', () => {
 		// Prepare editor2
 		treeView.createRoot( domEditor2, 'editor2' );
 
-		treeView.viewRoots.get( 'editor2' ).insertChildren( 0, [
-			new Element( 'p', [], [ new Text( 'foo' ) ] ),
-			new Element( 'p', [], [ new Text( 'bar' ) ] )
-		] );
+		treeView.viewRoots.get( 'editor2' ).appendChildren(
+			parse( '<container:p>foo</container:p><container:p>bar</container:p>' ) );
 
 		// Render editor2 (first editor has been rendered in the beforeEach function)
 		treeView.render();
@@ -128,6 +124,76 @@ describe( 'MutationObserver', () => {
 		expect( lastMutations.length ).to.equal( 2 );
 	} );
 
+	it( 'should fire nothing if there were no mutations', () => {
+		mutationObserver.flush();
+
+		expectDomEditorNotToChange();
+		expect( lastMutations ).to.be.null;
+	} );
+
+	it( 'should fire children mutation if the mutation occurred in the inline filler', () => {
+		const { view, selection } = parse( '<container:p>foo<attribute:b>[]</attribute:b>bar</container:p>' );
+
+		viewRoot.appendChildren( view );
+		treeView.selection.setTo( selection );
+
+		treeView.render();
+
+		const inlineFiller = domEditor.childNodes[ 2 ].childNodes[ 1 ].childNodes[ 0 ];
+		inlineFiller.data += 'x';
+
+		mutationObserver.flush();
+
+		expect( lastMutations.length ).to.equal( 1 );
+		expect( lastMutations[ 0 ].type ).to.equal( 'children' );
+		expect( lastMutations[ 0 ].node ).to.equal( selection.getFirstPosition().parent );
+	} );
+
+	it( 'should have no inline filler in mutation', () => {
+		const { view, selection } = parse( '<container:p>foo<attribute:b>[]</attribute:b>bar</container:p>' );
+
+		viewRoot.appendChildren( view );
+		treeView.selection.setTo( selection );
+
+		treeView.render();
+
+		let inlineFiller = domEditor.childNodes[ 2 ].childNodes[ 1 ].childNodes[ 0 ];
+		inlineFiller.data += 'x';
+
+		view.getChild( 1 ).appendChildren( parse( 'x' ) );
+		mutationObserver.flush();
+		treeView.render();
+
+		inlineFiller = domEditor.childNodes[ 2 ].childNodes[ 1 ].childNodes[ 0 ];
+		inlineFiller.data += 'y';
+
+		mutationObserver.flush();
+
+		expect( lastMutations.length ).to.equal( 1 );
+		expect( lastMutations[ 0 ].type ).to.equal( 'text' );
+		expect( lastMutations[ 0 ].oldText ).to.equal( 'x' );
+		expect( lastMutations[ 0 ].newText ).to.equal( 'xy' );
+	} );
+
+	it( 'should have no block filler in mutation', () => {
+		viewRoot.appendChildren( parse( '<container:p></container:p>' ) );
+
+		treeView.render();
+
+		const domP = domEditor.childNodes[ 2 ];
+		domP.removeChild( domP.childNodes[ 0 ] );
+		domP.appendChild( document.createTextNode( 'foo' ) );
+
+		mutationObserver.flush();
+
+		expect( lastMutations.length ).to.equal( 1 );
+
+		expect( lastMutations[ 0 ].newChildren.length ).to.equal( 1 );
+		expect( lastMutations[ 0 ].newChildren[ 0 ].data ).to.equal( 'foo' );
+
+		expect( lastMutations[ 0 ].oldChildren.length ).to.equal( 0 );
+	} );
+
 	function expectDomEditorNotToChange() {
 		expect( domEditor.childNodes.length ).to.equal( 2 );
 		expect( domEditor.childNodes[ 0 ].tagName ).to.equal( 'P' );