Prep for Ember data: misc #2 (#24791)

* consolidate policies tests, remove page  object for policies in favor of string selectors

* auth list test fix

* clean up pki-configuration test and only use error.errors if contents are string

* use mirage for version on landing page dashboard test

* changes not needed for upgrade but good clean up work.

* revert pki workflow changes

* remove unused test selector

* remove change to keep cleaner file count.

* add check on control groups

* remove space causing test problems

* use uuid for database backend name

---------

Co-authored-by: Chelsea Shaw <cshaw@hashicorp.com>
This commit is contained in:
Angel Garbarino 2024-01-11 10:55:26 -08:00 committed by GitHub
parent 6f5a7a9e8c
commit bde8b3b283
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 139 additions and 160 deletions

View File

@ -5,7 +5,7 @@
// accepts an error and returns error.errors joined with a comma, error.message or a fallback message
export default function (error, fallbackMessage = 'An error occurred, please try again') {
if (error instanceof Error && error?.errors) {
if (error instanceof Error && error?.errors && typeof error.errors[0] === 'string') {
return error.errors.join(', ');
}
return error?.message || fallbackMessage;

View File

@ -37,6 +37,14 @@ export default function (server) {
};
});
server.get('/sys/internal/ui/version', function () {
return {
data: {
version: '1.9.0+ent',
},
};
});
server.get('/sys/license/status', function () {
return {
data: {

View File

@ -34,14 +34,12 @@ module('Acceptance | auth backend list', function (hooks) {
this.user1 = 'user1';
this.user2 = 'user2';
await runCmd(mountAuthCmd('userpass', this.path1));
await runCmd(mountAuthCmd('userpass', this.path2));
await runCmd([mountAuthCmd('userpass', this.path1), mountAuthCmd('userpass', this.path2)], false);
});
hooks.afterEach(async function () {
await authPage.login();
await runCmd(deleteAuthCmd(this.path1));
await runCmd(deleteAuthCmd(this.path2));
await runCmd([deleteAuthCmd(this.path1), deleteAuthCmd(this.path2)], false);
return;
});

View File

@ -28,6 +28,7 @@ import { formatNumber } from 'core/helpers/format-number';
import { pollCluster } from 'vault/tests/helpers/poll-cluster';
import { disableReplication } from 'vault/tests/helpers/replication';
import connectionPage from 'vault/tests/pages/secrets/backend/database/connection';
import { v4 as uuidv4 } from 'uuid';
import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors';
@ -48,10 +49,8 @@ module('Acceptance | landing page dashboard', function (hooks) {
await authPage.login();
await visit('/vault/dashboard');
const version = this.owner.lookup('service:version');
const versionName = version.version;
const versionText = version.isEnterprise
? `Vault v${versionName.slice(0, versionName.indexOf('+'))} root`
: `Vault v${versionName}`;
// Since we're using mirage, version is mocked static value
const versionText = version.isEnterprise ? `Vault v1.9.0 root` : `Vault v1.9.0`;
assert.dom(SELECTORS.cardHeader('Vault version')).hasText(versionText);
});
@ -308,10 +307,11 @@ module('Acceptance | landing page dashboard', function (hooks) {
};
test('shows the correct actions and links associated with database', async function (assert) {
await mountSecrets.enable('database', 'database');
await newConnection('database');
const databaseBackend = `database-${uuidv4()}`;
await mountSecrets.enable('database', databaseBackend);
await newConnection(databaseBackend);
await runCommands([
`write database/roles/my-role \
`write ${databaseBackend}/roles/my-role \
db_name=mongodb-database-plugin \
creation_statements='{ "db": "admin", "roles": [{ "role": "readWrite" }, {"role": "read", "db": "foo"}] }' \
default_ttl="1h" \
@ -319,7 +319,7 @@ module('Acceptance | landing page dashboard', function (hooks) {
]);
await settled();
await visit('/vault/dashboard');
await selectChoose(SELECTORS.searchSelect('secrets-engines'), 'database');
await selectChoose(SELECTORS.searchSelect('secrets-engines'), databaseBackend);
await fillIn(SELECTORS.selectEl, 'Generate credentials for database');
assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist();
assert.dom(SELECTORS.subtitle('param')).hasText('Role to use');
@ -327,7 +327,7 @@ module('Acceptance | landing page dashboard', function (hooks) {
await selectChoose(SELECTORS.searchSelect('params'), '.ember-power-select-option', 0);
await click(SELECTORS.actionButton('Generate credentials'));
assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.backend.credentials');
await consoleComponent.runCommands(deleteEngineCmd('database'));
await consoleComponent.runCommands(deleteEngineCmd(databaseBackend));
});
test('shows the correct actions and links associated with kv v1', async function (assert) {

View File

@ -1,91 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { click, fillIn, find, currentURL, waitUntil } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { v4 as uuidv4 } from 'uuid';
import page from 'vault/tests/pages/policies/index';
import authPage from 'vault/tests/pages/auth';
module('Acceptance | policies (old)', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function () {
this.uid = uuidv4();
return authPage.login();
});
test('policies', async function (assert) {
const policyString = 'path "*" { capabilities = ["update"]}';
const policyName = `Policy test ${this.uid}`;
const policyLower = policyName.toLowerCase();
await page.visit({ type: 'acl' });
// new policy creation
await click('[data-test-policy-create-link]');
await fillIn('[data-test-policy-input="name"]', policyName);
await click('[data-test-policy-save]');
assert
.dom('[data-test-message-error]')
.hasText(`Error 'policy' parameter not supplied or empty`, 'renders error message on save');
find('.CodeMirror').CodeMirror.setValue(policyString);
await click('[data-test-policy-save]');
await waitUntil(() => currentURL() === `/vault/policy/acl/${encodeURIComponent(policyLower)}`);
assert.strictEqual(
currentURL(),
`/vault/policy/acl/${encodeURIComponent(policyLower)}`,
'navigates to policy show on successful save'
);
assert.dom('[data-test-policy-name]').hasText(policyLower, 'displays the policy name on the show page');
assert.dom('[data-test-flash-message].is-info').doesNotExist('no flash message is displayed on save');
await click('[data-test-policy-list-link] a');
await fillIn('[data-test-component="navigate-input"]', policyLower);
assert
.dom(`[data-test-policy-link="${policyLower}"]`)
.exists({ count: 1 }, 'new policy shown in the list');
// policy deletion
await click(`[data-test-policy-link="${policyLower}"]`);
await click('[data-test-policy-edit-toggle]');
await click('[data-test-confirm-action-trigger]');
await click('[data-test-confirm-button]');
await waitUntil(() => currentURL() === `/vault/policies/acl`);
assert.strictEqual(
currentURL(),
`/vault/policies/acl`,
'navigates to policy list on successful deletion'
);
await fillIn('[data-test-component="navigate-input"]', policyLower);
assert
.dom(`[data-test-policy-item="${policyLower}"]`)
.doesNotExist('deleted policy is not shown in the list');
});
// https://github.com/hashicorp/vault/issues/4395
test('it properly fetches policies when the name ends in a ,', async function (assert) {
const policyString = 'path "*" { capabilities = ["update"]}';
const policyName = `${this.uid}-policy-symbol,.`;
await page.visit({ type: 'acl' });
// new policy creation
await click('[data-test-policy-create-link]');
await fillIn('[data-test-policy-input="name"]', policyName);
find('.CodeMirror').CodeMirror.setValue(policyString);
await click('[data-test-policy-save]');
assert.ok(
await waitUntil(() => currentURL() === `/vault/policy/acl/${policyName}`),
'navigates to policy show on successful save'
);
assert.dom('[data-test-policy-edit-toggle]').exists({ count: 1 }, 'shows the edit toggle');
});
});

View File

@ -3,38 +3,58 @@
* SPDX-License-Identifier: BUSL-1.1
*/
import { currentURL, currentRouteName, settled, fillIn } from '@ember/test-helpers';
import {
currentURL,
currentRouteName,
settled,
fillIn,
visit,
click,
find,
waitFor,
waitUntil,
} from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { create } from 'ember-cli-page-object';
import { v4 as uuidv4 } from 'uuid';
import page from 'vault/tests/pages/policies/index';
import authPage from 'vault/tests/pages/auth';
import consoleClass from 'vault/tests/pages/components/console/ui-panel';
const consoleComponent = create(consoleClass);
import { runCmd } from 'vault/tests/helpers/commands';
const SELECT = {
policyByName: (name) => `[data-test-policy-link="${name}"]`,
filterBar: '[data-test-component="navigate-input"]',
delete: '[data-test-confirm-action-trigger]',
confirmDelete: '[data-test-confirm-button]',
createLink: '[data-test-policy-create-link]',
nameInput: '[data-test-policy-input="name"]',
save: '[data-test-policy-save]',
createError: '[data-test-message-error]',
policyTitle: '[data-test-policy-name]',
listBreadcrumb: '[data-test-policy-list-link] a',
};
module('Acceptance | policies/acl', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function () {
this.uid = uuidv4();
return authPage.login();
});
test('it lists default and root acls', async function (assert) {
await page.visit({ type: 'acl' });
await visit('/vault/policies/acl');
assert.strictEqual(currentURL(), '/vault/policies/acl');
await fillIn('[data-test-component="navigate-input"]', 'default');
assert.ok(page.findPolicyByName('default'), 'default policy shown in the list');
await fillIn('[data-test-component="navigate-input"]', 'root');
assert.ok(page.findPolicyByName('root'), 'root policy shown in the list');
await fillIn(SELECT.filterBar, 'default');
await waitFor(SELECT.policyByName('default'));
assert.dom(SELECT.policyByName('default')).exists('default policy shown in the list');
await fillIn(SELECT.filterBar, 'root');
// root isn't clickable so it has a different selector
assert.dom('[data-test-policy-name]').hasText('root', 'root policy shown in the list');
});
test('it navigates to show when clicking on the link', async function (assert) {
await page.visit({ type: 'acl' });
await settled();
await page.findPolicyByName('default').click();
await settled();
await visit('/vault/policies/acl');
await click(SELECT.policyByName('default'));
assert.strictEqual(currentRouteName(), 'vault.cluster.policy.show');
assert.strictEqual(currentURL(), '/vault/policy/acl/default');
});
@ -42,16 +62,86 @@ module('Acceptance | policies/acl', function (hooks) {
test('it allows deletion of policies with dots in names', async function (assert) {
const POLICY = 'path "*" { capabilities = ["list"]}';
const policyName = 'list.policy';
await consoleComponent.runCommands([`write sys/policies/acl/${policyName} policy=${btoa(POLICY)}`]);
await runCmd(`write sys/policies/acl/${policyName} policy=${window.btoa(POLICY)}`);
await settled();
await page.visit({ type: 'acl' });
await settled();
const policy = page.row.filterBy('name', policyName)[0];
assert.ok(policy, 'policy is shown in the list');
await policy.menu();
await settled();
await page.delete().confirmDelete();
await settled();
assert.notOk(page.findPolicyByName(policyName), 'policy is deleted successfully');
await visit('/vault/policies/acl');
assert.dom(SELECT.policyByName(policyName)).exists('policy is shown in list');
await click(`${SELECT.policyByName(policyName)} [data-test-popup-menu-trigger]`);
await click(SELECT.delete);
await click(SELECT.confirmDelete);
assert.dom(SELECT.policyByName(policyName)).doesNotExist('policy is deleted successfully');
});
// https://github.com/hashicorp/vault/issues/4395
test('it properly fetches policies when the name ends in a ,', async function (assert) {
const policyString = 'path "*" { capabilities = ["update"]}';
const policyName = `${this.uid}-policy-symbol,.`;
await visit('/vault/policies/acl');
// new policy creation
await click(SELECT.createLink);
await fillIn(SELECT.nameInput, policyName);
find('.CodeMirror').CodeMirror.setValue(policyString);
await click(SELECT.save);
assert.strictEqual(
currentURL(),
`/vault/policy/acl/${policyName}`,
'navigates to policy show on successful save'
);
assert.dom('[data-test-policy-edit-toggle]').exists({ count: 1 }, 'shows the edit toggle');
});
test('it can create and delete correctly', async function (assert) {
const policyString = 'path "*" { capabilities = ["update"]}';
const policyName = `Policy test ${this.uid}`;
const policyLower = policyName.toLowerCase();
await visit('/vault/policies/acl');
// new policy creation
await click(SELECT.createLink);
await fillIn(SELECT.nameInput, policyName);
await click(SELECT.save);
assert
.dom(SELECT.createError)
.hasText(`Error 'policy' parameter not supplied or empty`, 'renders error message on save');
find('.CodeMirror').CodeMirror.setValue(policyString);
await click(SELECT.save);
await waitUntil(() => currentURL() === `/vault/policy/acl/${encodeURIComponent(policyLower)}`);
assert.strictEqual(
currentURL(),
`/vault/policy/acl/${encodeURIComponent(policyLower)}`,
'navigates to policy show on successful save'
);
assert.dom(SELECT.policyTitle).hasText(policyLower, 'displays the policy name on the show page');
assert.dom('[data-test-flash-message].is-info').doesNotExist('no flash message is displayed on save');
await click(SELECT.listBreadcrumb);
assert.strictEqual(currentURL(), `/vault/policies/acl`, 'navigates to policy list from breadcrumb');
// List of policies can get long quickly -- filter for the policy to make the test more robust
await fillIn(SELECT.filterBar, policyLower);
assert
.dom(`[data-test-policy-link="${policyLower}"]`)
.exists({ count: 1 }, 'new policy shown in the list');
// policy deletion
await click(SELECT.policyByName(policyLower));
await click('[data-test-policy-edit-toggle]');
await click('[data-test-confirm-action-trigger]');
await click('[data-test-confirm-button]');
await waitUntil(() => currentURL() === `/vault/policies/acl`);
assert.strictEqual(
currentURL(),
`/vault/policies/acl`,
'navigates to policy list on successful deletion'
);
assert
.dom(`[data-test-policy-item="${policyLower}"]`)
.doesNotExist('deleted policy is not shown in the list');
});
});

View File

@ -31,6 +31,10 @@ export default {
}),
lastTextOutput: getter(function () {
const count = this.logTextItems.length;
if (count === 0) {
// If no logOutput items are found, we can assume the response is empty
return '';
}
return this.logTextItems.objectAt(count - 1).text;
}),
logJSONItems: collection('[data-test-component="console/log-json"]', {

View File

@ -1,9 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { create, visitable } from 'ember-cli-page-object';
export default create({
visit: visitable('/vault/policies/create'),
});

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { text, create, collection, clickable, visitable } from 'ember-cli-page-object';
export default create({
visit: visitable('/vault/policies/:type'),
policies: collection('[data-test-policy-item]', {
name: text('[data-test-policy-name]'),
}),
row: collection('[data-test-policy-link]', {
name: text(),
menu: clickable('[data-test-popup-menu-trigger]'),
}),
findPolicyByName(name) {
return this.policies.filterBy('name', name)[0];
},
delete: clickable('[data-test-confirm-action-trigger]'),
confirmDelete: clickable('[data-test-confirm-button]'),
});