Files
vault/ui/tests/acceptance/secrets/backend/database/secret-test.js
claire bontempo 43258c28fa UI: HDS adoption replace <Modal> (#23382)
* UI: Part 1 - hds adoption replace <Modal> (#23363)

* replace policy-form modal

* replace clients/attribution modal

* clients/config modal

* scope form odal

* remove button type

* include toolbar to match other example templates

* rotate credentials modal

* add toolbar button class for hds buttons

* transformation-edit modal

* add back test selector

* add route arg to button!

* update link status

* fix link-status tests

* remove prevent default

* update db tests

* update tests

* use page alert for hcp link status banner

* fix scopy button selector

* fix sidebar test

* change to neutral banner

* UI: Part 2 - hds adoption replace <Modal>  (#23398)

* upgrade HDS library (adds support for snippet containers

* cleanup flight icons

* replace transit key action modals

* re-add deps as devDeps

* remove line

* address transit tests

* UI: Part 3 - hds adoption replace <Modal> (#23415)

* cleanup css

* cleanup extra type attr

* masked input download modal

* use Hds::Button in  download button"

* fix size of modal

* tiny icon fix

* refactor download button to always render download icon

* update tests

* UI: Part 3.5 - hds adoption replace <Modal> (#23448)

* replication-promote modal

* replication component modals

* replication add secondary modal

* move update text for diff

* UI: Part 4 - hds adoption replace <Modal>  (#23451)

* k8 configure modal

* kv delete modal

* ldap modals

* pki modals

* add trash icon

* move deps

* UI: Part 5 - hds adoption replace <Modal> (#23471)

* replace confirmation modals
---------

* UI: Part 6 - hds adoption replace <Modal>  (#23484)

* search select with modal

* policy search select modal

* replace date dropdown for client dashboard

* change padding to top

* update policy example args

* lolllll test typo wow

* update dropdown tests

* shamir flow modals!

* add one more container

* update test selectors

* UI: Final hds adoption replace <Modal> cleanup PR (#23522)

* search select with modal

* policy search select modal

* replace date dropdown for client dashboard

* change padding to top

* update policy example args

* lolllll test typo wow

* update dropdown tests

* shamir flow modals!

* add one more container

* update test selectors

* remove wormhole and modal component

* fix selectors

* uninstall wormhole

* remove shamir-modal-flow class

* fix confirm modal test

* fix pki and kv test

* fix toolbar selector kv

* client and download button test

* fix-confirmation-modal-padding

* fix replication modal tests so relevant modal opens (#23540)

* more confirmation modal tests

* adds changelog
2023-10-06 22:06:36 +00:00

559 lines
25 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, settled, click, visit, fillIn, typeIn } 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 authPage from 'vault/tests/pages/auth';
import logout from 'vault/tests/pages/logout';
import searchSelect from 'vault/tests/pages/components/search-select';
import { deleteEngineCmd, mountEngineCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands';
const searchSelectComponent = create(searchSelect);
const newConnection = async (backend, plugin = 'mongodb-database-plugin') => {
const name = `connection-${Date.now()}`;
await connectionPage.visitCreate({ backend });
await connectionPage.dbPlugin(plugin);
await connectionPage.name(name);
await connectionPage.connectionUrl(`mongodb://127.0.0.1:4321/${name}`);
await connectionPage.toggleVerify();
await connectionPage.save();
await connectionPage.enable();
return name;
};
const navToConnection = async (backend, connection) => {
await visit('/vault/secrets');
await click(`[data-test-secrets-backend-link="${backend}"]`);
await click('[data-test-secret-list-tab="Connections"]');
await click(`[data-test-secret-link="${connection}"]`);
return;
};
const connectionTests = [
{
name: 'elasticsearch-connection',
plugin: 'elasticsearch-database-plugin',
elasticUser: 'username',
elasticPassword: 'password',
url: 'http://127.0.0.1:9200',
assertCount: 9,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert.dom('[data-test-input="ca_cert"]').exists(`CA certificate field exists for ${name}`);
assert.dom('[data-test-input="ca_path"]').exists(`CA path field exists for ${name}`);
assert.dom('[data-test-input="client_cert"]').exists(`Client certificate field exists for ${name}`);
assert.dom('[data-test-input="client_key"]').exists(`Client key field exists for ${name}`);
assert.dom('[data-test-input="tls_server_name"]').exists(`TLS server name field exists for ${name}`);
assert.dom('[data-test-input="insecure"]').exists(`Insecure checkbox exists for ${name}`);
assert
.dom('[data-test-toggle-input="show-username_template"]')
.exists(`Username template toggle exists for ${name}`);
},
},
{
name: 'mongodb-connection',
plugin: 'mongodb-database-plugin',
url: `mongodb://127.0.0.1:4321/test`,
assertCount: 5,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert.dom('[data-test-input="write_concern"]').exists(`Write concern field exists for ${name}`);
assert.dom('[data-test-toggle-group="TLS options"]').exists('TLS options toggle exists');
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'mssql-connection',
plugin: 'mssql-database-plugin',
url: `mssql://127.0.0.1:4321/test`,
assertCount: 6,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'mysql-connection',
plugin: 'mysql-database-plugin',
url: `{{username}}:{{password}}@tcp(127.0.0.1:3306)/test`,
assertCount: 7,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert.dom('[data-test-toggle-group="TLS options"]').exists('TLS options toggle exists');
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'mysql-aurora-connection',
plugin: 'mysql-aurora-database-plugin',
url: `{{username}}:{{password}}@tcp(127.0.0.1:3306)/test`,
assertCount: 7,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert.dom('[data-test-toggle-group="TLS options"]').exists('TLS options toggle exists');
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'mysql-rds-connection',
plugin: 'mysql-rds-database-plugin',
url: `{{username}}:{{password}}@tcp(127.0.0.1:3306)/test`,
assertCount: 7,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert.dom('[data-test-toggle-group="TLS options"]').exists('TLS options toggle exists');
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'mysql-legacy-connection',
plugin: 'mysql-legacy-database-plugin',
url: `{{username}}:{{password}}@tcp(127.0.0.1:3306)/test`,
assertCount: 7,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert.dom('[data-test-toggle-group="TLS options"]').exists('TLS options toggle exists');
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
},
},
{
name: 'postgresql-connection',
plugin: 'postgresql-database-plugin',
url: `postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable`,
assertCount: 7,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
assert
.dom('[data-test-toggle-input="show-username_template"]')
.exists(`Username template toggle exists for ${name}`);
},
},
];
module('Acceptance | secrets/database/*', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(async function () {
this.backend = `database-testing`;
await authPage.login();
return runCmd(mountEngineCmd('database', this.backend), false);
});
hooks.afterEach(async function () {
await authPage.login();
return runCmd(deleteEngineCmd(this.backend), false);
});
test('can enable the database secrets engine', async function (assert) {
const backend = `database-${Date.now()}`;
await mountSecrets.enable('database', backend);
await settled();
assert.strictEqual(
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('.active[data-test-secret-list-tab="Connections"]')
.exists('Has Connections tab which is active');
await click('[data-test-tab="overview"]');
assert.strictEqual(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');
await visit('/vault/secrets');
// Cleanup backend
await runCmd(deleteEngineCmd(backend), false);
});
for (const testCase of connectionTests) {
test(`database connection create and edit: ${testCase.plugin}`, async function (assert) {
assert.expect(19 + testCase.assertCount);
const backend = this.backend;
await connectionPage.visitCreate({ backend });
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/create`, 'Correct creation URL');
assert
.dom('[data-test-empty-state-title]')
.hasText('No plugin selected', 'No plugin is selected by default and empty state shows');
await connectionPage.dbPlugin(testCase.plugin);
assert.dom('[data-test-empty-state]').doesNotExist('Empty state goes away after plugin selected');
await connectionPage.name(testCase.name);
if (testCase.plugin === 'elasticsearch-database-plugin') {
await connectionPage.url(testCase.url);
await connectionPage.username(testCase.elasticUser);
await connectionPage.password(testCase.elasticPassword);
} else {
await connectionPage.connectionUrl(testCase.url);
}
testCase.requiredFields(assert, testCase.plugin);
assert.dom('[data-test-input="verify_connection"]').isChecked('verify is checked');
await connectionPage.toggleVerify();
assert.dom('[data-test-input="verify_connection"]').isNotChecked('verify is unchecked');
assert
.dom('[data-test-database-oracle-alert]')
.doesNotExist('does not show oracle alert for non-oracle plugins');
await connectionPage.save();
await settled();
assert
.dom('[data-test-db-connection-modal-title]')
.hasText('Rotate your root credentials?', 'Modal appears asking to rotate root credentials');
assert.dom('[data-test-enable-connection]').exists('Enable button exists');
await click('[data-test-enable-connection]');
assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/show/${testCase.name}`),
`Saves connection and takes you to show page for ${testCase.name}`
);
assert
.dom(`[data-test-row-value="Password"]`)
.doesNotExist(`Does not show Password value on show page for ${testCase.name}`);
await connectionPage.edit();
assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/edit/${testCase.name}`),
`Edit connection button and takes you to edit page for ${testCase.name}`
);
assert.dom(`[data-test-input="name"]`).hasAttribute('readonly');
assert.dom(`[data-test-input="plugin_name"]`).hasAttribute('readonly');
assert.dom('[data-test-input="password"]').doesNotExist('Password is not displayed on edit form');
assert.dom('[data-test-toggle-input="show-password"]').exists('Update password toggle exists');
assert.dom('[data-test-input="verify_connection"]').isNotChecked('verify is still unchecked');
await connectionPage.save();
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/show/${testCase.name}`);
// click "Add Role"
await connectionPage.addRole();
await settled();
assert.strictEqual(
searchSelectComponent.selectedOptions[0].text,
testCase.name,
'Database connection is pre-selected on the form'
);
await click('[data-test-database-role-cancel]');
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/list`, 'Cancel button links to list view');
});
}
test('database connection create and edit: vault-plugin-database-oracle', async function (assert) {
assert.expect(11);
// keep oracle as separate test because it behaves differently than the others
const testCase = {
name: 'oracle-connection',
plugin: 'vault-plugin-database-oracle',
url: `{{username}}/{{password}}@localhost:1521/OraDoc.localhost`,
requiredFields: async (assert, name) => {
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
assert
.dom('[data-test-input="max_open_connections"]')
.exists(`Max open connections exists for ${name}`);
assert
.dom('[data-test-input="max_idle_connections"]')
.exists(`Max idle connections exists for ${name}`);
assert
.dom('[data-test-input="max_connection_lifetime"]')
.exists(`Max connection lifetime exists for ${name}`);
assert
.dom('[data-test-input="root_rotation_statements"]')
.exists(`Root rotation statements exists for ${name}`);
assert
.dom('[data-test-database-oracle-alert]')
.hasTextContaining(
`Warning Please ensure that your Oracle plugin has the default name of vault-plugin-database-oracle. Custom naming is not supported in the UI at this time. If the plugin is already named vault-plugin-database-oracle, disregard this warning.`,
'warning banner displays for oracle plugin name'
);
},
};
const backend = this.backend;
await connectionPage.visitCreate({ backend });
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/create`, 'Correct creation URL');
assert
.dom('[data-test-empty-state-title]')
.hasText('No plugin selected', 'No plugin is selected by default and empty state shows');
await connectionPage.dbPlugin(testCase.plugin);
assert.dom('[data-test-empty-state]').doesNotExist('Empty state goes away after plugin selected');
assert.dom('[data-test-database-oracle-alert]').exists('shows oracle alert');
await connectionPage.name(testCase.name);
await connectionPage.connectionUrl(testCase.url);
testCase.requiredFields(assert, testCase.plugin);
// Cannot save without plugin mounted
// TODO: add fake server response for fuller test coverage
});
test('Can create and delete a connection', async function (assert) {
const backend = this.backend;
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' },
],
};
await visit(`/vault/secrets/${backend}/list`);
await connectionPage.createLink();
assert.strictEqual(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();
await settled();
assert
.dom('[data-test-db-connection-modal-title]')
.hasText('Rotate your root credentials?', 'Modal appears asking to ');
await connectionPage.enable();
assert.strictEqual(
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);
}
});
await connectionPage.delete();
assert
.dom('[data-test-confirmation-modal-title]')
.hasText('Delete connection?', 'Modal appears asking to confirm delete action');
await fillIn('[data-test-confirmation-modal-input="Delete connection?"]', connectionDetails.id);
await click('[data-test-confirm-button]');
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/list`, 'Redirects to connection list page');
assert
.dom('[data-test-empty-state-title]')
.hasText('No connections in this backend', 'No connections listed because it was deleted');
});
test('buttons show up for managing connection', async function (assert) {
const backend = this.backend;
const connection = await newConnection(backend);
const CONNECTION_VIEW_ONLY = `
path "${backend}/config" {
capabilities = ["list"]
}
path "${backend}/config/*" {
capabilities = ["read"]
}
`;
const token = await runCmd(tokenWithPolicyCmd('test-policy', CONNECTION_VIEW_ONLY));
await navToConnection(backend, 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');
await authPage.logout();
// Check with restricted permissions
await authPage.login(token);
await click('[data-test-sidebar-nav-link="Secrets engines"]');
assert.dom(`[data-test-secrets-backend-link="${backend}"]`).exists('Shows backend on secret list page');
await navToConnection(backend, connection);
assert.strictEqual(
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');
// confirm get credentials card is an option to select. Regression bug.
await typeIn('.ember-text-field', 'blah');
assert.dom('[data-test-get-credentials]').isEnabled();
});
test('Role create form', async function (assert) {
const backend = this.backend;
// 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.strictEqual(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');
// Real connection (actual running db) required to save role, so we aren't testing that flow yet
});
test('root and limited access', async function (assert) {
const backend = this.backend;
const NO_ROLES_POLICY = `
path "${backend}/roles/*" {
capabilities = ["delete"]
}
path "${backend}/static-roles/*" {
capabilities = ["delete"]
}
path "${backend}/config/*" {
capabilities = ["list", "create", "read", "update"]
}
path "${backend}/creds/*" {
capabilities = ["list", "create", "read", "update"]
}
`;
const token = await runCmd(tokenWithPolicyCmd('test-policy', NO_ROLES_POLICY));
// test root user flow first
await visit(`/vault/secrets/${backend}/overview`);
assert.dom('[data-test-component="empty-state"]').exists('renders empty state');
assert.dom('[data-test-secret-list-tab="Connections"]').exists('renders connections tab');
assert.dom('[data-test-secret-list-tab="Roles"]').exists('renders connections tab');
await click('[data-test-secret-create="connections"]');
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/create`);
// Login with restricted policy
await logout.visit();
await authPage.login(token);
await visit(`/vault/secrets/${backend}/overview`);
assert.dom('[data-test-tab="overview"]').exists('renders overview tab');
assert.dom('[data-test-secret-list-tab="Connections"]').exists('renders connections tab');
assert
.dom('[data-test-secret-list-tab="Roles"]')
.doesNotExist(`does not show the roles tab because it does not have permissions`);
assert
.dom('[data-test-selectable-card="Connections"]')
.exists({ count: 1 }, 'renders only the connection card');
await click('[data-test-action-text="Configure new"]');
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/create?itemType=connection`);
});
});