From 131e1b01baef03fa42ba72a1873042b69b21bddc Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 10:06:23 -0500 Subject: [PATCH 01/32] Add readme --- ui/tests/_README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 ui/tests/_README.md diff --git a/ui/tests/_README.md b/ui/tests/_README.md new file mode 100644 index 000000000000..a102b3a798aa --- /dev/null +++ b/ui/tests/_README.md @@ -0,0 +1,27 @@ +# Test Helpers Organization + +Our test are constantly evolving, but here's a general overview of how the tests and selectors organization + +## Folder organization + +### acceptance + +Acceptance tests should test the overall workflows and navigation within Vault. When possible, they should use the real API instead of mocked so that breaking changes from the backend can be caught. Reasons you may opt to use a mocked backend instead of the real one: + +- Using the real backend would cause instability in concurrently-running tests (eg. seal/unseal flow) +- There isn't a way to set up a 3rd party dependency that the backend needs to run correctly (Database Secrets Engine, Sync Secrets) + +### helpers + +### integration + +### pages + +[DEPRECATED] This file should be removed in favor of selectors within the "helpers" folder + +### unit + +## Process + +- Rename export from `general-selectors` to `GENERAL` +- From fdba7e64db51ef94b73e3656c27b9565bf995293 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 10:06:33 -0500 Subject: [PATCH 02/32] Rename general selectors export --- .../access/identity/entities/index-test.js | 2 +- ui/tests/helpers/clients.js | 2 +- .../helpers/config-ui/message-selectors.js | 2 +- ui/tests/helpers/general-selectors.js | 2 +- ui/tests/helpers/sync/sync-selectors.js | 2 +- .../auth-config-form/options-test.js | 56 +++++++++---------- .../components/kv-suggestion-input-test.js | 4 +- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ui/tests/acceptance/access/identity/entities/index-test.js b/ui/tests/acceptance/access/identity/entities/index-test.js index 8bb80fb28fab..5ede89efcfc4 100644 --- a/ui/tests/acceptance/access/identity/entities/index-test.js +++ b/ui/tests/acceptance/access/identity/entities/index-test.js @@ -9,7 +9,7 @@ import { setupApplicationTest } from 'ember-qunit'; import page from 'vault/tests/pages/access/identity/index'; import authPage from 'vault/tests/pages/auth'; import { runCmd } from 'vault/tests/helpers/commands'; -import { SELECTORS as GENERAL } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { v4 as uuidv4 } from 'uuid'; const SELECTORS = { diff --git a/ui/tests/helpers/clients.js b/ui/tests/helpers/clients.js index 38dea95fd78e..79c7d50b916b 100644 --- a/ui/tests/helpers/clients.js +++ b/ui/tests/helpers/clients.js @@ -4,7 +4,7 @@ */ import { Response } from 'miragejs'; -import { SELECTORS as GENERAL } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { click } from '@ember/test-helpers'; import { LICENSE_START } from 'vault/mirage/handlers/clients'; diff --git a/ui/tests/helpers/config-ui/message-selectors.js b/ui/tests/helpers/config-ui/message-selectors.js index f33b433d3b83..29adc18109c8 100644 --- a/ui/tests/helpers/config-ui/message-selectors.js +++ b/ui/tests/helpers/config-ui/message-selectors.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { SELECTORS as GENERAL } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; export const PAGE = { // General selectors that are common between pages diff --git a/ui/tests/helpers/general-selectors.js b/ui/tests/helpers/general-selectors.js index ea736f61e08f..570c3b955aad 100644 --- a/ui/tests/helpers/general-selectors.js +++ b/ui/tests/helpers/general-selectors.js @@ -5,7 +5,7 @@ import { findAll } from '@ember/test-helpers'; -export const SELECTORS = { +export const GENERAL = { breadcrumb: '[data-test-breadcrumbs] li', breadcrumbAtIdx: (idx) => `[data-test-breadcrumbs] li:nth-child(${idx + 1}) a`, breadcrumbs: '[data-test-breadcrumbs]', diff --git a/ui/tests/helpers/sync/sync-selectors.js b/ui/tests/helpers/sync/sync-selectors.js index 2bd7d9cc3f63..9a7123b45bd9 100644 --- a/ui/tests/helpers/sync/sync-selectors.js +++ b/ui/tests/helpers/sync/sync-selectors.js @@ -4,7 +4,7 @@ */ import { click, fillIn } from '@ember/test-helpers'; -import { SELECTORS as GENERAL } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; export const PAGE = { ...GENERAL, diff --git a/ui/tests/integration/components/auth-config-form/options-test.js b/ui/tests/integration/components/auth-config-form/options-test.js index c55b16a97c46..8f51ae81eb61 100644 --- a/ui/tests/integration/components/auth-config-form/options-test.js +++ b/ui/tests/integration/components/auth-config-form/options-test.js @@ -8,7 +8,7 @@ import { setupRenderingTest } from 'ember-qunit'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { click, fillIn, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; -import { SELECTORS } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { methods } from 'vault/helpers/mountable-auth-methods'; const userLockoutSupported = ['approle', 'ldap', 'userpass']; @@ -66,24 +66,24 @@ module('Integration | Component | auth-config-form options', function (hooks) { assert.dom('[data-test-user-lockout-section]').hasText('User lockout configuration'); - await click(SELECTORS.inputByAttr('config.listingVisibility')); - await fillIn(SELECTORS.inputByAttr('config.tokenType'), 'default-batch'); + await click(GENERAL.inputByAttr('config.listingVisibility')); + await fillIn(GENERAL.inputByAttr('config.tokenType'), 'default-batch'); - await click(SELECTORS.ttl.toggle('Default Lease TTL')); - await fillIn(SELECTORS.ttl.input('Default Lease TTL'), '30'); + await click(GENERAL.ttl.toggle('Default Lease TTL')); + await fillIn(GENERAL.ttl.input('Default Lease TTL'), '30'); - await fillIn(SELECTORS.inputByAttr('config.lockoutThreshold'), '7'); + await fillIn(GENERAL.inputByAttr('config.lockoutThreshold'), '7'); - await click(SELECTORS.ttl.toggle('Lockout duration')); - await fillIn(SELECTORS.ttl.input('Lockout duration'), '10'); + await click(GENERAL.ttl.toggle('Lockout duration')); + await fillIn(GENERAL.ttl.input('Lockout duration'), '10'); await fillIn( - `${SELECTORS.inputByAttr('config.lockoutDuration')} ${SELECTORS.selectByAttr('ttl-unit')}`, + `${GENERAL.inputByAttr('config.lockoutDuration')} ${GENERAL.selectByAttr('ttl-unit')}`, 'm' ); - await click(SELECTORS.ttl.toggle('Lockout counter reset')); - await fillIn(SELECTORS.ttl.input('Lockout counter reset'), '5'); + await click(GENERAL.ttl.toggle('Lockout counter reset')); + await fillIn(GENERAL.ttl.input('Lockout counter reset'), '5'); - await click(SELECTORS.inputByAttr('config.lockoutDisable')); + await click(GENERAL.inputByAttr('config.lockoutDisable')); await click('[data-test-save-config]'); }); @@ -124,23 +124,23 @@ module('Integration | Component | auth-config-form options', function (hooks) { .dom('[data-test-user-lockout-section]') .doesNotExist(`${type} method does not render user lockout section`); - await click(SELECTORS.inputByAttr('config.listingVisibility')); - await fillIn(SELECTORS.inputByAttr('config.tokenType'), 'default-batch'); + await click(GENERAL.inputByAttr('config.listingVisibility')); + await fillIn(GENERAL.inputByAttr('config.tokenType'), 'default-batch'); - await click(SELECTORS.ttl.toggle('Default Lease TTL')); - await fillIn(SELECTORS.ttl.input('Default Lease TTL'), '30'); + await click(GENERAL.ttl.toggle('Default Lease TTL')); + await fillIn(GENERAL.ttl.input('Default Lease TTL'), '30'); assert - .dom(SELECTORS.inputByAttr('config.lockoutThreshold')) + .dom(GENERAL.inputByAttr('config.lockoutThreshold')) .doesNotExist(`${type} method does not render lockout threshold`); assert - .dom(SELECTORS.ttl.toggle('Lockout duration')) + .dom(GENERAL.ttl.toggle('Lockout duration')) .doesNotExist(`${type} method does not render lockout duration `); assert - .dom(SELECTORS.ttl.toggle('Lockout counter reset')) + .dom(GENERAL.ttl.toggle('Lockout counter reset')) .doesNotExist(`${type} method does not render lockout counter reset`); assert - .dom(SELECTORS.inputByAttr('config.lockoutDisable')) + .dom(GENERAL.inputByAttr('config.lockoutDisable')) .doesNotExist(`${type} method does not render lockout disable`); await click('[data-test-save-config]'); @@ -175,25 +175,25 @@ module('Integration | Component | auth-config-form options', function (hooks) { await render(hbs``); assert - .dom(SELECTORS.inputByAttr('config.tokenType')) + .dom(GENERAL.inputByAttr('config.tokenType')) .doesNotExist('does not render tokenType for token auth method'); - await click(SELECTORS.inputByAttr('config.listingVisibility')); - await click(SELECTORS.ttl.toggle('Default Lease TTL')); - await fillIn(SELECTORS.ttl.input('Default Lease TTL'), '30'); + await click(GENERAL.inputByAttr('config.listingVisibility')); + await click(GENERAL.ttl.toggle('Default Lease TTL')); + await fillIn(GENERAL.ttl.input('Default Lease TTL'), '30'); assert.dom('[data-test-user-lockout-section]').doesNotExist('token does not render user lockout section'); assert - .dom(SELECTORS.inputByAttr('config.lockoutThreshold')) + .dom(GENERAL.inputByAttr('config.lockoutThreshold')) .doesNotExist('token method does not render lockout threshold'); assert - .dom(SELECTORS.ttl.toggle('Lockout duration')) + .dom(GENERAL.ttl.toggle('Lockout duration')) .doesNotExist('token method does not render lockout duration '); assert - .dom(SELECTORS.ttl.toggle('Lockout counter reset')) + .dom(GENERAL.ttl.toggle('Lockout counter reset')) .doesNotExist('token method does not render lockout counter reset'); assert - .dom(SELECTORS.inputByAttr('config.lockoutDisable')) + .dom(GENERAL.inputByAttr('config.lockoutDisable')) .doesNotExist('token method does not render lockout disable'); await click('[data-test-save-config]'); diff --git a/ui/tests/integration/components/kv-suggestion-input-test.js b/ui/tests/integration/components/kv-suggestion-input-test.js index 6fae4067cd62..d75cc31de6d7 100644 --- a/ui/tests/integration/components/kv-suggestion-input-test.js +++ b/ui/tests/integration/components/kv-suggestion-input-test.js @@ -8,12 +8,12 @@ import { setupRenderingTest } from 'ember-qunit'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { render, click, fillIn, settled, typeIn } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; -import { SELECTORS } from 'vault/tests/helpers/general-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; const { searchSelect: { option, options }, kvSuggestion: { input }, -} = SELECTORS; +} = GENERAL; module('Integration | Component | kv-suggestion-input', function (hooks) { setupRenderingTest(hooks); From 2e68dd42db94f5db4d813b8d90d3c9eea752ddc8 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 10:39:18 -0500 Subject: [PATCH 03/32] reorg clients helper -- all clients tests pass --- ui/tests/acceptance/clients/counts-test.js | 11 ++++++----- .../clients/counts/overview-test.js | 19 ++++++++++--------- .../acceptance/clients/counts/sync-test.js | 7 ++++--- ui/tests/helpers/clients.js | 19 ++++++++++++++++--- ui/tests/helpers/general-selectors.js | 16 ---------------- .../components/clients/page/counts-test.js | 11 +++++++---- .../components/clients/page/sync-test.js | 9 +++++---- .../components/clients/page/token-test.js | 3 ++- 8 files changed, 50 insertions(+), 45 deletions(-) diff --git a/ui/tests/acceptance/clients/counts-test.js b/ui/tests/acceptance/clients/counts-test.js index dcf81c7014cc..e6424f844845 100644 --- a/ui/tests/acceptance/clients/counts-test.js +++ b/ui/tests/acceptance/clients/counts-test.js @@ -10,6 +10,7 @@ import clientsHandler, { STATIC_NOW } from 'vault/mirage/handlers/clients'; import sinon from 'sinon'; import { visit, click, currentURL } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS as ts } from 'vault/tests/helpers/clients'; import timestamp from 'core/utils/timestamp'; @@ -36,8 +37,8 @@ module('Acceptance | clients | counts', function (hooks) { this.owner.lookup('service:version').type = 'community'; await visit('/vault/clients/counts/overview'); - assert.dom(ts.emptyStateTitle).hasText('No data received'); - assert.dom(ts.emptyStateMessage).hasText('Select a start date above to query client count data.'); + assert.dom(GENERAL.emptyStateTitle).hasText('No data received'); + assert.dom(GENERAL.emptyStateMessage).hasText('Select a start date above to query client count data.'); }); test('it should redirect to counts overview route for transitions to parent', async function (assert) { @@ -52,14 +53,14 @@ module('Acceptance | clients | counts', function (hooks) { const timeQueryRegex = /end_time=\d+&start_time=\d+/g; assert.ok(currentURL().match(timeQueryRegex).length, 'Start and end times added as query params'); - await click(ts.tab('token')); + await click(GENERAL.tab('token')); assert.ok( currentURL().match(timeQueryRegex).length, 'Start and end times persist through child route change' ); - await click(ts.navLink('Dashboard')); - await click(ts.navLink('Client Count')); + await click(GENERAL.navLink('Dashboard')); + await click(GENERAL.navLink('Client Count')); assert.strictEqual( currentURL(), '/vault/clients/counts/overview', diff --git a/ui/tests/acceptance/clients/counts/overview-test.js b/ui/tests/acceptance/clients/counts/overview-test.js index 2d136961a972..aea4262c9d0a 100644 --- a/ui/tests/acceptance/clients/counts/overview-test.js +++ b/ui/tests/acceptance/clients/counts/overview-test.js @@ -11,6 +11,7 @@ import sinon from 'sinon'; import { visit, click, findAll, settled } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { ARRAY_OF_MONTHS } from 'core/utils/date-formatters'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS } from 'vault/tests/helpers/clients'; import { create } from 'ember-cli-page-object'; import { clickTrigger } from 'ember-power-select/test-support/helpers'; @@ -40,9 +41,9 @@ module('Acceptance | clients | overview', function (hooks) { }); test('it should render the correct tabs', async function (assert) { - assert.dom(SELECTORS.tab('overview')).exists(); - assert.dom(SELECTORS.tab('token')).exists(); - assert.dom(SELECTORS.tab('config')).exists(); + assert.dom(GENERAL.tab('overview')).exists(); + assert.dom(GENERAL.tab('token')).exists(); + assert.dom(GENERAL.tab('config')).exists(); }); test('it should render charts', async function (assert) { @@ -270,17 +271,17 @@ module('Acceptance | clients | overview | sync in license, activated', function }); test('it should render the correct tabs', async function (assert) { - assert.dom(SELECTORS.tab('sync')).exists(); + assert.dom(GENERAL.tab('sync')).exists(); }); test('it should show secrets sync data in overview and tab', async function (assert) { assert .dom(SELECTORS.charts.statTextValue('Secrets sync clients')) .exists('shows secret sync data on overview'); - await click(SELECTORS.tab('sync')); + await click(GENERAL.tab('sync')); - assert.dom(SELECTORS.tab('sync')).hasClass('active'); - assert.dom(SELECTORS.emptyStateTitle).doesNotExist(); + assert.dom(GENERAL.tab('sync')).hasClass('active'); + assert.dom(GENERAL.emptyStateTitle).doesNotExist(); assert .dom(SELECTORS.charts.chart('Secrets sync usage')) .exists('chart is shown because feature is active and has data'); @@ -300,7 +301,7 @@ module('Acceptance | clients | overview | sync in license, not activated', funct }); test('it should show the secrets sync tab', async function (assert) { - assert.dom(SELECTORS.tab('sync')).exists('sync tab is shown because feature is in license'); + assert.dom(GENERAL.tab('sync')).exists('sync tab is shown because feature is in license'); }); test('it should hide secrets sync charts', async function (assert) { @@ -326,7 +327,7 @@ module('Acceptance | clients | overview | sync not in license', function (hooks) }); test('it should hide the secrets sync tab', async function (assert) { - assert.dom(SELECTORS.tab('sync')).doesNotExist(); + assert.dom(GENERAL.tab('sync')).doesNotExist(); }); test('it should hide secrets sync charts', async function (assert) { diff --git a/ui/tests/acceptance/clients/counts/sync-test.js b/ui/tests/acceptance/clients/counts/sync-test.js index 4fc5ffa8dc65..e5e80b5b0cf1 100644 --- a/ui/tests/acceptance/clients/counts/sync-test.js +++ b/ui/tests/acceptance/clients/counts/sync-test.js @@ -12,6 +12,7 @@ import { visit, click, currentURL } from '@ember/test-helpers'; import sinon from 'sinon'; import timestamp from 'core/utils/timestamp'; import authPage from 'vault/tests/pages/auth'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS } from 'vault/tests/helpers/clients'; module('Acceptance | clients | sync | activated', function (hooks) { @@ -37,7 +38,7 @@ module('Acceptance | clients | sync | activated', function (hooks) { assert.dom(SELECTORS.charts.chart('Secrets sync usage')).exists('Secrets sync usage chart is rendered'); assert.dom(SELECTORS.syncTab.total).exists('Total sync clients chart is rendered'); - assert.dom(SELECTORS.emptyStateTitle).doesNotExist(); + assert.dom(GENERAL.emptyStateTitle).doesNotExist(); }); }); @@ -84,9 +85,9 @@ module('Acceptance | clients | sync | not activated', function (hooks) { }; }); - assert.dom(SELECTORS.emptyStateTitle).exists('Shows empty state when secrets-sync is not activated'); + assert.dom(GENERAL.emptyStateTitle).exists('Shows empty state when secrets-sync is not activated'); - await click(`${SELECTORS.emptyStateActions} .hds-link-standalone`); + await click(`${GENERAL.emptyStateActions} .hds-link-standalone`); assert.strictEqual( currentURL(), '/vault/sync/secrets/overview', diff --git a/ui/tests/helpers/clients.js b/ui/tests/helpers/clients.js index 79c7d50b916b..0febcb8aa05c 100644 --- a/ui/tests/helpers/clients.js +++ b/ui/tests/helpers/clients.js @@ -4,7 +4,6 @@ */ import { Response } from 'miragejs'; -import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { click } from '@ember/test-helpers'; import { LICENSE_START } from 'vault/mirage/handlers/clients'; @@ -27,7 +26,6 @@ import { addMonths } from 'date-fns'; License start date this month */ export const SELECTORS = { - ...GENERAL, counts: { startLabel: '[data-test-counts-start-label]', description: '[data-test-counts-description]', @@ -77,7 +75,22 @@ export const SELECTORS = { monthDropdown: '[data-test-toggle-month]', yearDropdown: '[data-test-toggle-year]', currentBillingPeriod: '[data-test-current-billing-period]', - dateDropdownSubmit: '[data-test-date-dropdown-submit]', + dateDropdown: { + toggleMonth: '[data-test-toggle-month]', + toggleYear: '[data-test-toggle-year]', + selectMonth: (month) => `[data-test-dropdown-month="${month}"]`, + selectYear: (year) => `[data-test-dropdown-year="${year}"]`, + submit: '[data-test-date-dropdown-submit]', + }, + calendarWidget: { + trigger: '[data-test-calendar-widget-trigger]', + currentMonth: '[data-test-current-month]', + currentBillingPeriod: '[data-test-current-billing-period]', + customEndMonth: '[data-test-show-calendar]', + previousYear: '[data-test-previous-year]', + nextYear: '[data-test-next-year]', + calendarMonth: (month) => `[data-test-calendar-month="${month}"]`, + }, runningTotalMonthStats: '[data-test-running-total="single-month-stats"]', runningTotalMonthlyCharts: '[data-test-running-total="monthly-charts"]', selectedAuthMount: 'div#auth-method-search-select [data-test-selected-option] div', diff --git a/ui/tests/helpers/general-selectors.js b/ui/tests/helpers/general-selectors.js index 570c3b955aad..2b62258401e9 100644 --- a/ui/tests/helpers/general-selectors.js +++ b/ui/tests/helpers/general-selectors.js @@ -24,22 +24,6 @@ export const GENERAL = { emptyStateActions: '[data-test-empty-state-actions]', menuTrigger: '[data-test-popup-menu-trigger]', listItem: '[data-test-list-item-link]', - calendarWidget: { - trigger: '[data-test-calendar-widget-trigger]', - currentMonth: '[data-test-current-month]', - currentBillingPeriod: '[data-test-current-billing-period]', - customEndMonth: '[data-test-show-calendar]', - previousYear: '[data-test-previous-year]', - nextYear: '[data-test-next-year]', - calendarMonth: (month) => `[data-test-calendar-month="${month}"]`, - }, - dateDropdown: { - toggleMonth: '[data-test-toggle-month]', - toggleYear: '[data-test-toggle-year]', - selectMonth: (month) => `[data-test-dropdown-month="${month}"]`, - selectYear: (year) => `[data-test-dropdown-year="${year}"]`, - submit: '[data-test-date-dropdown-submit]', - }, // FORMS infoRowLabel: (label) => `[data-test-row-label="${label}"]`, infoRowValue: (label) => `[data-test-value-div="${label}"]`, diff --git a/ui/tests/integration/components/clients/page/counts-test.js b/ui/tests/integration/components/clients/page/counts-test.js index b65b7978504e..425d8d4479af 100644 --- a/ui/tests/integration/components/clients/page/counts-test.js +++ b/ui/tests/integration/components/clients/page/counts-test.js @@ -10,6 +10,7 @@ import { render, click, settled, findAll } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS as ts, dateDropdownSelect } from 'vault/tests/helpers/clients'; import { selectChoose } from 'ember-power-select/test-support/helpers'; import timestamp from 'core/utils/timestamp'; @@ -99,7 +100,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); assert - .dom(ts.emptyStateTitle) + .dom(GENERAL.emptyStateTitle) .hasText('No data received from July 2023 to January 2024', 'No data empty state renders'); }); @@ -109,7 +110,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); - assert.dom(ts.emptyStateTitle).hasText('You are not authorized', 'Activity error empty state renders'); + assert + .dom(GENERAL.emptyStateTitle) + .hasText('You are not authorized', 'Activity error empty state renders'); }); test('it should render config disabled alert', async function (assert) { @@ -246,7 +249,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); - assert.dom(ts.emptyStateTitle).hasText('No start date found', 'Empty state renders'); + assert.dom(GENERAL.emptyStateTitle).hasText('No start date found', 'Empty state renders'); assert.dom(ts.counts.startDropdown).exists('Date dropdown renders when start time is not provided'); }); @@ -256,7 +259,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); assert - .dom(ts.emptyStateTitle) + .dom(GENERAL.emptyStateTitle) .hasText('No data received from July 2023 to January 2024', 'Empty state renders'); }); }); diff --git a/ui/tests/integration/components/clients/page/sync-test.js b/ui/tests/integration/components/clients/page/sync-test.js index 0d75c9ae3bd1..a2c30e1f8a38 100644 --- a/ui/tests/integration/components/clients/page/sync-test.js +++ b/ui/tests/integration/components/clients/page/sync-test.js @@ -10,6 +10,7 @@ import { render, findAll } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS } from 'vault/tests/helpers/clients'; import { formatNumber } from 'core/helpers/format-number'; import { calculateAverage } from 'vault/utils/chart-helpers'; @@ -98,7 +99,7 @@ module('Integration | Component | clients | Clients::Page::Sync', function (hook await this.renderComponent(); assert.dom(charts.chart('Secrets sync usage')).doesNotExist('vertical bar chart does not render'); - assert.dom(SELECTORS.emptyStateTitle).hasText('No monthly secrets sync clients'); + assert.dom(GENERAL.emptyStateTitle).hasText('No monthly secrets sync clients'); const formattedTimestamp = dateFormat([this.activity.responseTimestamp, 'MMM d yyyy, h:mm:ss aaa'], { withTimeZone: true, }); @@ -130,11 +131,11 @@ module('Integration | Component | clients | Clients::Page::Sync', function (hook await this.renderComponent(); - assert.dom(SELECTORS.emptyStateTitle).hasText('No Secrets Sync clients'); + assert.dom(GENERAL.emptyStateTitle).hasText('No Secrets Sync clients'); assert - .dom(SELECTORS.emptyStateMessage) + .dom(GENERAL.emptyStateMessage) .hasText('No data is available because Secrets Sync has not been activated.'); - assert.dom(SELECTORS.emptyStateActions).hasText('Activate Secrets Sync'); + assert.dom(GENERAL.emptyStateActions).hasText('Activate Secrets Sync'); assert.dom(charts.chart('Secrets sync usage')).doesNotExist(); assert.dom(syncTab.total).doesNotExist(); diff --git a/ui/tests/integration/components/clients/page/token-test.js b/ui/tests/integration/components/clients/page/token-test.js index cee69399aa14..35023ca42e04 100644 --- a/ui/tests/integration/components/clients/page/token-test.js +++ b/ui/tests/integration/components/clients/page/token-test.js @@ -13,6 +13,7 @@ import { getUnixTime } from 'date-fns'; import { calculateAverage } from 'vault/utils/chart-helpers'; import { formatNumber } from 'core/helpers/format-number'; import { dateFormat } from 'core/helpers/date-format'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; import { SELECTORS as ts } from 'vault/tests/helpers/clients'; const START_TIME = getUnixTime(LICENSE_START); @@ -151,7 +152,7 @@ module('Integration | Component | clients | Page::Token', function (hooks) { assert.dom(`${chart} ${ts.charts.verticalBar}`).doesNotExist('Chart does not render'); assert.dom(`${chart} ${ts.charts.legend}`).doesNotExist('Legend does not render'); - assert.dom(ts.emptyStateTitle).hasText('No new clients'); + assert.dom(GENERAL.emptyStateTitle).hasText('No new clients'); assert.dom(ts.tokenTab.entity).doesNotExist('New client counts does not exist'); assert.dom(ts.tokenTab.nonentity).doesNotExist('Average new client counts does not exist'); }); From dcf40c3cfb2d1914299932bf25da1fee5fcdcd1f Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 12:50:20 -0500 Subject: [PATCH 04/32] Update custom messages & dashboard selectors --- .../config-ui/messages/messages-test.js | 199 +++++++++--------- .../messages/messages-unauth-auth-test.js | 69 +++--- ui/tests/acceptance/dashboard-test.js | 166 +++++++-------- .../dashboard/dashboard-selectors.js | 2 +- .../helpers/config-ui/message-selectors.js | 5 +- .../messages/page/create-and-edit-test.js | 153 ++++++++------ .../config-ui/messages/page/list-test.js | 20 +- .../components/dashboard/overview-test.js | 72 +++---- .../dashboard/quick-actions-card-test.js | 50 ++--- .../dashboard/replication-card-test.js | 76 +++---- .../dashboard/secrets-engines-card-test.js | 16 +- 11 files changed, 421 insertions(+), 407 deletions(-) diff --git a/ui/tests/acceptance/config-ui/messages/messages-test.js b/ui/tests/acceptance/config-ui/messages/messages-test.js index ee9837549064..da0c64291b0d 100644 --- a/ui/tests/acceptance/config-ui/messages/messages-test.js +++ b/ui/tests/acceptance/config-ui/messages/messages-test.js @@ -6,13 +6,14 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import { setupMirage } from 'ember-cli-mirage/test-support'; -import { click, visit, fillIn, currentRouteName } from '@ember/test-helpers'; +import { click, visit, fillIn, currentRouteName, currentURL } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import logout from 'vault/tests/pages/logout'; import { format, addDays, startOfDay } from 'date-fns'; import { datetimeLocalStringFormat } from 'core/utils/date-formatters'; -import { PAGE } from 'vault/tests/helpers/config-ui/message-selectors'; +import { CUSTOM_MESSAGES } from 'vault/tests/helpers/config-ui/message-selectors'; import { clickTrigger } from 'ember-power-select/test-support/helpers'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; module('Acceptance | Community | config-ui/messages', function (hooks) { setupApplicationTest(hooks); @@ -48,7 +49,7 @@ module('Acceptance | Community | config-ui/messages', function (hooks) { test('it should hide the sidebar settings section on community', async function (assert) { assert.expect(1); - assert.dom(PAGE.navLink).doesNotExist(); + assert.dom(CUSTOM_MESSAGES.navLink).doesNotExist(); }); }); @@ -57,40 +58,44 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { setupMirage(hooks); hooks.beforeEach(async function () { + this.messageDetailId = () => { + return currentURL().match(/messages\/(.*)\/details/)[1]; + }; this.createMessage = async (messageType = 'banner', endTime = '2023-12-12', authenticated = true) => { - await click(PAGE.navLink); - + await click(CUSTOM_MESSAGES.navLink); if (authenticated) { - await click(PAGE.tab('After user logs in')); - await click(PAGE.button('create message')); + await click(CUSTOM_MESSAGES.tab('After user logs in')); } else { - await click(PAGE.tab('On login page')); - await click(PAGE.button('create message')); + await click(CUSTOM_MESSAGES.tab('On login page')); } + await click(CUSTOM_MESSAGES.button('create message')); - await visit(`vault/config-ui/messages?authenticated=${authenticated}`); - await click(PAGE.button('create message')); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); - await click(PAGE.radio(messageType)); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); + await click(CUSTOM_MESSAGES.radio(messageType)); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn( - PAGE.input('startTime'), + CUSTOM_MESSAGES.input('startTime'), format(addDays(startOfDay(new Date('2023-12-12')), 1), datetimeLocalStringFormat) ); if (endTime) { await click('#specificDate'); await fillIn( - PAGE.input('endTime'), + CUSTOM_MESSAGES.input('endTime'), format(addDays(startOfDay(new Date('2023-12-12')), 10), datetimeLocalStringFormat) ); } await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('create-message')); + await click(CUSTOM_MESSAGES.button('create-message')); + }; + this.deleteMessage = async (id) => { + await visit(`vault/config-ui/messages/${id}/details`); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); }; this.server.get('/sys/health', function () { return { @@ -120,25 +125,25 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { }); test('it should show an empty state when no messages are created', async function (assert) { assert.expect(4); - await click(PAGE.navLink); + await click(CUSTOM_MESSAGES.navLink); assert.dom('[data-test-component="empty-state"]').exists(); - assert.dom(PAGE.emptyStateTitle).hasText('No messages yet'); - await click(PAGE.tab('On login page')); + assert.dom(GENERAL.emptyStateTitle).hasText('No messages yet'); + await click(CUSTOM_MESSAGES.tab('On login page')); assert.dom('[data-test-component="empty-state"]').exists(); - assert.dom(PAGE.emptyStateTitle).hasText('No messages yet'); + assert.dom(GENERAL.emptyStateTitle).hasText('No messages yet'); }); module('Authenticated messages', function () { test('it should create, edit, view, and delete a message', async function (assert) { assert.expect(3); await this.createMessage(); - assert.dom(PAGE.title).hasText('Awesome custom message title', 'on the details screen'); + assert.dom(GENERAL.title).hasText('Awesome custom message title', 'on the details screen'); await click('[data-test-link="edit"]'); - await fillIn(PAGE.input('title'), 'Edited custom message title'); - await click(PAGE.button('create-message')); - assert.dom(PAGE.title).hasText('Edited custom message title'); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Edited custom message title'); + await click(CUSTOM_MESSAGES.button('create-message')); + assert.dom(GENERAL.title).hasText('Edited custom message title'); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); assert.strictEqual( currentRouteName(), 'vault.cluster.config-ui.messages.index', @@ -149,23 +154,24 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { test('it should show multiple messages modal', async function (assert) { assert.expect(4); await this.createMessage('modal', null); - assert.dom(PAGE.title).hasText('Awesome custom message title'); + assert.dom(GENERAL.title).hasText('Awesome custom message title'); await this.createMessage('modal', null); - assert.dom(PAGE.modal('multiple modal messages')).exists(); + assert.dom(CUSTOM_MESSAGES.modal('multiple modal messages')).exists(); assert - .dom(PAGE.modalTitle('Warning: more than one modal')) + .dom(CUSTOM_MESSAGES.modalTitle('Warning: more than one modal')) .hasText('Warning: more than one modal after the user logs in'); - await click(PAGE.modalButton('cancel')); + await click(CUSTOM_MESSAGES.modalButton('cancel')); await visit('vault/config-ui/messages'); - await click(PAGE.listItem('Awesome custom message title')); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); + await click(CUSTOM_MESSAGES.listItem('Awesome custom message title')); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); assert.dom('[data-test-component="empty-state"]').exists('Message was deleted'); }); test('it should filter by type and status', async function (assert) { - assert.expect(6); await this.createMessage('banner', null); + const msg1 = this.messageDetailId(); await this.createMessage('banner'); + const msg2 = this.messageDetailId(); await visit('vault/config-ui/messages'); // check number of messages with status filters @@ -192,49 +198,44 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { assert.dom('.linked-block').exists({ count: 2 }, 'no filters selected'); // clean up custom messages - await click(PAGE.listItem('Awesome custom message title')); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); - await click(PAGE.listItem('Awesome custom message title')); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); - assert.dom('[data-test-component="empty-state"]').exists('Message was deleted'); + await this.deleteMessage(msg1); + await this.deleteMessage(msg2); }); test('it should display preview a message when all required fields are filled out', async function (assert) { assert.expect(2); - await click(PAGE.navLink); - await click(PAGE.tab('After user logs in')); - await click(PAGE.button('create message')); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); - await click(PAGE.radio('banner')); + await click(CUSTOM_MESSAGES.navLink); + await click(CUSTOM_MESSAGES.tab('After user logs in')); + await click(CUSTOM_MESSAGES.button('create message')); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); + await click(CUSTOM_MESSAGES.radio('banner')); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview image')).exists(); - await click(PAGE.modalButton('Close')); - await click(PAGE.radio('modal')); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview modal')).exists(); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).exists(); + await click(CUSTOM_MESSAGES.modalButton('Close')); + await click(CUSTOM_MESSAGES.radio('modal')); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview modal')).exists(); }); test('it should not display preview a message when all required fields are not filled out', async function (assert) { assert.expect(2); - await click(PAGE.navLink); - await click(PAGE.tab('After user logs in')); - await click(PAGE.button('create message')); - await click(PAGE.radio('banner')); + await click(CUSTOM_MESSAGES.navLink); + await click(CUSTOM_MESSAGES.tab('After user logs in')); + await click(CUSTOM_MESSAGES.button('create message')); + await click(CUSTOM_MESSAGES.radio('banner')); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview image')).doesNotExist(); - assert.dom(PAGE.input('title')).hasClass('has-error-border'); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).doesNotExist(); + assert.dom(CUSTOM_MESSAGES.input('title')).hasClass('has-error-border'); }); }); @@ -242,13 +243,13 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { test('it should create, edit, view, and delete a message', async function (assert) { assert.expect(3); await this.createMessage('banner', null, false); - assert.dom(PAGE.title).hasText('Awesome custom message title', 'on the details screen'); + assert.dom(GENERAL.title).hasText('Awesome custom message title', 'on the details screen'); await click('[data-test-link="edit"]'); - await fillIn(PAGE.input('title'), 'Edited custom message title'); - await click(PAGE.button('create-message')); - assert.dom(PAGE.title).hasText('Edited custom message title'); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Edited custom message title'); + await click(CUSTOM_MESSAGES.button('create-message')); + assert.dom(GENERAL.title).hasText('Edited custom message title'); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); assert.strictEqual( currentRouteName(), 'vault.cluster.config-ui.messages.index', @@ -258,65 +259,65 @@ module('Acceptance | Enterprise | config-ui/message', function (hooks) { test('it should show multiple messages modal', async function (assert) { assert.expect(4); await this.createMessage('modal', null, false); - assert.dom(PAGE.title).hasText('Awesome custom message title'); + assert.dom(GENERAL.title).hasText('Awesome custom message title'); await this.createMessage('modal', null, false); - assert.dom(PAGE.modal('multiple modal messages')).exists(); + assert.dom(CUSTOM_MESSAGES.modal('multiple modal messages')).exists(); assert - .dom(PAGE.modalTitle('Warning: more than one modal')) + .dom(CUSTOM_MESSAGES.modalTitle('Warning: more than one modal')) .hasText('Warning: more than one modal on the login page'); - await click(PAGE.modalButton('cancel')); + await click(CUSTOM_MESSAGES.modalButton('cancel')); await visit('vault/config-ui/messages?authenticated=false'); - await click(PAGE.listItem('Awesome custom message title')); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); + await click(CUSTOM_MESSAGES.listItem('Awesome custom message title')); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); assert.dom('[data-test-component="empty-state"]').exists('Message was deleted'); }); test('it should show info message on create and edit form', async function (assert) { assert.expect(1); - await click(PAGE.navLink); - await click(PAGE.tab('On login page')); - await click(PAGE.button('create message')); + await click(CUSTOM_MESSAGES.navLink); + await click(CUSTOM_MESSAGES.tab('On login page')); + await click(CUSTOM_MESSAGES.button('create message')); assert - .dom(PAGE.unauthCreateFormInfo) + .dom(CUSTOM_MESSAGES.unauthCreateFormInfo) .hasText( 'Note: Do not include sensitive information in this message since users are unauthenticated at this stage.' ); }); test('it should display preview a message when all required fields are filled out', async function (assert) { assert.expect(2); - await click(PAGE.navLink); - await click(PAGE.tab('On login page')); - await click(PAGE.button('create message')); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); - await click(PAGE.radio('banner')); + await click(CUSTOM_MESSAGES.navLink); + await click(CUSTOM_MESSAGES.tab('On login page')); + await click(CUSTOM_MESSAGES.button('create message')); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); + await click(CUSTOM_MESSAGES.radio('banner')); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview image')).exists(); - await click(PAGE.modalButton('Close')); - await click(PAGE.radio('modal')); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview modal')).exists(); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).exists(); + await click(CUSTOM_MESSAGES.modalButton('Close')); + await click(CUSTOM_MESSAGES.radio('modal')); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview modal')).exists(); }); test('it should not display preview a message when all required fields are not filled out', async function (assert) { assert.expect(2); - await click(PAGE.navLink); - await click(PAGE.tab('On login page')); - await click(PAGE.button('create message')); - await click(PAGE.radio('banner')); + await click(CUSTOM_MESSAGES.navLink); + await click(CUSTOM_MESSAGES.tab('On login page')); + await click(CUSTOM_MESSAGES.button('create message')); + await click(CUSTOM_MESSAGES.radio('banner')); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview image')).doesNotExist(); - assert.dom(PAGE.input('title')).hasClass('has-error-border'); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).doesNotExist(); + assert.dom(CUSTOM_MESSAGES.input('title')).hasClass('has-error-border'); }); }); }); diff --git a/ui/tests/acceptance/config-ui/messages/messages-unauth-auth-test.js b/ui/tests/acceptance/config-ui/messages/messages-unauth-auth-test.js index 9a962b8e85f6..a617d255b0e2 100644 --- a/ui/tests/acceptance/config-ui/messages/messages-unauth-auth-test.js +++ b/ui/tests/acceptance/config-ui/messages/messages-unauth-auth-test.js @@ -6,7 +6,8 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import { click, visit, fillIn, currentRouteName } from '@ember/test-helpers'; -import { PAGE } from 'vault/tests/helpers/config-ui/message-selectors'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; +import { CUSTOM_MESSAGES } from 'vault/tests/helpers/config-ui/message-selectors'; import { setupMirage } from 'ember-cli-mirage/test-support'; import authPage from 'vault/tests/pages/auth'; @@ -68,14 +69,14 @@ module('Acceptance | auth custom messages auth tests', function (hooks) { await visit('/vault/auth'); const modalId = 'some-awesome-id-1'; const alertId = 'some-awesome-id-2'; - assert.dom(PAGE.modal(modalId)).exists(); - assert.dom(PAGE.modalTitle(modalId)).hasText('Modal title'); - assert.dom(PAGE.modalBody(modalId)).exists(); - assert.dom(PAGE.modalBody(modalId)).hasText('here is a cool message'); - await click(PAGE.modalButton(modalId)); - assert.dom(PAGE.alertTitle(alertId)).hasText('Banner title'); - assert.dom(PAGE.alertDescription(alertId)).hasText('hello world hello wolrd'); - assert.dom(PAGE.alertAction('link')).hasText('some alert link'); + assert.dom(CUSTOM_MESSAGES.modal(modalId)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalId)).hasText('Modal title'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalId)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalId)).hasText('here is a cool message'); + await click(CUSTOM_MESSAGES.modalButton(modalId)); + assert.dom(CUSTOM_MESSAGES.alertTitle(alertId)).hasText('Banner title'); + assert.dom(CUSTOM_MESSAGES.alertDescription(alertId)).hasText('hello world hello wolrd'); + assert.dom(CUSTOM_MESSAGES.alertAction('link')).hasText('some alert link'); }); test('it shows the multiple modal messages', async function (assert) { const modalIdOne = 'some-awesome-id-2'; @@ -89,16 +90,16 @@ module('Acceptance | auth custom messages auth tests', function (hooks) { return unauthenticatedMessageResponse; }); await visit('/vault/auth'); - assert.dom(PAGE.modal(modalIdOne)).exists(); - assert.dom(PAGE.modalTitle(modalIdOne)).hasText('Modal title 1'); - assert.dom(PAGE.modalBody(modalIdOne)).exists(); - assert.dom(PAGE.modalBody(modalIdOne)).hasText('hello world hello wolrd some alert link'); - await click(PAGE.modalButton(modalIdOne)); - assert.dom(PAGE.modal(modalIdTwo)).exists(); - assert.dom(PAGE.modalTitle(modalIdTwo)).hasText('Modal title 2'); - assert.dom(PAGE.modalBody(modalIdTwo)).exists(); - assert.dom(PAGE.modalBody(modalIdTwo)).hasText('here is a cool message'); - await click(PAGE.modalButton(modalIdTwo)); + assert.dom(CUSTOM_MESSAGES.modal(modalIdOne)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalIdOne)).hasText('Modal title 1'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdOne)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdOne)).hasText('hello world hello wolrd some alert link'); + await click(CUSTOM_MESSAGES.modalButton(modalIdOne)); + assert.dom(CUSTOM_MESSAGES.modal(modalIdTwo)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalIdTwo)).hasText('Modal title 2'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdTwo)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdTwo)).hasText('here is a cool message'); + await click(CUSTOM_MESSAGES.modalButton(modalIdTwo)); }); test('it shows the multiple banner messages', async function (assert) { const bannerIdOne = 'some-awesome-id-2'; @@ -112,11 +113,11 @@ module('Acceptance | auth custom messages auth tests', function (hooks) { return unauthenticatedMessageResponse; }); await visit('/vault/auth'); - assert.dom(PAGE.alertTitle(bannerIdOne)).hasText('Banner title 1'); - assert.dom(PAGE.alertDescription(bannerIdOne)).hasText('hello world hello wolrd'); - assert.dom(PAGE.alertTitle(bannerIdTwo)).hasText('Banner title 2'); - assert.dom(PAGE.alertDescription(bannerIdTwo)).hasText('here is a cool message'); - assert.dom(PAGE.alertAction('link')).hasText('some alert link'); + assert.dom(CUSTOM_MESSAGES.alertTitle(bannerIdOne)).hasText('Banner title 1'); + assert.dom(CUSTOM_MESSAGES.alertDescription(bannerIdOne)).hasText('hello world hello wolrd'); + assert.dom(CUSTOM_MESSAGES.alertTitle(bannerIdTwo)).hasText('Banner title 2'); + assert.dom(CUSTOM_MESSAGES.alertDescription(bannerIdTwo)).hasText('here is a cool message'); + assert.dom(CUSTOM_MESSAGES.alertAction('link')).hasText('some alert link'); }); }); @@ -124,29 +125,29 @@ module('Acceptance | auth custom messages auth tests', function (hooks) { assert.expect(4); await authPage.login(); await visit('vault/config-ui/messages'); - await click(PAGE.button('create message')); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); - await click(PAGE.radio('banner')); + await click(CUSTOM_MESSAGES.button('create message')); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); + await click(CUSTOM_MESSAGES.radio('banner')); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn( - PAGE.input('startTime'), + CUSTOM_MESSAGES.input('startTime'), format(addDays(startOfDay(new Date('2023-12-12')), 1), datetimeLocalStringFormat) ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('create-message')); - assert.dom(PAGE.title).hasText('Awesome custom message title', 'on the details screen'); + await click(CUSTOM_MESSAGES.button('create-message')); + assert.dom(GENERAL.title).hasText('Awesome custom message title', 'on the details screen'); assert.dom('.hds-alert').exists('active custom message displays on authenticated.'); await runCmd(createNS('world'), false); await visit('vault/config-ui/messages'); assert.dom('.hds-alert').exists('active custom message displays on namespace authenticated.'); - await click(PAGE.listItem('Awesome custom message title')); - await click(PAGE.confirmActionButton('Delete message')); - await click(PAGE.confirmButton); + await click(CUSTOM_MESSAGES.listItem('Awesome custom message title')); + await click(CUSTOM_MESSAGES.confirmActionButton('Delete message')); + await click(GENERAL.confirmButton); assert.strictEqual( currentRouteName(), 'vault.cluster.config-ui.messages.index', diff --git a/ui/tests/acceptance/dashboard-test.js b/ui/tests/acceptance/dashboard-test.js index 0dc00b5e07fe..acdb8e984c20 100644 --- a/ui/tests/acceptance/dashboard-test.js +++ b/ui/tests/acceptance/dashboard-test.js @@ -27,8 +27,8 @@ import connectionPage from 'vault/tests/pages/secrets/backend/database/connectio import { v4 as uuidv4 } from 'uuid'; import { runCmd, deleteEngineCmd, createNS } from 'vault/tests/helpers/commands'; -import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; -import { PAGE } from 'vault/tests/helpers/config-ui/message-selectors'; +import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; +import { CUSTOM_MESSAGES } from 'vault/tests/helpers/config-ui/message-selectors'; const authenticatedMessageResponse = { request_id: '664fbad0-fcd8-9023-4c5b-81a7962e9f4b', @@ -87,7 +87,7 @@ module('Acceptance | landing page dashboard', function (hooks) { ? `Vault ${version.versionDisplay} root` : `Vault ${version.versionDisplay}`; - assert.dom(SELECTORS.cardHeader('Vault version')).hasText(versionText); + assert.dom(DASHBOARD.cardHeader('Vault version')).hasText(versionText); }); module('secrets engines card', function (hooks) { @@ -100,7 +100,7 @@ module('Acceptance | landing page dashboard', function (hooks) { await mountSecrets.enable('pki', 'pki'); await settled(); await visit('/vault/dashboard'); - assert.dom(SELECTORS.cardHeader('Secrets engines')).hasText('Secrets engines'); + assert.dom(DASHBOARD.cardHeader('Secrets engines')).hasText('Secrets engines'); // cleanup engine mount await runCmd(deleteEngineCmd('pki')); }); @@ -221,26 +221,26 @@ module('Acceptance | landing page dashboard', function (hooks) { await visit('/vault/dashboard'); const version = this.owner.lookup('service:version'); assert.true(version.isEnterprise, 'vault is enterprise'); - assert.dom(SELECTORS.cardName('configuration-details')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).exists(); await runCmd(createNS('world'), false); await visit('/vault/dashboard?namespace=world'); - assert.dom(SELECTORS.cardName('configuration-details')).doesNotExist(); + assert.dom(DASHBOARD.cardName('configuration-details')).doesNotExist(); }); test('shows the configuration details card', async function (assert) { assert.expect(8); await authPage.login(); await visit('/vault/dashboard'); - assert.dom(SELECTORS.cardHeader('configuration')).hasText('Configuration details'); + assert.dom(DASHBOARD.cardHeader('configuration')).hasText('Configuration details'); assert - .dom(SELECTORS.vaultConfigurationCard.configDetailsField('api_addr')) + .dom(DASHBOARD.vaultConfigurationCard.configDetailsField('api_addr')) .hasText('http://127.0.0.1:8200'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('default_lease_ttl')).hasText('0'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('max_lease_ttl')).hasText('2 days'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('tls')).hasText('Disabled'); // tls_disable=true - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('log_format')).hasText('None'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('log_level')).hasText('debug'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('type')).hasText('raft'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('default_lease_ttl')).hasText('0'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('max_lease_ttl')).hasText('2 days'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('tls')).hasText('Disabled'); // tls_disable=true + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('log_format')).hasText('None'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('log_level')).hasText('debug'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('type')).hasText('raft'); }); test('it should show tls as enabled if tls_disable, tls_cert_file and tls_key_file are in the config', async function (assert) { @@ -251,7 +251,7 @@ module('Acceptance | landing page dashboard', function (hooks) { await authPage.login(); await visit('/vault/dashboard'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('tls')).hasText('Enabled'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('tls')).hasText('Enabled'); }); test('it should show tls as enabled if only cert and key exist in config', async function (assert) { @@ -261,7 +261,7 @@ module('Acceptance | landing page dashboard', function (hooks) { this.data.listeners[0].config.tls_key_file = './key.pem'; await authPage.login(); await visit('/vault/dashboard'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('tls')).hasText('Enabled'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('tls')).hasText('Enabled'); }); test('it should show tls as disabled if there is no tls information in the config', async function (assert) { @@ -269,7 +269,7 @@ module('Acceptance | landing page dashboard', function (hooks) { this.data.listeners = []; await authPage.login(); await visit('/vault/dashboard'); - assert.dom(SELECTORS.vaultConfigurationCard.configDetailsField('tls')).hasText('Disabled'); + assert.dom(DASHBOARD.vaultConfigurationCard.configDetailsField('tls')).hasText('Disabled'); }); }); @@ -280,7 +280,7 @@ module('Acceptance | landing page dashboard', function (hooks) { test('shows the default state of the quick actions card', async function (assert) { assert.expect(1); - assert.dom(SELECTORS.emptyState('no-mount-selected')).exists(); + assert.dom(DASHBOARD.emptyState('no-mount-selected')).exists(); }); test('shows the correct actions and links associated with pki', async function (assert) { @@ -297,25 +297,25 @@ module('Acceptance | landing page dashboard', function (hooks) { await runCmd([`write ${backend}/root/generate/internal issuer_name="Hashicorp" common_name="Hello"`]); await settled(); await visit('/vault/dashboard'); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), backend); - await fillIn(SELECTORS.selectEl, 'Issue certificate'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - assert.dom(SELECTORS.subtitle('param')).hasText('Role to use'); - - await selectChoose(SELECTORS.searchSelect('params'), 'some-role'); - assert.dom(SELECTORS.actionButton('Issue leaf certificate')).exists({ count: 1 }); - await click(SELECTORS.actionButton('Issue leaf certificate')); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), backend); + await fillIn(DASHBOARD.selectEl, 'Issue certificate'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + assert.dom(DASHBOARD.subtitle('param')).hasText('Role to use'); + + await selectChoose(DASHBOARD.searchSelect('params'), 'some-role'); + assert.dom(DASHBOARD.actionButton('Issue leaf certificate')).exists({ count: 1 }); + await click(DASHBOARD.actionButton('Issue leaf certificate')); assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.backend.pki.roles.role.generate'); await visit('/vault/dashboard'); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), backend); - await fillIn(SELECTORS.selectEl, 'View certificate'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - assert.dom(SELECTORS.subtitle('param')).hasText('Certificate serial number'); - assert.dom(SELECTORS.actionButton('View certificate')).exists({ count: 1 }); - await selectChoose(SELECTORS.searchSelect('params'), '.ember-power-select-option', 0); - await click(SELECTORS.actionButton('View certificate')); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), backend); + await fillIn(DASHBOARD.selectEl, 'View certificate'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + assert.dom(DASHBOARD.subtitle('param')).hasText('Certificate serial number'); + assert.dom(DASHBOARD.actionButton('View certificate')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('params'), '.ember-power-select-option', 0); + await click(DASHBOARD.actionButton('View certificate')); assert.strictEqual( currentRouteName(), 'vault.cluster.secrets.backend.pki.certificates.certificate.details' @@ -323,13 +323,13 @@ module('Acceptance | landing page dashboard', function (hooks) { await visit('/vault/dashboard'); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), backend); - await fillIn(SELECTORS.selectEl, 'View issuer'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - assert.dom(SELECTORS.subtitle('param')).hasText('Issuer'); - assert.dom(SELECTORS.actionButton('View issuer')).exists({ count: 1 }); - await selectChoose(SELECTORS.searchSelect('params'), '.ember-power-select-option', 0); - await click(SELECTORS.actionButton('View issuer')); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), backend); + await fillIn(DASHBOARD.selectEl, 'View issuer'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + assert.dom(DASHBOARD.subtitle('param')).hasText('Issuer'); + assert.dom(DASHBOARD.actionButton('View issuer')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('params'), '.ember-power-select-option', 0); + await click(DASHBOARD.actionButton('View issuer')); assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.backend.pki.issuers.issuer.details'); // cleanup engine mount @@ -362,13 +362,13 @@ module('Acceptance | landing page dashboard', function (hooks) { ]); await settled(); await visit('/vault/dashboard'); - 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'); - assert.dom(SELECTORS.actionButton('Generate credentials')).exists({ count: 1 }); - await selectChoose(SELECTORS.searchSelect('params'), '.ember-power-select-option', 0); - await click(SELECTORS.actionButton('Generate credentials')); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), databaseBackend); + await fillIn(DASHBOARD.selectEl, 'Generate credentials for database'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + assert.dom(DASHBOARD.subtitle('param')).hasText('Role to use'); + assert.dom(DASHBOARD.actionButton('Generate credentials')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('params'), '.ember-power-select-option', 0); + await click(DASHBOARD.actionButton('Generate credentials')); assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.backend.credentials'); await runCmd(deleteEngineCmd(databaseBackend)); }); @@ -401,7 +401,7 @@ module('Acceptance | landing page dashboard', function (hooks) { const version = this.owner.lookup('service:version'); assert.true(version.isEnterprise, 'version is enterprise'); assert.strictEqual(currentURL(), '/vault/dashboard'); - assert.dom(SELECTORS.cardName('client-count')).exists(); + assert.dom(DASHBOARD.cardName('client-count')).exists(); const response = await this.store.peekRecord('clients/activity', 'some-activity-id'); assert.dom('[data-test-client-count-title]').hasText('Client count'); assert.dom('[data-test-stat-text="total-clients"] .stat-label').hasText('Total'); @@ -433,12 +433,12 @@ module('Acceptance | landing page dashboard', function (hooks) { await visit('/vault/dashboard'); const version = this.owner.lookup('service:version'); assert.true(version.isEnterprise, 'vault is enterprise'); - assert.dom(SELECTORS.emptyState('replication')).exists(); - assert.dom(SELECTORS.emptyStateTitle('replication')).hasText('Replication not set up'); + assert.dom(DASHBOARD.emptyState('replication')).exists(); + assert.dom(DASHBOARD.emptyStateTitle('replication')).hasText('Replication not set up'); assert - .dom(SELECTORS.emptyStateMessage('replication')) + .dom(DASHBOARD.emptyStateMessage('replication')) .hasText('Data will be listed here. Enable a primary replication cluster to get started.'); - assert.dom(SELECTORS.emptyStateActions('replication')).hasText('Enable replication'); + assert.dom(DASHBOARD.emptyStateActions('replication')).hasText('Enable replication'); }); test('hides the replication card on a non-root namespace enterprise version', async function (assert) { @@ -446,10 +446,10 @@ module('Acceptance | landing page dashboard', function (hooks) { await visit('/vault/dashboard'); const version = this.owner.lookup('service:version'); assert.true(version.isEnterprise, 'vault is enterprise'); - assert.dom(SELECTORS.cardName('replication')).exists(); + assert.dom(DASHBOARD.cardName('replication')).exists(); await runCmd(createNS('blah'), false); await visit('/vault/dashboard?namespace=blah'); - assert.dom(SELECTORS.cardName('replication')).doesNotExist(); + assert.dom(DASHBOARD.cardName('replication')).doesNotExist(); }); test('it should show replication status if both dr and performance replication are enabled as features in enterprise', async function (assert) { @@ -467,12 +467,12 @@ module('Acceptance | landing page dashboard', function (hooks) { 'details dashboard is shown' ); await visit('/vault/dashboard'); - assert.dom(SELECTORS.title('DR primary')).hasText('DR primary'); - assert.dom(SELECTORS.tooltipTitle('DR primary')).hasText('not set up'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'x-circle')).exists(); - assert.dom(SELECTORS.title('Performance primary')).hasText('Performance primary'); - assert.dom(SELECTORS.tooltipTitle('Performance primary')).hasText('running'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'check-circle')).exists(); + assert.dom(DASHBOARD.title('DR primary')).hasText('DR primary'); + assert.dom(DASHBOARD.tooltipTitle('DR primary')).hasText('not set up'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'x-circle')).exists(); + assert.dom(DASHBOARD.title('Performance primary')).hasText('Performance primary'); + assert.dom(DASHBOARD.tooltipTitle('Performance primary')).hasText('running'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'check-circle')).exists(); }); }); @@ -489,14 +489,14 @@ module('Acceptance | landing page dashboard', function (hooks) { await visit('/vault/dashboard'); const modalId = 'some-awesome-id-1'; const alertId = 'some-awesome-id-2'; - assert.dom(PAGE.modal(modalId)).exists(); - assert.dom(PAGE.modalTitle(modalId)).hasText('Modal title'); - assert.dom(PAGE.modalBody(modalId)).exists(); - assert.dom(PAGE.modalBody(modalId)).hasText('here is a cool message'); - await click(PAGE.modalButton(modalId)); - assert.dom(PAGE.alertTitle(alertId)).hasText('Banner title'); - assert.dom(PAGE.alertDescription(alertId)).hasText('hello world hello wolrd'); - assert.dom(PAGE.alertAction('link')).hasText('some link title'); + assert.dom(CUSTOM_MESSAGES.modal(modalId)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalId)).hasText('Modal title'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalId)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalId)).hasText('here is a cool message'); + await click(CUSTOM_MESSAGES.modalButton(modalId)); + assert.dom(CUSTOM_MESSAGES.alertTitle(alertId)).hasText('Banner title'); + assert.dom(CUSTOM_MESSAGES.alertDescription(alertId)).hasText('hello world hello wolrd'); + assert.dom(CUSTOM_MESSAGES.alertAction('link')).hasText('some link title'); }); test('it shows the multiple modal messages', async function (assert) { assert.expect(8); @@ -511,16 +511,16 @@ module('Acceptance | landing page dashboard', function (hooks) { return authenticatedMessageResponse; }); await visit('/vault/dashboard'); - assert.dom(PAGE.modal(modalIdOne)).exists(); - assert.dom(PAGE.modalTitle(modalIdOne)).hasText('Modal title 1'); - assert.dom(PAGE.modalBody(modalIdOne)).exists(); - assert.dom(PAGE.modalBody(modalIdOne)).hasText('hello world hello wolrd some link title'); - await click(PAGE.modalButton(modalIdOne)); - assert.dom(PAGE.modal(modalIdTwo)).exists(); - assert.dom(PAGE.modalTitle(modalIdTwo)).hasText('Modal title 2'); - assert.dom(PAGE.modalBody(modalIdTwo)).exists(); - assert.dom(PAGE.modalBody(modalIdTwo)).hasText('here is a cool message'); - await click(PAGE.modalButton(modalIdTwo)); + assert.dom(CUSTOM_MESSAGES.modal(modalIdOne)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalIdOne)).hasText('Modal title 1'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdOne)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdOne)).hasText('hello world hello wolrd some link title'); + await click(CUSTOM_MESSAGES.modalButton(modalIdOne)); + assert.dom(CUSTOM_MESSAGES.modal(modalIdTwo)).exists(); + assert.dom(CUSTOM_MESSAGES.modalTitle(modalIdTwo)).hasText('Modal title 2'); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdTwo)).exists(); + assert.dom(CUSTOM_MESSAGES.modalBody(modalIdTwo)).hasText('here is a cool message'); + await click(CUSTOM_MESSAGES.modalButton(modalIdTwo)); }); test('it shows the multiple banner messages', async function (assert) { assert.expect(5); @@ -535,11 +535,11 @@ module('Acceptance | landing page dashboard', function (hooks) { return authenticatedMessageResponse; }); await visit('/vault/dashboard'); - assert.dom(PAGE.alertTitle(bannerIdOne)).hasText('Banner title 1'); - assert.dom(PAGE.alertDescription(bannerIdOne)).hasText('hello world hello wolrd'); - assert.dom(PAGE.alertAction('link')).hasText('some link title'); - assert.dom(PAGE.alertTitle(bannerIdTwo)).hasText('Banner title 2'); - assert.dom(PAGE.alertDescription(bannerIdTwo)).hasText('here is a cool message'); + assert.dom(CUSTOM_MESSAGES.alertTitle(bannerIdOne)).hasText('Banner title 1'); + assert.dom(CUSTOM_MESSAGES.alertDescription(bannerIdOne)).hasText('hello world hello wolrd'); + assert.dom(CUSTOM_MESSAGES.alertAction('link')).hasText('some link title'); + assert.dom(CUSTOM_MESSAGES.alertTitle(bannerIdTwo)).hasText('Banner title 2'); + assert.dom(CUSTOM_MESSAGES.alertDescription(bannerIdTwo)).hasText('here is a cool message'); }); }); }); diff --git a/ui/tests/helpers/components/dashboard/dashboard-selectors.js b/ui/tests/helpers/components/dashboard/dashboard-selectors.js index 9f966c45490c..d7be836fff39 100644 --- a/ui/tests/helpers/components/dashboard/dashboard-selectors.js +++ b/ui/tests/helpers/components/dashboard/dashboard-selectors.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: BUSL-1.1 */ -export const SELECTORS = { +export const DASHBOARD = { cardName: (name) => `[data-test-card="${name}"]`, emptyState: (name) => `[data-test-empty-state="${name}"]`, emptyStateTitle: (name) => `[data-test-empty-state="${name}"] [data-test-empty-state-title]`, diff --git a/ui/tests/helpers/config-ui/message-selectors.js b/ui/tests/helpers/config-ui/message-selectors.js index 29adc18109c8..a2012a93a4df 100644 --- a/ui/tests/helpers/config-ui/message-selectors.js +++ b/ui/tests/helpers/config-ui/message-selectors.js @@ -3,11 +3,8 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { GENERAL } from 'vault/tests/helpers/general-selectors'; - -export const PAGE = { +export const CUSTOM_MESSAGES = { // General selectors that are common between pages - ...GENERAL, inlineErrorMessage: `[data-test-inline-error-message]`, unauthCreateFormInfo: '[data-test-unauth-info]', navLink: '[data-test-sidebar-nav-link="Custom Messages"]', diff --git a/ui/tests/integration/components/config-ui/messages/page/create-and-edit-test.js b/ui/tests/integration/components/config-ui/messages/page/create-and-edit-test.js index be01689cff7c..e08430ed6285 100644 --- a/ui/tests/integration/components/config-ui/messages/page/create-and-edit-test.js +++ b/ui/tests/integration/components/config-ui/messages/page/create-and-edit-test.js @@ -11,8 +11,9 @@ import { render, click, fillIn } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { datetimeLocalStringFormat } from 'core/utils/date-formatters'; import { format, addDays, startOfDay } from 'date-fns'; -import { PAGE } from 'vault/tests/helpers/config-ui/message-selectors'; +import { CUSTOM_MESSAGES } from 'vault/tests/helpers/config-ui/message-selectors'; import timestamp from 'core/utils/timestamp'; +import { GENERAL } from 'vault/tests/helpers/general-selectors'; module('Integration | Component | messages/page/create-and-edit', function (hooks) { setupRenderingTest(hooks); @@ -32,25 +33,25 @@ module('Integration | Component | messages/page/create-and-edit', function (hook owner: this.engine, }); - assert.dom(PAGE.title).hasText('Create message'); - assert.dom(PAGE.radio('authenticated')).exists(); - assert.dom(PAGE.radio('unauthenticated')).exists(); - assert.dom(PAGE.radio('authenticated')).isChecked(); - assert.dom(PAGE.radio('unauthenticated')).isNotChecked(); - assert.dom(PAGE.radio('banner')).exists(); - assert.dom(PAGE.radio('modal')).exists(); - assert.dom(PAGE.radio('banner')).isChecked(); - assert.dom(PAGE.radio('modal')).isNotChecked(); - assert.dom(PAGE.field('title')).exists(); - assert.dom(PAGE.field('message')).exists(); + assert.dom(GENERAL.title).hasText('Create message'); + assert.dom(CUSTOM_MESSAGES.radio('authenticated')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('unauthenticated')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('authenticated')).isChecked(); + assert.dom(CUSTOM_MESSAGES.radio('unauthenticated')).isNotChecked(); + assert.dom(CUSTOM_MESSAGES.radio('banner')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('modal')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('banner')).isChecked(); + assert.dom(CUSTOM_MESSAGES.radio('modal')).isNotChecked(); + assert.dom(CUSTOM_MESSAGES.field('title')).exists(); + assert.dom(CUSTOM_MESSAGES.field('message')).exists(); assert.dom('[data-test-kv-key="0"]').exists(); assert.dom('[data-test-kv-value="0"]').exists(); - assert.dom(PAGE.input('startTime')).exists(); + assert.dom(CUSTOM_MESSAGES.input('startTime')).exists(); assert - .dom(PAGE.input('startTime')) + .dom(CUSTOM_MESSAGES.input('startTime')) .hasValue(format(addDays(startOfDay(timestamp.now()), 1), datetimeLocalStringFormat)); - assert.dom(PAGE.input('endTime')).exists(); - assert.dom(PAGE.input('endTime')).hasValue(''); + assert.dom(CUSTOM_MESSAGES.input('endTime')).exists(); + assert.dom(CUSTOM_MESSAGES.input('endTime')).hasValue(''); }); test('it should display validation errors for invalid form fields', async function (assert) { @@ -59,22 +60,24 @@ module('Integration | Component | messages/page/create-and-edit', function (hook owner: this.engine, }); - await fillIn(PAGE.input('startTime'), '2024-01-20T00:00'); - await fillIn(PAGE.input('endTime'), '2024-01-01T00:00'); - await click(PAGE.button('create-message')); - assert.dom(PAGE.input('title')).hasClass('has-error-border'); - assert.dom(`${PAGE.fieldValidation('title')} ${PAGE.inlineErrorMessage}`).hasText('Title is required.'); - assert.dom(PAGE.input('message')).hasClass('has-error-border'); + await fillIn(CUSTOM_MESSAGES.input('startTime'), '2024-01-20T00:00'); + await fillIn(CUSTOM_MESSAGES.input('endTime'), '2024-01-01T00:00'); + await click(CUSTOM_MESSAGES.button('create-message')); + assert.dom(CUSTOM_MESSAGES.input('title')).hasClass('has-error-border'); assert - .dom(`${PAGE.fieldValidation('message')} ${PAGE.inlineErrorMessage}`) + .dom(`${CUSTOM_MESSAGES.fieldValidation('title')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) + .hasText('Title is required.'); + assert.dom(CUSTOM_MESSAGES.input('message')).hasClass('has-error-border'); + assert + .dom(`${CUSTOM_MESSAGES.fieldValidation('message')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) .hasText('Message is required.'); - assert.dom(PAGE.input('startTime')).hasClass('has-error-border'); + assert.dom(CUSTOM_MESSAGES.input('startTime')).hasClass('has-error-border'); assert - .dom(`${PAGE.fieldValidation('startTime')} ${PAGE.inlineErrorMessage}`) + .dom(`${CUSTOM_MESSAGES.fieldValidation('startTime')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) .hasText('Start time is after end time.'); - assert.dom(PAGE.input('endTime')).hasClass('has-error-border'); + assert.dom(CUSTOM_MESSAGES.input('endTime')).hasClass('has-error-border'); assert - .dom(`${PAGE.fieldValidation('endTime')} ${PAGE.inlineErrorMessage}`) + .dom(`${CUSTOM_MESSAGES.fieldValidation('endTime')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) .hasText('End time is before start time.'); }); @@ -88,23 +91,23 @@ module('Integration | Component | messages/page/create-and-edit', function (hook await render(hbs``, { owner: this.engine, }); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); await fillIn( - PAGE.input('startTime'), + CUSTOM_MESSAGES.input('startTime'), format(addDays(startOfDay(new Date('2023-12-12')), 1), datetimeLocalStringFormat) ); await click('#specificDate'); await fillIn( - PAGE.input('endTime'), + CUSTOM_MESSAGES.input('endTime'), format(addDays(startOfDay(new Date('2023-12-12')), 10), datetimeLocalStringFormat) ); await fillIn('[data-test-kv-key="0"]', 'Learn more'); await fillIn('[data-test-kv-value="0"]', 'www.learn.com'); - await click(PAGE.button('create-message')); + await click(CUSTOM_MESSAGES.button('create-message')); }); test('it should have form vaildations', async function (assert) { @@ -112,12 +115,18 @@ module('Integration | Component | messages/page/create-and-edit', function (hook await render(hbs``, { owner: this.engine, }); - await click(PAGE.button('create-message')); - assert.dom(PAGE.input('title')).hasClass('has-error-border', 'show error border for title field'); - assert.dom(`${PAGE.fieldValidation('title')} ${PAGE.inlineErrorMessage}`).hasText('Title is required.'); - assert.dom(PAGE.input('message')).hasClass('has-error-border', 'show error border for message field'); + await click(CUSTOM_MESSAGES.button('create-message')); + assert + .dom(CUSTOM_MESSAGES.input('title')) + .hasClass('has-error-border', 'show error border for title field'); + assert + .dom(`${CUSTOM_MESSAGES.fieldValidation('title')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) + .hasText('Title is required.'); assert - .dom(`${PAGE.fieldValidation('message')} ${PAGE.inlineErrorMessage}`) + .dom(CUSTOM_MESSAGES.input('message')) + .hasClass('has-error-border', 'show error border for message field'); + assert + .dom(`${CUSTOM_MESSAGES.fieldValidation('message')} ${CUSTOM_MESSAGES.inlineErrorMessage}`) .hasText('Message is required.'); }); @@ -139,23 +148,23 @@ module('Integration | Component | messages/page/create-and-edit', function (hook owner: this.engine, }); - assert.dom(PAGE.title).hasText('Edit message'); - assert.dom(PAGE.radio('authenticated')).exists(); - assert.dom(PAGE.radio('unauthenticated')).isChecked(); - assert.dom(PAGE.radio('modal')).exists(); - assert.dom(PAGE.radio('modal')).isChecked(); - assert.dom(PAGE.input('title')).hasValue('Hello world'); - assert.dom(PAGE.input('message')).hasValue('Blah blah blah. Some super long message.'); + assert.dom(GENERAL.title).hasText('Edit message'); + assert.dom(CUSTOM_MESSAGES.radio('authenticated')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('unauthenticated')).isChecked(); + assert.dom(CUSTOM_MESSAGES.radio('modal')).exists(); + assert.dom(CUSTOM_MESSAGES.radio('modal')).isChecked(); + assert.dom(CUSTOM_MESSAGES.input('title')).hasValue('Hello world'); + assert.dom(CUSTOM_MESSAGES.input('message')).hasValue('Blah blah blah. Some super long message.'); assert.dom('[data-test-kv-key="0"]').exists(); assert.dom('[data-test-kv-key="0"]').hasValue('Learn more'); assert.dom('[data-test-kv-value="0"]').exists(); assert.dom('[data-test-kv-value="0"]').hasValue('www.learnmore.com'); await click('#specificDate'); assert - .dom(PAGE.input('startTime')) + .dom(CUSTOM_MESSAGES.input('startTime')) .hasValue(format(new Date(this.message.startTime), datetimeLocalStringFormat)); assert - .dom(PAGE.input('endTime')) + .dom(CUSTOM_MESSAGES.input('endTime')) .hasValue(format(new Date(this.message.endTime), datetimeLocalStringFormat)); }); @@ -164,24 +173,26 @@ module('Integration | Component | messages/page/create-and-edit', function (hook await render(hbs``, { owner: this.engine, }); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview modal')).doesNotExist(); - assert.dom(PAGE.modal('preview image')).exists(); - assert.dom(PAGE.alertTitle('Awesome custom message title')).hasText('Awesome custom message title'); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview modal')).doesNotExist(); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).exists(); + assert + .dom(CUSTOM_MESSAGES.alertTitle('Awesome custom message title')) + .hasText('Awesome custom message title'); assert - .dom(PAGE.alertDescription('Awesome custom message title')) + .dom(CUSTOM_MESSAGES.alertDescription('Awesome custom message title')) .hasText( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); assert.dom('img').hasAttribute('src', '/ui/images/custom-messages-dashboard.png'); - await click(PAGE.modalButton('Close')); + await click(CUSTOM_MESSAGES.modalButton('Close')); await click('#unauthenticated'); - await click(PAGE.button('preview')); + await click(CUSTOM_MESSAGES.button('preview')); assert.dom('img').hasAttribute('src', '/ui/images/custom-messages-login.png'); }); @@ -190,14 +201,16 @@ module('Integration | Component | messages/page/create-and-edit', function (hook await render(hbs``, { owner: this.engine, }); - await click(PAGE.radio('modal')); - await fillIn(PAGE.input('title'), 'Preview modal title'); - await fillIn(PAGE.input('message'), 'Some preview modal message thats super long.'); - await click(PAGE.button('preview')); - assert.dom(PAGE.modal('preview modal')).exists(); - assert.dom(PAGE.modal('preview image')).doesNotExist(); - assert.dom(PAGE.modalTitle('Preview modal title')).hasText('Preview modal title'); - assert.dom(PAGE.modalBody('Preview modal title')).hasText('Some preview modal message thats super long.'); + await click(CUSTOM_MESSAGES.radio('modal')); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Preview modal title'); + await fillIn(CUSTOM_MESSAGES.input('message'), 'Some preview modal message thats super long.'); + await click(CUSTOM_MESSAGES.button('preview')); + assert.dom(CUSTOM_MESSAGES.modal('preview modal')).exists(); + assert.dom(CUSTOM_MESSAGES.modal('preview image')).doesNotExist(); + assert.dom(CUSTOM_MESSAGES.modalTitle('Preview modal title')).hasText('Preview modal title'); + assert + .dom(CUSTOM_MESSAGES.modalBody('Preview modal title')) + .hasText('Some preview modal message thats super long.'); }); test('it should show multiple modal message', async function (assert) { @@ -236,19 +249,19 @@ module('Integration | Component | messages/page/create-and-edit', function (hook owner: this.engine, } ); - await fillIn(PAGE.input('title'), 'Awesome custom message title'); + await fillIn(CUSTOM_MESSAGES.input('title'), 'Awesome custom message title'); await fillIn( - PAGE.input('message'), + CUSTOM_MESSAGES.input('message'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare.' ); - await click(PAGE.radio('modal')); - await click(PAGE.button('create-message')); - assert.dom(PAGE.modalTitle('Warning: more than one modal')).exists(); + await click(CUSTOM_MESSAGES.radio('modal')); + await click(CUSTOM_MESSAGES.button('create-message')); + assert.dom(CUSTOM_MESSAGES.modalTitle('Warning: more than one modal')).exists(); assert - .dom(PAGE.modalBody('Warning: more than one modal')) + .dom(CUSTOM_MESSAGES.modalBody('Warning: more than one modal')) .hasText( 'You have an active modal configured after the user logs in and are trying to create another one. It is recommended to avoid having more than one modal at once as it can be intrusive for users. Would you like to continue creating your message? Click “Confirm” to continue.' ); - await click(PAGE.modalButton('confirm')); + await click(CUSTOM_MESSAGES.modalButton('confirm')); }); }); diff --git a/ui/tests/integration/components/config-ui/messages/page/list-test.js b/ui/tests/integration/components/config-ui/messages/page/list-test.js index 94e9bb355b3d..bd95a13d27b8 100644 --- a/ui/tests/integration/components/config-ui/messages/page/list-test.js +++ b/ui/tests/integration/components/config-ui/messages/page/list-test.js @@ -9,7 +9,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import { setupEngine } from 'ember-engines/test-support'; import { render, click } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; -import { PAGE } from 'vault/tests/helpers/config-ui/message-selectors'; +import { CUSTOM_MESSAGES } from 'vault/tests/helpers/config-ui/message-selectors'; import { allowAllCapabilitiesStub } from 'vault/tests/helpers/stubs'; const META = { @@ -89,7 +89,7 @@ module('Integration | Component | messages/page/list', function (hooks) { }); assert.dom('[data-test-icon="message-circle"]').exists(); for (const message of this.messages) { - assert.dom(PAGE.listItem('Message title 1')).exists(); + assert.dom(CUSTOM_MESSAGES.listItem('Message title 1')).exists(); assert.dom(`[data-linked-block-title="${message.id}"]`).hasText(message.title); } }); @@ -121,14 +121,16 @@ module('Integration | Component | messages/page/list', function (hooks) { await render(hbs``, { owner: this.engine, }); - await click(PAGE.button('create message')); - assert.dom(PAGE.modalTitle('maximum-message-modal')).hasText('Maximum number of messages reached'); + await click(CUSTOM_MESSAGES.button('create message')); assert - .dom(PAGE.modalBody('maximum-message-modal')) + .dom(CUSTOM_MESSAGES.modalTitle('maximum-message-modal')) + .hasText('Maximum number of messages reached'); + assert + .dom(CUSTOM_MESSAGES.modalBody('maximum-message-modal')) .hasText( 'Vault can only store up to 100 messages. To create a message, delete one of your messages to clear up space.' ); - await click(PAGE.modalButton('maximum-message-modal')); + await click(CUSTOM_MESSAGES.modalButton('maximum-message-modal')); }); test('it should show the correct badge colors based on badge status', async function (assert) { @@ -137,8 +139,8 @@ module('Integration | Component | messages/page/list', function (hooks) { await render(hbs``, { owner: this.engine, }); - assert.dom(PAGE.badge('0')).hasClass('hds-badge--color-success'); - assert.dom(PAGE.badge('1')).hasClass('hds-badge--color-neutral'); - assert.dom(PAGE.badge('2')).hasClass('hds-badge--color-highlight'); + assert.dom(CUSTOM_MESSAGES.badge('0')).hasClass('hds-badge--color-success'); + assert.dom(CUSTOM_MESSAGES.badge('1')).hasClass('hds-badge--color-neutral'); + assert.dom(CUSTOM_MESSAGES.badge('2')).hasClass('hds-badge--color-highlight'); }); }); diff --git a/ui/tests/integration/components/dashboard/overview-test.js b/ui/tests/integration/components/dashboard/overview-test.js index b5a0ef429eda..6670e4d2ea4a 100644 --- a/ui/tests/integration/components/dashboard/overview-test.js +++ b/ui/tests/integration/components/dashboard/overview-test.js @@ -8,7 +8,7 @@ import { setupRenderingTest } from 'vault/tests/helpers'; import { render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; -import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; +import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; module('Integration | Component | dashboard/overview', function (hooks) { setupRenderingTest(hooks); @@ -74,15 +74,15 @@ module('Integration | Component | dashboard/overview', function (hooks) { @refreshModel={{this.refreshModel}} /> ` ); - assert.dom(SELECTORS.cardHeader('Vault version')).exists(); - assert.dom(SELECTORS.cardName('secrets-engines')).exists(); - assert.dom(SELECTORS.emptyState('secrets-engines')).exists(); - assert.dom(SELECTORS.cardName('learn-more')).exists(); - assert.dom(SELECTORS.cardName('quick-actions')).exists(); - assert.dom(SELECTORS.emptyState('quick-actions')).exists(); - assert.dom(SELECTORS.cardName('configuration-details')).doesNotExist(); - assert.dom(SELECTORS.cardName('replication')).doesNotExist(); - assert.dom(SELECTORS.cardName('client-count')).doesNotExist(); + assert.dom(DASHBOARD.cardHeader('Vault version')).exists(); + assert.dom(DASHBOARD.cardName('secrets-engines')).exists(); + assert.dom(DASHBOARD.emptyState('secrets-engines')).exists(); + assert.dom(DASHBOARD.cardName('learn-more')).exists(); + assert.dom(DASHBOARD.cardName('quick-actions')).exists(); + assert.dom(DASHBOARD.emptyState('quick-actions')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).doesNotExist(); + assert.dom(DASHBOARD.cardName('replication')).doesNotExist(); + assert.dom(DASHBOARD.cardName('client-count')).doesNotExist(); }); test('it should hide client count and replication card on community', async function (assert) { @@ -102,13 +102,13 @@ module('Integration | Component | dashboard/overview', function (hooks) { ` ); - assert.dom(SELECTORS.cardHeader('Vault version')).exists(); - assert.dom(SELECTORS.cardName('secrets-engines')).exists(); - assert.dom(SELECTORS.cardName('learn-more')).exists(); - assert.dom(SELECTORS.cardName('quick-actions')).exists(); - assert.dom(SELECTORS.cardName('configuration-details')).exists(); - assert.dom(SELECTORS.cardName('replication')).doesNotExist(); - assert.dom(SELECTORS.cardName('client-count')).doesNotExist(); + assert.dom(DASHBOARD.cardHeader('Vault version')).exists(); + assert.dom(DASHBOARD.cardName('secrets-engines')).exists(); + assert.dom(DASHBOARD.cardName('learn-more')).exists(); + assert.dom(DASHBOARD.cardName('quick-actions')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).exists(); + assert.dom(DASHBOARD.cardName('replication')).doesNotExist(); + assert.dom(DASHBOARD.cardName('client-count')).doesNotExist(); }); test('it should show client count on enterprise w/ license', async function (assert) { @@ -132,12 +132,12 @@ module('Integration | Component | dashboard/overview', function (hooks) { @license={{this.license}} @refreshModel={{this.refreshModel}} />` ); - assert.dom(SELECTORS.cardHeader('Vault version')).exists(); - assert.dom(SELECTORS.cardName('secrets-engines')).exists(); - assert.dom(SELECTORS.cardName('learn-more')).exists(); - assert.dom(SELECTORS.cardName('quick-actions')).exists(); - assert.dom(SELECTORS.cardName('configuration-details')).exists(); - assert.dom(SELECTORS.cardName('client-count')).exists(); + assert.dom(DASHBOARD.cardHeader('Vault version')).exists(); + assert.dom(DASHBOARD.cardName('secrets-engines')).exists(); + assert.dom(DASHBOARD.cardName('learn-more')).exists(); + assert.dom(DASHBOARD.cardName('quick-actions')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).exists(); + assert.dom(DASHBOARD.cardName('client-count')).exists(); }); test('it should hide client count on enterprise w/o license ', async function (assert) { @@ -158,13 +158,13 @@ module('Integration | Component | dashboard/overview', function (hooks) { />` ); - assert.dom(SELECTORS.cardHeader('Vault version')).exists(); + assert.dom(DASHBOARD.cardHeader('Vault version')).exists(); assert.dom('[data-test-badge-namespace]').exists(); - assert.dom(SELECTORS.cardName('secrets-engines')).exists(); - assert.dom(SELECTORS.cardName('learn-more')).exists(); - assert.dom(SELECTORS.cardName('quick-actions')).exists(); - assert.dom(SELECTORS.cardName('configuration-details')).exists(); - assert.dom(SELECTORS.cardName('client-count')).doesNotExist(); + assert.dom(DASHBOARD.cardName('secrets-engines')).exists(); + assert.dom(DASHBOARD.cardName('learn-more')).exists(); + assert.dom(DASHBOARD.cardName('quick-actions')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).exists(); + assert.dom(DASHBOARD.cardName('client-count')).doesNotExist(); }); test('it should hide replication on enterprise not on root namespace', async function (assert) { @@ -190,14 +190,14 @@ module('Integration | Component | dashboard/overview', function (hooks) { @refreshModel={{this.refreshModel}} />` ); - assert.dom(SELECTORS.cardHeader('Vault version')).exists(); + assert.dom(DASHBOARD.cardHeader('Vault version')).exists(); assert.dom('[data-test-badge-namespace]').exists(); - assert.dom(SELECTORS.cardName('secrets-engines')).exists(); - assert.dom(SELECTORS.cardName('learn-more')).exists(); - assert.dom(SELECTORS.cardName('quick-actions')).exists(); - assert.dom(SELECTORS.cardName('configuration-details')).exists(); - assert.dom(SELECTORS.cardName('replication')).doesNotExist(); - assert.dom(SELECTORS.cardName('client-count')).exists(); + assert.dom(DASHBOARD.cardName('secrets-engines')).exists(); + assert.dom(DASHBOARD.cardName('learn-more')).exists(); + assert.dom(DASHBOARD.cardName('quick-actions')).exists(); + assert.dom(DASHBOARD.cardName('configuration-details')).exists(); + assert.dom(DASHBOARD.cardName('replication')).doesNotExist(); + assert.dom(DASHBOARD.cardName('client-count')).exists(); }); module('learn more card', function () { diff --git a/ui/tests/integration/components/dashboard/quick-actions-card-test.js b/ui/tests/integration/components/dashboard/quick-actions-card-test.js index 8122f9260f36..1563b722cc63 100644 --- a/ui/tests/integration/components/dashboard/quick-actions-card-test.js +++ b/ui/tests/integration/components/dashboard/quick-actions-card-test.js @@ -10,7 +10,7 @@ import { hbs } from 'ember-cli-htmlbars'; import { fillIn } from '@ember/test-helpers'; import { selectChoose } from 'ember-power-select/test-support/helpers'; -import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; +import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; import { setRunOptions } from 'ember-a11y-testing/test-support'; module('Integration | Component | dashboard/quick-actions-card', function (hooks) { @@ -105,32 +105,32 @@ module('Integration | Component | dashboard/quick-actions-card', function (hooks test('it should show quick action empty state if no engine is selected', async function (assert) { await this.renderComponent(); assert.dom('.title').hasText('Quick actions'); - assert.dom(SELECTORS.searchSelect('secrets-engines')).exists({ count: 1 }); - assert.dom(SELECTORS.emptyState('no-mount-selected')).exists({ count: 1 }); + assert.dom(DASHBOARD.searchSelect('secrets-engines')).exists({ count: 1 }); + assert.dom(DASHBOARD.emptyState('no-mount-selected')).exists({ count: 1 }); }); test('it should show correct actions for pki', async function (assert) { await this.renderComponent(); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), 'pki-0-test'); - await fillIn(SELECTORS.selectEl, 'Issue certificate'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - await fillIn(SELECTORS.selectEl, 'Issue certificate'); - assert.dom(SELECTORS.actionButton('Issue leaf certificate')).exists({ count: 1 }); - assert.dom(SELECTORS.subtitle('param')).hasText('Role to use'); - await fillIn(SELECTORS.selectEl, 'View certificate'); - assert.dom(SELECTORS.subtitle('param')).hasText('Certificate serial number'); - assert.dom(SELECTORS.actionButton('View certificate')).exists({ count: 1 }); - await fillIn(SELECTORS.selectEl, 'View issuer'); - assert.dom(SELECTORS.subtitle('param')).hasText('Issuer'); - assert.dom(SELECTORS.actionButton('View issuer')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), 'pki-0-test'); + await fillIn(DASHBOARD.selectEl, 'Issue certificate'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + await fillIn(DASHBOARD.selectEl, 'Issue certificate'); + assert.dom(DASHBOARD.actionButton('Issue leaf certificate')).exists({ count: 1 }); + assert.dom(DASHBOARD.subtitle('param')).hasText('Role to use'); + await fillIn(DASHBOARD.selectEl, 'View certificate'); + assert.dom(DASHBOARD.subtitle('param')).hasText('Certificate serial number'); + assert.dom(DASHBOARD.actionButton('View certificate')).exists({ count: 1 }); + await fillIn(DASHBOARD.selectEl, 'View issuer'); + assert.dom(DASHBOARD.subtitle('param')).hasText('Issuer'); + assert.dom(DASHBOARD.actionButton('View issuer')).exists({ count: 1 }); }); test('it should show correct actions for database', async function (assert) { await this.renderComponent(); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), 'database-test'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - await fillIn(SELECTORS.selectEl, 'Generate credentials for database'); - assert.dom(SELECTORS.subtitle('param')).hasText('Role to use'); - assert.dom(SELECTORS.actionButton('Generate credentials')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), 'database-test'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + await fillIn(DASHBOARD.selectEl, 'Generate credentials for database'); + assert.dom(DASHBOARD.subtitle('param')).hasText('Role to use'); + assert.dom(DASHBOARD.actionButton('Generate credentials')).exists({ count: 1 }); }); test('it should show correct actions for kv', async function (assert) { await this.renderComponent(); @@ -140,10 +140,10 @@ module('Integration | Component | dashboard/quick-actions-card', function (hooks 5, 'renders only kv v2, pki and db engines' ); - await selectChoose(SELECTORS.searchSelect('secrets-engines'), 'kv-v2-test'); - assert.dom(SELECTORS.emptyState('quick-actions')).doesNotExist(); - await fillIn(SELECTORS.selectEl, 'Find KV secrets'); - assert.dom(SELECTORS.kvSearchSelect).exists('Shows option to search fo KVv2 secret'); - assert.dom(SELECTORS.actionButton('Read secrets')).exists({ count: 1 }); + await selectChoose(DASHBOARD.searchSelect('secrets-engines'), 'kv-v2-test'); + assert.dom(DASHBOARD.emptyState('quick-actions')).doesNotExist(); + await fillIn(DASHBOARD.selectEl, 'Find KV secrets'); + assert.dom(DASHBOARD.kvSearchSelect).exists('Shows option to search fo KVv2 secret'); + assert.dom(DASHBOARD.actionButton('Read secrets')).exists({ count: 1 }); }); }); diff --git a/ui/tests/integration/components/dashboard/replication-card-test.js b/ui/tests/integration/components/dashboard/replication-card-test.js index 7ee7d0d2f452..e8d9a154bade 100644 --- a/ui/tests/integration/components/dashboard/replication-card-test.js +++ b/ui/tests/integration/components/dashboard/replication-card-test.js @@ -9,7 +9,7 @@ import { render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; import timestamp from 'core/utils/timestamp'; -import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; +import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; module('Integration | Component | dashboard/replication-card', function (hooks) { setupRenderingTest(hooks); @@ -45,12 +45,12 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('DR primary')).hasText('DR primary'); - assert.dom(SELECTORS.tooltipTitle('DR primary')).hasText('running'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).exists(); - assert.dom(SELECTORS.title('Performance primary')).hasText('Performance primary'); - assert.dom(SELECTORS.tooltipTitle('Performance primary')).hasText('running'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'check-circle')).exists(); + assert.dom(DASHBOARD.title('DR primary')).hasText('DR primary'); + assert.dom(DASHBOARD.tooltipTitle('DR primary')).hasText('running'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).exists(); + assert.dom(DASHBOARD.title('Performance primary')).hasText('Performance primary'); + assert.dom(DASHBOARD.tooltipTitle('Performance primary')).hasText('running'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'check-circle')).exists(); }); test('it should display replication information if both dr and performance replication are enabled as features and only dr is setup', async function (assert) { this.replication = { @@ -72,17 +72,17 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('DR primary')).hasText('DR primary'); - assert.dom(SELECTORS.tooltipTitle('DR primary')).hasText('running'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).exists(); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).hasClass('has-text-success'); + assert.dom(DASHBOARD.title('DR primary')).hasText('DR primary'); + assert.dom(DASHBOARD.tooltipTitle('DR primary')).hasText('running'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).exists(); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'check-circle')).hasClass('has-text-success'); - assert.dom(SELECTORS.title('Performance primary')).hasText('Performance primary'); + assert.dom(DASHBOARD.title('Performance primary')).hasText('Performance primary'); - assert.dom(SELECTORS.tooltipTitle('Performance primary')).hasText('not set up'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')).exists(); + assert.dom(DASHBOARD.tooltipTitle('Performance primary')).hasText('not set up'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')).exists(); assert - .dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')) + .dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')) .hasClass('has-text-danger'); }); @@ -107,16 +107,16 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('state')).hasText('state'); - assert.dom(SELECTORS.subtext('state')).hasText('The current operating state of the cluster.'); - assert.dom(SELECTORS.tooltipTitle('state')).hasText('running'); - assert.dom(SELECTORS.tooltipIcon('dr', 'state', 'check-circle')).exists(); - assert.dom(SELECTORS.tooltipIcon('dr', 'state', 'check-circle')).hasClass('has-text-success'); - assert.dom(SELECTORS.statLabel('known secondaries')).hasText('known secondaries'); + assert.dom(DASHBOARD.title('state')).hasText('state'); + assert.dom(DASHBOARD.subtext('state')).hasText('The current operating state of the cluster.'); + assert.dom(DASHBOARD.tooltipTitle('state')).hasText('running'); + assert.dom(DASHBOARD.tooltipIcon('dr', 'state', 'check-circle')).exists(); + assert.dom(DASHBOARD.tooltipIcon('dr', 'state', 'check-circle')).hasClass('has-text-success'); + assert.dom(DASHBOARD.statLabel('known secondaries')).hasText('known secondaries'); assert - .dom(SELECTORS.statText('known secondaries')) + .dom(DASHBOARD.statText('known secondaries')) .hasText('Number of secondaries connected to this primary.'); - assert.dom(SELECTORS.statValue('known secondaries')).hasText('1'); + assert.dom(DASHBOARD.statValue('known secondaries')).hasText('1'); }); test('it should show correct icons if dr and performance replication is idle or shutdown states', async function (assert) { @@ -140,16 +140,16 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('DR primary')).hasText('DR primary'); - assert.dom(SELECTORS.tooltipTitle('DR primary')).hasText('idle'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'x-square')).exists(); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'DR primary', 'x-square')).hasClass('has-text-danger'); + assert.dom(DASHBOARD.title('DR primary')).hasText('DR primary'); + assert.dom(DASHBOARD.tooltipTitle('DR primary')).hasText('idle'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'x-square')).exists(); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'DR primary', 'x-square')).hasClass('has-text-danger'); - assert.dom(SELECTORS.title('Performance primary')).hasText('Performance primary'); - assert.dom(SELECTORS.tooltipTitle('Performance primary')).hasText('shutdown'); - assert.dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')).exists(); + assert.dom(DASHBOARD.title('Performance primary')).hasText('Performance primary'); + assert.dom(DASHBOARD.tooltipTitle('Performance primary')).hasText('shutdown'); + assert.dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')).exists(); assert - .dom(SELECTORS.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')) + .dom(DASHBOARD.tooltipIcon('dr-perf', 'Performance primary', 'x-circle')) .hasClass('has-text-danger'); }); @@ -173,8 +173,8 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('DR primary')).hasText('DR primary'); - assert.dom(SELECTORS.title('Performance primary')).hasText('Performance primary'); + assert.dom(DASHBOARD.title('DR primary')).hasText('DR primary'); + assert.dom(DASHBOARD.title('Performance primary')).hasText('Performance primary'); this.replication = { dr: { @@ -195,7 +195,7 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.title('Performance secondary')).hasText('Performance secondary'); + assert.dom(DASHBOARD.title('Performance secondary')).hasText('Performance secondary'); }); test('it should show empty state', async function (assert) { @@ -216,11 +216,11 @@ module('Integration | Component | dashboard/replication-card', function (hooks) @refresh={{this.refresh}} /> ` ); - assert.dom(SELECTORS.emptyState('replication')).exists(); - assert.dom(SELECTORS.emptyStateTitle('replication')).hasText('Replication not set up'); + assert.dom(DASHBOARD.emptyState('replication')).exists(); + assert.dom(DASHBOARD.emptyStateTitle('replication')).hasText('Replication not set up'); assert - .dom(SELECTORS.emptyStateMessage('replication')) + .dom(DASHBOARD.emptyStateMessage('replication')) .hasText('Data will be listed here. Enable a primary replication cluster to get started.'); - assert.dom(SELECTORS.emptyStateActions('replication')).hasText('Enable replication'); + assert.dom(DASHBOARD.emptyStateActions('replication')).hasText('Enable replication'); }); }); diff --git a/ui/tests/integration/components/dashboard/secrets-engines-card-test.js b/ui/tests/integration/components/dashboard/secrets-engines-card-test.js index c17238b0f5a6..8b529b94facb 100644 --- a/ui/tests/integration/components/dashboard/secrets-engines-card-test.js +++ b/ui/tests/integration/components/dashboard/secrets-engines-card-test.js @@ -7,7 +7,7 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'vault/tests/helpers'; import { render } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; -import { SELECTORS } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; +import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors'; module('Integration | Component | dashboard/secrets-engines-card', function (hooks) { setupRenderingTest(hooks); @@ -102,8 +102,8 @@ module('Integration | Component | dashboard/secrets-engines-card', function (hoo test('it should display only five secrets engines and show help text for more than 5 engines', async function (assert) { await this.renderComponent(); - assert.dom(SELECTORS.cardHeader('Secrets engines')).hasText('Secrets engines'); - assert.dom(SELECTORS.tableRow('Secrets engines')).exists({ count: 5 }); + assert.dom(DASHBOARD.cardHeader('Secrets engines')).hasText('Secrets engines'); + assert.dom(DASHBOARD.tableRow('Secrets engines')).exists({ count: 5 }); assert.dom('[data-test-secrets-engine-total-help-text]').exists(); assert .dom('[data-test-secrets-engine-total-help-text]') @@ -114,18 +114,18 @@ module('Integration | Component | dashboard/secrets-engines-card', function (hoo test('it should display the secrets engines accessor and path', async function (assert) { await this.renderComponent(); - assert.dom(SELECTORS.cardHeader('Secrets engines')).hasText('Secrets engines'); - assert.dom(SELECTORS.tableRow('Secrets engines')).exists({ count: 5 }); + assert.dom(DASHBOARD.cardHeader('Secrets engines')).hasText('Secrets engines'); + assert.dom(DASHBOARD.tableRow('Secrets engines')).exists({ count: 5 }); this.secretsEngines.slice(0, 5).forEach((engine) => { - assert.dom(SELECTORS.secretsEnginesCard.secretEngineAccessorRow(engine.id)).hasText(engine.accessor); + assert.dom(DASHBOARD.secretsEnginesCard.secretEngineAccessorRow(engine.id)).hasText(engine.accessor); if (engine.description) { assert - .dom(SELECTORS.secretsEnginesCard.secretEngineDescription(engine.id)) + .dom(DASHBOARD.secretsEnginesCard.secretEngineDescription(engine.id)) .hasText(engine.description); } else { assert - .dom(SELECTORS.secretsEnginesCard.secretEngineDescription(engine.id)) + .dom(DASHBOARD.secretsEnginesCard.secretEngineDescription(engine.id)) .doesNotExist(engine.description); } }); From d8ce0f90eecd215d8582a9477a84b82abf3f2b10 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 12:54:00 -0500 Subject: [PATCH 05/32] Rename client count selector export --- ui/tests/acceptance/clients/counts-test.js | 2 +- .../clients/counts/overview-test.js | 96 +++++++++---------- .../acceptance/clients/counts/sync-test.js | 8 +- ui/tests/helpers/clients.js | 4 +- .../components/clients/page/counts-test.js | 2 +- .../components/clients/page/sync-test.js | 4 +- .../components/clients/page/token-test.js | 2 +- .../components/clients/running-total-test.js | 2 +- 8 files changed, 61 insertions(+), 59 deletions(-) diff --git a/ui/tests/acceptance/clients/counts-test.js b/ui/tests/acceptance/clients/counts-test.js index e6424f844845..3e81af93cdb6 100644 --- a/ui/tests/acceptance/clients/counts-test.js +++ b/ui/tests/acceptance/clients/counts-test.js @@ -11,7 +11,7 @@ import sinon from 'sinon'; import { visit, click, currentURL } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; import timestamp from 'core/utils/timestamp'; module('Acceptance | clients | counts', function (hooks) { diff --git a/ui/tests/acceptance/clients/counts/overview-test.js b/ui/tests/acceptance/clients/counts/overview-test.js index aea4262c9d0a..9b3d6cf25b9c 100644 --- a/ui/tests/acceptance/clients/counts/overview-test.js +++ b/ui/tests/acceptance/clients/counts/overview-test.js @@ -12,7 +12,7 @@ import { visit, click, findAll, settled } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { ARRAY_OF_MONTHS } from 'core/utils/date-formatters'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; import { create } from 'ember-cli-page-object'; import { clickTrigger } from 'ember-power-select/test-support/helpers'; import { formatNumber } from 'core/helpers/format-number'; @@ -48,17 +48,17 @@ module('Acceptance | clients | overview', function (hooks) { test('it should render charts', async function (assert) { assert - .dom(SELECTORS.counts.startMonth) + .dom(CLIENT_COUNT.counts.startMonth) .hasText('July 2023', 'billing start month is correctly parsed from license'); assert - .dom(SELECTORS.rangeDropdown) + .dom(CLIENT_COUNT.rangeDropdown) .hasText('Jul 2023 - Jan 2024', 'Date range shows dates correctly parsed activity response'); - assert.dom(SELECTORS.attributionBlock).exists('Shows attribution area'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('Shows attribution area'); assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .exists('Shows running totals with monthly breakdown charts'); assert - .dom(SELECTORS.charts.line.xAxisLabel) + .dom(CLIENT_COUNT.charts.line.xAxisLabel) .hasText('7/23', 'x-axis labels start with billing start date'); assert.strictEqual( findAll('[data-test-line-chart="plot-point"]').length, @@ -69,17 +69,17 @@ module('Acceptance | clients | overview', function (hooks) { test('it should update charts when querying date ranges', async function (assert) { // query for single, historical month with no new counts (July 2023) - await click(SELECTORS.rangeDropdown); + await click(CLIENT_COUNT.rangeDropdown); await click('[data-test-show-calendar]'); await click('[data-test-previous-year]'); await click(`[data-test-calendar-month=${ARRAY_OF_MONTHS[LICENSE_START.getMonth()]}]`); assert - .dom(SELECTORS.runningTotalMonthStats) + .dom(CLIENT_COUNT.runningTotalMonthStats) .doesNotExist('running total single month stat boxes do not show'); assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .doesNotExist('running total month over month charts do not show'); - assert.dom(SELECTORS.attributionBlock).exists('attribution area shows'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('attribution area shows'); assert .dom('[data-test-chart-container="new-clients"] [data-test-component="empty-state"]') .exists('new client attribution has empty state'); @@ -89,22 +89,22 @@ module('Acceptance | clients | overview', function (hooks) { assert.dom('[data-test-chart-container="total-clients"]').exists('total client attribution chart shows'); // reset to billing period - await click(SELECTORS.rangeDropdown); + await click(CLIENT_COUNT.rangeDropdown); await click('[data-test-current-billing-period]'); // change billing start to month/year of upgrade to 1.10 - await click(SELECTORS.counts.startEdit); - await click(SELECTORS.monthDropdown); + await click(CLIENT_COUNT.counts.startEdit); + await click(CLIENT_COUNT.monthDropdown); await click(`[data-test-dropdown-month="${ARRAY_OF_MONTHS[UPGRADE_DATE.getMonth()]}"]`); - await click(SELECTORS.yearDropdown); + await click(CLIENT_COUNT.yearDropdown); await click(`[data-test-dropdown-year="${UPGRADE_DATE.getFullYear()}"]`); await click('[data-test-date-dropdown-submit]'); - assert.dom(SELECTORS.attributionBlock).exists('Shows attribution area'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('Shows attribution area'); assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .exists('Shows running totals with monthly breakdown charts'); assert - .dom(SELECTORS.charts.line.xAxisLabel) + .dom(CLIENT_COUNT.charts.line.xAxisLabel) .hasText('9/23', 'x-axis labels start with queried start month (upgrade date)'); assert.strictEqual( findAll('[data-test-line-chart="plot-point"]').length, @@ -113,50 +113,50 @@ module('Acceptance | clients | overview', function (hooks) { ); // query for single, historical month (upgrade month) - await click(SELECTORS.rangeDropdown); + await click(CLIENT_COUNT.rangeDropdown); await click('[data-test-show-calendar]'); assert.dom('[data-test-display-year]').hasText('2024'); await click('[data-test-previous-year]'); await click('[data-test-calendar-month="September"]'); - assert.dom(SELECTORS.runningTotalMonthStats).exists('running total single month stat boxes show'); + assert.dom(CLIENT_COUNT.runningTotalMonthStats).exists('running total single month stat boxes show'); assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .doesNotExist('running total month over month charts do not show'); - assert.dom(SELECTORS.attributionBlock).exists('attribution area shows'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('attribution area shows'); assert.dom('[data-test-chart-container="new-clients"]').exists('new client attribution chart shows'); assert.dom('[data-test-chart-container="total-clients"]').exists('total client attribution chart shows'); // query historical date range (from September 2023 to December 2023) - await click(SELECTORS.rangeDropdown); + await click(CLIENT_COUNT.rangeDropdown); await click('[data-test-show-calendar]'); await click('[data-test-calendar-month="December"]'); - assert.dom(SELECTORS.attributionBlock).exists('Shows attribution area'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('Shows attribution area'); assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .exists('Shows running totals with monthly breakdown charts'); assert.strictEqual( findAll('[data-test-line-chart="plot-point"]').length, 4, 'line chart plots 4 points to match query' ); - const xAxisLabels = findAll(SELECTORS.charts.line.xAxisLabel); + const xAxisLabels = findAll(CLIENT_COUNT.charts.line.xAxisLabel); assert .dom(xAxisLabels[xAxisLabels.length - 1]) .hasText('12/23', 'x-axis labels end with queried end month'); // reset to billing period - await click(SELECTORS.rangeDropdown); + await click(CLIENT_COUNT.rangeDropdown); await click('[data-test-current-billing-period]'); // query month older than count start date - await click(SELECTORS.counts.startEdit); - await click(SELECTORS.monthDropdown); + await click(CLIENT_COUNT.counts.startEdit); + await click(CLIENT_COUNT.monthDropdown); await click(`[data-test-dropdown-month="${ARRAY_OF_MONTHS[LICENSE_START.getMonth()]}"]`); - await click(SELECTORS.yearDropdown); + await click(CLIENT_COUNT.yearDropdown); await click(`[data-test-dropdown-year="${LICENSE_START.getFullYear() - 3}"]`); await click('[data-test-date-dropdown-submit]'); assert - .dom(SELECTORS.counts.startDiscrepancy) + .dom(CLIENT_COUNT.counts.startDiscrepancy) .hasTextContaining( 'You requested data from July 2020. We only have data from January 2023, and that is what is being shown here.', 'warning banner displays that date queried was prior to count start date' @@ -165,9 +165,9 @@ module('Acceptance | clients | overview', function (hooks) { test('totals filter correctly with full data', async function (assert) { assert - .dom(SELECTORS.charts.chart('running total')) + .dom(CLIENT_COUNT.charts.chart('running total')) .exists('Shows running totals with monthly breakdown charts'); - assert.dom(SELECTORS.attributionBlock).exists('Shows attribution area'); + assert.dom(CLIENT_COUNT.attributionBlock).exists('Shows attribution area'); const response = await this.store.peekRecord('clients/activity', 'some-activity-id'); // FILTER BY NAMESPACE @@ -177,19 +177,19 @@ module('Acceptance | clients | overview', function (hooks) { const topNamespace = response.byNamespace[0]; const topMount = topNamespace.mounts[0]; - assert.dom(SELECTORS.selectedNs).hasText(topNamespace.label, 'selects top namespace'); + assert.dom(CLIENT_COUNT.selectedNs).hasText(topNamespace.label, 'selects top namespace'); assert.dom('[data-test-top-attribution]').includesText('Top auth method'); assert - .dom(SELECTORS.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .includesText(`${formatNumber([topNamespace.entity_clients])}`, 'total entity clients is accurate'); assert - .dom(SELECTORS.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .includesText( `${formatNumber([topNamespace.non_entity_clients])}`, 'total non-entity clients is accurate' ); assert - .dom(SELECTORS.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .includesText(`${formatNumber([topNamespace.secret_syncs])}`, 'total sync clients is accurate'); assert .dom('[data-test-attribution-clients] p') @@ -201,35 +201,35 @@ module('Acceptance | clients | overview', function (hooks) { await settled(); assert.ok(true, 'Filter by first auth method'); - assert.dom(SELECTORS.selectedAuthMount).hasText(topMount.label, 'selects top mount'); + assert.dom(CLIENT_COUNT.selectedAuthMount).hasText(topMount.label, 'selects top mount'); assert - .dom(SELECTORS.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .includesText(`${formatNumber([topMount.entity_clients])}`, 'total entity clients is accurate'); assert - .dom(SELECTORS.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .includesText(`${formatNumber([topMount.non_entity_clients])}`, 'total non-entity clients is accurate'); assert - .dom(SELECTORS.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .includesText(`${formatNumber([topMount.secret_syncs])}`, 'total sync clients is accurate'); - assert.dom(SELECTORS.attributionBlock).doesNotExist('Does not show attribution block'); + assert.dom(CLIENT_COUNT.attributionBlock).doesNotExist('Does not show attribution block'); await click('#namespace-search-select [data-test-selected-list-button="delete"]'); assert.ok(true, 'Remove namespace filter without first removing auth method filter'); assert.dom('[data-test-top-attribution]').includesText('Top namespace'); assert - .dom(SELECTORS.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .hasTextContaining( `${formatNumber([response.total.entity_clients])}`, 'total entity clients is back to unfiltered value' ); assert - .dom(SELECTORS.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .hasTextContaining( `${formatNumber([formatNumber([response.total.non_entity_clients])])}`, 'total non-entity clients is back to unfiltered value' ); assert - .dom(SELECTORS.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .hasTextContaining( `${formatNumber([formatNumber([response.total.secret_syncs])])}`, 'total sync clients is back to unfiltered value' @@ -276,14 +276,14 @@ module('Acceptance | clients | overview | sync in license, activated', function test('it should show secrets sync data in overview and tab', async function (assert) { assert - .dom(SELECTORS.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .exists('shows secret sync data on overview'); await click(GENERAL.tab('sync')); assert.dom(GENERAL.tab('sync')).hasClass('active'); assert.dom(GENERAL.emptyStateTitle).doesNotExist(); assert - .dom(SELECTORS.charts.chart('Secrets sync usage')) + .dom(CLIENT_COUNT.charts.chart('Secrets sync usage')) .exists('chart is shown because feature is active and has data'); }); }); @@ -306,7 +306,7 @@ module('Acceptance | clients | overview | sync in license, not activated', funct test('it should hide secrets sync charts', async function (assert) { assert - .dom(SELECTORS.charts.chart('Secrets sync usage')) + .dom(CLIENT_COUNT.charts.chart('Secrets sync usage')) .doesNotExist('chart is hidden because feature is not activated'); assert.dom('[data-test-stat-text="secret-syncs"]').doesNotExist(); @@ -331,7 +331,7 @@ module('Acceptance | clients | overview | sync not in license', function (hooks) }); test('it should hide secrets sync charts', async function (assert) { - assert.dom(SELECTORS.charts.chart('Secrets sync usage')).doesNotExist(); + assert.dom(CLIENT_COUNT.charts.chart('Secrets sync usage')).doesNotExist(); assert.dom('[data-test-stat-text="secret-syncs"]').doesNotExist(); }); diff --git a/ui/tests/acceptance/clients/counts/sync-test.js b/ui/tests/acceptance/clients/counts/sync-test.js index e5e80b5b0cf1..e0c680f8f25b 100644 --- a/ui/tests/acceptance/clients/counts/sync-test.js +++ b/ui/tests/acceptance/clients/counts/sync-test.js @@ -13,7 +13,7 @@ import sinon from 'sinon'; import timestamp from 'core/utils/timestamp'; import authPage from 'vault/tests/pages/auth'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; module('Acceptance | clients | sync | activated', function (hooks) { setupApplicationTest(hooks); @@ -36,8 +36,10 @@ module('Acceptance | clients | sync | activated', function (hooks) { test('it should render charts when secrets sync is activated', async function (assert) { syncHandler(this.server); - assert.dom(SELECTORS.charts.chart('Secrets sync usage')).exists('Secrets sync usage chart is rendered'); - assert.dom(SELECTORS.syncTab.total).exists('Total sync clients chart is rendered'); + assert + .dom(CLIENT_COUNT.charts.chart('Secrets sync usage')) + .exists('Secrets sync usage chart is rendered'); + assert.dom(CLIENT_COUNT.syncTab.total).exists('Total sync clients chart is rendered'); assert.dom(GENERAL.emptyStateTitle).doesNotExist(); }); }); diff --git a/ui/tests/helpers/clients.js b/ui/tests/helpers/clients.js index 0febcb8aa05c..4439e712a539 100644 --- a/ui/tests/helpers/clients.js +++ b/ui/tests/helpers/clients.js @@ -25,7 +25,7 @@ import { addMonths } from 'date-fns'; queries unavailable License start date this month */ -export const SELECTORS = { +export const CLIENT_COUNT = { counts: { startLabel: '[data-test-counts-start-label]', description: '[data-test-counts-description]', @@ -140,7 +140,7 @@ export function overrideResponse(httpStatus, data) { } export async function dateDropdownSelect(month, year) { - const { dateDropdown, counts } = SELECTORS; + const { dateDropdown, counts } = CLIENT_COUNT; await click(counts.startEdit); await click(dateDropdown.toggleMonth); await click(dateDropdown.selectMonth(month)); diff --git a/ui/tests/integration/components/clients/page/counts-test.js b/ui/tests/integration/components/clients/page/counts-test.js index 425d8d4479af..a2b9a5cedb46 100644 --- a/ui/tests/integration/components/clients/page/counts-test.js +++ b/ui/tests/integration/components/clients/page/counts-test.js @@ -11,7 +11,7 @@ import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS as ts, dateDropdownSelect } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts, dateDropdownSelect } from 'vault/tests/helpers/clients'; import { selectChoose } from 'ember-power-select/test-support/helpers'; import timestamp from 'core/utils/timestamp'; import sinon from 'sinon'; diff --git a/ui/tests/integration/components/clients/page/sync-test.js b/ui/tests/integration/components/clients/page/sync-test.js index a2c30e1f8a38..a3d0447c8fac 100644 --- a/ui/tests/integration/components/clients/page/sync-test.js +++ b/ui/tests/integration/components/clients/page/sync-test.js @@ -11,14 +11,14 @@ import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; import { formatNumber } from 'core/helpers/format-number'; import { calculateAverage } from 'vault/utils/chart-helpers'; import { dateFormat } from 'core/helpers/date-format'; const START_TIME = getUnixTime(LICENSE_START); const END_TIME = getUnixTime(STATIC_NOW); -const { syncTab, charts, usageStats } = SELECTORS; +const { syncTab, charts, usageStats } = CLIENT_COUNT; module('Integration | Component | clients | Clients::Page::Sync', function (hooks) { setupRenderingTest(hooks); diff --git a/ui/tests/integration/components/clients/page/token-test.js b/ui/tests/integration/components/clients/page/token-test.js index 35023ca42e04..47c88906f6ac 100644 --- a/ui/tests/integration/components/clients/page/token-test.js +++ b/ui/tests/integration/components/clients/page/token-test.js @@ -14,7 +14,7 @@ import { calculateAverage } from 'vault/utils/chart-helpers'; import { formatNumber } from 'core/helpers/format-number'; import { dateFormat } from 'core/helpers/date-format'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { SELECTORS as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; const START_TIME = getUnixTime(LICENSE_START); const END_TIME = getUnixTime(STATIC_NOW); diff --git a/ui/tests/integration/components/clients/running-total-test.js b/ui/tests/integration/components/clients/running-total-test.js index fc42e32aef4d..e89c08a77421 100644 --- a/ui/tests/integration/components/clients/running-total-test.js +++ b/ui/tests/integration/components/clients/running-total-test.js @@ -15,7 +15,7 @@ import { findAll } from '@ember/test-helpers'; import { formatNumber } from 'core/helpers/format-number'; import timestamp from 'core/utils/timestamp'; import { setRunOptions } from 'ember-a11y-testing/test-support'; -import { SELECTORS as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; const START_TIME = getUnixTime(LICENSE_START); From c92e61f1111d6aa542f4006174628acb84fbb3ea Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 14:03:14 -0500 Subject: [PATCH 06/32] clean up .CodeMirror selectors to use helper instead --- ui/tests/acceptance/policies/index-test.js | 6 ++-- .../secrets/backend/kv/secret-test.js | 7 ++-- ui/tests/acceptance/tools-test.js | 33 ++++++++++++++----- ui/tests/acceptance/transit-test.js | 12 ++++--- ui/tests/helpers/codemirror.js | 22 ++++++++----- .../components/console/log-json-test.js | 3 +- .../components/secret-edit-test.js | 22 +++++++------ .../components/transit-key-actions-test.js | 18 ++++------ 8 files changed, 70 insertions(+), 53 deletions(-) diff --git a/ui/tests/acceptance/policies/index-test.js b/ui/tests/acceptance/policies/index-test.js index e79eb3057e58..9e2dfef83b4f 100644 --- a/ui/tests/acceptance/policies/index-test.js +++ b/ui/tests/acceptance/policies/index-test.js @@ -10,7 +10,6 @@ import { fillIn, visit, click, - find, waitFor, waitUntil, } from '@ember/test-helpers'; @@ -20,6 +19,7 @@ import { v4 as uuidv4 } from 'uuid'; import authPage from 'vault/tests/pages/auth'; import { runCmd } from 'vault/tests/helpers/commands'; +import codemirror from 'vault/tests/helpers/codemirror'; const SELECT = { policyByName: (name) => `[data-test-policy-link="${name}"]`, @@ -86,7 +86,7 @@ module('Acceptance | policies/acl', function (hooks) { await click(SELECT.createLink); await fillIn(SELECT.nameInput, policyName); - find('.CodeMirror').CodeMirror.setValue(policyString); + codemirror().setValue(policyString); await click(SELECT.save); assert.strictEqual( currentURL(), @@ -110,7 +110,7 @@ module('Acceptance | policies/acl', function (hooks) { assert .dom(SELECT.createError) .hasText(`Error 'policy' parameter not supplied or empty`, 'renders error message on save'); - find('.CodeMirror').CodeMirror.setValue(policyString); + codemirror().setValue(policyString); await click(SELECT.save); await waitUntil(() => currentURL() === `/vault/policy/acl/${encodeURIComponent(policyLower)}`); diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index ab1df0489425..c83916b07355 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -18,6 +18,7 @@ import logout from 'vault/tests/pages/logout'; import { writeSecret, writeVersionedSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { runCmd } from 'vault/tests/helpers/commands'; import { PAGE } from 'vault/tests/helpers/kv/kv-selectors'; +import codemirror from 'vault/tests/helpers/codemirror'; const deleteEngine = async function (enginePath, assert) { await logout.visit(); @@ -329,8 +330,7 @@ module('Acceptance | secrets/secret/create, read, delete', function (hooks) { await listPage.visitRoot({ backend: this.backend }); await listPage.create(); await editPage.path(secretPath).toggleJSON(); - const instance = document.querySelector('.CodeMirror').CodeMirror; - instance.setValue(content); + codemirror().setValue(content); await editPage.save(); assert.strictEqual( @@ -339,9 +339,8 @@ module('Acceptance | secrets/secret/create, read, delete', function (hooks) { 'redirects to the show page' ); assert.ok(showPage.editIsPresent, 'shows the edit button'); - const savedInstance = document.querySelector('.CodeMirror').CodeMirror; assert.strictEqual( - savedInstance.options.value, + codemirror().options.value, JSON.stringify({ bar: 'boo', foo: 'fa' }, null, 2), 'saves the content' ); diff --git a/ui/tests/acceptance/tools-test.js b/ui/tests/acceptance/tools-test.js index 152d23a10f2d..6b5bbc09d896 100644 --- a/ui/tests/acceptance/tools-test.js +++ b/ui/tests/acceptance/tools-test.js @@ -3,13 +3,24 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import { click, fillIn, find, findAll, currentURL, visit, settled, waitUntil } from '@ember/test-helpers'; +import { + click, + fillIn, + find, + findAll, + currentURL, + visit, + settled, + waitUntil, + waitFor, +} from '@ember/test-helpers'; import Pretender from 'pretender'; import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import { toolsActions } from 'vault/helpers/tools-actions'; import authPage from 'vault/tests/pages/auth'; import { capitalize } from '@ember/string'; +import codemirror from 'vault/tests/helpers/codemirror'; module('Acceptance | tools', function (hooks) { setupApplicationTest(hooks); @@ -48,8 +59,8 @@ module('Acceptance | tools', function (hooks) { assert.dom(`[data-test-sidebar-nav-link="${capitalize(action)}"]`).exists(`${action} link renders`); }); - const { CodeMirror } = await waitUntil(() => find('.CodeMirror')); - CodeMirror.setValue(DATA_TO_WRAP); + await waitFor('.CodeMirror'); + codemirror().setValue(DATA_TO_WRAP); // wrap await click('[data-test-tools-submit]'); @@ -86,16 +97,20 @@ module('Acceptance | tools', function (hooks) { await fillIn('[data-test-tools-input="wrapping-token"]', tokenStore.get()); await click('[data-test-tools-submit]'); + await waitFor('.CodeMirror'); assert.deepEqual( - JSON.parse(CodeMirror.getValue()), + JSON.parse(codemirror().getValue()), JSON.parse(DATA_TO_WRAP), 'unwrapped data equals input data' ); - const buttonDetails = await waitUntil(() => find('[data-test-button-details]')); - await click(buttonDetails); + await waitUntil(() => find('[data-test-button-details]')); + await click('[data-test-button-details]'); await click('[data-test-button-data]'); - assert.dom('.CodeMirror').exists(); - + assert.deepEqual( + JSON.parse(codemirror().getValue()), + JSON.parse(DATA_TO_WRAP), + 'data tab still has unwrapped data' + ); //random await click('[data-test-sidebar-nav-link="Random"]'); @@ -160,7 +175,7 @@ module('Acceptance | tools', function (hooks) { await click('[data-test-tools-submit]'); assert.deepEqual( - JSON.parse(findAll('.CodeMirror')[0].CodeMirror.getValue()), + JSON.parse(codemirror().getValue()), AUTH_RESPONSE.auth, 'unwrapped data equals input data' ); diff --git a/ui/tests/acceptance/transit-test.js b/ui/tests/acceptance/transit-test.js index 25b553a244c0..d6d826c88f65 100644 --- a/ui/tests/acceptance/transit-test.js +++ b/ui/tests/acceptance/transit-test.js @@ -11,6 +11,7 @@ import { v4 as uuidv4 } from 'uuid'; import { encodeString } from 'vault/utils/b64'; import authPage from 'vault/tests/pages/auth'; import { deleteEngineCmd, mountEngineCmd, runCmd } from 'vault/tests/helpers/commands'; +import codemirror from 'vault/tests/helpers/codemirror'; const SELECTORS = { secretLink: '[data-test-secret-link]', @@ -150,7 +151,7 @@ const testConvergentEncryption = async function (assert, keyName) { for (const testCase of tests) { await click('[data-test-transit-action-link="encrypt"]'); - find('#plaintext-control .CodeMirror').CodeMirror.setValue(testCase.plaintext); + codemirror('#plaintext-control').setValue(testCase.plaintext); await fillIn('[data-test-transit-input="context"]', testCase.context); if (!testCase.encodePlaintext) { @@ -160,7 +161,7 @@ const testConvergentEncryption = async function (assert, keyName) { if (testCase.encodeContext) { await click('[data-test-transit-b64-toggle="context"]'); } - assert.dom('[data-test-encrypt-modal]').doesNotExist(`${name}: is not open before encrypt`); + assert.dom('[data-test-encrypt-modal]').doesNotExist(`${keyName}: is not open before encrypt`); await click('[data-test-button-encrypt]'); if (testCase.assertAfterEncrypt) { @@ -171,14 +172,15 @@ const testConvergentEncryption = async function (assert, keyName) { const copiedCiphertext = find('[data-test-encrypted-value="ciphertext"]').innerText; await click('dialog button'); - assert.dom('dialog.hds-modal').doesNotExist(`${name}: Modal closes after background clicked`); + assert.dom('dialog.hds-modal').doesNotExist(`${keyName}: Modal closes after background clicked`); await click('[data-test-transit-action-link="decrypt"]'); if (testCase.assertBeforeDecrypt) { await settled(); testCase.assertBeforeDecrypt(keyName); } - find('#ciphertext-control .CodeMirror').CodeMirror.setValue(copiedCiphertext); + + codemirror('#ciphertext-control').setValue(copiedCiphertext); await click('[data-test-button-decrypt]'); if (testCase.assertAfterDecrypt) { @@ -188,7 +190,7 @@ const testConvergentEncryption = async function (assert, keyName) { await click('dialog button'); - assert.dom('dialog.hds-modal').doesNotExist(`${name}: Modal closes after background clicked`); + assert.dom('dialog.hds-modal').doesNotExist(`${keyName}: Modal closes after background clicked`); } }; diff --git a/ui/tests/helpers/codemirror.js b/ui/tests/helpers/codemirror.js index 247668079415..aba7e891893b 100644 --- a/ui/tests/helpers/codemirror.js +++ b/ui/tests/helpers/codemirror.js @@ -5,22 +5,22 @@ /* returns an instance of CodeMirror, see docs for callable functions https://codemirror.net/5/doc/manual.html#api_constructor +If you are targeting a specific CodeMirror instance, pass the selector of the parent element as an argument. sample use: import codemirror from 'vault/tests/helpers/codemirror'; test('it renders initial value', function (assert) { - - assert.strictEqual(codemirror.getValue(), 'some value') + // General use + assert.strictEqual(codemirror().getValue(), 'some other value') + // Specific selector + codemirror('#my-control').setValue('some value'); + assert.strictEqual(codemirror('#my-control').getValue(), 'some value') )} */ - -const invariant = (truthy, error) => { - if (!truthy) throw new Error(error); -}; - -export default function () { - const element = document.querySelector('.CodeMirror'); +export default function (parent) { + const selector = parent ? `${parent} .CodeMirror` : '.CodeMirror'; + const element = document.querySelector(selector); invariant(element, `Selector '.CodeMirror' matched no elements`); const cm = element.CodeMirror; @@ -28,3 +28,7 @@ export default function () { return cm; } + +const invariant = (truthy, error) => { + if (!truthy) throw new Error(error); +}; diff --git a/ui/tests/integration/components/console/log-json-test.js b/ui/tests/integration/components/console/log-json-test.js index d6d8944bca65..80ebc387403d 100644 --- a/ui/tests/integration/components/console/log-json-test.js +++ b/ui/tests/integration/components/console/log-json-test.js @@ -13,7 +13,6 @@ module('Integration | Component | console/log json', function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { - this.codeMirror = this.owner.lookup('service:code-mirror'); // TODO: Fix JSONEditor/CodeMirror setRunOptions({ rules: { @@ -30,7 +29,7 @@ module('Integration | Component | console/log json', function (hooks) { this.set('content', objectContent); - await render(hbs`{{console/log-json content=this.content}}`); + await render(hbs``); const instance = find('[data-test-component=code-mirror-modifier]').innerText; assert.strictEqual(instance, expectedText); }); diff --git a/ui/tests/integration/components/secret-edit-test.js b/ui/tests/integration/components/secret-edit-test.js index 6cef7a95d263..2afe24d1ff81 100644 --- a/ui/tests/integration/components/secret-edit-test.js +++ b/ui/tests/integration/components/secret-edit-test.js @@ -11,6 +11,7 @@ import { run } from '@ember/runloop'; import Service from '@ember/service'; import hbs from 'htmlbars-inline-precompile'; import { setRunOptions } from 'ember-a11y-testing/test-support'; +import codemirror from 'vault/tests/helpers/codemirror'; let capabilities; const storeService = Service.extend({ @@ -23,7 +24,6 @@ module('Integration | Component | secret edit', function (hooks) { hooks.beforeEach(function () { capabilities = null; - this.codeMirror = this.owner.lookup('service:code-mirror'); this.set('key', { id: 'Foobar' }); run(() => { this.owner.unregister('service:store'); @@ -47,7 +47,7 @@ module('Integration | Component | secret edit', function (hooks) { }, }); - await render(hbs`{{secret-edit mode=this.mode model=this.model key=this.key }}`); + await render(hbs``); assert.dom('[data-test-toggle-input="json"]').isDisabled(); }); @@ -61,7 +61,7 @@ module('Integration | Component | secret edit', function (hooks) { }, }); - await render(hbs`{{secret-edit mode=this.mode model=this.model key=this.key }}`); + await render(hbs``); assert.dom('[data-test-toggle-input="json"]').isNotDisabled(); }); @@ -71,10 +71,11 @@ module('Integration | Component | secret edit', function (hooks) { secretData: null, }); - await render(hbs`{{secret-edit mode=this.mode model=this.model preferAdvancedEdit=true key=this.key }}`); + await render( + hbs`` + ); - const instance = document.querySelector('.CodeMirror').CodeMirror; - instance.setValue(JSON.stringify([{ foo: 'bar' }])); + codemirror().setValue(JSON.stringify([{ foo: 'bar' }])); await settled(); assert .dom('[data-test-message-error]') @@ -91,7 +92,7 @@ module('Integration | Component | secret edit', function (hooks) { float: '1.234', }, }); - await render(hbs``); + await render(hbs``); assert.dom('[data-test-secret-save]').isNotDisabled(); }); @@ -109,10 +110,11 @@ module('Integration | Component | secret edit', function (hooks) { canReadSecretData: true, }); - await render(hbs`{{secret-edit mode=this.mode model=this.model preferAdvancedEdit=true key=this.key }}`); + await render( + hbs`` + ); - const instance = document.querySelector('.CodeMirror').CodeMirror; - instance.setValue(JSON.stringify([{ foo: 'bar' }])); + codemirror().setValue(JSON.stringify([{ foo: 'bar' }])); await settled(); assert .dom('[data-test-message-error]') diff --git a/ui/tests/integration/components/transit-key-actions-test.js b/ui/tests/integration/components/transit-key-actions-test.js index b516a57f81c4..0ffe376f0ab5 100644 --- a/ui/tests/integration/components/transit-key-actions-test.js +++ b/ui/tests/integration/components/transit-key-actions-test.js @@ -8,11 +8,12 @@ import { resolve } from 'rsvp'; import Service from '@ember/service'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, click, find, findAll, fillIn, blur, triggerEvent } from '@ember/test-helpers'; +import { render, click, find, fillIn, blur, triggerEvent } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { encodeString } from 'vault/utils/b64'; import waitForError from 'vault/tests/helpers/wait-for-error'; import { setRunOptions } from 'ember-a11y-testing/test-support'; +import codemirror from 'vault/tests/helpers/codemirror'; const storeStub = Service.extend({ callArgs: null, @@ -111,7 +112,7 @@ module('Integration | Component | transit key actions', function (hooks) { await render(hbs` `); - find('#plaintext-control .CodeMirror').CodeMirror.setValue('plaintext'); + codemirror('#plaintext-control').setValue('plaintext'); await click('button[type="submit"]'); assert.deepEqual( this.storeService.callArgs, @@ -132,7 +133,7 @@ module('Integration | Component | transit key actions', function (hooks) { await click('dialog button'); // Encrypt again, with pre-encoded value and checkbox selected const preEncodedValue = encodeString('plaintext'); - find('#plaintext-control .CodeMirror').CodeMirror.setValue(preEncodedValue); + codemirror('#plaintext-control').setValue(preEncodedValue); await click('input[data-test-transit-input="encodedBase64"]'); await click('button[type="submit"]'); @@ -161,7 +162,7 @@ module('Integration | Component | transit key actions', function (hooks) { await render(hbs` `); - findAll('.CodeMirror')[0].CodeMirror.setValue('plaintext'); + codemirror().setValue('plaintext'); assert.dom('#key_version').exists({ count: 1 }, 'it renders the key version selector'); await triggerEvent('#key_version', 'change'); @@ -190,8 +191,7 @@ module('Integration | Component | transit key actions', function (hooks) { await render(hbs` `); - // await fillIn('#plaintext', 'plaintext'); - find('#plaintext-control .CodeMirror').CodeMirror.setValue('plaintext'); + codemirror('#plaintext-control').setValue('plaintext'); assert.dom('#key_version').doesNotExist('it does not render the selector when there is only one key'); }); @@ -202,11 +202,7 @@ module('Integration | Component | transit key actions', function (hooks) { this.set('storeService.keyActionReturnVal', { plaintext }); this.set('selectedAction', 'decrypt'); - assert.strictEqual( - find('#ciphertext-control .CodeMirror').CodeMirror.getValue(), - '', - 'does not prefill ciphertext value' - ); + assert.strictEqual(codemirror('#ciphertext-control').getValue(), '', 'does not prefill ciphertext value'); }); const setupExport = async function () { From 2cc755d9f81b9387fdd8bc81e5213dfe180ae831 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 14:23:56 -0500 Subject: [PATCH 07/32] move secret-edit-toolbar helper --- ui/tests/acceptance/secrets/backend/cubbyhole/secret-test.js | 2 +- ui/tests/helpers/{ => components}/secret-edit-toolbar.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename ui/tests/helpers/{ => components}/secret-edit-toolbar.js (85%) diff --git a/ui/tests/acceptance/secrets/backend/cubbyhole/secret-test.js b/ui/tests/acceptance/secrets/backend/cubbyhole/secret-test.js index 860979d6f19c..7e91fe30c770 100644 --- a/ui/tests/acceptance/secrets/backend/cubbyhole/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/cubbyhole/secret-test.js @@ -13,7 +13,7 @@ import editPage from 'vault/tests/pages/secrets/backend/kv/edit-secret'; import showPage from 'vault/tests/pages/secrets/backend/kv/show'; import listPage from 'vault/tests/pages/secrets/backend/list'; import authPage from 'vault/tests/pages/auth'; -import assertSecretWrap from 'vault/tests/helpers/secret-edit-toolbar'; +import { assertSecretWrap } from 'vault/tests/helpers/components/secret-edit-toolbar'; module('Acceptance | secrets/cubbyhole/create', function (hooks) { setupApplicationTest(hooks); diff --git a/ui/tests/helpers/secret-edit-toolbar.js b/ui/tests/helpers/components/secret-edit-toolbar.js similarity index 85% rename from ui/tests/helpers/secret-edit-toolbar.js rename to ui/tests/helpers/components/secret-edit-toolbar.js index bb0797c28509..2c677dcf7c96 100644 --- a/ui/tests/helpers/secret-edit-toolbar.js +++ b/ui/tests/helpers/components/secret-edit-toolbar.js @@ -8,7 +8,7 @@ const SELECTORS = { dropdown: '[data-test-copy-menu-trigger]', wrapButton: '[data-test-wrap-button]', }; -export default async function assertSecretWrap(assert, server, path) { +export async function assertSecretWrap(assert, server, path) { server.get(path, () => { assert.ok(true, `request made to ${path} when wrapping secret`); }); From 0e0e40c35903da55ad6fbac058009a8a2421650d Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 14:34:27 -0500 Subject: [PATCH 08/32] remove helper used only once --- ui/tests/helpers/mirage-to-models.js | 17 ----------------- .../components/secret-list-header-test.js | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 ui/tests/helpers/mirage-to-models.js diff --git a/ui/tests/helpers/mirage-to-models.js b/ui/tests/helpers/mirage-to-models.js deleted file mode 100644 index f754fa240b47..000000000000 --- a/ui/tests/helpers/mirage-to-models.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { getContext } from '@ember/test-helpers'; - -export default (data) => { - const context = getContext(); - const store = context.owner.lookup('service:store'); - const modelName = Array.isArray(data) ? data[0].modelName : data.modelName; - const json = context.server.serializerOrRegistry.serialize(data); - store.push(json); - return Array.isArray(data) - ? data.map(({ id }) => store.peekRecord(modelName, id)) - : store.peekRecord(modelName, data.id); -}; diff --git a/ui/tests/integration/components/secret-list-header-test.js b/ui/tests/integration/components/secret-list-header-test.js index da4340a3b051..b78fd2890b52 100644 --- a/ui/tests/integration/components/secret-list-header-test.js +++ b/ui/tests/integration/components/secret-list-header-test.js @@ -5,11 +5,21 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; +import { getContext, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { supportedSecretBackends } from 'vault/helpers/supported-secret-backends'; import { setupMirage } from 'ember-cli-mirage/test-support'; -import mirageToModels from 'vault/tests/helpers/mirage-to-models'; + +const mirageToModels = (data) => { + const context = getContext(); + const store = context.owner.lookup('service:store'); + const modelName = Array.isArray(data) ? data[0].modelName : data.modelName; + const json = context.server.serializerOrRegistry.serialize(data); + store.push(json); + return Array.isArray(data) + ? data.map(({ id }) => store.peekRecord(modelName, id)) + : store.peekRecord(modelName, data.id); +}; module('Integration | Component | secret-list-header', function (hooks) { setupRenderingTest(hooks); From 8dfbe458b040d806d68b6c6a1772dab19875158c Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 18:08:28 -0500 Subject: [PATCH 09/32] replace noop-all-api-requests with mirage --- ui/tests/acceptance/auth-test.js | 149 +++++++++++------- .../secrets/backend/generic/secret-test.js | 15 +- .../settings/auth/configure/section-test.js | 28 ++-- ui/tests/helpers/noop-all-api-requests.js | 23 --- ui/tests/unit/adapters/aws-credential-test.js | 81 +++++----- .../adapters/identity/entity-alias-test.js | 33 ++-- .../unit/adapters/identity/entity-test.js | 33 ++-- .../adapters/identity/group-alias-test.js | 33 ++-- ui/tests/unit/adapters/identity/group-test.js | 33 ++-- ui/tests/unit/adapters/secret-engine-test.js | 75 ++++----- 10 files changed, 230 insertions(+), 273 deletions(-) delete mode 100644 ui/tests/helpers/noop-all-api-requests.js diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index ab48fe5d339a..edd0ca9368d8 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -3,40 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -/* eslint qunit/no-conditional-assertions: "warn" */ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; -import sinon from 'sinon'; import { click, currentURL, visit, waitUntil, find } from '@ember/test-helpers'; import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends'; import authForm from '../pages/components/auth-form'; import jwtForm from '../pages/components/auth-jwt'; import { create } from 'ember-cli-page-object'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; const component = create(authForm); const jwtComponent = create(jwtForm); module('Acceptance | auth', function (hooks) { setupApplicationTest(hooks); - - hooks.beforeEach(function () { - this.clock = sinon.useFakeTimers({ - now: Date.now(), - shouldAdvanceTime: true, - }); - this.server = apiStub({ usePassthrough: true }); - }); - - hooks.afterEach(function () { - this.clock.restore(); - this.server.shutdown(); - }); + setupMirage(hooks); test('auth query params', async function (assert) { const backends = supportedAuthBackends(); assert.expect(backends.length + 1); - await visit('/vault/auth'); + await visit('/vault/auth?with=token'); assert.strictEqual(currentURL(), '/vault/auth?with=token'); for (const backend of backends.reverse()) { await component.selectMethod(backend.type); @@ -55,53 +41,102 @@ module('Acceptance | auth', function (hooks) { assert.strictEqual(component.tokenValue, '', 'it clears the token value when toggling methods'); }); - test('it sends the right attributes when authenticating', async function (assert) { - assert.expect(8); - const backends = supportedAuthBackends(); - await visit('/vault/auth'); - for (const backend of backends.reverse()) { - await component.selectMethod(backend.type); - if (backend.type === 'github') { - await component.token('token'); - } - if (backend.type === 'jwt' || backend.type === 'oidc') { - await jwtComponent.role('test'); - } - await component.login(); - const lastRequest = this.server.passthroughRequests[this.server.passthroughRequests.length - 1]; - const body = JSON.parse(lastRequest.requestBody); + module('it sends the right attributes when authenticating', function (hooks) { + hooks.beforeEach(function () { + this.assertReq = () => {}; + this.server.get('/auth/token/lookup-self', (schema, req) => { + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/github/login', (schema, req) => { + // This one is for github only + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/:mount/oidc/auth_url', (schema, req) => { + // For JWT and OIDC + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/:mount/login/:username', (schema, req) => { + this.assertReq(req); + req.passthrough(); + }); + this.expected = { + token: { + included: 'X-Vault-Token', + url: '/v1/auth/token/lookup-self', + }, + userpass: { + included: 'password', + url: '/v1/auth/userpass/login/null', + }, + ldap: { + included: 'password', + url: '/v1/auth/ldap/login/null', + }, + okta: { + included: 'password', + url: '/v1/auth/okta/login/null', + }, + jwt: { + included: 'role', + url: '/v1/auth/jwt/oidc/auth_url', + }, + oidc: { + included: 'role', + url: '/v1/auth/oidc/oidc/auth_url', + }, + radius: { + included: 'password', + url: '/v1/auth/radius/login/null', + }, + github: { + included: 'token', + url: '/v1/auth/github/login', + }, + }; + }); - let keys; - let included; - if (backend.type === 'token') { - keys = lastRequest.requestHeaders; - included = 'x-vault-token'; - } else if (backend.type === 'github') { - keys = body; - included = 'token'; - } else if (backend.type === 'jwt' || backend.type === 'oidc') { - const authReq = this.server.passthroughRequests[this.server.passthroughRequests.length - 2]; - keys = JSON.parse(authReq.requestBody); - included = 'role'; - } else { - keys = body; - included = 'password'; - } - assert.ok(Object.keys(keys).includes(included), `${backend.type} includes ${included}`); + for (const backend of supportedAuthBackends().reverse()) { + test(`for ${backend.type}`, async function (assert) { + const { type } = backend; + const isOidc = ['jwt', 'oidc'].includes(type); + // OIDC types make 3 requests, each time the role changes + assert.expect(isOidc ? 6 : 2); + this.assertReq = (req) => { + const body = type === 'token' ? req.requestHeaders : JSON.parse(req.requestBody); + const { included, url } = this.expected[type]; + assert.ok(Object.keys(body).includes(included), `${type} includes ${included}`); + assert.strictEqual(req.url, url, `${type} calls the correct URL`); + }; + await visit('/vault/auth'); + await component.selectMethod(type); + if (type === 'github') { + await component.token('token'); + } + if (isOidc) { + await jwtComponent.role('test'); + } + await component.login(); + }); } }); test('it shows the push notification warning after submit', async function (assert) { assert.expect(1); - this.server.get('/v1/auth/token/lookup-self', async () => { - assert.ok( - await waitUntil(() => find('[data-test-auth-message="push"]')), - 'shows push notification message' - ); - return [204, { 'Content-Type': 'application/json' }, JSON.stringify({})]; - }); - + this.server.get( + '/auth/token/lookup-self', + async () => { + assert.ok( + await waitUntil(() => find('[data-test-auth-message="push"]')), + 'shows push notification message' + ); + return {}; + }, + { timing: 1000 } + ); await visit('/vault/auth'); await component.selectMethod('token'); await click('[data-test-auth-submit]'); diff --git a/ui/tests/acceptance/secrets/backend/generic/secret-test.js b/ui/tests/acceptance/secrets/backend/generic/secret-test.js index ec6a7cdbf300..70f3b19d394e 100644 --- a/ui/tests/acceptance/secrets/backend/generic/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/generic/secret-test.js @@ -17,8 +17,7 @@ import { writeSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { PAGE } from 'vault/tests/helpers/kv/kv-selectors'; import { create } from 'ember-cli-page-object'; - -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { deleteEngineCmd, runCmd } from 'vault/tests/helpers/commands'; const cli = create(consolePanel); @@ -27,14 +26,9 @@ module('Acceptance | secrets/generic/create', function (hooks) { hooks.beforeEach(function () { this.uid = uuidv4(); - this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); - hooks.afterEach(function () { - this.server.shutdown(); - }); - test('it creates and can view a secret with the generic backend', async function (assert) { const path = `generic-${this.uid}`; const kvPath = `generic-kv-${this.uid}`; @@ -55,6 +49,10 @@ module('Acceptance | secrets/generic/create', function (hooks) { 'redirects to the show page' ); assert.ok(showPage.editIsPresent, 'shows the edit button'); + + // Clean up + await runCmd(deleteEngineCmd(path)); + await runCmd(deleteEngineCmd(kvPath)); }); test('upgrading generic to version 2 lists all existing secrets, and CRUD continues to work', async function (assert) { @@ -78,5 +76,8 @@ module('Acceptance | secrets/generic/create', function (hooks) { assert.dom(PAGE.list.item(secret.path)).exists('lists both records'); }); assert.dom(PAGE.list.item()).exists({ count: 2 }, 'lists only the two secrets'); + + // Clean up + await runCmd(deleteEngineCmd(path)); }); }); diff --git a/ui/tests/acceptance/settings/auth/configure/section-test.js b/ui/tests/acceptance/settings/auth/configure/section-test.js index 2db3fde772b4..0d4c791f3ab3 100644 --- a/ui/tests/acceptance/settings/auth/configure/section-test.js +++ b/ui/tests/acceptance/settings/auth/configure/section-test.js @@ -5,6 +5,7 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; import { create } from 'ember-cli-page-object'; import { fillIn } from '@ember/test-helpers'; import { v4 as uuidv4 } from 'uuid'; @@ -12,7 +13,6 @@ import { v4 as uuidv4 } from 'uuid'; import enablePage from 'vault/tests/pages/settings/auth/enable'; import page from 'vault/tests/pages/settings/auth/configure/section'; import indexPage from 'vault/tests/pages/settings/auth/configure/index'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; import consolePanel from 'vault/tests/pages/components/console/ui-panel'; import authPage from 'vault/tests/pages/auth'; @@ -20,18 +20,24 @@ const cli = create(consolePanel); module('Acceptance | settings/auth/configure/section', function (hooks) { setupApplicationTest(hooks); + setupMirage(hooks); hooks.beforeEach(function () { this.uid = uuidv4(); - this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); - hooks.afterEach(function () { - this.server.shutdown(); - }); - test('it can save options', async function (assert) { + assert.expect(6); + this.server.post(`/sys/mounts/auth/:path/tune`, function (schema, request) { + const body = JSON.parse(request.requestBody); + const keys = Object.keys(body); + assert.strictEqual(body.token_type, 'batch', 'passes new token type'); + assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); + assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); + assert.ok(keys.includes('description'), 'passes updated description on tune'); + request.passthrough(); + }); const path = `approle-save-${this.uid}`; const type = 'approle'; const section = 'options'; @@ -48,16 +54,6 @@ module('Acceptance | settings/auth/configure/section', function (hooks) { `The configuration was saved successfully.`, 'success flash shows' ); - const tuneRequest = this.server.passthroughRequests.filterBy( - 'url', - `/v1/sys/mounts/auth/${path}/tune` - )[0]; - const keys = Object.keys(JSON.parse(tuneRequest.requestBody)); - const token_type = JSON.parse(tuneRequest.requestBody).token_type; - assert.strictEqual(token_type, 'batch', 'passes new token type'); - assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); - assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); - assert.ok(keys.includes('description'), 'passes updated description on tune'); }); for (const type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) { diff --git a/ui/tests/helpers/noop-all-api-requests.js b/ui/tests/helpers/noop-all-api-requests.js deleted file mode 100644 index 88e44034083f..000000000000 --- a/ui/tests/helpers/noop-all-api-requests.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Pretender from 'pretender'; -import { noopStub } from './stubs'; - -/** - * DEPRECATED prefer to use `setupMirage` along with stubs in vault/tests/helpers/stubs - */ -export default function (options = { usePassthrough: false }) { - return new Pretender(function () { - let fn = noopStub(); - if (options.usePassthrough) { - fn = this.passthrough; - } - this.post('/v1/**', fn); - this.put('/v1/**', fn); - this.get('/v1/**', fn); - this.delete('/v1/**', fn || noopStub(204)); - }); -} diff --git a/ui/tests/unit/adapters/aws-credential-test.js b/ui/tests/unit/adapters/aws-credential-test.js index 5f804fdedf0f..527338900cdc 100644 --- a/ui/tests/unit/adapters/aws-credential-test.js +++ b/ui/tests/unit/adapters/aws-credential-test.js @@ -5,41 +5,46 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; +const storeStub = { + pushPayload() {}, + serializerFor() { + return { + serializeIntoHash() {}, + }; + }, +}; + +const makeSnapshot = (obj) => { + obj.role = { + backend: 'aws', + name: 'foo', + }; + obj.attr = (attr) => obj[attr]; + return obj; +}; + +const type = { + modelName: 'aws-credential', +}; module('Unit | Adapter | aws credential', function (hooks) { setupTest(hooks); + setupMirage(hooks); hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); + this.getAssertion = () => {}; + this.postAssertion = () => {}; + this.server.get('/aws/creds/foo', (schema, req) => { + this.getAssertion(req); + return {}; + }); + this.server.post('/aws/creds/foo', (schema, req) => { + this.postAssertion(req); + return {}; + }); }); - const storeStub = { - pushPayload() {}, - serializerFor() { - return { - serializeIntoHash() {}, - }; - }, - }; - - const makeSnapshot = (obj) => { - obj.role = { - backend: 'aws', - name: 'foo', - }; - obj.attr = (attr) => obj[attr]; - return obj; - }; - - const type = { - modelName: 'aws-credential', - }; - const cases = [ ['iam_user type', [storeStub, type, makeSnapshot({ credentialType: 'iam_user', ttl: '3h' })], 'GET'], [ @@ -82,19 +87,19 @@ module('Unit | Adapter | aws credential', function (hooks) { { ttl: '3h', role_arn: 'arn' }, ], ]; - cases.forEach(([description, args, expectedMethod, expectedRequestBody]) => { + + cases.forEach(([description, args, method, expectedRequestBody]) => { test(`aws-credential: ${description}`, function (assert) { - assert.expect(3); + assert.expect(2); + const assertionName = method === 'GET' ? 'getAssertion' : 'postAssertion'; + this.set(assertionName, (req) => { + assert.strictEqual(req.method, method, `query calls the correct url with method ${method}`); + const body = JSON.parse(req.requestBody); + const expected = expectedRequestBody ? expectedRequestBody : null; + assert.deepEqual(body, expected); + }); const adapter = this.owner.lookup('adapter:aws-credential'); adapter.createRecord(...args); - const { method, url, requestBody } = this.server.handledRequests[0]; - assert.strictEqual(url, '/v1/aws/creds/foo', `calls the correct url`); - assert.strictEqual( - method, - expectedMethod, - `${description} uses the correct http verb: ${expectedMethod}` - ); - assert.strictEqual(requestBody, expectedRequestBody ? JSON.stringify(expectedRequestBody) : null); }); }); }); diff --git a/ui/tests/unit/adapters/identity/entity-alias-test.js b/ui/tests/unit/adapters/identity/entity-alias-test.js index e6605140199a..f51b3fd6d53c 100644 --- a/ui/tests/unit/adapters/identity/entity-alias-test.js +++ b/ui/tests/unit/adapters/identity/entity-alias-test.js @@ -6,37 +6,28 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; import testCases from './_test-cases'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; module('Unit | Adapter | identity/entity-alias', function (hooks) { setupTest(hooks); - - hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); - }); + setupMirage(hooks); const cases = testCases('identity/entity-alias'); cases.forEach((testCase) => { test(`entity-alias#${testCase.adapterMethod}`, function (assert) { - assert.expect(2); + assert.expect(3); + const method = testCase.method.toLowerCase(); + const url = testCase.url.replace('/v1', '').split('?')[0]; + const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; + this.server[method](url, (schema, req) => { + assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.strictEqual(req.method, testCase.method, `uses the correct http verb: ${testCase.method}`); + assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); + return {}; + }); const adapter = this.owner.lookup('adapter:identity/entity-alias'); adapter[testCase.adapterMethod](...testCase.args); - const { url, method } = this.server.handledRequests[0]; - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); - assert.strictEqual( - method, - testCase.method, - `${testCase.adapterMethod} uses the correct http verb: ${testCase.method}` - ); }); }); }); diff --git a/ui/tests/unit/adapters/identity/entity-test.js b/ui/tests/unit/adapters/identity/entity-test.js index a6211ec8bda0..dcfdfa7eb21e 100644 --- a/ui/tests/unit/adapters/identity/entity-test.js +++ b/ui/tests/unit/adapters/identity/entity-test.js @@ -6,37 +6,28 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; import testCases from './_test-cases'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; module('Unit | Adapter | identity/entity', function (hooks) { setupTest(hooks); - - hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); - }); + setupMirage(hooks); const cases = testCases('identit/entity'); cases.forEach((testCase) => { test(`entity#${testCase.adapterMethod}`, function (assert) { - assert.expect(2); + assert.expect(3); + const method = testCase.method.toLowerCase(); + const url = testCase.url.replace('/v1', '').split('?')[0]; + const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; + this.server[method](url, (schema, req) => { + assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); + assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); + return {}; + }); const adapter = this.owner.lookup('adapter:identity/entity'); adapter[testCase.adapterMethod](...testCase.args); - const { url, method } = this.server.handledRequests[0]; - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); - assert.strictEqual( - method, - testCase.method, - `${testCase.adapterMethod} uses the correct http verb: ${testCase.method}` - ); }); }); }); diff --git a/ui/tests/unit/adapters/identity/group-alias-test.js b/ui/tests/unit/adapters/identity/group-alias-test.js index a6d92478f55b..843735fee9de 100644 --- a/ui/tests/unit/adapters/identity/group-alias-test.js +++ b/ui/tests/unit/adapters/identity/group-alias-test.js @@ -6,37 +6,28 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; import testCases from './_test-cases'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; module('Unit | Adapter | identity/group-alias', function (hooks) { setupTest(hooks); - - hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); - }); + setupMirage(hooks); const cases = testCases('identity/group-alias'); cases.forEach((testCase) => { test(`group-alias#${testCase.adapterMethod}`, function (assert) { - assert.expect(2); + assert.expect(3); + const method = testCase.method.toLowerCase(); + const url = testCase.url.replace('/v1', '').split('?')[0]; + const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; + this.server[method](url, (schema, req) => { + assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); + assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); + return {}; + }); const adapter = this.owner.lookup('adapter:identity/group-alias'); adapter[testCase.adapterMethod](...testCase.args); - const { url, method } = this.server.handledRequests[0]; - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); - assert.strictEqual( - method, - testCase.method, - `${testCase.adapterMethod} uses the correct http verb: ${testCase.method}` - ); }); }); }); diff --git a/ui/tests/unit/adapters/identity/group-test.js b/ui/tests/unit/adapters/identity/group-test.js index b314cb3b831d..3ec14ed22ca0 100644 --- a/ui/tests/unit/adapters/identity/group-test.js +++ b/ui/tests/unit/adapters/identity/group-test.js @@ -6,37 +6,28 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; import testCases from './_test-cases'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; module('Unit | Adapter | identity/group', function (hooks) { setupTest(hooks); - - hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); - }); + setupMirage(hooks); const cases = testCases('identit/entity'); cases.forEach((testCase) => { test(`group#${testCase.adapterMethod}`, function (assert) { - assert.expect(2); + assert.expect(3); + const method = testCase.method.toLowerCase(); + const url = testCase.url.replace('/v1', '').split('?')[0]; + const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; + this.server[method](url, (schema, req) => { + assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); + assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); + return {}; + }); const adapter = this.owner.lookup('adapter:identity/group'); adapter[testCase.adapterMethod](...testCase.args); - const { url, method } = this.server.handledRequests[0]; - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); - assert.strictEqual( - method, - testCase.method, - `${testCase.adapterMethod} uses the correct http verb: ${testCase.method}` - ); }); }); }); diff --git a/ui/tests/unit/adapters/secret-engine-test.js b/ui/tests/unit/adapters/secret-engine-test.js index 38288d5847c4..ddbcbc81cbde 100644 --- a/ui/tests/unit/adapters/secret-engine-test.js +++ b/ui/tests/unit/adapters/secret-engine-test.js @@ -5,18 +5,11 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; module('Unit | Adapter | secret engine', function (hooks) { setupTest(hooks); - - hooks.beforeEach(function () { - this.server = apiStub(); - }); - - hooks.afterEach(function () { - this.server.shutdown(); - }); + setupMirage(hooks); const storeStub = { serializerFor() { @@ -29,46 +22,32 @@ module('Unit | Adapter | secret engine', function (hooks) { modelName: 'secret-engine', }; - const cases = [ - { - description: 'Empty query', - adapterMethod: 'query', - args: [storeStub, type, {}], - url: '/v1/sys/internal/ui/mounts', - method: 'GET', - }, - { - description: 'Query with a path', - adapterMethod: 'query', - args: [storeStub, type, { path: 'foo' }], - url: '/v1/sys/internal/ui/mounts/foo', - method: 'GET', - }, + test('Empty query', function (assert) { + assert.expect(1); + this.server.get('/sys/internal/ui/mounts', () => { + assert.ok('query calls the correct url'); + return {}; + }); + const adapter = this.owner.lookup('adapter:secret-engine'); + adapter['query'](storeStub, type, {}); + }); + test('Query with a path', function (assert) { + assert.expect(1); + this.server.get('/sys/internal/ui/mounts/foo', () => { + assert.ok('query calls the correct url'); + return {}; + }); + const adapter = this.owner.lookup('adapter:secret-engine'); + adapter['query'](storeStub, type, { path: 'foo' }); + }); - { - description: 'Query with nested path', - adapterMethod: 'query', - args: [storeStub, type, { path: 'foo/bar/baz' }], - url: '/v1/sys/internal/ui/mounts/foo/bar/baz', - method: 'GET', - }, - ]; - cases.forEach((testCase) => { - test(`secret-engine: ${testCase.description}`, function (assert) { - assert.expect(2); - const adapter = this.owner.lookup('adapter:secret-engine'); - adapter[testCase.adapterMethod](...testCase.args); - const { url, method } = this.server.handledRequests[0]; - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); - assert.strictEqual( - method, - testCase.method, - `${testCase.adapterMethod} uses the correct http verb: ${testCase.method}` - ); + test('Query with nested path', function (assert) { + assert.expect(1); + this.server.get('/sys/internal/ui/mounts/foo/bar/baz', () => { + assert.ok('query calls the correct url'); + return {}; }); + const adapter = this.owner.lookup('adapter:secret-engine'); + adapter['query'](storeStub, type, { path: 'foo/bar/baz' }); }); }); From 4607bd125236c59bc1d476603ff9bc73a9a5eadf Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 18:10:35 -0500 Subject: [PATCH 10/32] move policy generators into their respective folders --- ui/tests/acceptance/pki/pki-engine-workflow-test.js | 2 +- .../acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js | 2 +- .../acceptance/secrets/backend/kv/kv-v2-workflow-delete-test.js | 2 +- .../secrets/backend/kv/kv-v2-workflow-edge-cases-test.js | 2 +- .../secrets/backend/kv/kv-v2-workflow-navigation-test.js | 2 +- .../backend/kv/kv-v2-workflow-version-history-paths-test.js | 2 +- .../helpers/{policy-generator/kv.js => kv/policy-generator.js} | 0 .../{policy-generator/pki.js => pki/policy-generator.js} | 0 8 files changed, 6 insertions(+), 6 deletions(-) rename ui/tests/helpers/{policy-generator/kv.js => kv/policy-generator.js} (100%) rename ui/tests/helpers/{policy-generator/pki.js => pki/policy-generator.js} (100%) diff --git a/ui/tests/acceptance/pki/pki-engine-workflow-test.js b/ui/tests/acceptance/pki/pki-engine-workflow-test.js index 395bf41c19a4..eb3fb94b7621 100644 --- a/ui/tests/acceptance/pki/pki-engine-workflow-test.js +++ b/ui/tests/acceptance/pki/pki-engine-workflow-test.js @@ -12,7 +12,7 @@ import logout from 'vault/tests/pages/logout'; import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; import { click, currentURL, fillIn, find, isSettled, visit } from '@ember/test-helpers'; import { SELECTORS } from 'vault/tests/helpers/pki/workflow'; -import { adminPolicy, readerPolicy, updatePolicy } from 'vault/tests/helpers/policy-generator/pki'; +import { adminPolicy, readerPolicy, updatePolicy } from 'vault/tests/helpers/pki/policy-generator'; import { clearRecords } from 'vault/tests/helpers/pki/pki-run-commands'; import { runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands'; import { unsupportedPem } from 'vault/tests/helpers/pki/values'; diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js index fc121a888c2f..1b84ce0bce81 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js @@ -10,7 +10,7 @@ import { click, currentURL, fillIn, typeIn, visit } from '@ember/test-helpers'; import { setupApplicationTest } from 'vault/tests/helpers'; import authPage from 'vault/tests/pages/auth'; import { deleteEngineCmd, mountEngineCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands'; -import { personas } from 'vault/tests/helpers/policy-generator/kv'; +import { personas } from 'vault/tests/helpers/kv/policy-generator'; import { clearRecords, writeVersionedSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { FORM, PAGE } from 'vault/tests/helpers/kv/kv-selectors'; import { grantAccessForWrite, setupControlGroup } from 'vault/tests/helpers/control-groups'; diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-delete-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-delete-test.js index 6a5f5be9c982..d026dc2756ae 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-delete-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-delete-test.js @@ -8,7 +8,7 @@ import { v4 as uuidv4 } from 'uuid'; import { setupApplicationTest } from 'vault/tests/helpers'; import authPage from 'vault/tests/pages/auth'; import { deleteEngineCmd, mountEngineCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands'; -import { personas } from 'vault/tests/helpers/policy-generator/kv'; +import { personas } from 'vault/tests/helpers/kv/policy-generator'; import { clearRecords, deleteLatestCmd, diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-edge-cases-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-edge-cases-test.js index bf94b8018838..7a17ae8ae732 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-edge-cases-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-edge-cases-test.js @@ -21,7 +21,7 @@ import { destroyVersionsPolicy, metadataListPolicy, metadataPolicy, -} from 'vault/tests/helpers/policy-generator/kv'; +} from 'vault/tests/helpers/kv/policy-generator'; import { clearRecords, writeSecret, writeVersionedSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { FORM, PAGE } from 'vault/tests/helpers/kv/kv-selectors'; import codemirror from 'vault/tests/helpers/codemirror'; diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-navigation-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-navigation-test.js index 015683faeca0..05c5be873432 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-navigation-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-navigation-test.js @@ -16,7 +16,7 @@ import { createTokenCmd, tokenWithPolicyCmd, } from 'vault/tests/helpers/commands'; -import { personas } from 'vault/tests/helpers/policy-generator/kv'; +import { personas } from 'vault/tests/helpers/kv/policy-generator'; import { addSecretMetadataCmd, clearRecords, diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-version-history-paths-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-version-history-paths-test.js index 82d0461ed64d..391dcd79194d 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-version-history-paths-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-version-history-paths-test.js @@ -8,7 +8,7 @@ import { v4 as uuidv4 } from 'uuid'; import { setupApplicationTest } from 'vault/tests/helpers'; import authPage from 'vault/tests/pages/auth'; import { deleteEngineCmd, mountEngineCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands'; -import { personas } from 'vault/tests/helpers/policy-generator/kv'; +import { personas } from 'vault/tests/helpers/kv/policy-generator'; import { clearRecords, deleteVersionCmd, diff --git a/ui/tests/helpers/policy-generator/kv.js b/ui/tests/helpers/kv/policy-generator.js similarity index 100% rename from ui/tests/helpers/policy-generator/kv.js rename to ui/tests/helpers/kv/policy-generator.js diff --git a/ui/tests/helpers/policy-generator/pki.js b/ui/tests/helpers/pki/policy-generator.js similarity index 100% rename from ui/tests/helpers/policy-generator/pki.js rename to ui/tests/helpers/pki/policy-generator.js From 41483007de7439c64c6bd8b991043585f8fa20a4 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 18:12:38 -0500 Subject: [PATCH 11/32] Move LDAP helpers --- ui/tests/acceptance/secrets/backend/ldap/libraries-test.js | 2 +- ui/tests/acceptance/secrets/backend/ldap/overview-test.js | 2 +- ui/tests/acceptance/secrets/backend/ldap/roles-test.js | 2 +- ui/tests/helpers/{ldap.js => ldap/ldap-helpers.js} | 0 ui/tests/integration/components/ldap/page/configuration-test.js | 2 +- ui/tests/integration/components/ldap/page/configure-test.js | 2 +- ui/tests/integration/components/ldap/page/libraries-test.js | 2 +- ui/tests/integration/components/ldap/page/overview-test.js | 2 +- ui/tests/integration/components/ldap/page/roles-test.js | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename ui/tests/helpers/{ldap.js => ldap/ldap-helpers.js} (100%) diff --git a/ui/tests/acceptance/secrets/backend/ldap/libraries-test.js b/ui/tests/acceptance/secrets/backend/ldap/libraries-test.js index d8bd65b0094c..dd3d0e0725a6 100644 --- a/ui/tests/acceptance/secrets/backend/ldap/libraries-test.js +++ b/ui/tests/acceptance/secrets/backend/ldap/libraries-test.js @@ -10,7 +10,7 @@ import ldapMirageScenario from 'vault/mirage/scenarios/ldap'; import ldapHandlers from 'vault/mirage/handlers/ldap'; import authPage from 'vault/tests/pages/auth'; import { click } from '@ember/test-helpers'; -import { isURL, visitURL } from 'vault/tests/helpers/ldap'; +import { isURL, visitURL } from 'vault/tests/helpers/ldap/ldap-helpers'; module('Acceptance | ldap | libraries', function (hooks) { setupApplicationTest(hooks); diff --git a/ui/tests/acceptance/secrets/backend/ldap/overview-test.js b/ui/tests/acceptance/secrets/backend/ldap/overview-test.js index 726ff8ddbaea..8fe90cccf2e1 100644 --- a/ui/tests/acceptance/secrets/backend/ldap/overview-test.js +++ b/ui/tests/acceptance/secrets/backend/ldap/overview-test.js @@ -11,7 +11,7 @@ import ldapHandlers from 'vault/mirage/handlers/ldap'; import authPage from 'vault/tests/pages/auth'; import { click, fillIn, visit } from '@ember/test-helpers'; import { selectChoose } from 'ember-power-select/test-support'; -import { isURL, visitURL } from 'vault/tests/helpers/ldap'; +import { isURL, visitURL } from 'vault/tests/helpers/ldap/ldap-helpers'; module('Acceptance | ldap | overview', function (hooks) { setupApplicationTest(hooks); diff --git a/ui/tests/acceptance/secrets/backend/ldap/roles-test.js b/ui/tests/acceptance/secrets/backend/ldap/roles-test.js index 5c0551e36d93..15d1df74df2a 100644 --- a/ui/tests/acceptance/secrets/backend/ldap/roles-test.js +++ b/ui/tests/acceptance/secrets/backend/ldap/roles-test.js @@ -10,7 +10,7 @@ import ldapMirageScenario from 'vault/mirage/scenarios/ldap'; import ldapHandlers from 'vault/mirage/handlers/ldap'; import authPage from 'vault/tests/pages/auth'; import { click, fillIn } from '@ember/test-helpers'; -import { isURL, visitURL } from 'vault/tests/helpers/ldap'; +import { isURL, visitURL } from 'vault/tests/helpers/ldap/ldap-helpers'; module('Acceptance | ldap | roles', function (hooks) { setupApplicationTest(hooks); diff --git a/ui/tests/helpers/ldap.js b/ui/tests/helpers/ldap/ldap-helpers.js similarity index 100% rename from ui/tests/helpers/ldap.js rename to ui/tests/helpers/ldap/ldap-helpers.js diff --git a/ui/tests/integration/components/ldap/page/configuration-test.js b/ui/tests/integration/components/ldap/page/configuration-test.js index 9a881fcd4c5d..44e439b512c4 100644 --- a/ui/tests/integration/components/ldap/page/configuration-test.js +++ b/ui/tests/integration/components/ldap/page/configuration-test.js @@ -10,7 +10,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import { render, click } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { duration } from 'core/helpers/format-duration'; -import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap'; +import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap/ldap-helpers'; import { setRunOptions } from 'ember-a11y-testing/test-support'; const selectors = { diff --git a/ui/tests/integration/components/ldap/page/configure-test.js b/ui/tests/integration/components/ldap/page/configure-test.js index b2b3ed958ca9..f69047ee2cdb 100644 --- a/ui/tests/integration/components/ldap/page/configure-test.js +++ b/ui/tests/integration/components/ldap/page/configure-test.js @@ -11,7 +11,7 @@ import { render, click, fillIn } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { Response } from 'miragejs'; import sinon from 'sinon'; -import { generateBreadcrumbs } from 'vault/tests/helpers/ldap'; +import { generateBreadcrumbs } from 'vault/tests/helpers/ldap/ldap-helpers'; const selectors = { radioCard: '[data-test-radio-card="OpenLDAP"]', diff --git a/ui/tests/integration/components/ldap/page/libraries-test.js b/ui/tests/integration/components/ldap/page/libraries-test.js index 32ff5450cb61..39f355e116aa 100644 --- a/ui/tests/integration/components/ldap/page/libraries-test.js +++ b/ui/tests/integration/components/ldap/page/libraries-test.js @@ -10,7 +10,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import { render, click, fillIn } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { allowAllCapabilitiesStub } from 'vault/tests/helpers/stubs'; -import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap'; +import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap/ldap-helpers'; import { setRunOptions } from 'ember-a11y-testing/test-support'; module('Integration | Component | ldap | Page::Libraries', function (hooks) { diff --git a/ui/tests/integration/components/ldap/page/overview-test.js b/ui/tests/integration/components/ldap/page/overview-test.js index 19cc7f1ec884..b9365083d6a4 100644 --- a/ui/tests/integration/components/ldap/page/overview-test.js +++ b/ui/tests/integration/components/ldap/page/overview-test.js @@ -9,7 +9,7 @@ import { setupEngine } from 'ember-engines/test-support'; import { setupMirage } from 'ember-cli-mirage/test-support'; import { render, click } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; -import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap'; +import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap/ldap-helpers'; import sinon from 'sinon'; import { setRunOptions } from 'ember-a11y-testing/test-support'; diff --git a/ui/tests/integration/components/ldap/page/roles-test.js b/ui/tests/integration/components/ldap/page/roles-test.js index ff5807992fdf..ce1c91ac73cc 100644 --- a/ui/tests/integration/components/ldap/page/roles-test.js +++ b/ui/tests/integration/components/ldap/page/roles-test.js @@ -10,7 +10,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import { render, click, fillIn } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { allowAllCapabilitiesStub } from 'vault/tests/helpers/stubs'; -import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap'; +import { createSecretsEngine, generateBreadcrumbs } from 'vault/tests/helpers/ldap/ldap-helpers'; import sinon from 'sinon'; module('Integration | Component | ldap | Page::Roles', function (hooks) { From 5568ce077b5534460c350f6c1260d267be481ca9 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 2 Apr 2024 18:18:06 -0500 Subject: [PATCH 12/32] Move overrideResponse to stubs helper, rename clients helper --- ui/tests/acceptance/clients/counts-test.js | 2 +- .../clients/counts/overview-test.js | 2 +- .../acceptance/clients/counts/sync-test.js | 2 +- .../acceptance/reduced-disclosure-test.js | 2 +- ui/tests/acceptance/unseal-test.js | 2 +- .../client-count-helpers.js} | 33 ------------------- ui/tests/helpers/stubs.js | 24 ++++++++++++++ .../components/clients/page/counts-test.js | 2 +- .../components/clients/page/sync-test.js | 2 +- .../components/clients/page/token-test.js | 2 +- .../components/clients/running-total-test.js | 2 +- 11 files changed, 33 insertions(+), 42 deletions(-) rename ui/tests/helpers/{clients.js => clients/client-count-helpers.js} (96%) diff --git a/ui/tests/acceptance/clients/counts-test.js b/ui/tests/acceptance/clients/counts-test.js index 3e81af93cdb6..348470fd18b4 100644 --- a/ui/tests/acceptance/clients/counts-test.js +++ b/ui/tests/acceptance/clients/counts-test.js @@ -11,7 +11,7 @@ import sinon from 'sinon'; import { visit, click, currentURL } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; import timestamp from 'core/utils/timestamp'; module('Acceptance | clients | counts', function (hooks) { diff --git a/ui/tests/acceptance/clients/counts/overview-test.js b/ui/tests/acceptance/clients/counts/overview-test.js index 9b3d6cf25b9c..689d01832ecb 100644 --- a/ui/tests/acceptance/clients/counts/overview-test.js +++ b/ui/tests/acceptance/clients/counts/overview-test.js @@ -12,7 +12,7 @@ import { visit, click, findAll, settled } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { ARRAY_OF_MONTHS } from 'core/utils/date-formatters'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; import { create } from 'ember-cli-page-object'; import { clickTrigger } from 'ember-power-select/test-support/helpers'; import { formatNumber } from 'core/helpers/format-number'; diff --git a/ui/tests/acceptance/clients/counts/sync-test.js b/ui/tests/acceptance/clients/counts/sync-test.js index e0c680f8f25b..c8f0b2cb5339 100644 --- a/ui/tests/acceptance/clients/counts/sync-test.js +++ b/ui/tests/acceptance/clients/counts/sync-test.js @@ -13,7 +13,7 @@ import sinon from 'sinon'; import timestamp from 'core/utils/timestamp'; import authPage from 'vault/tests/pages/auth'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; module('Acceptance | clients | sync | activated', function (hooks) { setupApplicationTest(hooks); diff --git a/ui/tests/acceptance/reduced-disclosure-test.js b/ui/tests/acceptance/reduced-disclosure-test.js index a4dff8c28e1c..324dd9c03373 100644 --- a/ui/tests/acceptance/reduced-disclosure-test.js +++ b/ui/tests/acceptance/reduced-disclosure-test.js @@ -12,7 +12,7 @@ import { createTokenCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/ import { pollCluster } from 'vault/tests/helpers/poll-cluster'; import VAULT_KEYS from 'vault/tests/helpers/vault-keys'; import reducedDisclosureHandlers from 'vault/mirage/handlers/reduced-disclosure'; -import { overrideResponse } from 'vault/tests/helpers/clients'; +import { overrideResponse } from 'vault/tests/helpers/stubs'; const { unsealKeys } = VAULT_KEYS; const SELECTORS = { diff --git a/ui/tests/acceptance/unseal-test.js b/ui/tests/acceptance/unseal-test.js index f7a1cab3ecdf..7bbf66644943 100644 --- a/ui/tests/acceptance/unseal-test.js +++ b/ui/tests/acceptance/unseal-test.js @@ -11,7 +11,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support'; import VAULT_KEYS from 'vault/tests/helpers/vault-keys'; import authPage from 'vault/tests/pages/auth'; import { pollCluster } from 'vault/tests/helpers/poll-cluster'; -import { overrideResponse } from 'vault/tests/helpers/clients'; +import { overrideResponse } from 'vault/tests/helpers/stubs'; const { unsealKeys } = VAULT_KEYS; diff --git a/ui/tests/helpers/clients.js b/ui/tests/helpers/clients/client-count-helpers.js similarity index 96% rename from ui/tests/helpers/clients.js rename to ui/tests/helpers/clients/client-count-helpers.js index 4439e712a539..ce24221d1123 100644 --- a/ui/tests/helpers/clients.js +++ b/ui/tests/helpers/clients/client-count-helpers.js @@ -3,7 +3,6 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import { Response } from 'miragejs'; import { click } from '@ember/test-helpers'; import { LICENSE_START } from 'vault/mirage/handlers/clients'; @@ -107,38 +106,6 @@ export const CHART_ELEMENTS = { totalValues: '[data-test-group="total-values"]', }; -export function sendResponse(data, httpStatus = 200) { - if (httpStatus === 403) { - return [ - httpStatus, - { 'Content-Type': 'application/json' }, - JSON.stringify({ errors: ['permission denied'] }), - ]; - } - if (httpStatus === 204) { - // /activity endpoint returns 204 when no data, while - // /activity/monthly returns 200 with zero values on data - return [httpStatus, { 'Content-Type': 'application/json' }]; - } - return [httpStatus, { 'Content-Type': 'application/json' }, JSON.stringify(data)]; -} - -export function overrideResponse(httpStatus, data) { - if (httpStatus === 403) { - return new Response( - 403, - { 'Content-Type': 'application/json' }, - JSON.stringify({ errors: ['permission denied'] }) - ); - } - // /activity endpoint returns 204 when no data, while - // /activity/monthly returns 200 with zero values on data - if (httpStatus === 204) { - return new Response(204, { 'Content-Type': 'application/json' }); - } - return new Response(200, { 'Content-Type': 'application/json' }, JSON.stringify(data)); -} - export async function dateDropdownSelect(month, year) { const { dateDropdown, counts } = CLIENT_COUNT; await click(counts.startEdit); diff --git a/ui/tests/helpers/stubs.js b/ui/tests/helpers/stubs.js index 887fb82d1d1a..efe8024fb65c 100644 --- a/ui/tests/helpers/stubs.js +++ b/ui/tests/helpers/stubs.js @@ -3,6 +3,8 @@ * SPDX-License-Identifier: BUSL-1.1 */ +import { Response } from 'miragejs'; + export function capabilitiesStub(requestPath, capabilitiesArray) { // sample of capabilitiesArray: ['read', 'update'] return { @@ -57,3 +59,25 @@ export function allowAllCapabilitiesStub(capabilitiesList = ['root']) { }; }; } + +/** + * returns a response with the given httpStatus and data based on status + * @param {number} httpStatus 403, 204, or 200 + * @param {object} data what to return in the response if status is 200 + * @returns {Response} + */ +export function overrideResponse(httpStatus = 200, data = {}) { + if (httpStatus === 403) { + return new Response( + 403, + { 'Content-Type': 'application/json' }, + JSON.stringify({ errors: ['permission denied'] }) + ); + } + // /activity endpoint returns 204 when no data, while + // /activity/monthly returns 200 with zero values on data + if (httpStatus === 204) { + return new Response(204, { 'Content-Type': 'application/json' }); + } + return new Response(200, { 'Content-Type': 'application/json' }, JSON.stringify(data)); +} diff --git a/ui/tests/integration/components/clients/page/counts-test.js b/ui/tests/integration/components/clients/page/counts-test.js index a2b9a5cedb46..e570f037a1a0 100644 --- a/ui/tests/integration/components/clients/page/counts-test.js +++ b/ui/tests/integration/components/clients/page/counts-test.js @@ -11,7 +11,7 @@ import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts, dateDropdownSelect } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts, dateDropdownSelect } from 'vault/tests/helpers/clients/client-count-helpers'; import { selectChoose } from 'ember-power-select/test-support/helpers'; import timestamp from 'core/utils/timestamp'; import sinon from 'sinon'; diff --git a/ui/tests/integration/components/clients/page/sync-test.js b/ui/tests/integration/components/clients/page/sync-test.js index a3d0447c8fac..5355e00b600b 100644 --- a/ui/tests/integration/components/clients/page/sync-test.js +++ b/ui/tests/integration/components/clients/page/sync-test.js @@ -11,7 +11,7 @@ import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; import { formatNumber } from 'core/helpers/format-number'; import { calculateAverage } from 'vault/utils/chart-helpers'; import { dateFormat } from 'core/helpers/date-format'; diff --git a/ui/tests/integration/components/clients/page/token-test.js b/ui/tests/integration/components/clients/page/token-test.js index 47c88906f6ac..873d7ea6a900 100644 --- a/ui/tests/integration/components/clients/page/token-test.js +++ b/ui/tests/integration/components/clients/page/token-test.js @@ -14,7 +14,7 @@ import { calculateAverage } from 'vault/utils/chart-helpers'; import { formatNumber } from 'core/helpers/format-number'; import { dateFormat } from 'core/helpers/date-format'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; const START_TIME = getUnixTime(LICENSE_START); const END_TIME = getUnixTime(STATIC_NOW); diff --git a/ui/tests/integration/components/clients/running-total-test.js b/ui/tests/integration/components/clients/running-total-test.js index e89c08a77421..aa31035c6438 100644 --- a/ui/tests/integration/components/clients/running-total-test.js +++ b/ui/tests/integration/components/clients/running-total-test.js @@ -15,7 +15,7 @@ import { findAll } from '@ember/test-helpers'; import { formatNumber } from 'core/helpers/format-number'; import timestamp from 'core/utils/timestamp'; import { setRunOptions } from 'ember-a11y-testing/test-support'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients'; +import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; const START_TIME = getUnixTime(LICENSE_START); From 0242c4bacd3dbe0a4e5346c41d4c2fff8835aed7 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Wed, 3 Apr 2024 10:44:03 -0500 Subject: [PATCH 13/32] replace oidc-specific mirage & capabilities overrides --- .../oidc-config/clients-assignments-test.js | 16 +++---- .../oidc-config/clients-keys-test.js | 31 +++++++------ .../oidc-config/providers-scopes-test.js | 35 +++++++------- ui/tests/helpers/oidc-config.js | 46 +------------------ ui/tests/helpers/stubs.js | 15 +++--- .../components/oidc/assignment-form-test.js | 10 ++-- .../components/oidc/client-form-test.js | 12 ++--- .../components/oidc/client-list-test.js | 7 ++- .../components/oidc/key-form-test.js | 15 ++---- .../components/oidc/provider-form-test.js | 17 +++---- .../components/oidc/provider-list-test.js | 7 ++- .../components/oidc/scope-form-test.js | 5 +- 12 files changed, 81 insertions(+), 135 deletions(-) diff --git a/ui/tests/acceptance/oidc-config/clients-assignments-test.js b/ui/tests/acceptance/oidc-config/clients-assignments-test.js index edf65baec06d..b82fb4e17ce9 100644 --- a/ui/tests/acceptance/oidc-config/clients-assignments-test.js +++ b/ui/tests/acceptance/oidc-config/clients-assignments-test.js @@ -17,11 +17,11 @@ import { OIDC_BASE_URL, // -> '/vault/access/oidc' SELECTORS, clearRecord, - overrideCapabilities, - overrideMirageResponse, ASSIGNMENT_LIST_RESPONSE, ASSIGNMENT_DATA_RESPONSE, } from 'vault/tests/helpers/oidc-config'; +import { capabilitiesStub, overrideResponse } from 'vault/tests/helpers/stubs'; + const searchSelect = create(ss); const flashMessage = create(fm); @@ -51,7 +51,7 @@ module('Acceptance | oidc-config clients and assignments', function (hooks) { test('it renders empty state when no clients are configured', async function (assert) { assert.expect(5); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(404)); + this.server.get('/identity/oidc/client', () => overrideResponse(404)); await visit(OIDC_BASE_URL); assert.strictEqual(currentURL(), '/vault/access/oidc'); @@ -277,10 +277,10 @@ module('Acceptance | oidc-config clients and assignments', function (hooks) { test('it navigates to and from an assignment from the list view', async function (assert) { assert.expect(6); this.server.get('/identity/oidc/assignment', () => - overrideMirageResponse(null, ASSIGNMENT_LIST_RESPONSE) + overrideResponse(200, { data: ASSIGNMENT_LIST_RESPONSE }) ); this.server.get('/identity/oidc/assignment/test-assignment', () => - overrideMirageResponse(null, ASSIGNMENT_DATA_RESPONSE) + overrideResponse(200, { data: ASSIGNMENT_DATA_RESPONSE }) ); await visit(OIDC_BASE_URL + '/assignments'); assert @@ -327,13 +327,13 @@ module('Acceptance | oidc-config clients and assignments', function (hooks) { test('it hides assignment delete and edit when no permission', async function (assert) { assert.expect(5); this.server.get('/identity/oidc/assignment', () => - overrideMirageResponse(null, ASSIGNMENT_LIST_RESPONSE) + overrideResponse(null, { data: ASSIGNMENT_LIST_RESPONSE }) ); this.server.get('/identity/oidc/assignment/test-assignment', () => - overrideMirageResponse(null, ASSIGNMENT_DATA_RESPONSE) + overrideResponse(null, { data: ASSIGNMENT_DATA_RESPONSE }) ); this.server.post('/sys/capabilities-self', () => - overrideCapabilities(OIDC_BASE_URL + '/assignment/test-assignment', ['read']) + capabilitiesStub(OIDC_BASE_URL + '/assignment/test-assignment', ['read']) ); await visit(OIDC_BASE_URL + '/assignments'); diff --git a/ui/tests/acceptance/oidc-config/clients-keys-test.js b/ui/tests/acceptance/oidc-config/clients-keys-test.js index 7a37f8c6a9e2..33e2bd7c16f8 100644 --- a/ui/tests/acceptance/oidc-config/clients-keys-test.js +++ b/ui/tests/acceptance/oidc-config/clients-keys-test.js @@ -17,11 +17,10 @@ import { OIDC_BASE_URL, // -> '/vault/access/oidc' SELECTORS, clearRecord, - overrideCapabilities, - overrideMirageResponse, CLIENT_LIST_RESPONSE, CLIENT_DATA_RESPONSE, } from 'vault/tests/helpers/oidc-config'; +import { capabilitiesStub, overrideResponse } from 'vault/tests/helpers/stubs'; const searchSelect = create(ss); const flashMessage = create(fm); @@ -177,7 +176,7 @@ module('Acceptance | oidc-config clients and keys', function (hooks) { test('it creates, rotates and deletes a key', async function (assert) { assert.expect(10); // mock client list so OIDC url does not redirect to landing page - this.server.get('/identity/oidc/client', () => overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); this.server.post('/identity/oidc/key/test-key/rotate', (schema, req) => { const json = JSON.parse(req.requestBody); assert.strictEqual(json.verification_ttl, 86400, 'request made with correct args to accurate endpoint'); @@ -240,9 +239,9 @@ module('Acceptance | oidc-config clients and keys', function (hooks) { test('it renders client details and providers', async function (assert) { assert.expect(8); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); this.server.get('/identity/oidc/client/test-app', () => - overrideMirageResponse(null, CLIENT_DATA_RESPONSE) + overrideResponse(null, { data: CLIENT_DATA_RESPONSE }) ); await visit(OIDC_BASE_URL); await click('[data-test-oidc-client-linked-block]'); @@ -264,12 +263,12 @@ module('Acceptance | oidc-config clients and keys', function (hooks) { test('it hides delete and edit client when no permission', async function (assert) { assert.expect(5); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); this.server.get('/identity/oidc/client/test-app', () => - overrideMirageResponse(null, CLIENT_DATA_RESPONSE) + overrideResponse(null, { data: CLIENT_DATA_RESPONSE }) ); this.server.post('/sys/capabilities-self', () => - overrideCapabilities(OIDC_BASE_URL + '/client/test-app', ['read']) + capabilitiesStub(OIDC_BASE_URL + '/client/test-app', ['read']) ); await visit(OIDC_BASE_URL); @@ -283,17 +282,19 @@ module('Acceptance | oidc-config clients and keys', function (hooks) { test('it hides delete and edit key when no permission', async function (assert) { assert.expect(4); - this.server.get('/identity/oidc/keys', () => overrideMirageResponse(null, { keys: ['test-key'] })); + this.server.get('/identity/oidc/keys', () => overrideResponse(null, { data: { keys: ['test-key'] } })); this.server.get('/identity/oidc/key/test-key', () => - overrideMirageResponse(null, { - algorithm: 'RS256', - allowed_client_ids: ['*'], - rotation_period: 86400, - verification_ttl: 86400, + overrideResponse(null, { + data: { + algorithm: 'RS256', + allowed_client_ids: ['*'], + rotation_period: 86400, + verification_ttl: 86400, + }, }) ); this.server.post('/sys/capabilities-self', () => - overrideCapabilities(OIDC_BASE_URL + '/key/test-key', ['read']) + capabilitiesStub(OIDC_BASE_URL + '/key/test-key', ['read']) ); await visit(OIDC_BASE_URL + '/keys'); diff --git a/ui/tests/acceptance/oidc-config/providers-scopes-test.js b/ui/tests/acceptance/oidc-config/providers-scopes-test.js index 472fa443bc02..b680a64ec0fe 100644 --- a/ui/tests/acceptance/oidc-config/providers-scopes-test.js +++ b/ui/tests/acceptance/oidc-config/providers-scopes-test.js @@ -22,9 +22,8 @@ import { PROVIDER_LIST_RESPONSE, PROVIDER_DATA_RESPONSE, clearRecord, - overrideCapabilities, - overrideMirageResponse, } from 'vault/tests/helpers/oidc-config'; +import { capabilitiesStub, overrideResponse } from 'vault/tests/helpers/stubs'; const searchSelect = create(ss); const flashMessage = create(fm); @@ -38,14 +37,14 @@ module('Acceptance | oidc-config providers and scopes', function (hooks) { oidcConfigHandlers(this.server); this.store = this.owner.lookup('service:store'); // mock client list so OIDC BASE URL does not redirect to landing call-to-action image - this.server.get('/identity/oidc/client', () => overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); return authPage.login(); }); // LIST SCOPES EMPTY test('it navigates to scopes list view and renders empty state when no scopes are configured', async function (assert) { assert.expect(4); - this.server.get('/identity/oidc/scope', () => overrideMirageResponse(404)); + this.server.get('/identity/oidc/scope', () => overrideResponse(404)); await visit(OIDC_BASE_URL); await click('[data-test-tab="scopes"]'); assert.strictEqual(currentURL(), '/vault/access/oidc/scopes'); @@ -64,9 +63,9 @@ module('Acceptance | oidc-config providers and scopes', function (hooks) { // LIST SCOPE EXIST test('it renders scope list when scopes exist', async function (assert) { assert.expect(11); - this.server.get('/identity/oidc/scope', () => overrideMirageResponse(null, SCOPE_LIST_RESPONSE)); + this.server.get('/identity/oidc/scope', () => overrideResponse(null, { data: SCOPE_LIST_RESPONSE })); this.server.get('/identity/oidc/scope/test-scope', () => - overrideMirageResponse(null, SCOPE_DATA_RESPONSE) + overrideResponse(null, { data: SCOPE_DATA_RESPONSE }) ); await visit(OIDC_BASE_URL + '/scopes'); assert.strictEqual( @@ -125,13 +124,15 @@ module('Acceptance | oidc-config providers and scopes', function (hooks) { // ERROR DELETING SCOPE test('it throws error when trying to delete when scope is currently being associated with any provider', async function (assert) { assert.expect(3); - this.server.get('/identity/oidc/scope', () => overrideMirageResponse(null, SCOPE_LIST_RESPONSE)); + this.server.get('/identity/oidc/scope', () => overrideResponse(null, { data: SCOPE_LIST_RESPONSE })); this.server.get('/identity/oidc/scope/test-scope', () => - overrideMirageResponse(null, SCOPE_DATA_RESPONSE) + overrideResponse(null, { data: SCOPE_DATA_RESPONSE }) + ); + this.server.get('/identity/oidc/provider', () => + overrideResponse(null, { data: PROVIDER_LIST_RESPONSE }) ); - this.server.get('/identity/oidc/provider', () => overrideMirageResponse(null, PROVIDER_LIST_RESPONSE)); this.server.get('/identity/oidc/provider/test-provider', () => { - overrideMirageResponse(null, PROVIDER_DATA_RESPONSE); + overrideResponse(null, { data: PROVIDER_DATA_RESPONSE }); }); // throw error when trying to delete test-scope since it is associated to test-provider this.server.delete( @@ -376,17 +377,19 @@ module('Acceptance | oidc-config providers and scopes', function (hooks) { test('it hides delete and edit for a provider when no permission', async function (assert) { assert.expect(3); this.server.get('/identity/oidc/providers', () => - overrideMirageResponse(null, { providers: ['test-provider'] }) + overrideResponse(null, { data: { providers: ['test-provider'] } }) ); this.server.get('/identity/oidc/provider/test-provider', () => - overrideMirageResponse(null, { - allowed_client_ids: ['*'], - issuer: 'http://127.0.0.1:8200/v1/identity/oidc/provider/test-provider', - scopes_supported: ['test-scope'], + overrideResponse(null, { + data: { + allowed_client_ids: ['*'], + issuer: 'http://127.0.0.1:8200/v1/identity/oidc/provider/test-provider', + scopes_supported: ['test-scope'], + }, }) ); this.server.post('/sys/capabilities-self', () => - overrideCapabilities(OIDC_BASE_URL + '/provider/test-provider', ['read']) + capabilitiesStub(OIDC_BASE_URL + '/provider/test-provider', ['read']) ); await visit(OIDC_BASE_URL + '/providers'); diff --git a/ui/tests/helpers/oidc-config.js b/ui/tests/helpers/oidc-config.js index a226d8e1df8d..f16af74b3635 100644 --- a/ui/tests/helpers/oidc-config.js +++ b/ui/tests/helpers/oidc-config.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import { Response } from 'miragejs'; +import { debug } from '@ember/debug'; export const OIDC_BASE_URL = `/vault/access/oidc`; @@ -57,49 +57,6 @@ export const SELECTORS = { providerClientsTab: '[data-test-oidc-provider-clients]', }; -export function overrideMirageResponse(httpStatus, data) { - if (httpStatus === 403) { - return new Response( - 403, - { 'Content-Type': 'application/json' }, - JSON.stringify({ errors: ['permission denied'] }) - ); - } - if (httpStatus === 404) { - return new Response(404, { 'Content-Type': 'application/json' }); - } - if (httpStatus === 200) { - return new Response(200, { 'Content-Type': 'application/json' }, JSON.stringify(data)); - } - return { - request_id: crypto.randomUUID(), - lease_id: '', - renewable: false, - lease_duration: 0, - wrap_info: null, - warnings: null, - auth: null, - data: { ...data }, - }; -} - -export function overrideCapabilities(requestPath, capabilitiesArray) { - // sample of capabilitiesArray: ['read', 'update'] - return { - request_id: '40f7e44d-af5c-9b60-bd20-df72eb17e294', - lease_id: '', - renewable: false, - lease_duration: 0, - data: { - capabilities: capabilitiesArray, - [requestPath]: capabilitiesArray, - }, - wrap_info: null, - warnings: null, - auth: null, - }; -} - export async function clearRecord(store, modelType, id) { await store .findRecord(modelType, id) @@ -107,6 +64,7 @@ export async function clearRecord(store, modelType, id) { deleteModelRecord(model); }) .catch(() => { + debug(`Clearing record failed for ${modelType} with id: ${id}`); // swallow error }); } diff --git a/ui/tests/helpers/stubs.js b/ui/tests/helpers/stubs.js index efe8024fb65c..ab674dbf1fd8 100644 --- a/ui/tests/helpers/stubs.js +++ b/ui/tests/helpers/stubs.js @@ -8,8 +8,6 @@ import { Response } from 'miragejs'; export function capabilitiesStub(requestPath, capabilitiesArray) { // sample of capabilitiesArray: ['read', 'update'] return { - [requestPath]: capabilitiesArray, - capabilities: capabilitiesArray, request_id: '40f7e44d-af5c-9b60-bd20-df72eb17e294', lease_id: '', renewable: false, @@ -62,11 +60,11 @@ export function allowAllCapabilitiesStub(capabilitiesList = ['root']) { /** * returns a response with the given httpStatus and data based on status - * @param {number} httpStatus 403, 204, or 200 - * @param {object} data what to return in the response if status is 200 + * @param {number} httpStatus 403, 404, 204, or 200 (default) + * @param {object} payload what to return in the response if status is 200 * @returns {Response} */ -export function overrideResponse(httpStatus = 200, data = {}) { +export function overrideResponse(httpStatus = 200, payload = {}) { if (httpStatus === 403) { return new Response( 403, @@ -74,10 +72,11 @@ export function overrideResponse(httpStatus = 200, data = {}) { JSON.stringify({ errors: ['permission denied'] }) ); } - // /activity endpoint returns 204 when no data, while - // /activity/monthly returns 200 with zero values on data + if (httpStatus === 404) { + return new Response(404, { 'Content-Type': 'application/json' }); + } if (httpStatus === 204) { return new Response(204, { 'Content-Type': 'application/json' }); } - return new Response(200, { 'Content-Type': 'application/json' }, JSON.stringify(data)); + return new Response(200, { 'Content-Type': 'application/json' }, payload); } diff --git a/ui/tests/integration/components/oidc/assignment-form-test.js b/ui/tests/integration/components/oidc/assignment-form-test.js index 16bc99096a93..ea8f32e2bc49 100644 --- a/ui/tests/integration/components/oidc/assignment-form-test.js +++ b/ui/tests/integration/components/oidc/assignment-form-test.js @@ -9,8 +9,8 @@ import { render, fillIn, click, findAll } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; import oidcConfigHandlers from 'vault/mirage/handlers/oidc-config'; -import { overrideMirageResponse } from 'vault/tests/helpers/oidc-config'; import { setRunOptions } from 'ember-a11y-testing/test-support'; +import { overrideResponse } from 'vault/tests/helpers/stubs'; module('Integration | Component | oidc/assignment-form', function (hooks) { setupRenderingTest(hooks); @@ -95,8 +95,8 @@ module('Integration | Component | oidc/assignment-form', function (hooks) { test('it should use fallback component on create if no permissions for entities or groups', async function (assert) { assert.expect(2); this.model = this.store.createRecord('oidc/assignment'); - this.server.get('/identity/entity/id', () => overrideMirageResponse(403)); - this.server.get('/identity/group/id', () => overrideMirageResponse(403)); + this.server.get('/identity/entity/id', () => overrideResponse(403)); + this.server.get('/identity/group/id', () => overrideResponse(403)); await render(hbs` overrideMirageResponse(403)); - this.server.get('/identity/group/id', () => overrideMirageResponse(403)); + this.server.get('/identity/entity/id', () => overrideResponse(403)); + this.server.get('/identity/group/id', () => overrideResponse(403)); await render(hbs` overrideMirageResponse(403)); + this.server.get('/identity/oidc/assignment', () => overrideResponse(403)); await render(hbs` overrideCapabilities(OIDC_BASE_URL + '/clients')); + this.server.post('/sys/capabilities-self', () => capabilitiesStub(OIDC_BASE_URL + '/clients')); await render(hbs` { const { paths } = JSON.parse(req.requestBody); if (paths[0] === 'identity/oidc/client/first-client') { - return overrideCapabilities('identity/oidc/client/first-client', ['read']); + return capabilitiesStub('identity/oidc/client/first-client', ['read']); } else { - return overrideCapabilities('identity/oidc/client/second-client', ['deny']); + return capabilitiesStub('identity/oidc/client/second-client', ['deny']); } }); await render(hbs``); diff --git a/ui/tests/integration/components/oidc/key-form-test.js b/ui/tests/integration/components/oidc/key-form-test.js index a77e6915a0c6..47b52f1763ce 100644 --- a/ui/tests/integration/components/oidc/key-form-test.js +++ b/ui/tests/integration/components/oidc/key-form-test.js @@ -9,14 +9,9 @@ import { render, fillIn, click, findAll } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; import oidcConfigHandlers from 'vault/mirage/handlers/oidc-config'; -import { - OIDC_BASE_URL, - CLIENT_LIST_RESPONSE, - SELECTORS, - overrideMirageResponse, - overrideCapabilities, -} from 'vault/tests/helpers/oidc-config'; +import { OIDC_BASE_URL, CLIENT_LIST_RESPONSE, SELECTORS } from 'vault/tests/helpers/oidc-config'; import { setRunOptions } from 'ember-a11y-testing/test-support'; +import { capabilitiesStub, overrideResponse } from 'vault/tests/helpers/stubs'; module('Integration | Component | oidc/key-form', function (hooks) { setupRenderingTest(hooks); @@ -25,7 +20,7 @@ module('Integration | Component | oidc/key-form', function (hooks) { hooks.beforeEach(function () { oidcConfigHandlers(this.server); this.store = this.owner.lookup('service:store'); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); setRunOptions({ rules: { // TODO: fix RadioCard component (replace with HDS) @@ -177,7 +172,7 @@ module('Integration | Component | oidc/key-form', function (hooks) { this.model = this.store.peekRecord('oidc/key', 'test-key'); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(403)); + this.server.get('/identity/oidc/client', () => overrideResponse(403)); await render(hbs` overrideCapabilities(OIDC_BASE_URL + '/keys')); + this.server.post('/sys/capabilities-self', () => capabilitiesStub(OIDC_BASE_URL + '/keys')); await render(hbs` overrideMirageResponse(null, CLIENT_LIST_RESPONSE)); + this.server.get('/identity/oidc/client', () => overrideResponse(null, { data: CLIENT_LIST_RESPONSE })); setRunOptions({ rules: { // TODO: Fix SearchSelect component @@ -193,8 +188,8 @@ module('Integration | Component | oidc/provider-form', function (hooks) { test('it should render fallback for search select', async function (assert) { assert.expect(2); this.model = this.store.createRecord('oidc/provider'); - this.server.get('/identity/oidc/scope', () => overrideMirageResponse(403)); - this.server.get('/identity/oidc/client', () => overrideMirageResponse(403)); + this.server.get('/identity/oidc/scope', () => overrideResponse(403)); + this.server.get('/identity/oidc/client', () => overrideResponse(403)); await render(hbs` overrideCapabilities(OIDC_BASE_URL + '/providers')); + this.server.post('/sys/capabilities-self', () => capabilitiesStub(OIDC_BASE_URL + '/providers')); await render(hbs` { const { paths } = JSON.parse(req.requestBody); if (paths[0] === 'identity/oidc/provider/first-provider') { - return overrideCapabilities('identity/oidc/provider/first-provider', ['read']); + return capabilitiesStub('identity/oidc/provider/first-provider', ['read']); } else { - return overrideCapabilities('identity/oidc/provider/second-provider', ['deny']); + return capabilitiesStub('identity/oidc/provider/second-provider', ['deny']); } }); await render(hbs``); diff --git a/ui/tests/integration/components/oidc/scope-form-test.js b/ui/tests/integration/components/oidc/scope-form-test.js index 15a5390ea4e4..cfaed24e0681 100644 --- a/ui/tests/integration/components/oidc/scope-form-test.js +++ b/ui/tests/integration/components/oidc/scope-form-test.js @@ -8,8 +8,9 @@ import { setupRenderingTest } from 'ember-qunit'; import { render, fillIn, click, findAll } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { setupMirage } from 'ember-cli-mirage/test-support'; -import { SELECTORS, OIDC_BASE_URL, overrideCapabilities } from 'vault/tests/helpers/oidc-config'; +import { SELECTORS, OIDC_BASE_URL } from 'vault/tests/helpers/oidc-config'; import { setRunOptions } from 'ember-a11y-testing/test-support'; +import { capabilitiesStub } from 'vault/tests/helpers/stubs'; module('Integration | Component | oidc/scope-form', function (hooks) { setupRenderingTest(hooks); @@ -197,7 +198,7 @@ module('Integration | Component | oidc/scope-form', function (hooks) { test('it should render error alerts when API returns an error', async function (assert) { assert.expect(2); this.model = this.store.createRecord('oidc/scope'); - this.server.post('/sys/capabilities-self', () => overrideCapabilities(OIDC_BASE_URL + '/scopes')); + this.server.post('/sys/capabilities-self', () => capabilitiesStub(OIDC_BASE_URL + '/scopes')); await render(hbs` Date: Wed, 3 Apr 2024 16:13:11 -0500 Subject: [PATCH 14/32] add secretTab and checkboxByAttr to general selectors --- ui/tests/helpers/general-selectors.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/tests/helpers/general-selectors.js b/ui/tests/helpers/general-selectors.js index 2b62258401e9..a309670b4971 100644 --- a/ui/tests/helpers/general-selectors.js +++ b/ui/tests/helpers/general-selectors.js @@ -14,6 +14,8 @@ export const GENERAL = { headerContainer: 'header.page-header', icon: (name) => `[data-test-icon="${name}"]`, tab: (name) => `[data-test-tab="${name}"]`, + secretTab: (name) => `[data-test-secret-list-tab="${name}"]`, + filter: (name) => `[data-test-filter="${name}"]`, filterInput: '[data-test-filter-input]', confirmModalInput: '[data-test-confirmation-modal-input]', @@ -29,6 +31,7 @@ export const GENERAL = { infoRowValue: (label) => `[data-test-value-div="${label}"]`, inputByAttr: (attr) => `[data-test-input="${attr}"]`, selectByAttr: (attr) => `[data-test-select="${attr}"]`, + checkboxByAttr: (attr) => `[data-test-checkbox="${attr}"]`, fieldByAttr: (attr) => `[data-test-field="${attr}"]`, enableField: (attr) => `[data-test-enable-field="${attr}"] button`, ttl: { From fe7317d23cf8d53d766fee1abc063916a7ea06e7 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 09:36:11 -0500 Subject: [PATCH 15/32] general-selectors are TS --- ui/tests/helpers/general-selectors.js | 74 -------------------------- ui/tests/helpers/general-selectors.ts | 75 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 74 deletions(-) delete mode 100644 ui/tests/helpers/general-selectors.js create mode 100644 ui/tests/helpers/general-selectors.ts diff --git a/ui/tests/helpers/general-selectors.js b/ui/tests/helpers/general-selectors.js deleted file mode 100644 index a309670b4971..000000000000 --- a/ui/tests/helpers/general-selectors.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { findAll } from '@ember/test-helpers'; - -export const GENERAL = { - breadcrumb: '[data-test-breadcrumbs] li', - breadcrumbAtIdx: (idx) => `[data-test-breadcrumbs] li:nth-child(${idx + 1}) a`, - breadcrumbs: '[data-test-breadcrumbs]', - breadcrumbLink: (label) => `[data-test-breadcrumb="${label}"] a`, - title: '[data-test-page-title]', - headerContainer: 'header.page-header', - icon: (name) => `[data-test-icon="${name}"]`, - tab: (name) => `[data-test-tab="${name}"]`, - secretTab: (name) => `[data-test-secret-list-tab="${name}"]`, - - filter: (name) => `[data-test-filter="${name}"]`, - filterInput: '[data-test-filter-input]', - confirmModalInput: '[data-test-confirmation-modal-input]', - confirmButton: '[data-test-confirm-button]', - confirmTrigger: '[data-test-confirm-action-trigger]', - emptyStateTitle: '[data-test-empty-state-title]', - emptyStateMessage: '[data-test-empty-state-message]', - emptyStateActions: '[data-test-empty-state-actions]', - menuTrigger: '[data-test-popup-menu-trigger]', - listItem: '[data-test-list-item-link]', - // FORMS - infoRowLabel: (label) => `[data-test-row-label="${label}"]`, - infoRowValue: (label) => `[data-test-value-div="${label}"]`, - inputByAttr: (attr) => `[data-test-input="${attr}"]`, - selectByAttr: (attr) => `[data-test-select="${attr}"]`, - checkboxByAttr: (attr) => `[data-test-checkbox="${attr}"]`, - fieldByAttr: (attr) => `[data-test-field="${attr}"]`, - enableField: (attr) => `[data-test-enable-field="${attr}"] button`, - ttl: { - toggle: (attr) => `[data-test-toggle-label="${attr}"]`, - input: (attr) => `[data-test-ttl-value="${attr}"]`, - }, - - validation: (attr) => `[data-test-field-validation=${attr}]`, - validationWarning: (attr) => `[data-test-validation-warning=${attr}]`, - messageError: '[data-test-message-error]', - kvObjectEditor: { - deleteRow: (idx = 0) => `[data-test-kv-delete-row="${idx}"]`, - }, - searchSelect: { - options: '.ember-power-select-option', - optionIndex: (text) => findAll('.ember-power-select-options li').findIndex((e) => e.innerText === text), - option: (index = 0) => `.ember-power-select-option:nth-child(${index + 1})`, - selectedOption: (index = 0) => `[data-test-selected-option="${index}"]`, - noMatch: '.ember-power-select-option--no-matches-message', - removeSelected: '[data-test-selected-list-button="delete"]', - }, - overviewCard: { - title: (title) => `[data-test-overview-card-title="${title}"]`, - description: (title) => `[data-test-overview-card-subtitle="${title}"]`, - content: (title) => `[data-test-overview-card-content="${title}"]`, - action: (title) => `[data-test-overview-card-container="${title}"] [data-test-action-text]`, - actionLink: (label) => `[data-test-action-text="${label}"]`, - }, - pagination: { - next: '.hds-pagination-nav__arrow--direction-next', - prev: '.hds-pagination-nav__arrow--direction-prev', - }, - kvSuggestion: { - input: '[data-test-kv-suggestion-input]', - select: '[data-test-kv-suggestion-select]', - }, - navLink: (label) => `[data-test-sidebar-nav-link="${label}"]`, - cancelButton: '[data-test-cancel]', - saveButton: '[data-test-save]', -}; diff --git a/ui/tests/helpers/general-selectors.ts b/ui/tests/helpers/general-selectors.ts new file mode 100644 index 000000000000..5e338bd16267 --- /dev/null +++ b/ui/tests/helpers/general-selectors.ts @@ -0,0 +1,75 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { findAll } from '@ember/test-helpers'; + +export const GENERAL = { + breadcrumb: '[data-test-breadcrumbs] li', + breadcrumbAtIdx: (idx: string) => `[data-test-breadcrumbs] li:nth-child(${idx + 1}) a`, + breadcrumbs: '[data-test-breadcrumbs]', + breadcrumbLink: (label: string) => `[data-test-breadcrumb="${label}"] a`, + title: '[data-test-page-title]', + headerContainer: 'header.page-header', + icon: (name: string) => `[data-test-icon="${name}"]`, + tab: (name: string) => `[data-test-tab="${name}"]`, + secretTab: (name: string) => `[data-test-secret-list-tab="${name}"]`, + + filter: (name: string) => `[data-test-filter="${name}"]`, + filterInput: '[data-test-filter-input]', + confirmModalInput: '[data-test-confirmation-modal-input]', + confirmButton: '[data-test-confirm-button]', + confirmTrigger: '[data-test-confirm-action-trigger]', + emptyStateTitle: '[data-test-empty-state-title]', + emptyStateMessage: '[data-test-empty-state-message]', + emptyStateActions: '[data-test-empty-state-actions]', + menuTrigger: '[data-test-popup-menu-trigger]', + listItem: '[data-test-list-item-link]', + // FORMS + infoRowLabel: (label: string) => `[data-test-row-label="${label}"]`, + infoRowValue: (label: string) => `[data-test-value-div="${label}"]`, + inputByAttr: (attr: string) => `[data-test-input="${attr}"]`, + selectByAttr: (attr: string) => `[data-test-select="${attr}"]`, + checkboxByAttr: (attr: string) => `[data-test-checkbox="${attr}"]`, + fieldByAttr: (attr: string) => `[data-test-field="${attr}"]`, + enableField: (attr: string) => `[data-test-enable-field="${attr}"] button`, + ttl: { + toggle: (attr: string) => `[data-test-toggle-label="${attr}"]`, + input: (attr: string) => `[data-test-ttl-value="${attr}"]`, + }, + + validation: (attr: string) => `[data-test-field-validation=${attr}]`, + validationWarning: (attr: string) => `[data-test-validation-warning=${attr}]`, + messageError: '[data-test-message-error]', + kvObjectEditor: { + deleteRow: (idx = 0) => `[data-test-kv-delete-row="${idx}"]`, + }, + searchSelect: { + options: '.ember-power-select-option', + optionIndex: (text: string) => + findAll('.ember-power-select-options li').findIndex((e) => e.textContent?.trim() === text), + option: (index = 0) => `.ember-power-select-option:nth-child(${index + 1})`, + selectedOption: (index = 0) => `[data-test-selected-option="${index}"]`, + noMatch: '.ember-power-select-option--no-matches-message', + removeSelected: '[data-test-selected-list-button="delete"]', + }, + overviewCard: { + title: (title: string) => `[data-test-overview-card-title="${title}"]`, + description: (title: string) => `[data-test-overview-card-subtitle="${title}"]`, + content: (title: string) => `[data-test-overview-card-content="${title}"]`, + action: (title: string) => `[data-test-overview-card-container="${title}"] [data-test-action-text]`, + actionLink: (label: string) => `[data-test-action-text="${label}"]`, + }, + pagination: { + next: '.hds-pagination-nav__arrow--direction-next', + prev: '.hds-pagination-nav__arrow--direction-prev', + }, + kvSuggestion: { + input: '[data-test-kv-suggestion-input]', + select: '[data-test-kv-suggestion-select]', + }, + navLink: (label: string) => `[data-test-sidebar-nav-link="${label}"]`, + cancelButton: '[data-test-cancel]', + saveButton: '[data-test-save]', +}; From cd3c0284ea19ac75c8f74895f5b3948b75332e1f Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 10:45:29 -0500 Subject: [PATCH 16/32] fix merge conflict import --- ui/tests/integration/utils/client-count-utils-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/tests/integration/utils/client-count-utils-test.js b/ui/tests/integration/utils/client-count-utils-test.js index 907f0be10f16..2d40ea889a59 100644 --- a/ui/tests/integration/utils/client-count-utils-test.js +++ b/ui/tests/integration/utils/client-count-utils-test.js @@ -18,12 +18,12 @@ import { ACTIVITY_RESPONSE_STUB as RESPONSE, VERSION_HISTORY, SERIALIZED_ACTIVITY_RESPONSE, -} from 'vault/tests/helpers/clients'; +} from 'vault/tests/helpers/clients/client-count-helpers'; /* -formatByNamespace, formatByMonths, destructureClientCounts are utils -used to normalize the sys/counters/activity response in the clients/activity -serializer. these functions are tested individually here, instead of all at once +formatByNamespace, formatByMonths, destructureClientCounts are utils +used to normalize the sys/counters/activity response in the clients/activity +serializer. these functions are tested individually here, instead of all at once in a serializer test for easier debugging */ module('Integration | Util | client count utils', function (hooks) { From b5392d425e85c98c10ba50094257b4450c7115cc Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 10:46:11 -0500 Subject: [PATCH 17/32] Bump message wait time for oidc auth method test --- ui/tests/acceptance/oidc-auth-method-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/acceptance/oidc-auth-method-test.js b/ui/tests/acceptance/oidc-auth-method-test.js index cedd5899e3bb..82fb72a5e8a5 100644 --- a/ui/tests/acceptance/oidc-auth-method-test.js +++ b/ui/tests/acceptance/oidc-auth-method-test.js @@ -69,7 +69,7 @@ module('Acceptance | oidc auth method', function (hooks) { later(() => { window.postMessage(buildMessage().data, window.origin); cancelTimers(); - }, 50); + }, 100); await click('[data-test-auth-submit]'); }); From cf1b31b746e4c66f134d6e99cf79f14fc265fe9d Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 10:46:33 -0500 Subject: [PATCH 18/32] Refactor auth methods mgmt test so we don't run into a timeout --- ui/tests/acceptance/auth-list-test.js | 180 ++++++++++++-------------- 1 file changed, 83 insertions(+), 97 deletions(-) diff --git a/ui/tests/acceptance/auth-list-test.js b/ui/tests/acceptance/auth-list-test.js index ffbe95400975..5d6dbfc0b2d3 100644 --- a/ui/tests/acceptance/auth-list-test.js +++ b/ui/tests/acceptance/auth-list-test.js @@ -73,109 +73,95 @@ module('Acceptance | auth backend list', function (hooks) { assert.dom(SELECTORS.listItem).hasText(this.user1, 'user1 exists in the list'); }); - test('auth methods are linkable and link to correct view', async function (assert) { - assert.expect(45); - const uid = uuidv4(); - await visit('/vault/access'); + module('auth methods are linkable and link to correct view', function (hooks) { + hooks.beforeEach(async function () { + this.uid = uuidv4(); + await visit('/vault/access'); + }); - const supportManaged = supportedManagedAuthBackends(); // Test all auth methods, not just those you can log in with - const backends = methods().map((backend) => backend.type); - assert.deepEqual( - backends, - [ - 'alicloud', - 'approle', - 'aws', - 'azure', - 'gcp', - 'github', - 'jwt', - 'oidc', - 'kubernetes', - 'ldap', - 'okta', - 'radius', - 'cert', - 'userpass', - ], - 'non-enterprise auth methods are available' - ); - for (const type of backends) { - const path = type === 'token' ? 'token' : `auth-list-${type}-${uid}`; - if (type !== 'token') { - await enablePage.enable(type, path); - } - await settled(); + methods() + .map((backend) => backend.type) + .forEach((type) => { + test(`${type} auth method`, async function (assert) { + const supportManaged = supportedManagedAuthBackends(); + const path = type === 'token' ? 'token' : `auth-list-${type}-${this.uid}`; + if (type !== 'token') { + await enablePage.enable(type, path); + } + await settled(); + await visit('/vault/access'); + + // check popup menu + const itemCount = type === 'token' ? 2 : 3; + await click(`[data-test-auth-backend-link="${path}"] [data-test-popup-menu-trigger]`); + assert + .dom('.hds-dropdown-list-item') + .exists({ count: itemCount }, `shows ${itemCount} dropdown items for ${type}`); + + // all auth methods should be linkable + await click(`[data-test-auth-backend-link="${path}"]`); + if (!supportManaged.includes(type)) { + assert.dom('[data-test-auth-section-tab]').exists({ count: 1 }); + assert + .dom('[data-test-auth-section-tab]') + .hasText('Configuration', `only shows configuration tab for ${type} auth method`); + assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`); + } else { + let expectedTabs = 2; + if (type == 'ldap' || type === 'okta') { + expectedTabs = 3; + } + assert + .dom('[data-test-auth-section-tab]') + .exists({ count: expectedTabs }, `has management tabs for ${type} auth method`); + } + if (type !== 'token') { + // cleanup method + await runCmd(deleteAuthCmd(path)); + } + }); + }); + }); + + module('enterprise', function () { + test('ent-only auth methods are linkable and link to correct view', async function (assert) { + assert.expect(3); + const uid = uuidv4(); await visit('/vault/access'); - // check popup menu - const itemCount = type === 'token' ? 2 : 3; - await click(`[data-test-auth-backend-link="${path}"] [data-test-popup-menu-trigger]`); - assert - .dom('.hds-dropdown-list-item') - .exists({ count: itemCount }, `shows ${itemCount} dropdown items for ${type}`); + // Only SAML is enterprise-only for now + const type = 'saml'; + const path = `auth-list-${type}-${uid}`; + await enablePage.enable(type, path); + await settled(); + await visit('/vault/access'); // all auth methods should be linkable await click(`[data-test-auth-backend-link="${path}"]`); - if (!supportManaged.includes(type)) { - assert.dom('[data-test-auth-section-tab]').exists({ count: 1 }); - assert - .dom('[data-test-auth-section-tab]') - .hasText('Configuration', `only shows configuration tab for ${type} auth method`); - assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`); - } else { - let expectedTabs = 2; - if (type == 'ldap' || type === 'okta') { - expectedTabs = 3; - } - assert - .dom('[data-test-auth-section-tab]') - .exists({ count: expectedTabs }, `has management tabs for ${type} auth method`); - } - if (type !== 'token') { - // cleanup method - await runCmd(deleteAuthCmd(path)); - } - } - }); - - test('enterprise: auth methods are linkable and link to correct view', async function (assert) { - assert.expect(3); - const uid = uuidv4(); - await visit('/vault/access'); - - // Only SAML is enterprise-only for now - const type = 'saml'; - const path = `auth-list-${type}-${uid}`; - await enablePage.enable(type, path); - await settled(); - await visit('/vault/access'); - - // all auth methods should be linkable - await click(`[data-test-auth-backend-link="${path}"]`); - assert.dom('[data-test-auth-section-tab]').exists({ count: 1 }); - assert - .dom('[data-test-auth-section-tab]') - .hasText('Configuration', `only shows configuration tab for ${type} auth method`); - assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`); - await runCmd(deleteAuthCmd(path)); - }); - - test('enterprise: token config within namespace', async function (assert) { - const ns = 'ns-wxyz'; - await runCmd(createNS(ns), false); - await settled(); - await authPage.loginNs(ns); - // go directly to token configure route - await visit('/vault/settings/auth/configure/token/options'); - await fillIn('[data-test-input="description"]', 'My custom description'); - await click('[data-test-save-config="true"]'); - assert.strictEqual(currentURL(), '/vault/access', 'successfully saves and navigates away'); - await click('[data-test-auth-backend-link="token"]'); - assert - .dom('[data-test-row-value="Description"]') - .hasText('My custom description', 'description was saved'); - await runCmd(`delete sys/namespaces/${ns}`); + assert.dom('[data-test-auth-section-tab]').exists({ count: 1 }); + assert + .dom('[data-test-auth-section-tab]') + .hasText('Configuration', `only shows configuration tab for ${type} auth method`); + assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`); + await runCmd(deleteAuthCmd(path)); + }); + + test('token config within namespace', async function (assert) { + const ns = 'ns-wxyz'; + await runCmd(createNS(ns), false); + await settled(); + await authPage.loginNs(ns); + // go directly to token configure route + await visit('/vault/settings/auth/configure/token/options'); + await fillIn('[data-test-input="description"]', 'My custom description'); + await click('[data-test-save-config="true"]'); + assert.strictEqual(currentURL(), '/vault/access', 'successfully saves and navigates away'); + await click('[data-test-auth-backend-link="token"]'); + assert + .dom('[data-test-row-value="Description"]') + .hasText('My custom description', 'description was saved'); + await runCmd(`delete sys/namespaces/${ns}`); + }); }); }); From 3c4e0e45a3742a0ead8f31f80f5dbf867651d60c Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 12:12:45 -0500 Subject: [PATCH 19/32] Update comment --- ui/app/serializers/clients/activity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/serializers/clients/activity.js b/ui/app/serializers/clients/activity.js index 7229ed9382e0..87eda421c5e1 100644 --- a/ui/app/serializers/clients/activity.js +++ b/ui/app/serializers/clients/activity.js @@ -8,7 +8,7 @@ import { formatISO } from 'date-fns'; import { formatByMonths, formatByNamespace, destructureClientCounts } from 'core/utils/client-count-utils'; import timestamp from 'core/utils/timestamp'; -// see tests/helpers/clients for sample API response (ACTIVITY_RESPONSE_STUB) +// see tests/helpers/clients/client-count-helpers for sample API response (ACTIVITY_RESPONSE_STUB) // and transformed by_namespace and by_month examples (SERIALIZED_ACTIVITY_RESPONSE) export default class ActivitySerializer extends ApplicationSerializer { normalizeResponse(store, primaryModelClass, payload, id, requestType) { From 6a162ec58ffee3cfb2035c305d8b25b061ead918 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 12:29:25 -0500 Subject: [PATCH 20/32] revert acceptance tests only --- ui/tests/acceptance/auth-test.js | 149 +++++++----------- .../secrets/backend/generic/secret-test.js | 15 +- .../settings/auth/configure/section-test.js | 28 ++-- ui/tests/helpers/noop-all-api-requests.js | 23 +++ 4 files changed, 103 insertions(+), 112 deletions(-) create mode 100644 ui/tests/helpers/noop-all-api-requests.js diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index edd0ca9368d8..ab48fe5d339a 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -3,26 +3,40 @@ * SPDX-License-Identifier: BUSL-1.1 */ +/* eslint qunit/no-conditional-assertions: "warn" */ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; +import sinon from 'sinon'; import { click, currentURL, visit, waitUntil, find } from '@ember/test-helpers'; import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends'; import authForm from '../pages/components/auth-form'; import jwtForm from '../pages/components/auth-jwt'; import { create } from 'ember-cli-page-object'; -import { setupMirage } from 'ember-cli-mirage/test-support'; +import apiStub from 'vault/tests/helpers/noop-all-api-requests'; const component = create(authForm); const jwtComponent = create(jwtForm); module('Acceptance | auth', function (hooks) { setupApplicationTest(hooks); - setupMirage(hooks); + + hooks.beforeEach(function () { + this.clock = sinon.useFakeTimers({ + now: Date.now(), + shouldAdvanceTime: true, + }); + this.server = apiStub({ usePassthrough: true }); + }); + + hooks.afterEach(function () { + this.clock.restore(); + this.server.shutdown(); + }); test('auth query params', async function (assert) { const backends = supportedAuthBackends(); assert.expect(backends.length + 1); - await visit('/vault/auth?with=token'); + await visit('/vault/auth'); assert.strictEqual(currentURL(), '/vault/auth?with=token'); for (const backend of backends.reverse()) { await component.selectMethod(backend.type); @@ -41,102 +55,53 @@ module('Acceptance | auth', function (hooks) { assert.strictEqual(component.tokenValue, '', 'it clears the token value when toggling methods'); }); - module('it sends the right attributes when authenticating', function (hooks) { - hooks.beforeEach(function () { - this.assertReq = () => {}; - this.server.get('/auth/token/lookup-self', (schema, req) => { - this.assertReq(req); - req.passthrough(); - }); - this.server.post('/auth/github/login', (schema, req) => { - // This one is for github only - this.assertReq(req); - req.passthrough(); - }); - this.server.post('/auth/:mount/oidc/auth_url', (schema, req) => { - // For JWT and OIDC - this.assertReq(req); - req.passthrough(); - }); - this.server.post('/auth/:mount/login/:username', (schema, req) => { - this.assertReq(req); - req.passthrough(); - }); - this.expected = { - token: { - included: 'X-Vault-Token', - url: '/v1/auth/token/lookup-self', - }, - userpass: { - included: 'password', - url: '/v1/auth/userpass/login/null', - }, - ldap: { - included: 'password', - url: '/v1/auth/ldap/login/null', - }, - okta: { - included: 'password', - url: '/v1/auth/okta/login/null', - }, - jwt: { - included: 'role', - url: '/v1/auth/jwt/oidc/auth_url', - }, - oidc: { - included: 'role', - url: '/v1/auth/oidc/oidc/auth_url', - }, - radius: { - included: 'password', - url: '/v1/auth/radius/login/null', - }, - github: { - included: 'token', - url: '/v1/auth/github/login', - }, - }; - }); + test('it sends the right attributes when authenticating', async function (assert) { + assert.expect(8); + const backends = supportedAuthBackends(); + await visit('/vault/auth'); + for (const backend of backends.reverse()) { + await component.selectMethod(backend.type); + if (backend.type === 'github') { + await component.token('token'); + } + if (backend.type === 'jwt' || backend.type === 'oidc') { + await jwtComponent.role('test'); + } + await component.login(); + const lastRequest = this.server.passthroughRequests[this.server.passthroughRequests.length - 1]; + const body = JSON.parse(lastRequest.requestBody); - for (const backend of supportedAuthBackends().reverse()) { - test(`for ${backend.type}`, async function (assert) { - const { type } = backend; - const isOidc = ['jwt', 'oidc'].includes(type); - // OIDC types make 3 requests, each time the role changes - assert.expect(isOidc ? 6 : 2); - this.assertReq = (req) => { - const body = type === 'token' ? req.requestHeaders : JSON.parse(req.requestBody); - const { included, url } = this.expected[type]; - assert.ok(Object.keys(body).includes(included), `${type} includes ${included}`); - assert.strictEqual(req.url, url, `${type} calls the correct URL`); - }; - await visit('/vault/auth'); - await component.selectMethod(type); - if (type === 'github') { - await component.token('token'); - } - if (isOidc) { - await jwtComponent.role('test'); - } - await component.login(); - }); + let keys; + let included; + if (backend.type === 'token') { + keys = lastRequest.requestHeaders; + included = 'x-vault-token'; + } else if (backend.type === 'github') { + keys = body; + included = 'token'; + } else if (backend.type === 'jwt' || backend.type === 'oidc') { + const authReq = this.server.passthroughRequests[this.server.passthroughRequests.length - 2]; + keys = JSON.parse(authReq.requestBody); + included = 'role'; + } else { + keys = body; + included = 'password'; + } + assert.ok(Object.keys(keys).includes(included), `${backend.type} includes ${included}`); } }); test('it shows the push notification warning after submit', async function (assert) { assert.expect(1); - this.server.get( - '/auth/token/lookup-self', - async () => { - assert.ok( - await waitUntil(() => find('[data-test-auth-message="push"]')), - 'shows push notification message' - ); - return {}; - }, - { timing: 1000 } - ); + this.server.get('/v1/auth/token/lookup-self', async () => { + assert.ok( + await waitUntil(() => find('[data-test-auth-message="push"]')), + 'shows push notification message' + ); + return [204, { 'Content-Type': 'application/json' }, JSON.stringify({})]; + }); + await visit('/vault/auth'); await component.selectMethod('token'); await click('[data-test-auth-submit]'); diff --git a/ui/tests/acceptance/secrets/backend/generic/secret-test.js b/ui/tests/acceptance/secrets/backend/generic/secret-test.js index 70f3b19d394e..ec6a7cdbf300 100644 --- a/ui/tests/acceptance/secrets/backend/generic/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/generic/secret-test.js @@ -17,7 +17,8 @@ import { writeSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { PAGE } from 'vault/tests/helpers/kv/kv-selectors'; import { create } from 'ember-cli-page-object'; -import { deleteEngineCmd, runCmd } from 'vault/tests/helpers/commands'; + +import apiStub from 'vault/tests/helpers/noop-all-api-requests'; const cli = create(consolePanel); @@ -26,9 +27,14 @@ module('Acceptance | secrets/generic/create', function (hooks) { hooks.beforeEach(function () { this.uid = uuidv4(); + this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); + hooks.afterEach(function () { + this.server.shutdown(); + }); + test('it creates and can view a secret with the generic backend', async function (assert) { const path = `generic-${this.uid}`; const kvPath = `generic-kv-${this.uid}`; @@ -49,10 +55,6 @@ module('Acceptance | secrets/generic/create', function (hooks) { 'redirects to the show page' ); assert.ok(showPage.editIsPresent, 'shows the edit button'); - - // Clean up - await runCmd(deleteEngineCmd(path)); - await runCmd(deleteEngineCmd(kvPath)); }); test('upgrading generic to version 2 lists all existing secrets, and CRUD continues to work', async function (assert) { @@ -76,8 +78,5 @@ module('Acceptance | secrets/generic/create', function (hooks) { assert.dom(PAGE.list.item(secret.path)).exists('lists both records'); }); assert.dom(PAGE.list.item()).exists({ count: 2 }, 'lists only the two secrets'); - - // Clean up - await runCmd(deleteEngineCmd(path)); }); }); diff --git a/ui/tests/acceptance/settings/auth/configure/section-test.js b/ui/tests/acceptance/settings/auth/configure/section-test.js index 0d4c791f3ab3..2db3fde772b4 100644 --- a/ui/tests/acceptance/settings/auth/configure/section-test.js +++ b/ui/tests/acceptance/settings/auth/configure/section-test.js @@ -5,7 +5,6 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; -import { setupMirage } from 'ember-cli-mirage/test-support'; import { create } from 'ember-cli-page-object'; import { fillIn } from '@ember/test-helpers'; import { v4 as uuidv4 } from 'uuid'; @@ -13,6 +12,7 @@ import { v4 as uuidv4 } from 'uuid'; import enablePage from 'vault/tests/pages/settings/auth/enable'; import page from 'vault/tests/pages/settings/auth/configure/section'; import indexPage from 'vault/tests/pages/settings/auth/configure/index'; +import apiStub from 'vault/tests/helpers/noop-all-api-requests'; import consolePanel from 'vault/tests/pages/components/console/ui-panel'; import authPage from 'vault/tests/pages/auth'; @@ -20,24 +20,18 @@ const cli = create(consolePanel); module('Acceptance | settings/auth/configure/section', function (hooks) { setupApplicationTest(hooks); - setupMirage(hooks); hooks.beforeEach(function () { this.uid = uuidv4(); + this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); + hooks.afterEach(function () { + this.server.shutdown(); + }); + test('it can save options', async function (assert) { - assert.expect(6); - this.server.post(`/sys/mounts/auth/:path/tune`, function (schema, request) { - const body = JSON.parse(request.requestBody); - const keys = Object.keys(body); - assert.strictEqual(body.token_type, 'batch', 'passes new token type'); - assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); - assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); - assert.ok(keys.includes('description'), 'passes updated description on tune'); - request.passthrough(); - }); const path = `approle-save-${this.uid}`; const type = 'approle'; const section = 'options'; @@ -54,6 +48,16 @@ module('Acceptance | settings/auth/configure/section', function (hooks) { `The configuration was saved successfully.`, 'success flash shows' ); + const tuneRequest = this.server.passthroughRequests.filterBy( + 'url', + `/v1/sys/mounts/auth/${path}/tune` + )[0]; + const keys = Object.keys(JSON.parse(tuneRequest.requestBody)); + const token_type = JSON.parse(tuneRequest.requestBody).token_type; + assert.strictEqual(token_type, 'batch', 'passes new token type'); + assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); + assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); + assert.ok(keys.includes('description'), 'passes updated description on tune'); }); for (const type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) { diff --git a/ui/tests/helpers/noop-all-api-requests.js b/ui/tests/helpers/noop-all-api-requests.js new file mode 100644 index 000000000000..88e44034083f --- /dev/null +++ b/ui/tests/helpers/noop-all-api-requests.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Pretender from 'pretender'; +import { noopStub } from './stubs'; + +/** + * DEPRECATED prefer to use `setupMirage` along with stubs in vault/tests/helpers/stubs + */ +export default function (options = { usePassthrough: false }) { + return new Pretender(function () { + let fn = noopStub(); + if (options.usePassthrough) { + fn = this.passthrough; + } + this.post('/v1/**', fn); + this.put('/v1/**', fn); + this.get('/v1/**', fn); + this.delete('/v1/**', fn || noopStub(204)); + }); +} From e831a39330de78ef8abf5f65c0c848bc3e99cdb6 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 13:05:11 -0500 Subject: [PATCH 21/32] don't allow mutability of array returned by supportedAuthBackends --- ui/app/helpers/supported-auth-backends.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/helpers/supported-auth-backends.js b/ui/app/helpers/supported-auth-backends.js index a5e77ae28798..4c9185cf48ea 100644 --- a/ui/app/helpers/supported-auth-backends.js +++ b/ui/app/helpers/supported-auth-backends.js @@ -90,7 +90,7 @@ const ENTERPRISE_AUTH_METHODS = [ ]; export function supportedAuthBackends() { - return SUPPORTED_AUTH_BACKENDS; + return [...SUPPORTED_AUTH_BACKENDS]; } export function allSupportedAuthBackends() { From 60fad68c64e0299b019fbb7ef33caf3b5a56dedd Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 15:39:44 -0500 Subject: [PATCH 22/32] unrevert -- remove noop-all-api-requests --- ui/tests/acceptance/auth-test.js | 149 +++++++++++------- .../secrets/backend/generic/secret-test.js | 15 +- .../settings/auth/configure/section-test.js | 28 ++-- ui/tests/helpers/noop-all-api-requests.js | 23 --- 4 files changed, 112 insertions(+), 103 deletions(-) delete mode 100644 ui/tests/helpers/noop-all-api-requests.js diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index ab48fe5d339a..edd0ca9368d8 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -3,40 +3,26 @@ * SPDX-License-Identifier: BUSL-1.1 */ -/* eslint qunit/no-conditional-assertions: "warn" */ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; -import sinon from 'sinon'; import { click, currentURL, visit, waitUntil, find } from '@ember/test-helpers'; import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends'; import authForm from '../pages/components/auth-form'; import jwtForm from '../pages/components/auth-jwt'; import { create } from 'ember-cli-page-object'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { setupMirage } from 'ember-cli-mirage/test-support'; const component = create(authForm); const jwtComponent = create(jwtForm); module('Acceptance | auth', function (hooks) { setupApplicationTest(hooks); - - hooks.beforeEach(function () { - this.clock = sinon.useFakeTimers({ - now: Date.now(), - shouldAdvanceTime: true, - }); - this.server = apiStub({ usePassthrough: true }); - }); - - hooks.afterEach(function () { - this.clock.restore(); - this.server.shutdown(); - }); + setupMirage(hooks); test('auth query params', async function (assert) { const backends = supportedAuthBackends(); assert.expect(backends.length + 1); - await visit('/vault/auth'); + await visit('/vault/auth?with=token'); assert.strictEqual(currentURL(), '/vault/auth?with=token'); for (const backend of backends.reverse()) { await component.selectMethod(backend.type); @@ -55,53 +41,102 @@ module('Acceptance | auth', function (hooks) { assert.strictEqual(component.tokenValue, '', 'it clears the token value when toggling methods'); }); - test('it sends the right attributes when authenticating', async function (assert) { - assert.expect(8); - const backends = supportedAuthBackends(); - await visit('/vault/auth'); - for (const backend of backends.reverse()) { - await component.selectMethod(backend.type); - if (backend.type === 'github') { - await component.token('token'); - } - if (backend.type === 'jwt' || backend.type === 'oidc') { - await jwtComponent.role('test'); - } - await component.login(); - const lastRequest = this.server.passthroughRequests[this.server.passthroughRequests.length - 1]; - const body = JSON.parse(lastRequest.requestBody); + module('it sends the right attributes when authenticating', function (hooks) { + hooks.beforeEach(function () { + this.assertReq = () => {}; + this.server.get('/auth/token/lookup-self', (schema, req) => { + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/github/login', (schema, req) => { + // This one is for github only + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/:mount/oidc/auth_url', (schema, req) => { + // For JWT and OIDC + this.assertReq(req); + req.passthrough(); + }); + this.server.post('/auth/:mount/login/:username', (schema, req) => { + this.assertReq(req); + req.passthrough(); + }); + this.expected = { + token: { + included: 'X-Vault-Token', + url: '/v1/auth/token/lookup-self', + }, + userpass: { + included: 'password', + url: '/v1/auth/userpass/login/null', + }, + ldap: { + included: 'password', + url: '/v1/auth/ldap/login/null', + }, + okta: { + included: 'password', + url: '/v1/auth/okta/login/null', + }, + jwt: { + included: 'role', + url: '/v1/auth/jwt/oidc/auth_url', + }, + oidc: { + included: 'role', + url: '/v1/auth/oidc/oidc/auth_url', + }, + radius: { + included: 'password', + url: '/v1/auth/radius/login/null', + }, + github: { + included: 'token', + url: '/v1/auth/github/login', + }, + }; + }); - let keys; - let included; - if (backend.type === 'token') { - keys = lastRequest.requestHeaders; - included = 'x-vault-token'; - } else if (backend.type === 'github') { - keys = body; - included = 'token'; - } else if (backend.type === 'jwt' || backend.type === 'oidc') { - const authReq = this.server.passthroughRequests[this.server.passthroughRequests.length - 2]; - keys = JSON.parse(authReq.requestBody); - included = 'role'; - } else { - keys = body; - included = 'password'; - } - assert.ok(Object.keys(keys).includes(included), `${backend.type} includes ${included}`); + for (const backend of supportedAuthBackends().reverse()) { + test(`for ${backend.type}`, async function (assert) { + const { type } = backend; + const isOidc = ['jwt', 'oidc'].includes(type); + // OIDC types make 3 requests, each time the role changes + assert.expect(isOidc ? 6 : 2); + this.assertReq = (req) => { + const body = type === 'token' ? req.requestHeaders : JSON.parse(req.requestBody); + const { included, url } = this.expected[type]; + assert.ok(Object.keys(body).includes(included), `${type} includes ${included}`); + assert.strictEqual(req.url, url, `${type} calls the correct URL`); + }; + await visit('/vault/auth'); + await component.selectMethod(type); + if (type === 'github') { + await component.token('token'); + } + if (isOidc) { + await jwtComponent.role('test'); + } + await component.login(); + }); } }); test('it shows the push notification warning after submit', async function (assert) { assert.expect(1); - this.server.get('/v1/auth/token/lookup-self', async () => { - assert.ok( - await waitUntil(() => find('[data-test-auth-message="push"]')), - 'shows push notification message' - ); - return [204, { 'Content-Type': 'application/json' }, JSON.stringify({})]; - }); - + this.server.get( + '/auth/token/lookup-self', + async () => { + assert.ok( + await waitUntil(() => find('[data-test-auth-message="push"]')), + 'shows push notification message' + ); + return {}; + }, + { timing: 1000 } + ); await visit('/vault/auth'); await component.selectMethod('token'); await click('[data-test-auth-submit]'); diff --git a/ui/tests/acceptance/secrets/backend/generic/secret-test.js b/ui/tests/acceptance/secrets/backend/generic/secret-test.js index ec6a7cdbf300..70f3b19d394e 100644 --- a/ui/tests/acceptance/secrets/backend/generic/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/generic/secret-test.js @@ -17,8 +17,7 @@ import { writeSecret } from 'vault/tests/helpers/kv/kv-run-commands'; import { PAGE } from 'vault/tests/helpers/kv/kv-selectors'; import { create } from 'ember-cli-page-object'; - -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; +import { deleteEngineCmd, runCmd } from 'vault/tests/helpers/commands'; const cli = create(consolePanel); @@ -27,14 +26,9 @@ module('Acceptance | secrets/generic/create', function (hooks) { hooks.beforeEach(function () { this.uid = uuidv4(); - this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); - hooks.afterEach(function () { - this.server.shutdown(); - }); - test('it creates and can view a secret with the generic backend', async function (assert) { const path = `generic-${this.uid}`; const kvPath = `generic-kv-${this.uid}`; @@ -55,6 +49,10 @@ module('Acceptance | secrets/generic/create', function (hooks) { 'redirects to the show page' ); assert.ok(showPage.editIsPresent, 'shows the edit button'); + + // Clean up + await runCmd(deleteEngineCmd(path)); + await runCmd(deleteEngineCmd(kvPath)); }); test('upgrading generic to version 2 lists all existing secrets, and CRUD continues to work', async function (assert) { @@ -78,5 +76,8 @@ module('Acceptance | secrets/generic/create', function (hooks) { assert.dom(PAGE.list.item(secret.path)).exists('lists both records'); }); assert.dom(PAGE.list.item()).exists({ count: 2 }, 'lists only the two secrets'); + + // Clean up + await runCmd(deleteEngineCmd(path)); }); }); diff --git a/ui/tests/acceptance/settings/auth/configure/section-test.js b/ui/tests/acceptance/settings/auth/configure/section-test.js index 2db3fde772b4..0d4c791f3ab3 100644 --- a/ui/tests/acceptance/settings/auth/configure/section-test.js +++ b/ui/tests/acceptance/settings/auth/configure/section-test.js @@ -5,6 +5,7 @@ import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; import { create } from 'ember-cli-page-object'; import { fillIn } from '@ember/test-helpers'; import { v4 as uuidv4 } from 'uuid'; @@ -12,7 +13,6 @@ import { v4 as uuidv4 } from 'uuid'; import enablePage from 'vault/tests/pages/settings/auth/enable'; import page from 'vault/tests/pages/settings/auth/configure/section'; import indexPage from 'vault/tests/pages/settings/auth/configure/index'; -import apiStub from 'vault/tests/helpers/noop-all-api-requests'; import consolePanel from 'vault/tests/pages/components/console/ui-panel'; import authPage from 'vault/tests/pages/auth'; @@ -20,18 +20,24 @@ const cli = create(consolePanel); module('Acceptance | settings/auth/configure/section', function (hooks) { setupApplicationTest(hooks); + setupMirage(hooks); hooks.beforeEach(function () { this.uid = uuidv4(); - this.server = apiStub({ usePassthrough: true }); return authPage.login(); }); - hooks.afterEach(function () { - this.server.shutdown(); - }); - test('it can save options', async function (assert) { + assert.expect(6); + this.server.post(`/sys/mounts/auth/:path/tune`, function (schema, request) { + const body = JSON.parse(request.requestBody); + const keys = Object.keys(body); + assert.strictEqual(body.token_type, 'batch', 'passes new token type'); + assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); + assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); + assert.ok(keys.includes('description'), 'passes updated description on tune'); + request.passthrough(); + }); const path = `approle-save-${this.uid}`; const type = 'approle'; const section = 'options'; @@ -48,16 +54,6 @@ module('Acceptance | settings/auth/configure/section', function (hooks) { `The configuration was saved successfully.`, 'success flash shows' ); - const tuneRequest = this.server.passthroughRequests.filterBy( - 'url', - `/v1/sys/mounts/auth/${path}/tune` - )[0]; - const keys = Object.keys(JSON.parse(tuneRequest.requestBody)); - const token_type = JSON.parse(tuneRequest.requestBody).token_type; - assert.strictEqual(token_type, 'batch', 'passes new token type'); - assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); - assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); - assert.ok(keys.includes('description'), 'passes updated description on tune'); }); for (const type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) { diff --git a/ui/tests/helpers/noop-all-api-requests.js b/ui/tests/helpers/noop-all-api-requests.js deleted file mode 100644 index 88e44034083f..000000000000 --- a/ui/tests/helpers/noop-all-api-requests.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import Pretender from 'pretender'; -import { noopStub } from './stubs'; - -/** - * DEPRECATED prefer to use `setupMirage` along with stubs in vault/tests/helpers/stubs - */ -export default function (options = { usePassthrough: false }) { - return new Pretender(function () { - let fn = noopStub(); - if (options.usePassthrough) { - fn = this.passthrough; - } - this.post('/v1/**', fn); - this.put('/v1/**', fn); - this.get('/v1/**', fn); - this.delete('/v1/**', fn || noopStub(204)); - }); -} From fea667e48b3da06ca3064acbf102d9a3bb868b4f Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Thu, 4 Apr 2024 15:40:23 -0500 Subject: [PATCH 23/32] remove hardcoded ?with param --- ui/tests/acceptance/auth-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index edd0ca9368d8..e23f3ab0551f 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -22,7 +22,7 @@ module('Acceptance | auth', function (hooks) { test('auth query params', async function (assert) { const backends = supportedAuthBackends(); assert.expect(backends.length + 1); - await visit('/vault/auth?with=token'); + await visit('/vault/auth'); assert.strictEqual(currentURL(), '/vault/auth?with=token'); for (const backend of backends.reverse()) { await component.selectMethod(backend.type); From 007d766c8d4020a69b6acf6297a3434ff67a018d Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:55:10 -0500 Subject: [PATCH 24/32] Update ui/tests/_README.md Co-authored-by: Noelle Daley --- ui/tests/_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/_README.md b/ui/tests/_README.md index a102b3a798aa..64c15624b568 100644 --- a/ui/tests/_README.md +++ b/ui/tests/_README.md @@ -1,6 +1,6 @@ # Test Helpers Organization -Our test are constantly evolving, but here's a general overview of how the tests and selectors organization +Our test are constantly evolving, but here's a general overview of how we set up and organize tests. ## Folder organization From 867946ef394b43cf3c591b7c4209e04b429699ff Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:55:24 -0500 Subject: [PATCH 25/32] Update ui/tests/acceptance/auth-list-test.js Co-authored-by: Noelle Daley --- ui/tests/acceptance/auth-list-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/acceptance/auth-list-test.js b/ui/tests/acceptance/auth-list-test.js index 5d6dbfc0b2d3..2f11fffc488d 100644 --- a/ui/tests/acceptance/auth-list-test.js +++ b/ui/tests/acceptance/auth-list-test.js @@ -109,7 +109,7 @@ module('Acceptance | auth backend list', function (hooks) { assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`); } else { let expectedTabs = 2; - if (type == 'ldap' || type === 'okta') { + if (type === 'ldap' || type === 'okta') { expectedTabs = 3; } assert From 9c061fa4176910300a2216dc5c21c6778da07acb Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:56:07 -0500 Subject: [PATCH 26/32] Update ui/tests/acceptance/auth-test.js Co-authored-by: Noelle Daley --- ui/tests/acceptance/auth-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/acceptance/auth-test.js b/ui/tests/acceptance/auth-test.js index e23f3ab0551f..c0f8c6d1aca7 100644 --- a/ui/tests/acceptance/auth-test.js +++ b/ui/tests/acceptance/auth-test.js @@ -107,7 +107,7 @@ module('Acceptance | auth', function (hooks) { this.assertReq = (req) => { const body = type === 'token' ? req.requestHeaders : JSON.parse(req.requestBody); const { included, url } = this.expected[type]; - assert.ok(Object.keys(body).includes(included), `${type} includes ${included}`); + assert.true(Object.keys(body).includes(included), `${type} includes ${included}`); assert.strictEqual(req.url, url, `${type} calls the correct URL`); }; await visit('/vault/auth'); From cf6349a866449ad9932b86f008cad6358011bfca Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:56:36 -0500 Subject: [PATCH 27/32] Update ui/tests/acceptance/settings/auth/configure/section-test.js Co-authored-by: Noelle Daley --- ui/tests/acceptance/settings/auth/configure/section-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/tests/acceptance/settings/auth/configure/section-test.js b/ui/tests/acceptance/settings/auth/configure/section-test.js index 0d4c791f3ab3..318333a8962c 100644 --- a/ui/tests/acceptance/settings/auth/configure/section-test.js +++ b/ui/tests/acceptance/settings/auth/configure/section-test.js @@ -33,9 +33,9 @@ module('Acceptance | settings/auth/configure/section', function (hooks) { const body = JSON.parse(request.requestBody); const keys = Object.keys(body); assert.strictEqual(body.token_type, 'batch', 'passes new token type'); - assert.ok(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); - assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); - assert.ok(keys.includes('description'), 'passes updated description on tune'); + assert.true(keys.includes('default_lease_ttl'), 'passes default_lease_ttl on tune'); + assert.true(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); + assert.true(keys.includes('description'), 'passes updated description on tune'); request.passthrough(); }); const path = `approle-save-${this.uid}`; From 4839315b19c1ff5efbbd5c17083b46a42ff3b273 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:57:04 -0500 Subject: [PATCH 28/32] Update ui/tests/unit/adapters/identity/entity-test.js Co-authored-by: Noelle Daley --- ui/tests/unit/adapters/identity/entity-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/unit/adapters/identity/entity-test.js b/ui/tests/unit/adapters/identity/entity-test.js index dcfdfa7eb21e..2e99666ae482 100644 --- a/ui/tests/unit/adapters/identity/entity-test.js +++ b/ui/tests/unit/adapters/identity/entity-test.js @@ -22,7 +22,7 @@ module('Unit | Adapter | identity/entity', function (hooks) { const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); - assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); + assert.strictEqual(req.method, testCase.method, `uses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; }); From a8a538ba2888eb6c77cbea8469cbfacba71b738f Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:57:17 -0500 Subject: [PATCH 29/32] Update ui/tests/unit/adapters/identity/entity-alias-test.js Co-authored-by: Noelle Daley --- ui/tests/unit/adapters/identity/entity-alias-test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/tests/unit/adapters/identity/entity-alias-test.js b/ui/tests/unit/adapters/identity/entity-alias-test.js index f51b3fd6d53c..5c49101486cb 100644 --- a/ui/tests/unit/adapters/identity/entity-alias-test.js +++ b/ui/tests/unit/adapters/identity/entity-alias-test.js @@ -21,7 +21,11 @@ module('Unit | Adapter | identity/entity-alias', function (hooks) { const url = testCase.url.replace('/v1', '').split('?')[0]; const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { - assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.strictEqual( + url, + testCase.url, + `${testCase.adapterMethod} calls the correct url: ${testCase.url}` + ); assert.strictEqual(req.method, testCase.method, `uses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; From 1bc3047835785f7d452ee028a2b9db2aa7709bca Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Wed, 10 Apr 2024 09:02:05 -0500 Subject: [PATCH 30/32] replace CLIENT_COUNT as ts in tests --- ui/tests/acceptance/clients/counts-test.js | 6 +- .../components/clients/page/counts-test.js | 58 ++++++++++--------- .../components/clients/page/token-test.js | 58 +++++++++++-------- .../components/clients/running-total-test.js | 42 +++++++------- 4 files changed, 89 insertions(+), 75 deletions(-) diff --git a/ui/tests/acceptance/clients/counts-test.js b/ui/tests/acceptance/clients/counts-test.js index 348470fd18b4..3724f10f45b4 100644 --- a/ui/tests/acceptance/clients/counts-test.js +++ b/ui/tests/acceptance/clients/counts-test.js @@ -11,7 +11,7 @@ import sinon from 'sinon'; import { visit, click, currentURL } from '@ember/test-helpers'; import authPage from 'vault/tests/pages/auth'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; import timestamp from 'core/utils/timestamp'; module('Acceptance | clients | counts', function (hooks) { @@ -48,8 +48,8 @@ module('Acceptance | clients | counts', function (hooks) { test('it should persist filter query params between child routes', async function (assert) { await visit('/vault/clients/counts/overview'); - await click(ts.rangeDropdown); - await click(ts.currentBillingPeriod); + await click(CLIENT_COUNT.rangeDropdown); + await click(CLIENT_COUNT.currentBillingPeriod); const timeQueryRegex = /end_time=\d+&start_time=\d+/g; assert.ok(currentURL().match(timeQueryRegex).length, 'Start and end times added as query params'); diff --git a/ui/tests/integration/components/clients/page/counts-test.js b/ui/tests/integration/components/clients/page/counts-test.js index e570f037a1a0..328a1467e955 100644 --- a/ui/tests/integration/components/clients/page/counts-test.js +++ b/ui/tests/integration/components/clients/page/counts-test.js @@ -11,7 +11,7 @@ import hbs from 'htmlbars-inline-precompile'; import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients'; import { getUnixTime } from 'date-fns'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts, dateDropdownSelect } from 'vault/tests/helpers/clients/client-count-helpers'; +import { CLIENT_COUNT, dateDropdownSelect } from 'vault/tests/helpers/clients/client-count-helpers'; import { selectChoose } from 'ember-power-select/test-support/helpers'; import timestamp from 'core/utils/timestamp'; import sinon from 'sinon'; @@ -65,9 +65,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); - assert.dom(ts.counts.startLabel).hasText('Client counting start date', 'Label renders for OSS'); + assert.dom(CLIENT_COUNT.counts.startLabel).hasText('Client counting start date', 'Label renders for OSS'); assert - .dom(ts.counts.description) + .dom(CLIENT_COUNT.counts.description) .hasText( 'This date is when client counting starts. Without this starting point, the data shown is not reliable.', 'Description renders for OSS' @@ -76,9 +76,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { versionService.set('type', 'enterprise'); await settled(); - assert.dom(ts.counts.startLabel).hasText('Billing start month', 'Label renders for Enterprise'); + assert.dom(CLIENT_COUNT.counts.startLabel).hasText('Billing start month', 'Label renders for Enterprise'); assert - .dom(ts.counts.description) + .dom(CLIENT_COUNT.counts.description) .hasText( 'This date comes from your license, and defines when client counting starts. Without this starting point, the data shown is not reliable.', 'Description renders for Enterprise' @@ -88,9 +88,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { test('it should populate start and end month displays', async function (assert) { await this.renderComponent(); - assert.dom(ts.counts.startMonth).hasText('July 2023', 'Start month renders'); + assert.dom(CLIENT_COUNT.counts.startMonth).hasText('July 2023', 'Start month renders'); assert - .dom(ts.calendarWidget.trigger) + .dom(CLIENT_COUNT.calendarWidget.trigger) .hasText('Jul 2023 - Jan 2024', 'Start and end months render in filter bar'); }); @@ -120,7 +120,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); - assert.dom(ts.counts.configDisabled).hasText('Tracking is disabled', 'Config disabled alert renders'); + assert + .dom(CLIENT_COUNT.counts.configDisabled) + .hasText('Tracking is disabled', 'Config disabled alert renders'); }); test('it should send correct values on start and end date change', async function (assert) { @@ -137,18 +139,18 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await dateDropdownSelect('January', '2023'); expected.start_time = END_TIME; - await click(ts.calendarWidget.trigger); - await click(ts.calendarWidget.currentMonth); + await click(CLIENT_COUNT.calendarWidget.trigger); + await click(CLIENT_COUNT.calendarWidget.currentMonth); expected.start_time = getUnixTime(this.config.billingStartTimestamp); - await click(ts.calendarWidget.trigger); - await click(ts.calendarWidget.currentBillingPeriod); + await click(CLIENT_COUNT.calendarWidget.trigger); + await click(CLIENT_COUNT.calendarWidget.currentBillingPeriod); expected = { end_time: getUnixTime(new Date('2023-12-31T00:00:00Z')) }; - await click(ts.calendarWidget.trigger); - await click(ts.calendarWidget.customEndMonth); - await click(ts.calendarWidget.previousYear); - await click(ts.calendarWidget.calendarMonth('December')); + await click(CLIENT_COUNT.calendarWidget.trigger); + await click(CLIENT_COUNT.calendarWidget.customEndMonth); + await click(CLIENT_COUNT.calendarWidget.previousYear); + await click(CLIENT_COUNT.calendarWidget.calendarMonth('December')); }); test('it should render namespace and auth mount filters', async function (assert) { @@ -170,21 +172,21 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); - assert.dom(ts.counts.namespaces).includesText(this.namespace, 'Selected namespace renders'); - assert.dom(ts.counts.mountPaths).includesText(this.mountPath, 'Selected auth mount renders'); + assert.dom(CLIENT_COUNT.counts.namespaces).includesText(this.namespace, 'Selected namespace renders'); + assert.dom(CLIENT_COUNT.counts.mountPaths).includesText(this.mountPath, 'Selected auth mount renders'); - await click(`${ts.counts.namespaces} button`); + await click(`${CLIENT_COUNT.counts.namespaces} button`); // this is only necessary in tests since SearchSelect does not respond to initialValue changes // in the app the component is rerender on query param change assertion = null; - await click(`${ts.counts.mountPaths} button`); + await click(`${CLIENT_COUNT.counts.mountPaths} button`); assertion = (params) => assert.true(params.ns.includes('ns/'), 'Namespace value sent on change'); - await selectChoose(ts.counts.namespaces, '.ember-power-select-option', 0); + await selectChoose(CLIENT_COUNT.counts.namespaces, '.ember-power-select-option', 0); assertion = (params) => assert.true(params.mountPath.includes('auth/'), 'Auth mount value sent on change'); - await selectChoose(ts.counts.mountPaths, 'auth/authid0'); + await selectChoose(CLIENT_COUNT.counts.mountPaths, 'auth/authid0'); }); test('it should render start time discrepancy alert', async function (assert) { @@ -193,7 +195,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); assert - .dom(ts.counts.startDiscrepancy) + .dom(CLIENT_COUNT.counts.startDiscrepancy) .hasText( 'You requested data from June 2022. We only have data from July 2023, and that is what is being shown here.', 'Start discrepancy alert renders' @@ -215,18 +217,18 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); assert - .dom(ts.upgradeWarning) + .dom(CLIENT_COUNT.upgradeWarning) .hasTextContaining( `Client count data contains 2 upgrades Vault was upgraded during this time period. Keep this in mind while looking at the data. Visit our Client count FAQ for more information.`, 'it renders title and subtext' ); assert - .dom(`${ts.upgradeWarning} ul`) + .dom(`${CLIENT_COUNT.upgradeWarning} ul`) .doesNotHaveTextContaining( '1.9.1', 'Warning does not include subsequent patch releases (e.g. 1.9.1) of the same notable upgrade.' ); - const [first, second] = findAll(`${ts.upgradeWarning} li`); + const [first, second] = findAll(`${CLIENT_COUNT.upgradeWarning} li`); assert .dom(first) .hasText( @@ -250,7 +252,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) { await this.renderComponent(); assert.dom(GENERAL.emptyStateTitle).hasText('No start date found', 'Empty state renders'); - assert.dom(ts.counts.startDropdown).exists('Date dropdown renders when start time is not provided'); + assert + .dom(CLIENT_COUNT.counts.startDropdown) + .exists('Date dropdown renders when start time is not provided'); }); test('it should render catch all empty state', async function (assert) { diff --git a/ui/tests/integration/components/clients/page/token-test.js b/ui/tests/integration/components/clients/page/token-test.js index 873d7ea6a900..2f90adc12f20 100644 --- a/ui/tests/integration/components/clients/page/token-test.js +++ b/ui/tests/integration/components/clients/page/token-test.js @@ -14,7 +14,7 @@ import { calculateAverage } from 'vault/utils/chart-helpers'; import { formatNumber } from 'core/helpers/format-number'; import { dateFormat } from 'core/helpers/date-format'; import { GENERAL } from 'vault/tests/helpers/general-selectors'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; const START_TIME = getUnixTime(LICENSE_START); const END_TIME = getUnixTime(STATIC_NOW); @@ -68,18 +68,18 @@ module('Integration | Component | clients | Page::Token', function (hooks) { }; const expectedTotal = getAverage(this.activity.byMonth); const expectedNew = getAverage(this.newActivity); - const chart = ts.charts.chart('monthly total'); + const chart = CLIENT_COUNT.charts.chart('monthly total'); await this.renderComponent(); assert - .dom(ts.charts.statTextValue('Average total clients per month')) + .dom(CLIENT_COUNT.charts.statTextValue('Average total clients per month')) .hasText(expectedTotal, 'renders correct total clients'); assert - .dom(ts.charts.statTextValue('Average new clients per month')) + .dom(CLIENT_COUNT.charts.statTextValue('Average new clients per month')) .hasText(expectedNew, 'renders correct new clients'); // assert bar chart is correct - findAll(`${chart} ${ts.charts.bar.xAxisLabel}`).forEach((e, i) => { + findAll(`${chart} ${CLIENT_COUNT.charts.bar.xAxisLabel}`).forEach((e, i) => { assert .dom(e) .hasText( @@ -88,7 +88,7 @@ module('Integration | Component | clients | Page::Token', function (hooks) { ); }); assert - .dom(`${chart} ${ts.charts.bar.dataBar}`) + .dom(`${chart} ${CLIENT_COUNT.charts.bar.dataBar}`) .exists( { count: this.activity.byMonth.filter((m) => m.clients).length * 2 }, 'renders two stacked data bars of entity/non-entity clients for each month' @@ -97,27 +97,31 @@ module('Integration | Component | clients | Page::Token', function (hooks) { withTimeZone: true, }); assert - .dom(`${chart} ${ts.charts.timestamp}`) + .dom(`${chart} ${CLIENT_COUNT.charts.timestamp}`) .hasText(`Updated ${formattedTimestamp}`, 'renders timestamp'); - assert.dom(`${chart} ${ts.charts.legendLabel(1)}`).hasText('Entity clients', 'Legend label renders'); - assert.dom(`${chart} ${ts.charts.legendLabel(2)}`).hasText('Non-entity clients', 'Legend label renders'); + assert + .dom(`${chart} ${CLIENT_COUNT.charts.legendLabel(1)}`) + .hasText('Entity clients', 'Legend label renders'); + assert + .dom(`${chart} ${CLIENT_COUNT.charts.legendLabel(2)}`) + .hasText('Non-entity clients', 'Legend label renders'); }); test('it should render monthly new chart', async function (assert) { const expectedNewEntity = formatNumber([calculateAverage(this.newActivity, 'entity_clients')]); const expectedNewNonEntity = formatNumber([calculateAverage(this.newActivity, 'non_entity_clients')]); - const chart = ts.charts.chart('monthly new'); + const chart = CLIENT_COUNT.charts.chart('monthly new'); await this.renderComponent(); assert - .dom(ts.charts.statTextValue('Average new entity clients per month')) + .dom(CLIENT_COUNT.charts.statTextValue('Average new entity clients per month')) .hasText(expectedNewEntity, 'renders correct new entity clients'); assert - .dom(ts.charts.statTextValue('Average new non-entity clients per month')) + .dom(CLIENT_COUNT.charts.statTextValue('Average new non-entity clients per month')) .hasText(expectedNewNonEntity, 'renders correct new nonentity clients'); // assert bar chart is correct - findAll(`${chart} ${ts.charts.bar.xAxisLabel}`).forEach((e, i) => { + findAll(`${chart} ${CLIENT_COUNT.charts.bar.xAxisLabel}`).forEach((e, i) => { assert .dom(e) .hasText( @@ -126,7 +130,7 @@ module('Integration | Component | clients | Page::Token', function (hooks) { ); }); assert - .dom(`${chart} ${ts.charts.bar.dataBar}`) + .dom(`${chart} ${CLIENT_COUNT.charts.bar.dataBar}`) .exists( { count: this.activity.byMonth.filter((m) => m.clients).length * 2 }, 'renders two stacked bars of new entity/non-entity clients for each month' @@ -135,10 +139,14 @@ module('Integration | Component | clients | Page::Token', function (hooks) { withTimeZone: true, }); assert - .dom(`${chart} ${ts.charts.timestamp}`) + .dom(`${chart} ${CLIENT_COUNT.charts.timestamp}`) .hasText(`Updated ${formattedTimestamp}`, 'renders timestamp'); - assert.dom(`${chart} ${ts.charts.legendLabel(1)}`).hasText('Entity clients', 'Legend label renders'); - assert.dom(`${chart} ${ts.charts.legendLabel(2)}`).hasText('Non-entity clients', 'Legend label renders'); + assert + .dom(`${chart} ${CLIENT_COUNT.charts.legendLabel(1)}`) + .hasText('Entity clients', 'Legend label renders'); + assert + .dom(`${chart} ${CLIENT_COUNT.charts.legendLabel(2)}`) + .hasText('Non-entity clients', 'Legend label renders'); }); test('it should render empty state for no new monthly data', async function (assert) { @@ -146,15 +154,15 @@ module('Integration | Component | clients | Page::Token', function (hooks) { ...d, new_clients: { month: d.month }, })); - const chart = ts.charts.chart('monthly-new'); + const chart = CLIENT_COUNT.charts.chart('monthly-new'); await this.renderComponent(); - assert.dom(`${chart} ${ts.charts.verticalBar}`).doesNotExist('Chart does not render'); - assert.dom(`${chart} ${ts.charts.legend}`).doesNotExist('Legend does not render'); + assert.dom(`${chart} ${CLIENT_COUNT.charts.verticalBar}`).doesNotExist('Chart does not render'); + assert.dom(`${chart} ${CLIENT_COUNT.charts.legend}`).doesNotExist('Legend does not render'); assert.dom(GENERAL.emptyStateTitle).hasText('No new clients'); - assert.dom(ts.tokenTab.entity).doesNotExist('New client counts does not exist'); - assert.dom(ts.tokenTab.nonentity).doesNotExist('Average new client counts does not exist'); + assert.dom(CLIENT_COUNT.tokenTab.entity).doesNotExist('New client counts does not exist'); + assert.dom(CLIENT_COUNT.tokenTab.nonentity).doesNotExist('Average new client counts does not exist'); }); test('it should render usage stats', async function (assert) { @@ -167,13 +175,13 @@ module('Integration | Component | clients | Page::Token', function (hooks) { const checkUsage = () => { assert - .dom(ts.charts.statTextValue('Total clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Total clients')) .hasText(formatNumber([entity_clients + non_entity_clients]), 'Total clients value renders'); assert - .dom(ts.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .hasText(formatNumber([entity_clients]), 'Entity clients value renders'); assert - .dom(ts.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .hasText(formatNumber([non_entity_clients]), 'Non-entity clients value renders'); }; diff --git a/ui/tests/integration/components/clients/running-total-test.js b/ui/tests/integration/components/clients/running-total-test.js index aa31035c6438..90e4617afffc 100644 --- a/ui/tests/integration/components/clients/running-total-test.js +++ b/ui/tests/integration/components/clients/running-total-test.js @@ -15,7 +15,7 @@ import { findAll } from '@ember/test-helpers'; import { formatNumber } from 'core/helpers/format-number'; import timestamp from 'core/utils/timestamp'; import { setRunOptions } from 'ember-a11y-testing/test-support'; -import { CLIENT_COUNT as ts } from 'vault/tests/helpers/clients/client-count-helpers'; +import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-helpers'; const START_TIME = getUnixTime(LICENSE_START); @@ -77,23 +77,23 @@ module('Integration | Component | clients/running-total', function (hooks) { await this.renderComponent(); - assert.dom(ts.charts.chart('running total')).exists('running total component renders'); - assert.dom(ts.charts.lineChart).exists('line chart renders'); + assert.dom(CLIENT_COUNT.charts.chart('running total')).exists('running total component renders'); + assert.dom(CLIENT_COUNT.charts.lineChart).exists('line chart renders'); assert - .dom(ts.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .hasText(`${expectedTotalEntity}`, `renders correct total entity average ${expectedTotalEntity}`); assert - .dom(ts.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .hasText( `${expectedTotalNonEntity}`, `renders correct total nonentity average ${expectedTotalNonEntity}` ); assert - .dom(ts.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .hasText(`${expectedTotalSync}`, `renders correct total sync ${expectedTotalSync}`); // assert line chart is correct - findAll(ts.charts.line.xAxisLabel).forEach((e, i) => { + findAll(CLIENT_COUNT.charts.line.xAxisLabel).forEach((e, i) => { assert .dom(e) .hasText( @@ -102,7 +102,7 @@ module('Integration | Component | clients/running-total', function (hooks) { ); }); assert - .dom(ts.charts.line.plotPoint) + .dom(CLIENT_COUNT.charts.line.plotPoint) .exists( { count: this.byMonthActivity.filter((m) => m.clients).length }, 'renders correct number of plot points' @@ -121,20 +121,20 @@ module('Integration | Component | clients/running-total', function (hooks) { await this.renderComponent(); - assert.dom(ts.charts.chart('running total')).exists('running total component renders'); - assert.dom(ts.charts.lineChart).exists('line chart renders'); + assert.dom(CLIENT_COUNT.charts.chart('running total')).exists('running total component renders'); + assert.dom(CLIENT_COUNT.charts.lineChart).exists('line chart renders'); assert - .dom(ts.charts.statTextValue('Entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Entity clients')) .hasText(`${expectedTotalEntity}`, `renders correct total entity average ${expectedTotalEntity}`); assert - .dom(ts.charts.statTextValue('Non-entity clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')) .hasText( `${expectedTotalNonEntity}`, `renders correct total nonentity average ${expectedTotalNonEntity}` ); assert - .dom(ts.charts.statTextValue('Secrets sync clients')) + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) .hasText(`${expectedTotalSync}`, `renders correct total sync ${expectedTotalSync}`); }); @@ -150,14 +150,14 @@ module('Integration | Component | clients/running-total', function (hooks) { const expectedNewEntity = formatNumber([singleMonthNew.entity_clients]); const expectedNewNonEntity = formatNumber([singleMonthNew.non_entity_clients]); const expectedNewSyncs = formatNumber([singleMonthNew.secret_syncs]); - const { statTextValue } = ts.charts; + const { statTextValue } = CLIENT_COUNT.charts; this.byMonthActivity = [singleMonth]; this.isHistoricalMonth = true; await this.renderComponent(); - assert.dom(ts.charts.lineChart).doesNotExist('line chart does not render'); + assert.dom(CLIENT_COUNT.charts.lineChart).doesNotExist('line chart does not render'); assert.dom(statTextValue()).exists({ count: 8 }, 'renders 6 stat text containers'); assert .dom(`[data-test-new] ${statTextValue('New clients')}`) @@ -190,10 +190,12 @@ module('Integration | Component | clients/running-total', function (hooks) { await this.renderComponent(); - assert.dom(ts.charts.chart('running total')).exists('running total component renders'); - assert.dom(ts.charts.lineChart).exists('line chart renders'); - assert.dom(ts.charts.statTextValue('Entity clients')).exists(); - assert.dom(ts.charts.statTextValue('Non-entity clients')).exists(); - assert.dom(ts.charts.statTextValue('Secrets sync clients')).doesNotExist('does not render secret syncs'); + assert.dom(CLIENT_COUNT.charts.chart('running total')).exists('running total component renders'); + assert.dom(CLIENT_COUNT.charts.lineChart).exists('line chart renders'); + assert.dom(CLIENT_COUNT.charts.statTextValue('Entity clients')).exists(); + assert.dom(CLIENT_COUNT.charts.statTextValue('Non-entity clients')).exists(); + assert + .dom(CLIENT_COUNT.charts.statTextValue('Secrets sync clients')) + .doesNotExist('does not render secret syncs'); }); }); From b10ed461deb2481f63a649e59fd0ff087b282596 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Wed, 10 Apr 2024 09:08:10 -0500 Subject: [PATCH 31/32] update assertions --- ui/tests/unit/adapters/identity/entity-alias-test.js | 9 ++++----- ui/tests/unit/adapters/identity/entity-test.js | 5 ++++- ui/tests/unit/adapters/identity/group-alias-test.js | 5 ++++- ui/tests/unit/adapters/identity/group-test.js | 5 ++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ui/tests/unit/adapters/identity/entity-alias-test.js b/ui/tests/unit/adapters/identity/entity-alias-test.js index 5c49101486cb..5b0b5a9c0590 100644 --- a/ui/tests/unit/adapters/identity/entity-alias-test.js +++ b/ui/tests/unit/adapters/identity/entity-alias-test.js @@ -21,11 +21,10 @@ module('Unit | Adapter | identity/entity-alias', function (hooks) { const url = testCase.url.replace('/v1', '').split('?')[0]; const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { - assert.strictEqual( - url, - testCase.url, - `${testCase.adapterMethod} calls the correct url: ${testCase.url}` - ); + assert.true( + testCase.url.includes(url), + `${testCase.adapterMethod} calls the correct url: ${testCase.url}` + ); assert.strictEqual(req.method, testCase.method, `uses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; diff --git a/ui/tests/unit/adapters/identity/entity-test.js b/ui/tests/unit/adapters/identity/entity-test.js index 2e99666ae482..6857dc86f6a2 100644 --- a/ui/tests/unit/adapters/identity/entity-test.js +++ b/ui/tests/unit/adapters/identity/entity-test.js @@ -21,7 +21,10 @@ module('Unit | Adapter | identity/entity', function (hooks) { const url = testCase.url.replace('/v1', '').split('?')[0]; const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { - assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.true( + testCase.url.includes(url), + `${testCase.adapterMethod} calls the correct url: ${testCase.url}` + ); assert.strictEqual(req.method, testCase.method, `uses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; diff --git a/ui/tests/unit/adapters/identity/group-alias-test.js b/ui/tests/unit/adapters/identity/group-alias-test.js index 843735fee9de..d4d537184e8b 100644 --- a/ui/tests/unit/adapters/identity/group-alias-test.js +++ b/ui/tests/unit/adapters/identity/group-alias-test.js @@ -21,7 +21,10 @@ module('Unit | Adapter | identity/group-alias', function (hooks) { const url = testCase.url.replace('/v1', '').split('?')[0]; const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { - assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.true( + testCase.url.includes(url), + `${testCase.adapterMethod} calls the correct url: ${testCase.url}` + ); assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; diff --git a/ui/tests/unit/adapters/identity/group-test.js b/ui/tests/unit/adapters/identity/group-test.js index 3ec14ed22ca0..34c237a3a903 100644 --- a/ui/tests/unit/adapters/identity/group-test.js +++ b/ui/tests/unit/adapters/identity/group-test.js @@ -21,7 +21,10 @@ module('Unit | Adapter | identity/group', function (hooks) { const url = testCase.url.replace('/v1', '').split('?')[0]; const queryParams = testCase.url.includes('?list=true') ? { list: 'true' } : {}; this.server[method](url, (schema, req) => { - assert.ok(true, `${testCase.adapterMethod} calls the correct url with: ${testCase.url}`); + assert.true( + testCase.url.includes(url), + `${testCase.adapterMethod} calls the correct url: ${testCase.url}` + ); assert.strictEqual(req.method, testCase.method, `usses the correct http verb: ${testCase.method}`); assert.deepEqual(req.queryParams, queryParams, 'calls with correct query params'); return {}; From 48aec94f53c301b8cfb0744f90893d89efef803f Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Wed, 10 Apr 2024 09:21:50 -0500 Subject: [PATCH 32/32] move readme to docs --- ui/docs/tests.md | 35 +++++++++++++++++++++++++++++++++++ ui/tests/_README.md | 27 --------------------------- 2 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 ui/docs/tests.md delete mode 100644 ui/tests/_README.md diff --git a/ui/docs/tests.md b/ui/docs/tests.md new file mode 100644 index 000000000000..5ba7f8674d8d --- /dev/null +++ b/ui/docs/tests.md @@ -0,0 +1,35 @@ +# Test Helpers Organization + +Our test are constantly evolving, but here's a general overview of how we set up and organize tests. + +## Folder organization + +### /acceptance + +Acceptance tests should test the overall workflows and navigation within Vault. When possible, they should use the real API instead of mocked so that breaking changes from the backend can be caught. Reasons you may opt to use a mocked backend instead of the real one: + +- Using the real backend would cause instability in concurrently-running tests (eg. seal/unseal flow) +- There isn't a way to set up a 3rd party dependency that the backend needs to run correctly (Database Secrets Engine, Sync Secrets) + +### /helpers + +Shared helpers such as selectors, common interactions, WebREPL commands, and API response stubs live in this folder. When selectors are only used for a single test, they should be defined on the same file where they are used for the test. Once the selectors are being used for multiple tests, they should be moved to this folder so they can be defined in a single place and shared to wherever they are needed. + +Often we will need a set of selectors for "workflow" tests, or acceptance tests that navigate through an area of the app. For these, the helpers should be organized as such: + +- `/helpers//-selectors.ts` - exports selector consts (never default) for each page -- eg. for PKI we would have PKI_OVERVIEW, PKI_ROLE, etc. +- `/helpers//-interactions.js` - exports methods and consts which are otherwise helpful in the tests -- eg. example API responses, common interactions (eg. writeVersionedSecret for KV v2) + +Whenever possible we should try to use the general selectors exported from `/helpers/general-selectors.ts`. + +### integration + +Integration tests are most often used to test specific components out of context from the rest of the app. Be sure to mock anything that the component needs to work correctly -- for example, if the component has a certain behavior in enterprise than community edition, in your tests for each scenario it should not assume that the underlying Vault binary is in one state or the other, and mock the enterprise/community state in all the scenarios. The exports in `helpers/stubs.js` might be helpful for these tests, particularly when the component uses a model which fetches capabilities. + +### pages + +[DEPRECATED] This file should be removed in favor of selectors within the "helpers" folder. We are moving away from ember-page-object selectors toward simple strings + +### unit + +Unit tests are most often used to test utils, adapters, serializers, routes, and services functionality. diff --git a/ui/tests/_README.md b/ui/tests/_README.md deleted file mode 100644 index 64c15624b568..000000000000 --- a/ui/tests/_README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Test Helpers Organization - -Our test are constantly evolving, but here's a general overview of how we set up and organize tests. - -## Folder organization - -### acceptance - -Acceptance tests should test the overall workflows and navigation within Vault. When possible, they should use the real API instead of mocked so that breaking changes from the backend can be caught. Reasons you may opt to use a mocked backend instead of the real one: - -- Using the real backend would cause instability in concurrently-running tests (eg. seal/unseal flow) -- There isn't a way to set up a 3rd party dependency that the backend needs to run correctly (Database Secrets Engine, Sync Secrets) - -### helpers - -### integration - -### pages - -[DEPRECATED] This file should be removed in favor of selectors within the "helpers" folder - -### unit - -## Process - -- Rename export from `general-selectors` to `GENERAL` --