From 9d342cf517f8f5fb430b2100dfa35447a3e02ad3 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Tue, 27 Jul 2021 11:22:06 -0400 Subject: [PATCH] feat: Remove a credential library associated to a target --- .../targets/target/credential-libraries.js | 41 +++++--- .../targets/target/credential-libraries.hbs | 23 +++++ .../credential-library-test.js | 2 +- .../targets/credential-libraries-test.js | 98 +++++++++++++++++++ 4 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 ui/admin/tests/acceptance/targets/credential-libraries-test.js diff --git a/ui/admin/app/routes/scopes/scope/targets/target/credential-libraries.js b/ui/admin/app/routes/scopes/scope/targets/target/credential-libraries.js index 17e3e2692..66ce6f8ec 100644 --- a/ui/admin/app/routes/scopes/scope/targets/target/credential-libraries.js +++ b/ui/admin/app/routes/scopes/scope/targets/target/credential-libraries.js @@ -1,5 +1,9 @@ import Route from '@ember/routing/route'; -import { hash, all } from 'rsvp'; +import { all } from 'rsvp'; +import { action } from '@ember/object'; +import loading from 'ember-loading/decorator'; +import { confirm } from 'core/decorators/confirm'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeTargetsTargetCredentialLibrariesRoute extends Route { // =methods @@ -11,17 +15,13 @@ export default class ScopesScopeTargetsTargetCredentialLibrariesRoute extends Ro beforeModel() { const { application_credential_library_ids: credential_libraries } = this.modelFor('scopes.scope.targets.target'); - return hash({ - credentialLibraries: all( - credential_libraries.map((credential_library) => - this.store.findRecord( - 'credential-library', - credential_library.value, - { reload: true } - ) - ) - ), - }); + return all( + credential_libraries.map((credential_library) => + this.store.findRecord('credential-library', credential_library.value, { + reload: true, + }) + ) + ); } /** @@ -31,4 +31,21 @@ export default class ScopesScopeTargetsTargetCredentialLibrariesRoute extends Ro model() { return this.modelFor('scopes.scope.targets.target'); } + + // =actions + + /** + * Remove a credential library from the current target. + * @param {TargetModel} target + * @param {CredentialLibraryModel} credentialLibrary + */ + @action + @loading + @confirm('questions.remove-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('notifications.remove-success') + async removeCredentialLibrary(target, credentialLibrary) { + await target.removeCredentialLibrary(credentialLibrary.id); + this.refresh(); + } } diff --git a/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs b/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs index ebba89bff..9e7a24657 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs @@ -7,6 +7,7 @@ {{t 'form.name.label'}} {{t 'form.id.label'}} + {{t 'titles.actions'}} @@ -33,6 +34,28 @@ {{credentialLibrary.id}} + + + + {{t 'actions.remove'}} + + + {{/each}} diff --git a/ui/admin/tests/acceptance/credential-library/credential-library-test.js b/ui/admin/tests/acceptance/credential-library/credential-library-test.js index ea3568c45..0ca994ee1 100644 --- a/ui/admin/tests/acceptance/credential-library/credential-library-test.js +++ b/ui/admin/tests/acceptance/credential-library/credential-library-test.js @@ -58,7 +58,7 @@ module('Acceptance | credential-library', function (hooks) { urls.credentialLibraries = `${urls.credentialStore}/credential-libraries`; urls.credentialLibrary = `${urls.credentialLibraries}/${instances.credentialLibrary.id}`; urls.newCredentialLibrary = `${urls.credentialLibraries}/new`; - // Generate resource couner + // Generate resource counter getCredentialLibraryCount = () => this.server.schema.credentialLibraries.all().models.length; authenticateSession({}); diff --git a/ui/admin/tests/acceptance/targets/credential-libraries-test.js b/ui/admin/tests/acceptance/targets/credential-libraries-test.js new file mode 100644 index 000000000..b8e2d5233 --- /dev/null +++ b/ui/admin/tests/acceptance/targets/credential-libraries-test.js @@ -0,0 +1,98 @@ +import { module, test } from 'qunit'; +import { visit, find, findAll, click } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { Response } from 'miragejs'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | targets | credential-libraries', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let getCredentialLibraryCount; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + credentialLibraries: null, + }; + const urls = { + globalScope: null, + orgScope: null, + projectScope: null, + targets: null, + target: null, + targetCredentialLibraries: null, + }; + + hooks.beforeEach(function () { + // Generate resources + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.credentialLibraries = this.server.createList( + 'credential-library', + 2, + { scope: instances.scopes.project } + ); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + credentialLibraries: instances.credentialLibraries, + }); + // Generate route URLs for resources + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.targets = `/scopes/${instances.scopes.project.id}/targets`; + urls.target = `${urls.targets}/${instances.target.id}`; + urls.targetCredentialLibraries = `${urls.target}/credential-libraries`; + // Generate resource counter + getCredentialLibraryCount = () => + this.server.schema.credentialLibraries.all().models.length; + authenticateSession({}); + }); + + test('can remove a credential library', async function (assert) { + assert.expect(2); + const count = getCredentialLibraryCount(); + await visit(urls.targetCredentialLibraries); + assert.equal(findAll('tbody tr').length, count); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, count - 1); + }); + + test('removing a target credential library which errors displays error messages', async function (assert) { + assert.expect(2); + this.server.post('/targets/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + const count = getCredentialLibraryCount(); + await visit(urls.targetCredentialLibraries); + assert.equal(findAll('tbody tr').length, count); + await click('tbody tr .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]')); + }); +});