I have this component that I am trying to test, that shows a dialog which accepts images to upload into the app:
import React from 'react';
import { Box, Typography, Dialog, DialogTitle } from '@mui/material';
import UploadBox from './UploadBox';
/**
* An interface for uploading new images to the app.
*
* @param {object} props Contains props passed to the component.
* @param {boolean} props.open Controls open/visible state of the componenet.
*
* @returns The UploadDialog componenet to be rendered in the app.
*/
function UploadDialog(props) {
const handleClose = () => {
props.onClose();
};
return(
<Dialog open={props.open} onClose={handleClose}>
<DialogTitle>
Upload Media
</DialogTitle>
<Box sx={{margin: '0 5% 0 5%'}}>
<Typography>
Drag and drop into the box, or click the button to browse
</Typography>
<UploadBox/>
</Box>
</Dialog>
);
};
export default UploadDialog;
Jest passes the first two tests of the suite that check if the component renders correctly both open and closed, but the third test that tried to toggle between these states fails.
Here is the test code:
import React from 'react';
import { screen, render } from '@testing-library/react';
import '@testing-library/jest-dom';
import UploadDialog from './UploadDialog';
jest.mock('./UploadBox', () => () => {<div/>});
describe('UploadDialog', () => {
let handleClose = jest.fn();
test('renders closed', () => {
render(<UploadDialog open={false} handleClose={handleClose}/>);
expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
});
test('renders open', () => {
render(<UploadDialog open={true} handleClose={handleClose}/>);
// There are two presentation role elements; both should be present
const expectedElements = screen.getAllByRole('presentation');
expect(expectedElements[0]).toBeInTheDocument();
expect(expectedElements[1]).toBeInTheDocument();
});
test('toggles open and closed', () => {
// This piece passes
const {rerender} = render(
<UploadDialog open={false} handleClose={handleClose}/>
);
expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
// This also gets through fine
rerender(<UploadDialog open={true} handleClose={handleClose}/>);
const expectedElements = screen.getAllByRole('presentation');
expect(expectedElements[0]).toBeInTheDocument();
expect(expectedElements[1]).toBeInTheDocument();
// This is where the problem shows up
rerender(<UploadDialog open={false} handleClose={handleClose}/>);
expect(screen.queryAllByRole('presentation').length).toBe(0);
});
});
The final test fails with the following error:
UploadDialog › toggles open and closed
expect(received).toBe(expected) // Object.is equality
Expected: 0
Received: 2
50 | rerender(<UploadDialog open={dialogOpen} handleClose={handleClose}/>);
51 |
> 52 | expect(screen.queryAllByRole('presentation').length).toBe(0);
| ^
53 | });
54 | });
When using screen.debug()
, I see only the open={true}
version of this component. I have checked that this component is behaving correctly in the app, closing and opening when expected (as the first two tests suggest), so this seems to be a problem with React Testing Library. Does rerender only work once in React Testing Library? How do I rerender a second time?