prop-types: Add ability to throw error instead of warning in tests

In tests it would be nice to throw an error if the property isn’t of its expected type.

It would be nice if this could be scoped to our own components and not 3rd party ones using 3rd party components, but thats not necesary.

People are already turning console.warning calls to throw errors, so this would be a nice upgrade for them.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 60
  • Comments: 26

Most upvoted comments

For anyone else trying to captures prop-type errors in unit tests with Jest - this setupTest.js works for us:

beforeEach(() => {
  jest.spyOn(console, 'error')
  jest.spyOn(console, 'warn')
})

afterEach(() => {
  /* eslint-disable no-console,jest/no-standalone-expect */
  expect(console.error).not.toBeCalled()
  expect(console.warn).not.toBeCalled()
})

This breaks when any test calls jest.restoreAllMocks() - for us, calling jest.clearAllMocks()` instead helped.

It also requires your app to not call console.error or console.warn for “error handling” (scare quotes, since that’s usually not a good idea).

I’m trying to use prop-types to validate js schema of external service response on server.
And surprised it’s just generating console warnings.
How do I supposed to react to validation errors?

checkPropTypes should definitely generate some report (like suggested in #88), or at least return true/false. Anyway it would be nice for user to decide how validation results should be handled (log, throw error, etc).

This would be really useful for anyone using create-react-app, as PropType errors would appear in the new error overlay

My solution with Jest:

jest.mock('prop-types/checkPropTypes', () => {
  return (...args) => {
    const checkPropTypes = jest.requireActual('prop-types/checkPropTypes');
    const originalConsoleError = console.error;
    console.error = function(...args) {
      process.nextTick(() => {
        throw new Error(...args);
      });
    };
    const result = checkPropTypes(...args);
    console.error = originalConsoleError;
    return result;
  };
});

I am not sure what is the current state of this issue and the project.

I am using a small wrapper to throw error like so:

PropTypes.originalCheckPropTypes = PropTypes.checkPropTypes;
PropTypes.checkPropTypes = function(propTypes, attrs, attrsName, componentName) {
  const consoleError = console.error;
  console.error = function(message) {
    throw new Error(message);
  };
  PropTypes.originalCheckPropTypes(propTypes, attrs, attrsName, componentName);
  console.error = consoleError;
};

I just published a check-prop-types package that does this. The main export returns the error instead of logging it, and a helper assertPropTypes throws it.

#54 on this repo also has an interesting approach, using a callback instead.

I’m currently using Jest and my solution was to mock the console, then every warning or error will throw an error when running the tests. Hope this can be useful for someone else.

global.console = {
  log: jest.fn(),
  warn: (message) => {
    throw Error(message)
  },
  error: (message, data, details) => {
    throw Error(
      message + (data ? " - " + data : "") + (details ? " - " + details : "")
    )
  },
}

We recently upgraded Jest to latest and had to drop this. I don’t know of any alternatives 😕