テストは成功しているのに、なぜか以下のようなエラーが表示されることがある
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
「React の state を変更するなら act で囲んでね」とのこと。
だがしかし、**言われた通りにactでユーザーイベントをラップしてもエラーは出続けるし、なんなら「actは未定義です」ってエラーも出てくる。**なんやねん!!ってなる。
it("2 :Should change button name by icon click", async () => {
const user = userEvent.setup();
render(
<Provider store={store}>
<Auth />
</Provider>
);
expect(screen.getByRole("button")).toHaveTextContent("Login");
// actは未定義ですってエラーが出る。Testing Libraryのモジュールじゃないんかい!
**await act(() => {
user.click(screen.getByTestId("toggle-icon"));
});**
expect(screen.getByRole("button")).toHaveTextContent("Register");
});
※どうやらactはReactのAPIらしい。
ということで、色々調べたらこれで解決した
ユーザーイベントでstateを変更する場合は、変更後に実施したいテストを
await waitFor(() => ) でラップすること!
〜〜〜
import { render, screen, cleanup, **waitFor** } from "@testing-library/react";
〜〜〜
it("2 :Should change button name by icon click", async () => {
const user = userEvent.setup();
render(
<Provider store={store}>
<Auth />
</Provider>
);
expect(screen.getByRole("button")).toHaveTextContent("Login");
// こちらではなく
user.click(screen.getByTestId("toggle-icon"));
// こっちをラップ!
**await waitFor(() =>
expect(screen.getByRole("button")).toHaveTextContent("Register")
);**
});
解説は参考記事のが分かりやすかった。
useStateって非同期処理なのか?が疑問だけど、もしそうなら参考記事の解説がまるっと今回の事象にも当てはまるから理解しやすいと思う。
typeイベント(入力するタイプ)の場合、変更後に実施したいテストを
await waitFor(() => ) (またはawaitとfindByTextを使う方法)でラップするのと、typeイベント自体をawait act() でラップする必要もある!
▼例
〜〜〜
import { render, screen, cleanup, **act** } from "@testing-library/react";
〜〜〜
/** 新規Brand作成(ユーザー入力) */
it("4 :Should add new segment and also to the list", async () => {
const user = userEvent.setup();
render(
<Provider store={store}>
<Brand />
</Provider>
);
expect(screen.queryByText("Audi")).toBeNull();
const inputValue = screen.getByPlaceholderText("new brand name");
**await act(() => user.type(inputValue, "Audi"));**
user.click(screen.getByTestId("btn-post"));
// await と findByText を使うパターン
expect(**await** **screen.findByText**("Audi")).toBeInTheDocument();
});
await act(() =>)でラップする必要があるReact のテストを書いてたら act で囲んでよーって言われたとき - Mitsuyuki.Shiiba
もしものとき用に参考記事を丸々転載↓