How to test that a dropdown selector has value set in React with React Testing Library?
Having the following code:
import { useForm, Controller } from 'react-hook-form';
...
const { handleSubmit, reset, control, register, watch } = useForm({
resolver: yupResolver(schema)
});
const availableSensorPoolOptions = [
{ id: '0', name: 'sensor pool 0' },
{ id: '1', name: 'sensor pool 1' },
{ id: '2', name: 'sensor pool 2' }
];
...
onSubmit={handleSubmit(onAddSubmit)} // the action when the submit is called
...
const onAddSubmit = (data) => {
postSignalMapping(data); // the API call if all is good
toggle();
reset();
};
...
<div data-testid={MapSignalModalTestIds.AVAILABLE_SENSOR_POOL}>
<Controller
control={control}
name='availableSensorPool'
render={({ field: { onChange } }) =>
<SelectInput
label={t('calculation-engine.available-sensor-pool')}
initialSelectedOption={{ id: '0', name: '' }}
onChange={onChange}
options={availableSensorPoolOptions}
/>
}
/>
</div>
There are multiple SelectInput
s like thi, but in this example it will be only one
const schema = yup.object().shape({
availableSensorPool: yup.object().shape({
id: yup.string(),
name: yup.string()
})
});
const { handleSubmit, reset, control, register, watch } = useForm({
resolver: yupResolver(schema)
});
And here is the test:
import { fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderWithClientInstance } from '@oam/shared/test-utils';
import '@testing-library/jest-dom';
import MapSignalModal from './map-signal-modal';
describe('MapSignalModal', () => {
const title = 'title';
const toggle = jest.fn();
const postSignalMapping = jest.fn();
it('should call postSignalMapping function on clicking in Save button successfully', async () => {
const { getByTestId, getByLabelText } = renderWithClientInstance(
<MapSignalModal title={title} open={true} toggle={toggle} />
);
const saveButton = getByTestId('submit-button');
expect(saveButton).toBeInTheDocument();
userEvent.selectOptions(
getByLabelText('calculation-engine.available-sensor-pool'),
'sensor pool 0'
);
fireEvent.click(saveButton);
await waitFor(() => {
expect(postSignalMapping).toBeCalled();
});
});
});
it fails with the error:
TestingLibraryElementError: Value "sensor pool 0" not found in options
Solution 1:
So, since the select
behavior is being achieved using a button
and span
s.
You need to first click the button this would bring all the options on the screen and then you need to click one of those options.
And then you can finally test that the selected option is now on the screen.
it("test dropdpwn", async () => {
const { getByTestId, getByLabelText } = renderWithClientInstance(
<MapSignalModal title={title} open={true} toggle={toggle} />
);
userEvent.click(screen.getAllByTestId("selectButton")[0]);
userEvent.click(screen.getByText("sensor pool 1"));
expect(
await screen.findByText(screen.getByText("sensor pool 1"))
).toBeInTheDocument();
});
Also, to be really sure you can try the following, this should fail because "sensor pool 1" option is not initially on the screen.
And it should pass when the text is changed to "sensor pool 0" because that's there on the screen initially.
it("test dropdpwn", async () => {
const { getByTestId, getByLabelText } = renderWithClientInstance(
<MapSignalModal title={title} open={true} toggle={toggle} />
);
expect(screen.getByText("sensor pool 1")).toBeInTheDocument();
// if you replace the above text to "sensor pool 0", it should work
});
For testing if postSignalMapping
is being called you can mock it as shown below:
let mockPostSignalMapping = jest.fn();
jest.mock("../lib/hooks/use-post-signal-mapping", () => ({
mutate: mockPostSignalMapping,
}));
it("test dropdpwn", async () => {
// Do stuff
await waitFor(() => {
expect(mockPostSignalMapping).toBeCalled();
});
});