Skip to content

Commit 671cc92

Browse files
Fix
1 parent f795262 commit 671cc92

File tree

6 files changed

+184
-13
lines changed

6 files changed

+184
-13
lines changed

packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx

+64
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
describeValue,
1212
describePicker,
1313
getFieldSectionsContainer,
14+
getFieldInputRoot,
1415
} from 'test/utils/pickers';
1516
import { describeConformance } from 'test/utils/describeConformance';
17+
import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField';
1618

1719
describe('<MobileDateRangePicker /> - Describes', () => {
1820
const { render, clock } = createPickerRenderer({
@@ -102,4 +104,66 @@ describe('<MobileDateRangePicker /> - Describes', () => {
102104
return newValue;
103105
},
104106
}));
107+
108+
// With single input field
109+
describeValue<PickerRangeValue, 'picker'>(MobileDateRangePicker, () => ({
110+
render,
111+
componentFamily: 'picker',
112+
type: 'date-range',
113+
variant: 'mobile',
114+
initialFocus: 'start',
115+
isSingleInput: true,
116+
defaultProps: {
117+
slots: { field: SingleInputDateRangeField },
118+
},
119+
clock,
120+
values: [
121+
// initial start and end dates
122+
[adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-04')],
123+
// start and end dates after `setNewValue`
124+
[adapterToUse.date('2018-01-02'), adapterToUse.date('2018-01-05')],
125+
],
126+
emptyValue: [null, null],
127+
assertRenderedValue: (expectedValues: any[]) => {
128+
const fieldRoot = getFieldInputRoot(0);
129+
130+
const expectedStartValueStr = expectedValues[0]
131+
? adapterToUse.format(expectedValues[0], 'keyboardDate')
132+
: 'MM/DD/YYYY';
133+
134+
const expectedEndValueStr = expectedValues[1]
135+
? adapterToUse.format(expectedValues[1], 'keyboardDate')
136+
: 'MM/DD/YYYY';
137+
138+
const expectedValueStr = `${expectedStartValueStr}${expectedEndValueStr}`;
139+
140+
expectFieldValueV7(fieldRoot, expectedValueStr);
141+
},
142+
setNewValue: (
143+
value,
144+
{ isOpened, applySameValue, setEndDate = false, selectSection, pressKey },
145+
) => {
146+
let newValue: PickerNonNullableRangeValue;
147+
if (applySameValue) {
148+
newValue = value;
149+
} else if (setEndDate) {
150+
newValue = [value[0], adapterToUse.addDays(value[1], 1)];
151+
} else {
152+
newValue = [adapterToUse.addDays(value[0], 1), value[1]];
153+
}
154+
155+
if (isOpened) {
156+
fireEvent.click(
157+
screen.getAllByRole('gridcell', {
158+
name: adapterToUse.getDate(newValue[setEndDate ? 1 : 0]).toString(),
159+
})[0],
160+
);
161+
} else {
162+
selectSection('day');
163+
pressKey(undefined, 'ArrowUp');
164+
}
165+
166+
return newValue;
167+
},
168+
}));
105169
});

packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx

+103
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,107 @@ describe('<MobileDateTimeRangePicker /> - Describes', () => {
151151
return newValue;
152152
},
153153
}));
154+
155+
describeValue<PickerRangeValue, 'picker'>(MobileDateTimeRangePicker, () => ({
156+
render,
157+
componentFamily: 'picker',
158+
type: 'date-time-range',
159+
variant: 'mobile',
160+
initialFocus: 'start',
161+
clock,
162+
values: [
163+
// initial start and end dates
164+
[adapterToUse.date('2018-01-01T11:30:00'), adapterToUse.date('2018-01-04T11:45:00')],
165+
// start and end dates after `setNewValue`
166+
[adapterToUse.date('2018-01-02T12:35:00'), adapterToUse.date('2018-01-05T12:50:00')],
167+
],
168+
emptyValue: [null, null],
169+
assertRenderedValue: (expectedValues: any[]) => {
170+
const hasMeridiem = adapterToUse.is12HourCycleInCurrentLocale();
171+
const expectedPlaceholder = hasMeridiem ? 'MM/DD/YYYY hh:mm aa' : 'MM/DD/YYYY hh:mm';
172+
173+
const startSectionsContainer = getFieldSectionsContainer(0);
174+
const expectedStartValueStr = expectedValues[0]
175+
? adapterToUse.format(
176+
expectedValues[0],
177+
hasMeridiem ? 'keyboardDateTime12h' : 'keyboardDateTime24h',
178+
)
179+
: expectedPlaceholder;
180+
expectFieldValueV7(startSectionsContainer, expectedStartValueStr);
181+
182+
const endSectionsContainer = getFieldSectionsContainer(1);
183+
const expectedEndValueStr = expectedValues[1]
184+
? adapterToUse.format(
185+
expectedValues[1],
186+
hasMeridiem ? 'keyboardDateTime12h' : 'keyboardDateTime24h',
187+
)
188+
: expectedPlaceholder;
189+
expectFieldValueV7(endSectionsContainer, expectedEndValueStr);
190+
},
191+
setNewValue: (
192+
value,
193+
{ isOpened, applySameValue, setEndDate = false, selectSection, pressKey },
194+
) => {
195+
let newValue: PickerNonNullableRangeValue;
196+
if (applySameValue) {
197+
newValue = value;
198+
} else if (setEndDate) {
199+
newValue = [
200+
value[0],
201+
adapterToUse.addMinutes(adapterToUse.addHours(adapterToUse.addDays(value[1], 1), 1), 5),
202+
];
203+
} else {
204+
newValue = [
205+
adapterToUse.addMinutes(adapterToUse.addHours(adapterToUse.addDays(value[0], 1), 1), 5),
206+
value[1],
207+
];
208+
}
209+
if (isOpened) {
210+
fireEvent.click(
211+
screen.getByRole('gridcell', {
212+
name: adapterToUse.getDate(newValue[setEndDate ? 1 : 0]).toString(),
213+
}),
214+
);
215+
const hasMeridiem = adapterToUse.is12HourCycleInCurrentLocale();
216+
const hours = adapterToUse.format(
217+
newValue[setEndDate ? 1 : 0],
218+
hasMeridiem ? 'hours12h' : 'hours24h',
219+
);
220+
const hoursNumber = adapterToUse.getHours(newValue[setEndDate ? 1 : 0]);
221+
fireEvent.click(screen.getByRole('option', { name: `${parseInt(hours, 10)} hours` }));
222+
fireEvent.click(
223+
screen.getByRole('option', {
224+
name: `${adapterToUse.getMinutes(newValue[setEndDate ? 1 : 0])} minutes`,
225+
}),
226+
);
227+
if (hasMeridiem) {
228+
// meridiem is an extra view on `DesktopDateTimeRangePicker`
229+
// we need to click it to finish selection
230+
fireEvent.click(screen.getByRole('option', { name: hoursNumber >= 12 ? 'PM' : 'AM' }));
231+
}
232+
} else {
233+
selectSection('day');
234+
pressKey(undefined, 'ArrowUp');
235+
236+
selectSection('hours');
237+
pressKey(undefined, 'ArrowUp');
238+
239+
selectSection('minutes');
240+
pressKey(undefined, 'PageUp'); // increment by 5 minutes
241+
242+
const hasMeridiem = adapterToUse.is12HourCycleInCurrentLocale();
243+
if (hasMeridiem) {
244+
selectSection('meridiem');
245+
const previousHours = adapterToUse.getHours(value[setEndDate ? 1 : 0]);
246+
const newHours = adapterToUse.getHours(newValue[setEndDate ? 1 : 0]);
247+
// update meridiem section if it changed
248+
if ((previousHours < 12 && newHours >= 12) || (previousHours >= 12 && newHours < 12)) {
249+
pressKey(undefined, 'ArrowUp');
250+
}
251+
}
252+
}
253+
254+
return newValue;
255+
},
256+
}));
154257
});

packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeField.ts

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
useControlledValueWithTimezone,
1212
useFieldInternalPropsWithDefaults,
1313
UseFieldResponse,
14+
useNullablePickerContext,
1415
} from '@mui/x-date-pickers/internals';
1516
import { useValidation } from '@mui/x-date-pickers/validation';
1617
import { useMultiInputRangeFieldTextFieldProps } from './useMultiInputRangeFieldTextFieldProps';
@@ -158,6 +159,7 @@ export function useMultiInputRangeField<
158159
defaultValue: defaultValue === undefined ? undefined : defaultValue[0],
159160
onChange: handleStartDateChange,
160161
autoFocus,
162+
// ...(pickerContext?.variant === 'mobile' && { readOnly: true }),
161163
},
162164
});
163165

@@ -173,6 +175,7 @@ export function useMultiInputRangeField<
173175
defaultValue: defaultValue === undefined ? undefined : defaultValue[1],
174176
onChange: handleEndDateChange,
175177
autoFocus: false,
178+
// ...(pickerContext?.variant === 'mobile' && { readOnly: true }),
176179
},
177180
});
178181

packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ export function createMultiInputRangeField<TManager extends PickerAnyRangeManage
7272
enableAccessibleFieldDOMStructure: props.enableAccessibleFieldDOMStructure,
7373
dateSeparator: props.dateSeparator,
7474
});
75-
const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, manager.valueType);
75+
const { internalProps: rawInternalProps, forwardedProps } = useSplitFieldProps(
76+
themeProps,
77+
manager.valueType,
78+
);
79+
const internalProps = { ...rawInternalProps, readOnly: true };
7680

