mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	UI: Fix oidc auth method missing default_role field (#28539)
* add auth-config/oidc to openapi model helper * alphabetize * update maskedinput selector to be standard data-test-input * add test * add changelog * fix maskedinput test and kv selector * final textarea selector!
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/28539.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/28539.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | ```release-note:bug | ||||||
|  | ui: fix `default_role` input missing from oidc auth method configuration form | ||||||
|  | ``` | ||||||
| @@ -136,7 +136,6 @@ export function filterPathsByItemType(pathInfo: PathsInfo, itemType: string): Pa | |||||||
|  * This object maps model names to the openAPI path that hydrates the model, given the backend path. |  * This object maps model names to the openAPI path that hydrates the model, given the backend path. | ||||||
|  */ |  */ | ||||||
| const OPENAPI_POWERED_MODELS = { | const OPENAPI_POWERED_MODELS = { | ||||||
|   'role-ssh': (backend: string) => `/v1/${backend}/roles/example?help=1`, |  | ||||||
|   'auth-config/azure': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/azure': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/cert': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/cert': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/gcp': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/gcp': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
| @@ -144,18 +143,20 @@ const OPENAPI_POWERED_MODELS = { | |||||||
|   'auth-config/jwt': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/jwt': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/kubernetes': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/kubernetes': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/ldap': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/ldap': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|  |   'auth-config/oidc': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/okta': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/okta': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'auth-config/radius': (backend: string) => `/v1/auth/${backend}/config?help=1`, |   'auth-config/radius': (backend: string) => `/v1/auth/${backend}/config?help=1`, | ||||||
|   'kmip/config': (backend: string) => `/v1/${backend}/config?help=1`, |   'kmip/config': (backend: string) => `/v1/${backend}/config?help=1`, | ||||||
|   'kmip/role': (backend: string) => `/v1/${backend}/scope/example/role/example?help=1`, |   'kmip/role': (backend: string) => `/v1/${backend}/scope/example/role/example?help=1`, | ||||||
|   'pki/role': (backend: string) => `/v1/${backend}/roles/example?help=1`, |  | ||||||
|   'pki/tidy': (backend: string) => `/v1/${backend}/config/auto-tidy?help=1`, |  | ||||||
|   'pki/sign-intermediate': (backend: string) => `/v1/${backend}/issuer/example/sign-intermediate?help=1`, |  | ||||||
|   'pki/certificate/generate': (backend: string) => `/v1/${backend}/issue/example?help=1`, |   'pki/certificate/generate': (backend: string) => `/v1/${backend}/issue/example?help=1`, | ||||||
|   'pki/certificate/sign': (backend: string) => `/v1/${backend}/sign/example?help=1`, |   'pki/certificate/sign': (backend: string) => `/v1/${backend}/sign/example?help=1`, | ||||||
|   'pki/config/acme': (backend: string) => `/v1/${backend}/config/acme?help=1`, |   'pki/config/acme': (backend: string) => `/v1/${backend}/config/acme?help=1`, | ||||||
|   'pki/config/cluster': (backend: string) => `/v1/${backend}/config/cluster?help=1`, |   'pki/config/cluster': (backend: string) => `/v1/${backend}/config/cluster?help=1`, | ||||||
|   'pki/config/urls': (backend: string) => `/v1/${backend}/config/urls?help=1`, |   'pki/config/urls': (backend: string) => `/v1/${backend}/config/urls?help=1`, | ||||||
|  |   'pki/role': (backend: string) => `/v1/${backend}/roles/example?help=1`, | ||||||
|  |   'pki/sign-intermediate': (backend: string) => `/v1/${backend}/issuer/example/sign-intermediate?help=1`, | ||||||
|  |   'pki/tidy': (backend: string) => `/v1/${backend}/config/auto-tidy?help=1`, | ||||||
|  |   'role-ssh': (backend: string) => `/v1/${backend}/roles/example?help=1`, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export function getHelpUrlForModel(modelType: string, backend: string) { | export function getHelpUrlForModel(modelType: string, backend: string) { | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
|       aria-label={{or @name "masked input"}} |       aria-label={{or @name "masked input"}} | ||||||
|       {{on "change" this.onChange}} |       {{on "change" this.onChange}} | ||||||
|       {{on "keyup" (fn this.handleKeyUp @name)}} |       {{on "keyup" (fn this.handleKeyUp @name)}} | ||||||
|       data-test-textarea={{or @name ""}} |       data-test-input={{or @name ""}} | ||||||
|     /> |     /> | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   {{#if @allowCopy}} |   {{#if @allowCopy}} | ||||||
|   | |||||||
| @@ -18,8 +18,6 @@ import { GENERAL } from 'vault/tests/helpers/general-selectors'; | |||||||
| const SELECTORS = { | const SELECTORS = { | ||||||
|   backendLink: (path) => `[data-test-auth-backend-link="${path}"]`, |   backendLink: (path) => `[data-test-auth-backend-link="${path}"]`, | ||||||
|   createUser: '[data-test-entity-create-link="user"]', |   createUser: '[data-test-entity-create-link="user"]', | ||||||
|   input: (attr) => `[data-test-input="${attr}"]`, |  | ||||||
|   password: '[data-test-textarea]', |  | ||||||
|   saveBtn: '[data-test-save-config]', |   saveBtn: '[data-test-save-config]', | ||||||
|   methods: '[data-test-access-methods] a', |   methods: '[data-test-access-methods] a', | ||||||
|   listItem: '[data-test-list-item-content]', |   listItem: '[data-test-list-item-content]', | ||||||
| @@ -49,8 +47,8 @@ module('Acceptance | auth backend list', function (hooks) { | |||||||
|     await click(SELECTORS.backendLink(this.path1)); |     await click(SELECTORS.backendLink(this.path1)); | ||||||
|     assert.dom(GENERAL.emptyStateTitle).exists('shows empty state'); |     assert.dom(GENERAL.emptyStateTitle).exists('shows empty state'); | ||||||
|     await click(SELECTORS.createUser); |     await click(SELECTORS.createUser); | ||||||
|     await fillIn(SELECTORS.input('username'), this.user1); |     await fillIn(GENERAL.inputByAttr('username'), this.user1); | ||||||
|     await fillIn(SELECTORS.password, this.user1); |     await fillIn(GENERAL.inputByAttr('password'), this.user1); | ||||||
|     await click(SELECTORS.saveBtn); |     await click(SELECTORS.saveBtn); | ||||||
|     assert.strictEqual(currentURL(), `/vault/access/${this.path1}/item/user`); |     assert.strictEqual(currentURL(), `/vault/access/${this.path1}/item/user`); | ||||||
|  |  | ||||||
| @@ -61,8 +59,8 @@ module('Acceptance | auth backend list', function (hooks) { | |||||||
|     await click(SELECTORS.backendLink(this.path2)); |     await click(SELECTORS.backendLink(this.path2)); | ||||||
|     assert.dom(GENERAL.emptyStateTitle).exists('shows empty state'); |     assert.dom(GENERAL.emptyStateTitle).exists('shows empty state'); | ||||||
|     await click(SELECTORS.createUser); |     await click(SELECTORS.createUser); | ||||||
|     await fillIn(SELECTORS.input('username'), this.user2); |     await fillIn(GENERAL.inputByAttr('username'), this.user2); | ||||||
|     await fillIn(SELECTORS.password, this.user2); |     await fillIn(GENERAL.inputByAttr('password'), this.user2); | ||||||
|     await click(SELECTORS.saveBtn); |     await click(SELECTORS.saveBtn); | ||||||
|     assert.strictEqual(currentURL(), `/vault/access/${this.path2}/item/user`); |     assert.strictEqual(currentURL(), `/vault/access/${this.path2}/item/user`); | ||||||
|     // Confirm that the user was created. There was a bug where the apiPath was not being updated when toggling between auth routes. |     // Confirm that the user was created. There was a bug where the apiPath was not being updated when toggling between auth routes. | ||||||
|   | |||||||
							
								
								
									
										216
									
								
								ui/tests/acceptance/auth/enable-tune-form-test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								ui/tests/acceptance/auth/enable-tune-form-test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright (c) HashiCorp, Inc. | ||||||
|  |  * SPDX-License-Identifier: BUSL-1.1 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { module, test } from 'qunit'; | ||||||
|  | import { setupApplicationTest } from 'ember-qunit'; | ||||||
|  | import { v4 as uuidv4 } from 'uuid'; | ||||||
|  |  | ||||||
|  | import { login } from 'vault/tests/helpers/auth/auth-helpers'; | ||||||
|  | import { visit } from '@ember/test-helpers'; | ||||||
|  | import { deleteAuthCmd, runCmd } from 'vault/tests/helpers/commands'; | ||||||
|  | import testHelper from './test-helper'; | ||||||
|  | import { GENERAL } from 'vault/tests/helpers/general-selectors'; | ||||||
|  |  | ||||||
|  | // These models use openAPI so we assert the form inputs using an acceptance test | ||||||
|  | // The default selector is to use GENERAL.inputByAttr() | ||||||
|  | // custom fields should be added to the this.customSelectorss object | ||||||
|  | module('Acceptance | auth enable tune form test', function (hooks) { | ||||||
|  |   setupApplicationTest(hooks); | ||||||
|  |   hooks.beforeEach(async function () { | ||||||
|  |     // these tend to be the same across models because they share the same mount-config model | ||||||
|  |     // if necessary, they can be overridden in the individual module | ||||||
|  |     this.mountFields = [ | ||||||
|  |       'path', | ||||||
|  |       'description', | ||||||
|  |       'local', | ||||||
|  |       'sealWrap', | ||||||
|  |       'config.listingVisibility', | ||||||
|  |       'config.defaultLeaseTtl', | ||||||
|  |       'config.maxLeaseTtl', | ||||||
|  |       'config.tokenType', | ||||||
|  |       'config.auditNonHmacRequestKeys', | ||||||
|  |       'config.auditNonHmacResponseKeys', | ||||||
|  |       'config.passthroughRequestHeaders', | ||||||
|  |       'config.allowedResponseHeaders', | ||||||
|  |       'config.pluginVersion', | ||||||
|  |     ]; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   module('azure', function (hooks) { | ||||||
|  |     hooks.beforeEach(async function () { | ||||||
|  |       this.type = 'azure'; | ||||||
|  |       this.path = `${this.type}-${uuidv4()}`; | ||||||
|  |       this.tuneFields = [ | ||||||
|  |         'environment', | ||||||
|  |         'identityTokenAudience', | ||||||
|  |         'identityTokenTtl', | ||||||
|  |         'maxRetries', | ||||||
|  |         'maxRetryDelay', | ||||||
|  |         'resource', | ||||||
|  |         'retryDelay', | ||||||
|  |         'rootPasswordTtl', | ||||||
|  |         'tenantId', | ||||||
|  |       ]; | ||||||
|  |       this.tuneToggles = { 'Azure Options': ['clientId', 'clientSecret'] }; | ||||||
|  |       await login(); | ||||||
|  |       return visit('/vault/settings/auth/enable'); | ||||||
|  |     }); | ||||||
|  |     hooks.afterEach(async function () { | ||||||
|  |       await runCmd(deleteAuthCmd(this.path), false); | ||||||
|  |     }); | ||||||
|  |     testHelper(test); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   module('jwt', function (hooks) { | ||||||
|  |     hooks.beforeEach(async function () { | ||||||
|  |       this.type = 'jwt'; | ||||||
|  |       this.path = `${this.type}-${uuidv4()}`; | ||||||
|  |       this.customSelectors = { | ||||||
|  |         providerConfig: `${GENERAL.fieldByAttr('providerConfig')} textarea`, | ||||||
|  |       }; | ||||||
|  |       this.tuneFields = [ | ||||||
|  |         'defaultRole', | ||||||
|  |         'jwksCaPem', | ||||||
|  |         'jwksUrl', | ||||||
|  |         'namespaceInState', | ||||||
|  |         'oidcDiscoveryUrl', | ||||||
|  |         'oidcResponseMode', | ||||||
|  |         'oidcResponseTypes', | ||||||
|  |         'providerConfig', | ||||||
|  |         'unsupportedCriticalCertExtensions', | ||||||
|  |       ]; | ||||||
|  |       this.tuneToggles = { | ||||||
|  |         'JWT Options': [ | ||||||
|  |           'oidcClientId', | ||||||
|  |           'oidcClientSecret', | ||||||
|  |           'oidcDiscoveryCaPem', | ||||||
|  |           'jwtValidationPubkeys', | ||||||
|  |           'jwtSupportedAlgs', | ||||||
|  |           'boundIssuer', | ||||||
|  |         ], | ||||||
|  |       }; | ||||||
|  |       await login(); | ||||||
|  |       return visit('/vault/settings/auth/enable'); | ||||||
|  |     }); | ||||||
|  |     hooks.afterEach(async function () { | ||||||
|  |       await runCmd(deleteAuthCmd(this.path), false); | ||||||
|  |     }); | ||||||
|  |     testHelper(test); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   module('ldap', function (hooks) { | ||||||
|  |     hooks.beforeEach(async function () { | ||||||
|  |       this.type = 'ldap'; | ||||||
|  |       this.path = `${this.type}-${uuidv4()}`; | ||||||
|  |       this.tuneFields = [ | ||||||
|  |         'url', | ||||||
|  |         'caseSensitiveNames', | ||||||
|  |         'connectionTimeout', | ||||||
|  |         'dereferenceAliases', | ||||||
|  |         'maxPageSize', | ||||||
|  |         'passwordPolicy', | ||||||
|  |         'requestTimeout', | ||||||
|  |         'tokenBoundCidrs', | ||||||
|  |         'tokenExplicitMaxTtl', | ||||||
|  |         'tokenMaxTtl', | ||||||
|  |         'tokenNoDefaultPolicy', | ||||||
|  |         'tokenNumUses', | ||||||
|  |         'tokenPeriod', | ||||||
|  |         'tokenPolicies', | ||||||
|  |         'tokenTtl', | ||||||
|  |         'tokenType', | ||||||
|  |         'usePre111GroupCnBehavior', | ||||||
|  |         'usernameAsAlias', | ||||||
|  |       ]; | ||||||
|  |       this.tuneToggles = { | ||||||
|  |         'LDAP Options': [ | ||||||
|  |           'starttls', | ||||||
|  |           'insecureTls', | ||||||
|  |           'discoverdn', | ||||||
|  |           'denyNullBind', | ||||||
|  |           'tlsMinVersion', | ||||||
|  |           'tlsMaxVersion', | ||||||
|  |           'certificate', | ||||||
|  |           'clientTlsCert', | ||||||
|  |           'clientTlsKey', | ||||||
|  |           'userattr', | ||||||
|  |           'upndomain', | ||||||
|  |           'anonymousGroupSearch', | ||||||
|  |         ], | ||||||
|  |         'Customize User Search': ['binddn', 'userdn', 'bindpass', 'userfilter'], | ||||||
|  |         'Customize Group Membership Search': ['groupfilter', 'groupattr', 'groupdn', 'useTokenGroups'], | ||||||
|  |       }; | ||||||
|  |       await login(); | ||||||
|  |       return visit('/vault/settings/auth/enable'); | ||||||
|  |     }); | ||||||
|  |     hooks.afterEach(async function () { | ||||||
|  |       await runCmd(deleteAuthCmd(this.path), false); | ||||||
|  |     }); | ||||||
|  |     testHelper(test); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   module('oidc', function (hooks) { | ||||||
|  |     hooks.beforeEach(async function () { | ||||||
|  |       this.type = 'oidc'; | ||||||
|  |       this.path = `${this.type}-${uuidv4()}`; | ||||||
|  |       this.customSelectors = { | ||||||
|  |         providerConfig: `${GENERAL.fieldByAttr('providerConfig')} textarea`, | ||||||
|  |       }; | ||||||
|  |       this.tuneFields = [ | ||||||
|  |         'oidcDiscoveryUrl', | ||||||
|  |         'defaultRole', | ||||||
|  |         'jwksCaPem', | ||||||
|  |         'jwksUrl', | ||||||
|  |         'oidcResponseMode', | ||||||
|  |         'oidcResponseTypes', | ||||||
|  |         'namespaceInState', | ||||||
|  |         'providerConfig', | ||||||
|  |         'unsupportedCriticalCertExtensions', | ||||||
|  |       ]; | ||||||
|  |       this.tuneToggles = { | ||||||
|  |         'OIDC Options': [ | ||||||
|  |           'oidcClientId', | ||||||
|  |           'oidcClientSecret', | ||||||
|  |           'oidcDiscoveryCaPem', | ||||||
|  |           'jwtValidationPubkeys', | ||||||
|  |           'jwtSupportedAlgs', | ||||||
|  |           'boundIssuer', | ||||||
|  |         ], | ||||||
|  |       }; | ||||||
|  |       await login(); | ||||||
|  |       return visit('/vault/settings/auth/enable'); | ||||||
|  |     }); | ||||||
|  |     hooks.afterEach(async function () { | ||||||
|  |       await runCmd(deleteAuthCmd(this.path), false); | ||||||
|  |     }); | ||||||
|  |     testHelper(test); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   module('okta', function (hooks) { | ||||||
|  |     hooks.beforeEach(async function () { | ||||||
|  |       this.type = 'okta'; | ||||||
|  |       this.path = `${this.type}-${uuidv4()}`; | ||||||
|  |       this.tuneFields = [ | ||||||
|  |         'orgName', | ||||||
|  |         'tokenBoundCidrs', | ||||||
|  |         'tokenExplicitMaxTtl', | ||||||
|  |         'tokenMaxTtl', | ||||||
|  |         'tokenNoDefaultPolicy', | ||||||
|  |         'tokenNumUses', | ||||||
|  |         'tokenPeriod', | ||||||
|  |         'tokenPolicies', | ||||||
|  |         'tokenTtl', | ||||||
|  |         'tokenType', | ||||||
|  |       ]; | ||||||
|  |       this.tuneToggles = { Options: ['apiToken', 'baseUrl', 'bypassOktaMfa'] }; | ||||||
|  |       await login(); | ||||||
|  |       return visit('/vault/settings/auth/enable'); | ||||||
|  |     }); | ||||||
|  |     hooks.afterEach(async function () { | ||||||
|  |       await runCmd(deleteAuthCmd(this.path), false); | ||||||
|  |     }); | ||||||
|  |     testHelper(test); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
							
								
								
									
										49
									
								
								ui/tests/acceptance/auth/test-helper.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ui/tests/acceptance/auth/test-helper.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright (c) HashiCorp, Inc. | ||||||
|  |  * SPDX-License-Identifier: BUSL-1.1 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { click, currentURL, fillIn } from '@ember/test-helpers'; | ||||||
|  | import { GENERAL } from 'vault/tests/helpers/general-selectors'; | ||||||
|  |  | ||||||
|  | const SELECTORS = { | ||||||
|  |   mountType: (name) => `[data-test-mount-type="${name}"]`, | ||||||
|  |   submit: '[data-test-mount-submit]', | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const assertFields = (assert, fields, customSelectors = {}) => { | ||||||
|  |   fields.forEach((param) => { | ||||||
|  |     if (Object.keys(customSelectors).includes(param)) { | ||||||
|  |       assert.dom(customSelectors[param]).exists(); | ||||||
|  |     } else { | ||||||
|  |       assert.dom(GENERAL.inputByAttr(param)).exists(); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | export default (test) => { | ||||||
|  |   test('it renders mount fields', async function (assert) { | ||||||
|  |     await click(SELECTORS.mountType(this.type)); | ||||||
|  |     await click(GENERAL.toggleGroup('Method Options')); | ||||||
|  |     assertFields(assert, this.mountFields, this.customSelectors); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   test('it renders tune fields', async function (assert) { | ||||||
|  |     // enable auth method to check tune fields | ||||||
|  |     await click(SELECTORS.mountType(this.type)); | ||||||
|  |     await fillIn(GENERAL.inputByAttr('path'), this.path); | ||||||
|  |     await click(SELECTORS.submit); | ||||||
|  |     assert.strictEqual( | ||||||
|  |       currentURL(), | ||||||
|  |       `/vault/settings/auth/configure/${this.path}/configuration`, | ||||||
|  |       `${this.type}: it mounts navigates to tune form` | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     assertFields(assert, this.tuneFields, this.customSelectors); | ||||||
|  |  | ||||||
|  |     for (const toggle in this.tuneToggles) { | ||||||
|  |       const fields = this.tuneToggles[toggle]; | ||||||
|  |       await click(GENERAL.toggleGroup(toggle)); | ||||||
|  |       assertFields(assert, fields, this.customSelectors); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
| @@ -11,6 +11,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; | |||||||
| import mfaConfigHandler from 'vault/mirage/handlers/mfa-config'; | import mfaConfigHandler from 'vault/mirage/handlers/mfa-config'; | ||||||
| import { Response } from 'miragejs'; | import { Response } from 'miragejs'; | ||||||
| import { underscore } from '@ember/string'; | import { underscore } from '@ember/string'; | ||||||
|  | import { GENERAL } from 'vault/tests/helpers/general-selectors'; | ||||||
|  |  | ||||||
| module('Acceptance | mfa-method', function (hooks) { | module('Acceptance | mfa-method', function (hooks) { | ||||||
|   setupApplicationTest(hooks); |   setupApplicationTest(hooks); | ||||||
| @@ -181,17 +182,10 @@ module('Acceptance | mfa-method', function (hooks) { | |||||||
|         .dom('[data-test-inline-error-message]') |         .dom('[data-test-inline-error-message]') | ||||||
|         .exists({ count: required.length }, `Required field validations display for ${type}`); |         .exists({ count: required.length }, `Required field validations display for ${type}`); | ||||||
|  |  | ||||||
|       for (const [i, field] of required.entries()) { |       for (const field of required) { | ||||||
|         let inputType = 'input'; |         await fillIn(GENERAL.inputByAttr(field), 'foo'); | ||||||
|         // this is less than ideal but updating the test selectors in masked-input break a bunch of tests |  | ||||||
|         // add value to the masked input text area data-test attributes for selection |  | ||||||
|         if (['secret_key', 'integration_key'].includes(field)) { |  | ||||||
|           inputType = 'textarea'; |  | ||||||
|           const textareas = this.element.querySelectorAll('[data-test-textarea]'); |  | ||||||
|           textareas[i].setAttribute('data-test-textarea', field); |  | ||||||
|         } |  | ||||||
|         await fillIn(`[data-test-${inputType}="${field}"]`, 'foo'); |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       await click('[data-test-mfa-create-save]'); |       await click('[data-test-mfa-create-save]'); | ||||||
|       assert.strictEqual( |       assert.strictEqual( | ||||||
|         currentRouteName(), |         currentRouteName(), | ||||||
|   | |||||||
| @@ -59,11 +59,11 @@ module('Acceptance | reset password', function (hooks) { | |||||||
|       ); |       ); | ||||||
|  |  | ||||||
|     assert.dom('[data-test-title]').hasText('Reset password', 'page title'); |     assert.dom('[data-test-title]').hasText('Reset password', 'page title'); | ||||||
|     await fillIn('[data-test-textarea]', 'newpassword'); |     await fillIn('[data-test-input="reset-password"]', 'newpassword'); | ||||||
|     await click('[data-test-reset-password-save]'); |     await click('[data-test-reset-password-save]'); | ||||||
|     await waitFor('[data-test-flash-message]'); |     await waitFor('[data-test-flash-message]'); | ||||||
|     assert.dom('[data-test-flash-message]').hasText(`Success ${SUCCESS_MESSAGE}`); |     assert.dom('[data-test-flash-message]').hasText(`Success ${SUCCESS_MESSAGE}`); | ||||||
|     assert.dom('[data-test-textarea]').hasValue('', 'Resets input after save'); |     assert.dom('[data-test-input="reset-password"]').hasValue('', 'Resets input after save'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('allows password reset for userpass users logged in via tab', async function (assert) { |   test('allows password reset for userpass users logged in via tab', async function (assert) { | ||||||
| @@ -91,10 +91,10 @@ module('Acceptance | reset password', function (hooks) { | |||||||
|       ); |       ); | ||||||
|  |  | ||||||
|     assert.dom('[data-test-title]').hasText('Reset password', 'page title'); |     assert.dom('[data-test-title]').hasText('Reset password', 'page title'); | ||||||
|     await fillIn('[data-test-textarea]', 'newpassword'); |     await fillIn('[data-test-input="reset-password"]', 'newpassword'); | ||||||
|     await click('[data-test-reset-password-save]'); |     await click('[data-test-reset-password-save]'); | ||||||
|     await waitFor('[data-test-flash-message]'); |     await waitFor('[data-test-flash-message]'); | ||||||
|     assert.dom('[data-test-flash-message]').hasText(`Success ${SUCCESS_MESSAGE}`); |     assert.dom('[data-test-flash-message]').hasText(`Success ${SUCCESS_MESSAGE}`); | ||||||
|     assert.dom('[data-test-textarea]').hasValue('', 'Resets input after save'); |     assert.dom('[data-test-input="reset-password"]').hasValue('', 'Resets input after save'); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -368,12 +368,8 @@ module('Acceptance | aws | configuration', function (hooks) { | |||||||
|       // check all the form fields are present |       // check all the form fields are present | ||||||
|       await click(GENERAL.toggleGroup('Root config options')); |       await click(GENERAL.toggleGroup('Root config options')); | ||||||
|       for (const key of expectedConfigKeys('aws-root-create')) { |       for (const key of expectedConfigKeys('aws-root-create')) { | ||||||
|         if (key === 'secretKey') { |  | ||||||
|           assert.dom(GENERAL.maskedInput(key)).exists(`${key} shows for root section.`); |  | ||||||
|         } else { |  | ||||||
|         assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); |         assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); | ||||||
|       } |       } | ||||||
|       } |  | ||||||
|       for (const key of expectedConfigKeys('aws-lease')) { |       for (const key of expectedConfigKeys('aws-lease')) { | ||||||
|         assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); |         assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -86,7 +86,7 @@ module('Acceptance | ssh | configuration', function (hooks) { | |||||||
|       `/vault/secrets/${sshPath}/configuration/edit`, |       `/vault/secrets/${sshPath}/configuration/edit`, | ||||||
|       'after deleting public key stays on edit page' |       'after deleting public key stays on edit page' | ||||||
|     ); |     ); | ||||||
|     assert.dom(GENERAL.maskedInput('privateKey')).hasNoText('Private key is empty and reset'); |     assert.dom(GENERAL.inputByAttr('privateKey')).hasNoText('Private key is empty and reset'); | ||||||
|     assert.dom(GENERAL.inputByAttr('publicKey')).hasNoText('Public key is empty and reset'); |     assert.dom(GENERAL.inputByAttr('publicKey')).hasNoText('Public key is empty and reset'); | ||||||
|     assert.dom(GENERAL.inputByAttr('generateSigningKey')).isChecked('Generate signing key is checked'); |     assert.dom(GENERAL.inputByAttr('generateSigningKey')).isChecked('Generate signing key is checked'); | ||||||
|     await click(SES.viewBackend); |     await click(SES.viewBackend); | ||||||
|   | |||||||
| @@ -87,7 +87,7 @@ module('Acceptance | sync | destination (singular)', function (hooks) { | |||||||
|  |  | ||||||
|     await visit('vault/sync/secrets/destinations/vercel-project/destination-vercel/edit'); |     await visit('vault/sync/secrets/destinations/vercel-project/destination-vercel/edit'); | ||||||
|     await click(ts.enableField('accessToken')); |     await click(ts.enableField('accessToken')); | ||||||
|     await fillIn(ts.maskedInput('accessToken'), 'foobar'); |     await fillIn(GENERAL.inputByAttr('accessToken'), 'foobar'); | ||||||
|     await click(ts.saveButton); |     await click(ts.saveButton); | ||||||
|     await click(ts.toolbar('Edit destination')); |     await click(ts.toolbar('Edit destination')); | ||||||
|     await click(ts.saveButton); |     await click(ts.saveButton); | ||||||
|   | |||||||
| @@ -94,7 +94,6 @@ export const GENERAL = { | |||||||
|   navLink: (label: string) => `[data-test-sidebar-nav-link="${label}"]`, |   navLink: (label: string) => `[data-test-sidebar-nav-link="${label}"]`, | ||||||
|   cancelButton: '[data-test-cancel]', |   cancelButton: '[data-test-cancel]', | ||||||
|   saveButton: '[data-test-save]', |   saveButton: '[data-test-save]', | ||||||
|   maskedInput: (name: string) => `[data-test-textarea="${name}"]`, |  | ||||||
|   codemirror: `[data-test-component="code-mirror-modifier"]`, |   codemirror: `[data-test-component="code-mirror-modifier"]`, | ||||||
|   codemirrorTextarea: `[data-test-component="code-mirror-modifier"] textarea`, |   codemirrorTextarea: `[data-test-component="code-mirror-modifier"] textarea`, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ export const FORM = { | |||||||
|   kvRow: '[data-test-kv-row]', |   kvRow: '[data-test-kv-row]', | ||||||
|   keyInput: (idx = 0) => `[data-test-kv-key="${idx}"]`, |   keyInput: (idx = 0) => `[data-test-kv-key="${idx}"]`, | ||||||
|   valueInput: (idx = 0) => `[data-test-kv-value="${idx}"]`, |   valueInput: (idx = 0) => `[data-test-kv-value="${idx}"]`, | ||||||
|   maskedValueInput: (idx = 0) => `[data-test-kv-value="${idx}"] [data-test-textarea]`, |   maskedValueInput: (idx = 0) => `[data-test-kv-value="${idx}"] [data-test-input]`, | ||||||
|   addRow: (idx = 0) => `[data-test-kv-add-row="${idx}"]`, |   addRow: (idx = 0) => `[data-test-kv-add-row="${idx}"]`, | ||||||
|   deleteRow: (idx = 0) => `[data-test-kv-delete-row="${idx}"]`, |   deleteRow: (idx = 0) => `[data-test-kv-delete-row="${idx}"]`, | ||||||
|   // <KvPatchEditor> |   // <KvPatchEditor> | ||||||
|   | |||||||
| @@ -182,7 +182,7 @@ export const expectedValueOfConfigKeys = (type, string) => { | |||||||
| export const fillInAwsConfig = async (situation = 'withAccess') => { | export const fillInAwsConfig = async (situation = 'withAccess') => { | ||||||
|   if (situation === 'withAccess') { |   if (situation === 'withAccess') { | ||||||
|     await fillIn(GENERAL.inputByAttr('accessKey'), 'foo'); |     await fillIn(GENERAL.inputByAttr('accessKey'), 'foo'); | ||||||
|     await fillIn(GENERAL.maskedInput('secretKey'), 'bar'); |     await fillIn(GENERAL.inputByAttr('secretKey'), 'bar'); | ||||||
|   } |   } | ||||||
|   if (situation === 'withAccessOptions') { |   if (situation === 'withAccessOptions') { | ||||||
|     await click(GENERAL.toggleGroup('Root config options')); |     await click(GENERAL.toggleGroup('Root config options')); | ||||||
|   | |||||||
| @@ -99,11 +99,6 @@ export const PAGE = { | |||||||
|         case 'customTags': |         case 'customTags': | ||||||
|           await fillIn('[data-test-kv-key="0"]', 'foo'); |           await fillIn('[data-test-kv-key="0"]', 'foo'); | ||||||
|           return fillIn('[data-test-kv-value="0"]', value); |           return fillIn('[data-test-kv-value="0"]', value); | ||||||
|         case 'accessKeyId': |  | ||||||
|         case 'secretAccessKey': |  | ||||||
|         case 'clientSecret': |  | ||||||
|         case 'accessToken': |  | ||||||
|           return fillIn(GENERAL.maskedInput(attr), value); |  | ||||||
|         case 'deploymentEnvironments': |         case 'deploymentEnvironments': | ||||||
|           await click('[data-test-input="deploymentEnvironments"] input#development'); |           await click('[data-test-input="deploymentEnvironments"] input#development'); | ||||||
|           await click('[data-test-input="deploymentEnvironments"] input#preview'); |           await click('[data-test-input="deploymentEnvironments"] input#preview'); | ||||||
|   | |||||||
| @@ -6,13 +6,16 @@ | |||||||
| import { module, test } from 'qunit'; | import { module, test } from 'qunit'; | ||||||
| import { setupRenderingTest } from 'ember-qunit'; | import { setupRenderingTest } from 'ember-qunit'; | ||||||
| import { render, focus, triggerKeyEvent, typeIn, fillIn, click } from '@ember/test-helpers'; | import { render, focus, triggerKeyEvent, typeIn, fillIn, click } from '@ember/test-helpers'; | ||||||
| import { create } from 'ember-cli-page-object'; |  | ||||||
| import hbs from 'htmlbars-inline-precompile'; | import hbs from 'htmlbars-inline-precompile'; | ||||||
| import sinon from 'sinon'; | import sinon from 'sinon'; | ||||||
| import maskedInput from 'vault/tests/pages/components/masked-input'; |  | ||||||
|  |  | ||||||
| const component = create(maskedInput); |  | ||||||
|  |  | ||||||
|  | const SELECTORS = { | ||||||
|  |   copyBtn: '[data-test-copy-button]', | ||||||
|  |   downloadBtn: '[data-test-download-button]', | ||||||
|  |   toggle: '[data-test-button="toggle-masked"]', | ||||||
|  |   downloadIcon: '[data-test-download-icon]', | ||||||
|  |   stringify: '[data-test-stringify-toggle]', | ||||||
|  | }; | ||||||
| module('Integration | Component | masked input', function (hooks) { | module('Integration | Component | masked input', function (hooks) { | ||||||
|   setupRenderingTest(hooks); |   setupRenderingTest(hooks); | ||||||
|  |  | ||||||
| @@ -26,14 +29,14 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|   test('it renders', async function (assert) { |   test('it renders', async function (assert) { | ||||||
|     await render(hbs`<MaskedInput />`); |     await render(hbs`<MaskedInput />`); | ||||||
|     assert.dom('[data-test-masked-input]').exists('shows masked input'); |     assert.dom('[data-test-masked-input]').exists('shows masked input'); | ||||||
|     assert.ok(component.textareaIsPresent); |     assert.dom('textarea').exists(); | ||||||
|     assert.dom('[data-test-textarea]').hasClass('masked-font', 'it renders an input with obscure font'); |     assert.dom('textarea').hasClass('masked-font', 'it renders an input with obscure font'); | ||||||
|     assert.notOk(component.copyButtonIsPresent, 'does not render copy button by default'); |     assert.dom(SELECTORS.copyBtn).doesNotExist('does not render copy button by default'); | ||||||
|     assert.notOk(component.downloadButtonIsPresent, 'does not render download button by default'); |     assert.dom('[data-test-download-button]').doesNotExist('does not render download button by default'); | ||||||
|  |  | ||||||
|     await component.toggleMasked(); |     await click(SELECTORS.toggle); | ||||||
|     assert.dom('.masked-value').doesNotHaveClass('masked-font', 'it unmasks when show button is clicked'); |     assert.dom('.masked-value').doesNotHaveClass('masked-font', 'it unmasks when show button is clicked'); | ||||||
|     await component.toggleMasked(); |     await click(SELECTORS.toggle); | ||||||
|     assert.dom('.masked-value').hasClass('masked-font', 'it remasks text when button is clicked'); |     assert.dom('.masked-value').hasClass('masked-font', 'it remasks text when button is clicked'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -42,21 +45,21 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|     await render(hbs`<MaskedInput @displayOnly={{true}} @value={{this.value}} />`); |     await render(hbs`<MaskedInput @displayOnly={{true}} @value={{this.value}} />`); | ||||||
|  |  | ||||||
|     assert.dom('.masked-value').hasClass('masked-font', 'value has obscured font'); |     assert.dom('.masked-value').hasClass('masked-font', 'value has obscured font'); | ||||||
|     assert.notOk(component.textareaIsPresent, 'it does not render a textarea when displayOnly is true'); |     assert.dom('textarea').doesNotExist('it does not render a textarea when displayOnly is true'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it renders a copy button when allowCopy is true', async function (assert) { |   test('it renders a copy button when allowCopy is true', async function (assert) { | ||||||
|     this.set('value', { some: 'object' }); |     this.set('value', { some: 'object' }); | ||||||
|     await render(hbs`<MaskedInput @allowCopy={{true}} @value={{this.value}} />`); |     await render(hbs`<MaskedInput @allowCopy={{true}} @value={{this.value}} />`); | ||||||
|     assert.ok(component.copyButtonIsPresent); |     assert.dom(SELECTORS.copyBtn).exists(); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it renders a download button when allowDownload is true', async function (assert) { |   test('it renders a download button when allowDownload is true', async function (assert) { | ||||||
|     await render(hbs`<MaskedInput @allowDownload={{true}} /> `); |     await render(hbs`<MaskedInput @allowDownload={{true}} /> `); | ||||||
|     assert.ok(component.downloadIconIsPresent); |     assert.dom(SELECTORS.downloadIcon).exists(); | ||||||
|  |  | ||||||
|     await click('[data-test-download-icon]'); |     await click(SELECTORS.downloadIcon); | ||||||
|     assert.ok(component.downloadButtonIsPresent, 'clicking download icon opens modal with download button'); |     assert.dom(SELECTORS.downloadBtn).exists('clicking download icon opens modal with download button'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it shortens all outputs when displayOnly and masked', async function (assert) { |   test('it shortens all outputs when displayOnly and masked', async function (assert) { | ||||||
| @@ -65,7 +68,7 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|     const maskedValue = document.querySelector('.masked-value').innerText; |     const maskedValue = document.querySelector('.masked-value').innerText; | ||||||
|     assert.strictEqual(maskedValue.length, 11); |     assert.strictEqual(maskedValue.length, 11); | ||||||
|  |  | ||||||
|     await component.toggleMasked(); |     await click(SELECTORS.toggle); | ||||||
|     const unMaskedValue = document.querySelector('.masked-value').innerText; |     const unMaskedValue = document.querySelector('.masked-value').innerText; | ||||||
|     assert.strictEqual(unMaskedValue.length, this.value.length); |     assert.strictEqual(unMaskedValue.length, this.value.length); | ||||||
|   }); |   }); | ||||||
| @@ -83,7 +86,7 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|     this.set('value', 'before'); |     this.set('value', 'before'); | ||||||
|     this.set('onChange', changeSpy); |     this.set('onChange', changeSpy); | ||||||
|     await render(hbs`<MaskedInput @value={{this.value}} @onChange={{this.onChange}} />`); |     await render(hbs`<MaskedInput @value={{this.value}} @onChange={{this.onChange}} />`); | ||||||
|     await fillIn('[data-test-textarea]', 'after'); |     await fillIn('textarea', 'after'); | ||||||
|     assert.true(changeSpy.calledWith('after')); |     assert.true(changeSpy.calledWith('after')); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -92,7 +95,7 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|     this.set('value', ''); |     this.set('value', ''); | ||||||
|     this.set('onKeyUp', keyupSpy); |     this.set('onKeyUp', keyupSpy); | ||||||
|     await render(hbs`<MaskedInput @name="foo" @value={{this.value}} @onKeyUp={{this.onKeyUp}} />`); |     await render(hbs`<MaskedInput @name="foo" @value={{this.value}} @onKeyUp={{this.onKeyUp}} />`); | ||||||
|     await typeIn('[data-test-textarea]', 'baz'); |     await typeIn('textarea', 'baz'); | ||||||
|     assert.true(keyupSpy.calledThrice, 'calls for each letter of typing'); |     assert.true(keyupSpy.calledThrice, 'calls for each letter of typing'); | ||||||
|     assert.true(keyupSpy.firstCall.calledWithExactly('foo', 'b')); |     assert.true(keyupSpy.firstCall.calledWithExactly('foo', 'b')); | ||||||
|     assert.true(keyupSpy.secondCall.calledWithExactly('foo', 'ba')); |     assert.true(keyupSpy.secondCall.calledWithExactly('foo', 'ba')); | ||||||
| @@ -102,8 +105,8 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|   test('it does not remove value on tab', async function (assert) { |   test('it does not remove value on tab', async function (assert) { | ||||||
|     this.set('value', 'hello'); |     this.set('value', 'hello'); | ||||||
|     await render(hbs`<MaskedInput @value={{this.value}} />`); |     await render(hbs`<MaskedInput @value={{this.value}} />`); | ||||||
|     await triggerKeyEvent('[data-test-textarea]', 'keydown', 9); |     await triggerKeyEvent('textarea', 'keydown', 9); | ||||||
|     await component.toggleMasked(); |     await click(SELECTORS.toggle); | ||||||
|     const unMaskedValue = document.querySelector('.masked-value').value; |     const unMaskedValue = document.querySelector('.masked-value').value; | ||||||
|     assert.strictEqual(unMaskedValue, this.value); |     assert.strictEqual(unMaskedValue, this.value); | ||||||
|   }); |   }); | ||||||
| @@ -119,11 +122,11 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|       /> |       /> | ||||||
|     `); |     `); | ||||||
|     assert.dom('[data-test-masked-input]').exists('shows masked input'); |     assert.dom('[data-test-masked-input]').exists('shows masked input'); | ||||||
|     assert.ok(component.copyButtonIsPresent); |     assert.dom(SELECTORS.copyBtn).exists(); | ||||||
|     assert.ok(component.downloadIconIsPresent); |     assert.dom(SELECTORS.downloadIcon).exists(); | ||||||
|     assert.dom('[data-test-button="toggle-masked"]').exists('shows toggle mask button'); |     assert.dom(SELECTORS.toggle).exists('shows toggle mask button'); | ||||||
|  |  | ||||||
|     await component.toggleMasked(); |     await click(SELECTORS.toggle); | ||||||
|     assert.dom('.masked-value').doesNotHaveClass('masked-font', 'it unmasks when show button is clicked'); |     assert.dom('.masked-value').doesNotHaveClass('masked-font', 'it unmasks when show button is clicked'); | ||||||
|     assert |     assert | ||||||
|       .dom('[data-test-icon="minus"]') |       .dom('[data-test-icon="minus"]') | ||||||
| @@ -154,12 +157,12 @@ module('Integration | Component | masked input', function (hooks) { | |||||||
|       /> |       /> | ||||||
|     `); |     `); | ||||||
|  |  | ||||||
|     await click('[data-test-download-icon]'); |     await click(SELECTORS.downloadIcon); | ||||||
|     assert.dom('[data-test-stringify-toggle]').isNotChecked('Stringify toggle off as default'); |     assert.dom(SELECTORS.stringify).isNotChecked('Stringify toggle off as default'); | ||||||
|     await click('[data-test-download-button]'); |     await click(SELECTORS.downloadBtn); | ||||||
|  |  | ||||||
|     await click('[data-test-download-icon]'); |     await click(SELECTORS.downloadIcon); | ||||||
|     await click('[data-test-stringify-toggle]'); |     await click(SELECTORS.stringify); | ||||||
|     await click('[data-test-download-button]'); |     await click(SELECTORS.downloadBtn); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ const S = { | |||||||
|   infoBanner: '[data-test-current-user-banner]', |   infoBanner: '[data-test-current-user-banner]', | ||||||
|   save: '[data-test-reset-password-save]', |   save: '[data-test-reset-password-save]', | ||||||
|   error: '[data-test-reset-password-error]', |   error: '[data-test-reset-password-error]', | ||||||
|   input: '[data-test-textarea]', |   input: '[data-test-input="reset-password"]', | ||||||
| }; | }; | ||||||
| module('Integration | Component | page/userpass-reset-password', function (hooks) { | module('Integration | Component | page/userpass-reset-password', function (hooks) { | ||||||
|   setupRenderingTest(hooks); |   setupRenderingTest(hooks); | ||||||
|   | |||||||
| @@ -69,12 +69,8 @@ module('Integration | Component | SecretEngine/ConfigureAws', function (hooks) { | |||||||
|         // check all the form fields are present |         // check all the form fields are present | ||||||
|         await click(GENERAL.toggleGroup('Root config options')); |         await click(GENERAL.toggleGroup('Root config options')); | ||||||
|         for (const key of expectedConfigKeys('aws-root-create')) { |         for (const key of expectedConfigKeys('aws-root-create')) { | ||||||
|           if (key === 'secretKey') { |  | ||||||
|             assert.dom(GENERAL.maskedInput(key)).exists(`${key} shows for root section.`); |  | ||||||
|           } else { |  | ||||||
|           assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); |           assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         for (const key of expectedConfigKeys('aws-lease')) { |         for (const key of expectedConfigKeys('aws-lease')) { | ||||||
|           assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); |           assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); | ||||||
|         } |         } | ||||||
| @@ -94,12 +90,8 @@ module('Integration | Component | SecretEngine/ConfigureAws', function (hooks) { | |||||||
|         } |         } | ||||||
|         // check iam fields do not show |         // check iam fields do not show | ||||||
|         for (const key of expectedConfigKeys('aws-root-create-iam')) { |         for (const key of expectedConfigKeys('aws-root-create-iam')) { | ||||||
|           if (key === 'secretKey') { |  | ||||||
|             assert.dom(GENERAL.maskedInput(key)).doesNotExist(`${key} does not show when wif is selected.`); |  | ||||||
|           } else { |  | ||||||
|           assert.dom(GENERAL.inputByAttr(key)).doesNotExist(`${key} does not show when wif is selected.`); |           assert.dom(GENERAL.inputByAttr(key)).doesNotExist(`${key} does not show when wif is selected.`); | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|       }); |       }); | ||||||
|  |  | ||||||
|       test('it clears wif/iam inputs after toggling accessType', async function (assert) { |       test('it clears wif/iam inputs after toggling accessType', async function (assert) { | ||||||
| @@ -113,7 +105,7 @@ module('Integration | Component | SecretEngine/ConfigureAws', function (hooks) { | |||||||
|           .dom(GENERAL.inputByAttr('accessKey')) |           .dom(GENERAL.inputByAttr('accessKey')) | ||||||
|           .hasValue('', 'accessKey is cleared after toggling accessType'); |           .hasValue('', 'accessKey is cleared after toggling accessType'); | ||||||
|         assert |         assert | ||||||
|           .dom(GENERAL.maskedInput('secretKey')) |           .dom(GENERAL.inputByAttr('secretKey')) | ||||||
|           .hasValue('', 'secretKey is cleared after toggling accessType'); |           .hasValue('', 'secretKey is cleared after toggling accessType'); | ||||||
|  |  | ||||||
|         await click(SES.aws.accessType('wif')); |         await click(SES.aws.accessType('wif')); | ||||||
| @@ -435,12 +427,8 @@ module('Integration | Component | SecretEngine/ConfigureAws', function (hooks) { | |||||||
|         // check all the form fields are present |         // check all the form fields are present | ||||||
|         await click(GENERAL.toggleGroup('Root config options')); |         await click(GENERAL.toggleGroup('Root config options')); | ||||||
|         for (const key of expectedConfigKeys('aws-root-create')) { |         for (const key of expectedConfigKeys('aws-root-create')) { | ||||||
|           if (key === 'secretKey') { |  | ||||||
|             assert.dom(GENERAL.maskedInput(key)).exists(`${key} shows for root section.`); |  | ||||||
|           } else { |  | ||||||
|           assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); |           assert.dom(GENERAL.inputByAttr(key)).exists(`${key} shows for root section.`); | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         for (const key of expectedConfigKeys('aws-lease')) { |         for (const key of expectedConfigKeys('aws-lease')) { | ||||||
|           assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); |           assert.dom(`[data-test-ttl-form-label="${key}"]`).exists(`${key} shows for Lease section.`); | ||||||
|         } |         } | ||||||
| @@ -559,7 +547,7 @@ module('Integration | Component | SecretEngine/ConfigureAws', function (hooks) { | |||||||
|  |  | ||||||
|         await click(GENERAL.enableField('secretKey')); |         await click(GENERAL.enableField('secretKey')); | ||||||
|         await click('[data-test-button="toggle-masked"]'); |         await click('[data-test-button="toggle-masked"]'); | ||||||
|         await fillIn(GENERAL.maskedInput('secretKey'), 'new-secret'); |         await fillIn(GENERAL.inputByAttr('secretKey'), 'new-secret'); | ||||||
|         await click(GENERAL.saveButton); |         await click(GENERAL.saveButton); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ module('Integration | Component | SecretEngine/configure-ssh', function (hooks) | |||||||
|     @id={{this.id}} |     @id={{this.id}} | ||||||
|   /> |   /> | ||||||
|     `); |     `); | ||||||
|     assert.dom(GENERAL.maskedInput('privateKey')).hasNoText('Private key is empty and reset'); |     assert.dom(GENERAL.inputByAttr('privateKey')).hasNoText('Private key is empty and reset'); | ||||||
|     assert.dom(GENERAL.inputByAttr('publicKey')).hasNoText('Public key is empty and reset'); |     assert.dom(GENERAL.inputByAttr('publicKey')).hasNoText('Public key is empty and reset'); | ||||||
|     assert |     assert | ||||||
|       .dom(GENERAL.inputByAttr('generateSigningKey')) |       .dom(GENERAL.inputByAttr('generateSigningKey')) | ||||||
|   | |||||||
| @@ -183,9 +183,9 @@ module('Integration | Component | sync | Secrets::Page::Destinations::CreateAndE | |||||||
|  |  | ||||||
|     await this.renderFormComponent(); |     await this.renderFormComponent(); | ||||||
|     await click(PAGE.enableField('accessKeyId')); |     await click(PAGE.enableField('accessKeyId')); | ||||||
|     await click(PAGE.maskedInput('accessKeyId')); // click on input but do not change value |     await click(PAGE.inputByAttr('accessKeyId')); // click on input but do not change value | ||||||
|     await click(PAGE.enableField('secretAccessKey')); |     await click(PAGE.enableField('secretAccessKey')); | ||||||
|     await fillIn(PAGE.maskedInput('secretAccessKey'), 'new-secret'); |     await fillIn(PAGE.inputByAttr('secretAccessKey'), 'new-secret'); | ||||||
|     await click(PAGE.saveButton); |     await click(PAGE.saveButton); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -277,10 +277,10 @@ module('Integration | Component | sync | Secrets::Page::Destinations::CreateAndE | |||||||
|         // iterate over the form fields and filter for those that are obfuscated |         // iterate over the form fields and filter for those that are obfuscated | ||||||
|         // fill those in and assert that they are masked |         // fill those in and assert that they are masked | ||||||
|         filteredObfuscatedFields.forEach(async (field) => { |         filteredObfuscatedFields.forEach(async (field) => { | ||||||
|           await fillIn(PAGE.maskedInput(field.name), 'blah'); |           await fillIn(PAGE.inputByAttr(field.name), 'blah'); | ||||||
|  |  | ||||||
|           assert |           assert | ||||||
|             .dom(PAGE.maskedInput(field.name)) |             .dom(PAGE.inputByAttr(field.name)) | ||||||
|             .hasClass('masked-font', `it renders ${field.name} for ${destination} with masked font`); |             .hasClass('masked-font', `it renders ${field.name} for ${destination} with masked font`); | ||||||
|           assert |           assert | ||||||
|             .dom(PAGE.form.enableInput(field.name)) |             .dom(PAGE.form.enableInput(field.name)) | ||||||
|   | |||||||
| @@ -1,15 +0,0 @@ | |||||||
| /** |  | ||||||
|  * Copyright (c) HashiCorp, Inc. |  | ||||||
|  * SPDX-License-Identifier: BUSL-1.1 |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| import { clickable, isPresent } from 'ember-cli-page-object'; |  | ||||||
|  |  | ||||||
| export default { |  | ||||||
|   textareaIsPresent: isPresent('[data-test-textarea]'), |  | ||||||
|   copyButtonIsPresent: isPresent('[data-test-copy-button]'), |  | ||||||
|   downloadIconIsPresent: isPresent('[data-test-download-icon]'), |  | ||||||
|   downloadButtonIsPresent: isPresent('[data-test-download-button]'), |  | ||||||
|   toggleMasked: clickable('[data-test-button="toggle-masked"]'), |  | ||||||
|   copyValue: clickable('[data-test-copy-button]'), |  | ||||||
| }; |  | ||||||
		Reference in New Issue
	
	Block a user
	 claire bontempo
					claire bontempo