feat(settings): wire in the expired card alert to the back-end

This commit is contained in:
Phil Booth 2019-07-19 15:39:31 +01:00
Родитель 5869299ae2
Коммит c11d501dbf
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 36FBB106F9C32516
10 изменённых файлов: 424 добавлений и 137 удалений

Просмотреть файл

@ -149,5 +149,8 @@ module.exports = {
TWO_STEP_AUTHENTICATION_ACR: 'AAL2',
STYLE_TRAILHEAD: 'trailhead',
// https://stripe.com/docs/error-codes#expired-card
CC_EXPIRED: 'expired_card',
};
/*eslint-enable sorting/sort-object-props*/

Просмотреть файл

@ -826,6 +826,14 @@ FxaClientWrapper.prototype = {
*/
accountProfile: createClientDelegate('accountProfile'),
/**
* Get the account details from the auth server.
*
* @param {String} sessionToken
* @return {Promise}
*/
account: createClientDelegate('account'),
/**
* Get a list of all devices for a user
*

Просмотреть файл

@ -367,6 +367,35 @@ const Account = Backbone.Model.extend(
});
},
/**
* Fetches account details from GET /account, for use by the settings views.
* Caches its own result, because it's not intended for that endpoint to be
* called repeatedly like some of the polling methods are. If you're really,
* really sure you need to, pass the `force` option to force a clean request.
*
* @param {Object} [options]
* @param {Boolean} [options.force=false] - Ignore any cached results
*
* @returns {Promise} - Resolves to the result of `GET /account`, as defined in
* `packages/fxa-auth-server/lib/routes/account.js`.
*/
settingsData(options = {}) {
return Promise.resolve().then(() => {
if (this._settingsData && !options.force) {
return this._settingsData;
}
const sessionToken = this.get('sessionToken');
if (!sessionToken) {
throw AuthErrors.toError('INVALID_TOKEN');
}
return this._fxaClient
.account(sessionToken)
.then(result => (this._settingsData = result));
});
},
/**
* This function simply returns the session status of the user. It differs
* from `sessionStatus` function above because it is not used to determine

Просмотреть файл

@ -1,7 +1,7 @@
<div id="fxa-settings-header-wrapper">
{{#ccExpired}}
<div class="cc-expired-alert" role="alert">
{{#unsafeTranslate}}Your credit card has expired. Please update it <a href="#" class="alert-link">here</a>.{{/unsafeTranslate}}
{{#unsafeTranslate}}Your credit card has expired. Please update it <a %(escapedCcExpiredLinkAttrs)s>here</a>.{{/unsafeTranslate}}
</div>
{{/ccExpired}}
<header id="fxa-settings-header">

Просмотреть файл

@ -19,6 +19,7 @@ import ClientDisconnectView from './settings/client_disconnect';
import ClientsView from './settings/clients';
import Cocktail from 'cocktail';
import CommunicationPreferencesView from './settings/communication_preferences';
import Constants from '../lib/constants';
import DeleteAccountView from './settings/delete_account';
import DisplayNameView from './settings/display_name';
import Duration from 'duration';
@ -107,7 +108,8 @@ const View = BaseView.extend({
const account = this.getSignedInAccount();
context.set({
// ccExpired: true,
ccExpired: !!this._ccExpired,
escapedCcExpiredLinkAttrs: `href="/subscriptions" class="alert-link"`,
showSignOut: !account.isFromSync(),
unsafeHeaderHTML: this._getHeaderHTML(account),
});
@ -141,7 +143,17 @@ const View = BaseView.extend({
beforeRender() {
const account = this.getSignedInAccount();
return account.fetchProfile().then(() => this.user.setAccount(account));
return Promise.all([
account.fetchProfile(),
this.user.setAccount(account),
account.settingsData(),
]).then(([, , data]) => {
if (data && Array.isArray(data.subscriptions)) {
this._ccExpired = data.subscriptions.some(
s => s.failure_code === Constants.CC_EXPIRED
);
}
});
},
_onAccountUpdate(account) {

Просмотреть файл

@ -50,11 +50,11 @@ body.settings #stage .settings {
color: white;
padding: 5px;
text-align: center;
}
.cc-expired-alert a {
text-decoration: underline;
color: white;
a {
text-decoration: underline;
color: white;
}
}
// settings header controls

Просмотреть файл

@ -1442,6 +1442,16 @@ describe('lib/fxa-client', function() {
});
});
describe('account', () => {
it('calls account', () => {
sinon.stub(realClient, 'account').callsFake(() => Promise.resolve());
return client.account('wibble').then(() => {
assert.isTrue(realClient.account.calledWith('wibble'));
});
});
});
describe('isSignedIn', function() {
it('resolves to false if no sessionToken passed in', function() {
return client.isSignedIn().then(function(isSignedIn) {

Просмотреть файл

@ -2683,6 +2683,80 @@ describe('models/account', function() {
});
});
describe('settingsData:', () => {
let result;
beforeEach(() => {
account.set('sessionToken', 'wibble');
sinon
.stub(fxaClient, 'account')
.callsFake(() => Promise.resolve({ foo: 'bar' }));
return account.settingsData().then(r => (result = r));
});
it('returned the correct result', () => {
assert.deepEqual(result, { foo: 'bar' });
});
it('called fxaClient.account', () => {
assert.equal(fxaClient.account.callCount, 1);
const args = fxaClient.account.args[0];
assert.lengthOf(args, 1);
assert.equal(args[0], 'wibble');
});
describe('second call to settingsData:', () => {
beforeEach(() => {
return account.settingsData().then(r => (result = r));
});
it('returned the correct result', () => {
assert.deepEqual(result, { foo: 'bar' });
});
it('did not call fxaClient.account a second time', () => {
assert.equal(fxaClient.account.callCount, 1);
});
});
describe('second call to settingsData with force=true:', () => {
beforeEach(() => {
return account.settingsData({ force: true }).then(r => (result = r));
});
it('returned the correct result', () => {
assert.deepEqual(result, { foo: 'bar' });
});
it('called fxaClient.account a second time', () => {
assert.equal(fxaClient.account.callCount, 2);
});
});
});
describe('settingsData without sessionToken:', () => {
let err;
beforeEach(() => {
account.unset('sessionToken');
sinon
.stub(fxaClient, 'account')
.callsFake(() => Promise.resolve({ foo: 'bar' }));
return account.settingsData().catch(e => (err = e));
});
it('failed', () => {
assert.instanceOf(err, Error);
assert.equal(err.message, 'Invalid token');
});
it('did not call fxaClient.account', () => {
assert.equal(fxaClient.account.callCount, 0);
});
});
describe('checkEmailExists', function() {
beforeEach(function() {
account.set('email', EMAIL);

Просмотреть файл

@ -60,7 +60,9 @@ describe('views/settings', function() {
subPanelRenderSpy = sinon.spy(() => Promise.resolve());
view = new View({
childView: initialChildView,
config: { lang: 'en' },
config: {
lang: 'en',
},
createView,
experimentGroupingRules,
formPrefill,
@ -131,8 +133,90 @@ describe('views/settings', function() {
assert.equal(args[1], 'wibble');
});
describe('setInitialContext:', () => {
let context;
beforeEach(() => {
context = {
set: sinon.spy(),
};
});
it('called context.set', () => {
view.setInitialContext(context);
assert.equal(context.set.callCount, 1);
const args = context.set.args[0];
assert.lengthOf(args, 1);
assert.isFalse(args[0].ccExpired);
assert.equal(
args[0].escapedCcExpiredLinkAttrs,
'href="/subscriptions" class="alert-link"'
);
assert.isTrue(args[0].showSignOut);
assert.isString(args[0].unsafeHeaderHTML);
});
describe('beforeRender with expired card:', () => {
beforeEach(() => {
sinon.stub(account, 'settingsData').callsFake(() =>
Promise.resolve({
subscriptions: [
{ foo: 'bar' },
{ baz: 'qux', failure_code: 'expired_card' },
],
})
);
return view.beforeRender();
});
it('set ccExpired to true', () => {
view.setInitialContext(context);
assert.equal(context.set.callCount, 1);
assert.isTrue(context.set.args[0][0].ccExpired);
});
});
describe('beforeRender with some other failure:', () => {
beforeEach(() => {
sinon.stub(account, 'settingsData').callsFake(() =>
Promise.resolve({
subscriptions: [
{ foo: 'bar' },
{ baz: 'qux', failure_code: 'email_invalid' },
],
})
);
return view.beforeRender();
});
it('set ccExpired to false', () => {
view.setInitialContext(context);
assert.equal(context.set.callCount, 1);
assert.isFalse(context.set.args[0][0].ccExpired);
});
});
describe('beforeRender without subscriptions:', () => {
beforeEach(() => {
sinon.stub(account, 'settingsData').callsFake(() =>
Promise.resolve({
subscriptions: {},
})
);
return view.beforeRender();
});
it('set ccExpired to false', () => {
view.setInitialContext(context);
assert.equal(context.set.callCount, 1);
assert.isFalse(context.set.args[0][0].ccExpired);
});
});
});
describe('with uid', function() {
beforeEach(function() {
sinon.stub(account, 'settingsData').callsFake(() => Promise.resolve({}));
relier.set('uid', UID);
});
@ -186,6 +270,7 @@ describe('views/settings', function() {
describe('with session', function() {
beforeEach(function() {
sinon.stub(account, 'settingsData').callsFake(() => Promise.resolve({}));
sinon.stub(view, 'checkAuthorization').callsFake(function() {
return Promise.resolve(true);
});
@ -591,6 +676,50 @@ describe('views/settings', function() {
});
});
});
describe('render with expired card:', () => {
beforeEach(() => {
account.settingsData.restore();
sinon.stub(account, 'settingsData').callsFake(() =>
Promise.resolve({
subscriptions: [
{ foo: 'bar' },
{ baz: 'qux', failure_code: 'expired_card' },
],
})
);
return view.render();
});
it('rendered the alert', () => {
const $el = view.$('.cc-expired-alert');
assert.lengthOf($el, 1);
assert.equal(
$el[0].innerHTML.trim(),
'Your credit card has expired. Please update it <a href="/subscriptions" class="alert-link">here</a>.'
);
});
});
describe('render with non-expired card:', () => {
beforeEach(() => {
account.settingsData.restore();
sinon.stub(account, 'settingsData').callsFake(() =>
Promise.resolve({
subscriptions: [
{ foo: 'bar' },
{ baz: 'qux', failure_code: 'wibble' },
],
})
);
return view.render();
});
it('did not render the alert', () => {
const $el = view.$('.cc-expired-alert');
assert.lengthOf($el, 0);
});
});
});
describe('with no relier specified uid', function() {

280
packages/fxa-content-server/npm-shrinkwrap.json сгенерированный
Просмотреть файл

@ -37,9 +37,9 @@
}
},
"@babel/code-frame": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
"integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
"requires": {
"@babel/highlight": "^7.0.0"
}
@ -73,13 +73,13 @@
}
},
"@babel/generator": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.0.tgz",
"integrity": "sha512-1TTVrt7J9rcG5PMjvO7VEG3FrEoEJNHxumRq66GemPmzboLWtIjjcJgk8rokuAS7IiRSpgVSu5Vb9lc99iJkOA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz",
"integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==",
"requires": {
"@babel/types": "^7.5.0",
"@babel/types": "^7.5.5",
"jsesc": "^2.5.1",
"lodash": "^4.17.11",
"lodash": "^4.17.13",
"source-map": "^0.5.0",
"trim-right": "^1.0.1"
},
@ -128,26 +128,26 @@
}
},
"@babel/helper-create-class-features-plugin": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.0.tgz",
"integrity": "sha512-EAoMc3hE5vE5LNhMqDOwB1usHvmRjCDAnH8CD4PVkX9/Yr3W/tcz8xE8QvdZxfsFBDICwZnF2UTHIqslRpvxmA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz",
"integrity": "sha512-ZsxkyYiRA7Bg+ZTRpPvB6AbOFKTFFK4LrvTet8lInm0V468MWCaSYJE+I7v2z2r8KNLtYiV+K5kTCnR7dvyZjg==",
"requires": {
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-member-expression-to-functions": "^7.0.0",
"@babel/helper-member-expression-to-functions": "^7.5.5",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-replace-supers": "^7.4.4",
"@babel/helper-replace-supers": "^7.5.5",
"@babel/helper-split-export-declaration": "^7.4.4"
}
},
"@babel/helper-define-map": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz",
"integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz",
"integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==",
"requires": {
"@babel/helper-function-name": "^7.1.0",
"@babel/types": "^7.4.4",
"lodash": "^4.17.11"
"@babel/types": "^7.5.5",
"lodash": "^4.17.13"
}
},
"@babel/helper-explode-assignable-expression": {
@ -186,11 +186,11 @@
}
},
"@babel/helper-member-expression-to-functions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz",
"integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz",
"integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==",
"requires": {
"@babel/types": "^7.0.0"
"@babel/types": "^7.5.5"
}
},
"@babel/helper-module-imports": {
@ -202,16 +202,16 @@
}
},
"@babel/helper-module-transforms": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz",
"integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz",
"integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==",
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/helper-simple-access": "^7.1.0",
"@babel/helper-split-export-declaration": "^7.4.4",
"@babel/template": "^7.4.4",
"@babel/types": "^7.4.4",
"lodash": "^4.17.11"
"@babel/types": "^7.5.5",
"lodash": "^4.17.13"
}
},
"@babel/helper-optimise-call-expression": {
@ -228,11 +228,11 @@
"integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA=="
},
"@babel/helper-regex": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz",
"integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz",
"integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==",
"requires": {
"lodash": "^4.17.11"
"lodash": "^4.17.13"
}
},
"@babel/helper-remap-async-to-generator": {
@ -248,14 +248,14 @@
}
},
"@babel/helper-replace-supers": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz",
"integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz",
"integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==",
"requires": {
"@babel/helper-member-expression-to-functions": "^7.0.0",
"@babel/helper-member-expression-to-functions": "^7.5.5",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/traverse": "^7.4.4",
"@babel/types": "^7.4.4"
"@babel/traverse": "^7.5.5",
"@babel/types": "^7.5.5"
}
},
"@babel/helper-simple-access": {
@ -287,13 +287,13 @@
}
},
"@babel/helpers": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.4.tgz",
"integrity": "sha512-6LJ6xwUEJP51w0sIgKyfvFMJvIb9mWAfohJp0+m6eHJigkFdcH8duZ1sfhn0ltJRzwUIT/yqqhdSfRpCpL7oow==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz",
"integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==",
"requires": {
"@babel/template": "^7.4.4",
"@babel/traverse": "^7.5.0",
"@babel/types": "^7.5.0"
"@babel/traverse": "^7.5.5",
"@babel/types": "^7.5.5"
}
},
"@babel/highlight": {
@ -307,9 +307,9 @@
}
},
"@babel/parser": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.0.tgz",
"integrity": "sha512-I5nW8AhGpOXGCCNYGc+p7ExQIBxRFnS2fd/d862bNOKvmoEPjYPcfIjsfdy0ujagYOIYPczKgD9l3FsgTkAzKA=="
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz",
"integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g=="
},
"@babel/plugin-proposal-async-generator-functions": {
"version": "7.2.0",
@ -340,9 +340,9 @@
}
},
"@babel/plugin-proposal-object-rest-spread": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.4.tgz",
"integrity": "sha512-KCx0z3y7y8ipZUMAEEJOyNi11lMb/FOPUjjB113tfowgw0c16EGYos7worCKBcUAh2oG+OBnoUhsnTSoLpV9uA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz",
"integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-syntax-object-rest-spread": "^7.2.0"
@ -450,25 +450,25 @@
}
},
"@babel/plugin-transform-block-scoping": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz",
"integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz",
"integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"lodash": "^4.17.11"
"lodash": "^4.17.13"
}
},
"@babel/plugin-transform-classes": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz",
"integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz",
"integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.0.0",
"@babel/helper-define-map": "^7.4.4",
"@babel/helper-define-map": "^7.5.5",
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-replace-supers": "^7.4.4",
"@babel/helper-replace-supers": "^7.5.5",
"@babel/helper-split-export-declaration": "^7.4.4",
"globals": "^11.1.0"
}
@ -606,12 +606,12 @@
}
},
"@babel/plugin-transform-object-super": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz",
"integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
"integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-replace-supers": "^7.1.0"
"@babel/helper-replace-supers": "^7.5.5"
}
},
"@babel/plugin-transform-parameters": {
@ -727,11 +727,11 @@
}
},
"@babel/plugin-transform-typescript": {
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.2.tgz",
"integrity": "sha512-r4zJOMbKY5puETm8+cIpaa0RQZG/sSASW1u0pj8qYklcERgVIbxVbP2wyJA7zI1//h7lEagQmXi9IL9iI5rfsA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz",
"integrity": "sha512-pehKf4m640myZu5B2ZviLaiBlxMCjSZ1qTEO459AXKX5GnPueyulJeCqZFs1nz/Ya2dDzXQ1NxZ/kKNWyD4h6w==",
"requires": {
"@babel/helper-create-class-features-plugin": "^7.5.0",
"@babel/helper-create-class-features-plugin": "^7.5.5",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-syntax-typescript": "^7.2.0"
}
@ -823,9 +823,9 @@
}
},
"@babel/runtime": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.4.tgz",
"integrity": "sha512-Na84uwyImZZc3FKf4aUF1tysApzwf3p2yuFBIyBfbzT5glzKTdvYI4KVW4kcgjrzoGUjC7w3YyCHcJKaRxsr2Q==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
"integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
"requires": {
"regenerator-runtime": "^0.13.2"
}
@ -841,28 +841,28 @@
}
},
"@babel/traverse": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.0.tgz",
"integrity": "sha512-SnA9aLbyOCcnnbQEGwdfBggnc142h/rbqqsXcaATj2hZcegCl903pUD/lfpsNBlBSuWow/YDfRyJuWi2EPR5cg==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz",
"integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==",
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.5.0",
"@babel/code-frame": "^7.5.5",
"@babel/generator": "^7.5.5",
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-split-export-declaration": "^7.4.4",
"@babel/parser": "^7.5.0",
"@babel/types": "^7.5.0",
"@babel/parser": "^7.5.5",
"@babel/types": "^7.5.5",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.11"
"lodash": "^4.17.13"
}
},
"@babel/types": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.0.tgz",
"integrity": "sha512-UFpDVqRABKsW01bvw7/wSUe56uy6RXM5+VJibVVAybDGxEW25jdwiFJEf7ASvSaC7sN7rbE/l3cLp2izav+CtQ==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz",
"integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==",
"requires": {
"esutils": "^2.0.2",
"lodash": "^4.17.11",
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
},
@ -933,9 +933,9 @@
"dev": true
},
"@testing-library/dom": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-5.5.1.tgz",
"integrity": "sha512-FEKxR51dCBixz8WoIlTHJucLYlVSZ4oMaWcnbID8SKRy+07JNACwUDHzpeeQv0853Hme91niHnvNebwGWZu21w==",
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-5.6.0.tgz",
"integrity": "sha512-nAsRvQLr/b6TGNjuHMEbWXCNPLrQYnzqa/KKQZL7wBOtfptUxsa4Ah9aqkHW0ZmCSFmUDj4nFUxWPVTeMu0iCw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.5",
@ -946,13 +946,13 @@
}
},
"@testing-library/react": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-8.0.4.tgz",
"integrity": "sha512-omm4D00Z0aMaWfPRRP4X6zIaOVb0Kf1Yc1H5VE4id9D0pQRiBcTtmjbN0kZgT8rQGxHhVAuv1NuwFwMTwKzFqg==",
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-8.0.5.tgz",
"integrity": "sha512-2EzVi7HjUUF8gKzB4s+oCJ1+F4VOrphO+DlUO6Ptgtcz1ko4J2zqnr0t7g+T7uedXXjJ0wdq70zQMhJXP3w37A==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.5",
"@testing-library/dom": "^5.0.0"
"@babel/runtime": "^7.5.4",
"@testing-library/dom": "^5.5.4"
}
},
"@theintern/common": {
@ -1191,9 +1191,9 @@
"dev": true
},
"@types/node": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.2.tgz",
"integrity": "sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ==",
"version": "12.6.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz",
"integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==",
"dev": true
},
"@types/platform": {
@ -1552,9 +1552,9 @@
"dev": true
},
"ajv": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.1.tgz",
"integrity": "sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ==",
"version": "6.10.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
@ -1645,12 +1645,20 @@
},
"dependencies": {
"async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
"integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"dev": true,
"requires": {
"lodash": "^4.17.11"
"lodash": "^4.17.14"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
}
}
}
}
@ -2608,12 +2616,12 @@
}
},
"browserslist": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.4.tgz",
"integrity": "sha512-ErJT8qGfRt/VWHSr1HeqZzz50DvxHtr1fVL1m5wf20aGrG8e1ce8fpZ2EjZEfs09DDZYSvtRaDlMpWslBf8Low==",
"version": "4.6.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
"integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
"requires": {
"caniuse-lite": "^1.0.30000981",
"electron-to-chromium": "^1.3.188",
"caniuse-lite": "^1.0.30000984",
"electron-to-chromium": "^1.3.191",
"node-releases": "^1.1.25"
}
},
@ -2829,9 +2837,9 @@
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caniuse-lite": {
"version": "1.0.30000983",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000983.tgz",
"integrity": "sha512-/llD1bZ6qwNkt41AsvjsmwNOoA4ZB+8iqmf5LVyeSXuBODT/hAMFNVOh84NdUzoiYiSKqo5vQ3ZzeYHSi/olDQ=="
"version": "1.0.30000984",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000984.tgz",
"integrity": "sha512-n5tKOjMaZ1fksIpQbjERuqCyfgec/m9pferkFQbLmWtqLUdmt12hNhjSwsmPdqeiG2NkITOQhr1VYIwWSAceiA=="
},
"capture-stack-trace": {
"version": "1.0.1",
@ -4125,9 +4133,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.188",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.188.tgz",
"integrity": "sha512-tEQcughYIMj8WDMc59EGEtNxdGgwal/oLLTDw+NEqJRJwGflQvH3aiyiexrWeZOETP4/ko78PVr6gwNhdozvuQ=="
"version": "1.3.194",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.194.tgz",
"integrity": "sha512-w0LHR2YD9Ex1o+Sz4IN2hYzCB8vaFtMNW+yJcBf6SZlVqgFahkne/4rGVJdk4fPF98Gch9snY7PiabOh+vqHNg=="
},
"elliptic": {
"version": "6.5.0",
@ -4484,10 +4492,13 @@
}
},
"eslint-utils": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
"dev": true
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz",
"integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.0.0"
}
},
"eslint-visitor-keys": {
"version": "1.0.0",
@ -7112,9 +7123,9 @@
"dev": true
},
"inquirer": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.4.1.tgz",
"integrity": "sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw==",
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz",
"integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==",
"requires": {
"ansi-escapes": "^3.2.0",
"chalk": "^2.4.2",
@ -7122,7 +7133,7 @@
"cli-width": "^2.0.0",
"external-editor": "^3.0.3",
"figures": "^2.0.0",
"lodash": "^4.17.11",
"lodash": "^4.17.12",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rxjs": "^6.4.0",
@ -11885,12 +11896,17 @@
},
"dependencies": {
"async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
"integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"requires": {
"lodash": "^4.17.11"
"lodash": "^4.17.14"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
}
}
},
@ -11951,9 +11967,9 @@
}
},
"spdx-license-ids": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz",
"integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA=="
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
},
"speed-trap": {
"version": "0.0.8",
@ -12161,13 +12177,13 @@
"integrity": "sha1-tvmpANSWpX8CQI8iGYwQndoGMEE="
},
"table": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.1.tgz",
"integrity": "sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==",
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.4.tgz",
"integrity": "sha512-IIfEAUx5QlODLblLrGTTLJA7Tk0iLSGBvgY8essPRVNGHAzThujww1YqHLs6h3HfTg55h++RzLHH5Xw/rfv+mg==",
"dev": true,
"requires": {
"ajv": "^6.9.1",
"lodash": "^4.17.11",
"ajv": "^6.10.2",
"lodash": "^4.17.14",
"slice-ansi": "^2.1.0",
"string-width": "^3.0.0"
},
@ -12184,6 +12200,12 @@
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",