Skip to content

Commit

Permalink
Avoid localized time formats (#1991)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmtrKovalenko committed Jul 15, 2020
1 parent 6b0d30b commit 97aa0a7
Show file tree
Hide file tree
Showing 18 changed files with 113 additions and 164 deletions.
3 changes: 3 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"env": {
"UTILS": "date-fns"
},
"windows": {
"program": "${workspaceFolder}/lib/node_modules/jest/bin/jest"
}
Expand Down
1 change: 1 addition & 0 deletions docs/pages/demo/datepicker/CustomDay.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default function CustomDay(props) {

return (
<DatePicker
disableMaskedInput
showDaysOutsideCurrentMonth
label="Week picker"
value={selectedDate}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ function DateTimePickerDemo(props) {
value={selectedDate}
onChange={handleDateChange}
onError={console.log}
disableMaskedInput
inputFormat={props.__willBeReplacedGetFormatString({
moment: 'YYYY/MM/DD HH:mm',
dateFns: 'yyyy/MM/dd HH:mm',
})}
mask="___/__/__ __:__"
/>
</React.Fragment>
);
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/demo/timepicker/SecondsTimePicker.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function SecondsTimePicker() {
openTo="hours"
views={['hours', 'minutes', 'seconds']}
inputFormat="HH:mm:ss"
mask="__:__:__"
label="With seconds"
value={selectedDate}
onChange={date => handleDateChange(date)}
Expand All @@ -24,6 +25,7 @@ function SecondsTimePicker() {
openTo="minutes"
views={['minutes', 'seconds']}
inputFormat="mm:ss"
mask="__:__"
label="Minutes and seconds"
value={selectedDate}
onChange={date => handleDateChange(date)}
Expand Down
8 changes: 4 additions & 4 deletions e2e/component/DateTimePicker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ describe('<DateTimePicker />', () => {

// Year
cy.findByText('2015').click();
cy.get('input').should('have.value', '10/07/2015 7:36 PM');
cy.get('input').should('have.value', '10/07/2015 07:36 PM');

// Date
cy.findByLabelText('next month')
.click()
.click();
cy.findByLabelText('Dec 22, 2015').click();
cy.get('input').should('have.value', '12/22/2015 7:36 PM');
cy.get('input').should('have.value', '12/22/2015 07:36 PM');

// Hour
cy.findByRole('menu').trigger('mouseup', { buttons: 1, offsetX: 66, offsetY: 157 });
cy.get('input').should('have.value', '12/22/2015 8:36 PM');
cy.get('input').should('have.value', '12/22/2015 08:36 PM');

// Minute
cy.findByRole('menu').trigger('mouseup', {
Expand All @@ -43,6 +43,6 @@ describe('<DateTimePicker />', () => {
offsetY: 180,
});

cy.get('input').should('have.value', '12/22/2015 8:20 PM');
cy.get('input').should('have.value', '12/22/2015 08:20 PM');
});
});
6 changes: 0 additions & 6 deletions e2e/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ module.exports = (on, config) => {
},
module: {
rules: [
// {
// test: /\.(ts|tsx)?$/,
// loader: 'ts-loader',
// options: { transpileOnly: true },
// },
{
test: /\.(ts|tsx)?$/,
loader: 'babel-loader',
Expand All @@ -28,7 +23,6 @@ module.exports = (on, config) => {

on('file:preprocessor', wp(options));
on('task', percyHealthCheck);
// require('cypress-react-unit-test/plugins/react-scripts')(on, config);

return config;
};
12 changes: 6 additions & 6 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@
}
},
"dependencies": {
"@date-io/date-fns": "^2.6.0",
"@date-io/dayjs": "^2.6.0",
"@date-io/luxon": "^2.6.0",
"@date-io/moment": "^2.6.0",
"@date-io/date-fns": "^2.8.0",
"@date-io/dayjs": "^2.8.0",
"@date-io/luxon": "^2.8.0",
"@date-io/moment": "^2.8.0",
"clsx": "^1.0.2",
"prop-types": "^15.7.2",
"react-transition-group": "^4.4.1",
"rifm": "^0.12.0"
},
"scripts": {
"test": "jest",
"test:typescript": "rimraf src/__tests__/dist && tsc -p src/__tests__/tsconfig.json",
"test:typescript": "yarn rimraf src/__tests__/dist && tsc -p src/__tests__/tsconfig.json",
"test:date-fns": "UTILS=date-fns yarn test",
"test:dayjs": "UTILS=datejs yarn test",
"test:luxon": "UTILS=luxon yarn test",
Expand All @@ -83,6 +83,7 @@
"@babel/preset-react": "^7.9.4",
"@babel/runtime": "^7.9.6",
"@cypress/webpack-preprocessor": "^4.1.1",
"@date-io/core": "^2.8.0",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@rollup/plugin-babel": "^5.0.3",
Expand All @@ -105,7 +106,6 @@
"babel-plugin-react-remove-properties": "^0.3.0",
"codecov": "^3.6.5",
"cross-env": "^7.0.2",
"cypress-react-unit-test": "^3.3.1",
"date-fns": "^2.12.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
Expand Down
5 changes: 2 additions & 3 deletions lib/src/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView';
import { MobileWrapper, DesktopWrapper, StaticWrapper } from '../wrappers/Wrapper';
import { makeValidationHook, ValidationProps } from '../_shared/hooks/useValidation';
import { ParsableDate, defaultMinDate, defaultMaxDate } from '../constants/prop-types';
import { getFormatByViews, validateDate, DateValidationError } from '../_helpers/date-utils';
import { makePickerWithStateAndWrapper, AllPickerProps } from '../Picker/makePickerWithState';
import { getFormatAndMaskByViews, validateDate, DateValidationError } from '../_helpers/date-utils';

export type DatePickerView = 'year' | 'date' | 'month';

Expand Down Expand Up @@ -38,8 +38,7 @@ const datePickerConfig = {
openTo,
minDate,
maxDate,
mask: '__/__/____',
inputFormat: getFormatByViews(views, utils),
...getFormatAndMaskByViews(views, utils),
...other,
};
},
Expand Down
6 changes: 3 additions & 3 deletions lib/src/DateTimePicker/DateTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export interface BaseDateTimePickerProps
function useInterceptProps({
ampm,
inputFormat,
mask,
maxDate: __maxDate = defaultMaxDate,
maxDateTime: __maxDateTime,
maxTime: __maxTime,
Expand Down Expand Up @@ -87,8 +86,9 @@ function useInterceptProps({
maxTime: maxDateTime || maxTime,
disableIgnoringDatePartForTimeValidation: Boolean(minDateTime || maxDateTime),
acceptRegex: willUseAmPm ? /[\dap]/gi : /\d/gi,
mask: mask || (willUseAmPm ? '__/__/____ __:__ _M' : '__/__/____ __:__'),
inputFormat: pick12hOr24hFormat(inputFormat, ampm, {
mask: '__/__/____ __:__',
disableMaskedInput: willUseAmPm,
inputFormat: pick12hOr24hFormat(inputFormat, willUseAmPm, {
localized: utils.formats.keyboardDateTime,
'12h': utils.formats.keyboardDateTime12h,
'24h': utils.formats.keyboardDateTime24h,
Expand Down
6 changes: 3 additions & 3 deletions lib/src/TimePicker/TimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export function getTextFieldAriaText(value: ParsableDate, utils: MuiPickersAdapt
function useInterceptProps({
ampm,
inputFormat,
mask,
maxTime: __maxTime,
minTime: __minTime,
openTo = 'hours',
Expand All @@ -47,10 +46,11 @@ function useInterceptProps({
maxTime,
ampm: willUseAmPm,
acceptRegex: willUseAmPm ? /[\dapAP]/gi : /\d/gi,
mask: mask || (willUseAmPm ? '__:__ _M' : '__:__'),
mask: '__:__',
disableMaskedInput: willUseAmPm,
getOpenDialogAriaText: getTextFieldAriaText,
openPickerIcon: <ClockIcon />,
inputFormat: pick12hOr24hFormat(inputFormat, ampm, {
inputFormat: pick12hOr24hFormat(inputFormat, willUseAmPm, {
localized: utils.formats.fullTime,
'12h': utils.formats.fullTime12h,
'24h': utils.formats.fullTime24h,
Expand Down
5 changes: 3 additions & 2 deletions lib/src/__tests__/DateTimePickerTestingLib.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ describe('<DateTimePicker />', () => {
render(
<DesktopDateTimePicker
renderInput={props => <TextField autoFocus {...props} />}
ampm={false}
inputFormat={utilsToUse.moment ? 'MM.DD.YYYY HH:mm' : 'mm.dd.yyyy hh:mm'}
mask="__.__.____ __:__"
onChange={() => {}}
value={null}
Expand All @@ -25,15 +27,14 @@ describe('<DateTimePicker />', () => {
},
});

expect(textbox.value).toBe('12');
expect(textbox.value).toBe('12.');
});

it('prop: maxDateTime – minutes is disabled by date part', async () => {
render(
<DesktopDateTimePicker
open
openTo="minutes"
mask="__.__.____ __:__"
onChange={() => {}}
renderInput={props => <TextField {...props} />}
value={utilsToUse.date('2018-01-01T12:00:00.000Z')}
Expand Down
1 change: 1 addition & 0 deletions lib/src/__tests__/KeyboardDateTimePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('e2e - DesktopDateTimePicker', () => {
onChange={onChangeMock}
onClose={onCloseMock}
onOpen={onOpenMock}
disableMaskedInput
inputFormat={format}
OpenPickerButtonProps={{ id: 'keyboard-button' }}
renderInput={props => <TextField {...props} />}
Expand Down
20 changes: 17 additions & 3 deletions lib/src/__tests__/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const EnzymeAdapter = require('enzyme-adapter-react-16');
Enzyme.configure({ adapter: new EnzymeAdapter() });

// Convert any console error into a thrown error
const error = console.error;
console.error = (...args: any[]) => {
error.apply(console, args as any);
const consoleError = console.error;
const consoleWarn = console.warn;

function logAndThrowArgs(...args: any[]) {
if (args[0] instanceof Error) {
throw args[0];
} else {
Expand All @@ -25,4 +26,17 @@ console.error = (...args: any[]) => {
.join(' ');
throw new Error(message);
}
}

console.error = (...args: any[]) => {
consoleError.apply(console, args as any);
logAndThrowArgs(...args);
};

// Waiting to fix https://github.com/mui-org/material-ui-pickers/issues/1924
if (process.env.UTILS !== 'moment') {
console.warn = (...args: any[]) => {
consoleWarn.apply(console, args as any);
logAndThrowArgs(...args);
};
}
2 changes: 2 additions & 0 deletions lib/src/__tests__/test-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,5 @@ export const toHaveBeenCalledExceptMoment = (mock: jest.Mock<any, any>, params:

return expect(mock).toHaveBeenCalledWith(...params);
};

export const itOnlyIf = (condition: boolean) => condition ? it : it.skip
1 change: 1 addition & 0 deletions lib/src/__tests__/unit/text-field-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('test-field-helper', () => {
`(
'checkMaskIsValidFormat returns $expected for mask $mask and format $format',
({ format, mask, expected }) => {
console.warn = jest.fn();
const formatForCurrentLib =
typeof format === 'string'
? format
Expand Down
20 changes: 16 additions & 4 deletions lib/src/_helpers/date-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,28 @@ export const isYearOnlyView = (views: readonly DatePickerView[]) =>
export const isYearAndMonthViews = (views: readonly DatePickerView[]) =>
views.length === 2 && arrayIncludes(views, 'month') && arrayIncludes(views, 'year');

export const getFormatByViews = (views: readonly DatePickerView[], utils: MuiPickersAdapter) => {
export const getFormatAndMaskByViews = (
views: readonly DatePickerView[],
utils: MuiPickersAdapter
) => {
if (isYearOnlyView(views)) {
return utils.formats.year;
return {
mask: '____',
inputFormat: utils.formats.year,
};
}

if (isYearAndMonthViews(views)) {
return utils.formats.monthAndYear;
return {
disableMaskedInput: true,
inputFormat: utils.formats.monthAndYear,
};
}

return utils.formats.keyboardDate;
return {
mask: '__/__/____',
inputFormat: utils.formats.keyboardDate,
};
};

export function parsePickerInputValue(
Expand Down
4 changes: 2 additions & 2 deletions lib/src/_helpers/text-field-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export function checkMaskIsValidForCurrentFormat(
const isMaskValid =
inferredFormatPatternWith2Digits === mask && inferredFormatPatternWith1Digits === mask;

// @ts-ignore
if (!isMaskValid && process.env.NODE_ENV !== 'production') {
// @ts-ignore Ignore this warning for luxon because it is appearing mostly always (related to the formats structure of luxon itself)
if (!isMaskValid && utils.lib !== 'luxon' && process.env.NODE_ENV !== 'production') {
console.warn(
`The mask "${mask}" you passed is not valid for the format used ${format}. Falling down to uncontrolled not-masked input.`
);
Expand Down
Loading

1 comment on commit 97aa0a7

@vercel
Copy link

@vercel vercel bot commented on 97aa0a7 Jul 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.