diff --git a/ui/lib/replication/addon/controllers/application.js b/ui/lib/replication/addon/controllers/application.js index 36641ba42c..4a06e9a478 100644 --- a/ui/lib/replication/addon/controllers/application.js +++ b/ui/lib/replication/addon/controllers/application.js @@ -10,6 +10,7 @@ import Controller from '@ember/controller'; import { copy } from 'ember-copy'; import { resolve } from 'rsvp'; import decodeConfigFromJWT from 'replication/utils/decode-config-from-jwt'; +import { buildWaiter } from '@ember/test-waiters'; const DEFAULTS = { token: null, @@ -23,11 +24,13 @@ const DEFAULTS = { paths: [], }, }; +const waiter = buildWaiter('replication-actions'); export default Controller.extend(copy(DEFAULTS, true), { isModalActive: false, isTokenCopied: false, expirationDate: null, + router: service(), store: service(), rm: service('replication-mode'), replicationMode: alias('rm.mode'), @@ -87,6 +90,7 @@ export default Controller.extend(copy(DEFAULTS, true), { }, submitHandler(action, clusterMode, data, event) { + const waiterToken = waiter.beginAsync(); const replicationMode = this.replicationMode; if (event && event.preventDefault) { event.preventDefault(); @@ -116,7 +120,10 @@ export default Controller.extend(copy(DEFAULTS, true), { }, (...args) => this.submitError(...args) ) - .finally(() => this.set('secondaryToRevoke', null)); + .finally(() => { + this.set('secondaryToRevoke', null); + waiter.endAsync(waiterToken); + }); }, actions: { @@ -125,7 +132,7 @@ export default Controller.extend(copy(DEFAULTS, true), { }, closeTokenModal() { this.toggleProperty('isModalActive'); - this.transitionToRoute('mode.secondaries'); + this.router.transitionTo('vault.cluster.replication.mode.secondaries'); this.set('isTokenCopied', false); }, onCopy() { diff --git a/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js b/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js index 2d0b355232..e33e84f83f 100644 --- a/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js +++ b/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js @@ -9,6 +9,7 @@ import Controller from '@ember/controller'; export default Controller.extend({ flashMessages: service(), + router: service(), rm: service('replication-mode'), replicationMode: alias('rm.mode'), actions: { @@ -29,14 +30,15 @@ export default Controller.extend({ const flash = this.flashMessages; const id = config.id; const redirectArgs = isDelete - ? ['mode.secondaries', this.replicationMode] - : ['mode.secondaries.config-show', id]; + ? ['vault.cluster.replication.mode.secondaries', this.replicationMode] + : ['vault.cluster.replication.mode.secondaries.config-show', id]; const modelMethod = isDelete ? config.destroyRecord : config.save; modelMethod .call(config) .then(() => { - this.transitionToRoute(...redirectArgs) + this.router + .transitionTo(...redirectArgs) .followRedirects() .then(() => { flash.success( diff --git a/ui/lib/replication/addon/controllers/replication-mode.js b/ui/lib/replication/addon/controllers/replication-mode.js index afa6c929ec..a621e68b66 100644 --- a/ui/lib/replication/addon/controllers/replication-mode.js +++ b/ui/lib/replication/addon/controllers/replication-mode.js @@ -9,26 +9,27 @@ import Controller from '@ember/controller'; import { task, timeout } from 'ember-concurrency'; export default Controller.extend({ + router: service(), rm: service('replication-mode'), replicationMode: alias('rm.mode'), waitForNewClusterToInit: task(function* (replicationMode) { // waiting for the newly enabled cluster to init // this ensures we don't hit a capabilities-self error, called in the model of the mode/index route yield timeout(1000); - return this.transitionToRoute('mode', replicationMode); + this.router.transitionTo('vault.cluster.replication.mode', replicationMode); }), actions: { onEnable(replicationMode, mode) { if (replicationMode == 'dr' && mode === 'secondary') { - return this.transitionToRoute('vault.cluster'); + this.router.transitionTo('vault.cluster'); } else if (replicationMode === 'dr') { - return this.transitionToRoute('mode', replicationMode); + this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } else { this.waitForNewClusterToInit.perform(replicationMode); } }, onDisable() { - return this.transitionToRoute('index'); + this.router.transitionTo('vault.cluster.replication.index'); }, }, }); diff --git a/ui/lib/replication/addon/routes/mode.js b/ui/lib/replication/addon/routes/mode.js index 623a1a530e..04bd9ba716 100644 --- a/ui/lib/replication/addon/routes/mode.js +++ b/ui/lib/replication/addon/routes/mode.js @@ -12,11 +12,12 @@ const SUPPORTED_REPLICATION_MODES = ['dr', 'performance']; export default Route.extend({ replicationMode: service(), + router: service(), store: service(), beforeModel() { const replicationMode = this.paramsFor(this.routeName).replication_mode; if (!SUPPORTED_REPLICATION_MODES.includes(replicationMode)) { - return this.transitionTo('index'); + this.router.transitionTo('vault.cluster.replication.index'); } }, model() { diff --git a/ui/lib/replication/addon/routes/mode/index.js b/ui/lib/replication/addon/routes/mode/index.js index 4f408162b6..2e04a5033b 100644 --- a/ui/lib/replication/addon/routes/mode/index.js +++ b/ui/lib/replication/addon/routes/mode/index.js @@ -9,6 +9,7 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; export default Route.extend({ + router: service(), store: service(), model() { const replicationMode = this.paramsFor('mode').replication_mode; @@ -29,14 +30,12 @@ export default Route.extend({ return cluster; }); }, + afterModel(model) { const replicationMode = this.paramsFor('mode').replication_mode; - if ( - !model.get(`${replicationMode}.isPrimary`) || - model.get(`${replicationMode}.replicationDisabled`) || - model.get(`${replicationMode}.replicationUnsupported`) - ) { - return this.transitionTo('mode', replicationMode); + const cluster = model[replicationMode]; + if (!cluster.isPrimary || cluster.replicationDisabled || cluster.replicationUnsupported) { + return this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } }, }); diff --git a/ui/lib/replication/addon/routes/mode/manage.js b/ui/lib/replication/addon/routes/mode/manage.js index 226202d23b..1d2e212576 100644 --- a/ui/lib/replication/addon/routes/mode/manage.js +++ b/ui/lib/replication/addon/routes/mode/manage.js @@ -20,6 +20,7 @@ const pathForAction = (action, replicationMode, clusterMode) => { }; export default Route.extend({ + router: service(), store: service(), model() { const store = this.store; @@ -46,7 +47,7 @@ export default Route.extend({ model.get(replicationMode).get('replicationDisabled') || model.get(replicationMode).get('replicationUnsupported') ) { - return this.transitionTo('mode', replicationMode); + this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } }, }); diff --git a/ui/lib/replication/addon/routes/mode/secondaries.js b/ui/lib/replication/addon/routes/mode/secondaries.js index 4f408162b6..5e352ef9d6 100644 --- a/ui/lib/replication/addon/routes/mode/secondaries.js +++ b/ui/lib/replication/addon/routes/mode/secondaries.js @@ -9,6 +9,7 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; export default Route.extend({ + router: service(), store: service(), model() { const replicationMode = this.paramsFor('mode').replication_mode; @@ -36,7 +37,7 @@ export default Route.extend({ model.get(`${replicationMode}.replicationDisabled`) || model.get(`${replicationMode}.replicationUnsupported`) ) { - return this.transitionTo('mode', replicationMode); + this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } }, }); diff --git a/ui/lib/replication/addon/routes/mode/secondaries/add.js b/ui/lib/replication/addon/routes/mode/secondaries/add.js index 09ccf4c946..23ff704e20 100644 --- a/ui/lib/replication/addon/routes/mode/secondaries/add.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/add.js @@ -13,7 +13,7 @@ export default Base.extend({ redirect(model) { const replicationMode = this.paramsFor('mode').replication_mode; if (!model.get(`${replicationMode}.isPrimary`) || !model.get('canAddSecondary')) { - return this.transitionTo('mode', replicationMode); + return this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } }, diff --git a/ui/lib/replication/addon/routes/mode/secondaries/config-create.js b/ui/lib/replication/addon/routes/mode/secondaries/config-create.js index 6cf57ad52f..4d87effd0a 100644 --- a/ui/lib/replication/addon/routes/mode/secondaries/config-create.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/config-create.js @@ -9,6 +9,7 @@ import Base from '../../replication-base'; export default Base.extend({ flashMessages: service(), + router: service(), modelPath: 'model.config', @@ -48,7 +49,7 @@ export default Base.extend({ !cluster.get(`${replicationMode}.isPrimary`) || !cluster.get('canAddSecondary') ) { - return this.transitionTo('mode', replicationMode); + return this.router.transitionTo('vault.cluster.replication.mode', replicationMode); } }, diff --git a/ui/lib/replication/addon/routes/replication-base.js b/ui/lib/replication/addon/routes/replication-base.js index 30c73b593b..464165349d 100644 --- a/ui/lib/replication/addon/routes/replication-base.js +++ b/ui/lib/replication/addon/routes/replication-base.js @@ -9,6 +9,7 @@ import Route from '@ember/routing/route'; import UnloadModelRouteMixin from 'vault/mixins/unload-model-route'; export default Route.extend(UnloadModelRouteMixin, { + router: service(), store: service(), version: service(), rm: service('replication-mode'), diff --git a/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs b/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs index b7c8850513..5c63d23472 100644 --- a/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs @@ -16,7 +16,7 @@ {{else}} Create config diff --git a/ui/tests/acceptance/enterprise-replication-modes-test.js b/ui/tests/acceptance/enterprise-replication-modes-test.js index c06c7181ac..d4fcfa48bc 100644 --- a/ui/tests/acceptance/enterprise-replication-modes-test.js +++ b/ui/tests/acceptance/enterprise-replication-modes-test.js @@ -6,7 +6,7 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import { setupMirage } from 'ember-cli-mirage/test-support'; -import { click, visit } from '@ember/test-helpers'; +import { click, currentURL, settled, visit } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { STATUS_DISABLED_RESPONSE, mockReplicationBlock } from 'vault/tests/helpers/replication'; @@ -57,6 +57,8 @@ module('Acceptance | Enterprise | replication modes', function (hooks) { assert.dom(s.navLink('Disaster Recovery')).exists('shows dr link'); await click(s.navLink('Performance')); + assert.strictEqual(currentURL(), '/vault/replication/performance', 'it navigates to the correct page'); + await settled(); assert.dom(s.title).hasText('Enable Performance Replication', 'it shows the enable view for performance'); await click(s.navLink('Disaster Recovery')); @@ -80,6 +82,8 @@ module('Acceptance | Enterprise | replication modes', function (hooks) { assert.dom(s.navLink('Disaster Recovery')).exists('shows dr link'); await click(s.navLink('Performance')); + assert.strictEqual(currentURL(), `/vault/replication/performance`, `goes to correct URL`); + await settled(); assert.dom(s.title).hasText(`Performance ${mode}`, `it shows the performance title`); assert.dom(s.dashboard).exists(`it shows the replication dashboard`); @@ -104,6 +108,8 @@ module('Acceptance | Enterprise | replication modes', function (hooks) { assert.dom(s.navLink('Disaster Recovery')).exists('shows dr link'); await click(s.navLink('Performance')); + assert.strictEqual(currentURL(), `/vault/replication/performance`, `goes to correct URL`); + await settled(); assert.dom(s.title).hasText(`Enable Performance Replication`, `it shows the performance title`); assert.dom(s.enableForm).exists('it shows the enable view for performance'); diff --git a/ui/tests/acceptance/enterprise-replication-test.js b/ui/tests/acceptance/enterprise-replication-test.js index a4e2434838..bbb8ed13c4 100644 --- a/ui/tests/acceptance/enterprise-replication-test.js +++ b/ui/tests/acceptance/enterprise-replication-test.js @@ -4,7 +4,17 @@ */ import { clickTrigger } from 'ember-power-select/test-support/helpers'; -import { click, fillIn, findAll, currentURL, find, visit, settled, waitUntil } from '@ember/test-helpers'; +import { + click, + fillIn, + findAll, + currentURL, + find, + visit, + settled, + waitUntil, + waitFor, +} from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import authPage from 'vault/tests/pages/auth'; @@ -249,12 +259,11 @@ module('Acceptance | Enterprise | replication', function (hooks) { await pollCluster(this.owner); await settled(); - const modalDefaultTtl = document.querySelector('[data-test-row-value="TTL"]').innerText; // checks on secondary token modal assert.dom('#replication-copy-token-modal').exists(); assert.dom('[data-test-inline-error-message]').hasText('Copy token to dismiss modal'); - assert.strictEqual(modalDefaultTtl, '1800s', 'shows the correct TTL of 1800s'); + assert.dom('[data-test-row-value="TTL"]').hasText('1800s', 'shows the correct TTL of 1800s'); // click off the modal to make sure you don't just have to click on the copy-close button to copy the token assert.dom('[data-test-modal-close]').isDisabled('cancel is disabled'); await click('[data-test-modal-copy]'); @@ -272,8 +281,7 @@ module('Acceptance | Enterprise | replication', function (hooks) { await pollCluster(this.owner); await settled(); - const modalTtl = document.querySelector('[data-test-row-value="TTL"]').innerText; - assert.strictEqual(modalTtl, '180s', 'shows the correct TTL of 180s'); + assert.dom('[data-test-row-value="TTL"]').hasText('180s', 'shows the correct TTL of 180s'); await click('[data-test-modal-copy]'); await click('[data-test-modal-close]'); @@ -351,13 +359,15 @@ module('Acceptance | Enterprise | replication', function (hooks) { // Click confirm button await click('[data-test-confirm-button="Demote to secondary?"]'); - await click('[data-test-replication-link="details"]'); + await pollCluster(this.owner); + await settled(); + await click('[data-test-replication-link="details"]'); + await waitFor('[data-test-replication-dashboard]'); assert.dom('[data-test-replication-dashboard]').exists(); assert.dom('[data-test-selectable-card-container="secondary"]').exists(); - assert.ok( - find('[data-test-replication-mode-display]').textContent.includes('secondary'), - 'it displays the cluster mode correctly' - ); + assert + .dom('[data-test-replication-mode-display]') + .hasText('secondary', 'it displays the cluster mode correctly in header'); }); });