Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

Commit

Permalink
fix(router): show error screen when view rendering fails
Browse files Browse the repository at this point in the history
  • Loading branch information
zaach authored and Shane Tomlinson committed Jul 23, 2014
1 parent b7e90c3 commit 49eb706
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 3 deletions.
16 changes: 13 additions & 3 deletions app/scripts/router.js
Expand Up @@ -28,7 +28,8 @@ define([
'views/change_password',
'views/delete_account',
'views/cookies_disabled',
'views/clear_storage'
'views/clear_storage',
'views/unexpected_error'
],
function (
_,
Expand All @@ -54,7 +55,8 @@ function (
ChangePasswordView,
DeleteAccountView,
CookiesDisabledView,
ClearStorageView
ClearStorageView,
UnexpectedErrorView
) {

function showView(View, options) {
Expand Down Expand Up @@ -95,7 +97,8 @@ function (
'reset_password_complete(/)': showView(ReadyView, { type: 'reset_password' }),
'force_auth(/)': showView(ForceAuthView),
'cookies_disabled(/)': showView(CookiesDisabledView),
'clear(/)': showView(ClearStorageView)
'clear(/)': showView(ClearStorageView),
'unexpected_error(/)': showView(UnexpectedErrorView)
},

initialize: function (options) {
Expand Down Expand Up @@ -171,6 +174,13 @@ function (
}

self.$logo.css('opacity', 1);
})
.fail(function (err) {
// The router's navigate method doesn't set ephemeral messages,
// so use the view's higher level navigate method.
return viewToShow.navigate('unexpected_error', {
error: err && err.message
});
});
},

Expand Down
11 changes: 11 additions & 0 deletions app/scripts/templates/unexpected_error.mustache
@@ -0,0 +1,11 @@
<header>
<h1 id="fxa-unexpected-error-header">{{#t}}Unexpected error{{/t}}</h1>
</header>

<section class="unexpected-error">
<div class="error"></div>

<div class="button-row">
<a href="/" class="button" id="fxa-error-home">{{#t}}Home{{/t}}</a>
</div>
</section>
24 changes: 24 additions & 0 deletions app/scripts/views/unexpected_error.js
@@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
* This is a very small view to allow selenium tests
* to clear browser storage state between tests.
*/

'use strict';

define([
'views/base',
'stache!templates/unexpected_error'
],
function (BaseView, Template) {
var View = BaseView.extend({
template: Template,
className: 'unexpected-error'
});

return View;
});

1 change: 1 addition & 0 deletions app/tests/main.js
Expand Up @@ -86,6 +86,7 @@ function (Translator, Session) {
'../tests/spec/views/ready',
'../tests/spec/views/cookies_disabled',
'../tests/spec/views/clear_storage',
'../tests/spec/views/unexpected_error',
'../tests/spec/views/button_progress_indicator',
'../tests/spec/views/marketing_snippet',
'../tests/spec/views/mixins/floating-placeholder-mixin',
Expand Down
70 changes: 70 additions & 0 deletions app/tests/spec/lib/router.js
Expand Up @@ -127,6 +127,76 @@ function (chai, _, Backbone, Router, SignInView, SignUpView, Session, Constants,
});
});
});

describe('showView', function () {
var view;

beforeEach(function () {
view = new SignUpView({
metrics: metrics,
window: windowMock,
router: router
});
});

afterEach(function() {
view = null;
});

it('navigates to unexpected error view on beforeRender errors', function () {
windowMock.location.pathname = '/signup';
view.beforeRender = function () {
throw new Error('boom');
};

var navigate = view.navigate;
view.navigate = function (url, options) {
assert.equal(options.error, 'boom');
return navigate.call(this, url, options);
};

return router.showView(view)
.then(function () {
assert.include(navigateUrl, 'unexpected_error');
});
});

it('navigates to unexpected error view on context errors', function () {
windowMock.location.pathname = '/signup';
view.context = function () {
throw new Error('boom');
};

var navigate = view.navigate;
view.navigate = function (url, options) {
assert.equal(options.error, 'boom');
return navigate.call(this, url, options);
};

return router.showView(view)
.then(function () {
assert.include(navigateUrl, 'unexpected_error');
});
});

it('navigates to unexpected error view on afterRender errors', function () {
windowMock.location.pathname = '/signup';
view.afterRender = function () {
throw new Error('boom');
};

var navigate = view.navigate;
view.navigate = function (url, options) {
assert.equal(options.error, 'boom');
return navigate.call(this, url, options);
};

return router.showView(view)
.then(function () {
assert.include(navigateUrl, 'unexpected_error');
});
});
});
});
});

Expand Down
44 changes: 44 additions & 0 deletions app/tests/spec/views/unexpected_error.js
@@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict';


define([
'chai',
'lib/ephemeral-messages',
'views/unexpected_error',
'../../mocks/window'
],
function (chai, EphemeralMessages, View, WindowMock) {
var assert = chai.assert;

describe('views/unexpected_error', function () {
var view, windowMock, ephemeralMessages;

beforeEach(function () {
ephemeralMessages = new EphemeralMessages();
windowMock = new WindowMock();
view = new View({
window: windowMock,
ephemeralMessages: ephemeralMessages
});
});

afterEach(function () {
view.remove();
view.destroy();
view = null;
});

it('shows error', function () {
ephemeralMessages.set('error', 'boom');

return view.render()
.then(function () {
assert.equal(view.$('.error').text(), 'boom');
});
});
});
});

0 comments on commit 49eb706

Please sign in to comment.