Auth test selector cleanup (#30283)

* first pass of selector cleanup

* fix control group test
This commit is contained in:
claire bontempo 2025-04-17 10:38:57 -07:00 committed by GitHub
parent c4cfa371c1
commit d7e2b7bcd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 136 additions and 192 deletions

View File

@ -18,7 +18,7 @@
id="role"
class="input"
type="text"
data-test-role
data-test-input="role"
/>
</div>
<AlertInline
@ -33,7 +33,7 @@
<Hds::Button
@text="Sign in with SAML provider"
@icon={{if @disabled "loading"}}
data-test-auth-submit={{true}}
data-test-auth-submit
type="submit"
disabled={{@disabled}}
id="auth-submit"

View File

@ -64,7 +64,7 @@
<div class="field">
<div class="control">
<input
data-test-auth-form-ns-input
data-test-input="namespace"
value={{this.namespaceInput}}
placeholder={{if this.flags.hvdManagedNamespaceRoot "/ (Default)" "/ (Root)"}}
{{on "input" this.handleNamespaceUpdate}}

View File

@ -19,7 +19,7 @@
class="input"
value={{@customPath}}
oninput={{action @onPathChange value="target.value"}}
data-test-auth-form-mount-path
data-test-input="path"
/>
</div>
<AlertInline

View File

@ -108,7 +108,7 @@
name="token"
id="token"
class="input"
data-test-token={{true}}
data-test-input="token"
autocomplete="off"
spellcheck="false"
/>
@ -125,7 +125,7 @@
class="input"
autocomplete="off"
spellcheck="false"
data-test-token={{true}}
data-test-input="token"
id="token"
/>
</div>
@ -141,7 +141,7 @@
class="input"
autocomplete="off"
spellcheck="false"
data-test-username
data-test-input="username"
/>
</div>
</div>
@ -156,7 +156,7 @@
class="input"
autocomplete="off"
spellcheck="false"
data-test-password
data-test-input="password"
/>
</div>
</div>

View File

@ -17,7 +17,7 @@
class="input"
type="text"
{{on "input" this.onRoleInput}}
data-test-role
data-test-input="role"
/>
</div>
<AlertInline
@ -38,7 +38,7 @@
class="input"
autocomplete="off"
spellcheck="false"
data-test-jwt
data-test-input="jwt"
/>
</div>
</div>

View File

@ -59,7 +59,7 @@
</label>
<div class="control">
<Input
data-test-token-input
data-test-input="token"
class="input"
autocomplete="off"
spellcheck="false"

View File

@ -45,10 +45,10 @@ module('Acceptance | auth', function (hooks) {
test('it clears token when changing selected auth method', async function (assert) {
await visit('/vault/auth');
await fillIn(AUTH_FORM.input('token'), 'token');
await fillIn(GENERAL.inputByAttr('token'), 'token');
await fillIn(AUTH_FORM.method, 'github');
await fillIn(AUTH_FORM.method, 'token');
assert.dom(AUTH_FORM.input('token')).hasNoValue('it clears the token value when toggling methods');
assert.dom(GENERAL.inputByAttr('token')).hasNoValue('it clears the token value when toggling methods');
});
module('it sends the right payload when authenticating', function (hooks) {
@ -169,15 +169,14 @@ module('Acceptance | auth', function (hooks) {
if (type !== 'token') {
// set custom mount
await click('[data-test-auth-form-options-toggle]');
await fillIn('[data-test-auth-form-mount-path]', `custom-${type}`);
await click(AUTH_FORM.moreOptions);
await fillIn(GENERAL.inputByAttr('path'), `custom-${type}`);
}
backend.formAttributes.forEach(async (key) => {
for (const key of backend.formAttributes) {
// fill in all form items, except JWT which is not rendered
if (key === 'jwt') return;
await fillIn(`[data-test-${key}]`, `some-${key}`);
});
await fillIn(GENERAL.inputByAttr(key), `some-${key}`);
}
await click(AUTH_FORM.login);
});
}
@ -197,7 +196,7 @@ module('Acceptance | auth', function (hooks) {
},
{ timing: 1000 }
);
await visit('/vault/auth');
await visit('/vault/auth?with=token');
await fillIn(AUTH_FORM.method, 'token');
await click('[data-test-auth-submit]');
});
@ -248,8 +247,8 @@ module('Acceptance | auth', function (hooks) {
const inputValues = {
username: user,
password: user,
'auth-form-mount-path': userpass,
'auth-form-ns-input': ns,
path: userpass,
namespace: ns,
};
// login as user just to get token (this is the only way to generate a token in the UI right now..)
@ -277,7 +276,7 @@ module('Acceptance | auth', function (hooks) {
// cleanup
await visit(`/vault/logout?namespace=${ns}`);
await fillIn(AUTH_FORM.namespaceInput, ''); // clear login form namespace input
await fillIn(GENERAL.inputByAttr('namespace'), ''); // clear login form namespace input
await login();
await runCmd([`delete sys/namespaces/${ns}`], false);
});
@ -294,7 +293,7 @@ module('Acceptance | auth', function (hooks) {
);
return { errors: ['permission denied'] };
});
await typeIn(AUTH_FORM.namespaceInput, 'admin');
await typeIn(GENERAL.inputByAttr('namespace'), 'admin');
});
});
});

