Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ternary condition for default mask values #1797

Merged
merged 2 commits into from
May 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/DateTimePicker/DateTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function useInterceptProps({
maxTime: maxDateTime || maxTime,
disableTimeValidationIgnoreDatePart: Boolean(minDateTime || maxDateTime),
acceptRegex: willUseAmPm ? /[\dap]/gi : /\d/gi,
mask: mask || willUseAmPm ? '__/__/____ __:__ _M' : '__/__/____ __:__',
mask: mask || (willUseAmPm ? '__/__/____ __:__ _M' : '__/__/____ __:__'),
inputFormat: pick12hOr24hFormat(inputFormat, ampm, {
localized: utils.formats.keyboardDateTime,
'12h': utils.formats.keyboardDateTime12h,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/TimePicker/TimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function useInterceptProps({
maxTime,
ampm: willUseAmPm,
acceptRegex: willUseAmPm ? /[\dapAP]/gi : /\d/gi,
mask: mask || willUseAmPm ? '__:__ _M' : '__:__',
mask: mask || (willUseAmPm ? '__:__ _M' : '__:__'),
getOpenDialogAriaText: getTextFieldAriaText,
openPickerIcon: <ClockIcon />,
inputFormat: pick12hOr24hFormat(inputFormat, ampm, {
Expand Down
36 changes: 35 additions & 1 deletion lib/src/__tests__/DateTimePicker.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
import * as React from 'react';
import DateFnsUtils from '@date-io/date-fns';
import DateFnsLocaleDe from 'date-fns/locale/de';
import LocalizationProvider from '../LocalizationProvider';
import { ReactWrapper } from 'enzyme';
import { TextField } from '@material-ui/core';
import { mount as enzymeDefaultMount } from 'enzyme';
import { MaterialUiPickersDate } from '../typings/date';
import { createClientRender, fireEvent } from './createClientRender';
import { mount, utilsToUse, mountPickerWithState } from './test-utils';
import { DateTimePicker, DateTimePickerProps } from '../DateTimePicker/DateTimePicker';
import {
DesktopDateTimePicker,
DateTimePicker,
DateTimePickerProps,
} from '../DateTimePicker/DateTimePicker';

const format = process.env.UTILS === 'moment' ? 'MM/DD/YYYY HH:mm' : 'MM/dd/yyyy hh:mm';

describe('DateTimePicker', () => {
const render = createClientRender();

describe('prop: mask', () => {
it('should take the mask prop into account', () => {
const { getByRole } = render(
<LocalizationProvider dateAdapter={DateFnsUtils} locale={DateFnsLocaleDe}>
<DesktopDateTimePicker
renderInput={props => <TextField autoFocus {...props} />}
mask="__.__.____ __:__"
onChange={() => {}}
value={null}
/>
</LocalizationProvider>
);
const textbox = getByRole('textbox');
fireEvent.change(textbox, {
target: {
value: '12',
},
});
expect(textbox.value).toBe('12.');
});
});
});

describe('e2e - DateTimePicker', () => {
let component: ReactWrapper<DateTimePickerProps>;

Expand Down
191 changes: 191 additions & 0 deletions lib/src/__tests__/createClientRender.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/**
* Copy and paste from https://github.com/mui-org/material-ui/blob/master/test/utils/createClientRender.js.
*/
import * as React from 'react';
import PropTypes from 'prop-types';
import {
act,
buildQueries,
cleanup,
createEvent,
fireEvent as rtlFireEvent,
queries,
render as testingLibraryRender,
prettyDOM,
} from '@testing-library/react/pure';

// holes are *All* selectors which aren't necessary for id selectors
const [queryDescriptionOf, , getDescriptionOf, , findDescriptionOf] = buildQueries(
function queryAllDescriptionsOf(container: HTMLElement, element: HTMLElement) {
return container.querySelectorAll(`#${element.getAttribute('aria-describedby')}`);
} as any,
function getMultipleError() {
return `Found multiple descriptions. An element should be described by a unique element.`;
},
function getMissingError() {
return `Found no describing element.`;
}
);

const customQueries = { queryDescriptionOf, getDescriptionOf, findDescriptionOf };

/**
*
* @param {React.ReactElement} element
* @param {object} [options]
* @param {boolean} [options.baseElement] - https://testing-library.com/docs/react-testing-library/api#baseelement-1
* @param {boolean} [options.disableUnnmount] - if true does not cleanup before mount
* @param {boolean} [options.strict] - wrap in React.StrictMode?
* @returns {import('@testing-library/react').RenderResult<typeof queries & typeof customQueries> & { setProps(props: object): void}}
* TODO: type return RenderResult in setProps
*/
function clientRender(
element: any,
options: { wrapper?: any; baseElement?: any; strict?: boolean } = {}
) {
const { baseElement, strict = true, wrapper: InnerWrapper = React.Fragment } = options;

const Mode = strict ? React.StrictMode : React.Fragment;
function Wrapper({ children }: { children?: React.ReactNode }) {
return (
<Mode>
<InnerWrapper>{children}</InnerWrapper>
</Mode>
);
}
Wrapper.propTypes = { children: PropTypes.node };

const result = testingLibraryRender(element, {
baseElement,
queries: { ...queries, ...customQueries },
wrapper: Wrapper,
}) as any;

/**
* convenience helper. Better than repeating all props.
*/
result.setProps = function setProps(props: any) {
result.rerender(React.cloneElement(element, props));
return result;
};

result.forceUpdate = function forceUpdate() {
result.rerender(
React.cloneElement(element, {
'data-force-update': String(Math.random()),
})
);
return result;
};

return result;
}

export function createClientRender(globalOptions: { strict?: boolean } = {}) {
const { strict: globalStrict } = globalOptions;

afterEach(async () => {
// If this issues an act() warning you probably didn't
// wait for an async event in your test (or didn't wrap it in act() at all).
// please wait for every update in your test and make appropriate assertions
await cleanup();
});

return function configuredClientRender(element: any, options: { strict?: boolean } = {}) {
const { strict = globalStrict, ...localOptions } = options;

return clientRender(element, { ...localOptions, strict });
};
}

const fireEvent = Object.assign(rtlFireEvent, {
// polyfill event.key(Code) for chrome 49 and edge 15 (supported in Material-UI v4)
// for user-interactions react does the polyfilling but manually created
// events don't have this luxury
keyDown(element: any, options: { key?: string; keyCode?: string } = {}) {
// `element` shouldn't be `document` but we catch this later anyway
const document = element.ownerDocument || element;
const target = document.activeElement || document.body || document.documentElement;
if (target !== element) {
// see https://www.w3.org/TR/uievents/#keydown
const error = new Error(
`\`keydown\` events can only be targeted at the active element which is ${prettyDOM(
target,
undefined,
{ maxDepth: 1 }
)}`
);
// We're only interested in the callsite of fireEvent.keyDown
error.stack = error.stack
? error.stack
.split('\n')
.filter(line => !/at Function.key/.test(line))
.join('\n')
: '';
throw error;
}

const event = createEvent.keyDown(element, options) as any;
Object.defineProperty(event, 'key', {
get() {
return options.key || '';
},
});
if (options.keyCode !== undefined && event.keyCode === 0) {
Object.defineProperty(event, 'keyCode', {
get() {
return options.keyCode;
},
});
}

rtlFireEvent(element, event);
},
keyUp(element: any, options: { key?: string; keyCode?: string } = {}) {
// `element` shouldn't be `document` but we catch this later anyway
const document = element.ownerDocument || element;
const target = document.activeElement || document.body || document.documentElement;
if (target !== element) {
// see https://www.w3.org/TR/uievents/#keyup
const error = new Error(
`\`keyup\` events can only be targeted at the active element which is ${prettyDOM(
target,
undefined,
{ maxDepth: 1 }
)}`
);
// We're only interested in the callsite of fireEvent.keyUp
error.stack = error.stack
? error.stack
.split('\n')
.filter(line => !/at Function.key/.test(line))
.join('\n')
: '';
throw error;
}
const event = createEvent.keyUp(element, options) as any;
Object.defineProperty(event, 'key', {
get() {
return options.key || '';
},
});
if (options.keyCode !== undefined && event.keyCode === 0) {
Object.defineProperty(event, 'keyCode', {
get() {
return options.keyCode;
},
});
}

rtlFireEvent(element, event);
},
});

export * from '@testing-library/react/pure';
export { act, cleanup, fireEvent };

export function render() {
throw new Error(
"Don't use `render` directly. Instead use the return value from `createClientRender`"
);
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"@babel/runtime": "^7.8.4",
"@cypress/webpack-preprocessor": "^4.1.0",
"@percy/cypress": "^2.3.0",
"@testing-library/dom": "^7.5.7",
"@testing-library/react": "^10.0.4",
"@typescript-eslint/eslint-plugin": "^1.6.0",
"@typescript-eslint/parser": "^1.6.0",
"cypress": "4.5.0",
Expand Down
Loading