GithubHelp home page GithubHelp logo

Comments (25)

jzaefferer avatar jzaefferer commented on May 4, 2024 8

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).

from prop-types.

iainbeeston avatar iainbeeston commented on May 4, 2024 6

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

from prop-types.

art-in avatar art-in commented on May 4, 2024 6

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).

from prop-types.

mmiszy avatar mmiszy commented on May 4, 2024 5

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;
  };
});

from prop-types.

sarbbottam avatar sarbbottam commented on May 4, 2024 4

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;
};

from prop-types.

uniphil avatar uniphil commented on May 4, 2024 3

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.

from prop-types.

jzaefferer avatar jzaefferer commented on May 4, 2024 1

We recently upgraded Jest to latest and had to drop this. I don't know of any alternatives :/

from prop-types.

seanadenise avatar seanadenise commented on May 4, 2024

Related to previous conversation here.

from prop-types.

rumkin avatar rumkin commented on May 4, 2024

@artin-phares I've created typed-props library which has the same interface and produce an array of validation report issues.

from prop-types.

a-ignatov-parc avatar a-ignatov-parc commented on May 4, 2024

There is a workaround for throwing an error on warnings. We can use getStack argument.

PropTypes.checkPropTypes(spec, values, 'prop', name, () => {
    process.nextTick(() => {
        throw new Error('Check has failed');
    });
});

This should work even in browsers with process.nextTick polyfill.

from prop-types.

asapach avatar asapach commented on May 4, 2024

@a-ignatov-parc, won't nextTick cause it to fail after the test has already completed? Potentially even after test runner has already finished. Not very useful.

from prop-types.

a-ignatov-parc avatar a-ignatov-parc commented on May 4, 2024

nextTick will be called before the current event loop continues, so it will throw after the warning is printed and before everything else.

from prop-types.

rumkin avatar rumkin commented on May 4, 2024

@a-ignatov-parc Thrown error will loose the stack in that way and it will not be captured in the place where it was thrown. Also printing of PropTypes' message will not be stopped.

from prop-types.

jpenna avatar jpenna commented on May 4, 2024

@mmiszy Why are you using process.nextTick?

from prop-types.

vince1995 avatar vince1995 commented on May 4, 2024

I don't get what's the difference between @sarbbottam's and @mmiszy's workarounds.

from prop-types.

ljharb avatar ljharb commented on May 4, 2024

@vince1995 the second one throws the error in nextTick, which means you don't get a useful stack trace that tells you where console.error was called.

from prop-types.

mmiszy avatar mmiszy commented on May 4, 2024

@vince1995 @ljharb quite the opposite, actually. Throwing the error without nextTick results in the error being caught by React. It does result in a test failure, however, the stacktrace is much longer. It also includes the default React warning Consider adding an error boundary to your tree to customize error handling behaviour. Visit https://fb.me/react-error-boundaries to learn more about error boundaries.]. I found this error message to be misleading in this context.

After adding nextTick, the problems are gone. You get even more useful stracktrace without all the React functions. And the warning is not displayed. You can see for yourself:

Error message in Jest without nextTick:

  ● MyComponent › should be able to do something

    Error: Uncaught [Error: The above error occurred in one of your React components:
        in Unknown (at Database/index.js:23)
        in Unknown (created by Context.Consumer)
        in withRouter(withApiData(waitForApi(MyComponent))) (created by ConnectFunction)
        in ConnectFunction (at MyComponent.test.js:87)
        in Router (created by MemoryRouter)
        in MemoryRouter (at MyComponent.test.js:86)
        in Provider (at MyComponent.test.js:85)

    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://fb.me/react-error-boundaries to learn more about error boundaries.]

      14 |     const originalConsoleError = console.error;
      15 |     console.error = function(...args) {
    > 16 |       throw new Error(...args);
         |             ^
      17 |     };
      18 |     const result = checkPropTypes(...args);
      19 |     console.error = originalConsoleError;

      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:680:7)
      at CustomConsole.console.error (src/setupTests.js:16:13)
      at VirtualConsole.on.e (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:680:7)

Error message in Jest with nextTick

  ● MyComponent › should be able to do something

    Warning: Failed prop type: The prop `dsadsadas` is marked as required in `MyComponent`, but its value is `undefined`.
        in MyComponent (at Database/index.js:58)
        in Unknown (at Database/index.js:23)
        in Unknown (created by Context.Consumer)
        in withRouter(withApiData(waitForApi(MyComponent))) (created by ConnectFunction)
        in ConnectFunction (at MyComponent.test.js:87)
        in Router (created by MemoryRouter)
        in MemoryRouter (at MyComponent.test.js:86)
        in Provider (at MyComponent.test.js:85)

      15 |     console.error = function(...args) {
      16 |       process.nextTick(() => {
    > 17 |         throw new Error(...args);
         |               ^
      18 |       });
      19 |     };
      20 |     const result = checkPropTypes(...args);

      at process.nextTick (src/setupTests.js:17:15)

from prop-types.

ljharb avatar ljharb commented on May 4, 2024

ah, you’re right, I’d forgotten that react 16 changed that behavior around error catching.

from prop-types.

vince1995 avatar vince1995 commented on May 4, 2024

Ok, I understand this but if I add process.nextTick to my code the process exits:

image

from prop-types.

mmiszy avatar mmiszy commented on May 4, 2024

Do you have the latest React?

from prop-types.

vince1995 avatar vince1995 commented on May 4, 2024

Yes.

This is my setup-tests.js file
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import MutationObserver from "mutation-observer";

import Parse from "parse";


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;
  };
});

require("jest-fetch-mock");

Parse.CoreManager.set('IS_NODE', false);

process.env.SERVER_RENDERING = true;

const parseServerInfo = {
  url: "...",
  appId: "...",
  key: "..."
}

Parse.initialize(parseServerInfo.appId, parseServerInfo.key);
Parse.serverURL = parseServerInfo.url;

global.MutationObserver = MutationObserver;

configure({ adapter: new Adapter() });


window.matchMedia = window.matchMedia || function () {
  return {
    matches: false,
    addListener: function () { },
    removeListener: function () { }
  };
};

And my tests:
    shouldCrashTests.map(testCase => {
        test("Accordion: " + testCase.name, () => {

            function shouldThrow() {
                const wrapper = render(testCase.items);
            }

            expect(shouldThrow).toThrow()

        });
    })

EDIT: I've created a new project. Still fails with nextTick. Without it works.

Maybe my node version is different to yours? Mine is v12.13.1

from prop-types.

vicasas avatar vicasas commented on May 4, 2024

@jzaefferer The latter does not work for me.

Is there any advance or solution is there alternatives for this pain?

from prop-types.

vicasas avatar vicasas commented on May 4, 2024

Neither example worked for me. So create a new npm package to solve this problem and it is compatible with the latest version of Jest (27).

https://github.com/vicasas/jest-prop-types

from prop-types.

ljharb avatar ljharb commented on May 4, 2024

fwiw, there's nothing specific to jest in there - that technique should be applied for every testing framework.

from prop-types.

vicasas avatar vicasas commented on May 4, 2024

@ljharb I don't have the same experience in other testing frameworks, I don't know how they work. If anyone wants to help you are welcome and we can rename the repo and the npm package.

from prop-types.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.