View File

@ -69,7 +69,7 @@ for (const method of AUTH_METHOD_MAP) {
assert.dom(AUTH_FORM.form).exists('clicking back returns to auth form');
assert.dom(GENERAL.selectByAttr('auth-method')).hasValue(authType, 'preserves method type on back');
for (const field of loginKeys) {
assert.dom(AUTH_FORM.input(field)).hasValue('', `${field} input clears on back`);
assert.dom(GENERAL.inputByAttr(field)).hasValue('', `${field} input clears on back`);
}
});
@ -82,10 +82,7 @@ for (const method of AUTH_METHOD_MAP) {
// Fill in login form
await fillIn(AUTH_FORM.method, authType);
// Toggle more options to input a custom mount path
await fillInLoginFields(
{ ...options.loginData, 'auth-form-mount-path': this.mountPath },
{ toggleOptions: true }
);
await fillInLoginFields({ ...options.loginData, path: this.mountPath }, { toggleOptions: true });
if (options?.hasPopupWindow) {
// fires "message" event which methods that rely on popup windows wait for
@ -105,7 +102,7 @@ for (const method of AUTH_METHOD_MAP) {
assert.dom(AUTH_FORM.form).exists('clicking back returns to auth form');
assert.dom(GENERAL.selectByAttr('auth-method')).hasValue(authType, 'preserves method type on back');
for (const field of loginKeys) {
assert.dom(AUTH_FORM.input(field)).hasValue('', `${field} input clears on back`);
assert.dom(GENERAL.inputByAttr(field)).hasValue('', `${field} input clears on back`);
}
});
@ -154,10 +151,7 @@ for (const method of AUTH_METHOD_MAP) {
// Fill in login form
await fillIn(AUTH_FORM.method, authType);
// Toggle more options to input a custom mount path
await fillInLoginFields(
{ ...options.loginData, 'auth-form-mount-path': this.mountPath },
{ toggleOptions: true }
);
await fillInLoginFields({ ...options.loginData, path: this.mountPath }, { toggleOptions: true });
if (options?.hasPopupWindow) {
// fires "message" event which methods that rely on popup windows wait for

View File

@ -3,21 +3,21 @@
* SPDX-License-Identifier: BUSL-1.1
*/
import { settled, currentURL, currentRouteName, visit, waitUntil } from '@ember/test-helpers';
import { settled, currentURL, currentRouteName, visit, waitUntil, fillIn, click } from '@ember/test-helpers';
import { module, test, skip } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { create } from 'ember-cli-page-object';
import { storageKey } from 'vault/services/control-group';
import authForm from 'vault/tests/pages/components/auth-form';
import controlGroup from 'vault/tests/pages/components/control-group';
import controlGroupSuccess from 'vault/tests/pages/components/control-group-success';
import { writeSecret } from 'vault/tests/helpers/kv/kv-run-commands';
import authPage from 'vault/tests/pages/auth';
import { setRunOptions } from 'ember-a11y-testing/test-support';
import { runCmd } from 'vault/tests/helpers/commands';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
const authFormComponent = create(authForm);
const controlGroupComponent = create(controlGroup);
const controlGroupSuccessComponent = create(controlGroupSuccess);
@ -149,12 +149,9 @@ module('Acceptance | Enterprise | control groups', function (hooks) {
// and authorize the control group request
await visit('/vault/auth?with=userpass');
await authFormComponent.username(ADMIN_USER);
await settled();
await authFormComponent.password(ADMIN_PASSWORD);
await settled();
await authFormComponent.login();
await settled();
await fillIn(GENERAL.inputByAttr('username'), ADMIN_USER);
await fillIn(GENERAL.inputByAttr('password'), ADMIN_PASSWORD);
await click(AUTH_FORM.login);
await visit(`/vault/access/control-groups/${accessor}`);
// putting here to help with flaky test

View File

@ -9,6 +9,7 @@ import { setupApplicationTest } from 'ember-qunit';
import { runCmd, createNS } from 'vault/tests/helpers/commands';
import authPage from 'vault/tests/pages/auth';
import logout from 'vault/tests/pages/logout';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
module('Acceptance | Enterprise | namespaces', function (hooks) {
setupApplicationTest(hooks);
@ -71,9 +72,7 @@ module('Acceptance | Enterprise | namespaces', function (hooks) {
await logout.visit();
assert.strictEqual(currentURL(), '/vault/auth?with=token', 'Does not redirect');
assert.dom('[data-test-namespace-toolbar]').exists('Normal namespace toolbar exists');
assert
.dom('[data-test-managed-namespace-root]')
.doesNotExist('Managed namespace indicator does not exist');
assert.dom(AUTH_FORM.managedNsRoot).doesNotExist('Managed namespace indicator does not exist');
assert.dom('input#namespace').hasAttribute('placeholder', '/ (Root)');
await fillIn('input#namespace', '/foo/bar ');
const encodedNamespace = encodeURIComponent('foo/bar');

View File

@ -10,6 +10,8 @@ import { setupMirage } from 'ember-cli-mirage/test-support';
import sinon from 'sinon';
import { Response } from 'miragejs';
import { ERROR_JWT_LOGIN } from 'vault/components/auth-jwt';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
module('Acceptance | jwt auth method', function (hooks) {
setupApplicationTest(hooks);
@ -43,10 +45,10 @@ module('Acceptance | jwt auth method', function (hooks) {
});
await visit('/vault/auth');
await fillIn('[data-test-select="auth-method"]', 'jwt');
assert.dom('[data-test-role]').exists({ count: 1 }, 'Role input exists');
assert.dom('[data-test-jwt]').exists({ count: 1 }, 'JWT input exists');
await fillIn('[data-test-jwt]', 'my-test-jwt-token');
await click('[data-test-auth-submit]');
assert.dom(GENERAL.inputByAttr('role')).exists({ count: 1 }, 'Role input exists');
assert.dom(GENERAL.inputByAttr('jwt')).exists({ count: 1 }, 'JWT input exists');
await fillIn(GENERAL.inputByAttr('jwt'), 'my-test-jwt-token');
await click(AUTH_FORM.login);
assert.dom('[data-test-message-error]').exists('Failed login');
});
@ -61,12 +63,12 @@ module('Acceptance | jwt auth method', function (hooks) {
});
await visit('/vault/auth');
await fillIn('[data-test-select="auth-method"]', 'jwt');
assert.dom('[data-test-role]').exists({ count: 1 }, 'Role input exists');
assert.dom('[data-test-jwt]').exists({ count: 1 }, 'JWT input exists');
await fillIn('[data-test-role]', 'some-role');
await fillIn('[data-test-jwt]', 'my-test-jwt-token');
assert.dom('[data-test-jwt]').exists({ count: 1 }, 'JWT input exists');
await click('[data-test-auth-submit]');
assert.dom(GENERAL.inputByAttr('role')).exists({ count: 1 }, 'Role input exists');
assert.dom(GENERAL.inputByAttr('jwt')).exists({ count: 1 }, 'JWT input exists');
await fillIn(GENERAL.inputByAttr('role'), 'some-role');
await fillIn(GENERAL.inputByAttr('jwt'), 'my-test-jwt-token');
assert.dom(GENERAL.inputByAttr('jwt')).exists({ count: 1 }, 'JWT input exists');
await click(AUTH_FORM.login);
assert.dom('[data-test-message-error]').exists('Failed login');
});
@ -88,11 +90,11 @@ module('Acceptance | jwt auth method', function (hooks) {
});
await visit('/vault/auth');
await click('[data-test-auth-method-link="jwt"]');
assert.dom('[data-test-role]').exists({ count: 1 }, 'Role input exists');
assert.dom('[data-test-jwt]').exists({ count: 1 }, 'JWT input exists');
await fillIn('[data-test-role]', 'some-role');
await fillIn('[data-test-jwt]', 'my-test-jwt-token');
await click('[data-test-auth-submit]');
assert.dom(GENERAL.inputByAttr('role')).exists({ count: 1 }, 'Role input exists');
assert.dom(GENERAL.inputByAttr('jwt')).exists({ count: 1 }, 'JWT input exists');
await fillIn(GENERAL.inputByAttr('role'), 'some-role');
await fillIn(GENERAL.inputByAttr('jwt'), 'my-test-jwt-token');
await click(AUTH_FORM.login);
assert.dom('[data-test-message-error]').exists('Failed login');
});
});

View File

@ -8,6 +8,7 @@ import { currentURL, visit, fillIn } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { getManagedNamespace } from 'vault/routes/vault/cluster';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
module('Acceptance | Enterprise | Managed namespace root', function (hooks) {
setupApplicationTest(hooks);
@ -24,7 +25,7 @@ module('Acceptance | Enterprise | Managed namespace root', function (hooks) {
assert.ok(currentURL().startsWith('/vault/auth'), 'Redirected to auth');
assert.ok(currentURL().includes('?namespace=admin'), 'with base namespace');
assert.dom('[data-test-namespace-toolbar]').exists('Namespace toolbar exists');
assert.dom('[data-test-managed-namespace-root]').hasText('/admin', 'Shows /admin namespace prefix');
assert.dom(AUTH_FORM.managedNsRoot).hasText('/admin', 'Shows /admin namespace prefix');
assert.dom('input#namespace').hasAttribute('placeholder', '/ (Default)');
await fillIn('input#namespace', '/foo');
const encodedNamespace = encodeURIComponent('admin/foo');
@ -64,7 +65,7 @@ module('Acceptance | Enterprise | Managed namespace root', function (hooks) {
'with appended namespace'
);
assert.dom('[data-test-managed-namespace-root]').hasText('/admin', 'Shows /admin namespace prefix');
assert.dom(AUTH_FORM.managedNsRoot).hasText('/admin', 'Shows /admin namespace prefix');
assert.dom('input#namespace').hasValue('/admindev', 'Input has /dev value');
});
});

View File

@ -8,7 +8,7 @@ import { setupApplicationTest } from 'ember-qunit';
import { click, currentRouteName, fillIn, visit, waitUntil, find, waitFor } from '@ember/test-helpers';
import { setupMirage } from 'ember-cli-mirage/test-support';
import mfaLoginHandler, { validationHandler } from '../../mirage/handlers/mfa-login';
import { GENERAL } from '../helpers/general-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
module('Acceptance | mfa-login', function (hooks) {
setupApplicationTest(hooks);
@ -32,8 +32,8 @@ module('Acceptance | mfa-login', function (hooks) {
const login = async (user) => {
await visit('/vault/auth?with=token');
await fillIn('[data-test-select="auth-method"]', 'userpass');
await fillIn('[data-test-username]', user);
await fillIn('[data-test-password]', 'test');
await fillIn(GENERAL.inputByAttr('username'), user);
await fillIn(GENERAL.inputByAttr('password'), 'test');
await click('[data-test-auth-submit]');
};
const didLogin = async (assert) => {

View File

@ -127,11 +127,11 @@ module('Acceptance | oidc auth method', function (hooks) {
});
await this.selectMethod('oidc');
assert.dom('[data-test-jwt]').doesNotExist('JWT Token input hidden for OIDC');
assert.dom(GENERAL.inputByAttr('jwt')).doesNotExist('JWT Token input hidden for OIDC');
await this.selectMethod('jwt');
assert.dom('[data-test-jwt]').exists('JWT Token input renders for JWT configured method');
assert.dom(GENERAL.inputByAttr('jwt')).exists('JWT Token input renders for JWT configured method');
await click('[data-test-auth-form-options-toggle]');
await fillIn('[data-test-auth-form-mount-path]', 'foo');
await fillIn(GENERAL.inputByAttr('path'), 'foo');
assert.strictEqual(reqCount, 3, 'Role is fetched when dependant values are changed');
});
@ -147,7 +147,7 @@ module('Acceptance | oidc auth method', function (hooks) {
await click('[data-test-auth-submit]');
assert.dom('[data-test-message-error-description]').hasText('Invalid role. Please try again.');
await fillIn('[data-test-role]', 'test');
await fillIn(GENERAL.inputByAttr('role'), 'test');
await click('[data-test-auth-submit]');
assert.dom('[data-test-message-error-description]').hasText('Error fetching role: permission denied');
});

View File

@ -3,21 +3,19 @@
* SPDX-License-Identifier: BUSL-1.1
*/
import { create } from 'ember-cli-page-object';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { v4 as uuidv4 } from 'uuid';
import authPage from 'vault/tests/pages/auth';
import logout from 'vault/tests/pages/logout';
import authForm from 'vault/tests/pages/components/auth-form';
import enablePage from 'vault/tests/pages/settings/auth/enable';
import { visit, settled, currentURL, waitFor, currentRouteName } from '@ember/test-helpers';
import { visit, settled, currentURL, waitFor, currentRouteName, fillIn, click } from '@ember/test-helpers';
import { clearRecord } from 'vault/tests/helpers/oidc-config';
import { runCmd } from 'vault/tests/helpers/commands';
import queryParamString from 'vault/utils/query-param-string';
const authFormComponent = create(authForm);
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
const OIDC_USER = 'end-user';
const USER_PASSWORD = 'mypassword';
@ -159,11 +157,10 @@ module('Acceptance | oidc provider', function (hooks) {
'Once you log in, you will be redirected back to your application. If you require login credentials, contact your administrator.',
'Has updated text for client authorization flow'
);
await authFormComponent.selectMethod(authMethodPath);
await authFormComponent.username(OIDC_USER);
await authFormComponent.password(USER_PASSWORD);
await authFormComponent.login();
await settled();
await fillIn(AUTH_FORM.method, authMethodPath);
await fillIn(GENERAL.inputByAttr('username'), OIDC_USER);
await fillIn(GENERAL.inputByAttr('password'), USER_PASSWORD);
await click(AUTH_FORM.login);
assert.strictEqual(currentURL(), url, 'URL is as expected after login');
assert
.dom('[data-test-oidc-redirect]')
@ -189,26 +186,25 @@ module('Acceptance | oidc provider', function (hooks) {
currentURL().includes('prompt=login'),
'Url params no longer include prompt=login after redirect'
);
await authFormComponent.selectMethod(authMethodPath);
await authFormComponent.username(OIDC_USER);
await authFormComponent.password(USER_PASSWORD);
await authFormComponent.login();
await settled();
await fillIn(AUTH_FORM.method, authMethodPath);
await fillIn(GENERAL.inputByAttr('username'), OIDC_USER);
await fillIn(GENERAL.inputByAttr('password'), USER_PASSWORD);
await click(AUTH_FORM.login);
assert
.dom('[data-test-oidc-redirect]')
.hasTextContaining(`click here to go back to app`, 'Shows link back to app');
const link = document.querySelector('[data-test-oidc-redirect]').getAttribute('href');
assert.ok(link.includes('/callback?code='), 'Redirects to correct url');
assert.true(link.includes('/callback?code='), 'Redirects to correct url');
});
test('OIDC Provider shows consent form when prompt = consent', async function (assert) {
const { providerName, callback, clientId, authMethodPath } = this.oidcSetupInformation;
const url = getAuthzUrl(providerName, callback, clientId, { prompt: 'consent' });
await logout.visit();
await authFormComponent.selectMethod(authMethodPath);
await authFormComponent.username(OIDC_USER);
await authFormComponent.password(USER_PASSWORD);
await authFormComponent.login();
await fillIn(AUTH_FORM.method, authMethodPath);
await fillIn(GENERAL.inputByAttr('username'), OIDC_USER);
await fillIn(GENERAL.inputByAttr('password'), USER_PASSWORD);
await click(AUTH_FORM.login);
await visit(url);
assert.notOk(

View File

@ -11,6 +11,7 @@ import { Response } from 'miragejs';
import authPage from 'vault/tests/pages/auth';
import { windowStub } from 'vault/tests/helpers/oidc-window-stub';
import { setupTotpMfaResponse } from 'vault/tests/helpers/mfa/mfa-helpers';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
module('Acceptance | enterprise saml auth method', function (hooks) {
setupApplicationTest(hooks);
@ -129,19 +130,19 @@ module('Acceptance | enterprise saml auth method', function (hooks) {
// select saml auth type
await waitUntil(() => find('[data-test-select="auth-method"]'));
await fillIn('[data-test-select="auth-method"]', 'saml');
await fillIn('[data-test-auth-form-ns-input]', 'some-ns');
await fillIn(GENERAL.inputByAttr('namespace'), 'some-ns');
await click('[data-test-auth-submit]');
assert
.dom('[data-test-message-error-description]')
.hasText("missing required 'role' parameter", 'shows API error from role fetch');
await fillIn('[data-test-role]', 'my-role');
await fillIn(GENERAL.inputByAttr('role'), 'my-role');
await click('[data-test-auth-submit]');
assert
.dom('[data-test-message-error-description]')
.hasText('something went wrong', 'shows API error from login attempt');
await fillIn('[data-test-auth-form-ns-input]', '');
await fillIn(GENERAL.inputByAttr('namespace'), '');
await click('[data-test-auth-submit]');
});

View File

@ -10,12 +10,10 @@ export const AUTH_FORM = {
tabs: (method: string) => (method ? `[data-test-auth-method="${method}"]` : '[data-test-auth-method]'),
tabBtn: (method: string) => `[data-test-auth-method="${method}"] button`,
description: '[data-test-description]',
roleInput: '[data-test-role]',
input: (item: string) => `[data-test-${item}]`, // i.e. jwt, role, token, password or username
mountPathInput: '[data-test-auth-form-mount-path]',
// old form toggle, will eventually be deleted
moreOptions: '[data-test-auth-form-options-toggle]',
// new toggle, hds component is a button
advancedSettings: '[data-test-auth-form-options-toggle] button',
namespaceInput: '[data-test-auth-form-ns-input]',
managedNsRoot: '[data-test-managed-namespace-root]',
logo: '[data-test-auth-logo]',
helpText: '[data-test-auth-helptext]',

View File

@ -6,6 +6,7 @@
import { click, fillIn, visit } from '@ember/test-helpers';
import VAULT_KEYS from 'vault/tests/helpers/vault-keys';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { Server } from 'miragejs';
const { rootToken } = VAULT_KEYS;
@ -24,7 +25,7 @@ export const login = async (token = rootToken) => {
// make sure we're always logged out and logged back in
await logout();
await visit('/vault/auth?with=token');
await fillIn(AUTH_FORM.input('token'), token);
await fillIn(GENERAL.inputByAttr('token'), token);
return click(AUTH_FORM.login);
};
@ -32,8 +33,8 @@ export const loginNs = async (ns: string, token = rootToken) => {
// make sure we're always logged out and logged back in
await logout();
await visit('/vault/auth?with=token');
await fillIn(AUTH_FORM.namespaceInput, ns);
await fillIn(AUTH_FORM.input('token'), token);
await fillIn(GENERAL.inputByAttr('namespace'), ns);
await fillIn(GENERAL.inputByAttr('token'), token);
return click(AUTH_FORM.login);
};
@ -57,15 +58,15 @@ interface LoginFields {
password?: string;
token?: string;
role?: string;
'auth-form-mount-path': string; // todo update selectors
'auth-form-ns-input': string; // todo update selectors
path: string;
namespace: string;
}
export const fillInLoginFields = async (loginFields: LoginFields, { toggleOptions = false } = {}) => {
if (toggleOptions) await click(AUTH_FORM.moreOptions);
for (const [input, value] of Object.entries(loginFields)) {
await fillIn(AUTH_FORM.input(input), value);
await fillIn(GENERAL.inputByAttr(input), value);
}
};

View File

@ -37,7 +37,7 @@ module('Integration | Component | auth form', function (hooks) {
test('it calls performAuth on submit', async function (assert) {
await this.renderComponent();
await fillIn(AUTH_FORM.input('token'), '123token');
await fillIn(GENERAL.inputByAttr('token'), '123token');
await click(AUTH_FORM.login);
const [type, data] = this.performAuth.lastCall.args;
assert.strictEqual(type, 'token', 'performAuth is called with type');
@ -183,11 +183,11 @@ module('Integration | Component | auth form', function (hooks) {
await this.renderComponent();
await fillIn(GENERAL.selectByAttr('auth-method'), 'oidc');
await fillIn(AUTH_FORM.input('role'), 'foo');
await fillIn(GENERAL.inputByAttr('role'), 'foo');
await click(AUTH_FORM.moreOptions);
await fillIn(AUTH_FORM.input('role'), 'foo');
await fillIn(AUTH_FORM.mountPathInput, 'foo-oidc');
assert.dom(AUTH_FORM.input('role')).hasValue('foo', 'role is retained when mount path is changed');
await fillIn(GENERAL.inputByAttr('role'), 'foo');
await fillIn(GENERAL.inputByAttr('path'), 'foo-oidc');
assert.dom(GENERAL.inputByAttr('role')).hasValue('foo', 'role is retained when mount path is changed');
await click(AUTH_FORM.login);
});
});

View File

@ -6,19 +6,16 @@
import { _cancelTimers as cancelTimers } from '@ember/runloop';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { fillIn, render, settled, waitUntil } from '@ember/test-helpers';
import { click, fillIn, render, settled, waitUntil } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import { resolve } from 'rsvp';
import { create } from 'ember-cli-page-object';
import form from '../../pages/components/auth-jwt';
import { ERROR_JWT_LOGIN } from 'vault/components/auth-jwt';
import { callbackData } from 'vault/tests/helpers/oidc-window-stub';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { overrideResponse } from 'vault/tests/helpers/stubs';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
const component = create(form);
import { GENERAL } from 'vault/tests/helpers/general-selectors';
const renderIt = async (context, { path = 'jwt', type = 'jwt' } = {}) => {
const handler = (data, e) => {
@ -78,7 +75,7 @@ module('Integration | Component | auth jwt', function (hooks) {
test('it renders the yield', async function (assert) {
await render(hbs`<AuthJwt @onSubmit={{action (mut this.submit)}}>Hello!</AuthJwt>`);
assert.strictEqual(component.yieldContent, 'Hello!', 'yields properly');
assert.dom('[data-test-yield-content]').hasText('Hello!', 'yields properly');
});
test('it fetches auth_url when type changes', async function (assert) {
@ -119,8 +116,8 @@ module('Integration | Component | auth jwt', function (hooks) {
await renderIt(this);
await settled();
assert.strictEqual(postCount, 1, 'request to the default path is made');
assert.ok(component.jwtPresent, 'renders jwt field');
assert.ok(component.rolePresent, 'renders jwt field');
assert.dom(GENERAL.inputByAttr('jwt')).exists();
assert.dom(GENERAL.inputByAttr('role')).exists();
this.set('selectedAuthPath', 'foo');
await settled();
@ -129,7 +126,7 @@ module('Integration | Component | auth jwt', function (hooks) {
test('jwt: it calls passed action on login', async function (assert) {
await renderIt(this);
await component.login();
await click(AUTH_FORM.login);
assert.ok(this.handler.calledOnce);
});
@ -145,12 +142,12 @@ module('Integration | Component | auth jwt', function (hooks) {
});
await renderIt(this, { path: 'foo', type: 'oidc' });
await settled();
await fillIn(AUTH_FORM.roleInput, 'test');
await fillIn(GENERAL.inputByAttr('role'), 'test');
assert
.dom(AUTH_FORM.input('jwt'))
.dom(GENERAL.inputByAttr('jwt'))
.doesNotExist('does not show jwt token input if role matches OIDC login url');
assert.dom(AUTH_FORM.login).hasText('Sign in with OIDC Provider');
await fillIn(AUTH_FORM.roleInput, 'okta');
await fillIn(GENERAL.inputByAttr('role'), 'okta');
// 1 for initial render, 1 for each time role changed = 3
assert.strictEqual(postCount, 3, 'fetches the auth_url when the role changes');
assert.dom(AUTH_FORM.login).hasText('Sign in with Okta', 'recognizes auth methods with certain urls');
@ -176,8 +173,8 @@ module('Integration | Component | auth jwt', function (hooks) {
test('oidc: it calls window.open popup window on login', async function (assert) {
sinon.replaceGetter(window, 'screen', () => ({ height: 600, width: 500 }));
await renderIt(this, { path: 'foo', type: 'oidc' });
await component.role('test');
component.login();
await fillIn(GENERAL.inputByAttr('role'), 'test');
await click(AUTH_FORM.login);
await waitUntil(() => {
return this.windowStub.calledOnce;
});
@ -205,8 +202,8 @@ module('Integration | Component | auth jwt', function (hooks) {
window.addEventListener('message', assertEvent);
await renderIt(this, { path: 'foo', type: 'oidc' });
await component.role('test');
component.login();
await fillIn(GENERAL.inputByAttr('role'), 'test');
await click(AUTH_FORM.login);
await waitUntil(() => {
return this.windowStub.calledOnce;
});
@ -231,8 +228,8 @@ module('Integration | Component | auth jwt', function (hooks) {
window.addEventListener('message', assertEvent);
await renderIt(this, { path: 'foo', type: 'oidc' });
await component.role('test');
component.login();
await fillIn(GENERAL.inputByAttr('role'), 'test');
await click(AUTH_FORM.login);
await waitUntil(() => {
return this.windowStub.calledOnce;
});
@ -249,8 +246,8 @@ module('Integration | Component | auth jwt', function (hooks) {
test('oidc: it should trigger error callback when role is not found', async function (assert) {
await renderIt(this, { path: 'oidc', type: 'oidc' });
await component.role('foo');
await component.login();
await fillIn(GENERAL.inputByAttr('role'), 'foo');
await click(AUTH_FORM.login);
assert.strictEqual(
this.error,
'Invalid role. Please try again.',
@ -260,8 +257,8 @@ module('Integration | Component | auth jwt', function (hooks) {
test('oidc: it should trigger error callback when role is returned without auth_url', async function (assert) {
await renderIt(this, { path: 'oidc', type: 'oidc' });
await component.role('bar');
await component.login();
await fillIn(GENERAL.inputByAttr('role'), 'bar');
await click(AUTH_FORM.login);
assert.strictEqual(
this.error,
'Missing auth_url. Please check that allowed_redirect_uris for the role include this mount path.',

View File

@ -91,8 +91,8 @@ module('Integration | Component | auth | login-form', function (hooks) {
});
await this.renderComponent();
await fillIn(AUTH_FORM.input('username'), 'sandy');
await fillIn(AUTH_FORM.input('password'), '1234');
await fillIn(GENERAL.inputByAttr('username'), 'sandy');
await fillIn(GENERAL.inputByAttr('password'), '1234');
await click(AUTH_FORM.login);
const [actual] = authenticateStub.lastCall.args;
const expectedArgs = {
@ -123,7 +123,7 @@ module('Integration | Component | auth | login-form', function (hooks) {
});
await this.renderComponent();
await fillIn(AUTH_FORM.input('token'), 'mytoken');
await fillIn(GENERAL.inputByAttr('token'), 'mytoken');
await click(AUTH_FORM.login);
const [authResponse, backendType, data] = this.onSuccess.lastCall.args;
const expected = { isRoot: false, namespace: '', token: 'vault-token☃1' };
@ -191,8 +191,8 @@ module('Integration | Component | auth | login-form', function (hooks) {
await this.renderComponent();
await fillIn(GENERAL.selectByAttr('auth-method'), 'okta');
await fillIn(AUTH_FORM.input('username'), 'foo');
await fillIn(AUTH_FORM.input('password'), 'bar');
await fillIn(GENERAL.inputByAttr('username'), 'foo');
await fillIn(GENERAL.inputByAttr('password'), 'bar');
await click(AUTH_FORM.login);
assert
.dom('[data-test-okta-number-challenge]')

View File

@ -11,6 +11,7 @@ import sinon from 'sinon';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { AUTH_FORM } from 'vault/tests/helpers/auth/auth-form-selectors';
import { fillInLoginFields } from 'vault/tests/helpers/auth/auth-helpers';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
module('Integration | Component | auth | page', function (hooks) {
setupRenderingTest(hooks);
@ -57,14 +58,14 @@ module('Integration | Component | auth | page', function (hooks) {
this.version.features = ['Namespaces'];
await this.renderComponent();
assert.dom(AUTH_FORM.logo).exists();
assert.dom(AUTH_FORM.namespaceInput).isDisabled();
assert.dom(GENERAL.inputByAttr('namespace')).isDisabled();
});
test('it calls onNamespaceUpdate', async function (assert) {
assert.expect(1);
this.version.features = ['Namespaces'];
await this.renderComponent();
await fillIn(AUTH_FORM.namespaceInput, 'mynamespace');
await fillIn(GENERAL.inputByAttr('namespace'), 'mynamespace');
const [actual] = this.onNamespaceUpdate.lastCall.args;
assert.strictEqual(actual, 'mynamespace', `onNamespaceUpdate called with: ${actual}`);
});
@ -76,8 +77,8 @@ module('Integration | Component | auth | page', function (hooks) {
this.nsQp = 'admin';
await this.renderComponent();
assert.dom(AUTH_FORM.namespaceInput).hasValue('');
await fillIn(AUTH_FORM.namespaceInput, 'mynamespace');
assert.dom(GENERAL.inputByAttr('namespace')).hasValue('');
await fillIn(GENERAL.inputByAttr('namespace'), 'mynamespace');
const [actual] = this.onNamespaceUpdate.lastCall.args;
assert.strictEqual(actual, 'mynamespace', `onNamespaceUpdate called with: ${actual}`);
});
@ -126,7 +127,7 @@ module('Integration | Component | auth | page', function (hooks) {
assert.expect(1);
const customPath = `${authType}-custom`;
const { loginData, url } = options;
const loginDataWithPath = { ...loginData, 'auth-form-mount-path': customPath };
const loginDataWithPath = { ...loginData, path: customPath };
// pass custom path to request URL
const requestUrl = url({ path: customPath, username: loginData?.username });
this.authRequest(requestUrl);

View File

@ -9,12 +9,12 @@ import { click, fillIn, find, render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import { setRunOptions } from 'ember-a11y-testing/test-support';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
const SELECTORS = {
jsonViewer: '[data-test-json-viewer]',
navigate: '[data-test-navigate-button]',
navMessage: '[data-test-navigate-message]',
tokenInput: '[data-test-token-input]',
unwrap: '[data-test-unwrap-button]',
unwrapForm: '[data-test-unwrap-form]',
};
@ -67,7 +67,7 @@ module('Integration | Component | control group success', function (hooks) {
assert.expect(2);
await render(hbs`<ControlGroupSuccess @model={{this.model}} />`);
assert.dom(SELECTORS.unwrapForm).exists();
assert.dom(SELECTORS.tokenInput).hasValue('');
assert.dom(GENERAL.inputByAttr('token')).hasValue('');
});
test('it unwraps data on submit', async function (assert) {
@ -76,9 +76,9 @@ module('Integration | Component | control group success', function (hooks) {
sinon.stub(this.owner.lookup('service:api').sys, 'unwrap').resolves({ data: { foo: 'bar' } });
await render(hbs`<ControlGroupSuccess @model={{this.model}} />`);
assert.dom(SELECTORS.tokenInput).hasValue('');
assert.dom(GENERAL.inputByAttr('token')).hasValue('');
await fillIn(SELECTORS.tokenInput, 'token');
await fillIn(GENERAL.inputByAttr('token'), 'token');
await click(SELECTORS.unwrap);
const actual = find(SELECTORS.jsonViewer).innerText;

View File

@ -13,12 +13,12 @@ export default create({
visit: visitable('/vault/auth'),
logout: visitable('/vault/logout'),
submit: clickable('[data-test-auth-submit]'),
tokenInput: fillable('[data-test-token]'),
usernameInput: fillable('[data-test-username]'),
passwordInput: fillable('[data-test-password]'),
namespaceInput: fillable('[data-test-auth-form-ns-input]'),
tokenInput: fillable('[data-test-input="token"]'),
usernameInput: fillable('[data-test-input="username"]'),
passwordInput: fillable('[data-test-input="password"]'),
namespaceInput: fillable('[data-test-input="namespace"]'),
optionsToggle: clickable('[data-test-auth-form-options-toggle]'),
mountPath: fillable('[data-test-auth-form-mount-path]'),
mountPath: fillable('[data-test-input="path"]'),
authType: fillable('[data-test-select="auth-method"]'),
login: async function (token = rootToken) {

View File

@ -1,25 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { collection, clickable, fillable, text, value, isPresent } from 'ember-cli-page-object';
export default {
tabs: collection('[data-test-auth-method]', {
name: text(),
link: clickable('[data-test-auth-method-link]'),
}),
selectMethod: fillable('[data-test-select=auth-method]'),
username: fillable('[data-test-username]'),
token: fillable('[data-test-token]'),
tokenValue: value('[data-test-token]'),
password: fillable('[data-test-password]'),
errorText: text('[data-test-message-error]'),
errorMessagePresent: isPresent('[data-test-message-error]'),
descriptionText: text('[data-test-description]'),
login: clickable('[data-test-auth-submit]'),
oidcRole: fillable('[data-test-role]'),
oidcMoreOptions: clickable('[data-test-yield-content] button'),
oidcMountPath: fillable('#custom-path'),
};

View File

@ -1,16 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { text, isPresent, clickable, fillable } from 'ember-cli-page-object';
export default {
jwt: fillable('[data-test-jwt]'),
jwtPresent: isPresent('[data-test-jwt]'),
role: fillable('[data-test-role]'),
rolePresent: isPresent('[data-test-role]'),
login: clickable('[data-test-auth-submit]'),
loginButtonText: text('[data-test-auth-submit]'),
yieldContent: text('[data-test-yield-content]'),
};

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: BUSL-1.1
*/
import { isPresent, fillable, clickable } from 'ember-cli-page-object';
import { isPresent, clickable } from 'ember-cli-page-object';
export default {
showsJsonViewer: isPresent('[data-test-json-viewer]'),
@ -11,5 +11,4 @@ export default {
showsUnwrapForm: isPresent('[data-test-unwrap-form]'),
navigate: clickable('[data-test-navigate-button]'),
unwrap: clickable('[data-test-unwrap-button]'),
token: fillable('[data-test-token-input]'),
};