+ {{backend.accessor}}
+
+ {{/if}}
+ {{#if backend.description}}
+ tag
- * @param {string} description=null - will truncate if wider than parent div
- * @param {string} glyphText=null - tooltip for glyph
- * @param {string} glyph=null - will display as icon beside the title
- * @param {string} title=null - if @link object is passed in then title will link to @link.route
- */
-
-/* eslint ember/no-empty-glimmer-component-classes: 'warn' */
-class ContentComponent extends Component {}
-
-export default setComponentTemplate(layout, ContentComponent);
diff --git a/ui/lib/core/addon/components/linkable-item/menu.js b/ui/lib/core/addon/components/linkable-item/menu.js
deleted file mode 100644
index acc36b3ee..000000000
--- a/ui/lib/core/addon/components/linkable-item/menu.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: MPL-2.0
- */
-
-import Component from '@glimmer/component';
-import layout from '../../templates/components/linkable-item/menu';
-import { setComponentTemplate } from '@ember/component';
-
-/**
- * @module Menu
- * Menu components are contextual components of LinkableItem, used to display a menu on the right side of a LinkableItem component.
- *
- * @example
- * ```js
- *
- *
- * Some menu here
- *
- *
- * ```
- */
-
-/* eslint ember/no-empty-glimmer-component-classes: 'warn' */
-class MenuComponent extends Component {}
-
-export default setComponentTemplate(layout, MenuComponent);
diff --git a/ui/lib/core/addon/components/search-select.hbs b/ui/lib/core/addon/components/search-select.hbs
index 94a9a7d27..2a6ebfd74 100644
--- a/ui/lib/core/addon/components/search-select.hbs
+++ b/ui/lib/core/addon/components/search-select.hbs
@@ -39,6 +39,7 @@
@onChange={{this.selectOrCreate}}
@placeholderComponent={{component "search-select-placeholder"}}
@verticalPosition="below"
+ @disabled={{@disabled}}
as |option|
>
{{#if this.shouldRenderName}}
diff --git a/ui/lib/core/addon/components/search-select.js b/ui/lib/core/addon/components/search-select.js
index 7380e6d57..f3c13c407 100644
--- a/ui/lib/core/addon/components/search-select.js
+++ b/ui/lib/core/addon/components/search-select.js
@@ -53,6 +53,7 @@ import { filterOptions, defaultMatcher } from 'ember-power-select/utils/group-ut
* @param {string} [placeholder] - text you wish to replace the default "search" with
* @param {boolean} [displayInherit=false] - if you need the search select component to display inherit instead of box.
* @param {function} [renderInfoTooltip] - receives each inputValue string and list of dropdownOptions as args, so parent can determine when to render a tooltip beside a selectedOption and the tooltip text. see 'oidc/provider-form.js'
+ * @param {boolean} [disabled] - if true sets the disabled property on the ember-power-select component and makes it unusable.
*
// * advanced customization
* @param {Array} options - array of objects passed directly to the power-select component. If doing this, `models` should not also be passed as that will overwrite the
diff --git a/ui/lib/core/addon/templates/components/linkable-item.hbs b/ui/lib/core/addon/templates/components/linkable-item.hbs
deleted file mode 100644
index d2de17e04..000000000
--- a/ui/lib/core/addon/templates/components/linkable-item.hbs
+++ /dev/null
@@ -1,17 +0,0 @@
-
- {{#if @disabled}}
-
- {{yield (hash content=(component "linkable-item/content"))}}
- {{yield (hash menu=(component "linkable-item/menu"))}}
-
- {{else}}
-
- {{yield (hash content=(component "linkable-item/content"))}}
- {{yield (hash menu=(component "linkable-item/menu"))}}
-
- {{/if}}
-
\ No newline at end of file
diff --git a/ui/lib/core/addon/templates/components/linkable-item/content.hbs b/ui/lib/core/addon/templates/components/linkable-item/content.hbs
deleted file mode 100644
index d8f77fa01..000000000
--- a/ui/lib/core/addon/templates/components/linkable-item/content.hbs
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
- {{#if @glyph}}
-
-
-
-
-
-
- {{or @glyphText @title}}
-
-
-
- {{/if}}
-
- {{#if @title}}
- {{#if @link}}
-
- {{@title}}
-
- {{else}}
- {{@title}}
- {{/if}}
- {{/if}}
-
- {{#if @accessor}}
-
- {{@accessor}}
-
- {{/if}}
-
- {{#if @description}}
-
- {{@description}}
-
- {{/if}}
-
- {{yield}}
-
\ No newline at end of file
diff --git a/ui/lib/core/addon/templates/components/linkable-item/menu.hbs b/ui/lib/core/addon/templates/components/linkable-item/menu.hbs
deleted file mode 100644
index 2361fb7da..000000000
--- a/ui/lib/core/addon/templates/components/linkable-item/menu.hbs
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file
diff --git a/ui/lib/core/app/components/linkable-item.js b/ui/lib/core/app/components/linkable-item.js
deleted file mode 100644
index 628caf891..000000000
--- a/ui/lib/core/app/components/linkable-item.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: MPL-2.0
- */
-
-export { default } from 'core/components/linkable-item';
diff --git a/ui/tests/acceptance/secrets/backend/engines-test.js b/ui/tests/acceptance/secrets/backend/engines-test.js
index b6b7ef8f0..617799259 100644
--- a/ui/tests/acceptance/secrets/backend/engines-test.js
+++ b/ui/tests/acceptance/secrets/backend/engines-test.js
@@ -4,15 +4,21 @@
*/
import { currentRouteName, settled } from '@ember/test-helpers';
+import { clickTrigger } from 'ember-power-select/test-support/helpers';
+import { create } from 'ember-cli-page-object';
import { module, test } from 'qunit';
+import { runCommands } from 'vault/tests/helpers/pki/pki-run-commands';
import { setupApplicationTest } from 'ember-qunit';
import { v4 as uuidv4 } from 'uuid';
import mountSecrets from 'vault/tests/pages/settings/mount-secret-backend';
import backendsPage from 'vault/tests/pages/secrets/backends';
import authPage from 'vault/tests/pages/auth';
+import ss from 'vault/tests/pages/components/search-select';
-module('Acceptance | engine/disable', function (hooks) {
+const searchSelect = create(ss);
+
+module('Acceptance | secret-engine list view', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function () {
@@ -20,7 +26,7 @@ module('Acceptance | engine/disable', function (hooks) {
return authPage.login();
});
- test('disable engine', async function (assert) {
+ test('it allows you to disable an engine', async function (assert) {
// first mount an engine so we can disable it.
const enginePath = `alicloud-disable-${this.uid}`;
await mountSecrets.enable('alicloud', enginePath);
@@ -41,11 +47,68 @@ module('Acceptance | engine/disable', function (hooks) {
'vault.cluster.secrets.backends',
'redirects to the backends page'
);
-
assert.strictEqual(
backendsPage.rows.filterBy('path', `${enginePath}/`).length,
0,
'does not show the disabled engine'
);
});
+
+ test('it adds disabled css styling to unsupported secret engines', async function (assert) {
+ assert.expect(2);
+ // first mount engine that is not supported
+ const enginePath = `nomad-${this.uid}`;
+
+ await mountSecrets.enable('nomad', enginePath);
+ await settled();
+ await backendsPage.visit();
+ await settled();
+
+ const rows = document.querySelectorAll('[data-test-auth-backend-link]');
+ const rowUnsupported = Array.from(rows).filter((row) => row.innerText.includes('nomad'));
+ const rowSupported = Array.from(rows).filter((row) => row.innerText.includes('cubbyhole'));
+ assert
+ .dom(rowUnsupported[0])
+ .doesNotHaveClass(
+ 'linked-block',
+ `the linked-block class is not added to unsupported engines, which effectively disables it.`
+ );
+ assert.dom(rowSupported[0]).hasClass('linked-block', `linked-block class is added to supported engines.`);
+
+ // cleanup
+ await runCommands([`delete sys/mounts/${enginePath}`]);
+ });
+
+ test('it filters by name and engine type', async function (assert) {
+ assert.expect(3);
+ const enginePath1 = `aws-1-${this.uid}`;
+ const enginePath2 = `aws-2-${this.uid}`;
+
+ await mountSecrets.enable('aws', enginePath1);
+ await mountSecrets.enable('aws', enginePath2);
+ await backendsPage.visit();
+ await settled();
+ // filter by type
+ await clickTrigger('#filter-by-engine-type');
+ await searchSelect.options.objectAt(0).click();
+
+ const rows = document.querySelectorAll('[data-test-auth-backend-link]');
+ const rowsAws = Array.from(rows).filter((row) => row.innerText.includes('aws'));
+
+ assert.strictEqual(rows.length, rowsAws.length, 'all rows returned are aws');
+ // filter by name
+ await clickTrigger('#filter-by-engine-name');
+ await searchSelect.options.objectAt(1).click();
+ const singleRow = document.querySelectorAll('[data-test-auth-backend-link]');
+
+ assert.dom(singleRow[0]).includesText('aws-2', 'shows the filtered by name engine');
+ // clear filter by engine name
+ await searchSelect.deleteButtons.objectAt(1).click();
+ const rowsAgain = document.querySelectorAll('[data-test-auth-backend-link]');
+ assert.ok(rowsAgain.length > 1, 'filter has been removed');
+
+ // cleanup
+ await runCommands([`delete sys/mounts/${enginePath1}`]);
+ await runCommands([`delete sys/mounts/${enginePath2}`]);
+ });
});
diff --git a/ui/tests/acceptance/settings/mount-secret-backend-test.js b/ui/tests/acceptance/settings/mount-secret-backend-test.js
index 33c9152e5..12c3ef684 100644
--- a/ui/tests/acceptance/settings/mount-secret-backend-test.js
+++ b/ui/tests/acceptance/settings/mount-secret-backend-test.js
@@ -126,7 +126,7 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) {
await page.secretList();
await settled();
assert
- .dom(`[data-test-secret-backend-row=${path}]`)
+ .dom(`[data-test-auth-backend-link=${path}]`)
.exists({ count: 1 }, 'renders only one instance of the engine');
});
diff --git a/ui/tests/integration/components/linkable-item-test.js b/ui/tests/integration/components/linkable-item-test.js
deleted file mode 100644
index 1b376da1a..000000000
--- a/ui/tests/integration/components/linkable-item-test.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: MPL-2.0
- */
-
-import { module, test } from 'qunit';
-import { setupRenderingTest } from 'ember-qunit';
-import { render } from '@ember/test-helpers';
-import { hbs } from 'ember-cli-htmlbars';
-
-module('Integration | Component | linkable-item', function (hooks) {
- setupRenderingTest(hooks);
-
- test('it renders anything passed in', async function (assert) {
- await render(hbs` `);
- assert.dom(this.element).hasText('', 'No content rendered');
-
- await render(hbs`
-
-
- stuff here
-
-
- menu
-
-
- `);
- assert.dom('[data-test-linkable-item-content]').hasText('stuff here');
- assert.dom('[data-test-linkable-item-menu]').hasText('menu');
- });
-
- test('it is not wrapped in a linked block if disabled is true', async function (assert) {
- await render(hbs`
-
-
- stuff here
-
-
- `);
- assert.dom('.list-item-row').exists('List item row exists');
- assert.dom('.list-item-row.linked-block').doesNotExist('Does not render linked block');
- assert.dom('[data-test-secret-path]').doesNotExist('Title is not rendered');
- assert.dom('[data-test-linkable-item-accessor]').doesNotExist('Accessor is not rendered');
- assert.dom('[data-test-linkable-item-accessor]').doesNotExist('Accessor is not rendered');
- assert.dom('[data-test-linkable-item-glyph]').doesNotExist('Glyph is not rendered');
- });
-
- test('it is wrapped in a linked block if a link is passed', async function (assert) {
- await render(hbs`
-
-
- stuff here
-
-
- `);
-
- assert.dom('.list-item-row.linked-block').exists('Renders linked block');
- });
-
- test('it renders standard attributes on content', async function (assert) {
- this.set('title', 'A Title');
- this.set('accessor', 'my accessor');
- this.set('description', 'my description');
- this.set('glyph', 'key');
- this.set('glyphText', 'Here is some extra info');
-
- // Template block usage:
- await render(hbs`
-
-
-
- `);
- assert.dom('.list-item-row').exists('List item row exists');
- assert.dom('[data-test-secret-path]').hasText(this.title, 'Title is rendered');
- assert.dom('[data-test-linkable-item-accessor]').hasText(this.accessor, 'Accessor is rendered');
- assert.dom('[data-test-linkable-item-description]').hasText(this.description, 'Description is rendered');
- assert.dom('[data-test-linkable-item-glyph]').exists('Glyph is rendered');
- });
-});
diff --git a/ui/tests/pages/secrets/backends.js b/ui/tests/pages/secrets/backends.js
index f0dc796e4..1a7d3ebbb 100644
--- a/ui/tests/pages/secrets/backends.js
+++ b/ui/tests/pages/secrets/backends.js
@@ -9,7 +9,7 @@ import uiPanel from 'vault/tests/pages/components/console/ui-panel';
export default create({
consoleToggle: clickable('[data-test-console-toggle]'),
visit: visitable('/vault/secrets'),
- rows: collection('[data-test-secret-backend-row]', {
+ rows: collection('[data-test-auth-backend-link]', {
path: text('[data-test-secret-path]'),
menu: clickable('[data-test-popup-menu-trigger]'),
}),