I am facing an issue while writing a test for my error boundary higher-order component (HOC). The problem arises when I mock throwing an error in my wrapped component, causing the test to fail because it recognizes the error as a genuine one instead of understanding that it was intended for testing purposes. I'm unsure about what I might be doing incorrectly here.
Here is the code snippet for the ErrorBoundary HOC:
interface StateProps {
error: unknown;
info: unknown;
}
interface ErrorBoundaryProps {
createNotification(...args: any): void;
}
const connector = connect(null, {
createNotification: createNotificationAction,
});
export const withErrorBoundary = <P extends object>(TargetComponent: React.ComponentType<P>) => {
class ErrorBoundary extends React.Component<ErrorBoundaryProps, StateProps> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = {
error: null,
info: null,
};
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.props.createNotification({
alertType: 'error',
message: `${TargetComponent.name} is not being rendered. Error: ${error.message}`,
});
this.setState({ error, info: errorInfo });
}
public render() {
const { ...props } = this.props;
if (this.state.error instanceof Error) {
return null;
}
return <TargetComponent {...(props as P)} />;
}
}
return connector(ErrorBoundary) as any;
};
And here is the test scenario:
describe('ErrorBoundary HOC', () => {
let store;
let createNotification;
let props;
beforeEach(() => {
store = configureStore(defaultState);
createNotification = jest.fn();
props = {
createNotification,
};
});
test('Renders nothing if error', async () => {
const targetComponent = () => {
throw new Error('Errored!');
};
const WrappedComponent = withErrorBoundary(targetComponent);
const RenderedComponent = render(
<BrowserRouter>
<Provider store={store}>
<WrappedComponent {...props} />
</Provider>
</BrowserRouter>
);
await waitFor(() => expect(() => WrappedComponent.toThrow()));
expect(RenderedComponent.container.hasChildNodes()).toBeFalsy();
await waitFor(() => expect(createNotification).toHaveBeenCalled());
});
});
Upon investigation, I discovered that the error is thrown before rendering in the test environment. However, I am still uncertain about how to resolve this issue.
Thank you in advance for any assistance provided.