From 5a861e86f6def7f2321c4428f9b5dcc241245924 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 20 Dec 2023 00:32:23 +0200 Subject: [PATCH] [fields] Fix section pasting (#11447) --- .../tests/editing.DateField.test.tsx | 26 ++++++++++++- .../src/internals/hooks/useField/useField.ts | 9 ++++- test/e2e/index.test.ts | 37 ++++++++++++++++++- 3 files changed, 68 insertions(+), 4 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( 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) { diff --git a/test/e2e/index.test.ts b/test/e2e/index.test.ts index ff6f9bdc39b4..56e738c8d607 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,44 @@ 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 () => { + // 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'); + 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 input.press('ArrowLeft'); + // copy day section value + await input.press(`${modifier}+KeyC`); + // move to month section + await input.press('ArrowLeft'); + // initiate search query on month section + await input.press('1'); + // paste day section value to month section + 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('', () => { it('should allow selecting a value', async () => {