8
0
Maciej Bukowski 6 лет назад
Родитель
Сommit
d48b85a363

+ 16 - 3
packages/ckeditor5-watchdog/src/watchdog.js

@@ -65,6 +65,14 @@ export default class Watchdog {
 		 */
 		this._crashNumberLimit = typeof config.crashNumberLimit === 'number' ? config.crashNumberLimit : 3;
 
+		/**
+		 * Returns the result of `Date.now()` call. It can be overridden in tests to mock time as the popular
+		 * approaches like `sinon.useFakeTimers()` does not work well with error handling.
+		 *
+		 * @protected
+		 */
+		this._now = Date.now;
+
 		/**
 		 * @private
 		 * @type {Number}
@@ -99,7 +107,10 @@ export default class Watchdog {
 		 * @private
 		 * @type {Function}
 		 */
-		this._throttledSave = throttle( this._save.bind( this ), config.saveInterval || 5000 );
+		this._throttledSave = throttle(
+			this._save.bind( this ),
+			typeof config.saveInterval === 'number' ? config.saveInterval : 5000
+		);
 
 		/**
 		 * The current editor instance.
@@ -274,6 +285,9 @@ export default class Watchdog {
 
 		this.stopListening( this._editor.model.document, 'change:data', this._throttledSave );
 
+		// Save data if there is a remaining editor data change.
+		this._throttledSave.flush();
+
 		return Promise.resolve()
 			.then( () => this._destructor( this._editor ) )
 			.then( () => {
@@ -331,7 +345,7 @@ export default class Watchdog {
 				filename: evt.filename,
 				lineno: evt.lineno,
 				colno: evt.colno,
-				date: Date.now()
+				date: this._now()
 			} );
 
 			this.fire( 'error', { error } );
@@ -394,7 +408,6 @@ export default class Watchdog {
 	 */
 	_restart() {
 		this.state = 'initializing';
-		this._throttledSave.flush();
 
 		return Promise.resolve()
 			.then( () => this._destroy() )

+ 38 - 0
packages/ckeditor5-watchdog/tests/watchdog.js

@@ -772,6 +772,44 @@ describe( 'Watchdog', () => {
 		} );
 	} );
 
+	describe( 'destroy()', () => {
+		// See #19.
+		it( 'should clean internal stuff', () => {
+			// 30ms should be enough to make the two data changes split into two data save actions.
+			// This will ensure that the second data save action will be put off in time.
+			const SAVE_INTERVAL = 30;
+
+			const watchdog = Watchdog.for( ClassicTestEditor, {
+				saveInterval: SAVE_INTERVAL,
+			} );
+
+			return watchdog.create( element, {
+				initialData: '<p>foo</p>',
+				plugins: [ Paragraph ]
+			} ).then( () => {
+				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( 'foo', writer.createPositionAt( doc.getRoot(), 1 ) );
+				} );
+
+				return watchdog.destroy();
+			} ).then( () => {
+				// Wait to ensure that the throttled save is cleared and won't be executed
+				// on the non-existing editor.
+				return new Promise( res => setTimeout( res, SAVE_INTERVAL ) );
+			} ).then( () => {
+				expect( watchdog.editor ).to.equal( null );
+				expect( watchdog.state ).to.equal( 'destroyed' );
+				expect( watchdog.crashes ).to.deep.equal( [] );
+			} );
+		} );
+	} );
+
 	describe( 'static for()', () => {
 		it( 'should be a shortcut method for creating the watchdog', () => {
 			const watchdog = Watchdog.for( ClassicTestEditor );