From b0ac7de168c353ba4899cb74a2b38e25fd0cc0f1 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 22 Feb 2022 16:05:39 -0500 Subject: [PATCH] fix(datetime): improve datetime sizing in modals (#24762) Resolves #23992 --- core/src/components/datetime/datetime.tsx | 13 +- .../datetime/test/sub-pixel-width/e2e.ts | 53 +++++++ .../datetime/test/sub-pixel-width/index.html | 47 ++++++ core/src/components/datetime/test/zoom/e2e.ts | 136 ++++++++++++++++++ .../components/datetime/test/zoom/index.html | 42 ++++++ 5 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 core/src/components/datetime/test/sub-pixel-width/e2e.ts create mode 100644 core/src/components/datetime/test/sub-pixel-width/index.html create mode 100644 core/src/components/datetime/test/zoom/e2e.ts create mode 100644 core/src/components/datetime/test/zoom/index.html diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 2c71c5e2bd..494530f56d 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -811,6 +811,12 @@ export class Datetime implements ComponentInterface { navigator.maxTouchPoints > 1 ? [0.7, 1] : 1; + // Intersection observers cannot accurately detect the + // intersection with a threshold of 1, when the observed + // element width is a sub-pixel value (i.e. 334.05px). + // Setting a root margin to 1px solves the issue. + const rootMargin = '1px'; + /** * Listen on the first month to * prepend a new month and on the last @@ -829,15 +835,18 @@ export class Datetime implements ComponentInterface { * it applies to active gestures which is not * something WebKit does. */ + endIO = new IntersectionObserver(ev => ioCallback('end', ev), { threshold, - root: calendarBodyRef + root: calendarBodyRef, + rootMargin }); endIO.observe(endMonth); startIO = new IntersectionObserver(ev => ioCallback('start', ev), { threshold, - root: calendarBodyRef + root: calendarBodyRef, + rootMargin }); startIO.observe(startMonth); diff --git a/core/src/components/datetime/test/sub-pixel-width/e2e.ts b/core/src/components/datetime/test/sub-pixel-width/e2e.ts new file mode 100644 index 0000000000..cab744acbe --- /dev/null +++ b/core/src/components/datetime/test/sub-pixel-width/e2e.ts @@ -0,0 +1,53 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('datetime: sub-pixel width', () => { + + test('should update the month when next button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[1].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('March 2022'); + }); + + test('should update the month when prev button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[0].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('January 2022'); + }); + +}); diff --git a/core/src/components/datetime/test/sub-pixel-width/index.html b/core/src/components/datetime/test/sub-pixel-width/index.html new file mode 100644 index 0000000000..f532491e1b --- /dev/null +++ b/core/src/components/datetime/test/sub-pixel-width/index.html @@ -0,0 +1,47 @@ + + + + + + Datetime - Sub Pixel Width + + + + + + + + + + + + + Datetime - Sub Pixel Width + + + +

Modal

+ Present Modal + +
+ +
+
+
+
+ + + diff --git a/core/src/components/datetime/test/zoom/e2e.ts b/core/src/components/datetime/test/zoom/e2e.ts new file mode 100644 index 0000000000..a81b71d18e --- /dev/null +++ b/core/src/components/datetime/test/zoom/e2e.ts @@ -0,0 +1,136 @@ +import { newE2EPage } from '@stencil/core/testing'; + +/** + * This test emulates zoom behavior in the browser to make sure + * that key functions of the ion-datetime continue to function even + * if the page is zoomed in or out. + */ +describe('datetime: zoom interactivity', () => { + + let deviceScaleFactor; + + describe('zoom out', () => { + + beforeEach(() => { + deviceScaleFactor = 0.75; + }); + + test('should update the month when next button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + page.setViewport({ + width: 640, + height: 480, + deviceScaleFactor + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[1].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('March 2022'); + }); + + test('should update the month when prev button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[0].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('January 2022'); + }); + + }); + + describe('zoom in', () => { + + beforeEach(() => { + deviceScaleFactor = 2; + }); + + test('should update the month when next button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + page.setViewport({ + width: 640, + height: 480, + deviceScaleFactor + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[1].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('March 2022'); + }); + + test('should update the month when prev button is clicked', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/sub-pixel-width?ionic:_testing=true' + }); + + const openModalBtn = await page.find('#open-modal'); + + await openModalBtn.click(); + + const modal = await page.find('ion-modal'); + await modal.waitForVisible(); + await page.waitForTimeout(250); + + const buttons = await page.findAll('ion-datetime >>> .calendar-next-prev ion-button') + + await buttons[0].click(); + + await page.waitForTimeout(350); + + const monthYear = await page.find('ion-datetime >>> .calendar-month-year'); + + expect(monthYear.textContent.trim()).toBe('January 2022'); + }); + + }); + +}); diff --git a/core/src/components/datetime/test/zoom/index.html b/core/src/components/datetime/test/zoom/index.html new file mode 100644 index 0000000000..b17d394f56 --- /dev/null +++ b/core/src/components/datetime/test/zoom/index.html @@ -0,0 +1,42 @@ + + + + + + Datetime - Zoom + + + + + + + + + + + + + Datetime - Zoom + + + +

Modal

+ Present Modal + +
+ +
+
+
+
+ + +