From accf9faf600e9896f4472b3bd4ed7992c4e88006 Mon Sep 17 00:00:00 2001
From: Lisbet Alvarez <107949262+lisbet-alvarez@users.noreply.github.com>
Date: Fri, 14 Nov 2025 15:49:32 -0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20update=20credential-?=
=?UTF-8?q?library=20form=20for=20password=20type=20(#3060)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* refactor: 💡 update credential-library form for password type
* style: 💄 fix display issue
* test: 💍 add test cases
---
.../generated/models/credential-library.js | 3 +-
.../addon/serializers/credential-library.js | 4 +-
.../serializers/credential-library-test.js | 8 +-
addons/core/translations/resources/en-us.yaml | 11 +-
e2e-tests/admin/pages/credential-stores.js | 12 +-
.../tests/credential-store-vault.spec.js | 6 +-
.../mapping-overrides/index.hbs | 79 ++++----
.../mapping-overrides/index.js | 36 +---
.../form/credential-library/radio/index.hbs | 1 +
.../vault-generic/index.hbs | 7 +-
.../credential-library/vault-generic/index.js | 2 +-
.../credential-library/create-test.js | 156 +++++++---------
.../credential-library/selectors.js | 10 +-
.../credential-library/update-test.js | 171 +++++++-----------
ui/desktop/app/styles/app.scss | 2 +
15 files changed, 186 insertions(+), 322 deletions(-)
diff --git a/addons/api/addon/generated/models/credential-library.js b/addons/api/addon/generated/models/credential-library.js
index 3d8ba617e..9e8d9c0d1 100644
--- a/addons/api/addon/generated/models/credential-library.js
+++ b/addons/api/addon/generated/models/credential-library.js
@@ -81,9 +81,10 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
})
credential_type;
- @attr('object-as-array', {
+ @attr('object', {
for: 'vault-generic',
description: 'It indicates the credential mapping overrides.',
+ emptyObjectIfMissing: true,
})
credential_mapping_overrides;
diff --git a/addons/api/addon/serializers/credential-library.js b/addons/api/addon/serializers/credential-library.js
index 5e2186eb7..13e155c83 100644
--- a/addons/api/addon/serializers/credential-library.js
+++ b/addons/api/addon/serializers/credential-library.js
@@ -68,7 +68,9 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
*/
handleCredentialMappingOverrides(serialized, isNew) {
const { credential_type, credential_mapping_overrides } = serialized;
-
+ if (Object.keys(credential_mapping_overrides).length === 0) {
+ serialized.credential_mapping_overrides = null;
+ }
// API expects to send null to fields if it is undefined or deleted
if (credential_mapping_overrides && !isNew) {
serialized.credential_mapping_overrides = options.mapping_overrides[
diff --git a/addons/api/tests/unit/serializers/credential-library-test.js b/addons/api/tests/unit/serializers/credential-library-test.js
index 817ecb42c..cb90605d6 100644
--- a/addons/api/tests/unit/serializers/credential-library-test.js
+++ b/addons/api/tests/unit/serializers/credential-library-test.js
@@ -25,9 +25,7 @@ module('Unit | Serializer | credential library', function (hooks) {
http_method: 'GET',
version: 1,
credential_type: 'ssh_private_key',
- credential_mapping_overrides: [
- { key: 'username_attribute', value: 'user' },
- ],
+ credential_mapping_overrides: { username_attribute: 'user' },
});
const snapshot = record._createSnapshot();
const serializedRecord = serializer.serialize(snapshot);
@@ -64,9 +62,7 @@ module('Unit | Serializer | credential library', function (hooks) {
http_method: 'GET',
version: 1,
credential_type: 'ssh_private_key',
- credential_mapping_overrides: [
- { key: 'private_key_attribute', value: 'test' },
- ],
+ credential_mapping_overrides: { private_key_attribute: 'test' },
},
},
});
diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml
index c73fe5d82..9b91d20b3 100644
--- a/addons/core/translations/resources/en-us.yaml
+++ b/addons/core/translations/resources/en-us.yaml
@@ -913,11 +913,12 @@ credential-library:
ssh_private_key: SSH Private Key
username_password: Username & Password
username_password_domain: Username, Password & Domain
- username_attribute: Username
- password_attribute: Password
- private_key_passphrase_attribute: Private Key Passphrase
- private_key_attribute: Private Key
- domain_attribute: Domain
+ password: Password
+ username_attribute: username_attribute
+ password_attribute: password_attribute
+ private_key_passphrase_attribute: private_key_passphrase_attribute
+ private_key_attribute: private_key_attribute
+ domain_attribute: domain_attribute
actions:
create: New Credential Library
delete: Delete Credential Library
diff --git a/e2e-tests/admin/pages/credential-stores.js b/e2e-tests/admin/pages/credential-stores.js
index f11c88a6f..716021ceb 100644
--- a/e2e-tests/admin/pages/credential-stores.js
+++ b/e2e-tests/admin/pages/credential-stores.js
@@ -308,11 +308,9 @@ export class CredentialStoresPage extends BaseResourcePage {
await this.page.getByRole('link', { name: 'Credential Libraries' }).click();
await this.page.getByRole('link', { name: 'New', exact: true }).click();
await this.page
- .getByLabel('Name (Optional)', { exact: true })
+ .getByLabel('Name', { exact: true })
.fill(credentialLibraryName);
- await this.page
- .getByLabel('Description (Optional)')
- .fill('This is an automated test');
+ await this.page.getByLabel('Description').fill('This is an automated test');
await this.page
.getByRole('group', { name: 'Type' })
.getByLabel('Generic Secrets')
@@ -345,11 +343,9 @@ export class CredentialStoresPage extends BaseResourcePage {
await this.page.getByRole('link', { name: 'New', exact: true }).click();
await this.page
- .getByLabel('Name (Optional)', { exact: true })
+ .getByLabel('Name', { exact: true })
.fill(credentialLibraryName);
- await this.page
- .getByLabel('Description (Optional)')
- .fill('This is an automated test');
+ await this.page.getByLabel('Description').fill('This is an automated test');
await this.page
.getByRole('group', { name: 'Type' })
.getByLabel('SSH Certificates')
diff --git a/e2e-tests/admin/tests/credential-store-vault.spec.js b/e2e-tests/admin/tests/credential-store-vault.spec.js
index fa148d474..3f4c7f413 100644
--- a/e2e-tests/admin/tests/credential-store-vault.spec.js
+++ b/e2e-tests/admin/tests/credential-store-vault.spec.js
@@ -99,11 +99,9 @@ test(
await page.getByRole('link', { name: 'Credential Libraries' }).click();
await page.getByRole('link', { name: 'New', exact: true }).click();
await page
- .getByLabel('Name (Optional)', { exact: true })
+ .getByLabel('Name', { exact: true })
.fill(credentialLibraryName);
- await page
- .getByLabel('Description (Optional)')
- .fill('This is an automated test');
+ await page.getByLabel('Description').fill('This is an automated test');
await page
.getByLabel('Vault Path')
.fill(`${secretsPath}/data/${secretName}`);
diff --git a/ui/admin/app/components/form/credential-library/mapping-overrides/index.hbs b/ui/admin/app/components/form/credential-library/mapping-overrides/index.hbs
index 894013d87..d22d2697e 100644
--- a/ui/admin/app/components/form/credential-library/mapping-overrides/index.hbs
+++ b/ui/admin/app/components/form/credential-library/mapping-overrides/index.hbs
@@ -3,49 +3,36 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
- <:fieldset as |F|>
-
- {{t
- 'resources.credential-library.form.credential_mapping_overrides.label'
- }}
-
-
- {{t
- 'resources.credential-library.form.credential_mapping_overrides.help'
- }}
-
-
- {{#if @model.errors.credential_mapping_overrides}}
-
- {{#each @model.errors.credential_mapping_overrides as |error|}}
- {{error.message}}
- {{/each}}
-
- {{/if}}
-
-
- <:field as |F|>
-
- <:newKey as |N|>
-
-
- <:key as |K|>
-
-
- <:value as |V|>
-
-
-
-
-
\ No newline at end of file
+
+ {{t
+ 'resources.credential-library.form.credential_mapping_overrides.label'
+ }}
+ {{t
+ 'resources.credential-library.form.credential_mapping_overrides.help'
+ }}
+
+ {{#each this.mappingOverrides as |option|}}
+
+ {{t
+ (concat 'resources.credential-library.titles.' option)
+ }}
+
+ {{/each}}
+
+ {{#if @model.errors.credential_mapping_overrides}}
+
+ {{#each @model.errors.credential_mapping_overrides as |error|}}
+ {{error.message}}
+ {{/each}}
+
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/admin/app/components/form/credential-library/mapping-overrides/index.js b/ui/admin/app/components/form/credential-library/mapping-overrides/index.js
index 9d50d724a..cd082393b 100644
--- a/ui/admin/app/components/form/credential-library/mapping-overrides/index.js
+++ b/ui/admin/app/components/form/credential-library/mapping-overrides/index.js
@@ -5,43 +5,11 @@
import Component from '@glimmer/component';
import { options } from 'api/models/credential-library';
-import { action } from '@ember/object';
export default class FormCredentialLibraryMappingOverridesComponent extends Component {
+ // =attributes
+
get mappingOverrides() {
return options.mapping_overrides[this.args.model.credential_type];
}
-
- get allowedEntries() {
- return this.mappingOverrides.length;
- }
-
- /**
- * Prevents users from selecting duplicate keys from the select list if the arg is set to true
- * @type {array}
- */
- get selectOptions() {
- const previouslySelectedKeys =
- this.args.model.credential_mapping_overrides || [];
- if (previouslySelectedKeys.length) {
- return this.mappingOverrides.filter((key) =>
- previouslySelectedKeys.every((obj) => obj.key !== key),
- );
- } else {
- return this.mappingOverrides;
- }
- }
-
- /**
- * Determines if we need to show an empty row to the users to enter more key/value pairs based on removeDuplicates arg,
- * by default it is true
- * @type {object}
- */
- @action
- showNewRow() {
- return (
- this.args.model.credential_mapping_overrides?.length !==
- this.allowedEntries
- );
- }
}
diff --git a/ui/admin/app/components/form/credential-library/radio/index.hbs b/ui/admin/app/components/form/credential-library/radio/index.hbs
index e2bc8fd96..fa209f079 100644
--- a/ui/admin/app/components/form/credential-library/radio/index.hbs
+++ b/ui/admin/app/components/form/credential-library/radio/index.hbs
@@ -5,6 +5,7 @@
diff --git a/ui/admin/app/components/form/credential-library/vault-generic/index.hbs b/ui/admin/app/components/form/credential-library/vault-generic/index.hbs
index f4b61eb27..aaa1725e1 100644
--- a/ui/admin/app/components/form/credential-library/vault-generic/index.hbs
+++ b/ui/admin/app/components/form/credential-library/vault-generic/index.hbs
@@ -14,7 +14,6 @@
name='name'
@value={{@model.name}}
@isInvalid={{@model.errors.name}}
- @isOptional={{true}}
disabled={{form.disabled}}
{{on 'input' (set-from-event @model 'name')}}
as |F|
@@ -36,7 +35,6 @@
name='description'
@value={{@model.description}}
@isInvalid={{@model.errors.description}}
- @isOptional={{true}}
disabled={{form.disabled}}
as |F|
>
@@ -70,7 +68,6 @@
{{/if}}
- {{else}}
+ {{else if @model.credential_type}}
this.server.schema.credentialLibraries.all().models.length;
- getUsernamePasswordDomainCredentialLibraryCount = () => {
- return this.server.schema.credentialLibraries.where({
- credentialType: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
- }).length;
+ getTypeCredentialLibraryCount = (credentialType) => {
+ return this.server.schema.credentialLibraries.where({ credentialType })
+ .length;
};
featuresService = this.owner.lookup('service:features');
});
@@ -100,102 +100,68 @@ module('Acceptance | credential-libraries | create', function (hooks) {
assert.strictEqual(currentURL(), urls.credentialLibrary);
});
- test('can create a new credential library of type vault generic', async function (assert) {
- setRunOptions({
- rules: {
- 'color-contrast': {
- // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-01
- enabled: false,
+ test.each(
+ 'can create a new credential library with credential type for vault generic',
+ options.credential_types,
+ async function (assert, type) {
+ setRunOptions({
+ rules: {
+ 'color-contrast': {
+ // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-26
+ enabled: false,
+ },
},
- },
- });
+ });
- const count = getCredentialLibraryCount();
- await visit(urls.newCredentialLibrary);
+ const credentialLibraryCount = getCredentialLibraryCount();
+ const typeCredentialLibraryCount = getTypeCredentialLibraryCount(type);
+ await visit(urls.newCredentialLibrary);
- await fillIn(commonSelectors.FIELD_NAME, commonSelectors.FIELD_NAME_VALUE);
- await select(
- selectors.FIELD_CRED_TYPE,
- selectors.FIELD_CRED_TYPE_SSH_VALUE,
- );
- await select(
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT,
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT_SSH_VALUE,
- );
- await fillIn(selectors.FIELD_CRED_MAP_OVERRIDES_INPUT, 'key');
- await click(selectors.FIELD_CRED_MAP_OVERRIDES_BTN);
- await click(commonSelectors.SAVE_BTN);
+ await fillIn(
+ selectors.FIELD_VAULT_PATH,
+ selectors.FIELD_VAULT_PATH_VALUE,
+ );
+ await fillIn(
+ commonSelectors.FIELD_NAME,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ await select(selectors.FIELD_CRED_TYPE, type);
- assert.strictEqual(getCredentialLibraryCount(), count + 1);
- const credentialLibrary = this.server.schema.credentialLibraries.findBy({
- name: commonSelectors.FIELD_NAME_VALUE,
- });
- assert.strictEqual(
- credentialLibrary.name,
- commonSelectors.FIELD_NAME_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.credentialType,
- selectors.FIELD_CRED_TYPE_SSH_VALUE,
- );
- assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
- private_key_attribute: 'key',
- });
- });
+ const credentialMappingOverrides = {};
+ options.mapping_overrides[type].forEach(async (overrideField) => {
+ const randName = faker.word.words();
+ credentialMappingOverrides[overrideField] = randName;
+ await fillIn(
+ selectors.FIELD_CRED_MAP_OVERRIDES(overrideField),
+ randName,
+ );
+ });
+ await click(commonSelectors.SAVE_BTN);
- test('can create a new credential library with username, password and domain type for vault generic', async function (assert) {
- setRunOptions({
- rules: {
- 'color-contrast': {
- // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-26
- enabled: false,
- },
- },
- });
+ assert.strictEqual(
+ getCredentialLibraryCount(),
+ credentialLibraryCount + 1,
+ );
+ assert.strictEqual(
+ getTypeCredentialLibraryCount(),
+ typeCredentialLibraryCount + 1,
+ );
- const credentialLibraryCount = getCredentialLibraryCount();
- const usernamePasswordDomainCredentialLibraryCount =
- getUsernamePasswordDomainCredentialLibraryCount();
- await visit(urls.newCredentialLibrary);
+ const credentialLibrary = this.server.schema.credentialLibraries.findBy({
+ credentialType: type,
+ });
- await fillIn(selectors.FIELD_VAULT_PATH, selectors.FIELD_VAULT_PATH_VALUE);
- await fillIn(commonSelectors.FIELD_NAME, commonSelectors.FIELD_NAME_VALUE);
- await select(
- selectors.FIELD_CRED_TYPE,
- selectors.FIELD_CRED_TYPE_UPD_VALUE,
- );
-
- await select(
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT,
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT_DOMAIN_VALUE,
- );
- await fillIn(selectors.FIELD_CRED_MAP_OVERRIDES_INPUT, 'domain');
-
- await click(selectors.FIELD_CRED_MAP_OVERRIDES_BTN);
- await click(commonSelectors.SAVE_BTN);
-
- assert.strictEqual(getCredentialLibraryCount(), credentialLibraryCount + 1);
- assert.strictEqual(
- getUsernamePasswordDomainCredentialLibraryCount(),
- usernamePasswordDomainCredentialLibraryCount + 1,
- );
-
- const credentialLibrary = this.server.schema.credentialLibraries.findBy({
- credentialType: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
- });
-
- assert.strictEqual(
- credentialLibrary.name,
- commonSelectors.FIELD_NAME_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.credentialType,
- selectors.FIELD_CRED_TYPE_UPD_VALUE,
- );
- assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
- domain_attribute: 'domain',
- });
- });
+ assert.strictEqual(
+ credentialLibrary.name,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ assert.strictEqual(credentialLibrary.credentialType, type);
+ assert.deepEqual(
+ credentialLibrary.credentialMappingOverrides,
+ credentialMappingOverrides,
+ );
+ },
+ );
test('can create a new credential library of type vault ssh cert', async function (assert) {
setRunOptions({
diff --git a/ui/admin/tests/acceptance/credential-library/selectors.js b/ui/admin/tests/acceptance/credential-library/selectors.js
index d66b0891d..8b208703e 100644
--- a/ui/admin/tests/acceptance/credential-library/selectors.js
+++ b/ui/admin/tests/acceptance/credential-library/selectors.js
@@ -26,15 +26,7 @@ export const FIELD_TTL_VALUE = 'ttl';
export const FIELD_KEY_ID = '[name=key_id]';
export const FIELD_KEY_ID_VALUE = 'key_id';
-export const FIELD_CRED_MAP_OVERRIDES_SELECT =
- '[name="credential_mapping_overrides"] select';
-export const FIELD_CRED_MAP_OVERRIDES_SELECT_SSH_VALUE =
- 'private_key_attribute';
-export const FIELD_CRED_MAP_OVERRIDES_SELECT_DOMAIN_VALUE = 'domain_attribute';
-export const FIELD_CRED_MAP_OVERRIDES_INPUT =
- '[name="credential_mapping_overrides"] input';
-export const FIELD_CRED_MAP_OVERRIDES_BTN =
- '[name="credential_mapping_overrides"] button';
+export const FIELD_CRED_MAP_OVERRIDES = (field) => `[name=${field}]`;
export const TYPE_VAULT_SSH_CERT = '[value="vault-ssh-certificate"]';
export const TYPE_VAULT_LDAP = '[value="vault-ldap"]';
diff --git a/ui/admin/tests/acceptance/credential-library/update-test.js b/ui/admin/tests/acceptance/credential-library/update-test.js
index 8366c7939..1ea602eaf 100644
--- a/ui/admin/tests/acceptance/credential-library/update-test.js
+++ b/ui/admin/tests/acceptance/credential-library/update-test.js
@@ -4,19 +4,20 @@
*/
import { module, test } from 'qunit';
-import { visit, click, fillIn, currentURL, select } from '@ember/test-helpers';
+import { visit, click, fillIn, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'admin/tests/helpers';
import { setupSqlite } from 'api/test-support/helpers/sqlite';
import { Response } from 'miragejs';
+import { faker } from '@faker-js/faker';
+import * as selectors from './selectors';
+import * as commonSelectors from 'admin/tests/helpers/selectors';
+import { setRunOptions } from 'ember-a11y-testing/test-support';
import {
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
TYPE_CREDENTIAL_LIBRARY_VAULT_LDAP,
} from 'api/models/credential-library';
-import * as selectors from './selectors';
-import * as commonSelectors from 'admin/tests/helpers/selectors';
-import { setRunOptions } from 'ember-a11y-testing/test-support';
-import { TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN } from 'api/models/credential';
+import { options } from 'api/models/credential-library';
module('Acceptance | credential-libraries | update', function (hooks) {
setupApplicationTest(hooks);
@@ -57,17 +58,9 @@ module('Acceptance | credential-libraries | update', function (hooks) {
});
instances.credentialLibrary = this.server.create('credential-library', {
scope: instances.scopes.project,
+ type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
credentialStore: instances.credentialStore,
});
- instances.usernamePasswordDomainCredentialLibrary = this.server.create(
- 'credential-library',
- {
- scope: instances.scopes.project,
- credentialStore: instances.credentialStore,
- type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
- credential_type: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
- },
- );
instances.vaultLDAPCredentialLibrary = this.server.create(
'credential-library',
{
@@ -86,7 +79,6 @@ module('Acceptance | credential-libraries | update', function (hooks) {
urls.credentialLibrary = `${urls.credentialLibraries}/${instances.credentialLibrary.id}`;
urls.newCredentialLibrary = `${urls.credentialLibraries}/new`;
urls.unknownCredentialLibrary = `${urls.credentialLibraries}/foo`;
- urls.usernamePasswordDomainCredentialLibrary = `${urls.credentialLibraries}/${instances.usernamePasswordDomainCredentialLibrary.id}`;
urls.vaultLDAPCredentialLibrary = `${urls.credentialLibraries}/${instances.vaultLDAPCredentialLibrary.id}`;
});
@@ -126,100 +118,67 @@ module('Acceptance | credential-libraries | update', function (hooks) {
.hasValue(instances.credentialLibrary.name);
});
- test('can update a vault generic credential library and save changes', async function (assert) {
- setRunOptions({
- rules: {
- 'color-contrast': {
- // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-01
- enabled: false,
+ test.each(
+ 'can update a vault generic credential library with credential type and save changes',
+ options.credential_types,
+ async function (assert, type) {
+ setRunOptions({
+ rules: {
+ 'color-contrast': {
+ // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-26
+ enabled: false,
+ },
},
- },
- });
+ });
+ instances.credentialLibrary.update({ credentialType: type });
+ await visit(urls.credentialLibraries);
- await visit(urls.credentialLibrary);
+ await click(commonSelectors.HREF(urls.credentialLibrary));
+ await click(commonSelectors.EDIT_BTN);
+ await fillIn(
+ commonSelectors.FIELD_NAME,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ await fillIn(
+ commonSelectors.FIELD_DESCRIPTION,
+ commonSelectors.FIELD_DESCRIPTION_VALUE,
+ );
+ await fillIn(
+ selectors.FIELD_VAULT_PATH,
+ selectors.FIELD_VAULT_PATH_VALUE,
+ );
+ const credentialMappingOverrides = {};
+ options.mapping_overrides[type].forEach(async (overrideField) => {
+ const randName = faker.word.words();
+ credentialMappingOverrides[overrideField] = randName;
+ await fillIn(
+ selectors.FIELD_CRED_MAP_OVERRIDES(overrideField),
+ randName,
+ );
+ });
+ await click(commonSelectors.SAVE_BTN);
- await click(commonSelectors.EDIT_BTN);
- await fillIn(commonSelectors.FIELD_NAME, commonSelectors.FIELD_NAME_VALUE);
- await fillIn(
- commonSelectors.FIELD_DESCRIPTION,
- commonSelectors.FIELD_DESCRIPTION_VALUE,
- );
- await fillIn(selectors.FIELD_VAULT_PATH, selectors.FIELD_VAULT_PATH_VALUE);
- await select(
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT,
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT_SSH_VALUE,
- );
- await fillIn(selectors.FIELD_CRED_MAP_OVERRIDES_INPUT, 'key');
- await click(selectors.FIELD_CRED_MAP_OVERRIDES_BTN);
- await click(commonSelectors.SAVE_BTN);
-
- const credentialLibrary = this.server.schema.credentialLibraries.findBy({
- name: commonSelectors.FIELD_NAME_VALUE,
- });
- assert.strictEqual(
- credentialLibrary.name,
- commonSelectors.FIELD_NAME_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.description,
- commonSelectors.FIELD_DESCRIPTION_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.attributes.path,
- selectors.FIELD_VAULT_PATH_VALUE,
- );
- assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
- private_key_attribute: 'key',
- });
- });
-
- test('can update a vault generic credential library of username, password and domain type and save changes', async function (assert) {
- setRunOptions({
- rules: {
- 'color-contrast': {
- // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2025-08-26
- enabled: false,
- },
- },
- });
-
- await visit(urls.usernamePasswordDomainCredentialLibrary);
-
- await click(commonSelectors.EDIT_BTN);
- await fillIn(commonSelectors.FIELD_NAME, commonSelectors.FIELD_NAME_VALUE);
- await fillIn(
- commonSelectors.FIELD_DESCRIPTION,
- commonSelectors.FIELD_DESCRIPTION_VALUE,
- );
- await fillIn(selectors.FIELD_VAULT_PATH, selectors.FIELD_VAULT_PATH_VALUE);
- await select(
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT,
- selectors.FIELD_CRED_MAP_OVERRIDES_SELECT_DOMAIN_VALUE,
- );
- await fillIn(selectors.FIELD_CRED_MAP_OVERRIDES_INPUT, 'domain');
-
- await click(selectors.FIELD_CRED_MAP_OVERRIDES_BTN);
- await click(commonSelectors.SAVE_BTN);
-
- const credentialLibrary = this.server.schema.credentialLibraries.findBy({
- credentialType: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
- });
- assert.strictEqual(
- credentialLibrary.name,
- commonSelectors.FIELD_NAME_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.description,
- commonSelectors.FIELD_DESCRIPTION_VALUE,
- );
- assert.strictEqual(
- credentialLibrary.attributes.path,
- selectors.FIELD_VAULT_PATH_VALUE,
- );
- assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
- domain_attribute: 'domain',
- });
- });
+ const credentialLibrary = this.server.schema.credentialLibraries.findBy({
+ credentialType: type,
+ });
+ assert.strictEqual(
+ credentialLibrary.name,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ assert.strictEqual(
+ credentialLibrary.description,
+ commonSelectors.FIELD_DESCRIPTION_VALUE,
+ );
+ assert.strictEqual(
+ credentialLibrary.attributes.path,
+ selectors.FIELD_VAULT_PATH_VALUE,
+ );
+ assert.deepEqual(
+ credentialLibrary.credentialMappingOverrides,
+ credentialMappingOverrides,
+ );
+ },
+ );
test('saving an existing credential library with invalid fields displays error messages', async function (assert) {
setRunOptions({
diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss
index e53d43c10..03eb12f01 100644
--- a/ui/desktop/app/styles/app.scss
+++ b/ui/desktop/app/styles/app.scss
@@ -331,6 +331,8 @@
.credential-header {
padding: 1.5rem;
width: 33%;
+ display: flex;
+ flex-direction: column;
}
.credential-secret {