fix(datetime): time picker display matches dynamically set value (#25010)

Resolves #24967
This commit is contained in:
Sean Perkins
2022-04-15 12:29:37 -04:00
committed by GitHub
parent b00159e1dd
commit 11493a086a
161 changed files with 650 additions and 416 deletions

View File

@@ -317,6 +317,8 @@ export class Datetime implements ComponentInterface {
const valueDateParts = parseDate(this.value);
if (valueDateParts) {
const { month, day, year, hour, minute } = valueDateParts;
const ampm = hour >= 12 ? 'pm' : 'am';
this.activePartsClone = {
...this.activeParts,
month,
@@ -324,7 +326,17 @@ export class Datetime implements ComponentInterface {
year,
hour,
minute,
ampm,
};
/**
* The working parts am/pm value must be updated when the value changes, to
* ensure the time picker hour column values are generated correctly.
*/
this.setWorkingParts({
...this.workingParts,
ampm,
});
} else {
printIonWarning(`Unable to parse date string: ${this.value}. Please provide a valid ISO 8601 datetime string.`);
}
@@ -1049,7 +1061,7 @@ export class Datetime implements ComponentInterface {
const valueToProcess = value || getToday();
const { month, day, year, hour, minute, tzOffset } = parseDate(valueToProcess);
this.workingParts = {
this.setWorkingParts({
month,
day,
year,
@@ -1057,7 +1069,7 @@ export class Datetime implements ComponentInterface {
minute,
tzOffset,
ampm: hour >= 12 ? 'pm' : 'am',
};
});
this.activeParts = {
month,
@@ -1628,7 +1640,7 @@ export class Datetime implements ComponentInterface {
const timeOnlyPresentation = presentation === 'time';
const use24Hour = is24Hour(this.locale, this.hourCycle);
const { hours, minutes, am, pm } = generateTime(
this.workingParts,
workingParts,
use24Hour ? 'h23' : 'h12',
this.minParts,
this.maxParts,

View File

@@ -0,0 +1,112 @@
import type { Locator } from '@playwright/test';
import { expect } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
import { test } from '@utils/test/playwright';
test.describe('datetime: presentation', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/datetime/test/presentation`);
await page.setIonViewport();
const compares = [];
const presentations = ['date-time', 'time-date', 'time', 'date', 'month-year', 'month', 'year'];
for (const presentation of presentations) {
await page.locator('select').selectOption(presentation);
await page.waitForChanges();
compares.push({
presentation,
screenshot: await page.screenshot({ fullPage: true }),
});
}
for (const compare of compares) {
expect(compare.screenshot).toMatchSnapshot(
`datetime-presentation-${compare.presentation}-diff-${page.getSnapshotSettings()}.png`
);
}
});
});
test.describe('datetime: presentation: time', () => {
let timePickerFixture: TimePickerFixture;
test.beforeEach(async ({ page }) => {
timePickerFixture = new TimePickerFixture(page);
await timePickerFixture.goto();
});
test('changing value from AM to AM should update the text', async () => {
await timePickerFixture.setValue('04:20:00');
await timePickerFixture.expectTime('4', '20', 'AM');
await timePickerFixture.setValue('11:03:00');
await timePickerFixture.expectTime('11', '03', 'AM');
});
test('changing value from AM to PM should update the text', async () => {
await timePickerFixture.setValue('05:30:00');
await timePickerFixture.expectTime('5', '30', 'AM');
await timePickerFixture.setValue('16:40:00');
await timePickerFixture.expectTime('4', '40', 'PM');
});
test('changing the value from PM to AM should update the text', async () => {
await timePickerFixture.setValue('16:40:00');
await timePickerFixture.expectTime('4', '40', 'PM');
await timePickerFixture.setValue('04:20:00');
await timePickerFixture.expectTime('4', '20', 'AM');
});
test('changing the value from PM to PM should update the text', async () => {
await timePickerFixture.setValue('16:40:00');
await timePickerFixture.expectTime('4', '40', 'PM');
await timePickerFixture.setValue('19:32:00');
await timePickerFixture.expectTime('7', '32', 'PM');
});
});
class TimePickerFixture {
readonly page: E2EPage;
private timePicker!: Locator;
constructor(page: E2EPage) {
this.page = page;
}
async goto() {
await this.page.goto(`/src/components/datetime/test/presentation`);
await this.page.locator('select').selectOption('time');
await this.page.waitForSelector('.datetime-presentation-time');
this.timePicker = this.page.locator('ion-datetime');
}
async setValue(value: string) {
const ionChange = await this.page.spyOnEvent('ionChange');
await this.timePicker.evaluate((el: HTMLIonDatetimeElement, newValue: string) => {
el.value = newValue;
}, value);
await ionChange.next();
// Changing the value can take longer than the default 100ms to repaint
await this.page.waitForChanges(300);
}
async expectTime(hour: string, minute: string, ampm: string) {
expect(
await this.timePicker.locator('ion-picker-column-internal:nth-child(1) .picker-item-active').textContent()
).toBe(hour);
expect(
await this.timePicker.locator('ion-picker-column-internal:nth-child(2) .picker-item-active').textContent()
).toBe(minute);
expect(
await this.timePicker.locator('ion-picker-column-internal:nth-child(3) .picker-item-active').textContent()
).toBe(ampm);
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Some files were not shown because too many files have changed in this diff Show More