diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js index 781c3aa087..2220472b85 100644 --- a/ui/.eslintrc.js +++ b/ui/.eslintrc.js @@ -13,6 +13,7 @@ module.exports = { rules: { 'no-unused-vars': ['error', { ignoreRestSiblings: true }], 'prettier/prettier': 'error', + 'ember/no-jquery': 'error', }, globals: { TextEncoderLite: true, diff --git a/ui/app/adapters/application.js b/ui/app/adapters/application.js index 6a7a15a7fc..6e54c834b6 100644 --- a/ui/app/adapters/application.js +++ b/ui/app/adapters/application.js @@ -3,13 +3,14 @@ import { assign } from '@ember/polyfills'; import { set } from '@ember/object'; import RSVP from 'rsvp'; import DS from 'ember-data'; +import AdapterFetch from 'ember-fetch/mixins/adapter-fetch'; import fetch from 'fetch'; import config from '../config/environment'; const { APP } = config; const { POLLING_URLS, NAMESPACE_ROOT_URLS } = APP; -export default DS.RESTAdapter.extend({ +export default DS.RESTAdapter.extend(AdapterFetch, { auth: service(), namespaceService: service('namespace'), controlGroup: service(), diff --git a/ui/app/components/auth-form.js b/ui/app/components/auth-form.js index fc8596404d..2884634302 100644 --- a/ui/app/components/auth-form.js +++ b/ui/app/components/auth-form.js @@ -175,15 +175,17 @@ export default Component.extend(DEFAULTS, { handleError(e, prefixMessage = true) { this.set('loading', false); - if (!e.errors) { - return e; + let errors; + if (e.errors) { + errors = e.errors.map(error => { + if (error.detail) { + return error.detail; + } + return error; + }); + } else { + errors = [e]; } - let errors = e.errors.map(error => { - if (error.detail) { - return error.detail; - } - return error; - }); let message = prefixMessage ? 'Authentication failed: ' : ''; this.set('error', `${message}${errors.join('.')}`); }, diff --git a/ui/app/components/linked-block.js b/ui/app/components/linked-block.js index b829b27548..1cd3e897f2 100644 --- a/ui/app/components/linked-block.js +++ b/ui/app/components/linked-block.js @@ -15,12 +15,12 @@ let LinkedBlockComponent = Component.extend({ encode: false, click(event) { - const $target = this.$(event.target); + const $target = event.target; const isAnchorOrButton = - $target.is('a') || - $target.is('button') || - $target.closest('button', event.currentTarget).length > 0 || - $target.closest('a', event.currentTarget).length > 0; + $target.tagName === 'A' || + $target.tagName === 'BUTTON' || + $target.closest('button') || + $target.closest('a'); if (!isAnchorOrButton) { let params = this.get('params'); if (this.encode) { diff --git a/ui/app/components/role-edit.js b/ui/app/components/role-edit.js index 9291276444..fb9bc80b6b 100644 --- a/ui/app/components/role-edit.js +++ b/ui/app/components/role-edit.js @@ -1,7 +1,7 @@ import { inject as service } from '@ember/service'; import { or } from '@ember/object/computed'; import { isBlank } from '@ember/utils'; -import $ from 'jquery'; +import { task, waitForEvent } from 'ember-concurrency'; import Component from '@ember/component'; import { set, get } from '@ember/object'; import FocusOnInsertMixin from 'vault/mixins/focus-on-insert'; @@ -42,20 +42,22 @@ export default Component.extend(FocusOnInsertMixin, { } }, - didInsertElement() { - this._super(...arguments); - $(document).on('keyup.keyEdit', this.onEscape.bind(this)); - }, - willDestroyElement() { this._super(...arguments); - const model = this.get('model'); - if (get(model, 'isError')) { - model.rollbackAttributes(); + if (this.model && this.model.isError) { + this.model.rollbackAttributes(); } - $(document).off('keyup.keyEdit'); }, + waitForKeyUp: task(function*() { + while (true) { + let event = yield waitForEvent(document.body, 'keyup'); + this.onEscape(event); + } + }) + .on('didInsertElement') + .cancelOn('willDestroyElement'), + transitionToRoute() { this.get('router').transitionTo(...arguments); }, @@ -84,18 +86,6 @@ export default Component.extend(FocusOnInsertMixin, { }, actions: { - handleKeyDown(_, e) { - e.stopPropagation(); - if (!(e.keyCode === keys.ENTER && e.metaKey)) { - return; - } - let $form = this.$('form'); - if ($form.length) { - $form.submit(); - } - $form = null; - }, - createOrUpdate(type, event) { event.preventDefault(); @@ -112,10 +102,6 @@ export default Component.extend(FocusOnInsertMixin, { }); }, - handleChange() { - this.hasDataChanges(); - }, - setValue(key, event) { set(get(this, 'model'), key, event.target.checked); }, diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index c2634900a3..c9dd40041b 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -95,7 +95,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { updatePath: maybeQueryRecord( 'capabilities', context => { - if (context.mode === 'create') { + if (!context.model || context.mode === 'create') { return; } let backend = context.isV2 ? context.get('model.engine.id') : context.model.backend; @@ -116,7 +116,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { v2UpdatePath: maybeQueryRecord( 'capabilities', context => { - if (context.mode === 'create' || context.isV2 === false) { + if (!context.model || context.mode === 'create' || context.isV2 === false) { return; } let backend = context.get('model.engine.id'); @@ -137,7 +137,9 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { buttonDisabled: or('requestInFlight', 'model.isFolder', 'model.flagsIsInvalid', 'hasLintError', 'error'), modelForData: computed('isV2', 'model', function() { - return this.isV2 ? this.model.belongsTo('selectedVersion').value() : this.model; + let { model } = this; + if (!model) return null; + return this.isV2 ? model.belongsTo('selectedVersion').value() : model; }), basicModeDisabled: computed('secretDataIsAdvanced', 'showAdvancedMode', function() { @@ -160,6 +162,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { 'model.{failedServerRead,selectedVersion.failedServerRead}', 'isV2', function() { + if (!this.model) return; // if the version couldn't be read from the server if (this.isV2 && this.model.selectedVersion.failedServerRead) { return true; diff --git a/ui/app/components/transit-edit.js b/ui/app/components/transit-edit.js index 9c465c472e..d5258086e1 100644 --- a/ui/app/components/transit-edit.js +++ b/ui/app/components/transit-edit.js @@ -1,9 +1,10 @@ import { inject as service } from '@ember/service'; import { or } from '@ember/object/computed'; import { isBlank } from '@ember/utils'; -import $ from 'jquery'; import Component from '@ember/component'; +import { task, waitForEvent } from 'ember-concurrency'; import { set, get } from '@ember/object'; + import FocusOnInsertMixin from 'vault/mixins/focus-on-insert'; import keys from 'vault/lib/keycodes'; @@ -19,24 +20,22 @@ export default Component.extend(FocusOnInsertMixin, { key: null, requestInFlight: or('key.isLoading', 'key.isReloading', 'key.isSaving'), - init() { - this._super(...arguments); - }, - - didInsertElement() { - this._super(...arguments); - $(document).on('keyup.keyEdit', this.onEscape.bind(this)); - }, - willDestroyElement() { this._super(...arguments); - const key = this.get('key'); - if (get(key, 'isError')) { - key.rollbackAttributes(); + if (this.key && this.key.isError) { + this.key.rollbackAttributes(); } - $(document).off('keyup.keyEdit'); }, + waitForKeyUp: task(function*() { + while (true) { + let event = yield waitForEvent(document.body, 'keyup'); + this.onEscape(event); + } + }) + .on('didInsertElement') + .cancelOn('willDestroyElement'), + transitionToRoute() { this.get('router').transitionTo(...arguments); }, @@ -69,18 +68,6 @@ export default Component.extend(FocusOnInsertMixin, { }, actions: { - handleKeyDown(_, e) { - e.stopPropagation(); - if (!(e.keyCode === keys.ENTER && e.metaKey)) { - return; - } - let $form = this.$('form'); - if ($form.length) { - $form.submit(); - } - $form = null; - }, - createOrUpdateKey(type, event) { event.preventDefault(); @@ -101,10 +88,6 @@ export default Component.extend(FocusOnInsertMixin, { ); }, - handleChange() { - this.hasDataChanges(); - }, - setValueOnKey(key, event) { set(get(this, 'key'), key, event.target.checked); }, diff --git a/ui/app/controllers/vault/cluster/settings/seal.js b/ui/app/controllers/vault/cluster/settings/seal.js index d0afb3673b..721a2fee6d 100644 --- a/ui/app/controllers/vault/cluster/settings/seal.js +++ b/ui/app/controllers/vault/cluster/settings/seal.js @@ -12,7 +12,7 @@ export default Controller.extend({ .then(() => { this.model.cluster.get('leaderNode').set('sealed', true); this.get('auth').deleteCurrentToken(); - return this.transitionToRoute('vault.cluster'); + return this.transitionToRoute('vault.cluster.unseal'); }); }, }, diff --git a/ui/app/mixins/unload-model-route.js b/ui/app/mixins/unload-model-route.js index 2440798953..b1f10d111c 100644 --- a/ui/app/mixins/unload-model-route.js +++ b/ui/app/mixins/unload-model-route.js @@ -5,12 +5,15 @@ import Mixin from '@ember/object/mixin'; export default Mixin.create({ modelPath: 'model', unloadModel() { - const model = this.controller.get(this.get('modelPath')); + let { modelPath } = this; + let model = this.controller.get(modelPath); if (!model || !model.unloadRecord) { return; } this.store.unloadRecord(model); model.destroy(); + // it's important to unset the model on the controller since controllers are singletons + this.controller.set(modelPath, null); }, actions: { diff --git a/ui/app/routes/vault/cluster.js b/ui/app/routes/vault/cluster.js index 46a41eb3b8..ab2b78b07b 100644 --- a/ui/app/routes/vault/cluster.js +++ b/ui/app/routes/vault/cluster.js @@ -52,14 +52,14 @@ export default Route.extend(ModelBoundaryRoute, ClusterRoute, { } }, - beforeModel() { + async beforeModel() { const params = this.paramsFor(this.routeName); this.clearNonGlobalModels(); this.get('namespaceService').setNamespace(params.namespaceQueryParam); const id = this.getClusterId(params); if (id) { this.get('auth').setCluster(id); - this.get('permissions').getPaths.perform(); + await this.get('permissions').getPaths.perform(); return this.get('version').fetchFeatures(); } else { return reject({ httpStatus: 404, message: 'not found', path: params.cluster_name }); diff --git a/ui/app/services/auth.js b/ui/app/services/auth.js index f9704de339..c757b0c7da 100644 --- a/ui/app/services/auth.js +++ b/ui/app/services/auth.js @@ -1,9 +1,10 @@ import Ember from 'ember'; -import { resolve } from 'rsvp'; +import { resolve, reject } from 'rsvp'; import { assign } from '@ember/polyfills'; -import $ from 'jquery'; import { isArray } from '@ember/array'; import { computed, get } from '@ember/object'; + +import fetch from 'fetch'; import { getOwner } from '@ember/application'; import Service, { inject as service } from '@ember/service'; import getStorage from '../lib/token-storage'; @@ -86,7 +87,18 @@ export default Service.extend({ if (namespace) { defaults.headers['X-Vault-Namespace'] = namespace; } - return $.ajax(assign(defaults, options)); + let opts = assign(defaults, options); + + return fetch(url, { + method: opts.method || 'GET', + headers: opts.headers || {}, + }).then(response => { + if (response.status >= 200 && response.status < 300) { + return resolve(response.json()); + } else { + return reject(); + } + }); }, renewCurrentToken() { diff --git a/ui/app/services/csp-event.js b/ui/app/services/csp-event.js index df1a5779d2..21a3947779 100644 --- a/ui/app/services/csp-event.js +++ b/ui/app/services/csp-event.js @@ -1,6 +1,5 @@ /*eslint-disable no-constant-condition*/ import { computed } from '@ember/object'; -import { filterBy } from '@ember/object/computed'; import Service from '@ember/service'; import { task, waitForEvent } from 'ember-concurrency'; @@ -9,7 +8,9 @@ export default Service.extend({ events: computed(function() { return []; }), - connectionViolations: filterBy('events', 'violatedDirective', 'connect-src'), + connectionViolations: computed('events.[].violatedDirective', function() { + return this.get('events').filter(e => e.violatedDirective.startsWith('connect-src')); + }), attach() { this.monitor.perform(); diff --git a/ui/app/templates/partials/role-aws/form.hbs b/ui/app/templates/partials/role-aws/form.hbs index 73f2a126c5..de75c1dc31 100644 --- a/ui/app/templates/partials/role-aws/form.hbs +++ b/ui/app/templates/partials/role-aws/form.hbs @@ -1,4 +1,4 @@ -
+
{{message-error model=model}} diff --git a/ui/app/templates/partials/role-pki/form.hbs b/ui/app/templates/partials/role-pki/form.hbs index 5fe8745f9e..6e28fddb49 100644 --- a/ui/app/templates/partials/role-pki/form.hbs +++ b/ui/app/templates/partials/role-pki/form.hbs @@ -1,4 +1,4 @@ - +
{{message-error model=model}} diff --git a/ui/app/templates/partials/role-ssh/form.hbs b/ui/app/templates/partials/role-ssh/form.hbs index 986506f9ec..13367ef1ec 100644 --- a/ui/app/templates/partials/role-ssh/form.hbs +++ b/ui/app/templates/partials/role-ssh/form.hbs @@ -1,28 +1,30 @@ - +
{{message-error model=model}} - {{#with (if (eq model.keyType 'otp') 3 4) as |numRequired|}} - {{#each (take numRequired model.attrsForKeyType) as |attr|}} - {{#unless (and (eq mode 'edit') (eq attr.name 'name'))}} - {{partial "partials/form-field-from-model"}} - {{/unless}} - {{/each}} - {{toggle-button - toggleAttr="showOptions" - toggleTarget=this - openLabel="Hide options" - closedLabel="More options" - data-test-toggle-more="true" - }} - {{#if showOptions}} -
- {{#each (drop numRequired model.attrsForKeyType) as |attr|}} + {{#if model.attrsForKeyType}} + {{#with (if (eq model.keyType 'otp') 3 4) as |numRequired|}} + {{#each (take numRequired model.attrsForKeyType) as |attr|}} + {{#unless (and (eq mode 'edit') (eq attr.name 'name'))}} {{partial "partials/form-field-from-model"}} - {{/each}} -
- {{/if}} - {{/with}} + {{/unless}} + {{/each}} + {{toggle-button + toggleAttr="showOptions" + toggleTarget=this + openLabel="Hide options" + closedLabel="More options" + data-test-toggle-more="true" + }} + {{#if showOptions}} +
+ {{#each (drop numRequired model.attrsForKeyType) as |attr|}} + {{partial "partials/form-field-from-model"}} + {{/each}} +
+ {{/if}} + {{/with}} + {{/if}}
diff --git a/ui/app/templates/partials/transit-form-create.hbs b/ui/app/templates/partials/transit-form-create.hbs index 897e07b375..17bbfe0e45 100644 --- a/ui/app/templates/partials/transit-form-create.hbs +++ b/ui/app/templates/partials/transit-form-create.hbs @@ -1,4 +1,4 @@ - +
{{message-error model=key}} diff --git a/ui/app/templates/partials/transit-form-edit.hbs b/ui/app/templates/partials/transit-form-edit.hbs index b3ebba439b..5262c5da9b 100644 --- a/ui/app/templates/partials/transit-form-edit.hbs +++ b/ui/app/templates/partials/transit-form-edit.hbs @@ -1,4 +1,4 @@ - +
{{message-error model=key}} diff --git a/ui/app/templates/vault/cluster/secrets/backend/sign.hbs b/ui/app/templates/vault/cluster/secrets/backend/sign.hbs index 39639fbf65..0a4d552270 100644 --- a/ui/app/templates/vault/cluster/secrets/backend/sign.hbs +++ b/ui/app/templates/vault/cluster/secrets/backend/sign.hbs @@ -84,21 +84,23 @@
{{message-error model=model}} - {{#each (take 1 model.attrs) as |attr|}} - {{partial "partials/form-field-from-model"}} - {{/each}} - {{toggle-button - toggleAttr="showOptions" - toggleTarget=this - openLabel="Hide options" - closedLabel="More options" - }} - {{#if showOptions}} -
- {{#each (drop 1 model.attrs) as |attr|}} - {{partial "partials/form-field-from-model"}} - {{/each}} -
+ {{#if model.attrs}} + {{#each (take 1 model.attrs) as |attr|}} + {{partial "partials/form-field-from-model"}} + {{/each}} + {{toggle-button + toggleAttr="showOptions" + toggleTarget=this + openLabel="Hide options" + closedLabel="More options" + }} + {{#if showOptions}} +
+ {{#each (drop 1 model.attrs) as |attr|}} + {{partial "partials/form-field-from-model"}} + {{/each}} +
+ {{/if}} {{/if}}
diff --git a/ui/app/transforms/object.js b/ui/app/transforms/object.js index 4bf7ddd8d7..c1cf7ac282 100644 --- a/ui/app/transforms/object.js +++ b/ui/app/transforms/object.js @@ -1,18 +1,18 @@ -import $ from 'jquery'; import DS from 'ember-data'; +import { typeOf } from '@ember/utils'; /* DS.attr('object') */ export default DS.Transform.extend({ deserialize: function(value) { - if (!$.isPlainObject(value)) { + if (typeOf(value) !== 'object') { return {}; } else { return value; } }, serialize: function(value) { - if (!$.isPlainObject(value)) { + if (typeOf(value) !== 'object') { return {}; } else { return value; diff --git a/ui/config/optional-features.json b/ui/config/optional-features.json index 21f1dc719e..b1902623ae 100644 --- a/ui/config/optional-features.json +++ b/ui/config/optional-features.json @@ -1,3 +1,3 @@ { - "jquery-integration": true + "jquery-integration": false } diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js index 4d8336bff0..faa4bb2989 100644 --- a/ui/ember-cli-build.js +++ b/ui/ember-cli-build.js @@ -60,6 +60,10 @@ module.exports = function(defaults) { 'ember-test-selectors': { strip: isProd, }, + // https://github.com/ember-cli/ember-fetch/issues/204 + 'ember-fetch': { + preferNative: true, + }, }); app.import('vendor/string-includes.js'); diff --git a/ui/package.json b/ui/package.json index 0b9f2c6620..f01966574c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -40,8 +40,7 @@ } }, "devDependencies": { - "@ember/jquery": "^0.5.2", - "@ember/optional-features": "^0.6.3", + "@ember/optional-features": "^0.7.0", "@hashicorp/structure-icons": "^1.3.0", "Duration.js": "icholy/Duration.js#golang_compatible", "autosize": "^4.0.0", @@ -74,12 +73,14 @@ "ember-cli-content-security-policy": "^1.0.0", "ember-cli-dependency-checker": "^3.0.0", "ember-cli-deprecation-workflow": "^1.0.1", + "ember-cli-element-closest-polyfill": "^0.0.1", "ember-cli-flash": "1.7.1", "ember-cli-htmlbars": "^3.0.0", "ember-cli-htmlbars-inline-precompile": "^1.0.3", "ember-cli-inject-live-reload": "^1.8.2", "ember-cli-page-object": "^1.15.3", - "ember-cli-pretender": "^1.0.1", + "ember-cli-pretender": "^3.1.1", + "ember-cli-qunit": "^4.3.2", "ember-cli-sass": "^9.0.0", "ember-cli-sri": "meirish/ember-cli-sri#rooturl", "ember-cli-string-helpers": "^1.5.0", @@ -94,7 +95,7 @@ "ember-data-model-fragments": "^3.3.0", "ember-engines": "^0.7.0", "ember-export-application-global": "^2.0.0", - "ember-fetch": "^6.1.0", + "ember-fetch": "^6.5.1", "ember-inflector": "^3.0.0", "ember-link-action": "^0.1.2", "ember-load-initializers": "^1.1.0", diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index 809da61093..e6d0a0b88e 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -73,7 +73,7 @@ module('Acceptance | auth', function(hooks) { let body = JSON.parse(lastRequest.requestBody); if (backend.type === 'token') { assert.ok( - Object.keys(lastRequest.requestHeaders).includes('X-Vault-Token'), + Object.keys(lastRequest.requestHeaders).includes('x-vault-token'), 'token uses vault token header' ); } else if (backend.type === 'github') { diff --git a/ui/tests/acceptance/transit-test.js b/ui/tests/acceptance/transit-test.js index 0393e6cf13..f3b090e569 100644 --- a/ui/tests/acceptance/transit-test.js +++ b/ui/tests/acceptance/transit-test.js @@ -5,82 +5,81 @@ import { encodeString } from 'vault/utils/b64'; import authPage from 'vault/tests/pages/auth'; import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; -let generateTransitKeys = async () => { - const ts = new Date().getTime(); - const keys = [ - { - name: `aes-${ts}`, - type: 'aes256-gcm96', - exportable: true, - supportsEncryption: true, - }, - { - name: `aes-convergent-${ts}`, - type: 'aes256-gcm96', - convergent: true, - supportsEncryption: true, - }, - { - name: `chacha-${ts}`, - type: 'chacha20-poly1305', - exportable: true, - supportsEncryption: true, - }, - { - name: `chacha-convergent-${ts}`, - type: 'chacha20-poly1305', - convergent: true, - supportsEncryption: true, - }, - { - name: `ecdsa-${ts}`, - type: 'ecdsa-p256', - exportable: true, - supportsSigning: true, - }, - { - name: `ed25519-${ts}`, - type: 'ed25519', - derived: true, - supportsSigning: true, - }, - { - name: `rsa-2048-${ts}`, - type: `rsa-2048`, - supportsSigning: true, - supportsEncryption: true, - }, - { - name: `rsa-4096-${ts}`, - type: `rsa-4096`, - supportsSigning: true, - supportsEncryption: true, - }, - ]; +const keyTypes = [ + { + name: ts => `aes-${ts}`, + type: 'aes256-gcm96', + exportable: true, + supportsEncryption: true, + }, + { + name: ts => `aes-convergent-${ts}`, + type: 'aes256-gcm96', + convergent: true, + supportsEncryption: true, + }, + { + name: ts => `chacha-${ts}`, + type: 'chacha20-poly1305', + exportable: true, + supportsEncryption: true, + }, + { + name: ts => `chacha-convergent-${ts}`, + type: 'chacha20-poly1305', + convergent: true, + supportsEncryption: true, + }, + { + name: ts => `ecdsa-${ts}`, + type: 'ecdsa-p256', + exportable: true, + supportsSigning: true, + }, + { + name: ts => `ed25519-${ts}`, + type: 'ed25519', + derived: true, + supportsSigning: true, + }, + { + name: ts => `rsa-2048-${ts}`, + type: `rsa-2048`, + supportsSigning: true, + supportsEncryption: true, + }, + { + name: ts => `rsa-4096-${ts}`, + type: `rsa-4096`, + supportsSigning: true, + supportsEncryption: true, + }, +]; - for (let key of keys) { - await click('[data-test-secret-create]'); - await fillIn('[data-test-transit-key-name]', key.name); - await fillIn('[data-test-transit-key-type]', key.type); - if (key.exportable) { - await click('[data-test-transit-key-exportable]'); - } - if (key.derived) { - await click('[data-test-transit-key-derived]'); - } - if (key.convergent) { - await click('[data-test-transit-key-convergent-encryption]'); - } - await click('[data-test-transit-key-create]'); - - // link back to the list - await click('[data-test-secret-root-link]'); +let generateTransitKey = async function(key, now) { + let name = key.name(now); + await click('[data-test-secret-create]'); + await fillIn('[data-test-transit-key-name]', name); + await fillIn('[data-test-transit-key-type]', key.type); + if (key.exportable) { + await click('[data-test-transit-key-exportable]'); } + if (key.derived) { + await click('[data-test-transit-key-derived]'); + } + if (key.convergent) { + await click('[data-test-transit-key-convergent-encryption]'); + } + await click('[data-test-transit-key-create]'); await settled(); - return keys; + + // link back to the list + await click('[data-test-secret-root-link]'); + await settled(); + return name; }; -const testEncryption = async (assert, keyName) => { +const testConvergentEncryption = async function(assert, keyName) { const tests = [ // raw bytes for plaintext and context { @@ -204,14 +203,17 @@ const testEncryption = async (assert, keyName) => { await click('[data-test-transit-b64-toggle="context"]'); } await click('[data-test-button-encrypt]'); + await settled(); if (testCase.assertAfterEncrypt) { testCase.assertAfterEncrypt(keyName); } await click('[data-test-transit-action-link="decrypt"]'); + await settled(); if (testCase.assertBeforeDecrypt) { testCase.assertBeforeDecrypt(keyName); } await click('[data-test-button-decrypt]'); + await settled(); if (testCase.assertAfterDecrypt) { if (testCase.decodeAfterDecrypt) { @@ -225,56 +227,58 @@ const testEncryption = async (assert, keyName) => { }; module('Acceptance | transit', function(hooks) { setupApplicationTest(hooks); + let path; + let now; hooks.beforeEach(async function() { await authPage.login(); - const now = new Date().getTime(); - hooks.transitPath = `transit-${now}`; + now = new Date().getTime(); + path = `transit-${now}`; - await enablePage.enable('transit', hooks.transitPath); - // create a bunch of different kinds of keys - hooks.transitKeys = await generateTransitKeys(); + await enablePage.enable('transit', path); + await settled(); }); - test('transit backend', async function(assert) { - assert.expect(47); - for (let [index, key] of hooks.transitKeys.entries()) { - await visit(`vault/secrets/${hooks.transitPath}/show/${key.name}`); - if (index === 0) { - await click('[data-test-transit-link="versions"]'); - assert - .dom('[data-test-transit-key-version-row]') - .exists({ count: 1 }, `${key.name}: only one key version`); - await click('[data-test-transit-key-rotate] button'); - await click('[data-test-confirm-button]'); - assert - .dom('[data-test-transit-key-version-row]') - .exists({ count: 2 }, `${key.name}: two key versions after rotate`); - } + for (let key of keyTypes) { + test(`transit backend: ${key.type}`, async function(assert) { + let name = await generateTransitKey(key, now); + await visit(`vault/secrets/${path}/show/${name}`); + await settled(); + await click('[data-test-transit-link="versions"]'); + // wait for capabilities + await settled(); + assert.dom('[data-test-transit-key-version-row]').exists({ count: 1 }, `${name}: only one key version`); + await click('[data-test-confirm-action-trigger'); + await click('[data-test-confirm-button]'); + // wait for rotate call + await settled(); + assert + .dom('[data-test-transit-key-version-row]') + .exists({ count: 2 }, `${name}: two key versions after rotate`); await click('[data-test-transit-key-actions-link]'); + await settled(); assert.ok( - currentURL().startsWith(`/vault/secrets/${hooks.transitPath}/actions/${key.name}`), - `${key.name}: navigates to tranist actions` + currentURL().startsWith(`/vault/secrets/${path}/actions/${name}`), + `${name}: navigates to tranist actions` + ); + assert.ok( + find('[data-test-transit-key-version-select]'), + `${name}: the rotated key allows you to select versions` ); - if (index === 0) { - assert.ok( - find('[data-test-transit-key-version-select]'), - `${key.name}: the rotated key allows you to select versions` - ); - } if (key.exportable) { assert.ok( find('[data-test-transit-action-link="export"]'), - `${key.name}: exportable key has a link to export action` + `${name}: exportable key has a link to export action` ); } else { assert .dom('[data-test-transit-action-link="export"]') - .doesNotExist(`${key.name}: non-exportable key does not link to export action`); + .doesNotExist(`${name}: non-exportable key does not link to export action`); } if (key.convergent && key.supportsEncryption) { - await testEncryption(assert, key.name); + await testConvergentEncryption(assert, name); } - } - }); + await settled(); + }); + } }); diff --git a/ui/tests/helpers/poll-cluster.js b/ui/tests/helpers/poll-cluster.js index bbe82da88a..45b0ee174a 100644 --- a/ui/tests/helpers/poll-cluster.js +++ b/ui/tests/helpers/poll-cluster.js @@ -1,13 +1,8 @@ import { run } from '@ember/runloop'; -import { registerAsyncHelper } from '@ember/test'; export function pollCluster(owner) { - const clusterRoute = owner.lookup('route:vault/cluster'); + const store = owner.lookup('service:store'); return run(() => { - return clusterRoute.controller.model.reload(); + return store.peekAll('cluster').firstObject.reload(); }); } - -registerAsyncHelper('pollCluster', function(app) { - pollCluster(app.__container__); -}); diff --git a/ui/tests/integration/components/auth-config-form/options-test.js b/ui/tests/integration/components/auth-config-form/options-test.js index f2200c14e8..0ed015f735 100644 --- a/ui/tests/integration/components/auth-config-form/options-test.js +++ b/ui/tests/integration/components/auth-config-form/options-test.js @@ -31,12 +31,6 @@ module('Integration | Component | auth-config-form options', function(hooks) { this.owner.lookup('service:flash-messages').registerTypes(['success']); this.owner.register('service:router', routerService); this.router = this.owner.lookup('service:router'); - - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); }); test('it submits data correctly', async function(assert) { diff --git a/ui/tests/integration/components/auth-form-test.js b/ui/tests/integration/components/auth-form-test.js index 2330fbd7d5..93dfb8bfef 100644 --- a/ui/tests/integration/components/auth-form-test.js +++ b/ui/tests/integration/components/auth-form-test.js @@ -1,12 +1,12 @@ import { later, run } from '@ember/runloop'; import EmberObject from '@ember/object'; import { resolve } from 'rsvp'; -import $ from 'jquery'; import Service from '@ember/service'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; +import fetch from 'fetch'; import sinon from 'sinon'; import Pretender from 'pretender'; import { create } from 'ember-cli-page-object'; @@ -15,8 +15,8 @@ import authForm from '../../pages/components/auth-form'; const component = create(authForm); const authService = Service.extend({ - authenticate() { - return $.getJSON('http://localhost:2000'); + async authenticate() { + return fetch('http://localhost:2000'); }, setLastFetch() {}, }); @@ -204,7 +204,7 @@ module('Integration | Component | auth form', function(hooks) { this.post('/v1/sys/wrapping/unwrap', () => { return [ 200, - { 'Content-Type': 'application/json' }, + { 'content-type': 'application/json' }, JSON.stringify({ auth: { client_token: '12345', @@ -222,7 +222,7 @@ module('Integration | Component | auth form', function(hooks) { await settled(); assert.equal(server.handledRequests[0].url, '/v1/sys/wrapping/unwrap', 'makes call to unwrap the token'); assert.equal( - server.handledRequests[0].requestHeaders['X-Vault-Token'], + server.handledRequests[0].requestHeaders['x-vault-token'], wrappedToken, 'uses passed wrapped token for the unwrap' ); diff --git a/ui/tests/integration/components/config-pki-ca-test.js b/ui/tests/integration/components/config-pki-ca-test.js index f318864b38..2096aeb1f8 100644 --- a/ui/tests/integration/components/config-pki-ca-test.js +++ b/ui/tests/integration/components/config-pki-ca-test.js @@ -29,7 +29,6 @@ module('Integration | Component | config pki ca', function(hooks) { hooks.beforeEach(function() { this.server = apiStub(); - component.setContext(this); this.owner.lookup('service:flash-messages').registerTypes(['success']); this.owner.register('service:store', storeStub); this.storeService = this.owner.lookup('service:store'); @@ -37,7 +36,6 @@ module('Integration | Component | config pki ca', function(hooks) { hooks.afterEach(function() { this.server.shutdown(); - component.removeContext(); }); const config = function(pem) { diff --git a/ui/tests/integration/components/config-pki-test.js b/ui/tests/integration/components/config-pki-test.js index a59753da7c..9fec291776 100644 --- a/ui/tests/integration/components/config-pki-test.js +++ b/ui/tests/integration/components/config-pki-test.js @@ -12,14 +12,9 @@ module('Integration | Component | config pki', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { - component.setContext(this); this.owner.lookup('service:flash-messages').registerTypes(['success']); }); - hooks.afterEach(function() { - component.removeContext(); - }); - const config = function(saveFn) { return { save: saveFn, diff --git a/ui/tests/integration/components/console/ui-panel-test.js b/ui/tests/integration/components/console/ui-panel-test.js index 18fa928a29..2537f00a43 100644 --- a/ui/tests/integration/components/console/ui-panel-test.js +++ b/ui/tests/integration/components/console/ui-panel-test.js @@ -10,14 +10,6 @@ const component = create(uiPanel); module('Integration | Component | console/ui panel', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders', async function(assert) { await render(hbs`{{console/ui-panel}}`); assert.ok(component.hasInput); diff --git a/ui/tests/integration/components/control-group-success-test.js b/ui/tests/integration/components/control-group-success-test.js index 3c3ee97c3a..59dcfe399f 100644 --- a/ui/tests/integration/components/control-group-success-test.js +++ b/ui/tests/integration/components/control-group-success-test.js @@ -41,14 +41,9 @@ module('Integration | Component | control group success', function(hooks) { this.owner.register('service:router', routerService); this.owner.register('service:store', storeService); this.router = this.owner.lookup('service:router'); - component.setContext(this); }); }); - hooks.afterEach(function() { - component.removeContext(); - }); - const MODEL = { approved: false, requestPath: 'foo/bar', diff --git a/ui/tests/integration/components/control-group-test.js b/ui/tests/integration/components/control-group-test.js index 714868eb00..2b0c2d0158 100644 --- a/ui/tests/integration/components/control-group-test.js +++ b/ui/tests/integration/components/control-group-test.js @@ -25,17 +25,12 @@ module('Integration | Component | control group', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { - component.setContext(this); this.owner.register('service:auth', authService); this.owner.register('service:control-group', controlGroupService); this.controlGroup = this.owner.lookup('service:controlGroup'); this.auth = this.owner.lookup('service:auth'); }); - hooks.afterEach(function() { - component.removeContext(); - }); - const setup = (modelData = {}, authData = {}) => { let modelDefaults = { approved: false, diff --git a/ui/tests/integration/components/edit-form-test.js b/ui/tests/integration/components/edit-form-test.js index ab7b3cbb21..62cfe85a65 100644 --- a/ui/tests/integration/components/edit-form-test.js +++ b/ui/tests/integration/components/edit-form-test.js @@ -37,14 +37,9 @@ module('Integration | Component | edit form', function(hooks) { run(() => { this.owner.unregister('service:flash-messages'); this.owner.register('service:flash-messages', flash); - component.setContext(this); }); }); - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders', async function(assert) { let model = createModel(); this.set('model', model); diff --git a/ui/tests/integration/components/hover-copy-button-test.js b/ui/tests/integration/components/hover-copy-button-test.js index 4875a3142f..ae0d50a6d4 100644 --- a/ui/tests/integration/components/hover-copy-button-test.js +++ b/ui/tests/integration/components/hover-copy-button-test.js @@ -9,14 +9,6 @@ const component = create(copyButton); module('Integration | Component | hover copy button', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - // ember-cli-clipboard helpers don't like the new style skip('it shows success message in tooltip', async function(assert) { this.set('copyValue', 'foo'); diff --git a/ui/tests/integration/components/identity/item-details-test.js b/ui/tests/integration/components/identity/item-details-test.js index cd8153ea4b..e15a40a836 100644 --- a/ui/tests/integration/components/identity/item-details-test.js +++ b/ui/tests/integration/components/identity/item-details-test.js @@ -14,14 +14,9 @@ module('Integration | Component | identity/item details', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { - component.setContext(this); this.owner.lookup('service:flash-messages').registerTypes(['success']); }); - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders the disabled warning', async function(assert) { let model = EmberObject.create({ save() { diff --git a/ui/tests/integration/components/kv-object-editor-test.js b/ui/tests/integration/components/kv-object-editor-test.js index 917dc0b2d2..c4b881816a 100644 --- a/ui/tests/integration/components/kv-object-editor-test.js +++ b/ui/tests/integration/components/kv-object-editor-test.js @@ -12,14 +12,6 @@ const component = create(kvObjectEditor); module('Integration | Component | kv object editor', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders with no initial value', async function(assert) { let spy = sinon.spy(); this.set('onChange', spy); diff --git a/ui/tests/integration/components/masked-input-test.js b/ui/tests/integration/components/masked-input-test.js index a7c4362cfa..d5f8c67a50 100644 --- a/ui/tests/integration/components/masked-input-test.js +++ b/ui/tests/integration/components/masked-input-test.js @@ -10,14 +10,6 @@ const component = create(maskedInput); module('Integration | Component | masked input', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - const hasClass = (classString = '', classToFind) => { return classString.split(' ').includes(classToFind); }; diff --git a/ui/tests/integration/components/mount-backend-form-test.js b/ui/tests/integration/components/mount-backend-form-test.js index ee6ea7c6ed..4bc2459b9a 100644 --- a/ui/tests/integration/components/mount-backend-form-test.js +++ b/ui/tests/integration/components/mount-backend-form-test.js @@ -16,13 +16,11 @@ module('Integration | Component | mount backend form', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { - component.setContext(this); this.owner.lookup('service:flash-messages').registerTypes(['success', 'danger']); this.server = apiStub(); }); hooks.afterEach(function() { - component.removeContext(); this.server.shutdown(); }); diff --git a/ui/tests/integration/components/nav-header-test.js b/ui/tests/integration/components/nav-header-test.js index bf33e6f724..2bc769b85a 100644 --- a/ui/tests/integration/components/nav-header-test.js +++ b/ui/tests/integration/components/nav-header-test.js @@ -10,14 +10,6 @@ const component = create(navHeader); module('Integration | Component | nav header', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders', async function(assert) { await render(hbs` {{#nav-header as |h|}} diff --git a/ui/tests/integration/components/radial-progress-test.js b/ui/tests/integration/components/radial-progress-test.js index 97521f49ab..4a42b97853 100644 --- a/ui/tests/integration/components/radial-progress-test.js +++ b/ui/tests/integration/components/radial-progress-test.js @@ -10,14 +10,6 @@ const component = create(radialProgress); module('Integration | Component | radial progress', function(hooks) { setupRenderingTest(hooks); - hooks.beforeEach(function() { - component.setContext(this); - }); - - hooks.afterEach(function() { - component.removeContext(); - }); - test('it renders', async function(assert) { // We have to manually round the circumference, strokeDash, and strokeDashOffset because // ie11 truncates decimals differently than other browsers. diff --git a/ui/tests/integration/services/auth-test.js b/ui/tests/integration/services/auth-test.js index 2e40a9fa18..b7488cc7cf 100644 --- a/ui/tests/integration/services/auth-test.js +++ b/ui/tests/integration/services/auth-test.js @@ -129,8 +129,8 @@ module('Integration | Service | auth', function(hooks) { this.server = new Pretender(function() { this.get('/v1/auth/token/lookup-self', function(request) { let resp = copy(ROOT_TOKEN_RESPONSE, true); - resp.id = request.requestHeaders['X-Vault-Token']; - resp.data.id = request.requestHeaders['X-Vault-Token']; + resp.id = request.requestHeaders['x-vault-token']; + resp.data.id = request.requestHeaders['x-vault-token']; return [200, {}, resp]; }); this.post('/v1/auth/userpass/login/:username', function(request) { @@ -205,8 +205,7 @@ module('Integration | Service | auth', function(hooks) { }); }); - test('token authentication: root token in ember development environment', function(assert) { - let done = assert.async(); + test('token authentication: root token in ember development environment', async function(assert) { let self = this; let service = this.owner.factoryFor('service:auth').create({ storage(tokenName) { @@ -222,30 +221,26 @@ module('Integration | Service | auth', function(hooks) { }, environment: () => 'development', }); - run(() => { - service.authenticate({ clusterId: '1', backend: 'token', data: { token: 'test' } }).then(() => { - const clusterTokenName = service.get('currentTokenName'); - const clusterToken = service.get('currentToken'); - const authData = service.get('authData'); + await service.authenticate({ clusterId: '1', backend: 'token', data: { token: 'test' } }); + const clusterTokenName = service.get('currentTokenName'); + const clusterToken = service.get('currentToken'); + const authData = service.get('authData'); - const expectedTokenName = `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`; - assert.equal('test', clusterToken, 'token is saved properly'); - assert.equal( - `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`, - clusterTokenName, - 'token name is saved properly' - ); - assert.equal('token', authData.backend.type, 'backend is saved properly'); - assert.equal( - ROOT_TOKEN_RESPONSE.data.display_name, - authData.displayName, - 'displayName is saved properly' - ); - assert.ok(this.store.keys().includes(expectedTokenName), 'root token is stored in the store'); - assert.equal(this.memStore.keys().length, 0, 'mem storage is empty'); - done(); - }); - }); + const expectedTokenName = `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`; + assert.equal('test', clusterToken, 'token is saved properly'); + assert.equal( + `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`, + clusterTokenName, + 'token name is saved properly' + ); + assert.equal('token', authData.backend.type, 'backend is saved properly'); + assert.equal( + ROOT_TOKEN_RESPONSE.data.display_name, + authData.displayName, + 'displayName is saved properly' + ); + assert.ok(this.store.keys().includes(expectedTokenName), 'root token is stored in the store'); + assert.equal(this.memStore.keys().length, 0, 'mem storage is empty'); }); test('github authentication', function(assert) { @@ -313,8 +308,8 @@ module('Integration | Service | auth', function(hooks) { this.server.map(function() { this.get('/v1/auth/token/lookup-self', function(request) { let resp = copy(tokenResp, true); - resp.id = request.requestHeaders['X-Vault-Token']; - resp.data.id = request.requestHeaders['X-Vault-Token']; + resp.id = request.requestHeaders['x-vault-token']; + resp.data.id = request.requestHeaders['x-vault-token']; return [200, {}, resp]; }); }); diff --git a/ui/yarn.lock b/ui/yarn.lock index 4f119de096..282979f134 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -1158,20 +1158,10 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@ember/jquery@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@ember/jquery/-/jquery-0.5.2.tgz#fe312c03ada0022fa092d23f7cd7e2eb0374b53a" - integrity sha1-/jEsA62gAi+gktI/fNfi6wN0tTo= - dependencies: - broccoli-funnel "^2.0.1" - ember-cli-babel "^6.6.0" - jquery "^3.3.1" - resolve "^1.7.1" - -"@ember/optional-features@^0.6.3": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@ember/optional-features/-/optional-features-0.6.4.tgz#8199f853c1781234fcb1f05090cddd0b822bff69" - integrity sha512-nKmKxMk+Q/BGE8cmfq8KTHnYHVgrU3GHhy/eZ/OTj/fUvzXZhxaEVFOfAXssiOzV3FOQDJjznpbua2TEtHaQRw== +"@ember/optional-features@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@ember/optional-features/-/optional-features-0.7.0.tgz#f65a858007020ddfb8342f586112750c32abd2d9" + integrity sha512-qLXvL/Kq/COb43oQmCrKx7Fy8k1XJDI2RlgbCnZHH26AGVgJT/sZugx1A2AIxKdamtl/Mi+rQSjGIuscSjqjDw== dependencies: chalk "^2.3.0" co "^4.6.0" @@ -1190,6 +1180,16 @@ ember-cli-babel "^6.16.0" ember-compatibility-helpers "^1.0.0" +"@ember/test-helpers@^0.7.26": + version "0.7.27" + resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-0.7.27.tgz#c622cabd0cbb95b34efc1e1b6274ab5a14edc138" + integrity sha512-AQESk0FTFxRY6GyZ8PharR4SC7Fju0rXqNkfNYIntAjzefZ8xEqEM4iXDj5h7gAvfx/8dA69AQ9+p7ubc+KvJg== + dependencies: + broccoli-funnel "^2.0.1" + ember-assign-polyfill "~2.4.0" + ember-cli-babel "^6.12.0" + ember-cli-htmlbars-inline-precompile "^1.0.0" + "@ember/test-helpers@^1.3.1", "@ember/test-helpers@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.5.0.tgz#a480181c412778294e317c256d04ca52e63c813a" @@ -1985,6 +1985,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== +"@types/symlink-or-copy@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a" + integrity sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg== + "@types/tmp@^0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" @@ -2290,6 +2295,11 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" +"@xg-wang/whatwg-fetch@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@xg-wang/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#f7b222c012a238e7d6e89ed3d72a1e0edb58453d" + integrity sha512-ULtqA6L75RLzTNW68IiOja0XYv4Ebc3OGMzfia1xxSEMpD0mk/pMvkQX0vbCFyQmKc5xGp80Ms2WiSlXLh8hbA== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2330,6 +2340,11 @@ abortcontroller-polyfill@^1.1.9: resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.1.9.tgz#9fefe359fda2e9e0932dc85e6106453ac393b2da" integrity sha512-omvG7zOHIs3BphdH62Kh3xy8nlftAsTyp7PDa9EmC3Jz9pa6sZFYk7UhNgu9Y4sIBhj6jF0RgeFZYvPnsP5sBw== +abortcontroller-polyfill@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.3.0.tgz#de69af32ae926c210b7efbcc29bf644ee4838b00" + integrity sha512-lbWQgf+eRvku3va8poBlDBO12FigTQr9Zb7NIjXrePrhxWVKdCP2wbDl1tLDaYa18PWTom3UEWwdH13S46I+yA== + accepts@~1.3.4, accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" @@ -4499,7 +4514,7 @@ broccoli-kitchen-sink-helpers@^0.3.1: glob "^5.0.10" mkdirp "^0.5.1" -broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.0, broccoli-merge-trees@^1.1.1, broccoli-merge-trees@^1.2.1: +broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.0, broccoli-merge-trees@^1.1.1: version "1.2.4" resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz#a001519bb5067f06589d91afa2942445a2d0fdb5" integrity sha1-oAFRm7UGfwZYnZGvopQkRaLQ/bU= @@ -4607,6 +4622,25 @@ broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.2.0: symlink-or-copy "^1.0.1" walk-sync "^0.3.1" +broccoli-persistent-filter@^2.1.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-2.2.3.tgz#63dbd7ff05b6d7dcfdefd75238e1097370ac7467" + integrity sha512-WSq6S9lC78LZ2T6L8s+NueEDuWdVSDiwjH8XbHo4ocL7V5fZLXupxvnPWtoH2Jp20j6/nvznTkgKJC4g70JVdA== + dependencies: + async-disk-cache "^1.2.1" + async-promise-queue "^1.0.3" + broccoli-plugin "^1.0.0" + fs-tree-diff "^2.0.0" + hash-for-dep "^1.5.0" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + mkdirp "^0.5.1" + promise-map-series "^0.2.1" + rimraf "^2.6.1" + rsvp "^4.7.0" + symlink-or-copy "^1.0.1" + walk-sync "^1.0.0" + broccoli-persistent-filter@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-2.2.2.tgz#e0180e75ede5dd05d4c702f24f6c049e93fba915" @@ -4736,6 +4770,26 @@ broccoli-stew@^2.0.0: symlink-or-copy "^1.2.0" walk-sync "^0.3.0" +broccoli-stew@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-2.1.0.tgz#ba73add17fda3b9b01d8cfb343a8b613b7136a0a" + integrity sha512-tgCkuTWYl4uf7k7ib2D79KFEj2hCgnTUNPMnrCoAha0/4bywcNccmaZVWtL9Ex37yX5h5eAbnM/ak2ULoMwSSw== + dependencies: + broccoli-debug "^0.6.5" + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^3.0.1" + broccoli-persistent-filter "^2.1.1" + broccoli-plugin "^1.3.1" + chalk "^2.4.1" + debug "^3.1.0" + ensure-posix-path "^1.0.1" + fs-extra "^6.0.1" + minimatch "^3.0.4" + resolve "^1.8.1" + rsvp "^4.8.4" + symlink-or-copy "^1.2.0" + walk-sync "^0.3.3" + broccoli-string-replace@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/broccoli-string-replace/-/broccoli-string-replace-0.1.2.tgz#1ed92f85680af8d503023925e754e4e33676b91f" @@ -4919,6 +4973,15 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" +browserslist@^4.0.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.0.tgz#5274028c26f4d933d5b1323307c1d1da5084c9ff" + integrity sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg== + dependencies: + caniuse-lite "^1.0.30000967" + electron-to-chromium "^1.3.133" + node-releases "^1.1.19" + browserslist@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.2.1.tgz#257a24c879d1cd4016348eee5c25de683260b21d" @@ -5135,6 +5198,13 @@ calculate-cache-key-for-tree@^1.1.0: dependencies: json-stable-stringify "^1.0.1" +calculate-cache-key-for-tree@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-2.0.0.tgz#7ac57f149a4188eacb0a45b210689215d3fef8d6" + integrity sha512-Quw8a6y8CPmRd6eU+mwypktYCwUcf8yVFIRbNZ6tPQEckX9yd+EBVEPC/GSZZrMWH9e7Vz4pT7XhpmyApRByLQ== + dependencies: + json-stable-stringify "^1.0.1" + call-limit@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" @@ -5238,6 +5308,21 @@ can-symlink@^1.0.0: dependencies: tmp "0.0.28" +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000967: + version "1.0.30000969" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000969.tgz#7664f571f2072657bde70b00a1fc1ba41f1942a9" + integrity sha512-Kus0yxkoAJgVc0bax7S4gLSlFifCa7MnSZL9p9VuS/HIKEL4seaqh28KIQAAO50cD/rJ5CiJkJFapkdDAlhFxQ== + caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844: version "1.0.30000885" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz#e889e9f8e7e50e769f2a49634c932b8aee622984" @@ -6997,6 +7082,11 @@ electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.113: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g== +electron-to-chromium@^1.3.133: + version "1.3.135" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.135.tgz#f5799b95f2bcd8de17cde47d63392d83a4477041" + integrity sha512-xXLNstRdVsisPF3pL3H9TVZo2XkMILfqtD6RiWIUmDK2sFX1Bjwqmd8LBp0Kuo2FgKO63JXPoEVGm8WyYdwP0Q== + electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47: version "1.3.64" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.64.tgz#39f5a93bf84ab7e10cfbb7522ccfc3f1feb756cf" @@ -7012,6 +7102,11 @@ elegant-spinner@^1.0.1: resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= +element-closest@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/element-closest/-/element-closest-2.0.2.tgz#72a740a107453382e28df9ce5dbb5a8df0f966ec" + integrity sha1-cqdAoQdFM4LijfnOXbtajfD5Zuw= + elliptic@^6.0.0: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" @@ -7071,6 +7166,14 @@ ember-assign-polyfill@^2.5.0, ember-assign-polyfill@^2.6.0: ember-cli-babel "^6.16.0" ember-cli-version-checker "^2.0.0" +ember-assign-polyfill@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/ember-assign-polyfill/-/ember-assign-polyfill-2.4.0.tgz#acb00466f7d674b3e6b030acfe255b3b1f6472e1" + integrity sha512-0SnGQb9CenRqbZdIa1KFsEjT+1ijGWfAbCSaDbg5uVa5l6HPdppuTzOXK6sfEQMsd2nbrp27QWFy7W5VX6l4Ag== + dependencies: + ember-cli-babel "^6.6.0" + ember-cli-version-checker "^2.0.0" + ember-auto-import@^1.2.3: version "1.2.13" resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.2.13.tgz#8f6f5d1c64e173f9093dd0c5031dc1d446b7cff1" @@ -7336,6 +7439,17 @@ ember-cli-deprecation-workflow@^1.0.1: broccoli-plugin "^1.3.1" ember-debug-handlers-polyfill "^1.1.1" +ember-cli-element-closest-polyfill@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ember-cli-element-closest-polyfill/-/ember-cli-element-closest-polyfill-0.0.1.tgz#cc4d09120acc8a655e77a288ce929d4691d2c80a" + integrity sha512-LBYICCsG1WIhsieUoZndW5LQyuz7DtnXYgGrH9APuwR7qYsEdXJt5Uv6Pvu211GY2EnuNtJ7V24ZhFGCFu1dQg== + dependencies: + broccoli-funnel "^2.0.1" + caniuse-api "^3.0.0" + element-closest "^2.0.2" + ember-cli-babel "^6.16.0" + fastboot-transform "^0.1.3" + ember-cli-flash@1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/ember-cli-flash/-/ember-cli-flash-1.7.1.tgz#0b9d2464d80144df0c65e928b6fc006259ef6a58" @@ -7350,6 +7464,17 @@ ember-cli-get-component-path-option@^1.0.0: resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771" integrity sha1-DXtZVVni+QUKvtgE8djv8bCLx3E= +ember-cli-htmlbars-inline-precompile@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-1.0.5.tgz#312e050c9e3dd301c55fb399fd706296cd0b1d6a" + integrity sha512-/CNEqPxroIcbY6qejrt704ZaghHLCntZKYLizFfJ2esirXoJx6fuYKBY1YyJ8GOgjfbHHKjBZuK4vFFJpkGqkQ== + dependencies: + babel-plugin-htmlbars-inline-precompile "^0.2.5" + ember-cli-version-checker "^2.1.2" + hash-for-dep "^1.2.3" + heimdalljs-logger "^0.1.9" + silent-error "^1.1.0" + ember-cli-htmlbars-inline-precompile@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-1.0.3.tgz#332ff96c06fc522965162f1090d78a615379c3c2" @@ -7486,15 +7611,27 @@ ember-cli-preprocess-registry@^3.1.2: process-relative-require "^1.0.0" silent-error "^1.0.0" -ember-cli-pretender@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ember-cli-pretender/-/ember-cli-pretender-1.0.1.tgz#35540babddef6f2778e91c627d190c73505103cd" - integrity sha1-NVQLq93vbyd46RxifRkMc1BRA80= +ember-cli-pretender@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/ember-cli-pretender/-/ember-cli-pretender-3.1.1.tgz#289c41683de266fec8bfaf5b7b7f6026aaefc8cf" + integrity sha512-RGGj9la0138bgHUxyaGDHCZydmdpW+BFN9v0vMBzNPeXsaexCZotaFTIZDCNcKWPx8jtRHR8AXf318VRGXLJsw== dependencies: - broccoli-funnel "^1.1.0" - broccoli-merge-trees "^1.2.1" - pretender "^1.4.2" - resolve "^1.2.0" + abortcontroller-polyfill "^1.1.9" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^3.0.0" + ember-cli-babel "^6.6.0" + fake-xml-http-request "^2.0.0" + pretender "^2.1.0" + route-recognizer "^0.3.3" + whatwg-fetch "^3.0.0" + +ember-cli-qunit@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/ember-cli-qunit/-/ember-cli-qunit-4.4.0.tgz#0edd7d651001d0d7ea200b9236a4733a5b7420f1" + integrity sha512-+gkx380AV4WXYjQeIuQi675STL9K12fHFtxs8B9u3EFbw45vJKrnYR4Vph3FujxhE/1pr/Je8kZEPAuezZAVLw== + dependencies: + ember-cli-babel "^6.11.0" + ember-qunit "^3.5.0" ember-cli-sass@^9.0.0: version "9.0.0" @@ -7827,18 +7964,20 @@ ember-export-application-global@^2.0.0: dependencies: ember-cli-babel "^6.0.0-beta.7" -ember-fetch@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-6.2.0.tgz#88988e1fb94f44722a1cbb9416310711e65f6706" - integrity sha512-Rc/QgsfPOldT55WSnlN4z7TqKsE1YqGnjAwB7I8myjgEulIu00t0wx4zLjznEz5ng6VeRupXW6WaGE/B/0BYUA== +ember-fetch@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-6.5.1.tgz#6512153b9b85042744ed5a7934c8edb4a5b02dd0" + integrity sha512-ZA90lbTFZHhQCQKQNA6/3TdtiF1wBoT8nC7EI1pmkUZ49XDBP7i2eddUodR6qWRn8jK/D7IavQy3tx5fJBx7mw== dependencies: - abortcontroller-polyfill "^1.1.9" + abortcontroller-polyfill "^1.3.0" broccoli-concat "^3.2.2" broccoli-debug "^0.6.5" broccoli-merge-trees "^3.0.0" broccoli-rollup "^2.1.1" - broccoli-stew "^2.0.0" + broccoli-stew "^2.1.0" broccoli-templater "^2.0.1" + calculate-cache-key-for-tree "^2.0.0" + caniuse-api "^3.0.0" ember-cli-babel "^6.8.2" node-fetch "^2.3.0" whatwg-fetch "^3.0.0" @@ -7916,6 +8055,19 @@ ember-power-select@^2.0.0: ember-text-measurer "^0.5.0" ember-truth-helpers "^2.1.0" +ember-qunit@^3.5.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-3.5.3.tgz#bfd0bff8298c78c77e870cca43fe0826e78a0d09" + integrity sha512-FmXsI1bGsZ5th25x4KEle2fLCVURTptsQODfBt+Pg8tk9rX7y79cqny91PrhtkhE+giZ8p029tnq94SdpJ4ojg== + dependencies: + "@ember/test-helpers" "^0.7.26" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^2.0.0" + common-tags "^1.4.0" + ember-cli-babel "^6.8.2" + ember-cli-test-loader "^2.2.0" + qunit "~2.6.0" + ember-qunit@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-4.4.1.tgz#3654cadf9fa7e2287fe7b61fc7f19c3eb06222b5" @@ -8653,6 +8805,11 @@ exenv@^1.2.0: resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= +exists-stat@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/exists-stat/-/exists-stat-1.0.0.tgz#0660e3525a2e89d9e446129440c272edfa24b529" + integrity sha1-BmDjUlouidnkRhKUQMJy7foktSk= + exists-sync@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/exists-sync/-/exists-sync-0.0.4.tgz#9744c2c428cc03b01060db454d4b12f0ef3c8879" @@ -8816,10 +8973,10 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fake-xml-http-request@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-1.6.0.tgz#bd0ac79ae3e2660098282048a12c730a6f64d550" - integrity sha512-99XPwwSg89BfzPuv4XCpZxn3EbauMCgAQCxq9MzrvS6DFD73OON6AnUTicL4A0HZtYMBwCZBWVnRqGjZDgQkTg== +fake-xml-http-request@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.0.0.tgz#41a92f0ca539477700cb1dafd2df251d55dac8ff" + integrity sha512-UjNnynb6eLAB0lyh2PlTEkjRJORnNsVF1hbzU+PQv89/cyBV9GDRCy7JAcLQgeCLYT+3kaumWWZKEJvbaK74eQ== fast-deep-equal@^1.0.0: version "1.1.0" @@ -8891,6 +9048,14 @@ fastboot-transform@0.1.1: dependencies: broccoli-stew "^1.5.0" +fastboot-transform@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/fastboot-transform/-/fastboot-transform-0.1.3.tgz#7dea0b117594afd8772baa6c9b0919644e7f7dcd" + integrity sha512-6otygPIJw1ARp1jJb+6KVO56iKBjhO+5x59RSC9qiZTbZRrv+HZAuP00KD3s+nWMvcFDemtdkugki9DNFTTwCQ== + dependencies: + broccoli-stew "^1.5.0" + convert-source-map "^1.5.1" + fault@^1.0.1, fault@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa" @@ -9154,7 +9319,7 @@ find-yarn-workspace-root@^1.1.0: fs-extra "^4.0.3" micromatch "^3.1.4" -findup-sync@^2.0.0: +findup-sync@2.0.0, findup-sync@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= @@ -9432,6 +9597,17 @@ fs-tree-diff@^1.0.2: path-posix "^1.0.0" symlink-or-copy "^1.1.8" +fs-tree-diff@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa" + integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A== + dependencies: + "@types/symlink-or-copy" "^1.2.0" + heimdalljs-logger "^0.1.7" + object-assign "^4.1.0" + path-posix "^1.0.0" + symlink-or-copy "^1.1.8" + fs-updater@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/fs-updater/-/fs-updater-1.0.4.tgz#2329980f99ae9176e9a0e84f7637538a182ce63b" @@ -12310,7 +12486,7 @@ lodash.union@~4.6.0: resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg= -lodash.uniq@^4.2.0, lodash.uniq@~4.5.0: +lodash.uniq@^4.2.0, lodash.uniq@^4.5.0, lodash.uniq@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= @@ -13337,6 +13513,13 @@ node-releases@^1.0.0-alpha.14: dependencies: semver "^5.3.0" +node-releases@^1.1.19: + version "1.1.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.19.tgz#c492d1e381fea0350b338b646c27867e88e91b3d" + integrity sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA== + dependencies: + semver "^5.3.0" + node-releases@^1.1.3, node-releases@^1.1.8: version "1.1.9" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.9.tgz#70d0985ec4bf7de9f08fc481f5dae111889ca482" @@ -14556,12 +14739,13 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -pretender@^1.4.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/pretender/-/pretender-1.6.1.tgz#77d1e42ac8c6b298f5cd43534a87645df035db8c" - integrity sha1-d9HkKsjGspj1zUNTSodkXfA124w= +pretender@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pretender/-/pretender-2.1.1.tgz#5085f0a1272c31d5b57c488386f69e6ca207cb35" + integrity sha512-IkidsJzaroAanw3I43tKCFm2xCpurkQr9aPXv5/jpN+LfCwDaeI8rngVWtQZTx4qqbhc5zJspnLHJ4N/25KvDQ== dependencies: - fake-xml-http-request "^1.6.0" + "@xg-wang/whatwg-fetch" "^3.0.0" + fake-xml-http-request "^2.0.0" route-recognizer "^0.3.3" prettier-eslint-cli@^4.7.1: @@ -14952,6 +15136,19 @@ qunit@^2.9.2: node-watch "0.6.0" resolve "1.9.0" +qunit@~2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/qunit/-/qunit-2.6.2.tgz#551210c5cf857258a4fe39a7fe15d9e14dfef22c" + integrity sha512-PHbKulmd4rrDhFto7iHicIstDTX7oMRvAcI7loHstvU8J7AOGwzcchONmy+EG4KU8HDk0K90o7vO0GhlYyKlOg== + dependencies: + commander "2.12.2" + exists-stat "1.0.0" + findup-sync "2.0.0" + js-reporters "1.2.1" + resolve "1.5.0" + sane "^2.5.2" + walk-sync "0.3.2" + qw@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" @@ -15909,6 +16106,13 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + integrity sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw== + dependencies: + path-parse "^1.0.5" + resolve@1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" @@ -15916,7 +16120,7 @@ resolve@1.9.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.3, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.7.1, resolve@^1.8.1: +resolve@^1.1.3, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.7.1, resolve@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== @@ -16144,7 +16348,7 @@ samsam@~1.1: resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" integrity sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE= -sane@^2.4.1: +sane@^2.4.1, sane@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o= @@ -18376,6 +18580,14 @@ walk-back@^3.0.0: resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-3.0.1.tgz#0c0012694725604960d6c2f75aaf1a1e7d455d35" integrity sha512-umiNB2qLO731Sxbp6cfZ9pwURJzTnftxE4Gc7hq8n/ehkuXC//s9F65IEIJA2ZytQZ1ZOsm/Fju4IWx0bivkUQ== +walk-sync@0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.2.tgz#4827280afc42d0e035367c4a4e31eeac0d136f75" + integrity sha512-FMB5VqpLqOCcqrzA9okZFc0wq0Qbmdm396qJxvQZhDpyu0W95G9JCmp74tx7iyYnyOcBtUuKJsgIKAqjozvmmQ== + dependencies: + ensure-posix-path "^1.0.0" + matcher-collection "^1.0.0" + walk-sync@^0.2.5, walk-sync@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.2.7.tgz#b49be4ee6867657aeb736978b56a29d10fa39969"