I have been trying (without success) to write a test case for ErrorBoundary
component that is handling errors via componentDidCatch lifecycle method.
Despite the error produced by child component inside the <ErrorBoundry>
component, <ErrorBoundry>
does not render info about error in code but the content of faulty component if it would work correct.
Component works as expected in production/development but not when it is executed by Jest / Enzyme for testing.
Error from testing:
PASS src/ErrorBoundary.test.js
● Console
console.error node_modules/fbjs/lib/warning.js:33
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components.
in input (at ErrorBoundary.test.js:11)
in div (at ErrorBoundary.test.js:10)
in ComponentWithError (at ErrorBoundary.test.js:26)
in ErrorBoundry (created by WrapperComponent)
in WrapperComponent
console.log src/ErrorBoundary.test.js:29
<ErrorBoundry>
<ComponentWithError>
<div>
<input type="text" value={{...}} />
</div>
</ComponentWithError>
</ErrorBoundry>
ErrorBoundry.js:
import React, { Component } from 'react'
import Raven from 'raven-js'
import { Segment, Button } from 'semantic-ui-react'
export default class ErrorBoundry extends Component {
state = {
hasError: false
}
componentDidCatch(error, info) {
this.setState({ hasError: true })
Raven.captureException(error, { extra: info });
}
render() {
if(this.state.hasError) {
return (
<div className='error-boundry'>
<Segment>
<h2> Oh no! Somethin went wrong </h2>
<p>Our team has been notified, but click
<Button onClick={() => Raven.lastEventId() && Raven.showReportDialog()}>
here </Button> to fill out a report.
</p>
</Segment>
</div>
);
} else {
return this.props.children;
}
}
}
ErrorBoundry.test.js:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import renderer from 'react-test-renderer'
import { shallow, mount } from 'enzyme'
import ErrorBoundary from './ErrorBoundary'
class ComponentWithError extends Component {
render() {
return (
<div>
<input type = "text" value = {null}/>
</div>
);
}
}
describe('<ErrorBoundary> window',()=> {
it('should match the snapshot', () => {
const tree = renderer.create(<ErrorBoundary>Test</ErrorBoundary> ).toJSON()
expect(tree).toMatchSnapshot()
})
it('displays error message on error generated by child', () => {
const wrapper = mount(
<ErrorBoundary >
<ComponentWithError />
</ErrorBoundary>
)
console.log(wrapper.debug() )
})
})
Enzyme has simulateError
helper now.
So this works very well for me:
const Something = () => null;
describe('ErrorBoundary', () => {
it('should display an ErrorMessage if wrapped component throws', () => {
const wrapper = mount(
<ErrorBoundary>
<Something />
</ErrorBoundary>
);
const error = new Error('test');
wrapper.find(Something).simulateError(error);
/* The rest fo your test */
}
}