In an answer to a different SO question about how to test propTypes
in React using Jest, I proposed a solution that mocks console.error
, something others have done before but which I thought could be improved. My solution, a function, is below. The example code below contains some arbitrary propTypes
that are then tested. For each test, I expected the first sub-array of "acceptable values" to not cause the mock of console.error
to have been called by React, but I expected each test prop value in the second sub-array of "unacceptable values" to cause the mock to have been called.
The testPropTypes
Function
const testPropTypes = (component, propName, arraysOfTestValues, otherProps) => {
console.error = jest.fn();
const _test = (testValues, expectError) => {
for (let propValue of testValues) {
console.error.mockClear();
React.createElement(component, {...otherProps, [propName]: propValue});
expect(console.error).toHaveBeenCalledTimes(expectError ? 1 : 0);
}
};
_test(arraysOfTestValues[0], false);
_test(arraysOfTestValues[1], true);
};
Example Code
MyComponent.js (just the propTypes
):
MyComponent.propTypes = {
myProp1: React.PropTypes.number, // optional number
myProp2: React.PropTypes.oneOfType([ // required number or array of numbers
React.PropTypes.number,
React.PropTypes.arrayOf(React.PropTypes.number)
]).isRequired
MyComponent.test.js:
describe('MyComponent', () => {
it('should accept an optional number for myProp1', () => {
const testValues = [
[0, null], // acceptable values
['', {}, [], Symbol(), true] // unacceptable values
];
testPropTypes(MyComponent, 'myProp1', testValues, {myProp2: 123});
});
it('should require a number or an array of numbers for myProp2', () => {
const testValues = [
[0, [0]], // acceptable values
['', {}, [], Symbol(), true, null] // unacceptable values
];
testPropTypes(MyComponent, 'myProp2', testValues);
});
});
The code seems to work fine in simple circumstances. However, the sub-array of unacceptable test prop values for the more complex propType
, i.e. for myProp2
, produces some funny results. The presence or absence of null
(which tests for whether the prop is optional or required) makes no difference, i.e. it behaves properly all the time. However, the other test prop type values seem to interact with each other in some mysterious way. If a single non-null
unacceptable test prop value is used, the test performs as expected. However, if more than one such non-null
unacceptable test prop value is used, the test breaks, responding as if the second, third, etc. unacceptable types (again, other than null
) are actually acceptable.
What's going on and how can I fix this?