Open aodinok opened 3 years ago
This looks like a problem in App.tsx, specifically, how you throw an error in the react function
https://blog.pusher.com/react-error-boundaries/
Error Boundaries were introduced [...] to solve the problem of being unable to handle render errors due to the declarative nature of React components.
No, it is not because of error boundaries. Same happens if component is wrapped in ErrorBoundary, I pushed the updated example with ErrorBoundary where this issue can be reproduced as well.
In short, this doesn't work:
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import { expect } from 'chai';
import App from './AppWithBoundary';
describe('<App>', () => {
it('renders without error', () => {
render(<App initialSimulateError={false} />)
expect(screen.getByRole('button')).not.to.eql('null');
});
it('throws error', () => {
// Neither of this works
// try {
// const { getByText } = render(<App />);
// const createAccount = getByText(/Hello world/i);
// expect(document.body.contains(createAccount));
// } catch (err) {
// console.log('error catch successful')
// }
expect(() => render(<App initialSimulateError={false} />)).to.throw();
});
});
And even this:
it('throws error', () => {
try {
expect(() => render(<App initialSimulateError={true} />)).to.throw();
} catch (err) {
console.log('catched error', err)
}
console.log('test execution end')
});
Still failing test because of uncaught error, even though it is wrapped in try/catch. Something is definitely going wrong there.
This has to do with how chai and react interact witb each other, not web test runner.
If you use this assertion from chai, it expects an error to be thrown synchronously by the render function.
Any suggestions how this can be avoided? Maybe you know other assertion library that will work for that use case?
Unfortunately I'm not really familiar enough with react to know that
import {ErrorBoundary} from 'react-error-boundary'
test('error is thrown', async () => { const fallbackRender = jest.fn(() => null) render(
) fireEvent.click(await screen.findByText('Add todo'));
await waitFor(() => expect(fallbackRender).toHaveBeenCalled()) expect(fallbackRender.mock.calls[0].error).toMatchInlineSnapshot(/ jest will update this /) })
Reproduction repo: https://github.com/aodinok/wtr-rtl-example
Please see linked repo to reproduce the problem. This looks like some kind of conflict between testing-library and wtr. The error that is thrown inside rendered component is thrown in a way that it can't be catched by test code and appears later in the console.
I spend 2 hours debugging this and couldn't find a solution 😞 Would appreciate any help or advice!
If you throw error from other places it works and catched properly, when error is thrown from component that is rendered by testing-library - it can't be catched.
Even this simple test fails:
const TestComponent = () => { throw new Error('test'); };
describe('test, () => { it('throws', () => { expect(() => render( )).to.throw();
});
});