I am testing a react component which has a simple Material-ui
switch that updates a boolean field. The component works without any issues when I run the app locally.
In my test, I am mocking the graphql calls via MockedProvider
. The mocked provider works as expected, and I can see that the initial response and the update response arrive and they update the state. However, when I find the switch and check it on the screen, it stays unchecked. My test fails with:
Received element is checked: <input checked="" class="PrivateSwitchBase-input-40 MuiSwitch-input" name="callbackEnabled" type="checkbox" value="" />
My first guess is that React doesn't rerender this state change. Do I need to somehow force rerender? Or what is the correct way of testing this kind of behaviour?
The test:
it('should update boolean field', async () => {
const mocks = [
{
request: {
query: myQuery,
variables: {
clientId: 'cl_0',
},
},
result: {
data: {
myQuery: {
callbackEnabled: true
},
},
},
},
{
request: {
query: myMutation,
variables: {
clientId: 'cl_0',
callbackEnabled: false,
},
},
result: {
data: {
myMutation: {
callbackEnabled: false,
},
},
},
},
];
let base = null;
await act(async () => {
const { baseElement, } = render(
<MockedProvider mocks={mocks} addTypename={false}>
<MyComponent clientId="cl_0" error={undefined} />
</MockedProvider>
);
base = baseElement;
});
// eslint-disable-next-line no-promise-executor-return
await new Promise((resolve) => setTimeout(resolve, 0));
// check for info: https://www.apollographql.com/docs/react/development-testing/testing/#testing-the-success-state
// testing initial state: these pass
expect(base).toBeTruthy();
expect(screen.getByRole('checkbox', { name: /callbacks/i })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: /callbacks/i })).toBeChecked();
// simulate a switch click
await act(async () => {
userEvent.click(screen.getByRole('checkbox', { name: 'Callbacks' }));
});
// eslint-disable-next-line no-promise-executor-return
await new Promise((resolve) => setTimeout(resolve, 0)); // wait for response
// fails here
expect(screen.getByRole('checkbox', { name: /callbacks/i })).not.toBeChecked();
});