Przeglądaj źródła

Added tests checking renderer issue #922.

Szymon Kupś 8 lat temu
rodzic
commit
1b713c2703

+ 2 - 2
packages/ckeditor5-engine/src/view/observer/focusobserver.js

@@ -35,7 +35,7 @@ export default class FocusObserver extends DomEventObserver {
 			// We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will
 			// overwrite new DOM selection with selection from the view.
 			// See https://github.com/ckeditor/ckeditor5-engine/issues/795 for more details.
-			this._renderTimeoutId = setTimeout( () => document.render(), 0 );
+			// this._renderTimeoutId = setTimeout( () => document.render(), 0 );
 		} );
 
 		document.on( 'blur', ( evt, data ) => {
@@ -45,7 +45,7 @@ export default class FocusObserver extends DomEventObserver {
 				document.isFocused = false;
 
 				// Re-render the document to update view elements.
-				document.render();
+				// document.render();
 			}
 		} );
 

+ 8 - 1
packages/ckeditor5-engine/src/view/renderer.js

@@ -190,7 +190,7 @@ export default class Renderer {
 		if ( this._inlineFiller ) {
 			inlineFillerPosition = this._getInlineFillerPosition();
 		}
-		// Othewise, if it's needed, create it at the selection position.
+		// Otherwise, if it's needed, create it at the selection position.
 		else if ( this._needsInlineFillerAtSelection() ) {
 			inlineFillerPosition = this.selection.getFirstPosition();
 
@@ -464,20 +464,27 @@ export default class Renderer {
 		const actions = diff( actualDomChildren, expectedDomChildren, sameNodes );
 
 		let i = 0;
+		const nodesToUnbind = new Set();
 
 		for ( const action of actions ) {
 			if ( action === 'insert' ) {
+				// this.domConverter.bindElements( expectedDomChildren[ i ],  );
 				insertAt( domElement, i, expectedDomChildren[ i ] );
+				// TODO: bind element it might be unbind when deleting before.
 				i++;
 			} else if ( action === 'delete' ) {
 				// Whenever element is removed from DOM, unbind it and all of its children.
 				this.domConverter.unbindDomElement( actualDomChildren[ i ] );
+				// nodesToUnbind.add( actualDomChildren[ i ] );
+
 				remove( actualDomChildren[ i ] );
 			} else { // 'equal'
 				i++;
 			}
 		}
 
+
+
 		function sameNodes( actualDomChild, expectedDomChild ) {
 			// Elements.
 			if ( actualDomChild === expectedDomChild ) {

+ 113 - 0
packages/ckeditor5-engine/tests/tickets/922.js

@@ -0,0 +1,113 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* global document */
+
+import { setData as setViewData, getData as getViewData } from '../../src/dev-utils/view';
+import ViewDocument from '../../src/view/document';
+import { unwrap, insert } from '../../src/view/writer';
+import ViewAttributeElement from '../../src/view/attributeelement';
+import ViewPosition from '../../src/view/position';
+import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
+
+describe( 'Bug ckeditor5-engine#922', () => {
+	let viewDoc, viewRoot, domRoot;
+
+	beforeEach( () => {
+		viewDoc = new ViewDocument();
+		domRoot = document.createElement( 'div' );
+		document.body.appendChild( domRoot );
+		viewRoot = viewDoc.createRoot( domRoot );
+	} );
+
+	it( 'should properly render unwrapped attributes #1', () => {
+		setViewData( viewDoc,
+			'<container:p>' +
+				'[<attribute:italic>' +
+					'<attribute:strong>f</attribute:strong>' +
+				'</attribute:italic>]' +
+				'<attribute:strong>oo</attribute:strong>' +
+			'</container:p>'
+		);
+
+		// Render it to DOM to create initial DOM <-> view mappings.
+		viewDoc.render();
+
+		// Unwrap italic attribute element.
+		unwrap( viewDoc.selection.getFirstRange(), new ViewAttributeElement( 'italic' ) );
+		expect( getViewData( viewDoc ) ).to.equal( '<p>[<strong>foo</strong>]</p>' );
+
+		// Re-render changes in view to DOM.
+		viewDoc.render();
+
+		// Check if DOM is rendered correctly.
+		expect( normalizeHtml( domRoot.innerHTML ) ).to.equal( '<p><strong>foo</strong></p>' );
+	} );
+
+	it( 'should properly render unwrapped attributes #2', () => {
+		setViewData( viewDoc,
+			'<container:p>' +
+				'[<attribute:italic>' +
+					'<attribute:strong>foo</attribute:strong>' +
+				'</attribute:italic>]' +
+			'</container:p>' );
+
+		// Render it to DOM to create initial DOM <-> view mappings.
+		viewDoc.render();
+
+		// Unwrap italic attribute element and change text inside.
+		unwrap( viewDoc.selection.getFirstRange(), new ViewAttributeElement( 'italic' ) );
+		viewRoot.getChild( 0 ).getChild( 0 ).getChild( 0 ).data = 'bar';
+		expect( getViewData( viewDoc ) ).to.equal( '<p>[<strong>bar</strong>]</p>' );
+
+		// Re-render changes in view to DOM.
+		viewDoc.render();
+
+		// Check if DOM is rendered correctly.
+		expect( normalizeHtml( domRoot.innerHTML ) ).to.equal( '<p><strong>bar</strong></p>' );
+	} );
+
+	it( 'should properly render if text is changed and element is inserted into same node #1', () => {
+		setViewData( viewDoc,
+			'<container:p>foo</container:p>'
+		);
+
+		// Render it to DOM to create initial DOM <-> view mappings.
+		viewDoc.render();
+
+		// Change text and insert new element into paragraph.
+		const textNode = viewRoot.getChild( 0 ).getChild( 0 );
+		textNode.data = 'foobar';
+		insert( ViewPosition.createAfter( textNode ), new ViewAttributeElement( 'img' ) );
+		expect( getViewData( viewDoc ) ).to.equal( '<p>foobar<img></img></p>' );
+
+		// Re-render changes in view to DOM.
+		viewDoc.render();
+
+		// Check if DOM is rendered correctly.
+		expect( normalizeHtml( domRoot.innerHTML ) ).to.equal( '<p>foobar<img></img></p>' );
+	} );
+
+	it( 'should properly render if text is changed and element is inserted into same node #2', () => {
+		setViewData( viewDoc,
+			'<container:p>foo</container:p>'
+		);
+
+		// Render it to DOM to create initial DOM <-> view mappings.
+		viewDoc.render();
+
+		// Change text and insert new element into paragraph.
+		const textNode = viewRoot.getChild( 0 ).getChild( 0 );
+		textNode.data = 'foobar';
+		insert( ViewPosition.createBefore( textNode ), new ViewAttributeElement( 'img' ) );
+		expect( getViewData( viewDoc ) ).to.equal( '<p><img></img>foobar</p>' );
+
+		// Re-render changes in view to DOM.
+		viewDoc.render();
+
+		// Check if DOM is rendered correctly.
+		expect( normalizeHtml( domRoot.innerHTML ) ).to.equal( '<p><img></img>foobar</p>' );
+	} );
+} );