mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-26 00:51:08 +02:00
* increase bar width, show new clients only, add timestamp to header, update bar color * remove extra timestamps, switch to basic bar chart * update docs and styling * remove unneeded timestamp args * show new client running totatls * initial test updates * update test * clean up new client total calc into util fn * bits of clean up and todos * update tests * update to avoid activity call when in CE and missing either start or end time * update todos * update tests * tidying * move new client total onto payload for easier access * update more tests to align with copy changes and new client totals * remove addressed TODOs * Update comment * add changelog entry * revert to using total, update tests and clean up * Update ui/app/components/clients/page/counts.hbs Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> * remove duplicate charts and update descriptions * update tests after removing extra charts * tidy * update instances of byMonthActivityData to use byMonthNewClients and update tests * Update ui/app/components/clients/running-total.ts Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com> * update chart styles --------- Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
193 lines
7.8 KiB
JavaScript
193 lines
7.8 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { module, test } from 'qunit';
|
|
import { setupRenderingTest } from 'ember-qunit';
|
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
|
import { render, findAll } from '@ember/test-helpers';
|
|
import hbs from 'htmlbars-inline-precompile';
|
|
import { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients';
|
|
import syncHandler from 'vault/mirage/handlers/sync';
|
|
import { getUnixTime } from 'date-fns';
|
|
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
|
import { CLIENT_COUNT, CHARTS } from 'vault/tests/helpers/clients/client-count-selectors';
|
|
import { formatNumber } from 'core/helpers/format-number';
|
|
import { assertBarChart } from 'vault/tests/helpers/clients/client-count-helpers';
|
|
|
|
const START_TIME = getUnixTime(LICENSE_START);
|
|
const END_TIME = getUnixTime(STATIC_NOW);
|
|
const { statText, usageStats } = CLIENT_COUNT;
|
|
|
|
module('Integration | Component | clients | Clients::Page::Sync', function (hooks) {
|
|
setupRenderingTest(hooks);
|
|
setupMirage(hooks);
|
|
|
|
hooks.beforeEach(async function () {
|
|
this.renderComponent = () =>
|
|
render(hbs`
|
|
<Clients::Page::Sync
|
|
@activity={{this.activity}}
|
|
@versionHistory={{this.versionHistory}}
|
|
@startTimestamp={{this.startTimestamp}}
|
|
@endTimestamp={{this.endTimestamp}}
|
|
@namespace={{this.countsController.ns}}
|
|
@mountPath={{this.countsController.mountPath}}
|
|
/>
|
|
`);
|
|
});
|
|
|
|
module('with secrets sync not activated', function () {
|
|
test('it should render an empty state', async function (assert) {
|
|
await this.renderComponent();
|
|
|
|
assert.dom(GENERAL.emptyStateTitle).hasText('No Secrets Sync clients');
|
|
assert
|
|
.dom(GENERAL.emptyStateMessage)
|
|
.hasText('No data is available because Secrets Sync has not been activated.');
|
|
assert.dom(GENERAL.emptyStateActions).hasText('Activate Secrets Sync');
|
|
|
|
assert.dom(CHARTS.chart('Secrets sync usage')).doesNotExist();
|
|
assert.dom(statText('Total sync clients')).doesNotExist();
|
|
});
|
|
});
|
|
|
|
module('with secrets sync activated', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
syncHandler(this.server);
|
|
this.owner.lookup('service:flags').activatedFlags = ['secrets-sync'];
|
|
|
|
this.store = this.owner.lookup('service:store');
|
|
const activityQuery = {
|
|
start_time: { timestamp: START_TIME },
|
|
end_time: { timestamp: END_TIME },
|
|
};
|
|
// set this to 0
|
|
this.activity = await this.store.queryRecord('clients/activity', activityQuery);
|
|
this.startTimestamp = START_TIME;
|
|
this.endTimestamp = END_TIME;
|
|
});
|
|
|
|
test('it should render with full month activity data', async function (assert) {
|
|
const monthCount = this.activity.byMonth.length;
|
|
assert.expect(3 + monthCount);
|
|
const expectedTotal = formatNumber([this.activity.total.secret_syncs]);
|
|
await this.renderComponent();
|
|
assert
|
|
.dom(statText('Total sync clients'))
|
|
.hasText(
|
|
`Total sync clients The total number of secrets synced from Vault to other destinations during this date range. ${expectedTotal}`,
|
|
`renders correct total sync stat ${expectedTotal}`
|
|
);
|
|
|
|
assertBarChart(assert, 'Secrets sync usage', this.activity.byMonth);
|
|
});
|
|
|
|
test('it should render stats without chart for a single month', async function (assert) {
|
|
const activityQuery = { start_time: { timestamp: END_TIME }, end_time: { timestamp: END_TIME } };
|
|
this.activity = await this.store.queryRecord('clients/activity', activityQuery);
|
|
const expectedTotal = formatNumber([this.activity.total.secret_syncs]);
|
|
|
|
await this.renderComponent();
|
|
|
|
assert.dom(CHARTS.chart('Secrets sync usage')).doesNotExist('total usage chart does not render');
|
|
assert.dom(CHARTS.container('Monthly new')).doesNotExist('monthly new chart does not render');
|
|
assert.dom(statText('Average new sync clients per month')).doesNotExist();
|
|
assert
|
|
.dom(usageStats('Secrets sync usage'))
|
|
.hasText(
|
|
`Secrets sync usage Usage metrics tutorial Secrets sync clients which interacted with Vault for the first time each month. Each bar represents the total new sync clients for that month. Total sync clients ${expectedTotal}`,
|
|
'it renders usage stats with single month copy'
|
|
);
|
|
});
|
|
|
|
// EMPTY STATES
|
|
test('it should render empty state when sync data does not exist for a date range', async function (assert) {
|
|
assert.expect(7);
|
|
// this happens when a user queries historical data that predates the monthly breakdown (added in 1.11)
|
|
// only entity + non-entity clients existed then, so we show an empty state for sync clients
|
|
// because the activity response just returns { secret_syncs: 0 } which isn't very clear
|
|
this.activity.byMonth = [];
|
|
|
|
await this.renderComponent();
|
|
|
|
assert.dom(GENERAL.emptyStateTitle).hasText('No secrets sync clients');
|
|
assert.dom(GENERAL.emptyStateMessage).hasText('There is no sync data available for this date range.');
|
|
|
|
assert.dom(CHARTS.chart('Secrets sync usage')).doesNotExist('vertical bar chart does not render');
|
|
assert.dom(CHARTS.container('Monthly new')).doesNotExist('monthly new chart does not render');
|
|
assert.dom(statText('Total sync clients')).doesNotExist();
|
|
assert.dom(statText('Average new sync clients per month')).doesNotExist();
|
|
assert.dom(usageStats('Secrets sync usage')).doesNotExist();
|
|
});
|
|
|
|
test('it should render empty state when sync data does not exist for a single month', async function (assert) {
|
|
assert.expect(1);
|
|
const activityQuery = { start_time: { timestamp: START_TIME }, end_time: { timestamp: START_TIME } };
|
|
this.activity = await this.store.queryRecord('clients/activity', activityQuery);
|
|
this.activity.byMonth = [];
|
|
await this.renderComponent();
|
|
|
|
assert.dom(GENERAL.emptyStateMessage).hasText('There is no sync data available for this month.');
|
|
});
|
|
|
|
test('it should render an empty total usage chart if secrets sync is activated but monthly syncs are null or 0', async function (assert) {
|
|
// manually stub because mirage isn't setup to handle mixed data yet
|
|
const counts = {
|
|
clients: 10,
|
|
entity_clients: 4,
|
|
non_entity_clients: 6,
|
|
secret_syncs: 0,
|
|
};
|
|
const monthData = {
|
|
month: '1/24',
|
|
timestamp: '2024-01-01T00:00:00-08:00',
|
|
...counts,
|
|
namespaces: [
|
|
{
|
|
label: 'root',
|
|
...counts,
|
|
mounts: [],
|
|
},
|
|
],
|
|
};
|
|
this.activity.byMonth = [
|
|
{
|
|
...monthData,
|
|
new_clients: {
|
|
...monthData,
|
|
},
|
|
},
|
|
];
|
|
this.activity.total = counts;
|
|
|
|
assert.expect(6);
|
|
await this.renderComponent();
|
|
|
|
assert.dom(CHARTS.chart('Secrets sync usage')).exists('renders empty sync usage chart');
|
|
assert
|
|
.dom(statText('Total sync clients'))
|
|
.hasText(
|
|
'Total sync clients The total number of secrets synced from Vault to other destinations during this date range. 0'
|
|
);
|
|
findAll(`${CHARTS.chart('Secrets sync usage')} ${CHARTS.xAxisLabel}`).forEach((e, i) => {
|
|
assert
|
|
.dom(e)
|
|
.hasText(
|
|
`${this.activity.byMonth[i].month}`,
|
|
`renders x-axis labels for empty bar chart: ${this.activity.byMonth[i].month}`
|
|
);
|
|
});
|
|
findAll(`${CHARTS.chart('Secrets sync usage')} ${CHARTS.verticalBar}`).forEach((e, i) => {
|
|
assert.dom(e).isNotVisible(`does not render data bar for: ${this.activity.byMonth[i].month}`);
|
|
});
|
|
|
|
assert
|
|
.dom(CHARTS.container('Monthly new'))
|
|
.doesNotExist('empty monthly new chart does not render at all');
|
|
assert.dom(statText('Average new sync clients per month')).doesNotExist();
|
|
});
|
|
});
|
|
});
|