-
Notifications
You must be signed in to change notification settings - Fork 13.4k
fix(datetime-button): respect datetime constraints in initial text #31218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f82ea68
ba0ebeb
7d95269
4824122
ef4c1cd
41952e6
be319d6
9d784dd
05d81cb
7d6c32f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -344,4 +344,146 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { | |
| await expect(page.locator('ion-datetime-button')).toContainText('Thu, November 02 01:22 AM'); | ||
| }); | ||
| }); | ||
|
|
||
| test.describe(title('datetime-button: datetime constraints'), () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional / nice-to-have, take it or leave it. These four tests repeat the same clock setup and formatter definitions. We already share per-describe setup with test.describe(title('datetime-button: datetime constraints'), () => {
const fixedTime = new Date('2026-06-18T17:54:54.518Z');
const dateFormat = new Intl.DateTimeFormat('en-US', {
weekday: 'short',
month: 'long',
day: '2-digit',
});
const timeFormat = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
});
test.beforeEach(async ({ page }) => {
await page.clock.setFixedTime(fixedTime);
});Then each test drops its local const expectedTime = new Date(fixedTime);
expectedTime.setMinutes(0);.One caveat if you do take this: once |
||
| const fixedTime = new Date('2026-06-18T17:54:54.518Z'); | ||
|
|
||
| const dateFormat = new Intl.DateTimeFormat('en-US', { | ||
| weekday: 'short', | ||
| month: 'long', | ||
| day: '2-digit', | ||
| }); | ||
| const timeFormat = new Intl.DateTimeFormat('en-US', { | ||
| hour: '2-digit', | ||
| minute: '2-digit', | ||
| }); | ||
|
|
||
| test.beforeEach(async ({ page }) => { | ||
| await page.clock.setFixedTime(fixedTime); | ||
| }); | ||
|
|
||
| test('should default to exact current time with no constraints', async ({ page }, testInfo) => { | ||
| testInfo.annotations.push({ | ||
| type: 'issue', | ||
| description: 'https://github.com/ionic-team/ionic-framework/issues/30183', | ||
| }); | ||
|
|
||
| await page.setContent( | ||
| ` | ||
| <ion-datetime-button datetime="datetime"></ion-datetime-button> | ||
| <ion-datetime id="datetime" presentation="date-time" locale="en-US"></ion-datetime> | ||
| <script> | ||
| const datetime = document.querySelector('ion-datetime'); | ||
| datetime.formatOptions = { | ||
| date: { | ||
| weekday: "short", | ||
| month: "long", | ||
| day: "2-digit" | ||
| }, | ||
| time: { | ||
| hour: "2-digit", | ||
| minute: "2-digit" | ||
| } | ||
| } | ||
| </script> | ||
| `, | ||
| config | ||
| ); | ||
| await page.locator('.datetime-ready').waitFor(); | ||
|
|
||
| await expect(page.locator('#date-button')).toContainText(dateFormat.format(fixedTime)); | ||
| await expect(page.locator('#time-button')).toContainText(timeFormat.format(fixedTime)); | ||
| }); | ||
|
|
||
| test('should obey minuteValues constraint', async ({ page }, testInfo) => { | ||
| testInfo.annotations.push({ | ||
| type: 'issue', | ||
| description: 'https://github.com/ionic-team/ionic-framework/issues/30183', | ||
| }); | ||
|
|
||
| await page.setContent( | ||
| ` | ||
| <ion-datetime-button datetime="datetime"></ion-datetime-button> | ||
| <ion-datetime id="datetime" presentation="time" locale="en-US" minute-values="0"></ion-datetime> | ||
| <script> | ||
| const datetime = document.querySelector('ion-datetime'); | ||
| datetime.formatOptions = { | ||
| time: { | ||
| hour: "2-digit", | ||
| minute: "2-digit" | ||
| } | ||
| } | ||
| </script> | ||
| `, | ||
| config | ||
| ); | ||
| await page.locator('.datetime-ready').waitFor(); | ||
|
|
||
| const expectedTime = new Date(fixedTime); | ||
| expectedTime.setMinutes(0); | ||
|
|
||
| await expect(page.locator('#time-button')).toContainText(timeFormat.format(expectedTime)); | ||
| }); | ||
|
|
||
| test('should obey hourValues constraint', async ({ page }, testInfo) => { | ||
| testInfo.annotations.push({ | ||
| type: 'issue', | ||
| description: 'https://github.com/ionic-team/ionic-framework/issues/30183', | ||
| }); | ||
|
|
||
| await page.setContent( | ||
| ` | ||
| <ion-datetime-button datetime="datetime"></ion-datetime-button> | ||
| <ion-datetime id="datetime" presentation="time" locale="en-US" hour-values="0"></ion-datetime> | ||
| <script> | ||
| const datetime = document.querySelector('ion-datetime'); | ||
| datetime.formatOptions = { | ||
| time: { | ||
| hour: "2-digit", | ||
| minute: "2-digit" | ||
| } | ||
| } | ||
| </script> | ||
| `, | ||
| config | ||
| ); | ||
| await page.locator('.datetime-ready').waitFor(); | ||
|
|
||
| const expectedTime = new Date(fixedTime); | ||
| expectedTime.setHours(0); | ||
|
|
||
| await expect(page.locator('#time-button')).toContainText(timeFormat.format(expectedTime)); | ||
| }); | ||
|
|
||
| test('should obey monthValues constraint', async ({ page }, testInfo) => { | ||
| testInfo.annotations.push({ | ||
| type: 'issue', | ||
| description: 'https://github.com/ionic-team/ionic-framework/issues/30183', | ||
| }); | ||
|
|
||
| await page.setContent( | ||
| ` | ||
| <ion-datetime-button datetime="datetime"></ion-datetime-button> | ||
| <ion-datetime id="datetime" presentation="date" locale="en-US" month-values="1"></ion-datetime> | ||
| <script> | ||
| const datetime = document.querySelector('ion-datetime'); | ||
| datetime.formatOptions = { | ||
| date: { | ||
| weekday: "short", | ||
| month: "long", | ||
| day: "2-digit" | ||
| } | ||
| } | ||
| </script> | ||
| `, | ||
| config | ||
| ); | ||
| await page.locator('.datetime-ready').waitFor(); | ||
|
|
||
| const expectedTime = new Date(fixedTime); | ||
| expectedTime.setMonth(0); | ||
|
|
||
| await expect(page.locator('#date-button')).toContainText(dateFormat.format(expectedTime)); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -604,6 +604,18 @@ export class Datetime implements ComponentInterface { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Returns the default parts the datetime falls back to when no value is set: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * today's date and time snapped to the closest value allowed by the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * component's constraints (`min`, `max`, and the `*Values` props). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @internal | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Method() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async getDefaultPart(): Promise<DatetimeParts> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this.defaultParts; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+607
to
+617
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd recommend an
Making it
Suggested change
The /**
* Both ion-datetime and ion-datetime-button default to today's date and
* time if no value is set. We read the datetime's computed default so the
* button respects the same constraints (min, max, minuteValues, etc.) that
* the datetime applies to its own fallback, instead of using a raw "now".
*/
const parsedDatetimes =
parsedValues.length > 0 ? parseDate(parsedValues) : [await datetimeEl.getDefaultPart()]; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private warnIfIncorrectValueUsage = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { multiple, value } = this; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!multiple && Array.isArray(value)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.