From 148f2db9413faf87bf5e81d6087cf2f511005dae Mon Sep 17 00:00:00 2001 From: Lisbet Alvarez <107949262+lisbet-alvarez@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:33:06 -0700 Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20remove=20route-actio?= =?UTF-8?q?n=20usage=20for=20auth-methods=20(#2178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 💡 remove route-action usage for auth-methods ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12603 --- .../auth-method/actions/index.hbs | 8 +- .../auth-method/accounts/index.js | 4 +- .../scope/auth-methods/auth-method/index.js | 5 + .../auth-method/managed-groups/index.js | 4 +- .../scopes/scope/auth-methods/index.js | 185 ++++++++++++++- .../scopes/scope/auth-methods/new.js | 4 +- .../app/routes/scopes/scope/auth-methods.js | 158 ------------- .../scopes/scope/auth-methods/auth-method.js | 59 ----- .../auth-method/accounts/index.hbs | 8 +- .../scope/auth-methods/auth-method/index.hbs | 20 +- .../auth-method/managed-groups/index.hbs | 8 +- .../scopes/scope/auth-methods/index.hbs | 4 +- .../scopes/scope/auth-methods/new.hbs | 10 +- .../acceptance/auth-methods/create-test.js | 12 +- .../acceptance/auth-methods/update-test.js | 18 +- .../accounts/account/index-test.js | 2 +- .../accounts/account/set-password-test.js | 2 +- .../auth-method/accounts/index-test.js | 2 +- .../auth-method/accounts/new-test.js | 2 +- .../auth-methods/auth-method/index-test.js | 16 ++ .../scopes/scope/auth-methods/index-test.js | 212 ++++++++++++++++-- .../scopes/scope/auth-methods/new-test.js | 2 +- 22 files changed, 469 insertions(+), 276 deletions(-) create mode 100644 ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/index.js create mode 100644 ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/index-test.js diff --git a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs index 382877ac1..e46d01d75 100644 --- a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs +++ b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs @@ -23,7 +23,7 @@ {{#each @model.options.state as |state|}} @@ -48,14 +48,14 @@ {{#if @model.isPrimary}} {{t 'resources.auth-method.actions.remove-as-primary'}} {{else}} {{t 'resources.auth-method.actions.make-primary'}} @@ -86,7 +86,7 @@ {{t 'resources.auth-method.actions.delete'}} diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/accounts/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/accounts/index.js index 1fb3699ca..3d6906073 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/accounts/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/accounts/index.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import Controller from '@ember/controller'; +import Controller, { inject as controller } from '@ember/controller'; import { action } from '@ember/object'; import { inject as service } from '@ember/service'; import { loading } from 'ember-loading'; @@ -11,6 +11,8 @@ import { confirm } from 'core/decorators/confirm'; import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeAuthMethodsAuthMethodAccountsIndexController extends Controller { + @controller('scopes/scope/auth-methods/index') authMethods; + // =services @service can; diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/index.js new file mode 100644 index 000000000..fedcfdfbb --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/index.js @@ -0,0 +1,5 @@ +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeAuthMethodsAuthMethodIndexController extends Controller { + @controller('scopes/scope/auth-methods/index') authMethods; +} diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/managed-groups/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/managed-groups/index.js index 3274e64d6..d24597e4f 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/managed-groups/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method/managed-groups/index.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import Controller from '@ember/controller'; +import Controller, { inject as controller } from '@ember/controller'; import { action } from '@ember/object'; import { inject as service } from '@ember/service'; import { loading } from 'ember-loading'; @@ -11,6 +11,8 @@ import { confirm } from 'core/decorators/confirm'; import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsIndexController extends Controller { + @controller('scopes/scope/auth-methods/index') authMethods; + // =services @service can; diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js index 45e0cc1b3..e81aae706 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js @@ -5,14 +5,19 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; -import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; +import { loading } from 'ember-loading'; +import { confirm } from 'core/decorators/confirm'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; +import { tracked } from '@glimmer/tracking'; import { debounce } from 'core/decorators/debounce'; import { TYPES_AUTH_METHOD } from 'api/models/auth-method'; export default class ScopesScopeAuthMethodsIndexController extends Controller { // =services + @service router; + @service can; @service intl; // =attributes @@ -92,6 +97,111 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { this.page = 1; } + /** + * Rollback changes to an auth-method. + * @param {AuthMethodModel} authMethod + */ + @action + cancel(authMethod) { + const { isNew } = authMethod; + authMethod.rollbackAttributes(); + if (isNew) this.router.transitionTo('scopes.scope.auth-methods'); + } + + /** + * Save an auth-method in current scope. + * @param {AuthMethodModel} authMethod + */ + @action + @loading + @notifyError(({ message }) => message) + @notifySuccess(({ isNew }) => + isNew ? 'notifications.create-success' : 'notifications.save-success', + ) + async save(authMethod) { + await authMethod.save(); + if (this.can.can('read model', authMethod)) { + await this.router.transitionTo( + 'scopes.scope.auth-methods.auth-method', + authMethod, + ); + } else { + await this.router.transitionTo('scopes.scope.auth-methods'); + } + await this.router.refresh(); + } + + /** + * Delete an auth method in current scope and redirect to index + * @param {AuthMethodModel} authMethod + */ + @action + @loading + @confirm('questions.delete-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.delete-success') + async delete(authMethod) { + await authMethod.destroyRecord(); + // Reload the scope, since this is where the primary_auth_method_id is + // stored. An auth method deletion could affect this field. + await this.scopeModel.reload(); + this.router.replaceWith('scopes.scope.auth-methods'); + await this.router.refresh(); + } + + /** + * Elects the specified auth method to primary for the current scope. + * @param {AuthMethodModel} authMethod + * @param {string} authMethod.id + */ + @action + @loading + @confirm('resources.auth-method.questions.make-primary-confirm', { + title: 'resources.auth-method.questions.make-primary', + }) + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('resources.auth-method.notifications.make-primary-success') + async makePrimary({ id }) { + this.scopeModel.primary_auth_method_id = id; + // Attempt to save the change to the scope. If this operation fails, + // we rollback the change and rethrow the error so the user can be notified. + try { + await this.scopeModel.save(); + } catch (e) { + this.scopeModel.rollbackAttributes(); + throw e; + } + await this.router.refresh(); + } + + /** + * Sets the `primary_auth_method_id` field to null for the current scope + * and saves it if and only if the specified auth method is in fact primary + * for the current scope. + * @param {AuthMethodModel} authMethod + */ + @action + @loading + @confirm('resources.auth-method.questions.remove-as-primary-confirm', { + title: 'resources.auth-method.questions.remove-as-primary', + }) + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess( + 'resources.auth-method.notifications.remove-as-primary-success', + ) + async removeAsPrimary(authMethod) { + this.scopeModel.primary_auth_method_id = null; + // Attempt to save the change to the scope. If this operation fails, + // we rollback the change and rethrow the error so the user can be notified. + try { + await this.scopeModel.save(); + } catch (e) { + this.scopeModel.rollbackAttributes(); + throw e; + } + await authMethod.reload(); + } + /** * Removes an item from array `property` at `index` on the * passed `authMethod`. This is used to manage entries in fragment array @@ -101,7 +211,7 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { * @param {number} index */ @action - async removeItemByIndex(authMethod, property, index) { + removeItemByIndex(authMethod, property, index) { const array = authMethod.get(property).filter((item, i) => i !== index); authMethod.set(property, array); } @@ -115,9 +225,78 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { * @param {string} value */ @action - async addStringItem(authMethod, property, value) { + addStringItem(authMethod, property, value) { const existingArray = authMethod[property] ?? []; const array = [...existingArray, { value }]; authMethod.set(property, array); } + + /** + * Adds an account map fragment to the passed `authMethod`. + * @param {AuthMethodModel} authMethod + * @param {string} field + * @param {string} from + * @param {string} to + */ + @action + addAccountMapItem(authMethod, field, from, to) { + const existingArray = authMethod[field] ?? []; + const array = [...existingArray, { from, to }]; + authMethod.set(field, array); + } + + /** + * Copies the contents of string array fields in order to force the instance + * into a dirty state. This ensures that `model.rollbackAttributes()` reverts + * to the original expected array. + * + * The deep copy implemented here is required to ensure that both the + * array itself and its members are all new. + * + * @param {authMethodModel} authMethod + */ + @action + edit(authMethod) { + if (authMethod.claims_scopes) { + authMethod.claims_scopes = structuredClone(authMethod.claims_scopes); + } + if (authMethod.signing_algorithms) { + authMethod.signing_algorithms = structuredClone( + authMethod.signing_algorithms, + ); + } + if (authMethod.allowed_audiences) { + authMethod.allowed_audiences = structuredClone( + authMethod.allowed_audiences, + ); + } + if (authMethod.idp_ca_certs) { + authMethod.idp_ca_certs = structuredClone(authMethod.idp_ca_certs); + } + if (authMethod.account_claim_maps) { + authMethod.account_claim_maps = structuredClone( + authMethod.account_claim_maps, + ); + } + if (authMethod.certificates) { + authMethod.certificates = structuredClone(authMethod.certificates); + } + if (authMethod.account_attribute_maps) { + authMethod.account_attribute_maps = structuredClone( + authMethod.account_attribute_maps, + ); + } + } + + /** + * Update state of OIDC or LDAP auth method + * @param {string} state + * @param {authMethodModel} authMethod + */ + @action + @notifyError(({ message }) => message) + @notifySuccess('notifications.save-success') + async changeState(authMethod, state) { + await authMethod.changeState(state); + } } diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/new.js b/ui/admin/app/controllers/scopes/scope/auth-methods/new.js index bdc0330cf..7b3ed7308 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/new.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/new.js @@ -3,9 +3,11 @@ * SPDX-License-Identifier: MPL-2.0 */ -import Controller from '@ember/controller'; +import Controller, { inject as controller } from '@ember/controller'; export default class ScopesScopeAuthMethodsNewController extends Controller { + @controller('scopes/scope/auth-methods/index') authMethods; + // =services // =attributes diff --git a/ui/admin/app/routes/scopes/scope/auth-methods.js b/ui/admin/app/routes/scopes/scope/auth-methods.js index a3785bcf2..f7d139627 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods.js @@ -5,16 +5,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; -import { loading } from 'ember-loading'; -import { confirm } from 'core/decorators/confirm'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeAuthMethodsRoute extends Route { // =services @service session; - @service can; @service router; // =methods @@ -25,157 +20,4 @@ export default class ScopesScopeAuthMethodsRoute extends Route { beforeModel() { if (!this.session.isAuthenticated) this.router.transitionTo('index'); } - - // =actions - - /** - * Rollback changes to an auth-method. - * @param {AuthMethodModel} authMethod - */ - @action - cancel(authMethod) { - const { isNew } = authMethod; - authMethod.rollbackAttributes(); - if (isNew) this.router.transitionTo('scopes.scope.auth-methods'); - } - - /** - * Save an auth-method in current scope. - * @param {AuthMethodModel} authMethod - */ - @action - @loading - @notifyError(({ message }) => message) - @notifySuccess(({ isNew }) => - isNew ? 'notifications.create-success' : 'notifications.save-success', - ) - async save(authMethod) { - await authMethod.save(); - if (this.can.can('read model', authMethod)) { - await this.router.transitionTo( - 'scopes.scope.auth-methods.auth-method', - authMethod, - ); - } else { - await this.router.transitionTo('scopes.scope.auth-methods'); - } - this.refresh(); - } - - /** - * Delete an auth method in current scope and redirect to index - * @param {AuthMethodModel} authMethod - */ - @action - @loading - @confirm('questions.delete-confirm') - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('notifications.delete-success') - async delete(authMethod) { - const scopeModel = this.modelFor('scopes.scope'); - await authMethod.destroyRecord(); - // Reload the scope, since this is where the primary_auth_method_id is - // stored. An auth method deletion could affect this field. - await scopeModel.reload(); - this.router.replaceWith('scopes.scope.auth-methods'); - this.refresh(); - } - - /** - * Elects the specified auth method to primary for the current scope. - * @param {AuthMethodModel} authMethod - * @param {string} authMethod.id - */ - @action - @loading - @confirm('resources.auth-method.questions.make-primary-confirm', { - title: 'resources.auth-method.questions.make-primary', - }) - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess('resources.auth-method.notifications.make-primary-success') - async makePrimary({ id }) { - const scopeModel = this.modelFor('scopes.scope'); - scopeModel.primary_auth_method_id = id; - // Attempt to save the change to the scope. If this operation fails, - // we rollback the change and rethrow the error so the user can be notified. - try { - await scopeModel.save(); - } catch (e) { - scopeModel.rollbackAttributes(); - throw e; - } - await this.refresh(); - } - - /** - * Sets the `primary_auth_method_id` field to null for the current scope - * and saves it if and only if the specified auth method is in fact primary - * for the current scope. - * @param {AuthMethodModel} authMethod - */ - @action - @loading - @confirm('resources.auth-method.questions.remove-as-primary-confirm', { - title: 'resources.auth-method.questions.remove-as-primary', - }) - @notifyError(({ message }) => message, { catch: true }) - @notifySuccess( - 'resources.auth-method.notifications.remove-as-primary-success', - ) - async removeAsPrimary(authMethod) { - const scopeModel = this.modelFor('scopes.scope'); - scopeModel.primary_auth_method_id = null; - // Attempt to save the change to the scope. If this operation fails, - // we rollback the change and rethrow the error so the user can be notified. - try { - await scopeModel.save(); - } catch (e) { - scopeModel.rollbackAttributes(); - throw e; - } - await authMethod.reload(); - } - - /** - * Removes an item from array `property` at `index` on the - * passed `authMethod`. This is used to manage entries in fragment array - * fields such as `signing_algorithms`. - * @param {AuthMethodModel} authMethod - * @param {string} property - * @param {number} index - */ - @action - async removeItemByIndex(authMethod, property, index) { - const array = authMethod.get(property).filter((item, i) => i !== index); - authMethod.set(property, array); - } - - /** - * Adds a string item to array `property` on the passed `authMethod`. - * This is used to manage entries in fragment OIDC string array fields such - * as `signing_algorithms`. - * @param {AuthMethodModel} authMethod - * @param {string} property - * @param {string} value - */ - @action - async addStringItem(authMethod, property, value) { - const existingArray = authMethod[property] ?? []; - const array = [...existingArray, { value }]; - authMethod.set(property, array); - } - - /** - * Adds an account map fragment to the passed `authMethod`. - * @param {AuthMethodModel} authMethod - * @param {string} field - * @param {string} from - * @param {string} to - */ - @action - async addAccountMapItem(authMethod, field, from, to) { - const existingArray = authMethod[field] ?? []; - const array = [...existingArray, { from, to }]; - authMethod.set(field, array); - } } diff --git a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js index 252e54721..76c9b751a 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js @@ -4,8 +4,6 @@ */ import Route from '@ember/routing/route'; -import { action } from '@ember/object'; -import { notifySuccess, notifyError } from 'core/decorators/notify'; import { inject as service } from '@ember/service'; import { paramValueFinder } from 'admin/utils/param-value-finder'; @@ -47,61 +45,4 @@ export default class ScopesScopeAuthMethodsAuthMethodRoute extends Route { ); } } - - // =actions - - /** - * Copies the contents of string array fields in order to force the instance - * into a dirty state. This ensures that `model.rollbackAttributes()` reverts - * to the original expected array. - * - * The deep copy implemented here is required to ensure that both the - * array itself and its members are all new. - * - * @param {authMethodModel} authMethod - */ - @action - edit(authMethod) { - if (authMethod.claims_scopes) { - authMethod.claims_scopes = structuredClone(authMethod.claims_scopes); - } - if (authMethod.signing_algorithms) { - authMethod.signing_algorithms = structuredClone( - authMethod.signing_algorithms, - ); - } - if (authMethod.allowed_audiences) { - authMethod.allowed_audiences = structuredClone( - authMethod.allowed_audiences, - ); - } - if (authMethod.idp_ca_certs) { - authMethod.idp_ca_certs = structuredClone(authMethod.idp_ca_certs); - } - if (authMethod.account_claim_maps) { - authMethod.account_claim_maps = structuredClone( - authMethod.account_claim_maps, - ); - } - if (authMethod.certificates) { - authMethod.certificates = structuredClone(authMethod.certificates); - } - if (authMethod.account_attribute_maps) { - authMethod.account_attribute_maps = structuredClone( - authMethod.account_attribute_maps, - ); - } - } - - /** - * Update state of OIDC or LDAP auth method - * @param {string} state - */ - @action - @notifyError(({ message }) => message) - @notifySuccess('notifications.save-success') - async changeState(state) { - const model = this.modelFor('scopes.scope.auth-methods.auth-method'); - await model.changeState(state); - } } diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index ad2e2e494..37d36c0b7 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -18,7 +18,13 @@ - + diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/index.hbs index 064a674ab..1b0027f92 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/index.hbs @@ -18,18 +18,24 @@ - + diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/managed-groups/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/managed-groups/index.hbs index 8c343829c..6042475e4 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/managed-groups/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/managed-groups/index.hbs @@ -18,7 +18,13 @@ - + diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs index 011003503..64b46e0db 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs @@ -149,7 +149,7 @@ {{/unless}} {{#if B.data.isPrimary}} @@ -157,7 +157,7 @@ @text={{t 'resources.auth-method.actions.remove-as-primary' }} - {{on 'click' (route-action 'removeAsPrimary' B.data)}} + {{on 'click' (fn this.removeAsPrimary B.data)}} /> {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/new.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/new.hbs index 4e5597192..114a9129d 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/new.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/new.hbs @@ -25,11 +25,11 @@ \ No newline at end of file diff --git a/ui/admin/tests/acceptance/auth-methods/create-test.js b/ui/admin/tests/acceptance/auth-methods/create-test.js index c22a998de..77fbba0b1 100644 --- a/ui/admin/tests/acceptance/auth-methods/create-test.js +++ b/ui/admin/tests/acceptance/auth-methods/create-test.js @@ -324,8 +324,11 @@ module('Acceptance | auth-methods | create', function (hooks) { instances.orgScope.primaryAuthMethodId, 'Primary auth method is not yet set.', ); - await visit(urls.authMethod); + await visit(urls.authMethods); + + await click(`[href="${urls.authMethod}"]`); await click(MAKE_PRIMARY_SELECTOR); + const scope = this.server.schema.scopes.find(instances.orgScope.id); assert.strictEqual( scope.primaryAuthMethodId, @@ -363,7 +366,9 @@ module('Acceptance | auth-methods | create', function (hooks) { instances.orgScope.primaryAuthMethodId, 'Primary auth method is set.', ); - await visit(urls.authMethod); + await visit(urls.authMethods); + + await click(`[href="${urls.authMethod}"]`); await click(MAKE_PRIMARY_SELECTOR); const scope = this.server.schema.scopes.find(instances.orgScope.id); assert.notOk(scope.primaryAuthMethodId, 'Primary auth method is unset.'); @@ -389,8 +394,9 @@ module('Acceptance | auth-methods | create', function (hooks) { instances.orgScope.primaryAuthMethodId, instances.authMethod.id, ); + await visit(urls.authMethods); - await visit(urls.authMethod); + await click(`[href="${urls.authMethod}"]`); await click(MAKE_PRIMARY_SELECTOR); assert.dom(ERROR_MSG_SELECTOR).hasText('Sorry!'); diff --git a/ui/admin/tests/acceptance/auth-methods/update-test.js b/ui/admin/tests/acceptance/auth-methods/update-test.js index 964dbbe47..a8ec06188 100644 --- a/ui/admin/tests/acceptance/auth-methods/update-test.js +++ b/ui/admin/tests/acceptance/auth-methods/update-test.js @@ -163,11 +163,12 @@ module('Acceptance | auth-methods | update', function (hooks) { await click(CLAIMS_SCOPES_BTN_SELECTOR, 'allowed_audiences'); // Remove all claim maps - await Promise.all( - findAll('form fieldset:nth-of-type(4) [title="Remove"]').map((element) => - click(element), - ), + const claimMaps = await Promise.all( + findAll('form fieldset:nth-of-type(4) [title="Remove"]'), ); + for (const element of claimMaps) { + await click(element); + } await fillIn('[name="from_claim"]', 'from_claim'); await select('form fieldset:nth-of-type(4) select', 'email'); await click('form fieldset:nth-of-type(4) [title="Add"]'); @@ -235,11 +236,12 @@ module('Acceptance | auth-methods | update', function (hooks) { await fillIn('[name="user_attr"]', 'user attr'); await fillIn('[name="user_filter"]', 'user filter'); // Remove all attribute maps - await Promise.all( - findAll( - '[name="account_attribute_maps"] .hds-button--color-critical', - ).map((element) => click(element)), + const attributeMaps = await Promise.all( + findAll('[name="account_attribute_maps"] .hds-button--color-critical'), ); + for (const element of attributeMaps) { + await click(element); + } await fillIn('[name="account_attribute_maps"] input', 'attribute'); await select('[name="account_attribute_maps"] select', 'email'); await click('[name="account_attribute_maps"] button'); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/index-test.js index 1e19f3038..4a258bb51 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/index-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/index-test.js @@ -4,7 +4,7 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; module( 'Unit | Controller | scopes/scope/auth-methods/auth-method/accounts/account/index', diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js index a263ae3cf..473bc1f95 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/account/set-password-test.js @@ -4,7 +4,7 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; module( 'Unit | Controller | scopes/scope/auth-methods/auth-method/accounts/account/set-password', diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/index-test.js index cdd2b45e3..188e88e4c 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/index-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/index-test.js @@ -4,7 +4,7 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; module( 'Unit | Controller | scopes/scope/auth-methods/auth-method/accounts/index', diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/new-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/new-test.js index 8e7e33a51..0da385a0d 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/new-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/accounts/new-test.js @@ -4,7 +4,7 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; module( 'Unit | Controller | scopes/scope/auth-methods/auth-method/accounts/new', diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/index-test.js new file mode 100644 index 000000000..d8572130d --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/auth-method/index-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module( + 'Unit | Controller | scopes/scope/auth-methods/auth-method/index', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/auth-methods/auth-method/index', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/index-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/index-test.js index 9276cc3d9..dfaae2247 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/index-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/index-test.js @@ -6,6 +6,10 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; import { waitUntil } from '@ember/test-helpers'; +import { visit } from '@ember/test-helpers'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { setupIndexedDb } from 'api/test-support/helpers/indexed-db'; +import { authenticateSession } from 'ember-simple-auth/test-support'; import { TYPE_AUTH_METHOD_PASSWORD, TYPE_AUTH_METHOD_OIDC, @@ -14,18 +18,41 @@ import { module('Unit | Controller | scopes/scope/auth-methods/index', function (hooks) { setupTest(hooks); + setupMirage(hooks); + setupIndexedDb(hooks); - test('it exists', function (assert) { - let controller = this.owner.lookup( + let store; + let controller; + let getAuthMethodCount; + + const instances = { + scope: { + global: null, + }, + authMethod: null, + }; + + hooks.beforeEach(async function () { + authenticateSession({}); + store = this.owner.lookup('service:store'); + controller = this.owner.lookup( 'controller:scopes/scope/auth-methods/index', ); + + instances.scope.global = this.server.create('scope', { id: 'global' }); + instances.authMethod = this.server.create('auth-method', { + scopeId: 'global', + }); + + getAuthMethodCount = () => + this.server.schema.authMethods.all().models.length; + }); + + test('controller exists', function (assert) { assert.ok(controller); }); test('primaryOptions returns expected object', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/auth-methods/index', - ); assert.deepEqual(controller.primaryOptions, [ { id: 'true', name: 'Yes' }, { id: 'false', name: 'No' }, @@ -33,9 +60,6 @@ module('Unit | Controller | scopes/scope/auth-methods/index', function (hooks) { }); test('authMethodTypeOptions returns expected object', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/auth-methods/index', - ); assert.deepEqual(controller.authMethodTypeOptions, [ { id: TYPE_AUTH_METHOD_PASSWORD, name: 'Password' }, { id: TYPE_AUTH_METHOD_OIDC, name: 'OIDC' }, @@ -44,17 +68,11 @@ module('Unit | Controller | scopes/scope/auth-methods/index', function (hooks) { }); test('filters returns expected entries', function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/auth-methods/index', - ); assert.ok(controller.filters.allFilters); assert.ok(controller.filters.selectedFilters); }); test('handleSearchInput action sets expected values correctly', async function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/auth-methods/index', - ); const searchValue = 'test'; controller.handleSearchInput({ target: { value: searchValue } }); await waitUntil(() => controller.search === searchValue); @@ -64,13 +82,173 @@ module('Unit | Controller | scopes/scope/auth-methods/index', function (hooks) { }); test('applyFilter action sets expected values correctly', async function (assert) { - let controller = this.owner.lookup( - 'controller:scopes/scope/auth-methods/index', - ); const selectedItems = ['true']; controller.applyFilter('primary', selectedItems); assert.strictEqual(controller.page, 1); assert.deepEqual(controller.primary, selectedItems); }); + + test('cancel action rolls-back changes on the specified model', async function (assert) { + await visit('/scopes/global/auth-methods'); + const authMethodModelBefore = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + authMethodModelBefore.name = 'test'; + + assert.strictEqual(authMethodModelBefore.name, 'test'); + + await controller.cancel(authMethodModelBefore); + const authMethodModelAfter = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + assert.notEqual(authMethodModelAfter.name, 'test'); + assert.strictEqual(authMethodModelAfter.name, authMethodModelBefore.name); + }); + + test('save action saves changes on the specified model', async function (assert) { + await visit('/scopes/global/auth-methods'); + const authMethodModelBefore = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + authMethodModelBefore.name = 'test'; + + await controller.save(authMethodModelBefore); + const authMethodModelAfter = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + assert.strictEqual(authMethodModelAfter.name, 'test'); + }); + + test('delete action destroys specified model', async function (assert) { + await visit('/scopes/global/scopes'); + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + const authMethodCount = getAuthMethodCount(); + + await controller.delete(authMethodModel); + + assert.strictEqual(getAuthMethodCount(), authMethodCount - 1); + }); + + test('makePrimary action updates scope with auth-method id', async function (assert) { + await visit('/scopes/global/auth-methods'); + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + await controller.makePrimary(authMethodModel); + const scopeModel = await store.findRecord( + 'scope', + instances.scope.global.id, + ); + + assert.strictEqual( + scopeModel.primary_auth_method_id, + instances.authMethod.id, + ); + }); + + test('removeAsPrimary action updates scope with null as auth-method id', async function (assert) { + await visit('/scopes/global/auth-methods'); + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + await controller.removeAsPrimary(authMethodModel); + const scopeModel = await store.findRecord( + 'scope', + instances.scope.global.id, + ); + + assert.notOk(scopeModel.primary_auth_method_id); + }); + + test('addStringItem action adds item to field and removeItemByIndex removes correct item', async function (assert) { + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + controller.addStringItem(authMethodModel, 'certificates', 'cert_123'); + + assert.deepEqual(authMethodModel.certificates, [{ value: 'cert_123' }]); + + controller.addStringItem(authMethodModel, 'certificates', 'cert_456'); + controller.removeItemByIndex(authMethodModel, 'certificates', 0); + + assert.deepEqual(authMethodModel.certificates, [{ value: 'cert_456' }]); + }); + + test('addAccountMapItem action adds item to field and removeItemByIndex removes correct item', async function (assert) { + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + controller.addAccountMapItem( + authMethodModel, + 'account_attribute_maps', + 'name123', + 'fullName', + ); + + assert.deepEqual(authMethodModel.account_attribute_maps, [ + { from: 'name123', to: 'fullName' }, + ]); + + controller.addAccountMapItem( + authMethodModel, + 'account_attribute_maps', + 'name456', + 'fullName', + ); + controller.removeItemByIndex(authMethodModel, 'account_attribute_maps', 0); + + assert.deepEqual(authMethodModel.account_attribute_maps, [ + { from: 'name456', to: 'fullName' }, + ]); + }); + + test('edit action updates to a dirty state', async function (assert) { + const authMethodModel = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + assert.false(authMethodModel.hasDirtyAttributes); + + controller.edit(authMethodModel); + + assert.true(authMethodModel.hasDirtyAttributes); + }); + + test('changeState action updates state of auth-method', async function (assert) { + instances.authMethod.update({ type: TYPE_AUTH_METHOD_LDAP }); + const authMethodModelBefore = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + assert.notOk(authMethodModelBefore.state); + + await controller.changeState(authMethodModelBefore, 'public'); + + const authMethodModelAfter = await store.findRecord( + 'auth-method', + instances.authMethod.id, + ); + + assert.strictEqual(authMethodModelAfter.state, 'public'); + }); }); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/new-test.js b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/new-test.js index e399fc1b3..4fbac6fc1 100644 --- a/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/new-test.js +++ b/ui/admin/tests/unit/controllers/scopes/scope/auth-methods/new-test.js @@ -4,7 +4,7 @@ */ import { module, test } from 'qunit'; -import { setupTest } from 'admin/tests/helpers'; +import { setupTest } from 'ember-qunit'; module('Unit | Controller | scopes/scope/auth-methods/new', function (hooks) { setupTest(hooks);