mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-03 20:40:45 -05:00
* first full pass with new filtering * updates and making dropdowns searchable * fixing tests * updates, test fix * update version dropdown * update icons * comments and cleanup * filter fixes, update template and add test * fix tests * fix tests but not insane * update, changelog Co-authored-by: Dan Rivera <dan.rivera@hashicorp.com>
This commit is contained in:
parent
7e2f411859
commit
d17181c596
9 changed files with 250 additions and 110 deletions
3
changelog/_9577.txt
Normal file
3
changelog/_9577.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
ui/secrets: Updated filters on secret engines list to sort by path, engine type and version
|
||||
```
|
||||
|
|
@ -20,35 +20,84 @@
|
|||
</PH.Actions>
|
||||
</Hds::PageHeader>
|
||||
|
||||
<Toolbar class="has-top-margin-m">
|
||||
<ToolbarFilters>
|
||||
<SearchSelect
|
||||
@id="filter-by-engine-type"
|
||||
@options={{this.secretEngineArrayByType}}
|
||||
@selectLimit="1"
|
||||
@disallowNewItems={{true}}
|
||||
@fallbackComponent="input-search"
|
||||
@onChange={{this.filterEngineType}}
|
||||
@placeholder="Filter by engine type"
|
||||
@displayInherit={{true}}
|
||||
@inputValue={{if this.selectedEngineType (array this.selectedEngineType)}}
|
||||
@disabled={{if this.selectedEngineName true false}}
|
||||
class="is-marginless"
|
||||
<Hds::SegmentedGroup class="has-top-margin-m" as |SG|>
|
||||
<SG.TextInput
|
||||
@width="300px"
|
||||
@type="search"
|
||||
placeholder="Search by path"
|
||||
aria-label="Search"
|
||||
data-test-input-search="secret-engine-path"
|
||||
{{on "input" (fn this.setSearchText "path")}}
|
||||
/>
|
||||
<SG.Dropdown @width="175px" as |D|>
|
||||
<D.Header @hasDivider={{true}}>
|
||||
<SG.TextInput @type="search" placeholder="Search" aria-label="Search" {{on "input" (fn this.setSearchText "type")}} />
|
||||
</D.Header>
|
||||
<D.ToggleButton @color="secondary" @text="Engine type" data-test-toggle-input="filter-by-engine-type" />
|
||||
{{#each this.secretEngineArrayByType as |type|}}
|
||||
<D.Checkbox
|
||||
value={{type.name}}
|
||||
checked={{includes type.name this.engineTypeFilters}}
|
||||
{{on "click" (fn this.filterByEngineType type.name)}}
|
||||
data-test-checkbox={{type.name}}
|
||||
><Hds::Icon @name={{type.icon}} @isInline={{true}} /> {{type.name}}</D.Checkbox>
|
||||
{{/each}}
|
||||
</SG.Dropdown>
|
||||
<SG.Dropdown @width="250px" as |D|>
|
||||
<D.ToggleButton @color="secondary" @text="Version" data-test-toggle-input="filter-by-engine-version" />
|
||||
{{#if this.engineTypeFilters.length}}
|
||||
<D.Header @hasDivider={{true}}>
|
||||
<SG.TextInput
|
||||
@type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
{{on "input" (fn this.setSearchText "version")}}
|
||||
/>
|
||||
</D.Header>
|
||||
{{#each this.secretEngineArrayByVersions as |backend|}}
|
||||
<D.Checkbox
|
||||
value={{backend.version}}
|
||||
checked={{includes backend.version this.engineVersionFilters}}
|
||||
{{on "click" (fn this.filterByEngineVersion backend.version)}}
|
||||
data-test-checkbox={{backend.version}}
|
||||
>
|
||||
{{backend.version}}
|
||||
</D.Checkbox>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<D.Description class="has-top-padding-s" @text="Select an engine type first to filter by versions." />
|
||||
{{/if}}
|
||||
</SG.Dropdown>
|
||||
</Hds::SegmentedGroup>
|
||||
|
||||
<Hds::Layout::Flex @gap="8" class="has-top-margin-xs has-bottom-margin-m" @align="center">
|
||||
{{#if (and (not this.engineTypeFilters) (not this.engineVersionFilters))}}
|
||||
<Hds::Text::Body>No filters applied:</Hds::Text::Body>
|
||||
<Hds::TooltipButton
|
||||
@text="Select the desired filters in the dropdowns above to narrow your search."
|
||||
aria-label="More information"
|
||||
data-test-tooltip="Filter info"
|
||||
>
|
||||
<Hds::Icon @name="info" />
|
||||
</Hds::TooltipButton>
|
||||
{{else}}
|
||||
<Hds::Text::Body>Filters applied:</Hds::Text::Body>
|
||||
{{#each this.engineTypeFilters as |type|}}
|
||||
<Hds::Tag @text={{type}} @onDismiss={{fn this.filterByEngineType type}} data-test-button={{type}} />
|
||||
{{/each}}
|
||||
{{#each this.engineVersionFilters as |version|}}
|
||||
<Hds::Tag @text={{version}} @onDismiss={{fn this.filterByEngineVersion version}} data-test-button={{version}} />
|
||||
{{/each}}
|
||||
<Hds::Button
|
||||
@text="Clear all"
|
||||
@color="tertiary"
|
||||
@icon="x"
|
||||
@size="small"
|
||||
data-test-button="Clear all"
|
||||
{{on "click" this.clearAllFilters}}
|
||||
/>
|
||||
<SearchSelect
|
||||
@id="filter-by-engine-name"
|
||||
@options={{this.secretEngineArrayByName}}
|
||||
@selectLimit="1"
|
||||
@disallowNewItems={{true}}
|
||||
@fallbackComponent="input-search"
|
||||
@onChange={{this.filterEngineName}}
|
||||
@placeholder="Filter by engine name"
|
||||
@displayInherit={{true}}
|
||||
@inputValue={{if this.selectedEngineName (array this.selectedEngineName)}}
|
||||
class="is-marginless has-left-padding-s"
|
||||
/>
|
||||
</ToolbarFilters>
|
||||
</Toolbar>
|
||||
{{/if}}
|
||||
</Hds::Layout::Flex>
|
||||
|
||||
{{#each this.sortedDisplayableBackends as |backend|}}
|
||||
<LinkedBlock
|
||||
|
|
@ -60,7 +109,11 @@
|
|||
<div>
|
||||
<div class="has-text-grey is-grid align-items-center linked-block-title">
|
||||
{{#if backend.icon}}
|
||||
<Hds::TooltipButton aria-label="Type of backend" @text={{this.generateToolTipText backend}}>
|
||||
<Hds::TooltipButton
|
||||
aria-label="Type of backend"
|
||||
@text={{this.generateToolTipText backend}}
|
||||
data-test-tooltip="Backend type"
|
||||
>
|
||||
<Icon @name={{backend.icon}} class="has-text-grey-light" />
|
||||
</Hds::TooltipButton>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -38,10 +38,16 @@ export default class SecretEngineList extends Component<Args> {
|
|||
@service declare readonly version: VersionService;
|
||||
|
||||
@tracked secretEngineOptions: Array<string> | [] = [];
|
||||
@tracked selectedEngineType = '';
|
||||
@tracked selectedEngineName = '';
|
||||
@tracked engineToDisable: SecretsEngineResource | undefined = undefined;
|
||||
|
||||
@tracked engineTypeFilters: Array<string> = [];
|
||||
@tracked engineVersionFilters: Array<string> = [];
|
||||
@tracked searchText = '';
|
||||
|
||||
// search text for dropdown filters
|
||||
@tracked typeSearchText = '';
|
||||
@tracked versionSearchText = '';
|
||||
|
||||
get clusterName() {
|
||||
return this.version.clusterName;
|
||||
}
|
||||
|
|
@ -52,28 +58,86 @@ export default class SecretEngineList extends Component<Args> {
|
|||
|
||||
get sortedDisplayableBackends() {
|
||||
// show supported secret engines first and then organize those by id.
|
||||
const sortedBackends = this.displayableBackends.sort(
|
||||
(a, b) => Number(b.isSupportedBackend) - Number(a.isSupportedBackend) || a.id.localeCompare(b.id)
|
||||
);
|
||||
let sortedBackends = this.displayableBackends
|
||||
.slice()
|
||||
.sort(
|
||||
(a, b) => Number(b.isSupportedBackend) - Number(a.isSupportedBackend) || a.id.localeCompare(b.id)
|
||||
);
|
||||
|
||||
// return an options list to filter by engine type, ex: 'kv'
|
||||
if (this.selectedEngineType) {
|
||||
// check first if the user has also filtered by name.
|
||||
if (this.selectedEngineName) {
|
||||
return sortedBackends.filter((backend) => this.selectedEngineName === backend.id);
|
||||
}
|
||||
// otherwise filter by engine type
|
||||
return sortedBackends.filter((backend) => this.selectedEngineType === backend.engineType);
|
||||
// filters by engine type, ex: 'kv'
|
||||
if (this.engineTypeFilters.length > 0) {
|
||||
sortedBackends = sortedBackends.filter((backend) =>
|
||||
this.engineTypeFilters.includes(backend.engineType)
|
||||
);
|
||||
}
|
||||
|
||||
// return an options list to filter by engine name, ex: 'secret'
|
||||
if (this.selectedEngineName) {
|
||||
return sortedBackends.filter((backend) => this.selectedEngineName === backend.id);
|
||||
// filters by engine version, ex: 'v1.21.0...'
|
||||
if (this.engineVersionFilters.length > 0) {
|
||||
sortedBackends = sortedBackends.filter((backend) =>
|
||||
this.engineVersionFilters.includes(backend.running_plugin_version)
|
||||
);
|
||||
}
|
||||
|
||||
// if there is search text, filter path name by that
|
||||
if (this.searchText.trim() !== '') {
|
||||
sortedBackends = sortedBackends.filter((backend) =>
|
||||
backend.path.toLowerCase().includes(this.searchText.toLowerCase())
|
||||
);
|
||||
}
|
||||
// no filters, return full sorted list.
|
||||
return sortedBackends;
|
||||
}
|
||||
|
||||
// Returns filter options for engine type dropdown
|
||||
get typeFilterOptions() {
|
||||
// if there is search text, filter types by that
|
||||
if (this.typeSearchText.trim() !== '') {
|
||||
return this.displayableBackends.filter((backend) =>
|
||||
backend.engineType.toLowerCase().includes(this.typeSearchText.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
return this.displayableBackends;
|
||||
}
|
||||
|
||||
// Returns filter options for version dropdown
|
||||
get versionFilterOptions() {
|
||||
// if there is search text, filter versions by that
|
||||
if (this.versionSearchText.trim() !== '') {
|
||||
// filtered by sorted backends array since an engine type filter has to be selected first
|
||||
return this.sortedDisplayableBackends.filter((backend) =>
|
||||
backend.running_plugin_version.toLowerCase().includes(this.versionSearchText.toLowerCase())
|
||||
);
|
||||
}
|
||||
return this.sortedDisplayableBackends;
|
||||
}
|
||||
|
||||
// Returns filtered engines list by type
|
||||
get secretEngineArrayByType() {
|
||||
const arrayOfAllEngineTypes = this.typeFilterOptions.map((modelObject) => modelObject.engineType);
|
||||
// filter out repeated engineTypes (e.g. [kv, kv] => [kv])
|
||||
const arrayOfUniqueEngineTypes = [...new Set(arrayOfAllEngineTypes)];
|
||||
|
||||
return arrayOfUniqueEngineTypes.map((engineType) => ({
|
||||
name: engineType,
|
||||
id: engineType,
|
||||
icon: engineDisplayData(engineType)?.glyph ?? 'lock',
|
||||
}));
|
||||
}
|
||||
|
||||
// Returns filtered engines list by version
|
||||
get secretEngineArrayByVersions() {
|
||||
const arrayOfAllEngineVersions = this.versionFilterOptions.map(
|
||||
(modelObject) => modelObject.running_plugin_version
|
||||
);
|
||||
// filter out repeated engineVersions (e.g. [1.0, 1.0] => [1.0])
|
||||
const arrayOfUniqueEngineVersions = [...new Set(arrayOfAllEngineVersions)];
|
||||
return arrayOfUniqueEngineVersions.map((version) => ({
|
||||
version,
|
||||
id: version,
|
||||
}));
|
||||
}
|
||||
|
||||
generateToolTipText = (backend: SecretsEngineResource) => {
|
||||
const displayData = engineDisplayData(backend.type);
|
||||
|
||||
|
|
@ -96,35 +160,40 @@ export default class SecretEngineList extends Component<Args> {
|
|||
}
|
||||
};
|
||||
|
||||
// Filtering & searching
|
||||
get secretEngineArrayByType() {
|
||||
const arrayOfAllEngineTypes = this.sortedDisplayableBackends.map((modelObject) => modelObject.engineType);
|
||||
// filter out repeated engineTypes (e.g. [kv, kv] => [kv])
|
||||
const arrayOfUniqueEngineTypes = [...new Set(arrayOfAllEngineTypes)];
|
||||
|
||||
return arrayOfUniqueEngineTypes.map((engineType) => ({
|
||||
name: engineType,
|
||||
id: engineType,
|
||||
}));
|
||||
}
|
||||
|
||||
get secretEngineArrayByName() {
|
||||
return this.sortedDisplayableBackends.map((modelObject) => ({
|
||||
name: modelObject.id,
|
||||
id: modelObject.id,
|
||||
}));
|
||||
@action
|
||||
setSearchText(type: string, event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (type === 'type') {
|
||||
this.typeSearchText = target.value;
|
||||
} else if (type === 'version') {
|
||||
this.versionSearchText = target.value;
|
||||
} else {
|
||||
this.searchText = target.value;
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
filterEngineType(type: string[]) {
|
||||
const [selectedType] = type;
|
||||
this.selectedEngineType = selectedType || '';
|
||||
filterByEngineType(type: string) {
|
||||
if (this.engineTypeFilters.includes(type)) {
|
||||
this.engineTypeFilters = this.engineTypeFilters.filter((t) => t !== type);
|
||||
} else {
|
||||
this.engineTypeFilters = [...this.engineTypeFilters, type];
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
filterEngineName(name: string[]) {
|
||||
const [selectedName] = name;
|
||||
this.selectedEngineName = selectedName || '';
|
||||
filterByEngineVersion(version: string) {
|
||||
if (this.engineVersionFilters.includes(version)) {
|
||||
this.engineVersionFilters = this.engineVersionFilters.filter((v) => v !== version);
|
||||
} else {
|
||||
this.engineVersionFilters = [...this.engineVersionFilters, version];
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
clearAllFilters() {
|
||||
this.engineTypeFilters = [];
|
||||
this.engineVersionFilters = [];
|
||||
}
|
||||
|
||||
@dropTask
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import { click, fillIn, currentRouteName, visit, currentURL } from '@ember/test-helpers';
|
||||
import { selectChoose } from 'ember-power-select/test-support';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
|
@ -162,7 +161,7 @@ module('Acceptance | secret-engine list view', function (hooks) {
|
|||
await runCmd(mountEngineCmd('alicloud', enginePath));
|
||||
await visit('/vault/secrets');
|
||||
// to reduce flakiness, searching by engine name first in case there are pagination issues
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), enginePath);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), enginePath);
|
||||
assert.dom(SES.secretsBackendLink(enginePath)).exists('the alicloud engine is mounted');
|
||||
|
||||
await click(GENERAL.menuTrigger);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { click, currentRouteName, settled, visit } from '@ember/test-helpers';
|
||||
import { selectChoose } from 'ember-power-select/test-support';
|
||||
import { click, currentRouteName, fillIn, visit } from '@ember/test-helpers';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
|
@ -20,6 +19,7 @@ import { createSecret } from 'vault/tests/helpers/secret-engine/secret-engine-he
|
|||
|
||||
import { create } from 'ember-cli-page-object';
|
||||
import { deleteEngineCmd, runCmd } from 'vault/tests/helpers/commands';
|
||||
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||
|
||||
const cli = create(consolePanel);
|
||||
|
||||
|
|
@ -66,8 +66,7 @@ module('Acceptance | secrets/generic/create', function (hooks) {
|
|||
`write sys/mounts/${path}/tune options=version=2`,
|
||||
]);
|
||||
await visit('/vault/secrets');
|
||||
await selectChoose('[data-test-component="search-select"]#filter-by-engine-name', path);
|
||||
await settled();
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), path);
|
||||
await click(SES.secretsBackendLink(path));
|
||||
assert.strictEqual(
|
||||
currentRouteName(),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import { currentURL, visit, click, fillIn } from '@ember/test-helpers';
|
||||
import { selectChoose } from 'ember-power-select/test-support';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
|
@ -56,7 +55,7 @@ module('Acceptance | secret engine mount settings', function (hooks) {
|
|||
await visit('/vault/secrets/mounts');
|
||||
await runCmd(mountEngineCmd(type, path), false);
|
||||
await visit('/vault/secrets');
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), path);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), path);
|
||||
await click(GENERAL.menuTrigger);
|
||||
await click(GENERAL.menuItem('view-configuration'));
|
||||
assert.strictEqual(
|
||||
|
|
@ -75,7 +74,7 @@ module('Acceptance | secret engine mount settings', function (hooks) {
|
|||
await visit('/vault/secrets/mounts');
|
||||
await runCmd(mountEngineCmd(type, path), false);
|
||||
await visit('/vault/secrets');
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), path);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), path);
|
||||
await click(GENERAL.menuTrigger);
|
||||
await click(GENERAL.menuItem('view-configuration'));
|
||||
assert.strictEqual(
|
||||
|
|
|
|||
|
|
@ -171,4 +171,5 @@ export const GENERAL = {
|
|||
/* ────── Misc ────── */
|
||||
icon: (name: string) => (name ? `[data-test-icon="${name}"]` : '[data-test-icon]'),
|
||||
badge: (name: string) => (name ? `[data-test-badge="${name}"]` : '[data-test-badge]'),
|
||||
tooltip: (label: string) => `[data-test-tooltip="${label}"]`,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ export async function createSecret(path, key, value) {
|
|||
return;
|
||||
}
|
||||
|
||||
export const createSecretsEngine = (store, type, path) => {
|
||||
export const createSecretsEngine = (store, type, path, version) => {
|
||||
if (store) {
|
||||
store.pushPayload('secret-engine', {
|
||||
modelName: 'secret-engine',
|
||||
id: path,
|
||||
path: `${path}/`,
|
||||
type: type,
|
||||
running_plugin_version: version,
|
||||
data: {
|
||||
type: type,
|
||||
},
|
||||
|
|
@ -36,6 +37,7 @@ export const createSecretsEngine = (store, type, path) => {
|
|||
return new SecretsEngineResource({
|
||||
path: `${path}/`,
|
||||
type,
|
||||
running_plugin_version: version,
|
||||
});
|
||||
};
|
||||
/* Create configurations methods
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@
|
|||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'vault/tests/helpers';
|
||||
import { render, click, find, findAll, triggerEvent } from '@ember/test-helpers';
|
||||
import { render, click, findAll, triggerEvent, fillIn } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import sinon from 'sinon';
|
||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
import { overrideResponse } from 'vault/tests/helpers/stubs';
|
||||
import { clickTrigger } from 'ember-power-select/test-support/helpers';
|
||||
import { selectChoose } from 'ember-power-select/test-support';
|
||||
import { createSecretsEngine } from 'vault/tests/helpers/secret-engine/secret-engine-helpers';
|
||||
import { SECRET_ENGINE_SELECTORS as SES } from 'vault/tests/helpers/secret-engine/secret-engine-selectors';
|
||||
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||
|
|
@ -37,8 +35,8 @@ module('Integration | Component | secret-engine/list', function (hooks) {
|
|||
this.secretEngineModels = [
|
||||
createSecretsEngine(undefined, 'cubbyhole', 'cubbyhole-test'),
|
||||
createSecretsEngine(undefined, 'kv', 'kv-test'),
|
||||
createSecretsEngine(undefined, 'aws', 'aws-1'),
|
||||
createSecretsEngine(undefined, 'aws', 'aws-2'),
|
||||
createSecretsEngine(undefined, 'aws', 'aws-1', 'v1.0.0'),
|
||||
createSecretsEngine(undefined, 'aws', 'aws-2', 'v2.0.0'),
|
||||
createSecretsEngine(undefined, 'nomad', 'nomad-test'),
|
||||
createSecretsEngine(undefined, 'badType', 'external-test'),
|
||||
];
|
||||
|
|
@ -66,12 +64,13 @@ module('Integration | Component | secret-engine/list', function (hooks) {
|
|||
|
||||
test('hovering over the icon of an external unrecognized engine type sets unrecognized tooltip text', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}} />`);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), 'external-test');
|
||||
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), 'external-test');
|
||||
await triggerEvent('.hds-tooltip-button', 'mouseenter');
|
||||
const engineTooltip = document.querySelector(GENERAL.tooltip('Backend type'));
|
||||
await triggerEvent(engineTooltip, 'mouseenter');
|
||||
|
||||
assert
|
||||
.dom('.hds-tooltip-container')
|
||||
.dom(engineTooltip.nextSibling)
|
||||
.hasText(
|
||||
`This engine's type is not recognized by the UI. Please use the CLI to manage this engine.`,
|
||||
'shows tooltip text for unknown engine'
|
||||
|
|
@ -80,12 +79,13 @@ module('Integration | Component | secret-engine/list', function (hooks) {
|
|||
|
||||
test('hovering over the icon of an unsupported engine sets unsupported tooltip text', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}} />`);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), 'nomad');
|
||||
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-type'), 'nomad');
|
||||
await triggerEvent('.hds-tooltip-button', 'mouseenter');
|
||||
const engineTooltip = document.querySelector(GENERAL.tooltip('Backend type'));
|
||||
await triggerEvent(engineTooltip, 'mouseenter');
|
||||
|
||||
assert
|
||||
.dom('.hds-tooltip-container')
|
||||
.dom(engineTooltip.nextSibling)
|
||||
.hasText(
|
||||
'The UI only supports configuration views for these secret engines. The CLI must be used to manage other engine resources.',
|
||||
'shows tooltip text for unsupported engine'
|
||||
|
|
@ -94,21 +94,22 @@ module('Integration | Component | secret-engine/list', function (hooks) {
|
|||
|
||||
test('hovering over the icon of a supported engine sets engine name as tooltip', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}} />`);
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), 'aws-1');
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), 'aws-1');
|
||||
|
||||
await triggerEvent('.hds-tooltip-button', 'mouseenter');
|
||||
const engineTooltip = document.querySelector(GENERAL.tooltip('Backend type'));
|
||||
await triggerEvent(engineTooltip, 'mouseenter');
|
||||
|
||||
assert.dom('.hds-tooltip-container').hasText('AWS', 'shows tooltip text for supported engine with name');
|
||||
assert.dom(engineTooltip.nextSibling).hasText('AWS', 'shows tooltip text for supported engine with name');
|
||||
});
|
||||
|
||||
test('hovering over the icon of a kv engine shows engine name and version', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}}/>`);
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), `kv-test`);
|
||||
|
||||
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), `kv-test`);
|
||||
|
||||
await triggerEvent('.hds-tooltip-button', 'mouseenter');
|
||||
const engineTooltip = document.querySelector(GENERAL.tooltip('Backend type'));
|
||||
await triggerEvent(engineTooltip, 'mouseenter');
|
||||
assert
|
||||
.dom('.hds-tooltip-container')
|
||||
.dom(engineTooltip.nextSibling)
|
||||
.hasText('KV version 1', 'shows tooltip text for kv engine with version');
|
||||
});
|
||||
|
||||
|
|
@ -126,28 +127,42 @@ module('Integration | Component | secret-engine/list', function (hooks) {
|
|||
.hasClass('linked-block', `linked-block class is added to supported aws engines.`);
|
||||
});
|
||||
|
||||
test('it filters by name and engine type', async function (assert) {
|
||||
test('it filters by engine path and engine type', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}} />`);
|
||||
// filter by type
|
||||
await clickTrigger('#filter-by-engine-type');
|
||||
await click(GENERAL.searchSelect.option());
|
||||
await click(GENERAL.toggleInput('filter-by-engine-type'));
|
||||
await click(GENERAL.checkboxByAttr('aws'));
|
||||
|
||||
const rows = findAll(SES.secretsBackendLink());
|
||||
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');
|
||||
const firstItemToSelect = find(GENERAL.searchSelect.option()).innerText;
|
||||
await click(GENERAL.searchSelect.option());
|
||||
const singleRow = document.querySelectorAll(SES.secretsBackendLink());
|
||||
assert.strictEqual(singleRow.length, 1, 'returns only one row');
|
||||
assert.dom(singleRow[0]).includesText(firstItemToSelect, 'shows the filtered by name engine');
|
||||
|
||||
// clear filter by engine name
|
||||
await click(`#filter-by-engine-name ${GENERAL.searchSelect.removeSelected}`);
|
||||
// clear filter by type
|
||||
await click(GENERAL.button('Clear all'));
|
||||
assert.true(document.querySelectorAll(SES.secretsBackendLink()).length > 1, 'filter has been removed');
|
||||
|
||||
// filter by path
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), 'kv');
|
||||
const singleRow = document.querySelectorAll(SES.secretsBackendLink());
|
||||
assert.dom(singleRow[0]).includesText('kv', 'shows the filtered by path engine');
|
||||
|
||||
// clear filter by engine path
|
||||
await fillIn(GENERAL.inputSearch('secret-engine-path'), '');
|
||||
const rowsAgain = document.querySelectorAll(SES.secretsBackendLink());
|
||||
assert.true(rowsAgain.length > 1, 'filter has been removed');
|
||||
assert.true(rowsAgain.length > 1, 'search filter text has been removed');
|
||||
});
|
||||
|
||||
test('it filters by engine version', async function (assert) {
|
||||
await render(hbs`<SecretEngine::List @secretEngines={{this.secretEngineModels}} />`);
|
||||
// select engine type
|
||||
await click(GENERAL.toggleInput('filter-by-engine-type'));
|
||||
await click(GENERAL.checkboxByAttr('aws'));
|
||||
|
||||
// filter by version
|
||||
await click(GENERAL.toggleInput('filter-by-engine-version'));
|
||||
await click(GENERAL.checkboxByAttr('v2.0.0'));
|
||||
const singleRow = document.querySelectorAll(SES.secretsBackendLink());
|
||||
assert.dom(singleRow[0]).includesText('aws-2', 'shows the single engine filtered by version');
|
||||
});
|
||||
|
||||
test('it applies overflow styling', async function (assert) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue