How could I write tests for uncovered lines in useEffect and dispatch?

Viewed 481

I recently started to write a test, so I am not familiar with that.

When I run :

$ yarn test:coverage

I face this result:

enter image description here

I want to get list of Models through dispatch when my drop-down will change (formik.values.make), and also when user select models, get list of trims.

How could I write a test for these two lines:

useEffect(() => {
    if (formik.values.make) {
      dispatch(carModelsSuccess(formik.values.make));// <-- 59 line ***
    }
    if (formik.values.model) {
      dispatch(carTrimsSuccess(formik.values.model));// <--- 62 line ***
    }
}, [dispatch, formik.values.make, formik.values.model])

and this part :

<FormControl className={classes.formControl} disabled={!formik.values.model}>
    <InputLabel id="trim">Trim</InputLabel>
    <Select
        data-testid="trim"
        labelId="trim"
        id="trim"
        name="trim"
        value={formik.values.trim}
        onChange={formik.handleChange}
    >
        {carTrims?.map(({ name, value }) => (
          <MenuItem value={value} key={value}>{name}</MenuItem>
        ))}
    </Select>
</FormControl>

I work with Next.js and I want write tests with Jest and @testing-library/react. I also used material-UI for select option. I searched a lot in google on how to write tests for this code, but I couldn't find anything.

2 Answers

I succeeded in writing the test : adding inputProps={{ id: "trimInput" }} to select tag like this :

<Select
  inputProps={{
    id: "trimInput"
   }}
  data-testid="trim"
  labelId="trim"
  id="trim"
  name="trim"
  value={formik.values.trim}
  onChange={formik.handleChange}
 >
  {carTrims?.map(({ name, value }) => (
    <MenuItem value={value} key={value}>{name}</MenuItem>
 ))}
and this is test:
describe('fetch form options', () => {
  it('dispatches the actions', async () => {
    const { container } = render(<Provider store={store}><FormSection /></Provider>);
    store.dispatch = jest.fn();
    await act(async () => {
      let makeSelectInput = container.querySelector(
        "#makeInput"
      ) as HTMLDivElement;
      fireEvent.change(makeSelectInput, { target: { value: "bmw" } });
    });
    expect(store.dispatch).toBeCalledWith(carModelsSuccess('bmw'));
    await act(async () => {
      let modelSelectInput = container.querySelector(
        "#modelInput"
      ) as HTMLDivElement;
      fireEvent.change(modelSelectInput, { target: { value: "320i" } });
    });
    expect(store.dispatch).toBeCalledWith(carTrimsSuccess('320i'));
  });
});

useEffect will be called on render itself, you just need to render with the corresponding props that are needed.

Imagining your code is in a component named TestComponent that's getting the formik as props, see the code below

const props = {
    formik: {
        values: {
          make: 'Japan' // a truthy value,
          model: 2010 // a truthy value
        }
    },
   dispatch: Jest.fn()
}
const {getByTestId} = render(<TestComponent {...props} />);

This will get you coverage for those lines.

Related