I'm trying to test that when a <Switch /> component is clicked, my application responds in the appropriate way. I've had great success using React Testing Library, but in this case I can't seem to simulate a click on a <Switch /> component.
A simple component and a simple test:
import React, {useState} from 'react';
import {fireEvent, render} from '@testing-library/react';
import wait from 'waait';
import Switch from '@material-ui/core/Switch';
const MyComponent = () => {
const [checked, setChecked] = useState(false);
return (
<Switch
data-testid="foo"
checked={checked}
onChange={() => setChecked(!checked)}
/>
);
};
describe('Testing a Switch', () => {
it('works', async () => {
const {getByTestId} = render(<MyComponent />);
const myComponent = getByTestId('foo');
expect(myComponent).not.toHaveAttribute('checked', '');
fireEvent.click(myComponent);
fireEvent.change(myComponent, {target: {checked: true}});
// just in case
await wait(1000);
expect(myComponent).toHaveAttribute('checked', '');
});
});
When the test runs, it fails at the last assertion. The virtual representation of the MUI Switch looks like:
<input
class="PrivateSwitchBase-input-24 MuiSwitch-input"
type="checkbox"
value=""
/>
None of the fireEvent.click or fireEvent.change events from RTL Seem to have any affect.
I realize this could be an issue on RTL or even jest-dom but I'm not certain yet. I realize MUI is tested with RTL so I looked at the MUI tests for <Switch /> but they still seem to use Enzyme.
firing event clicks should result in
<input
class="PrivateSwitchBase-input-24 MuiSwitch-input"
type="checkbox"
value=""
checked=""
/>
I'm not sure that a live example would be helpful for a test running issue, but I'd be happy to put together a repo to recreate what I'm experiencing.
| Tech | Version |
| ----------- | ------- |
| Material-UI | v4.4.2 |
| React | 16.9 |
| Browser | |
| TypeScript | |
| etc. | |
You should use byRole queries. These should be your go-to query. If these don't work with our components then this is a bug.
We don't have any guarantee that the root element matches the semantics of it's native counterpart.
I realize MUI is tested with RTL so I looked at the MUI tests for
but they still seem to use Enzyme.
Yeah :sweat_smile:
@eps1lon Thanks so much for your reply!
I tried getByRole but still no luck in getting the switch to change states:
describe('Testing a Switch', () => {
it('works', async () => {
const {getByRole} = render(<MyComponent />);
const myComponent = getByRole('checkbox');
fireEvent.click(myComponent);
fireEvent.change(myComponent, {target: {checked: ''}});
// just in case ?
await wait(1000);
expect(myComponent).toHaveAttribute('checked', '');
});
});
鈽濓笍 this still results in an unchanged (unchecked) switch. I also tried the role "switch" but computer said no.
Unable to find an accessible element with the role "switch"
Here are the accessible roles:
checkbox:
<input
class="PrivateSwitchBase-input-16 MuiSwitch-input"
type="checkbox"
value=""
/>
Unable to find an accessible element with the role "switch"
Yeah that is definitely a bug. Switch should have the switch role. Thank you for testing this.
const { getByRole } = render(<Switch defaultChecked />);
// how a user would trigger it
getByRole('checkbox').click();
fireEvent.change(getByRole('checkbox'), { target: { checked: '' } });
expect(getByRole('checkbox')).to.have.property('checked', false);
For more context (checkbox vs switch) see #17870
Most helpful comment
For more context (checkbox vs switch) see #17870