| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /**
- * @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, setTimeout, window */
- import ContextWatchdog from '../src/contextwatchdog';
- import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
- import Context from '@ckeditor/ckeditor5-core/src/context';
- import sinon from 'sinon';
- import { expect } from 'chai';
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
- describe( 'ContextWatchdog', () => {
- let element1, element2;
- let mainWatchdog;
- beforeEach( () => {
- element1 = document.createElement( 'div' );
- element2 = document.createElement( 'div' );
- document.body.appendChild( element1 );
- document.body.appendChild( element2 );
- } );
- afterEach( () => {
- element1.remove();
- element2.remove();
- sinon.restore();
- } );
- it.skip( 'case: editor, contextItem', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- mainWatchdog.add( {
- editor1: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element1,
- config: {}
- },
- annotatedInput: {
- type: 'contextItem',
- creator: () => { }
- }
- } );
- await mainWatchdog.waitForReady();
- await mainWatchdog.destroy();
- } );
- describe( 'for no items added', () => {
- it( 'should create only context', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- await mainWatchdog.waitForReady();
- expect( mainWatchdog.context ).to.be.instanceOf( Context );
- await mainWatchdog.destroy();
- } );
- it( 'should have proper states', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- expect( mainWatchdog.state ).to.equal( 'initializing' );
- await mainWatchdog.waitForReady();
- expect( mainWatchdog.state ).to.equal( 'ready' );
- await mainWatchdog.destroy();
- expect( mainWatchdog.state ).to.equal( 'destroyed' );
- } );
- describe( 'in case of error handling', () => {
- it( 'should restart the `Context`', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- const errorSpy = sinon.spy();
- await mainWatchdog.waitForReady();
- const oldContext = mainWatchdog.context;
- const originalErrorHandler = window.onerror;
- window.onerror = sinon.spy();
- mainWatchdog.on( 'restart', errorSpy );
- setTimeout( () => throwCKEditorError( 'foo', mainWatchdog.context ) );
- await waitCycle();
- sinon.assert.calledOnce( errorSpy );
- expect( mainWatchdog.context ).to.not.equal( oldContext );
- window.onerror = originalErrorHandler;
- } );
- } );
- } );
- describe( 'for multiple editors', () => {
- it( 'should allow adding multiple items without waiting', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- mainWatchdog.add( {
- editor1: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element1,
- config: {}
- },
- } );
- mainWatchdog.add( {
- editor2: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element2,
- config: {}
- },
- } );
- await mainWatchdog.waitForReady();
- await mainWatchdog.destroy();
- } );
- it( 'should allow adding and removing items without waiting', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- mainWatchdog.add( {
- editor1: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element1,
- config: {}
- },
- } );
- mainWatchdog.add( {
- editor2: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element2,
- config: {}
- },
- } );
- await mainWatchdog.waitForReady();
- expect( mainWatchdog.state ).to.equal( 'ready' );
- mainWatchdog.remove( [ 'editor1' ] );
- await mainWatchdog.waitForReady();
- mainWatchdog.remove( [ 'editor2' ] );
- await mainWatchdog.waitForReady();
- await mainWatchdog.destroy();
- } );
- describe( 'in case of error handling', () => {
- it( 'should restart the whole structure of editors if an error happens inside the `Context`', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- mainWatchdog.add( {
- editor1: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element1,
- config: {}
- }
- } );
- await mainWatchdog.waitForReady();
- const oldContext = mainWatchdog.context;
- const restartSpy = sinon.spy();
- const originalErrorHandler = window.onerror;
- window.onerror = sinon.spy();
- mainWatchdog.on( 'error', () => {
- window.onerror = originalErrorHandler;
- } );
- mainWatchdog.on( 'restart', restartSpy );
- setTimeout( () => throwCKEditorError( 'foo', mainWatchdog.context ) );
- await waitCycle();
- sinon.assert.calledOnce( restartSpy );
- expect( mainWatchdog.context ).to.not.equal( oldContext );
- window.onerror = originalErrorHandler;
- } );
- } );
- } );
- it( 'case: recreating watchdog', async () => {
- mainWatchdog = ContextWatchdog.for( Context, {} );
- await mainWatchdog.destroy();
- let err;
- try {
- await mainWatchdog.add( {
- editor2: {
- type: 'editor',
- creator: ( el, config ) => ClassicTestEditor.create( el, config ),
- sourceElementOrData: element1,
- config: {}
- },
- } );
- } catch ( _err ) {
- err = _err;
- }
- expect( err ).to.be.instanceOf( Error );
- expect( err.message ).to.match( /Cannot add items do destroyed watchdog\./ );
- } );
- } );
- function throwCKEditorError( name, context ) {
- throw new CKEditorError( name, context );
- }
- function waitCycle() {
- return new Promise( res => setTimeout( res ) );
- }
|