Comments (25)
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.
This would be really useful for anyone using create-react-app, as PropType errors would appear in the new error overlay
from prop-types.
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.
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.
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.
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.
We recently upgraded Jest to latest and had to drop this. I don't know of any alternatives :/
from prop-types.
Related to previous conversation here.
from prop-types.
@artin-phares I've created typed-props library which has the same interface and produce an array of validation report issues.
from prop-types.
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.
@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.
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.
@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.
@mmiszy Why are you using process.nextTick
?
from prop-types.
I don't get what's the difference between @sarbbottam's and @mmiszy's workarounds.
from prop-types.
@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.
@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.
ah, you’re right, I’d forgotten that react 16 changed that behavior around error catching.
from prop-types.
Ok, I understand this but if I add process.nextTick
to my code the process exits:
from prop-types.
Do you have the latest React?
from prop-types.
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.
@jzaefferer The latter does not work for me.
Is there any advance or solution is there alternatives for this pain?
from prop-types.
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.
fwiw, there's nothing specific to jest in there - that technique should be applied for every testing framework.
from prop-types.
@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)
- v15.8.0 breaks `PropTypes.shape({...})` for objects and class-instances. HOT 11
- 15.8.0: `checkPropTypes` sometimes throws: Cannot read properties of undefined (reading 'hasOwnProperty') HOT 11
- Children required prop-types fire warning on create HOT 5
- Update to @babel/preset-react7.10.1 HOT 3
- _propTypes.default.shapeOf is not a function HOT 1
- Potential isRequired bug in v15.8.0 and above HOT 10
- TypeError: Cannot destructure property 'checkPropTypes' as it is undefined. HOT 2
- error (checkPropTypes is not a function) while using with sveltekit HOT 1
- Accidental issue creation, apologies
- Failed prop type: Converting circular structure to JSON when stringifying React jsx HOT 6
- Conditional prop for value another prop HOT 2
- Error : `_propTypes2.default.oneOfType is not a function` HOT 2
- `oneOfType()` does not seem to allow all types specified HOT 2
- SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED HOT 1
- Importing a reference to PropTypes as opposed Proptypes directly HOT 4
- List transitive failures on failure of oneOfType
- The `prop-types` package import is not suddenly recognized when running jest HOT 6
- Update prop-types Version | Severity: high HOT 2
- [spam]
- Add a PropType for an exact shape plus "...rest" properties HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from prop-types.