/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'vault/tests/helpers';
import { click, fillIn, find, findAll, render, triggerEvent } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { ACTIVITY_RESPONSE_STUB } from 'vault/tests/helpers/clients/client-count-helpers';
import { CLIENT_COUNT, FILTERS } from 'vault/tests/helpers/clients/client-count-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import sinon from 'sinon';
import { ClientFilters, flattenMounts } from 'core/utils/client-count-utils';
module('Integration | Component | clients/page/overview', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
hooks.beforeEach(async function () {
this.server.get('sys/internal/counters/activity', () => {
return {
request_id: 'some-activity-id',
data: ACTIVITY_RESPONSE_STUB,
};
});
this.store = this.owner.lookup('service:store');
this.activity = await this.store.queryRecord('clients/activity', {});
this.mostRecentMonth = this.activity.byMonth[this.activity.byMonth.length - 1];
this.onFilterChange = sinon.spy();
this.filterQueryParams = { namespace_path: '', mount_path: '', mount_type: '' };
this.renderComponent = () =>
render(hbs`
`);
this.assertTableData = async (assert, filterKey, filterValue) => {
const expectedData = flattenMounts(this.mostRecentMonth.new_clients.namespaces).filter(
(d) => d[filterKey] === filterValue
);
await fillIn(GENERAL.selectByAttr('attribution-month'), this.mostRecentMonth.timestamp);
assert.dom(GENERAL.tableRow()).exists({ count: expectedData.length });
// Find all rendered rows and assert they satisfy the filter value and table data matches expected values
const rows = findAll(GENERAL.tableRow());
rows.forEach((_, idx) => {
assert.dom(GENERAL.tableData(idx, filterKey)).hasText(filterValue);
// Get namespace and mount paths to find original data in expectedData
const rowMountPath = find(GENERAL.tableData(idx, 'mount_path')).innerText;
const rowNsPath = find(GENERAL.tableData(idx, 'namespace_path')).innerText;
// find the expected clients from the response and assert the table matches
const { clients: expectedClients } = expectedData.find(
(d) => d.mount_path === rowMountPath && d.namespace_path === rowNsPath
);
assert.dom(GENERAL.tableData(idx, 'clients')).hasText(`${expectedClients}`);
});
};
});
test('it hides attribution when there is no data', async function (assert) {
// Stub activity response when there's no activity data
this.server.get('sys/internal/counters/activity', () => {
return {
request_id: 'some-activity-id',
data: {
by_namespace: [],
end_time: '2024-08-31T23:59:59Z',
months: [],
start_time: '2024-01-01T00:00:00Z',
total: {
distinct_entities: 0,
entity_clients: 0,
non_entity_tokens: 0,
non_entity_clients: 0,
clients: 0,
secret_syncs: 0,
},
},
};
});
this.activity = await this.store.queryRecord('clients/activity', {});
await this.renderComponent();
assert.dom(CLIENT_COUNT.card('Client attribution')).doesNotExist('it does not render attribution card');
assert.dom(GENERAL.selectByAttr('attribution-month')).doesNotExist('it hides months dropdown');
});
test('it shows correct state message when selected month has no data', async function (assert) {
await this.renderComponent();
assert.dom(GENERAL.selectByAttr('attribution-month')).exists('shows month selection dropdown');
await fillIn(GENERAL.selectByAttr('attribution-month'), '2023-06-01T00:00:00Z');
assert
.dom(CLIENT_COUNT.card('table empty state'))
.hasText('No data found Clear or change filters to view client count data. Client count documentation');
});
test('it shows table when month selection has data', async function (assert) {
await this.renderComponent();
assert.dom(GENERAL.selectByAttr('attribution-month')).exists('shows month selection dropdown');
await fillIn(GENERAL.selectByAttr('attribution-month'), '9/23');
assert.dom(CLIENT_COUNT.card('table empty state')).doesNotExist('does not show card when table has data');
assert.dom(GENERAL.table('attribution')).exists('shows table');
assert.dom(GENERAL.paginationInfo).hasText('1–6 of 6', 'shows correct pagination info');
assert.dom(GENERAL.paginationSizeSelector).hasValue('10', 'page size selector defaults to "10"');
});
test('it shows correct month options for billing period', async function (assert) {
await this.renderComponent();
assert.dom(GENERAL.selectByAttr('attribution-month')).exists('shows month selection dropdown');
await fillIn(GENERAL.selectByAttr('attribution-month'), '');
await triggerEvent(GENERAL.selectByAttr('attribution-month'), 'change');
// assert that months options in select are those of selected billing period
// '' represents default state of 'Select month'
const expectedOptions = ['', ...this.activity.byMonth.reverse().map((m) => m.timestamp)];
const actualOptions = findAll(`${GENERAL.selectByAttr('attribution-month')} option`).map(
(option) => option.value
);
assert.deepEqual(actualOptions, expectedOptions, 'All