Обновление не обернуто в act (), и фиктивная функция не запускается. реагировать-тестирование-библиотека, шутка

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

Заранее благодарю за ваше время и внимание,

Я рыскал в Интернете и пробовал много вещей, но мне все еще не повезло - вот в чем проблема.

В общем, я слежу за https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning.

Использование библиотеки react-testing-library в тандеме с jest - и возникновение двух проблем

  1. Warning: An update to Login inside a test was not wrapped in act(...).
  2. Jest не понимает, что шутка называется

Я действительно думаю, что у меня все подключено правильно - не знаю, что мне не хватает. Внутри макета я могу поместить console.log и могу подтвердить, что макет действительно вызывается.

/*
  Test
*/
it('should call props.fetchSignIn with the username and password', async () => {
  const promise = Promise.resolve({
    email: '[email protected]',
    firstName: 'Mike',
    lastName: 'A',
  });
  const fetchSignIn = jest.fn(() => promise);
  const { queryByTestId, queryByPlaceholderText } = renderLogin({
    fetchSignIn,
  });
  const emailInput = queryByPlaceholderText('[email protected]');
  const passwordInput = queryByPlaceholderText('password');
  const submitButton = queryByTestId('submitButton');

  fireEvent.change(emailInput, {
    target: { value: '[email protected]' },
  });
  fireEvent.change(passwordInput, { target: { value: 'Password1!' } });

  fireEvent.click(submitButton);

  // I expected this to fail from the parameters being wrong
  expect(fetchSignIn).toHaveBeenCalledWith('asf');

  await act(() => promise);
});
/*
  Functional Component using the `useState(...)` hooks
  onFormFinished is the form `onSubmit` handler
*/
  const handleSignIn = async (
    email: string,
    password: string
  ): Promise<UserContextType['user']> => {
    setIsLoginInFlight(true);
    try {
      const result = await props.fetchSignIn(email, password);
      setIsLoginInFlight(false);
      return result;
    } catch (error) {
      // Other logic removed
  };

  const onFormFinish = async (values: FormValues): Promise<void> => {
    const { email, password } = values;
    const signInResult = await handleSignIn(email, password);

    // Other logic removed
  };

Происходят две вещи 1 - Это предупреждение 2 - Тест не проходит, потому что fetchSignIn никогда не вызывается

Что ожидается Тест не пройден из-за вызова fetchSignIn, но неверные параметры

Любой вклад или запрос разъяснений приветствуются.

Спасибо


person MichaelA58    schedule 13.05.2020    source источник
comment
Похоже, это проблема с antd и react-testing-library ‹/ 3 github .com / ant-design / ant-design / issues / 21272 Однако изменить его на submit не помогло   -  person MichaelA58    schedule 13.05.2020


Ответы (3)


У меня тоже были проблемы с отправкой форм с помощью Ant Design 4 + react-testing-library. После некоторых экспериментов я закончил тем, что всегда использовал data-testid для отправки форм:

<Button data-testid="submit" htmlType="submit">Submit</>

// Form element has onFinish attribute

// in test
fireEvent.click(rtl.getByTestId("submit"));
expect(...);

Это не то, что продвигает RTL (следует избегать datat-testid, тестируйте как настоящий пользователь), но я могу с этим жить.

Но согласно https://github.com/ant-design/ant-design/issues/21272 запуск события отправки тоже должен работать, я обязательно попробую.

person Florian Motteau    schedule 14.05.2020
comment
К сожалению, наличие submit не помогло мне. Я отвечу на этот вопрос, хотя для чего сделал! - person MichaelA58; 14.05.2020

Граничит с комедией и определенно НЕ является правильным способом решения проблемы. Но способ решить проблему - единственный, который сработал для меня, кроме отказа от использования onFinish полностью и использования onClick на кнопке.

Так в чем же заключался трюк, заключающийся в том, чтобы обернуть expect(...) в setTimeout(...)

      // click || submit - both seemed to work for me
      fireEvent.submit(submitButton);
      setTimeout(() => {
        expect(fetchSignIn).toHaveBeenCalledWith('asf');
      });
    it('should call props.fetchSignIn with the username and password', async () => {
      const promise = Promise.resolve({
        email: '[email protected]',
        firstName: 'Mike',
        lastName: 'A',
      });
      const fetchSignIn = jest.fn(() => promise);
      const { queryByTestId, queryByPlaceholderText } = renderLogin({
        seedEmail: 'aasdf',
        seedPassword: 'asdf',
        fetchSignIn,
      });
      const emailInput = queryByPlaceholderText('[email protected]');
      const passwordInput = queryByPlaceholderText('password');
      const submitButton = queryByTestId('submitButton');

      fireEvent.change(emailInput, {
        target: { value: '[email protected]' },
      });
      fireEvent.change(passwordInput, { target: { value: 'Password1!' } });

      // click || submit - both seemed to work for me
      fireEvent.submit(submitButton);
      setTimeout(() => {
        expect(fetchSignIn).toHaveBeenCalledWith('asf');
      });

      await act(() => promise);
    });

Об этом мне рассказал кто-то по проблеме GitHub https://github.com/ant-design/ant-design/issues/21272#issuecomment-628607141, так что привет @ildarnm на GH

person MichaelA58    schedule 14.05.2020

Давайте сначала рассмотрим вашу вторую проблему.

Jest не понимает, что шутка называется

Я считаю, что также сложно запустить тест с формами дизайна муравьев. После некоторых копаний и экспериментов кажется, что имитация «щелчка» не запускает onFinish, а вместо этого запускает имитацию «отправки». Визуализируйте следующий пример с помощью Jest и Enzyme:

export default MyForm = () => {
    <Form onFinish={onFinish}>
       <Form.Item>
         <Button htmlType='submit'>Submit</Button>
       </Form.Item>
    </Form>
}

it('should trigger onFinish if submit', () => {
   const onFinish = jest.fn();
   const wrapper = mount(<MyForm onFinish={onFinish}/>);
   wrapper.find('button').simulate('submit');
   await sleep(200)
   expect(onFinish).toHaveBeenCalled();
})

Я тоже борюсь с первой проблемой:

Предупреждение: обновление входа в систему внутри теста не было заключено в act (...)

Обратите внимание, что это произойдет только в случае ошибки проверки из-за изменения внутреннего состояния в их реализации формы.

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

Во-вторых, это предупреждение только тогда, когда это «разработка», а не «производство».

Если вы действительно хотите, чтобы он исчез, это хакерский способ (я не знаю, есть ли лучший способ), который я беру:

it('should trigger onFinish if submit', () => {
   const onFinish = jest.fn();
   const wrapper = mount(<MyForm onFinish={onFinish}/>);
   await act(async () => {
     wrapper.find('button').simulate('submit');
   })
   await sleep(200)
   wrapper.update()
   // check errors here
   expect(onFinish).not.toHaveBeenCalled();
})

Это официально задокументировано здесь: https://github.com/enzymejs/enzyme

person Cheng Xu    schedule 05.08.2020