7781
const {
7882
slots,

packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/useTextFieldProps.ts

-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ export function useTextFieldProps({
8080
// TODO: Decide if we also want to set the default labels on standalone fields.
8181
label: pickerContext ? translations[position] : undefined,
8282
focused: pickerContext?.open ? rangePosition === position : undefined,
83-
...(pickerContext?.variant === 'mobile' && { readOnly: true }),
8483
},
8584
ownerState: { ...ownerState, position },
8685
});

test/e2e/index.test.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -994,31 +994,30 @@ async function initializeEnvironment(
994994
await page.waitForSelector('[role="tooltip"]', { state: 'detached' });
995995
});
996996

997-
it('should have the same selection process when "readOnly" with single input field with an accessible DOM structure', async () => {
997+
it('should have the same selection process as a non-range picker when using a single input field with an accessible DOM structure', async () => {
998998
// firefox in CI is not happy with this test
999999
if (browserType.name() === 'firefox') {
10001000
return;
10011001
}
10021002

10031003
await renderFixture('DatePicker/ReadonlyDesktopDateRangePickerSingle');
1004+
await page.getByRole('button').click();
10041005

1005-
await page.locator(`.${pickersSectionListClasses.root}`).first().click();
1006-
1007-
// assert that the tooltip has been opened
1008-
await page.waitForSelector('[role="tooltip"]', { state: 'attached' });
1006+
// assert that the dialog has been opened
1007+
await page.waitForSelector('[role="dialog"]', { state: 'attached' });
10091008

10101009
await page.getByRole('gridcell', { name: '11' }).first().click();
10111010
await page.getByRole('gridcell', { name: '13' }).first().click();
10121011

10131012
// assert that the tooltip closes after selection is complete
1014-
await page.waitForSelector('[role="tooltip"]', { state: 'detached' });
1013+
await page.waitForSelector('[role="dialog"]', { state: 'detached' });
10151014

10161015
expect(await page.getByRole('textbox', { includeHidden: true }).inputValue()).to.equal(
10171016
'04/11/2022 – 04/13/2022',
10181017
);
10191018
});
10201019

1021-
it('should have the same selection process when "readOnly" with single input field with a non-accessible DOM structure', async () => {
1020+
it('should have the same selection process as a non-range picker when using a single input field with a non-accessible DOM structure', async () => {
10221021
// firefox in CI is not happy with this test
10231022
if (browserType.name() === 'firefox') {
10241023
return;
@@ -1027,17 +1026,16 @@ async function initializeEnvironment(
10271026
await renderFixture(
10281027
'DatePicker/ReadonlyDesktopDateRangePickerSingleNonAccessibleDOMStructure',
10291028
);
1030-
1031-
await page.getByRole('textbox').click();
1029+
await page.getByRole('button').click();
10321030

10331031
// assert that the tooltip has been opened
1034-
await page.waitForSelector('[role="tooltip"]', { state: 'attached' });
1032+
await page.waitForSelector('[role="dialog"]', { state: 'attached' });
10351033

10361034
await page.getByRole('gridcell', { name: '11' }).first().click();
10371035
await page.getByRole('gridcell', { name: '13' }).first().click();
10381036

10391037
// assert that the tooltip closes after selection is complete
1040-
await page.waitForSelector('[role="tooltip"]', { state: 'detached' });
1038+
await page.waitForSelector('[role="dialog"]', { state: 'detached' });
10411039

10421040
expect(await page.getByRole('textbox').inputValue()).to.equal('04/11/2022 – 04/13/2022');
10431041
});

0 commit comments

Comments
 (0)