Replace time element with Hds::Time component (#3112)

* refactor: 💡 use Hds::Time component

* refactor: 💡 fix data test selector

* refactor: 💡 standardardized date/time format

* refactor: 💡 fix tests and remove date helpers

* fix: 🐛 fixed helper test import
This commit is contained in:
Priya Patel authored and GitHub committed 2026-02-02 18:52:19 -06:00
1 parent 1e49283a33
commit 1780077068
19 files changed
+85 -169

No files matched your search

@@ -9,10 +9,9 @@ import {
TYPE_CREDENTIAL_JSON,
TYPE_CREDENTIAL_SSH_PRIVATE_KEY,
TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
TYPE_CREDENTIAL_USERNAME_PASSWORD
TYPE_CREDENTIAL_USERNAME_PASSWORD,
} from 'api/models/credential';
module('Unit | Model | credential', function (hooks) {
setupTest(hooks);
@@ -35,7 +34,9 @@ module('Unit | Model | credential', function (hooks) {
test('it has isJSON property and returns the expected values', async function (assert) {
const store = this.owner.lookup('service:store');
const modelA = store.createRecord('credential', { type: TYPE_CREDENTIAL_JSON });
const modelA = store.createRecord('credential', {
type: TYPE_CREDENTIAL_JSON,
});
const modelB = store.createRecord('credential', {
type: TYPE_CREDENTIAL_USERNAME_PASSWORD,
});
@@ -51,13 +52,15 @@ module('Unit | Model | credential', function (hooks) {
test('it has isUnknown property and returns the expected values', async function (assert) {
const store = this.owner.lookup('service:store');
const modelA = store.createRecord('credential', {
type: TYPE_CREDENTIAL_USERNAME_PASSWORD
type: TYPE_CREDENTIAL_USERNAME_PASSWORD,
});
const modelB = store.createRecord('credential', {
type: TYPE_CREDENTIAL_SSH_PRIVATE_KEY
type: TYPE_CREDENTIAL_SSH_PRIVATE_KEY,
});
const modelC = store.createRecord('credential', { type: 'unknown' });
const modelD = store.createRecord('credential', { type: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN });
const modelD = store.createRecord('credential', {
type: TYPE_CREDENTIAL_USERNAME_PASSWORD_DOMAIN,
});
assert.false(modelA.isUnknown);
assert.false(modelB.isUnknown);
@@ -70,7 +70,8 @@ module('Unit | Utility | sqlite-query', function (hooks) {
{ field: 'name', alias: 'resource_name' },
{ field: 'type', alias: 'resource_type' },
],
expectedSelect: '"target".name as resource_name, "target".type as resource_type',
expectedSelect:
'"target".name as resource_name, "target".type as resource_type',
},
'count with alias': {
select: [{ field: 'id', isCount: true, alias: 'total_count' }],
@@ -118,7 +119,8 @@ module('Unit | Utility | sqlite-query', function (hooks) {
{ field: 'type', isDistinct: true, isCount: true },
{ field: 'status', isDistinct: true, isCount: true },
],
expectedSelect: 'count(DISTINCT "target".type), count(DISTINCT "target".status)',
expectedSelect:
'count(DISTINCT "target".type), count(DISTINCT "target".status)',
},
'distinct with alias': {
select: [{ field: 'type', isDistinct: true, alias: 'unique_type' }],
@@ -129,7 +131,8 @@ module('Unit | Utility | sqlite-query', function (hooks) {
{ field: 'type', isDistinct: true, alias: 'unique_type' },
{ field: 'status', isDistinct: true, alias: 'unique_status' },
],
expectedSelect: 'DISTINCT "target".type as unique_type, "target".status as unique_status',
expectedSelect:
'DISTINCT "target".type as unique_type, "target".status as unique_status',
},
'count distinct multiple fields': {
select: [
@@ -1,17 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
import { helper } from '@ember/component/helper';
/**
* Takes a `Date` instance and returns a string formatted in human-friendly
* ISO-ish, e.g. "2020-01-01 00:00:00".
*/
export default helper(function formatDateIsoHuman(params /*, hash*/) {
return params[0]
?.toISOString()
.replace('T', ' ')
.replace(/\.\d*Z/, '');
});
@@ -1,14 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
import { helper } from '@ember/component/helper';
/**
* Takes a `Date` instance and returns a string formatted in ISO,
* e.g. "2020-01-01T00:00:00.999Z".
*/
export default helper(function formatDateIso(params /*, hash*/) {
return params[0]?.toISOString();
});
@@ -1,6 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'core/helpers/format-date-iso-human';
@@ -1,6 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'core/helpers/format-date-iso';
@@ -1,29 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Helper | format-date-iso-human', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
this.set('inputValue', new Date('2020-01-01T00:00:00.999Z'));
await render(hbs`{{format-date-iso-human this.inputValue}}`);
assert.strictEqual(this.element.textContent.trim(), '2020-01-01 00:00:00');
});
test('it renders when null', async function (assert) {
this.set('inputValue', null);
await render(hbs`{{format-date-iso-human this.inputValue}}`);
assert.strictEqual(this.element.textContent.trim(), '');
});
});
@@ -1,32 +0,0 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Helper | format-date-iso', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
this.set('inputValue', new Date('2020-01-01T00:00:00.999Z'));
await render(hbs`{{format-date-iso this.inputValue}}`);
assert.strictEqual(
this.element.textContent.trim(),
'2020-01-01T00:00:00.999Z',
);
});
test('it renders when null', async function (assert) {
this.set('inputValue', null);
await render(hbs`{{format-date-iso this.inputValue}}`);
assert.strictEqual(this.element.textContent.trim(), '');
});
});
@@ -32,7 +32,7 @@ module('Integration | Helper | format-day-year', function (hooks) {
});
test('it renders when null', async function (assert) {
this.set('inputValue', null);
await render(hbs`{{format-date-iso this.inputValue}}`);
await render(hbs`{{format-day-year this.inputValue}}`);
assert.strictEqual(this.element.textContent.trim(), '');
});
});
@@ -183,9 +183,10 @@
<B.Td>
{{#if data.created_time}}
<Hds::Text::Body @color='faint'>
<time datetime={{format-date-iso data.created_time}}>
{{format-date-iso data.created_time}}
</time>
<Hds::Time
@date={{data.created_time}}
@display='friendly-local'
/>
</Hds::Text::Body>
{{/if}}
</B.Td>
@@ -54,13 +54,10 @@
{{#if @model.channelRecording.start_time}}
<list.Item @icon='calendar' @color='faint'>
{{t 'form.started.label'}}
<time
datetime={{format-date-iso
@model.channelRecording.start_time
}}
>
{{format-date-iso @model.channelRecording.start_time}}
</time>
<Hds::Time
@display='friendly-local'
@date={{@model.channelRecording.start_time}}
/>
</list.Item>
{{/if}}
{{! Duration }}
@@ -216,13 +216,10 @@
{{#if @model.sessionRecording.created_time}}
<list.Item @icon='calendar' @color='faint'>
{{t 'form.created.label'}}
<time
datetime={{format-date-iso
@model.sessionRecording.created_time
}}
>
{{format-date-iso @model.sessionRecording.created_time}}
</time>
<Hds::Time
@date={{@model.sessionRecording.created_time}}
@display='friendly-local'
/>
</list.Item>
{{/if}}
{{! Duration }}
@@ -257,32 +254,27 @@
{{#if @model.sessionRecording.retain_until}}
<list.Item @icon='hourglass' @color='faint'>
{{t 'resources.policy.titles.retain_until'}}
<time
data-test-retain-until
datetime={{format-date-iso
@model.sessionRecording.retain_until
}}
>
<div data-test-retain-until>
{{#if @model.sessionRecording.retainForever}}
{{t 'resources.policy.titles.forever'}}
{{else}}
{{format-date-iso @model.sessionRecording.retain_until}}
<Hds::Time
@date={{@model.sessionRecording.retain_until}}
@display='friendly-local'
/>
{{/if}}
</time>
</div>
</list.Item>
{{/if}}
{{#if @model.sessionRecording.delete_after}}
<list.Item @icon='hourglass' @color='faint'>
{{t 'resources.policy.titles.delete_after'}}
<time
<Hds::Time
data-test-delete-after
datetime={{format-date-iso
@model.sessionRecording.delete_after
}}
>
{{format-date-iso @model.sessionRecording.delete_after}}
</time>
@date={{@model.sessionRecording.delete_after}}
@display='friendly-local'
/>
</list.Item>
{{/if}}
</Rose::MetadataList>
@@ -153,9 +153,10 @@
{{data.target.displayName}}
</B.Td>
<B.Td>
<time datetime={{format-date-iso data.created_time}}>
{{format-date-iso-human data.created_time}}
</time>
<Hds::Time
@date={{data.created_time}}
@display='friendly-local'
/>
</B.Td>
<B.Td>
<SessionStatus @model={{data}} />
@@ -29,8 +29,7 @@ export const MANAGE_DROPDOWN_HOST_CATALOG_DELETE =
export const FIELD_ROLE_ARN = '[name="role_arn"]';
export const FIELD_ROLE_ARN_VALUE = 'arn:aws:iam';
export const FIELD_CREDENTIAL_TYPE =
'.credential-selection input:checked';
export const FIELD_CREDENTIAL_TYPE = '.credential-selection input:checked';
export const FIELD_DYNAMIC_CREDENTIAL = '[name="dynamic-credential"]';
export const FIELD_DYNAMIC_CREDENTIAL_VALUE = 'dynamic-credentials';
export const FIELD_STATIC_CREDENTIAL = '[name="static-credential"]';
@@ -11,6 +11,7 @@ import { setupSqlite } from 'api/test-support/helpers/sqlite';
import { faker } from '@faker-js/faker';
import * as commonSelectors from 'admin/tests/helpers/selectors';
import * as selectors from './selectors';
import { formatDateUserFriendly } from 'admin/tests/helpers/format-date-user-friendly';
import {
STATE_SESSION_RECORDING_STARTED,
STATE_SESSION_RECORDING_AVAILABLE,
@@ -31,6 +32,10 @@ module('Acceptance | session-recordings | list', function (hooks) {
'2020-01-01T00:01:00.000Z',
];
const CREATED_TIME_VALUES_FORMATTED = CREATED_TIME_VALUES_ARRAY.map(
formatDateUserFriendly,
);
let featuresService;
let createdTimeValues;
@@ -325,6 +330,8 @@ module('Acceptance | session-recordings | list', function (hooks) {
this.server.schema.sessionRecordings.all().destroy();
const expectedDescendingSort = CREATED_TIME_VALUES_ARRAY.toReversed();
const expectedDescendingFormattedSort =
CREATED_TIME_VALUES_FORMATTED.toReversed();
faker.helpers.shuffle(expectedDescendingSort).forEach((value) => {
this.server.create('session-recording', {
created_time: value,
@@ -337,7 +344,7 @@ module('Acceptance | session-recordings | list', function (hooks) {
assert
.dom(commonSelectors.TABLE_ROWS)
.isVisible({ count: CREATED_TIME_VALUES_ARRAY.length });
expectedDescendingSort.forEach((expected, index) => {
expectedDescendingFormattedSort.forEach((expected, index) => {
// nth-child index starts at 1
assert.dom(commonSelectors.TABLE_ROW(index + 1)).containsText(expected);
});
@@ -351,7 +358,7 @@ module('Acceptance | session-recordings | list', function (hooks) {
key: 'created_time',
values: CREATED_TIME_VALUES_ARRAY,
},
expectedAscendingSort: CREATED_TIME_VALUES_ARRAY,
expectedAscendingSort: CREATED_TIME_VALUES_FORMATTED,
column: 1,
},
'on state': {
@@ -18,6 +18,7 @@ import {
} from 'api/models/session';
import * as commonSelectors from 'admin/tests/helpers/selectors';
import * as selectors from './selectors';
import { formatDateUserFriendly } from 'admin/tests/helpers/format-date-user-friendly';
import { setRunOptions } from 'ember-a11y-testing/test-support';
module('Acceptance | sessions | list', function (hooks) {
@@ -31,14 +32,9 @@ module('Acceptance | sessions | list', function (hooks) {
'2020-01-01T01:00:10.000Z',
'2020-01-01T10:00:00.000Z',
];
const CREATED_TIME_ISO_VALUES_ARRAY = [
'2020-01-01 00:00:01',
'2020-01-01 00:00:10',
'2020-01-01 00:10:01',
'2020-01-01 01:00:10',
'2020-01-01 10:00:00',
];
const CREATED_TIME_VALUES_FORMATTED = CREATED_TIME_VALUES_ARRAY.map(
formatDateUserFriendly,
);
const ID_VALUES_ARRAY = ['i_0001', 'i_0010', 'i_0100', 'i_1000', 'i_10000'];
const instances = {
@@ -485,7 +481,7 @@ module('Acceptance | sessions | list', function (hooks) {
});
this.server.schema.sessions.all().destroy();
const expectedDescendingSort = CREATED_TIME_ISO_VALUES_ARRAY.toReversed();
const expectedDescendingSort = CREATED_TIME_VALUES_FORMATTED.toReversed();
faker.helpers.shuffle(CREATED_TIME_VALUES_ARRAY).forEach((value) => {
this.server.create('session', {
created_time: value,
@@ -520,7 +516,7 @@ module('Acceptance | sessions | list', function (hooks) {
key: 'created_time',
values: CREATED_TIME_VALUES_ARRAY,
},
expectedAscendingSort: CREATED_TIME_ISO_VALUES_ARRAY,
expectedAscendingSort: CREATED_TIME_VALUES_FORMATTED,
column: 4,
},
'on status': {
@@ -0,0 +1,22 @@
/**
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/
/**
* Formats a date string into a user-friendly date/time format.
* Example: Jan 1, 2024, 12:00:00 AM GMT
* @param {date string} value
* @returns
*/
export const formatDateUserFriendly = (value) =>
new Intl.DateTimeFormat('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
hour12: true,
timeZoneName: 'short',
}).format(new Date(value));
@@ -82,9 +82,7 @@
<:body as |B|>
<B.Tr>
<B.Td>
<time datetime={{format-date-iso B.data.created_time}}>
{{format-date-iso-human B.data.created_time}}
</time>
<Hds::Time @date={{B.data.created_time}} @display='friendly-local' />
</B.Td>
<B.Td>
<div class='link-copy-button-container'>
@@ -253,9 +253,10 @@
<:body as |B|>
<B.Tr>
<B.Td>
<time datetime={{format-date-iso B.data.created_time}}>
{{format-date-iso-human B.data.created_time}}
</time>
<Hds::Time
@date={{B.data.created_time}}
@display='friendly-local'
/>
</B.Td>
<B.Td>
<div class='link-copy-button-container'>