反应库测试没有更新我的屏幕
react library testing are not updating my screen
我最近遇到了这个奇怪的问题。我正在使用 react-testing-library
并尝试进行简单的更新。每当用户输入正确的名称时,他们将获得 10 分,并将记录在屏幕上。但是,目前没有记录新分数(我保持默认分数为 0)并且我还收到错误消息:
Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Warning: An update to Pokemon inside a test was not wrapped in act(...).
这是我的测试代码的样子
//PokemonPage.test.js
test.only("should have their score updated if they guess the name correctly", async () => {
const guessedPokemon = "Pikachu";
jest.spyOn(global, "fetch").mockResolvedValue({
json: () =>
Promise.resolve({
name: "Pikachu",
sprites: {
other: {
"official-artwork": {
front_default:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/25.png",
},
},
},
}),
});
render(<Pokemon pokemonTrainer={pokemonTrainer} />);
expect(screen.getByText(/Score: 0/)).toBeInTheDocument();
await waitFor(() => screen.findByRole("img"));
userEvent.type(await screen.findByRole("textbox"), guessedPokemon);
await waitFor(() => userEvent.click(screen.getByRole("button")))
expect(screen.getByText(/Score: 10/)).toBeInTheDocument()
});
这是它应该调用的代码:
//PokemonPage.js
const handleChange = (e) => setValue(e.target.value);
const handleSubmit = async (e) => {
e.preventDefault();
pokemonRef.current = await getPokemon();
setPokemonList((prev) => [
...prev,
{ name: pokemonRef.current.name, image: pokemonRef.current.image },
]);
updateScore(value)
setValue('')
};
const updateScore = async (guessedPokemonName) => {
if (guessedPokemonName === pokemonList[pokemonList.length - 1].name) {
setPokemonTrainerObject(prev => ({...prev, score: pokemonTrainerObject['score'] + 10 || 10 }))
}
};
基本上我是在提交用户输入,如果它是正确的 guessedPokemonName === pokemonList[pokemonList.length - 1].name
那么用户对象将更新分数。这就是我试图用我的测试来模拟的。
我尝试使用 waitFor
希望代码理解组件需要更新但无济于事。
有没有人遇到过类似的事情?
来自 React 的警告,“警告:测试中对 Pokemon 的更新未包含在 act(...) 中”意味着它检测到您的状态发生了变化,但您的测试中没有考虑到。
在这种情况下,此警告包含在一条更具解释性的消息中,说明此问题是在您的测试后发生的。
在您的代码中,您有 await waitFor(() => userEvent.click(screen.getByRole("button")))
。但是,waitFor
应该与断言一起使用。换句话说,它意味着要等到期望为真——而不是等到事件被触发,因为像这样的事件的触发不是异步的(它的处理可能是,但不是它的触发。)
相反,您应该只触发事件,然后然后 waitFor
您可以测试表明该过程已完成的东西。例如,您说“他们将获得 10 分,并将记录在屏幕上”。因此,在您的活动结束后,执行 waitFor
查找显示他们正确回答的消息,您已经在下一行中这样做了。
所以尝试:
userEvent.click(screen.getByRole("button"));
await waitFor(() => {
expect(screen.getByText(/Score: 10/)).toBeInTheDocument();
});
或者,更简单,因为 findBy* 方法在内部使用 waitFor
:
userEvent.click(screen.getByRole("button"));
await screen.findByText(/Score: 10/);
PS 您可以阅读 Kent Dodds 的文章,了解有关该错误消息的更多信息以及一些不同的修复方法,Fix the "not wrapped in act() warning
我最近遇到了这个奇怪的问题。我正在使用 react-testing-library
并尝试进行简单的更新。每当用户输入正确的名称时,他们将获得 10 分,并将记录在屏幕上。但是,目前没有记录新分数(我保持默认分数为 0)并且我还收到错误消息:
Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Warning: An update to Pokemon inside a test was not wrapped in act(...).
这是我的测试代码的样子
//PokemonPage.test.js
test.only("should have their score updated if they guess the name correctly", async () => {
const guessedPokemon = "Pikachu";
jest.spyOn(global, "fetch").mockResolvedValue({
json: () =>
Promise.resolve({
name: "Pikachu",
sprites: {
other: {
"official-artwork": {
front_default:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/25.png",
},
},
},
}),
});
render(<Pokemon pokemonTrainer={pokemonTrainer} />);
expect(screen.getByText(/Score: 0/)).toBeInTheDocument();
await waitFor(() => screen.findByRole("img"));
userEvent.type(await screen.findByRole("textbox"), guessedPokemon);
await waitFor(() => userEvent.click(screen.getByRole("button")))
expect(screen.getByText(/Score: 10/)).toBeInTheDocument()
});
这是它应该调用的代码:
//PokemonPage.js
const handleChange = (e) => setValue(e.target.value);
const handleSubmit = async (e) => {
e.preventDefault();
pokemonRef.current = await getPokemon();
setPokemonList((prev) => [
...prev,
{ name: pokemonRef.current.name, image: pokemonRef.current.image },
]);
updateScore(value)
setValue('')
};
const updateScore = async (guessedPokemonName) => {
if (guessedPokemonName === pokemonList[pokemonList.length - 1].name) {
setPokemonTrainerObject(prev => ({...prev, score: pokemonTrainerObject['score'] + 10 || 10 }))
}
};
基本上我是在提交用户输入,如果它是正确的 guessedPokemonName === pokemonList[pokemonList.length - 1].name
那么用户对象将更新分数。这就是我试图用我的测试来模拟的。
我尝试使用 waitFor
希望代码理解组件需要更新但无济于事。
有没有人遇到过类似的事情?
来自 React 的警告,“警告:测试中对 Pokemon 的更新未包含在 act(...) 中”意味着它检测到您的状态发生了变化,但您的测试中没有考虑到。
在这种情况下,此警告包含在一条更具解释性的消息中,说明此问题是在您的测试后发生的。
在您的代码中,您有 await waitFor(() => userEvent.click(screen.getByRole("button")))
。但是,waitFor
应该与断言一起使用。换句话说,它意味着要等到期望为真——而不是等到事件被触发,因为像这样的事件的触发不是异步的(它的处理可能是,但不是它的触发。)
相反,您应该只触发事件,然后然后 waitFor
您可以测试表明该过程已完成的东西。例如,您说“他们将获得 10 分,并将记录在屏幕上”。因此,在您的活动结束后,执行 waitFor
查找显示他们正确回答的消息,您已经在下一行中这样做了。
所以尝试:
userEvent.click(screen.getByRole("button"));
await waitFor(() => {
expect(screen.getByText(/Score: 10/)).toBeInTheDocument();
});
或者,更简单,因为 findBy* 方法在内部使用 waitFor
:
userEvent.click(screen.getByRole("button"));
await screen.findByText(/Score: 10/);
PS 您可以阅读 Kent Dodds 的文章,了解有关该错误消息的更多信息以及一些不同的修复方法,Fix the "not wrapped in act() warning