8
0
Maciej Bukowski 6 лет назад
Родитель
Сommit
465b5efeb4
2 измененных файлов с 65 добавлено и 43 удалено
  1. 2 1
      packages/ckeditor5-watchdog/src/watchdog.js
  2. 63 42
      packages/ckeditor5-watchdog/tests/watchdog.js

+ 2 - 1
packages/ckeditor5-watchdog/src/watchdog.js

@@ -235,7 +235,7 @@ export default class Watchdog {
 		} );
 		} );
 
 
 		return Promise.resolve()
 		return Promise.resolve()
-			.then( () => this._creator( elementOrData, config ) )
+			.then( () => this._creator( elementOrData, this._config ) )
 			.then( editor => {
 			.then( editor => {
 				this._editor = editor;
 				this._editor = editor;
 
 
@@ -261,6 +261,7 @@ export default class Watchdog {
 
 
 		return Promise.resolve()
 		return Promise.resolve()
 			.then( () => this.destroy() )
 			.then( () => this.destroy() )
+			.catch( err => console.error( 'An error happened during the editor destructing.', err ) )
 			.then( () => {
 			.then( () => {
 				if ( typeof this._elementOrData === 'string' ) {
 				if ( typeof this._elementOrData === 'string' ) {
 					return this.create( this._data, this._config );
 					return this.create( this._data, this._config );

+ 63 - 42
packages/ckeditor5-watchdog/tests/watchdog.js

@@ -12,15 +12,15 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 
 describe( 'Watchdog', () => {
 describe( 'Watchdog', () => {
-	let sourceElement;
+	let element;
 
 
 	beforeEach( () => {
 	beforeEach( () => {
-		sourceElement = document.createElement( 'div' );
-		document.body.appendChild( sourceElement );
+		element = document.createElement( 'div' );
+		document.body.appendChild( element );
 	} );
 	} );
 
 
 	afterEach( () => {
 	afterEach( () => {
-		sourceElement.remove();
+		element.remove();
 		sinon.restore();
 		sinon.restore();
 	} );
 	} );
 
 
@@ -34,7 +34,7 @@ describe( 'Watchdog', () => {
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setDestructor( editor => editor.destroy() );
 			watchdog.setDestructor( editor => editor.destroy() );
 
 
-			return watchdog.create( sourceElement, {} )
+			return watchdog.create( element, {} )
 				.then( () => {
 				.then( () => {
 					sinon.assert.calledOnce( editorCreateSpy );
 					sinon.assert.calledOnce( editorCreateSpy );
 					sinon.assert.notCalled( editorDestroySpy );
 					sinon.assert.notCalled( editorDestroySpy );
@@ -68,6 +68,22 @@ describe( 'Watchdog', () => {
 				null
 				null
 			);
 			);
 		} );
 		} );
+
+		it( 'should properly copy the config', () => {
+			const watchdog = new Watchdog();
+			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
+			watchdog.setDestructor( editor => editor.destroy() );
+
+			const config = {
+				foo: [],
+				bar: document.createElement( 'div' )
+			};
+
+			return watchdog.create( element, config ).then( () => {
+				expect( watchdog.editor.config._config.foo ).to.not.equal( config.foo );
+				expect( watchdog.editor.config._config.bar ).to.equal( config.bar );
+			} );
+		} );
 	} );
 	} );
 
 
 	describe( 'restart()', () => {
 	describe( 'restart()', () => {
@@ -80,7 +96,7 @@ describe( 'Watchdog', () => {
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setDestructor( editor => editor.destroy() );
 			watchdog.setDestructor( editor => editor.destroy() );
 
 
-			return watchdog.create( sourceElement, {} )
+			return watchdog.create( element, {} )
 				.then( () => {
 				.then( () => {
 					sinon.assert.calledOnce( editorCreateSpy );
 					sinon.assert.calledOnce( editorCreateSpy );
 					sinon.assert.notCalled( editorDestroySpy );
 					sinon.assert.notCalled( editorDestroySpy );
@@ -101,7 +117,7 @@ describe( 'Watchdog', () => {
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
 			watchdog.setDestructor( editor => editor.destroy() );
 			watchdog.setDestructor( editor => editor.destroy() );
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} )
 			} )
@@ -148,7 +164,7 @@ describe( 'Watchdog', () => {
 
 
 			let oldEditor;
 			let oldEditor;
 
 
-			return watchdog.create( sourceElement, {} )
+			return watchdog.create( element, {} )
 				.then( () => {
 				.then( () => {
 					oldEditor = watchdog.editor;
 					oldEditor = watchdog.editor;
 					expect( watchdog.editor ).to.be.instanceOf( ClassicTestEditor );
 					expect( watchdog.editor ).to.be.instanceOf( ClassicTestEditor );
@@ -177,7 +193,7 @@ describe( 'Watchdog', () => {
 			);
 			);
 			watchdog.setDestructor( editor => editor.destroy() );
 			watchdog.setDestructor( editor => editor.destroy() );
 
 
-			return watchdog.create( sourceElement ).then(
+			return watchdog.create( element ).then(
 				() => { throw new Error( '`watchdog.create()` should throw an error.' ); },
 				() => { throw new Error( '`watchdog.create()` should throw an error.' ); },
 				err => {
 				err => {
 					expect( err ).to.be.instanceOf( Error );
 					expect( err ).to.be.instanceOf( Error );
@@ -193,7 +209,7 @@ describe( 'Watchdog', () => {
 			watchdog.setDestructor( () => Promise.reject( new Error( 'foo' ) ) );
 			watchdog.setDestructor( () => Promise.reject( new Error( 'foo' ) ) );
 
 
 			return Promise.resolve()
 			return Promise.resolve()
-				.then( () => watchdog.create( sourceElement ) )
+				.then( () => watchdog.create( element ) )
 				.then( () => watchdog.destroy() )
 				.then( () => watchdog.destroy() )
 				.then(
 				.then(
 					() => { throw new Error( '`watchdog.create()` should throw an error.' ); },
 					() => { throw new Error( '`watchdog.create()` should throw an error.' ); },
@@ -215,7 +231,7 @@ describe( 'Watchdog', () => {
 			const windowErrorSpy = sinon.spy();
 			const windowErrorSpy = sinon.spy();
 			window.onerror = windowErrorSpy;
 			window.onerror = windowErrorSpy;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 
 
 				return new Promise( res => {
 				return new Promise( res => {
@@ -241,7 +257,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 
 
 				return new Promise( res => {
 				return new Promise( res => {
@@ -267,7 +283,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => {
 				setTimeout( () => {
 					throw new Error( 'foo' );
 					throw new Error( 'foo' );
 				} );
 				} );
@@ -285,22 +301,20 @@ describe( 'Watchdog', () => {
 		} );
 		} );
 
 
 		it( 'Watchdog should not intercept other editor errors', () => {
 		it( 'Watchdog should not intercept other editor errors', () => {
-			const watchdog1 = new Watchdog();
-			const watchdog2 = new Watchdog();
-
-			watchdog1.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
-			watchdog1.setDestructor( editor => editor.destroy() );
+			const watchdog1 = Watchdog.for( ClassicTestEditor );
+			const watchdog2 = Watchdog.for( ClassicTestEditor );
 
 
-			watchdog2.setCreator( ( el, config ) => ClassicTestEditor.create( el, config ) );
-			watchdog2.setDestructor( editor => editor.destroy() );
+			const config = {
+				plugins: []
+			};
 
 
 			// sinon.stub( window, 'onerror' ).value( undefined ); and similar do not work.
 			// sinon.stub( window, 'onerror' ).value( undefined ); and similar do not work.
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
 			return Promise.all( [
 			return Promise.all( [
-				watchdog1.create( sourceElement ),
-				watchdog2.create( sourceElement )
+				watchdog1.create( element, config ),
+				watchdog2.create( element, config )
 			] ).then( () => {
 			] ).then( () => {
 				return new Promise( res => {
 				return new Promise( res => {
 					const watchdog1ErrorSpy = sinon.spy();
 					const watchdog1ErrorSpy = sinon.spy();
@@ -334,7 +348,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor.model.document ) );
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor.model.document ) );
 
 
 				return new Promise( res => {
 				return new Promise( res => {
@@ -357,7 +371,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', {
 				setTimeout( () => throwCKEditorError( 'foo', {
 					foo: [ 1, 2, 3, {
 					foo: [ 1, 2, 3, {
 						bar: new Set( [
 						bar: new Set( [
@@ -395,7 +409,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo1', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo1', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo2', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo2', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo3', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo3', watchdog.editor ) );
@@ -431,7 +445,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo1', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo1', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo2', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo2', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo3', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo3', watchdog.editor ) );
@@ -463,7 +477,7 @@ describe( 'Watchdog', () => {
 
 
 			sinon.stub( console, 'error' );
 			sinon.stub( console, 'error' );
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo' ) );
 				setTimeout( () => throwCKEditorError( 'foo' ) );
 
 
 				return new Promise( res => {
 				return new Promise( res => {
@@ -472,7 +486,6 @@ describe( 'Watchdog', () => {
 
 
 						expect( watchdog.crashes ).to.deep.equal( [] );
 						expect( watchdog.crashes ).to.deep.equal( [] );
 
 
-						sinon.assert.calledOnce( console.error );
 						sinon.assert.calledWithExactly(
 						sinon.assert.calledWithExactly(
 							console.error,
 							console.error,
 							'The error is missing its context and Watchdog cannot restart the proper editor.'
 							'The error is missing its context and Watchdog cannot restart the proper editor.'
@@ -496,7 +509,7 @@ describe( 'Watchdog', () => {
 
 
 			sinon.stub( console, 'error' );
 			sinon.stub( console, 'error' );
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', null ) );
 				setTimeout( () => throwCKEditorError( 'foo', null ) );
 
 
 				return new Promise( res => {
 				return new Promise( res => {
@@ -522,7 +535,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} ).then( () => {
 			} ).then( () => {
@@ -550,7 +563,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} ).then( () => {
 			} ).then( () => {
@@ -584,7 +597,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} ).then( () => {
 			} ).then( () => {
@@ -621,27 +634,30 @@ describe( 'Watchdog', () => {
 
 
 			sinon.stub( console, 'error' );
 			sinon.stub( console, 'error' );
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} ).then( () => {
 			} ).then( () => {
 				const editorGetDataError = new Error( 'Some error' );
 				const editorGetDataError = new Error( 'Some error' );
-				const getDataStub = sinon.stub( watchdog.editor, 'getData' )
+				const getDataStub = sinon.stub( watchdog.editor.data, 'get' )
 					.throwsException( editorGetDataError );
 					.throwsException( editorGetDataError );
 
 
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 
 
-				const doc = watchdog.editor.model.document;
+				return new Promise( res => {
+					const doc = watchdog.editor.model.document;
 
 
-				watchdog.editor.model.change( writer => {
-					writer.insertText( 'bar', writer.createPositionAt( doc.getRoot(), 1 ) );
-				} );
+					watchdog.editor.model.change( writer => {
+						writer.insertText( 'bar', writer.createPositionAt( doc.getRoot(), 1 ) );
+					} );
 
 
-				return new Promise( res => {
 					watchdog.on( 'restart', () => {
 					watchdog.on( 'restart', () => {
 						window.onerror = originalErrorHandler;
 						window.onerror = originalErrorHandler;
 
 
-						sinon.assert.calledOnce( getDataStub );
+						// It is called second time by during the default editor destruction
+						// to update the source element.
+						sinon.assert.calledTwice( getDataStub );
+
 						expect( watchdog.editor.getData() ).to.equal( '<p>foo</p>' );
 						expect( watchdog.editor.getData() ).to.equal( '<p>foo</p>' );
 
 
 						sinon.assert.calledWith(
 						sinon.assert.calledWith(
@@ -650,6 +666,11 @@ describe( 'Watchdog', () => {
 							'An error happened during restoring editor data. Editor will be restored from the previously saved data.'
 							'An error happened during restoring editor data. Editor will be restored from the previously saved data.'
 						);
 						);
 
 
+						sinon.assert.calledWith(
+							console.error,
+							'An error happened during the editor destructing.'
+						);
+
 						watchdog.destroy().then( res );
 						watchdog.destroy().then( res );
 					} );
 					} );
 				} );
 				} );
@@ -665,7 +686,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement, {
+			return watchdog.create( element, {
 				initialData: '<p>foo</p>',
 				initialData: '<p>foo</p>',
 				plugins: [ Paragraph ]
 				plugins: [ Paragraph ]
 			} ).then( () => {
 			} ).then( () => {
@@ -700,7 +721,7 @@ describe( 'Watchdog', () => {
 			const originalErrorHandler = window.onerror;
 			const originalErrorHandler = window.onerror;
 			window.onerror = undefined;
 			window.onerror = undefined;
 
 
-			return watchdog.create( sourceElement ).then( () => {
+			return watchdog.create( element ).then( () => {
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'bar', watchdog.editor ) );
 				setTimeout( () => throwCKEditorError( 'bar', watchdog.editor ) );