diff --git a/ui/admin/app/components/form/storage-bucket/aws/index.hbs b/ui/admin/app/components/form/storage-bucket/aws/index.hbs
index a4f53c64a..ccb7c6feb 100644
--- a/ui/admin/app/components/form/storage-bucket/aws/index.hbs
+++ b/ui/admin/app/components/form/storage-bucket/aws/index.hbs
@@ -26,7 +26,7 @@
{{#if @model.errors.name}}
{{#each @model.errors.name as |error|}}
- {{error.message}}
+ {{error.message}}
{{/each}}
{{/if}}
diff --git a/ui/admin/app/components/form/storage-bucket/minio/index.hbs b/ui/admin/app/components/form/storage-bucket/minio/index.hbs
index f63b30ee7..452a6de6e 100644
--- a/ui/admin/app/components/form/storage-bucket/minio/index.hbs
+++ b/ui/admin/app/components/form/storage-bucket/minio/index.hbs
@@ -26,7 +26,7 @@
{{#if @model.errors.name}}
{{#each @model.errors.name as |error|}}
- {{error.message}}
+ {{error.message}}
{{/each}}
{{/if}}
diff --git a/ui/admin/tests/acceptance/targets/enable-session-recording/create-storage-bucket-test.js b/ui/admin/tests/acceptance/targets/enable-session-recording/create-storage-bucket-test.js
index 0ca84d7d8..5ba8f1276 100644
--- a/ui/admin/tests/acceptance/targets/enable-session-recording/create-storage-bucket-test.js
+++ b/ui/admin/tests/acceptance/targets/enable-session-recording/create-storage-bucket-test.js
@@ -21,16 +21,11 @@ module(
let features;
let getStorageBucketCount;
- const SAVE_BTN_SELECTOR = '[type="submit"]';
- const CANCEL_BTN_SELECTOR = '.rose-form-actions [type="button"]';
- const NAME_FIELD_SELECTOR = '[name="name"]';
- const FIELD_ERROR_TEXT_SELECTOR = '.hds-form-error__message';
- const NAME_FIELD_TEXT = 'random string';
- const BUCKET_NAME_FIELD_SELECTOR = '[name="bucket_name"]';
- const BUCKET_PREFIX_FIELD_SELECTOR = '[name="bucket_prefix"]';
- const EDITOR_WORKER_FILTER =
- '[data-test-code-editor-field-editor] textarea';
- const EDITOR_WORKER_FILTER_VALUE = '"dev" in "/tags/env"';
+ const FIELD_BUCKET_NAME = '[name="bucket_name"]';
+ const FIELD_BUCKET_PREFIX = '[name="bucket_prefix"]';
+ const FIELD_EDITOR = '[data-test-code-editor-field-editor] textarea';
+ const WORKER_FILTER_VALUE = '"dev" in "/tags/env"';
+ const FIELD_SCOPE = (scope) => `[value="${scope}"]`;
const instances = {
scopes: {
@@ -40,8 +35,6 @@ module(
};
const urls = {
- globalScope: null,
- projectScope: null,
targets: null,
target: null,
enableSessionRecording: null,
@@ -63,10 +56,8 @@ module(
scope: instances.scopes.project,
type: TYPE_TARGET_SSH,
});
- urls.globalScope = `/scopes/global`;
- urls.projectScope = `/scopes/${instances.scopes.project.id}`;
- urls.targets = `${urls.projectScope}/targets`;
+ urls.targets = `/scopes/${instances.scopes.project.id}/targets`;
urls.target = `${urls.targets}/${instances.target.id}`;
urls.enableSessionRecording = `${urls.target}/enable-session-recording`;
urls.newStorageBucket = `${urls.enableSessionRecording}/create-storage-bucket`;
@@ -82,22 +73,25 @@ module(
const storageBucketCount = getStorageBucketCount();
await visit(urls.enableSessionRecording);
- await click(`[href="${urls.newStorageBucket}"]`);
- await fillIn(NAME_FIELD_SELECTOR, NAME_FIELD_TEXT);
- await click('[value="global"]');
- await fillIn(EDITOR_WORKER_FILTER, EDITOR_WORKER_FILTER_VALUE);
+ await click(commonSelectors.HREF(urls.newStorageBucket));
+ await fillIn(
+ commonSelectors.FIELD_NAME,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ await click(FIELD_SCOPE('global'));
+ await fillIn(FIELD_EDITOR, WORKER_FILTER_VALUE);
- assert.dom(BUCKET_NAME_FIELD_SELECTOR).isNotDisabled();
- assert.dom(BUCKET_PREFIX_FIELD_SELECTOR).isNotDisabled();
- assert.dom(BUCKET_NAME_FIELD_SELECTOR).doesNotHaveAttribute('readOnly');
- assert.dom(BUCKET_PREFIX_FIELD_SELECTOR).doesNotHaveAttribute('readOnly');
+ assert.dom(FIELD_BUCKET_NAME).isNotDisabled();
+ assert.dom(FIELD_BUCKET_PREFIX).isNotDisabled();
+ assert.dom(FIELD_BUCKET_NAME).doesNotHaveAttribute('readOnly');
+ assert.dom(FIELD_BUCKET_PREFIX).doesNotHaveAttribute('readOnly');
- await click(SAVE_BTN_SELECTOR);
+ await click(commonSelectors.SAVE_BTN);
const storageBucket = this.server.schema.storageBuckets.findBy({
- name: NAME_FIELD_TEXT,
+ name: commonSelectors.FIELD_NAME_VALUE,
});
- assert.strictEqual(storageBucket.name, NAME_FIELD_TEXT);
+ assert.strictEqual(storageBucket.name, commonSelectors.FIELD_NAME_VALUE);
assert.strictEqual(storageBucket.scopeId, 'global');
assert.strictEqual(getStorageBucketCount(), storageBucketCount + 1);
});
@@ -106,22 +100,25 @@ module(
const storageBucketCount = getStorageBucketCount();
await visit(urls.enableSessionRecording);
- await click(`[href="${urls.newStorageBucket}"]`);
- await fillIn(NAME_FIELD_SELECTOR, NAME_FIELD_TEXT);
- await click(`[value="${instances.scopes.org.scope.id}"]`);
- await fillIn(EDITOR_WORKER_FILTER, EDITOR_WORKER_FILTER_VALUE);
+ await click(commonSelectors.HREF(urls.newStorageBucket));
+ await fillIn(
+ commonSelectors.FIELD_NAME,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ await click(FIELD_SCOPE(instances.scopes.org.scope.id));
+ await fillIn(FIELD_EDITOR, WORKER_FILTER_VALUE);
- assert.dom(BUCKET_NAME_FIELD_SELECTOR).isNotDisabled();
- assert.dom(BUCKET_PREFIX_FIELD_SELECTOR).isNotDisabled();
- assert.dom(BUCKET_NAME_FIELD_SELECTOR).doesNotHaveAttribute('readOnly');
- assert.dom(BUCKET_PREFIX_FIELD_SELECTOR).doesNotHaveAttribute('readOnly');
+ assert.dom(FIELD_BUCKET_NAME).isNotDisabled();
+ assert.dom(FIELD_BUCKET_PREFIX).isNotDisabled();
+ assert.dom(FIELD_BUCKET_NAME).doesNotHaveAttribute('readOnly');
+ assert.dom(FIELD_BUCKET_PREFIX).doesNotHaveAttribute('readOnly');
- await click(SAVE_BTN_SELECTOR);
+ await click(commonSelectors.SAVE_BTN);
const storageBucket = this.server.schema.storageBuckets.findBy({
- name: NAME_FIELD_TEXT,
+ name: commonSelectors.FIELD_NAME_VALUE,
});
- assert.strictEqual(storageBucket.name, NAME_FIELD_TEXT);
+ assert.strictEqual(storageBucket.name, commonSelectors.FIELD_NAME_VALUE);
assert.strictEqual(storageBucket.scopeId, instances.scopes.org.scope.id);
assert.strictEqual(getStorageBucketCount(), storageBucketCount + 1);
});
@@ -130,15 +127,20 @@ module(
const storageBucketCount = getStorageBucketCount();
await visit(urls.enableSessionRecording);
- await click(`[href="${urls.newStorageBucket}"]`);
- await fillIn(NAME_FIELD_SELECTOR, NAME_FIELD_TEXT);
- await click(CANCEL_BTN_SELECTOR);
+ await click(commonSelectors.HREF(urls.newStorageBucket));
+ await fillIn(
+ commonSelectors.FIELD_NAME,
+ commonSelectors.FIELD_NAME_VALUE,
+ );
+ await click(commonSelectors.CANCEL_BTN);
assert.strictEqual(currentURL(), urls.enableSessionRecording);
assert.strictEqual(getStorageBucketCount(), storageBucketCount);
});
test('saving a new storage bucket with invalid fields displays error messages', async function (assert) {
+ const errorMessage = 'The request was invalid.';
+ const errorDescription = 'Name is required.';
this.server.post('/storage-buckets', () => {
return new Response(
400,
@@ -146,12 +148,12 @@ module(
{
status: 400,
code: 'invalid_argument',
- message: 'The request was invalid.',
+ message: errorMessage,
details: {
request_fields: [
{
name: 'name',
- description: 'Name is required.',
+ description: errorDescription,
},
],
},
@@ -160,14 +162,12 @@ module(
});
await visit(urls.enableSessionRecording);
- await click(`[href="${urls.newStorageBucket}"]`);
- await fillIn(EDITOR_WORKER_FILTER, EDITOR_WORKER_FILTER_VALUE);
- await click(SAVE_BTN_SELECTOR);
+ await click(commonSelectors.HREF(urls.newStorageBucket));
+ await fillIn(FIELD_EDITOR, WORKER_FILTER_VALUE);
+ await click(commonSelectors.SAVE_BTN);
- assert
- .dom(commonSelectors.ALERT_TOAST_BODY)
- .hasText('The request was invalid.');
- assert.dom(FIELD_ERROR_TEXT_SELECTOR).hasText('Name is required.');
+ assert.dom(commonSelectors.ALERT_TOAST_BODY).hasText(errorMessage);
+ assert.dom(commonSelectors.FIELD_NAME_ERROR).hasText(errorDescription);
});
},
);
diff --git a/ui/admin/tests/acceptance/targets/enable-session-recording/index-test.js b/ui/admin/tests/acceptance/targets/enable-session-recording/index-test.js
index c42520dcc..aef7ed499 100644
--- a/ui/admin/tests/acceptance/targets/enable-session-recording/index-test.js
+++ b/ui/admin/tests/acceptance/targets/enable-session-recording/index-test.js
@@ -11,6 +11,8 @@ import a11yAudit from 'ember-a11y-testing/test-support/audit';
import { authenticateSession } from 'ember-simple-auth/test-support';
import { TYPE_TARGET_SSH } from 'api/models/target';
import select from '@ember/test-helpers/dom/select';
+import * as commonSelectors from 'admin/tests/helpers/selectors';
+import * as selectors from '../selectors';
module(
'Acceptance | targets | enable session recording | index',
@@ -22,17 +24,13 @@ module(
let storageBucketOne;
let storageBucketTwo;
- const SETTINGS_LINK_SELECTOR = '.target-sidebar .hds-link-standalone';
- const ENABLE_BUTTON_SELECTOR = '.target-sidebar .hds-button';
- const DROPDOWN_SELECTOR = '[name=storage_bucket_id]';
- const LINK_LIST_SELECTOR = '.link-list-item > a';
- const LINK_LIST_SELECTOR_ITEM_TEXT = '.link-list-item__text';
- const BADGE_TEXT_SELECTOR = '.target-sidebar .hds-badge__text';
- const TOGGLE_SELECTOR = '[name=target-enable-session-recording]';
+ const SESSION_RECORDING_SETTINGS_LINK =
+ '.target-sidebar .hds-link-standalone';
+ const SESSION_RECORDING_ENABLE_BTN = '.target-sidebar .hds-button';
+ const ENABLE_TOGGLE = '[name=target-enable-session-recording]';
+ const BADGE_TEXT = '.target-sidebar .hds-badge__text';
const LINK_TO_NEW_STORAGE_BUCKET =
'.enable-session-recording-toggle .hds-link-standalone';
- const SAVE_BTN_SELECTOR = '.rose-form-actions [type="submit"]';
- const CANCEL_BTN_SELECTOR = '.rose-form-actions [type="button"]';
// Instances
const instances = {
@@ -45,9 +43,6 @@ module(
//URLs
const urls = {
- globalScope: null,
- orgScope: null,
- projectScope: null,
targets: null,
target: null,
enableSessionRecording: null,
@@ -82,13 +77,10 @@ module(
storageBucketTwo = instances.storageBucket[1];
// Generate route URLs for resources
- urls.globalScope = `/scopes/global`;
- urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`;
- urls.projectScope = `/scopes/${instances.scopes.project.id}`;
- urls.targets = `${urls.projectScope}/targets`;
+ urls.targets = `/scopes/${instances.scopes.project.id}/targets`;
urls.target = `${urls.targets}/${instances.target.id}`;
urls.enableSessionRecording = `${urls.target}/enable-session-recording`;
- urls.storageBuckets = `${urls.globalScope}/storage-buckets`;
+ urls.storageBuckets = '/scopes/global/storage-buckets';
urls.newStorageBucket = `${urls.enableSessionRecording}/create-storage-bucket`;
urls.storageBucket = `${urls.storageBuckets}/${storageBucketOne.id}`;
@@ -99,16 +91,21 @@ module(
test('cannot enable session recording for a target without proper authorization', async function (assert) {
assert.false(featuresService.isEnabled('ssh-session-recording'));
+
await visit(urls.target);
await a11yAudit();
- assert.dom('.target-sidebar a').doesNotExist();
+
+ assert.dom(SESSION_RECORDING_ENABLE_BTN).doesNotExist();
});
test('users can click on enable-recording button in target session-recording sidebar and it takes them to enable session recording', async function (assert) {
featuresService.enable('ssh-session-recording');
await visit(urls.target);
- assert.dom(SETTINGS_LINK_SELECTOR).doesNotExist();
- await click(ENABLE_BUTTON_SELECTOR);
+
+ assert.dom(SESSION_RECORDING_SETTINGS_LINK).doesNotExist();
+
+ await click(SESSION_RECORDING_ENABLE_BTN);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
});
@@ -119,7 +116,8 @@ module(
enableSessionRecording: true,
});
await visit(urls.target);
- await click(SETTINGS_LINK_SELECTOR);
+ await click(SESSION_RECORDING_SETTINGS_LINK);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
});
@@ -130,37 +128,45 @@ module(
enableSessionRecording: true,
});
await visit(urls.target);
- await click(LINK_LIST_SELECTOR);
+ await click(selectors.LINK_LIST_ITEM);
+
assert.strictEqual(currentURL(), urls.storageBucket);
});
test('toggle should be disabled and storage buckets list should be shown when enable session recording button is clicked', async function (assert) {
featuresService.enable('ssh-session-recording');
await visit(urls.target);
- await click(ENABLE_BUTTON_SELECTOR);
+ await click(SESSION_RECORDING_ENABLE_BTN);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
- assert.dom(TOGGLE_SELECTOR).isVisible();
- assert.dom(DROPDOWN_SELECTOR).isNotVisible();
+ assert.dom(ENABLE_TOGGLE).isVisible();
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).isNotVisible();
});
test('storage buckets list is hidden when toggle is disabled', async function (assert) {
featuresService.enable('ssh-session-recording');
await visit(urls.target);
- await click(ENABLE_BUTTON_SELECTOR);
+ await click(SESSION_RECORDING_ENABLE_BTN);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
- assert.dom(TOGGLE_SELECTOR).isVisible();
- assert.dom(DROPDOWN_SELECTOR).isNotVisible();
- await click(TOGGLE_SELECTOR);
- assert.dom(DROPDOWN_SELECTOR).isVisible();
+ assert.dom(ENABLE_TOGGLE).isVisible();
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).isNotVisible();
+
+ await click(ENABLE_TOGGLE);
+
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).isVisible();
});
test('link to add new storage bucket should be displayed and redirect to new storage buckets form', async function (assert) {
featuresService.enable('ssh-session-recording');
await visit(urls.target);
- await click(ENABLE_BUTTON_SELECTOR);
+ await click(SESSION_RECORDING_ENABLE_BTN);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
assert.dom(LINK_TO_NEW_STORAGE_BUCKET).isVisible();
+
await click(LINK_TO_NEW_STORAGE_BUCKET);
+
assert.strictEqual(currentURL(), urls.newStorageBucket);
});
@@ -171,45 +177,54 @@ module(
enable_session_recording: true,
});
await visit(urls.target);
- await click(SETTINGS_LINK_SELECTOR);
+ await click(SESSION_RECORDING_SETTINGS_LINK);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
- const existingStorageBucketId = find(DROPDOWN_SELECTOR).value;
+ const existingStorageBucketId = find(
+ selectors.STORAGE_BUCKET_DROPDOWN,
+ ).value;
//disable the toggle, dropdown should be hidden
- await click(TOGGLE_SELECTOR);
- assert.dom(DROPDOWN_SELECTOR).isNotVisible();
+ await click(ENABLE_TOGGLE);
+
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).isNotVisible();
//enable the toggle now,
//it should have the previously selected storage_bucket_id
- await click(TOGGLE_SELECTOR);
- assert.dom(DROPDOWN_SELECTOR).hasValue(existingStorageBucketId);
+ await click(ENABLE_TOGGLE);
+
+ assert
+ .dom(selectors.STORAGE_BUCKET_DROPDOWN)
+ .hasValue(existingStorageBucketId);
});
test('can assign a storage bucket for the target', async function (assert) {
featuresService.enable('ssh-session-recording');
await visit(urls.target);
- await click(ENABLE_BUTTON_SELECTOR);
+ await click(SESSION_RECORDING_ENABLE_BTN);
assert.strictEqual(currentURL(), urls.enableSessionRecording);
- await click(TOGGLE_SELECTOR);
- assert.dom(DROPDOWN_SELECTOR).hasNoValue();
- await select(DROPDOWN_SELECTOR, storageBucketTwo.id);
- assert.dom(DROPDOWN_SELECTOR).hasValue();
- await click(SAVE_BTN_SELECTOR);
+
+ await click(ENABLE_TOGGLE);
+
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).hasNoValue();
+
+ await select(selectors.STORAGE_BUCKET_DROPDOWN, storageBucketTwo.id);
+
+ assert.dom(selectors.STORAGE_BUCKET_DROPDOWN).hasValue();
+
+ await click(commonSelectors.SAVE_BTN);
assert.strictEqual(currentURL(), urls.target);
- assert.strictEqual(
- find(BADGE_TEXT_SELECTOR).textContent.trim(),
- intl.t(
- `resources.storage-bucket.plugin-types.${storageBucketTwo.plugin.name}`,
- ),
- );
-
- assert.strictEqual(
- find(LINK_LIST_SELECTOR_ITEM_TEXT).textContent.trim(),
- storageBucketTwo.name,
- );
+ assert
+ .dom(BADGE_TEXT)
+ .hasText(
+ intl.t(
+ `resources.storage-bucket.plugin-types.${storageBucketTwo.plugin.name}`,
+ ),
+ );
+ assert.dom(selectors.LINK_LIST_ITEM_TEXT).hasText(storageBucketTwo.name);
});
test('can cancel changes to an existing storage bucket selection', async function (assert) {
@@ -220,25 +235,23 @@ module(
});
await visit(urls.target);
- await click(SETTINGS_LINK_SELECTOR);
+ await click(SESSION_RECORDING_SETTINGS_LINK);
+
assert.strictEqual(currentURL(), urls.enableSessionRecording);
//update the storage bucket selection
- await select(DROPDOWN_SELECTOR, storageBucketTwo);
+ await select(selectors.STORAGE_BUCKET_DROPDOWN, storageBucketTwo);
+ await click(commonSelectors.CANCEL_BTN);
- await click(CANCEL_BTN_SELECTOR);
assert.strictEqual(currentURL(), urls.target);
- assert.strictEqual(
- find(BADGE_TEXT_SELECTOR).textContent.trim(),
- intl.t(
- `resources.storage-bucket.plugin-types.${storageBucketOne.plugin.name}`,
- ),
- );
-
- assert.strictEqual(
- find(LINK_LIST_SELECTOR_ITEM_TEXT).textContent.trim(),
- storageBucketOne.name,
- );
+ assert
+ .dom(BADGE_TEXT)
+ .hasText(
+ intl.t(
+ `resources.storage-bucket.plugin-types.${storageBucketOne.plugin.name}`,
+ ),
+ );
+ assert.dom(selectors.LINK_LIST_ITEM_TEXT).hasText(storageBucketOne.name);
});
},
);
diff --git a/ui/admin/tests/acceptance/targets/selectors.js b/ui/admin/tests/acceptance/targets/selectors.js
index e986a7121..60f299ddb 100644
--- a/ui/admin/tests/acceptance/targets/selectors.js
+++ b/ui/admin/tests/acceptance/targets/selectors.js
@@ -49,6 +49,8 @@ export const RECORDING_SETTINGS_LINK = '.target-sidebar .hds-link-standalone';
export const LINK_LIST_ITEM = '.link-list-item > a';
export const LINK_LIST_ITEM_TEXT = '.link-list-item__text';
+export const STORAGE_BUCKET_DROPDOWN = '[name=storage_bucket_id]';
+
export const NO_RESULTS_MSG = '[data-test-no-target-results]';
export const TABLE_ACTIVE_SESSIONS = (id) =>
`tbody [data-test-targets-table-row="${id}"] .hds-table__td:nth-child(3) a`;