#javascript #reactjs #jestjs #react-testing-library
#javascript #reactjs #jestjs #react-testing-library
Вопрос:
Я тестирую свой компонент с помощью react-testing-library, и тест работает хорошо. Я просто не могу избавиться от этого предупреждения, fireEvent должен быть завернут в act из коробки, но я попытался обернуть его снова, и это не помогло.
Вот мой тестовый пример.
it.only("should start file upload if file is added to the field", async () => {
jest.useFakeTimers();
const { getByTestId } = wrapper;
const file = new File(["filefilefile"], "videoFile.mxf");
const fileInput = getByTestId("drop-zone").querySelector(
"input[type='file']"
);
fireEvent.change(fileInput, { target: { files: [file] } });
act(() => {
jest.runAllTimers();
});
await wait(() => {
expect(
initialProps.uploadItemVideoFileConnect.calledWith(file, 123)
).toBe(true);
});
});
Вот предупреждение
Warning: An update to UploadButtonGridComponent inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
Комментарии:
1. Временный обходной путь, на который вы можете сослаться по ссылке github.com/testing-library/react-testing-library/issues /…
Ответ №1:
Эта проблема вызвана множеством обновлений внутри компонента.
Я получил то же самое, вот как я решил проблему.
await act( async () => {
fireEvent.change(fileInput, { target: { files: [file] } });
});
Комментарии:
1. Следует отметить, что если у вас есть два fireEvent прямо рядом друг с другом, вам нужно два
act()
, по одному для каждого.2. Это дает мне
Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);
3. Это решение решило мою проблему при тестировании компонента, который вводит данные в форму Formik. Я получал это предупреждение: Предупреждение: Обновление Formik внутри теста не было завернуто в act (…)
4. Это также было полезно при рендеринге компонента, который вызывал изменения внутреннего состояния
5. Я почти удалил Formik, пока не нашел это решение. Спасибо
Ответ №2:
В исходном коде оно fireEvent
уже завернуто в act()
.
Проблема может быть связана с этой проблемой, в которой асинхронная логика (такая как useEffect
) запускает изменения состояния за пределами fireEvent:
https://github.com/kentcdodds/react-testing-library/issues/281
(Не видя реализацию вашего компонента, трудно быть уверенным, что это именно то, что происходит в вашем случае.)
По-видимому, планируется включить асинхронную обработку в будущий выпуск, так что это не будет проблемой.
Комментарии:
1. Похоже, ваша проблема связана со следующим, пожалуйста, смотрите github.com/facebook/react/issues/14769
Ответ №3:
Так что это сложно обобщить, но я попытаюсь.
act
Предупреждение просто сообщает вам, что в вашем функциональном компоненте происходит что-то, что вы не тестируете.
Допустим, мы визуализируем список задач следующим образом
<ul>
{loading ? (
<p>Fetching todos</p>
) : (
<>
{appData.todoList.slice(0, 15).map((item) => {
const { id, title } = item;
return (
<li key={id} data-testid={id}>
<Link to={`/item/${id}`}>{title}</Link>
</li>
);
})}
</>
)}
</ul>
Приведенный ниже тестовый пример выдаст act
предупреждение
import { waitFor, screen, waitForElementToBeRemoved } from "@testing-library/react";
it("Renders <TodoList /> component", async () => {
render(<TodoList />);
await waitFor(() => expect(axios.get).toHaveBeenCalledTimes(1));
await waitForElementToBeRemoved(() => screen.getByText(/Fetching todos/i));
expect(axios.get).toHaveBeenCalledTimes(1);
todos.slice(0, 15).forEach((td) => {
expect(screen.getByText(td.title)).toBeInTheDocument();
});
});
Но если вы измените порядок await
строк следующим образом
await waitForElementToBeRemoved(() => screen.getByText(/Fetching todos/i));
await waitFor(() => expect(axios.get).toHaveBeenCalledTimes(1));
act
Предупреждение исчезает. Это имеет смысл. Вы должны убедиться, что ваши пользователи больше не видят индикатор загрузки.
Есть и другие случаи, так что продолжайте и прочитайте этот пост от Кента Доддса.
https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning
Комментарии:
1. Я не знаю, сработало ли это у меня или нет, но это отличный ответ! «Вы должны убедиться, что ваши пользователи больше не видят индикатор загрузки». <— yes
2. Спасибо за это. Отличное объяснение, и я смог исправить свои предупреждения.