反应库测试没有更新我的屏幕

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