/** * 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