UI/db tests (#11013)

* Add tests for connection create and edit

* Cleanup old tests, add role create form test

* Fix linter/selector
This commit is contained in:
Chelsea Shaw
2021-02-25 18:41:04 -06:00
committed by GitHub
parent 2d2ebdb491
commit a13f6073ae
5 changed files with 230 additions and 3 deletions

View File

@@ -183,6 +183,7 @@
}} class="textarea"></textarea>
{{else if (eq attr.options.editType "password")}}
<Input
data-test-input={{attr.name}}
@type="password"
@value={{get model valuePath}}
@name={{attr.name}}
@@ -206,6 +207,7 @@
<p class="sub-text">{{attr.options.subText}}</p>
{{/if}}
<JsonEditor
data-test-input={{attr.name}}
@value={{if
(get model valuePath)
(stringify (jsonify (get model valuePath)))

View File

@@ -29,7 +29,7 @@
/> No
{{/if}}
{{else if (and (not value) (and alwaysRender defaultShown))}}
{{defaultShown}}
<span data-test-row-value="{{label}}">{{defaultShown}}</span>
{{else}}
{{#if (eq type 'array')}}
<InfoTableItemArray

View File

@@ -1,11 +1,19 @@
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, settled, click, visit } from '@ember/test-helpers';
import { currentURL, settled, click, visit, fillIn, findAll } from '@ember/test-helpers';
import { create } from 'ember-cli-page-object';
import { selectChoose, clickTrigger } from 'ember-power-select/test-support/helpers';
import mountSecrets from 'vault/tests/pages/settings/mount-secret-backend';
import connectionPage from 'vault/tests/pages/secrets/backend/database/connection';
import rolePage from 'vault/tests/pages/secrets/backend/database/role';
import apiStub from 'vault/tests/helpers/noop-all-api-requests';
import authPage from 'vault/tests/pages/auth';
import logout from 'vault/tests/pages/logout';
import consoleClass from 'vault/tests/pages/components/console/ui-panel';
import searchSelect from 'vault/tests/pages/components/search-select';
const searchSelectComponent = create(searchSelect);
const consoleComponent = create(consoleClass);
@@ -14,7 +22,25 @@ const MODEL = {
id: 'database-name',
};
// ARG TODO add more to test her once you fill out the flow
const mount = async () => {
let path = `database-${Date.now()}`;
await mountSecrets.enable('database', path);
await settled();
return path;
};
const newConnection = async backend => {
const name = `connection-${Date.now()}`;
await connectionPage.visitCreate({ backend });
await connectionPage.dbPlugin('mongodb-database-plugin');
await connectionPage.name(name);
await connectionPage.url(`mongodb://127.0.0.1:4321/${name}`);
await connectionPage.toggleVerify();
await connectionPage.save();
await connectionPage.enable();
return name;
};
module('Acceptance | secrets/database/*', function(hooks) {
setupApplicationTest(hooks);
@@ -26,6 +52,174 @@ module('Acceptance | secrets/database/*', function(hooks) {
this.server.shutdown();
});
test('can enable the database secrets engine', async function(assert) {
let backend = `database-${Date.now()}`;
await mountSecrets.enable('database', backend);
await settled();
assert.equal(
currentURL(),
`/vault/secrets/${backend}/list`,
'Mounts and redirects to connection list page'
);
assert.dom('[data-test-component="empty-state"]').exists('Empty state exists');
assert
.dom('.is-active[data-test-secret-list-tab="Connections"]')
.exists('Has Connections tab which is active');
await click('[data-test-tab="overview"]');
assert.equal(currentURL(), `/vault/secrets/${backend}/overview`, 'Tab links to overview page');
assert.dom('[data-test-component="empty-state"]').exists('Empty state also exists on overview page');
assert.dom('[data-test-secret-list-tab="Roles"]').exists('Has Roles tab');
});
test('Connection create and edit form happy path works as expected', async function(assert) {
const backend = await mount();
const connectionDetails = {
plugin: 'mongodb-database-plugin',
id: 'horses-db',
fields: [
{ label: 'Connection Name', name: 'name', value: 'horses-db' },
{ label: 'Connection url', name: 'connection_url', value: 'mongodb://127.0.0.1:235/horses' },
{ label: 'Username', name: 'username', value: 'user', hideOnShow: true },
{ label: 'Password', name: 'password', password: 'so-secure', hideOnShow: true },
{ label: 'Write concern', name: 'write_concern' },
],
};
assert.equal(
currentURL(),
`/vault/secrets/${backend}/list`,
'Mounts and redirects to connection list page'
);
await connectionPage.createLink();
assert.equal(currentURL(), `/vault/secrets/${backend}/create`, 'Create link goes to create page');
assert
.dom('[data-test-empty-state-title')
.hasText('No plugin selected', 'No plugin is selected by default and empty state shows');
await connectionPage.dbPlugin(connectionDetails.plugin);
assert.dom('[data-test-empty-state]').doesNotExist('Empty state goes away after plugin selected');
connectionDetails.fields.forEach(async ({ name, value }) => {
assert
.dom(`[data-test-input="${name}"]`)
.exists(`Field ${name} exists for ${connectionDetails.plugin}`);
if (value) {
await fillIn(`[data-test-input="${name}"]`, value);
}
});
// uncheck verify for the save step to work
await connectionPage.toggleVerify();
await connectionPage.save();
assert
.dom('[data-test-modal-title]')
.hasText('Rotate your root credentials?', 'Modal appears asking to ');
await connectionPage.enable();
assert.equal(
currentURL(),
`/vault/secrets/${backend}/show/${connectionDetails.id}`,
'Saves connection and takes you to show page'
);
connectionDetails.fields.forEach(({ label, name, value, hideOnShow }) => {
if (hideOnShow) {
assert
.dom(`[data-test-row-value="${label}"]`)
.doesNotExist(`Does not show ${name} value on show page for ${connectionDetails.plugin}`);
} else if (!value) {
assert.dom(`[data-test-row-value="${label}"]`).hasText('Default');
} else {
assert.dom(`[data-test-row-value="${label}"]`).hasText(value);
}
});
// go back and edit write_concern
await connectionPage.edit();
assert.dom(`[data-test-input="name"]`).hasAttribute('readonly');
assert.dom(`[data-test-input="plugin_name"]`).hasAttribute('readonly');
// assert password is hidden
findAll('.CodeMirror')[0].CodeMirror.setValue(JSON.stringify({ wtimeout: 5000 }));
// uncheck verify for the save step to work
await connectionPage.toggleVerify();
await connectionPage.save();
assert
.dom(`[data-test-row-value="Write concern"]`)
.hasText('{ "wtimeout": 5000 }', 'Write concern is now showing on the table');
});
test('buttons show up for managing connection', async function(assert) {
const backend = await mount();
const connection = await newConnection(backend);
await connectionPage.visitShow({ backend, id: connection });
assert
.dom('[data-test-database-connection-delete]')
.hasText('Delete connection', 'Delete connection button exists with correct text');
assert
.dom('[data-test-database-connection-reset]')
.hasText('Reset connection', 'Reset button exists with correct text');
assert.dom('[data-test-secret-create]').hasText('Add role', 'Add role button exists with correct text');
assert.dom('[data-test-edit-link]').hasText('Edit configuration', 'Edit button exists with correct text');
const CONNECTION_VIEW_ONLY = `
path "${backend}/*" {
capabilities = ["deny"]
}
path "${backend}/config" {
capabilities = ["list"]
}
path "${backend}/config/*" {
capabilities = ["read"]
}
`;
await consoleComponent.runCommands([
`write sys/mounts/${backend} type=database`,
`write sys/policies/acl/test-policy policy=${btoa(CONNECTION_VIEW_ONLY)}`,
'write -field=client_token auth/token/create policies=test-policy ttl=1h',
]);
let token = consoleComponent.lastTextOutput;
await logout.visit();
await authPage.login(token);
await connectionPage.visitShow({ backend, id: connection });
assert.equal(currentURL(), `/vault/secrets/${backend}/show/${connection}`, 'Allows reading connection');
assert
.dom('[data-test-database-connection-delete]')
.doesNotExist('Delete button does not show due to permissions');
assert
.dom('[data-test-database-connection-reset]')
.doesNotExist('Reset button does not show due to permissions');
assert.dom('[data-test-secret-create]').doesNotExist('Add role button does not show due to permissions');
assert.dom('[data-test-edit-link]').doesNotExist('Edit button does not show due to permissions');
await visit(`/vault/secrets/${backend}/overview`);
assert.dom('[data-test-selectable-card="Connections"]').exists('Connections card exists on overview');
assert
.dom('[data-test-selectable-card="Roles"]')
.doesNotExist('Roles card does not exist on overview w/ policy');
assert.dom('.title-number').hasText('1', 'Lists the correct number of connections');
});
test('Role create form', async function(assert) {
const backend = await mount();
// Connection needed for role fields
await newConnection(backend);
await rolePage.visitCreate({ backend });
await rolePage.name('bar');
assert
.dom('[data-test-component="empty-state"]')
.exists({ count: 2 }, 'Two empty states exist before selections made');
await clickTrigger('#database');
assert.equal(searchSelectComponent.options.length, 1, 'list shows existing connections so far');
await selectChoose('#database', '.ember-power-select-option', 0);
assert
.dom('[data-test-component="empty-state"]')
.exists({ count: 2 }, 'Two empty states exist before selections made');
await rolePage.roleType('static');
assert.dom('[data-test-component="empty-state"]').doesNotExist('Empty states go away');
assert.dom('[data-test-input="username"]').exists('Username field appears for static role');
assert
.dom('[data-test-toggle-input="Rotation period"]')
.exists('Rotation period field appears for static role');
await rolePage.roleType('dynamic');
assert
.dom('[data-test-toggle-input="Generated credentialss Time-to-Live (TTL)"]')
.exists('TTL field exists for dynamic');
assert
.dom('[data-test-toggle-input="Generated credentialss maximum Time-to-Live (Max TTL)"]')
.exists('Max TTL field exists for dynamic');
});
test('root and limited access', async function(assert) {
this.set('model', MODEL);
let backend = 'database';

View File

@@ -0,0 +1,17 @@
import { create, clickable, fillable, visitable, selectable } from 'ember-cli-page-object';
import ListView from 'vault/tests/pages/components/list-view';
export default create({
...ListView,
visit: visitable('/vault/secrets/:backend/list'),
visitShow: visitable('/vault/secrets/:backend/show/:id'),
visitCreate: visitable('/vault/secrets/:backend/create'),
createLink: clickable('[data-test-secret-create="true"]'),
dbPlugin: selectable('[data-test-input="plugin_name"]'),
name: fillable('[data-test-input="name"]'),
toggleVerify: clickable('[data-test-input="verify_connection"]'),
url: fillable('[data-test-input="connection_url"'),
save: clickable('[data-test-secret-save=""]'),
enable: clickable('[data-test-enable-connection=""]'),
edit: clickable('[data-test-edit-link="true"]'),
});

View File

@@ -0,0 +1,14 @@
import { create, clickable, fillable, visitable, selectable } from 'ember-cli-page-object';
import ListView from 'vault/tests/pages/components/list-view';
export default create({
...ListView,
visit: visitable('/vault/secrets/:backend/list?itemType=role'),
visitShow: visitable('/vault/secrets/:backend/show/role/:id'),
visitCreate: visitable('/vault/secrets/:backend/create?itemType=role'),
createLink: clickable('[data-test-secret-create="true"]'),
name: fillable('[data-test-input="name"]'),
roleType: selectable('[data-test-input="type"'),
save: clickable('[data-test-secret-save=""]'),
edit: clickable('[data-test-edit-link="true"]'),
});