Jest макет для библиотеки реагировать-выбирать или реагировать-тестирование на изменение не срабатывает при изменении цели - PullRequest
7 голосов
/ 18 февраля 2020

В настоящее время я пытаюсь смоделировать компонентact-select, и независимо от того, что я делаю, firevent.change из реагирующей-тестирующей библиотеки, похоже, срабатывает только при первом вызове firevent.change.

Мне было интересно, почему изменение сработало только один раз и как это исправить.

Моя шутка выглядит следующим образом:

jest.mock("react-select", () => ({ options, value, onChange }) => {
  function handleChange(event) {
    console.log("called");

    const option = options.find(option => {
      return option.value == event.currentTarget.value;
    });

    onChange(option);
  }
  return (
    <select
      id="uc"
      data-testid="select"
      value={value}
      onChange={event => handleChange(event)}
    >
      {options?.map(({ label, value }) => (
        <option key={value} value={value}>
          {label}
        </option>
      ))}
    </select>
  );
});

Как вы можете видеть, это довольно простой блок выбора, и я подумал, что я смогу позвонить.

fireEvent.change(selectOptions[0], { target: { value: "0" } });

И это сработает, однако, если я затем соединю их вместе, как в следующем примере:

test("Should render add another button and function", () => {
  const mockSetOpen = jest.fn();

  const { queryAllByTestId, getByTestId, getByLabelText, debug } = renderWithRedux(
    <TabByRestraints setOpen={mockSetOpen} hidden={false} />,
    {
      userCatagories: userCategoriesMock,
      permissionGroups: permissionGroupsMock,
      roles: rolesMock
    }
  );

  // Check that the user catagories exist and user catagories values
  const selectOptions = queryAllByTestId("select");
  expect(selectOptions).toHaveLength(2);

  expect(getByTestId("user-category-row")).toBeTruthy();

  fireEvent.change(selectOptions[0], { target: { value: "0" } });
  fireEvent.change(selectOptions[1], { target: { value: "132" } });

  expect(getByLabelText("Add a new user category restraint")).toBeTruthy();
});

Я вижу, что console.log («звонил») запускается только один раз. У второго выбора на странице никогда не будет выбрано его значение, потому что тест не пройден.

Я бы хотел, чтобы оба изменения отправили событие изменения.

fireEvent.change(selectOptions[0], { target: { value: "0" } });
fireEvent.change(selectOptions[1], { target: { value: "132" } }); 

Однако это только когда-либо наборы первая.

Любая помощь очень нужна.

Ответы [ 2 ]

2 голосов
/ 25 февраля 2020

Тот факт, что render работает, но renderWithRedux не предполагает, что проблема заключается в управлении состоянием с избыточностью.

Одна вещь, на которую следует обратить внимание - установка очередей состояний для повторного рендеринга в React при отправке действие для Redux ставит в очередь изменение в собственной очереди обновлений Redux. Реактивные инструменты тестирования могут не знать, как с этим справиться.

Хотя это ближе к коду, вы можете рассмотреть возможность насмешки dispatch и проверки получения ожидаемых результатов выбранных изменений. Таким образом, вы можете проверить, работает ли ваш код, не беспокоясь о том, что делает сторонний код. (Вид иронии c, которую вы пытались избегать с использованиемact-select, когда renderWithRedux был фактической проблемой стороннего производителя.: D)

Вы также можете рассмотреть возможность прямого вызова вашего обработчика onChange и его извлечения. от выбора в вашем компоненте вместо запуска событий. Это было бы еще одним способом уменьшить количество стороннего кода, который вы тестируете и макетируете.

2 голосов
/ 24 февраля 2020

Вы должны сделать еще один запрос для элементов выбора. Далее я бы назвал go и назвал бы их по-другому, чтобы облегчить чтение / отладку теста.

  // it's easier to have separate ids for each select, will be easier to read/maintain the test in the future
  const firstSelect = queryByTestId("select1");
  fireEvent.change(firstSelect, { target: { value: "0" } });

  // a rerender might have happened so you need to query for the second select after the first event.
  const secondSelect = queryByTestId("select2");
  fireEvent.change(secondSelect, { target: { value: "132" } });

  expect(getByLabelText("Add a new user category restraint")).toBeTruthy();
...