0

Having the following code:

    import { useForm, Controller } from 'react-hook-form';
    ...
      const { handleSubmit, reset, control, register, watch } = useForm({
        resolver: yupResolver(schema)
      });
    
    
    const sensorOptions = [
      { id: '0', name: 'sensor 0' },
      { id: '1', name: 'sensor 1' },
      { id: '2', name: 'sensor 2' }
    ];
    
    
    ...

onSubmit={handleSubmit(onAddSubmit)} // the action when the submit is called

...
  const onAddSubmit = (data) => {
    postData(data); // the API call if all is good
    toggle();
    reset();
  };

...
    
              <div data-testid={TestIds.SENSOR}>
                <Controller
                  control={control}
                  name='availableSensor'
                  render={({ field: { onChange } }) =>
                    <SelectInput
                      label='sensor')}
                      initialSelectedOption={{ id: '0', name: '' }}
                      onChange={onChange}
                      options={sensorOptions}
                    />
                  }
                />
              </div>

There are multiple SelectInputs like thi, but in this example it will be only one

const schema = yup.object().shape({
  sensor: 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 '../shared/test-utils';

import '@testing-library/jest-dom';
import MyModal from './my-modal';
describe('MyModal', () => {
  const title = 'title';
  const toggle = jest.fn();
  const postData = jest.fn();

  it('should call postData function on clicking in Save button successfully', async () => {
    const { getByTestId, getByLabelText } = renderWithClientInstance(
      <MyModal title={title} open={true} toggle={toggle} />
    );

    const saveButton = getByTestId('submit-button');
    expect(saveButton).toBeInTheDocument();

    userEvent.selectOptions(
      getByLabelText('sensor'),
      'sensor 0'
    );

    fireEvent.click(saveButton);

    await waitFor(() => {
      expect(postData).toBeCalled();
    });
  });
});

it fails with the error:

TestingLibraryElementError: Value "sensor 0" not found in options

4
  • Let's do some debugging here, can you tell what text the options display? I mean by what text you see the options on the screen? Commented Jan 15, 2022 at 12:18
  • But you would not see an array on the screen, right? You would either see id or name. Can you do one thing just put screen.debug() in your test after render remove everything else. You would import screen from '@testing-library/react' Commented Jan 15, 2022 at 12:22
  • it doesn't show that part, it doesn't show the whole screen, I commented out unit and description in order to see available-sensor-pool. Here is the output: pastebin.com/gxF7qm0A Commented Jan 15, 2022 at 12:27
  • Oh so its actually not creating a select DOM node, its made up of divs and spans. Let me add an answer then Commented Jan 15, 2022 at 12:29

1 Answer 1

5

So, since the select behavior is being achieved using a button and spans.

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();
  });
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.