fix(datetime): setting max/min does not increase number of nodes rendered (#26065)

resolves #26059
This commit is contained in:
Liam DeBeasi
2022-10-10 12:43:43 -05:00
committed by GitHub
parent 0aee328b4b
commit a5d178f4c0
2 changed files with 136 additions and 35 deletions

View File

@@ -19,7 +19,7 @@ import { isRTL } from '../../utils/rtl';
import { createColorClasses } from '../../utils/theme';
import type { PickerColumnItem } from '../picker-column-internal/picker-column-internal-interfaces';
import { isSameDay, warnIfValueOutOfBounds } from './utils/comparison';
import { isSameDay, warnIfValueOutOfBounds, isBefore, isAfter } from './utils/comparison';
import {
generateMonths,
getDaysOfMonth,
@@ -32,7 +32,7 @@ import {
getCombinedDateColumnData,
} from './utils/data';
import { formatValue, getLocalizedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
import { is24Hour, isLocaleDayPeriodRTL, isMonthFirstLocale } from './utils/helpers';
import { is24Hour, isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth } from './utils/helpers';
import {
calculateHourFromAMPM,
convertDataToISO,
@@ -1400,23 +1400,24 @@ export class Datetime implements ComponentInterface {
* Previous month, current month, and next month
*/
const monthsToRender = generateMonths(workingParts);
const lastMonth = monthsToRender[monthsToRender.length - 1];
/**
* generateMonths returns the day data as well,
* but we do not want the day value to act as a max/min
* on the data we are going to generate.
* Ensure that users can select the entire window of dates.
*/
for (let i = 0; i <= monthsToRender.length - 1; i++) {
monthsToRender[i].day = null;
}
monthsToRender[0].day = 1;
lastMonth.day = getNumDaysInMonth(lastMonth.month, lastMonth.year);
/**
* If developers have provided their own
* min/max values, use that instead. Otherwise,
* fallback to the default range of 3 months.
* Narrow the dates rendered based on min/max dates (if any).
* The `min` date is used if the min is after the generated min month.
* The `max` date is used if the max is before the generated max month.
* This ensures that the sliding window always stays at 3 months
* but still allows future dates to be lazily rendered based on any min/max
* constraints.
*/
const min = minParts || monthsToRender[0];
const max = maxParts || monthsToRender[monthsToRender.length - 1];
const min = minParts !== undefined && isAfter(minParts, monthsToRender[0]) ? minParts : monthsToRender[0];
const max = maxParts !== undefined && isBefore(maxParts, lastMonth) ? maxParts : lastMonth;
const result = getCombinedDateColumnData(
locale,
@@ -1426,6 +1427,7 @@ export class Datetime implements ComponentInterface {
this.parsedDayValues,
this.parsedMonthValues
);
let items = result.items;
const parts = result.parts;

View File

@@ -14,14 +14,37 @@ test.describe('datetime: prefer wheel', () => {
* are rendering quirks on Linux
* if the datetime is too small.
*/
test.describe('datetime: date wheel rendering', () => {
test('should not have visual regressions', async ({ page }) => {
test.describe('datetime: wheel rendering', () => {
test('should not have visual regressions for date wheel', async ({ page }) => {
await page.setContent(`
<ion-datetime size="cover" presentation="date" prefer-wheel="true" value="2019-05-30"></ion-datetime>
`);
expect(await page.screenshot()).toMatchSnapshot(`datetime-wheel-date-diff-${page.getSnapshotSettings()}.png`);
});
test('should not have visual regressions for date-time wheel', async ({ page }) => {
await page.setContent(`
<ion-datetime size="cover" presentation="date-time" prefer-wheel="true" value="2019-05-30T16:30:00"></ion-datetime>
`);
expect(await page.screenshot()).toMatchSnapshot(
`datetime-wheel-date-time-diff-${page.getSnapshotSettings()}.png`
);
});
test('should not have visual regressions for time-date wheel', async ({ page }) => {
await page.setContent(`
<ion-datetime size="cover" presentation="time-date" prefer-wheel="true" value="2019-05-30T16:30:00"></ion-datetime>
`);
expect(await page.screenshot()).toMatchSnapshot(
`datetime-wheel-time-date-diff-${page.getSnapshotSettings()}.png`
);
});
});
test.describe('datetime: date wheel', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should respect the min bounds', async ({ page }) => {
await page.setContent(`
<ion-datetime presentation="date" prefer-wheel="true" min="2019-05-05" max="2023-10-01" value="2019-05-30"></ion-datetime>
@@ -149,15 +172,9 @@ test.describe('datetime: prefer wheel', () => {
});
});
});
test.describe('datetime: date-time wheel rendering', () => {
test('should not have visual regressions', async ({ page }) => {
await page.setContent(`
<ion-datetime size="cover" presentation="date-time" prefer-wheel="true" value="2019-05-30T16:30:00"></ion-datetime>
`);
expect(await page.screenshot()).toMatchSnapshot(
`datetime-wheel-date-time-diff-${page.getSnapshotSettings()}.png`
);
test.describe('datetime: date-time wheel', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should respect the min bounds', async ({ page }) => {
await page.setContent(`
@@ -249,20 +266,58 @@ test.describe('datetime: prefer wheel', () => {
await page.waitForSelector('.datetime-ready');
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
const dateColumn = page.locator('.date-column');
const dateValues = dateColumn.locator('.picker-item:not(.picker-item-empty)');
expect(await dateValues.count()).toBe(397);
expect(await dateValues.count()).toBe(90);
/**
* Select 1st item to change the dates rendered
*/
await expect(dateValues.nth(0)).toHaveAttribute('data-value', '2022-1-1');
await dateColumn.evaluate((el: HTMLElement) => (el.scrollTop = 0));
await page.waitForChanges();
await expect(dateValues.nth(0)).toHaveAttribute('data-value', '2021-12-1');
});
});
test.describe('datetime: time-date wheel rendering', () => {
test('should not have visual regressions', async ({ page }) => {
test('should keep sliding window if default window is within min and max constraints', async ({ page }) => {
await page.setContent(`
<ion-datetime size="cover" presentation="time-date" prefer-wheel="true" value="2019-05-30T16:30:00"></ion-datetime>
<ion-datetime
presentation="date-time"
prefer-wheel="true"
value="2022-06-01"
max="2030-01-01"
min="2010-01-01"
></ion-datetime>
`);
expect(await page.screenshot()).toMatchSnapshot(
`datetime-wheel-time-date-diff-${page.getSnapshotSettings()}.png`
);
await page.waitForSelector('.datetime-ready');
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
expect(await dayValues.count()).toBe(92);
});
test('should narrow sliding window if default window is not within min and max constraints', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date-time"
prefer-wheel="true"
value="2022-06-01"
max="2022-05-15"
min="2022-05-01"
></ion-datetime>
`);
await page.waitForSelector('.datetime-ready');
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
expect(await dayValues.count()).toBe(15);
});
});
test.describe('datetime: time-date wheel', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should respect the min bounds', async ({ page }) => {
await page.setContent(`
@@ -354,9 +409,53 @@ test.describe('datetime: prefer wheel', () => {
await page.waitForSelector('.datetime-ready');
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
const dateColumn = page.locator('.date-column');
const dateValues = dateColumn.locator('.picker-item:not(.picker-item-empty)');
expect(await dateValues.count()).toBe(397);
expect(await dateValues.count()).toBe(90);
/**
* Select 1st item to change the dates rendered
*/
await expect(dateValues.nth(0)).toHaveAttribute('data-value', '2022-1-1');
await dateColumn.evaluate((el: HTMLElement) => (el.scrollTop = 0));
await page.waitForChanges();
await expect(dateValues.nth(0)).toHaveAttribute('data-value', '2021-12-1');
});
test('should keep sliding window if default window is within min and max constraints', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="time-date"
prefer-wheel="true"
value="2022-06-01"
max="2030-01-01"
min="2010-01-01"
></ion-datetime>
`);
await page.waitForSelector('.datetime-ready');
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
expect(await dayValues.count()).toBe(92);
});
test('should narrow sliding window if default window is not within min and max constraints', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="time-date"
prefer-wheel="true"
value="2022-06-01"
max="2022-05-15"
min="2022-05-01"
></ion-datetime>
`);
await page.waitForSelector('.datetime-ready');
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
expect(await dayValues.count()).toBe(15);
});
});
});