diff --git a/ui/admin/app/templates/scopes/scope/roles/role/scopes.hbs b/ui/admin/app/templates/scopes/scope/roles/role/scopes.hbs index 4684c7bea..911e8c718 100644 --- a/ui/admin/app/templates/scopes/scope/roles/role/scopes.hbs +++ b/ui/admin/app/templates/scopes/scope/roles/role/scopes.hbs @@ -45,36 +45,38 @@ {{#if @model.role.grant_scope_ids}} - - - {{#if @model.role.scope.isGlobal}} - - - - - - - {{/if}} - + {{#unless @model.role.scope.isProject}} + + + {{#if @model.role.scope.isGlobal}} + + + + + + + {{/if}} + + {{/unless}} {{#if @model.role.scope.isGlobal}} @@ -89,7 +91,7 @@ (hash label=(t 'resources.role.scope.titles.parent_scope')) (hash label=(t 'resources.role.scope.titles.resource_type')) }} - @valin='middle' + @valign='middle' > <:body as |B|> @@ -178,12 +180,14 @@ - + {{#unless @model.role.scope.isProject}} + + {{/unless}} {{else}} diff --git a/ui/admin/tests/acceptance/roles/global-scope-test.js b/ui/admin/tests/acceptance/roles/global-scope-test.js index c63370f48..a05d829ce 100644 --- a/ui/admin/tests/acceptance/roles/global-scope-test.js +++ b/ui/admin/tests/acceptance/roles/global-scope-test.js @@ -54,6 +54,7 @@ module('Acceptance | roles | global-scope', function (hooks) { '.role-grant-scopes div div:nth-child(3) a'; const BUTTON_ICON_SELECTOR = '.hds-button__icon [data-test-icon="check-circle"]'; + const PAGINATION_SELECTOR = '.hds-pagination'; const instances = { scopes: { @@ -110,7 +111,7 @@ module('Acceptance | roles | global-scope', function (hooks) { .exists({ count: instances.role.grant_scope_ids.length }); }); - test('user can naviage to scope from role grant scopes', async function (assert) { + test('user can navigate to scope from role grant scopes', async function (assert) { await visit(urls.role); await click(`[href="${urls.roleScopes}"]`); @@ -141,6 +142,7 @@ module('Acceptance | roles | global-scope', function (hooks) { .length === 0, ); + assert.dom(PAGINATION_SELECTOR).exists(); assert .dom(GRANT_SCOPE_ROW_SELECTOR(instances.role.grant_scope_ids[0])) .exists(); @@ -221,7 +223,7 @@ module('Acceptance | roles | global-scope', function (hooks) { .exists(); }); - test('user can naviage to parent scope from role grant scopes', async function (assert) { + test('user can navigate to parent scope from role grant scopes', async function (assert) { instances.role.update({ grant_scope_ids: ['this', instances.scopes.org.id], }); @@ -430,7 +432,7 @@ module('Acceptance | roles | global-scope', function (hooks) { assert.dom(TOAST_SELECTOR).isVisible(); }); - test('user can search for a specifc org scope by id on manage custom scopes page', async function (assert) { + test('user can search for a specific org scope by id on manage custom scopes page', async function (assert) { const anotherOrg = this.server.create('scope', { type: 'org', scope: { id: 'global', type: 'global' }, @@ -589,7 +591,7 @@ module('Acceptance | roles | global-scope', function (hooks) { assert.dom(TOAST_SELECTOR).isVisible(); }); - test('user can search for a specifc project scope by id on manage org projects page', async function (assert) { + test('user can search for a specific project scope by id on manage org projects page', async function (assert) { const anotherProject = this.server.create('scope', { type: 'project', scope: { id: instances.scopes.org.id, type: 'org' }, diff --git a/ui/admin/tests/acceptance/roles/org-scope-test.js b/ui/admin/tests/acceptance/roles/org-scope-test.js index 98fc49bd6..451dafc8d 100644 --- a/ui/admin/tests/acceptance/roles/org-scope-test.js +++ b/ui/admin/tests/acceptance/roles/org-scope-test.js @@ -51,6 +51,7 @@ module('Acceptance | roles | org-scope', function (hooks) { '.role-grant-scopes div div:nth-child(3) a'; const BUTTON_ICON_SELECTOR = '.hds-button__icon [data-test-icon="check-circle"]'; + const PAGINATION_SELECTOR = '.hds-pagination'; const instances = { scopes: { @@ -107,7 +108,7 @@ module('Acceptance | roles | org-scope', function (hooks) { .exists({ count: instances.role.grant_scope_ids.length }); }); - test('user can naviage to scope from role grant scopes', async function (assert) { + test('user can navigate to scope from role grant scopes', async function (assert) { await visit(urls.role); await click(`[href="${urls.roleScopes}"]`); @@ -119,7 +120,7 @@ module('Acceptance | roles | org-scope', function (hooks) { ); }); - test('user can naviage to parent scope from role grant scopes', async function (assert) { + test('user can navigate to parent scope from role grant scopes', async function (assert) { await visit(urls.role); await click(`[href="${urls.roleScopes}"]`); @@ -150,6 +151,7 @@ module('Acceptance | roles | org-scope', function (hooks) { .length === 0, ); + assert.dom(PAGINATION_SELECTOR).exists(); assert .dom(GRANT_SCOPE_ROW_SELECTOR(instances.role.grant_scope_ids[0])) .exists(); @@ -392,7 +394,7 @@ module('Acceptance | roles | org-scope', function (hooks) { assert.dom(TOAST_SELECTOR).isVisible(); }); - test('user can search for a specifc project scope by id on manage org projects page', async function (assert) { + test('user can search for a specific project scope by id on manage org projects page', async function (assert) { const anotherProject = this.server.create('scope', { type: 'project', scope: { id: instances.scopes.org.id, type: 'org' }, diff --git a/ui/admin/tests/acceptance/roles/project-scope-test.js b/ui/admin/tests/acceptance/roles/project-scope-test.js new file mode 100644 index 000000000..bfd296a26 --- /dev/null +++ b/ui/admin/tests/acceptance/roles/project-scope-test.js @@ -0,0 +1,105 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { visit, currentURL, click } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { authenticateSession } from 'ember-simple-auth/test-support'; +import { GRANT_SCOPE_THIS } from 'api/models/role'; + +module('Acceptance | roles | project-scope', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const GRANT_SCOPE_ROW_SELECTOR = (id) => + `tbody [data-test-grant-scope-row="${id}"]`; + const TABLE_ROW_SELECTOR = 'tbody tr'; + const MANAGE_DROPDOWN_SELECTOR = '.hds-dropdown-toggle-button'; + const MANAGE_SCOPES_SELECTOR = '[data-test-manage-dropdown-scopes]'; + const SEARCH_INPUT_SELECTOR = '.search-filtering [type="search"]'; + const NO_SCOPES_MSG_SELECTOR = '.role-grant-scopes div'; + const NO_SCOPES_MSG_LINK_SELECTOR = + '.role-grant-scopes div div:nth-child(3) a'; + const PAGINATION_SELECTOR = '.hds-pagination'; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + role: null, + }; + const urls = { + roles: null, + role: null, + roleScopes: null, + }; + + hooks.beforeEach(function () { + authenticateSession({}); + 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.role = this.server.create('role', { + scope: instances.scopes.project, + }); + + urls.roles = `/scopes/${instances.scopes.project.id}/roles`; + urls.role = `${urls.roles}/${instances.role.id}`; + urls.roleScopes = `${urls.role}/scopes`; + urls.manageScopes = `${urls.role}/manage-scopes`; + }); + + test('visiting role scopes', async function (assert) { + await visit(urls.role); + + await click(`[href="${urls.roleScopes}"]`); + await a11yAudit(); + + assert.strictEqual(currentURL(), urls.roleScopes); + assert.dom(GRANT_SCOPE_ROW_SELECTOR(GRANT_SCOPE_THIS)).exists(); + assert + .dom(TABLE_ROW_SELECTOR) + .exists({ count: instances.role.grant_scope_ids.length }); + }); + + test('search and pagination is not visible for project role scopes', async function (assert) { + await visit(urls.role); + + await click(`[href="${urls.roleScopes}"]`); + + assert.strictEqual(currentURL(), urls.roleScopes); + assert.dom(SEARCH_INPUT_SELECTOR).doesNotExist(); + assert.dom(PAGINATION_SELECTOR).doesNotExist(); + }); + + test('user cannot manage scopes for project role scopes', async function (assert) { + await visit(urls.role); + + await click(`[href="${urls.roleScopes}"]`); + await click(MANAGE_DROPDOWN_SELECTOR); + + assert.dom(MANAGE_SCOPES_SELECTOR).doesNotExist(); + }); + + test('user sees no scopes message without action when role has no grant scopes', async function (assert) { + instances.role.update({ grant_scope_ids: [] }); + await visit(urls.role); + + await click(`[href="${urls.roleScopes}"]`); + + assert.dom(NO_SCOPES_MSG_SELECTOR).includesText('No scopes added'); + assert.dom(NO_SCOPES_MSG_LINK_SELECTOR).doesNotExist(); + }); +});