UI: CE Datepicker (#30488)

* CE date picker and header changes

* update test

* add changelog and update empty component css

* update modal values from args

* update modal copy

* header changes to add docs and move edit button

* move + update test

* Update ui/app/components/clients/date-range.ts

Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com>

* Update ui/app/components/clients/date-range.ts

Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com>

* refactor modal state and update docs

* update tests

* update modal copy

* Update changelog/30488.txt

Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>

* update date parsing, docs link copy and tidy

* update var name for clarity

* add date range test to check for disallowing current month selection

* update tests to reflect disallowal of current month (or beyond) date selection

* move ce header into page header comp and update tests

---------

Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com>
Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
This commit is contained in:
lane-wetmore 2025-05-09 12:26:43 -05:00 committed by GitHub
parent 0920108754
commit ddd34fdbc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 255 additions and 138 deletions

3
changelog/30488.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:improvement
ui: Update date selector in client count usage page to disable current month selection for Vault clusters without a license.
```

View file

@ -2,96 +2,112 @@
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
<div ...attributes>
<div class="is-flex-column align-items-end">
<Hds::Text::Display @tag="p" @size="100" class="has-bottom-margin-xs">
Change billing period
</Hds::Text::Display>
<div class="is-flex">
{{#if this.version.isEnterprise}}
<Hds::Dropdown class="has-left-margin-xs" @matchToggleWidth={{true}} as |D|>
<D.ToggleButton @text="Billing start date" @color="secondary" data-test-date-range-edit />
<D.Description @text="Current period" />
<D.Checkmark
{{on "click" (fn this.updateEnterpriseDateRange @billingStartTime)}}
@selected={{eq this.selectedStart (this.formattedDate @billingStartTime)}}
data-test-date-range-billing-start="0"
>
{{this.formattedDate @billingStartTime}}
</D.Checkmark>
{{#if this.historicalBillingPeriods.length}}
<D.Separator />
<D.Description @text="Historical periods" />
{{#each this.historicalBillingPeriods as |period idx|}}
<D.Checkmark
{{on "click" (fn this.updateEnterpriseDateRange period)}}
data-test-date-range-billing-start={{add idx 1}}
@selected={{eq this.selectedStart (this.formattedDate period)}}
>
{{this.formattedDate period}}
</D.Checkmark>
{{/each}}
{{/if}}
</Hds::Dropdown>
{{else}}
{{#if this.version.isEnterprise}}
<Hds::Text::Display @tag="p" @size="100" class="has-bottom-margin-xs">
Change billing period
</Hds::Text::Display>
<Hds::Dropdown class="has-left-margin-xs" @matchToggleWidth={{true}} as |D|>
<D.ToggleButton @text="Billing start date" @color="secondary" data-test-date-range-edit />
<D.Description @text="Current period" />
<D.Checkmark
{{on "click" (fn this.updateEnterpriseDateRange @billingStartTime)}}
@selected={{eq this.selectedStart (this.formattedDate @billingStartTime)}}
data-test-date-range-billing-start="0"
>
{{this.formattedDate @billingStartTime}}
</D.Checkmark>
{{#if this.historicalBillingPeriods.length}}
<D.Separator />
<D.Description @text="Historical periods" />
{{#each this.historicalBillingPeriods as |period idx|}}
<D.Checkmark
{{on "click" (fn this.updateEnterpriseDateRange period)}}
data-test-date-range-billing-start={{add idx 1}}
@selected={{eq this.selectedStart (this.formattedDate period)}}
>
{{this.formattedDate period}}
</D.Checkmark>
{{/each}}
{{/if}}
</Hds::Dropdown>
{{else}}
{{#unless (and this.startDate this.endDate)}}
<Hds::Button
class="has-left-margin-xs"
@text="Set date range"
@icon="edit"
{{on "click" (fn (mut this.showEditModal) true)}}
{{on "click" (fn @setEditModalVisible true)}}
data-test-date-range-edit
/>
{{/if}}
</div>
{{/unless}}
{{/if}}
</div>
{{#if this.showEditModal}}
{{#if @showEditModal}}
<Hds::Modal data-test-date-range-edit-modal @onClose={{this.onClose}} as |M|>
<M.Header>
Edit date range
</M.Header>
<M.Body>
<p class="has-bottom-margin-s">
The start date will be used as the client counting start time and all clients in that month will be considered new.
</p>
<div class="clients-date-range-display">
<div>
<Hds::Form::TextInput::Field
@type="month"
@value={{this.startDate}}
max={{this.currentMonth}}
id="start-month"
name="start"
{{on "change" this.updateDate}}
data-test-date-edit="start"
as |F|
>
<F.Label>Start</F.Label>
</Hds::Form::TextInput::Field>
<Hds::Text::Body @tag="div">
<p class="has-bottom-margin-s">
Use custom date ranges to query historic client count data. Query results do not include the current month.
</p>
<ul class="has-bottom-margin-s">
<li>
<strong>Start</strong>
sets the month and year (inclusive) for the first month of client counting.
</li>
<li>
<strong>End</strong>
sets the month and year (inclusive) for the final month of client counting.
</li>
</ul>
<p class="has-bottom-margin-s">
We recommend setting
<strong>Start</strong>
to your Vault deploy date to get the most accurate new and total client count estimations.</p>
<div class="clients-date-range-display">
<div>
<Hds::Form::TextInput::Field
@type="month"
@value={{this.modalStart}}
max={{this.previousMonth}}
id="start-month"
name="start"
{{on "change" this.updateDate}}
data-test-date-edit="start"
as |F|
>
<F.Label>Start</F.Label>
</Hds::Form::TextInput::Field>
</div>
<div>
<Hds::Form::TextInput::Field
@type="month"
@value={{this.modalEnd}}
max={{this.previousMonth}}
id="end-month"
name="end"
{{on "change" this.updateDate}}
data-test-date-edit="end"
as |F|
>
<F.Label>End</F.Label>
</Hds::Form::TextInput::Field>
</div>
</div>
<div>
<Hds::Form::TextInput::Field
@type="month"
@value={{this.endDate}}
max={{this.currentMonth}}
id="end-month"
name="end"
{{on "change" this.updateDate}}
data-test-date-edit="end"
as |F|
>
<F.Label>End</F.Label>
</Hds::Form::TextInput::Field>
</div>
</div>
{{#if this.validationError}}
<Hds::Form::Error
class="has-top-margin-xs"
data-test-date-range-validation
>{{this.validationError}}</Hds::Form::Error>
{{/if}}
{{#if this.validationError}}
<Hds::Form::Error
class="has-top-margin-xs"
data-test-date-range-validation
>{{this.validationError}}</Hds::Form::Error>
{{/if}}
</Hds::Text::Body>
</M.Body>
<M.Footer as |F|>
<Hds::Button data-test-save @text="Save" {{on "click" this.handleSave}} />

View file

@ -20,6 +20,8 @@ interface OnChangeParams {
}
interface Args {
onChange: (callback: OnChangeParams) => void;
setEditModalVisible: (visible: boolean) => void;
showEditModal: boolean;
startTime: string;
endTime: string;
billingStartTime: string;
@ -34,6 +36,8 @@ interface Args {
* <Clients::DateRange @startTime="2018-01-01T14:15:30Z" @endTime="2019-01-31T14:15:30Z" @onChange={{this.handleDateChange}} />
*
* @param {function} onChange - callback when a new range is saved.
* @param {function} setEditModalVisible - callback to tell parent header when modal is opened/closed
* @param {boolean} showEditModal - boolean for when parent header triggers the modal open
* @param {string} [startTime] - ISO string timestamp of the current start date
* @param {string} [endTime] - ISO string timestamp of the current end date
* @param {int} [retentionMonths=48] - number of months for historical billing
@ -43,11 +47,17 @@ interface Args {
export default class ClientsDateRangeComponent extends Component<Args> {
@service declare readonly version: VersionService;
@tracked showEditModal = false;
@tracked startDate = ''; // format yyyy-MM
@tracked endDate = ''; // format yyyy-MM
@tracked selectedStart = this.args.billingStartTime;
currentMonth = format(timestamp.now(), 'yyyy-MM');
@tracked modalStart = ''; // format yyyy-MM
@tracked modalEnd = ''; // format yyyy-MM
currentMonth = timestamp.now();
previousMonth = format(
new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() - 1, 1),
'yyyy-MM'
);
constructor(owner: unknown, args: Args) {
super(owner, args);
@ -57,10 +67,12 @@ export default class ClientsDateRangeComponent extends Component<Args> {
setTrackedFromArgs() {
if (this.args.startTime) {
this.startDate = parseAPITimestamp(this.args.startTime, 'yyyy-MM') as string;
this.modalStart = this.startDate;
this.selectedStart = this.formattedDate(this.args.startTime) as string;
}
if (this.args.endTime) {
this.endDate = parseAPITimestamp(this.args.endTime, 'yyyy-MM') as string;
this.modalEnd = this.endDate;
}
}
@ -96,19 +108,21 @@ export default class ClientsDateRangeComponent extends Component<Args> {
// this means we want to reset, which is fine for ent only
return null;
}
if (!this.startDate || !this.endDate) {
if (!this.modalStart || !this.modalEnd) {
return 'You must supply both start and end dates.';
}
if (this.startDate > this.endDate) {
if (this.modalStart > this.modalEnd) {
return 'Start date must be before end date.';
}
if (this.modalStart > this.previousMonth || this.modalEnd > this.previousMonth)
return 'You cannot select the current month or beyond.';
return null;
}
@action onClose() {
// since the component never gets torn down, we have to manually re-set this on close
this.setTrackedFromArgs();
this.showEditModal = false;
this.args.setEditModalVisible(false);
}
@action resetDates() {
@ -119,9 +133,9 @@ export default class ClientsDateRangeComponent extends Component<Args> {
@action updateDate(evt: HTMLElementEvent<HTMLInputElement>) {
const { name, value } = evt.target;
if (name === 'end') {
this.endDate = value;
this.modalEnd = value;
} else {
this.startDate = value;
this.modalStart = value;
}
}
@ -132,17 +146,17 @@ export default class ClientsDateRangeComponent extends Component<Args> {
start_time: undefined,
end_time: undefined,
};
if (this.startDate) {
const [year, month] = this.startDate.split('-');
if (year && month) {
params.start_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, false);
}
this.startDate = this.modalStart;
this.endDate = this.modalEnd;
let year, month;
[year, month] = this.startDate.split('-');
if (year && month) {
params.start_time = formatDateObject({ monthIdx: Number(month) - 1, year: Number(year) }, false);
}
if (this.endDate) {
const [year, month] = this.endDate.split('-');
if (year && month) {
params.end_time = formatDateObject({ monthIdx: parseInt(month) - 1, year: parseInt(year) }, true);
}
[year, month] = this.endDate.split('-');
if (year && month) {
params.end_time = formatDateObject({ monthIdx: Number(month) - 1, year: Number(year) }, true);
}
this.args.onChange(params);

View file

@ -7,8 +7,8 @@
<PH.Title>
Client Usage
</PH.Title>
{{#if (and this.formattedStartDate this.formattedEndDate)}}
<PH.Description class="has-text-weight-semibold">
{{#if this.version.isEnterprise}}
<PH.Description class="has-text-weight-semibold flex">
<p>
For billing period:
<span data-test-date-range="start">{{this.formattedStartDate}}</span>
@ -17,7 +17,36 @@
</p>
</PH.Description>
{{/if}}
<PH.Actions class="align-items-end">
<PH.Description>
This is the dashboard for your overall client count usages. Review Vault's
<Hds::Link::Inline @href={{doc-link "/vault/docs/concepts/client-count"}}>client counting documentation
</Hds::Link::Inline>for more information.
{{#if this.showCommunity}}
<div class="has-top-padding-m">
<Hds::Text::Display @tag="h3">Client counting period</Hds::Text::Display>
<Hds::Text::Body @tag="p" class="has-text-grey">Specify a date range to view within that timeframe. Click 'Edit' to
choose a different date range.</Hds::Text::Body>
<Hds::Text::Body @tag="p">
<span data-test-date-range="start">{{this.formattedStartDate}}</span>
-
<span data-test-date-range="end">{{this.formattedEndDate}}</span>
<Hds::Button
@size="small"
@text="Edit"
@isInline="true"
@color="tertiary"
@icon="edit"
@iconPosition="trailing"
data-test-date-range-edit
{{on "click" (fn (mut this.showEditModal) true)}}
/>
</Hds::Text::Body>
</div>
{{/if}}
</PH.Description>
<PH.Actions class="align-items-end align-self-end">
{{#if this.showExportButton}}
<Hds::Button
class="has-font-weight-normal"
@ -34,8 +63,12 @@
@billingStartTime={{@billingStartTime}}
@retentionMonths={{@retentionMonths}}
@onChange={{@onChange}}
@showEditModal={{this.showEditModal}}
@setEditModalVisible={{this.setEditModalVisible}}
class={{if (and this.version.isCommunity this.startDate this.endDate) "position-absolute"}}
/>
</PH.Actions>
</Hds::PageHeader>
{{#if this.showExportModal}}

View file

@ -21,11 +21,14 @@ import { task } from 'ember-concurrency';
* ```js
* <Clients::PageHeader @startTimestamp="2022-06-01T23:00:11.050Z" @endTimestamp="2022-12-01T23:00:11.050Z" @namespace="foo" @upgradesDuringActivity={{array (hash version="1.10.1" previousVersion="1.9.1" timestampInstalled= "2021-11-18T10:23:16Z") }} />
* ```
* @param {string} [billingStartTime] - ISO string timestamp of billing start date, to be passed to datepicker
* @param {string} [startTimestamp] - ISO timestamp of start time, to be passed to export request
* @param {string} [endTimestamp] - ISO timestamp of end time, to be passed to export request
* @param {number} [retentionMonths=48] - number of months for historical billing, to be passed to datepicker
* @param {string} [namespace] - namespace filter. Will be appended to the current namespace in the export request.
* @param {string} [upgradesDuringActivity] - array of objects containing version history upgrade data
* @param {boolean} [noData = false] - when true, export button will hide regardless of capabilities
* @param {function} onChange - callback when a new range is saved, to be passed to datepicker
*/
export default class ClientsPageHeaderComponent extends Component {
@service download;
@ -34,6 +37,7 @@ export default class ClientsPageHeaderComponent extends Component {
@service version;
@tracked canDownload = false;
@tracked showEditModal = false;
@tracked showExportModal = false;
@tracked exportFormat = 'csv';
@tracked downloadError = '';
@ -94,6 +98,10 @@ export default class ClientsPageHeaderComponent extends Component {
return namespace ? sanitizePath(`${currentNs}/${namespace}`) : sanitizePath(currentNs);
}
get showCommunity() {
return this.version.isCommunity && !!this.formattedStartDate && !!this.formattedEndDate;
}
async getExportData() {
const adapter = this.store.adapterFor('clients/activity');
const { startTimestamp, endTimestamp } = this.args;
@ -120,13 +128,20 @@ export default class ClientsPageHeaderComponent extends Component {
}
});
@action setExportFormat(evt) {
@action
setExportFormat(evt) {
const { value } = evt.target;
this.exportFormat = value;
}
@action resetModal() {
@action
resetModal() {
this.showExportModal = false;
this.downloadError = '';
}
@action
setEditModalVisible(visible) {
this.showEditModal = visible;
}
}

View file

@ -42,6 +42,10 @@ export default class ClientsCountsPageComponent extends Component<Args> {
return this.args.startTimestamp ? parseAPITimestamp(this.args.startTimestamp, 'MMMM yyyy') : null;
}
get formattedEndDate() {
return this.args.endTimestamp ? parseAPITimestamp(this.args.endTimestamp, 'MMMM yyyy') : null;
}
get formattedBillingStartDate() {
return this.args.config.billingStartTimestamp.toISOString();
}
@ -200,7 +204,8 @@ export default class ClientsCountsPageComponent extends Component<Args> {
this.args.onFilterChange(params);
}
@action resetFilters() {
@action
resetFilters() {
this.args.onFilterChange({
start_time: undefined,
end_time: undefined,

View file

@ -43,6 +43,10 @@
position: relative;
}
.position-absolute {
position: absolute;
}
.top-xxs {
top: size_variables.$spacing-4;
}

View file

@ -27,6 +27,7 @@ HOW TO ADD NEW TYPES:
*/
export const LICENSE_START = new Date('2023-07-02T00:00:00Z');
export const STATIC_NOW = new Date('2024-01-25T23:59:59Z');
export const STATIC_PREVIOUS_MONTH = new Date('2023-12-25T23:59:59Z');
const COUNTS_START = subMonths(STATIC_NOW, 12); // user started Vault cluster on 2023-01-25
// upgrade happened 2 month after license start
export const UPGRADE_DATE = addMonths(LICENSE_START, 2); // monthly attribution added

View file

@ -6,7 +6,12 @@
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import clientsHandler, { STATIC_NOW, LICENSE_START, UPGRADE_DATE } from 'vault/mirage/handlers/clients';
import clientsHandler, {
STATIC_NOW,
LICENSE_START,
UPGRADE_DATE,
STATIC_PREVIOUS_MONTH,
} from 'vault/mirage/handlers/clients';
import syncHandler from 'vault/mirage/handlers/sync';
import sinon from 'sinon';
import { visit, click, findAll, fillIn, currentURL } from '@ember/test-helpers';
@ -63,11 +68,14 @@ module('Acceptance | clients | overview', function (hooks) {
assert.dom(CHARTS.xAxisLabel).exists({ count: 7 }, 'chart months matches query');
});
// TODO revisit once CE changes are finalized
test.skip('it should update charts when querying date ranges', async function (assert) {
test('it should update charts when querying date ranges', async function (assert) {
// query for single, historical month with no new counts (July 2023)
const service = this.owner.lookup('service:version');
service.type = 'community';
const licenseStartMonth = format(LICENSE_START, 'yyyy-MM');
const upgradeMonth = format(UPGRADE_DATE, 'yyyy-MM');
const endMonth = format(STATIC_PREVIOUS_MONTH, 'yyyy-MM');
await click(CLIENT_COUNT.dateRange.edit);
await fillIn(CLIENT_COUNT.dateRange.editDate('start'), licenseStartMonth);
await fillIn(CLIENT_COUNT.dateRange.editDate('end'), licenseStartMonth);
@ -83,22 +91,14 @@ module('Acceptance | clients | overview', function (hooks) {
assert.dom(CHARTS.container('namespace')).exists('namespace attribution chart shows');
assert.dom(CHARTS.container('mount')).exists('mount attribution chart shows');
// reset to billing period
await click(CLIENT_COUNT.dateRange.edit);
await click(CLIENT_COUNT.dateRange.reset);
await click(GENERAL.saveButton);
// change to start on month/year of upgrade to 1.10
await click(CLIENT_COUNT.dateRange.edit);
await fillIn(CLIENT_COUNT.dateRange.editDate('start'), upgradeMonth);
await fillIn(CLIENT_COUNT.dateRange.editDate('end'), endMonth);
await click(GENERAL.saveButton);
assert
.dom(CLIENT_COUNT.dateRange.dateDisplay('start'))
.hasText('September 2023', 'billing start month is correctly parsed from license');
assert
.dom(CLIENT_COUNT.dateRange.dateDisplay('end'))
.hasText('January 2024', 'billing start month is correctly parsed from license');
assert.dom(CLIENT_COUNT.attributionBlock()).exists({ count: 2 });
assert
.dom(CHARTS.container('Vault client counts'))
@ -106,7 +106,7 @@ module('Acceptance | clients | overview', function (hooks) {
assert
.dom(`${CHARTS.container('Vault client counts')} ${CHARTS.xAxisLabel}`)
.hasText('9/23', 'x-axis labels start with queried start month (upgrade date)');
assert.dom(CHARTS.xAxisLabel).exists({ count: 5 }, 'chart months matches query');
assert.dom(CHARTS.xAxisLabel).exists({ count: 4 }, 'chart months matches query');
// query for single, historical month (upgrade month)
await click(CLIENT_COUNT.dateRange.edit);
@ -147,16 +147,10 @@ module('Acceptance | clients | overview', function (hooks) {
.dom(xAxisLabels[xAxisLabels.length - 1])
.hasText('12/23', 'x-axis labels end with queried end month');
// reset to billing period
await click(CLIENT_COUNT.dateRange.edit);
await click(CLIENT_COUNT.dateRange.reset);
await click(GENERAL.saveButton);
// query month older than count start date
await click(CLIENT_COUNT.dateRange.edit);
await fillIn(CLIENT_COUNT.dateRange.editDate('start'), '2020-07');
await click(GENERAL.saveButton);
assert
.dom(CLIENT_COUNT.counts.startDiscrepancy)
.hasTextContaining(

View file

@ -9,6 +9,7 @@ import { click, fillIn, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import Sinon from 'sinon';
import timestamp from 'core/utils/timestamp';
import { format } from 'date-fns';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-selectors';
@ -24,9 +25,13 @@ module('Integration | Component | clients/date-range', function (hooks) {
this.billingStartTime = '2018-01-01T14:15:30';
this.retentionMonths = 48;
this.onChange = Sinon.spy();
this.setEditModalVisible = Sinon.stub().callsFake((visible) => {
this.set('showEditModal', visible);
});
this.showEditModal = false;
this.renderComponent = async () => {
await render(
hbs`<Clients::DateRange @startTime={{this.startTime}} @endTime={{this.endTime}} @onChange={{this.onChange}} @billingStartTime={{this.billingStartTime}} @retentionMonths={{this.retentionMonths}}/>`
hbs`<Clients::DateRange @startTime={{this.startTime}} @endTime={{this.endTime}} @onChange={{this.onChange}} @billingStartTime={{this.billingStartTime}} @retentionMonths={{this.retentionMonths}} @setEditModalVisible={{this.setEditModalVisible}} @showEditModal={{this.showEditModal}}/>`
);
};
});
@ -43,11 +48,11 @@ module('Integration | Component | clients/date-range', function (hooks) {
assert.dom(DATE_RANGE.editModal).exists();
assert.dom(DATE_RANGE.editDate('start')).hasValue('');
await fillIn(DATE_RANGE.editDate('start'), '2018-01');
await fillIn(DATE_RANGE.editDate('end'), '2019-01');
await fillIn(DATE_RANGE.editDate('end'), '2018-03');
await click(GENERAL.saveButton);
assert.deepEqual(this.onChange.args[0], [
{
end_time: 1548892800,
end_time: 1522454400,
start_time: 1514764800,
},
]);
@ -56,8 +61,8 @@ module('Integration | Component | clients/date-range', function (hooks) {
test('it does not trigger onChange if date range invalid', async function (assert) {
this.owner.lookup('service:version').type = 'community';
this.endTime = undefined;
await this.renderComponent();
await click(DATE_RANGE.edit);
await fillIn(DATE_RANGE.editDate('end'), '');
assert.dom(DATE_RANGE.validation).hasText('You must supply both start and end dates.');
@ -75,16 +80,26 @@ module('Integration | Component | clients/date-range', function (hooks) {
assert.dom(DATE_RANGE.editModal).doesNotExist();
});
test('it resets the tracked values on close', async function (assert) {
test('it does not allow the current month to be selected as a start date or as an end date', async function (assert) {
this.owner.lookup('service:version').type = 'community';
this.endTime = undefined;
const currentMonth = format(timestamp.now(), 'yyyy-MM');
await this.renderComponent();
await click(DATE_RANGE.edit);
await fillIn(DATE_RANGE.editDate('start'), '2017-04');
await fillIn(DATE_RANGE.editDate('end'), '2018-05');
await click(GENERAL.cancelButton);
await fillIn(DATE_RANGE.editDate('start'), currentMonth);
await fillIn(DATE_RANGE.editDate('end'), currentMonth);
await click(DATE_RANGE.edit);
assert.dom(DATE_RANGE.editDate('start')).hasValue('2018-01');
assert.dom(DATE_RANGE.editDate('end')).hasValue('2019-01');
assert.dom(DATE_RANGE.validation).hasText('You cannot select the current month or beyond.');
await click(GENERAL.saveButton);
assert.false(this.onChange.called);
// This tests validation when the end date is the current month and start is valid.
// If start is current month and end is a valid prior selection, it will run into the validation error of start being after end date
// which is covered by prior tests.
await fillIn(DATE_RANGE.editDate('start'), '2018-01');
await fillIn(DATE_RANGE.editDate('end'), currentMonth);
await click(GENERAL.saveButton);
assert.false(this.onChange.called);
});
});

View file

@ -8,7 +8,11 @@ import { setupRenderingTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { render, click, findAll, fillIn } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import clientsHandler, { LICENSE_START, STATIC_NOW } from 'vault/mirage/handlers/clients';
import clientsHandler, {
LICENSE_START,
STATIC_NOW,
STATIC_PREVIOUS_MONTH,
} from 'vault/mirage/handlers/clients';
import { fromUnixTime, getUnixTime } from 'date-fns';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import { CLIENT_COUNT } from 'vault/tests/helpers/clients/client-count-selectors';
@ -18,9 +22,9 @@ import sinon from 'sinon';
import { allowAllCapabilitiesStub } from 'vault/tests/helpers/stubs';
const START_TIME = getUnixTime(LICENSE_START);
const END_TIME = getUnixTime(STATIC_NOW);
const END_TIME = getUnixTime(STATIC_PREVIOUS_MONTH);
const START_ISO = LICENSE_START.toISOString();
const END_ISO = STATIC_NOW.toISOString();
const END_ISO = STATIC_PREVIOUS_MONTH.toISOString();
module('Integration | Component | clients | Page::Counts', function (hooks) {
setupRenderingTest(hooks);
@ -62,7 +66,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) {
await this.renderComponent();
assert.dom(CLIENT_COUNT.dateRange.dateDisplay('start')).hasText('July 2023', 'Start month renders');
assert.dom(CLIENT_COUNT.dateRange.dateDisplay('end')).hasText('January 2024', 'End month renders');
assert.dom(CLIENT_COUNT.dateRange.dateDisplay('end')).hasText('December 2023', 'End month renders');
});
test('it should render no data empty state', async function (assert) {
@ -72,7 +76,7 @@ module('Integration | Component | clients | Page::Counts', function (hooks) {
assert
.dom(GENERAL.emptyStateTitle)
.hasText('No data received from July 2023 to January 2024', 'No data empty state renders');
.hasText('No data received from July 2023 to December 2023', 'No data empty state renders');
});
test('it should render activity error', async function (assert) {
@ -100,14 +104,13 @@ module('Integration | Component | clients | Page::Counts', function (hooks) {
// license start is July 2, 2024 on date change it recalculates start to beginning of the month
const july23start = getUnixTime(new Date('2023-07-01T00:00:00Z'));
const dec23end = getUnixTime(new Date('2023-12-31T00:00:00Z'));
const jan24end = getUnixTime(new Date('2024-01-31T00:00:00Z'));
[
{
scenario: 'changing start only',
expected: { start_time: jan23start, end_time: jan24end },
expected: { start_time: jan23start, end_time: dec23end },
editStart: '2023-01',
expectedStart: 'January 2023',
expectedEnd: 'January 2024',
expectedEnd: 'December 2023',
},
{
scenario: 'changing end only',
@ -142,9 +145,9 @@ module('Integration | Component | clients | Page::Counts', function (hooks) {
await this.renderComponent();
await click(CLIENT_COUNT.dateRange.edit);
// page starts with default billing dates, which are july 23 - jan 24
// page starts with default billing dates, which are july 23 - dec 23
assert.dom(CLIENT_COUNT.dateRange.editDate('start')).hasValue('2023-07');
assert.dom(CLIENT_COUNT.dateRange.editDate('end')).hasValue('2024-01');
assert.dom(CLIENT_COUNT.dateRange.editDate('end')).hasValue('2023-12');
if (testCase.editStart) {
await fillIn(CLIENT_COUNT.dateRange.editDate('start'), testCase.editStart);
@ -275,6 +278,20 @@ module('Integration | Component | clients | Page::Counts', function (hooks) {
assert
.dom(GENERAL.emptyStateTitle)
.hasText('No data received from July 2023 to January 2024', 'Empty state renders');
.hasText('No data received from July 2023 to December 2023', 'Empty state renders');
});
test('it resets the tracked values on close', async function (assert) {
await this.renderComponent();
const DATE_RANGE = CLIENT_COUNT.dateRange;
await click(DATE_RANGE.edit);
await fillIn(DATE_RANGE.editDate('start'), '2017-04');
await fillIn(DATE_RANGE.editDate('end'), '2018-05');
await click(GENERAL.cancelButton);
await click(DATE_RANGE.edit);
assert.dom(DATE_RANGE.editDate('start')).hasValue('2023-07');
assert.dom(DATE_RANGE.editDate('end')).hasValue('2023-12');
});
});