From 8f660504438510d164bd0125158976a6abbfb1fa Mon Sep 17 00:00:00 2001 From: Justin Holdstock Date: Wed, 7 Mar 2018 15:10:25 -0600 Subject: [PATCH] Create load timeout error and guard trigger error (#693) --- src/lib/events.js | 1 + src/lib/viewers/BaseViewer.js | 10 ++-- src/lib/viewers/__tests__/BaseViewer-test.js | 51 +++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/lib/events.js b/src/lib/events.js index 6e822e69a..b541ecae1 100644 --- a/src/lib/events.js +++ b/src/lib/events.js @@ -38,6 +38,7 @@ export const ERROR_CODE = { CONVERSION_PASSWORD_PROTECTED: 'error_password_protected', CONVERSION_TRY_AGAIN_LATER: 'error_try_again_later', CONVERSION_UNSUPPORTED_FORMAT: 'error_unsupported_format', + VIEWER_LOAD_TIMEOUT: 'error_viewer_load_timeout', CONTENT_DOWNLOAD: 'error_content_download' }; diff --git a/src/lib/viewers/BaseViewer.js b/src/lib/viewers/BaseViewer.js index 15b25b60d..9963aed55 100644 --- a/src/lib/viewers/BaseViewer.js +++ b/src/lib/viewers/BaseViewer.js @@ -275,8 +275,10 @@ class BaseViewer extends EventEmitter { this.resetLoadTimeout(); return; } + if (!this.isLoaded() && !this.isDestroyed()) { - this.triggerError(); + const error = new PreviewError(ERROR_CODE.VIEWER_LOAD_TIMEOUT, __('error_refresh')); + this.triggerError(error); } }, this.loadTimeout); } @@ -335,14 +337,16 @@ class BaseViewer extends EventEmitter { * * @protected * @emits error - * @param {Error|string} [err] - Optional error or string with message + * @param {Error|PreviewError} [err] - Error object related to the error that happened. * @return {void} */ triggerError(err) { + const message = err ? err.message : ''; const error = err instanceof PreviewError ? err - : new PreviewError(ERROR_CODE.LOAD_VIEWER, __('error_refresh'), {}, err.message); + : new PreviewError(ERROR_CODE.LOAD_VIEWER, __('error_refresh'), {}, message); + this.emit('error', error); } diff --git a/src/lib/viewers/__tests__/BaseViewer-test.js b/src/lib/viewers/__tests__/BaseViewer-test.js index 1b05ce2be..ef462c156 100644 --- a/src/lib/viewers/__tests__/BaseViewer-test.js +++ b/src/lib/viewers/__tests__/BaseViewer-test.js @@ -11,7 +11,7 @@ import * as dr from '../../downloadReachability'; import * as file from '../../file'; import * as icons from '../../icons/icons'; import * as constants from '../../constants'; -import { VIEWER_EVENT, LOAD_METRIC } from '../../events'; +import { VIEWER_EVENT, LOAD_METRIC, ERROR_CODE } from '../../events'; import Timer from '../../Timer'; let base; @@ -170,6 +170,22 @@ describe('lib/viewers/BaseViewer', () => { // Test cleanup clearTimeout(base.loadTimeoutId); }); + + it('should trigger an error if the viewer times out', () => { + const triggerStub = sandbox.stub(base, 'triggerError'); + sandbox.stub(window, 'setTimeout').callsFake((func) => func()); + + base.loaded = false; + base.destroyed = false; + + base.resetLoadTimeout(); + const [ error ] = triggerStub.getCall(0).args; + expect(error).to.be.instanceof(PreviewError); + expect(error.code).to.equal(ERROR_CODE.VIEWER_LOAD_TIMEOUT); + + // Test cleanup + clearTimeout(base.loadTimeoutId); + }); }); describe('startLoadTimer()', () => { @@ -250,6 +266,39 @@ describe('lib/viewers/BaseViewer', () => { expect(error.code).to.equal('error_load_viewer'); expect(error.message).to.equal('blah'); }); + + it('should emit a load viewer error if no error provided', () => { + const stub = sandbox.stub(base, 'emit'); + base.triggerError(); + + expect(base.emit).to.be.called; + const [ event, error ] = stub.getCall(0).args; + expect(event).to.equal('error'); + expect(error).to.be.instanceof(PreviewError); + expect(error.code).to.equal('error_load_viewer'); + + }); + + it('should pass through the error if it is a PreviewError', () => { + const code = 'my_special_error'; + const displayMessage = 'Such a special error!'; + const message = 'Bad things have happened'; + const details = { + what: 'what?!' + }; + const err = new PreviewError(code, displayMessage, details, message); + const stub = sandbox.stub(base, 'emit'); + base.triggerError(err); + + expect(base.emit).to.be.called; + const [ event, error ] = stub.getCall(0).args; + expect(event).to.equal('error'); + expect(error).to.be.instanceof(PreviewError); + expect(error.code).to.equal(code); + expect(error.displayMessage).to.equal(displayMessage); + expect(error.details).to.equal(details); + expect(error.message).to.equal(message); + }); }); describe('isLoaded()', () => {