-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Jasmine fails on errors in React 16 components #1453
Comments
I was able to reproduce the issue without using an Error Boundary. It looks like React is triggering an |
Yeah, I've added an Error Boundary to my sample to show that I can't catch this error. Does Jasmine have a way to expect on error events? |
My temporary solution for now: function catchWindowError(testSpec, handleError) {
const backup = window.onerror;
const unhandledErrors = [];
function onUnhandledError(error) {
unhandledErrors.push(error);
}
let regularError;
try {
window.onerror = onUnhandledError;
testSpec();
} catch (error) {
regularError = error;
}
window.onerror = backup;
handleError(regularError, unhandledErrors);
}
it("should throw an error on empty props", () => {
catchWindowError(() => {
mount(<MyComp />);
}, error => {
expect(error).toEqual(new Error("MockCmp requires <name> prop"));
});
}); |
Jasmine doesn't currently have any way to Thanks for using Jasmine! |
@slackersoft I think this issue should be renamed -- as @sgravrock mentioned, Error Boundary usage is not required for Jasmine to fail to catch thrown errors in React 16 components. I'd also like to suggest this get some kind of prioritization. Right now there doesn't seem to be a built-in way to properly handle |
I spent a bit of time digging into this recently. I'm seeing some inconsistency in whether or not a global I've had some success with using an error boundary to take control of the behavior, e.g.:
This can be used to write tests that expect an error to occur, that fail if an error occurs, or (if you really want to) that don't care if an error occurs:
There are a couple of major issues still: React will log the error to the console even if it's caught by an error boundary, and Enzyme will throw if you try to do anything to the wrapper after the error is caught. I don't believe there's anything Jasmine can do about those issues, and to my way of thinking they seriously limit the usefulness of any test that intentionally causes a component to throw. To cover all the bases around React 16 errors and error boundaries, I think we need three things:
I don't think Jasmine itself can or should solve any of those problems. The first is best handled with individual test code, as above. The second is ultimately up to react-dom, and the third seems to be solidly on Enzyme's turf (or on the turf of whatever it is that people use instead of Enzyme). Further discussion and new ideas are welcome but as it is I'm inclined to close this since I don't think there's anything that Jasmine can do to help the situation. |
Not sure how it works for you. I've used MyComp from CodePen, copied you error boundary and tests, and added one more test that always pass. Code: class SpecErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { isError: false };
}
componentDidCatch(error, info) {
if (this.props.errorHandler) {
this.props.errorHandler(error);
} else {
// Rethrow from a setTimeout so react can't catch it.
// This way it will fail the test suite even if the error
// might not be associated with the test that caused it.
setTimeout(() => {
throw error;
});
}
this.setState({ isError: true });
}
render() {
if (this.state.isError) {
return "Error";
}
return this.props.children;
}
}
class MyComp extends React.Component {
componentDidMount() {
throw new Error("Ha-ha!");
}
render() {
return <span>{"No error"}</span>;
}
}
describe("React 16 issues", () => {
it("should always pass", () => {
expect(true).toBe(true);
});
it("throws an exception", () => {
const errorHandler = jasmine.createSpy("errorHandler");
mount(
<SpecErrorBoundary errorHandler={errorHandler}>
<MyComp />
</SpecErrorBoundary>
);
expect(errorHandler).toHaveBeenCalledWith(
jasmine.objectContaining({ message: "Ha-ha!" })
);
});
xit("fails the suite if an exception is thrown", () => {
mount(
<SpecErrorBoundary>
<MyComp />
</SpecErrorBoundary>
);
});
}); Results:
|
There is also another weird issue with results duplication: it there're many other tests (even excluded), output will be duplicated. But maybe this is an issue with
|
Okay, with
|
I haven't been able to reproduce either the test failure or the duplication. I wonder if the duplication has something to do with the reporter that you're using. Here's what I get with
|
We ran into this issue, we fixed it by spying on it('should handle an error correctly', () => {
const onerror = spyOn(window, 'onerror');
// do something that throws the error
expect(onerror).toHaveBeenCalled();
}) |
Yay! Thank you! |
Expected Behavior
The test should be green
Current Behavior
Test fails.
Possible Solution
Suite that reproduces the behavior (for bugs)
A React component has an error which is caught by an Error Boundary. React prints the error in console and Jasmine fails the test.
CodePen
Context
Not sure if it's desired behavior in Jasmine.
Your Environment
The text was updated successfully, but these errors were encountered: