| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /**
- * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
- */
- /* globals document */
- import createElement from '@ckeditor/ckeditor5-utils/src/dom/createelement';
- import FakeSelectionObserver from '../../../src/view/observer/fakeselectionobserver';
- import View from '../../../src/view/view';
- import DomEventData from '../../../src/view/observer/domeventdata';
- import createViewRoot from '../_utils/createroot';
- import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
- import { setData, stringify } from '../../../src/dev-utils/view';
- import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
- import { StylesProcessor } from '../../../src/view/stylesmap';
- describe( 'FakeSelectionObserver', () => {
- let observer, view, viewDocument, root, domRoot;
- testUtils.createSinonSandbox();
- before( () => {
- domRoot = createElement( document, 'div', {
- contenteditable: 'true'
- } );
- document.body.appendChild( domRoot );
- } );
- after( () => {
- domRoot.parentElement.removeChild( domRoot );
- } );
- beforeEach( () => {
- view = new View( new StylesProcessor() );
- viewDocument = view.document;
- root = createViewRoot( viewDocument );
- view.attachDomRoot( domRoot );
- observer = view.getObserver( FakeSelectionObserver );
- viewDocument.selection._setTo( null, { fake: true } );
- } );
- afterEach( () => {
- view.destroy();
- } );
- it( 'should do nothing if selection is not fake', () => {
- viewDocument.selection._setTo( null, { fake: false } );
- return checkEventPrevention( keyCodes.arrowleft, false );
- } );
- it( 'should do nothing if is disabled', () => {
- observer.disable();
- return checkEventPrevention( keyCodes.arrowleft, false );
- } );
- it( 'should prevent default for left arrow key', ( ) => {
- return checkEventPrevention( keyCodes.arrowleft );
- } );
- it( 'should prevent default for right arrow key', ( ) => {
- return checkEventPrevention( keyCodes.arrowright );
- } );
- it( 'should prevent default for up arrow key', ( ) => {
- return checkEventPrevention( keyCodes.arrowup );
- } );
- it( 'should prevent default for down arrow key', ( ) => {
- return checkEventPrevention( keyCodes.arrowdown );
- } );
- it( 'should fire selectionChange event with new selection when left arrow key is pressed', () => {
- return checkSelectionChange(
- '<container:p>foo[<strong>bar</strong>]baz</container:p>',
- keyCodes.arrowleft,
- '<container:p>foo[]<strong>bar</strong>baz</container:p>'
- );
- } );
- it( 'should fire selectionChange event with new selection when right arrow key is pressed', () => {
- return checkSelectionChange(
- '<container:p>foo[<strong>bar</strong>]baz</container:p>',
- keyCodes.arrowright,
- '<container:p>foo<strong>bar</strong>[]baz</container:p>'
- );
- } );
- it( 'should fire selectionChange event with new selection when up arrow key is pressed', () => {
- return checkSelectionChange(
- '<container:p>foo[<strong>bar</strong>]baz</container:p>',
- keyCodes.arrowup,
- '<container:p>foo[]<strong>bar</strong>baz</container:p>'
- );
- } );
- it( 'should fire selectionChange event with new selection when down arrow key is pressed', () => {
- return checkSelectionChange(
- '<container:p>foo[<strong>bar</strong>]baz</container:p>',
- keyCodes.arrowdown,
- '<container:p>foo<strong>bar</strong>[]baz</container:p>'
- );
- } );
- it( 'should fire `selectionChangeDone` event after selection stop changing', () => {
- const clock = testUtils.sinon.useFakeTimers();
- const spy = sinon.spy();
- viewDocument.on( 'selectionChangeDone', spy );
- // Change selection.
- changeFakeSelectionPressing( keyCodes.arrowdown );
- // Wait 100ms.
- clock.tick( 100 );
- // Check if spy was called.
- sinon.assert.notCalled( spy );
- // Change selection one more time.
- changeFakeSelectionPressing( keyCodes.arrowdown );
- // Wait 210ms (debounced function should be called).
- clock.tick( 210 );
- sinon.assert.calledOnce( spy );
- } );
- it( 'should not fire `selectionChangeDone` event when observer will be destroyed', () => {
- const clock = testUtils.sinon.useFakeTimers();
- const spy = sinon.spy();
- viewDocument.on( 'selectionChangeDone', spy );
- // Change selection.
- changeFakeSelectionPressing( keyCodes.arrowdown );
- // Wait 100ms.
- clock.tick( 100 );
- // And destroy observer.
- observer.destroy();
- // Wait another 110ms.
- clock.tick( 110 );
- // Check that event won't be called.
- sinon.assert.notCalled( spy );
- } );
- // Checks if preventDefault method was called by FakeSelectionObserver for specified key code.
- //
- // @param {Number} keyCode
- // @param {Boolean} shouldPrevent If set to true method checks if event was prevented.
- // @returns {Promise}
- function checkEventPrevention( keyCode, shouldPrevent = true ) {
- return new Promise( resolve => {
- const data = {
- keyCode,
- preventDefault: sinon.spy()
- };
- viewDocument.once( 'keydown', () => {
- if ( shouldPrevent ) {
- sinon.assert.calledOnce( data.preventDefault );
- } else {
- sinon.assert.notCalled( data.preventDefault );
- }
- resolve();
- }, { priority: 'lowest' } );
- viewDocument.fire( 'keydown', new DomEventData( viewDocument, { target: document.body }, data ) );
- } );
- }
- // Checks if proper selectionChange event is fired by FakeSelectionObserver for specified key.
- //
- // @param {String} initialData
- // @param {Number} keyCode
- // @param {String} output
- // @returns {Promise}
- function checkSelectionChange( initialData, keyCode, output ) {
- return new Promise( resolve => {
- viewDocument.once( 'selectionChange', ( eventInfo, data ) => {
- expect( stringify( root.getChild( 0 ), data.newSelection, { showType: true } ) ).to.equal( output );
- resolve();
- } );
- setData( view, initialData );
- changeFakeSelectionPressing( keyCode );
- } );
- }
- // Sets fake selection to the document and fire `keydown` event what cause `selectionChange` event.
- //
- // @param {Number} keyCode
- function changeFakeSelectionPressing( keyCode ) {
- viewDocument.selection._setTo( viewDocument.selection.getRanges(), {
- backward: viewDocument.selection.isBackward,
- fake: true
- } );
- const data = {
- keyCode,
- preventDefault: sinon.spy()
- };
- viewDocument.fire( 'keydown', new DomEventData( viewDocument, { target: document.body }, data ) );
- }
- } );
|