Selaa lähdekoodia

SelectionObserver small fixes and tests.

Piotr Jasiun 9 vuotta sitten
vanhempi
sitoutus
c097bd87dd

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

@@ -29,7 +29,6 @@ export default class SelectionObserver extends Observer {
 		if ( this.documents.has( domDocument ) ) {
 			return;
 		}
-		this._handleSelectionChange();
 
 		domDocument.addEventListener( 'selectionchange', () => this._handleSelectionChange( domDocument ) );
 
@@ -62,4 +61,4 @@ export default class SelectionObserver extends Observer {
 
 		this.treeView.render();
 	}
-}
+}

+ 2 - 0
packages/ckeditor5-engine/tests/treeview/observer/__template__.html

@@ -0,0 +1,2 @@
+<div contenteditable="true" id="editor"></div>
+<div contenteditable="true" id="editor2"></div>

+ 0 - 2
packages/ckeditor5-engine/tests/treeview/observer/mutationobserver.html

@@ -1,2 +0,0 @@
-<div contenteditable="true" id="editor"></div>
-<div contenteditable="true" id="editor2"></div>

+ 147 - 0
packages/ckeditor5-engine/tests/treeview/observer/selectionobserver.js

@@ -0,0 +1,147 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* bender-tags: treeview */
+
+'use strict';
+
+import ViewRange from '/ckeditor5/engine/treeview/range.js';
+import ViewSelection from '/ckeditor5/engine/treeview/selection.js';
+import TreeView from '/ckeditor5/engine/treeview/treeview.js';
+import SelectionObserver from '/ckeditor5/engine/treeview/observer/selectionobserver.js';
+import MutationObserver from '/ckeditor5/engine/treeview/observer/mutationobserver.js';
+
+import EmitterMixin from '/ckeditor5/utils/emittermixin.js';
+
+import { parse } from '/tests/engine/_utils/view.js';
+
+describe( 'SelectionObserver', () => {
+	let treeView, viewRoot, mutationObserver, selectionObserver, listenter;
+
+	before( () => {
+		listenter = Object.create( EmitterMixin );
+
+		treeView = new TreeView();
+
+		treeView.createRoot( document.getElementById( 'editor' ) );
+
+		mutationObserver = treeView.addObserver( MutationObserver );
+		selectionObserver = treeView.addObserver( SelectionObserver );
+
+		viewRoot = treeView.getRoot();
+
+		viewRoot.appendChildren( parse( '<container:p>foo</container:p><container:p>bar</container:p>' ) );
+
+		treeView.render();
+	} );
+
+	beforeEach( ( done ) => {
+		treeView.selection.removeAllRanges();
+		document.getSelection().removeAllRanges();
+
+		treeView.getObserver( SelectionObserver ).enable();
+
+		// Ensure selectionchange will not be fired.
+		setTimeout( () => done(), 100 );
+	} );
+
+	afterEach( () => {
+		listenter.stopListening();
+	} );
+
+	it( 'should fire selectionchange when it is the only change', ( done ) => {
+		listenter.listenTo( treeView, 'selectionchange', ( evt, data ) => {
+			expect( data ).to.have.property( 'domSelection' ).that.equals( document.getSelection() );
+
+			expect( data ).to.have.property( 'oldSelection' ).that.is.instanceof( ViewSelection );
+			expect( data.oldSelection.rangeCount ).to.equal( 0 );
+
+			expect( data ).to.have.property( 'newSelection' ).that.is.instanceof( ViewSelection );
+			expect( data.newSelection.rangeCount ).to.equal( 1 );
+
+			const newViewRange = data.newSelection.getFirstRange();
+			const viewFoo = treeView.getRoot().getChild( 0 ).getChild( 0 );
+
+			expect( newViewRange.start.parent ).to.equal( viewFoo );
+			expect( newViewRange.start.offset ).to.equal( 1 );
+			expect( newViewRange.end.parent ).to.equal( viewFoo );
+			expect( newViewRange.end.offset ).to.equal( 2 );
+
+			done();
+		} );
+
+		changeDomSelection();
+	} );
+
+	it( 'should add only one listener to one document', ( done ) => {
+		// Add second roots to ensure that listener is added once.
+		treeView.createRoot( document.getElementById( 'editor2' ), 'editor2' );
+
+		listenter.listenTo( treeView, 'selectionchange', () => {
+			done();
+		} );
+
+		changeDomSelection();
+	} );
+
+	it( 'should not fire selectionchange on render', ( done ) => {
+		listenter.listenTo( treeView, 'selectionchange', () => {
+			throw 'selectionchange on render';
+		} );
+
+		setTimeout( () => done(), 70 );
+
+		const viewBar = treeView.getRoot().getChild( 1 ).getChild( 0 );
+		treeView.selection.addRange( ViewRange.createFromParentsAndOffsets( viewBar, 1, viewBar, 2 ) );
+		treeView.render();
+	} );
+
+	it( 'should not fired if observer is disabled', ( done ) => {
+		treeView.getObserver( SelectionObserver ).disable();
+
+		listenter.listenTo( treeView, 'selectionchange', () => {
+			throw 'selectionchange on render';
+		} );
+
+		setTimeout( () => done(), 70 );
+
+		changeDomSelection();
+	} );
+
+	it( 'should call render after selection change which reset selection if it was not changed', ( done ) => {
+		const viewBar = treeView.getRoot().getChild( 1 ).getChild( 0 );
+		treeView.selection.addRange( ViewRange.createFromParentsAndOffsets( viewBar, 0, viewBar, 1 ) );
+
+		listenter.listenTo( treeView, 'selectionchange', () => {
+			setTimeout( () => {
+				const domSelection = document.getSelection();
+
+				expect( domSelection.rangeCount ).to.equal( 1 );
+
+				const domRange = domSelection.getRangeAt( 0 );
+				const domBar = document.getElementById( 'editor' ).childNodes[ 1 ].childNodes[ 0 ];
+
+				expect( domRange.startContainer ).to.equal( domBar );
+				expect( domRange.startOffset ).to.equal( 0 );
+				expect( domRange.endContainer ).to.equal( domBar );
+				expect( domRange.endOffset ).to.equal( 1 );
+
+				done();
+			} );
+		} );
+
+		changeDomSelection();
+	} );
+} );
+
+function changeDomSelection() {
+	const domSelection = document.getSelection();
+	domSelection.removeAllRanges();
+	const domFoo = document.getElementById( 'editor' ).childNodes[ 0 ].childNodes[ 0 ];
+	const domRange = new Range();
+	domRange.setStart( domFoo, 1 );
+	domRange.setEnd( domFoo, 2 );
+	domSelection.addRange( domRange );
+}