From 72b8fb3376c8d742804b40e302eec59729a92311 Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 18 Dec 2023 11:05:37 +0200 Subject: [PATCH 1/8] Add e2e test asserting correct section pasting behavior --- test/e2e/index.test.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index ff6f9bdc39b4..e529e14fa38f 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -1,3 +1,4 @@ +import { platform } from 'node:os'; import { expect } from 'chai'; import { chromium, @@ -547,10 +548,32 @@ async function initializeEnvironment( const input = page.getByRole('textbox'); await input.focus(); - await input.type('04/11/2022'); + await input.fill('04/11/2022'); expect(await input.inputValue()).to.equal('04/11/2022'); }); + + it('should allow pasting a section', async () => { + await renderFixture('DatePicker/BasicDesktopDatePicker'); + const input = page.getByRole('textbox'); + + const isMac = platform() === 'darwin'; + const modifier = isMac ? 'Meta' : 'Control'; + + await input.focus(); + // ensure that the focus is moved to the end section by typing naturally - with a timeout + await input.pressSequentially('04/11/2022'); + // move to day section + await page.keyboard.press('ArrowLeft'); + // copy day section value + await page.keyboard.press(`${modifier}+KeyC`); + // move to month section + await page.keyboard.press('ArrowLeft'); + // paste day section value to month section + await page.keyboard.press(`${modifier}+KeyV`); + + expect(await input.inputValue()).to.equal('11/11/2022'); + }); }); describe('', () => { it('should allow selecting a value', async () => { From a9a3b290b53b91df8c6d4d6be36e261d3aea8fbc Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 18 Dec 2023 17:06:49 +0200 Subject: [PATCH 2/8] Update test with search query assertion and skip on chrome --- test/e2e/index.test.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index e529e14fa38f..5feed5c53cb3 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -554,6 +554,10 @@ async function initializeEnvironment( }); it('should allow pasting a section', async () => { + // the pasting does not seem to work in chromium headless + if (browserType.name() === 'chromium') { + return; + } await renderFixture('DatePicker/BasicDesktopDatePicker'); const input = page.getByRole('textbox'); @@ -564,15 +568,23 @@ async function initializeEnvironment( // ensure that the focus is moved to the end section by typing naturally - with a timeout await input.pressSequentially('04/11/2022'); // move to day section - await page.keyboard.press('ArrowLeft'); + await input.press('ArrowLeft'); // copy day section value - await page.keyboard.press(`${modifier}+KeyC`); + await input.press(`${modifier}+KeyC`); // move to month section - await page.keyboard.press('ArrowLeft'); + await input.press('ArrowLeft'); + // initiate search query on month section + await input.press('1'); // paste day section value to month section - await page.keyboard.press(`${modifier}+KeyV`); + await input.press(`${modifier}+KeyV`); expect(await input.inputValue()).to.equal('11/11/2022'); + + // move back to month section + await input.press('ArrowLeft'); + // check that the search query has been cleared after pasting + await input.press('2'); + expect(await input.inputValue()).to.equal('02/11/2022'); }); }); describe('', () => { From 68d9bc4ae4b7ad841ef4ed33d8d54578b908adf9 Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 18 Dec 2023 17:07:20 +0200 Subject: [PATCH 3/8] Execute section pasting when detected --- .../src/internals/hooks/useField/useField.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts index 81b84d3b059d..149fffceaf29 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -180,7 +180,14 @@ export const useField = < (activeSection.contentType === 'digit' && digitsOnly) || (activeSection.contentType === 'digit-with-letter' && digitsAndLetterOnly); if (isValidPastedValue) { - // Early return to let the paste update section, value + resetCharacterQuery(); + updateSectionValue({ + activeSection, + newSectionValue: pastedValue, + shouldGoToNextSection: true, + }); + // prevent default to avoid the input change handler being called + event.preventDefault(); return; } if (lettersOnly || digitsOnly) { From e97d8558ae6307e1960c78cf96db007df6de3659 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 19 Dec 2023 09:16:26 +0200 Subject: [PATCH 4/8] Does `webkit` use `Meta` regardless of OS? --- test/e2e/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 5feed5c53cb3..350fb9468287 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -562,7 +562,7 @@ async function initializeEnvironment( const input = page.getByRole('textbox'); const isMac = platform() === 'darwin'; - const modifier = isMac ? 'Meta' : 'Control'; + const modifier = isMac || browserType.name() === 'webkit' ? 'Meta' : 'Control'; await input.focus(); // ensure that the focus is moved to the end section by typing naturally - with a timeout From e436c3a843e90b9174082e8ec51d59b872b53a62 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 19 Dec 2023 11:25:09 +0200 Subject: [PATCH 5/8] Try headed mode --- test/e2e/index.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 350fb9468287..857edc595f07 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -96,7 +96,7 @@ async function initializeEnvironment( contextOptions?: BrowserContextOptions, ) { browser = await browserType.launch({ - headless: true, + headless: false, }); // eslint-disable-next-line no-console console.log(`Running on: ${browserType.name()}, version: ${browser.version()}.`); @@ -554,15 +554,11 @@ async function initializeEnvironment( }); it('should allow pasting a section', async () => { - // the pasting does not seem to work in chromium headless - if (browserType.name() === 'chromium') { - return; - } await renderFixture('DatePicker/BasicDesktopDatePicker'); const input = page.getByRole('textbox'); const isMac = platform() === 'darwin'; - const modifier = isMac || browserType.name() === 'webkit' ? 'Meta' : 'Control'; + const modifier = isMac ? 'Meta' : 'Control'; await input.focus(); // ensure that the focus is moved to the end section by typing naturally - with a timeout From 778e3c14aea81e82eaefb25e68ae6d6e29151fb8 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 19 Dec 2023 11:52:32 +0200 Subject: [PATCH 6/8] Do permissions help? --- test/e2e/index.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 857edc595f07..5a10e022bc7f 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -96,13 +96,17 @@ async function initializeEnvironment( contextOptions?: BrowserContextOptions, ) { browser = await browserType.launch({ - headless: false, + headless: true, }); // eslint-disable-next-line no-console console.log(`Running on: ${browserType.name()}, version: ${browser.version()}.`); context = await browser.newContext({ // ensure consistent date formatting regardless of environment locale: 'en-US', + permissions: [ + ...(browserType.name() !== 'firefox' ? ['clipboard-read'] : []), + ...(browserType.name() === 'chromium' ? ['clipboard-write'] : []), + ], ...contextOptions, }); // Circle CI has low-performance CPUs. @@ -554,6 +558,10 @@ async function initializeEnvironment( }); it('should allow pasting a section', async () => { + // the pasting does not seem to work in chromium headless + if (browserType.name() === 'chromium') { + return; + } await renderFixture('DatePicker/BasicDesktopDatePicker'); const input = page.getByRole('textbox'); From 880f0e70dda5b7204bd92927e4894f5361094fb1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 19 Dec 2023 14:31:21 +0200 Subject: [PATCH 7/8] Keep e2e test only on firefox :( --- test/e2e/index.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index 5a10e022bc7f..56e738c8d607 100644 --- a/test/e2e/index.test.ts +++ b/test/e2e/index.test.ts @@ -103,10 +103,6 @@ async function initializeEnvironment( context = await browser.newContext({ // ensure consistent date formatting regardless of environment locale: 'en-US', - permissions: [ - ...(browserType.name() !== 'firefox' ? ['clipboard-read'] : []), - ...(browserType.name() === 'chromium' ? ['clipboard-write'] : []), - ], ...contextOptions, }); // Circle CI has low-performance CPUs. @@ -558,8 +554,8 @@ async function initializeEnvironment( }); it('should allow pasting a section', async () => { - // the pasting does not seem to work in chromium headless - if (browserType.name() === 'chromium') { + // Only firefox is capable of reliably running this test in CI and headless browsers + if (browserType.name() !== 'firefox' && process.env.CIRCLECI) { return; } await renderFixture('DatePicker/BasicDesktopDatePicker'); From 85fe1621e8d10700d8cd9ef07345dc9a893f5723 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 19 Dec 2023 15:01:27 +0200 Subject: [PATCH 8/8] At least add unit test --- .../tests/editing.DateField.test.tsx | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx b/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx index 2e5f3ae50828..a26b58f6a522 100644 --- a/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx +++ b/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx @@ -745,7 +745,7 @@ describe(' - Editing', () => { ); describeAdapters('Pasting', DateField, ({ adapter, render, renderWithProps, clickOnInput }) => { - const firePasteEvent = (input: HTMLInputElement, pastedValue: string) => { + const firePasteEvent = (input: HTMLInputElement, pastedValue?: string, rawValue?: string) => { act(() => { const clipboardEvent = new window.Event('paste', { bubbles: true, @@ -755,7 +755,7 @@ describe(' - Editing', () => { // @ts-ignore clipboardEvent.clipboardData = { - getData: () => pastedValue, + getData: () => pastedValue ?? rawValue ?? '', }; // canContinue is `false` if default have been prevented const canContinue = input.dispatchEvent(clipboardEvent); @@ -763,6 +763,10 @@ describe(' - Editing', () => { return; } + if (!pastedValue) { + return; + } + const prevValue = input.value; const nextValue = `${prevValue.slice( 0, @@ -927,6 +931,24 @@ describe(' - Editing', () => { fireEvent.change(input, { target: { value: '09/2/2022' } }); // Press 2 expectInputValue(input, '09/02/2022'); // If internal state is not reset it would be 22 instead of 02 }); + + it('should allow pasting a section', () => { + const { input, selectSection } = renderWithProps({ + defaultValue: adapter.date('2018-12-05'), + }); + + selectSection('month'); + + fireEvent.change(input, { target: { value: '1/05/2018' } }); // initiate search query on month section + expectInputValue(input, '01/05/2018'); + + firePasteEvent(input, undefined, '05'); + expectInputValue(input, '05/05/2018'); + + selectSection('month'); // move back to month section + fireEvent.change(input, { target: { value: '2/05/2018' } }); // check that the search query has been cleared after pasting + expectInputValue(input, '02/05/2018'); // If internal state is not reset it would be 12 instead of 02 + }); }); describeAdapters(