【问题标题】:My async component renders two times and expect doesn't wait for the second time even using await?我的异步组件渲染了两次,并且即使使用 await 也不会等待第二次?
【发布时间】:2021-01-06 08:41:56
【问题描述】:

我想测试一个简单的应用程序,它从输入中获取代码,然后在文档中显示代码。

我的组件渲染了两次:一次没有输入值(我将useState初始化为undefined);另一个使用正确的字符串。我希望我的测试第二次等待代码出现。现在在第一次渲染时失败。

这是我的测试:

test("Keeps track of input value [async]", async () => {
  const { getByText, queryByText, getByLabelText, debug } = render(<App />);
  userEvent.type(getByLabelText("Code:"), "12345")
  userEvent.click(getByText(/Change route/i));
  expect(await queryByText(/The code you chose is: 12345/i)).toBeInTheDocument();
});

这是我的应用代码:

const App = () => {
  const [route, setRoute] = useState("home")
  const [code, setCode] = useState("");
  return (
    <Router
      currentRoute={route}
      render={(currentRoute: string) => (
        <Fragment>
          <Router.View route="home" currentRoute={currentRoute}>
            This is the homepage.
            <label htmlFor="code">Code:</label><input id="code" type="text" value={code} onChange={(e) => setCode(e.target.value)} />
            <button onClick={() => {
              setRoute('selection')
            }}>Change route</button>
          </Router.View>
          <Router.View route="selection" currentRoute={currentRoute}>
            <Selection code={code} />
          </Router.View>
        </Fragment>
      )}
    />
  );
};

选择代码(Promise.resolve 模拟异步):

编辑:原来useEffect 在第一次渲染时甚至没有被调用

const Selection = (props) => {
  const [code, setCode] = useState();
  useEffect(() => {
    Promise.resolve(props.code).then(res => setCode("12345"));
  },[props.code])
  return (<>This is the selection page. The code you chose is: {code}</>)
}

制作了一个代码框,但由于不相关的原因而失败。如果我能让它工作,我会更新:https://codesandbox.io/s/lingering-thunder-z9oqq

【问题讨论】:

  • 也许:const result = await queryByText(/The code you chose is: 12345/i); expect( result ).toBeInTheDocument();
  • 没用。还是从screen.debug()得到&lt;div&gt;This is the selection page. The code you chose is:&lt;/div&gt;
  • 原来 useEffect 甚至没有在第一次渲染时调用 - 是的,它没有,它是在安装组件时调用的。 await queryByText 也没有意义,因为它没有返回承诺。如果您没有特定的等待时间,请使用waitFor

标签: javascript reactjs async-await jestjs react-testing-library


【解决方案1】:

这个测试解决了我的问题:

test("Keeps track of input value [async]", async () => {
  render(<App />);
  userEvent.type(screen.getByLabelText(/Code:/i), "12345")
  userEvent.click(screen.getByText(/Change route/i));
  expect(await screen.findByText(/12345/i)).toBeInTheDocument();
});

四处挖掘我得出的结论是,我应该 screen.findByText()await 出现一个元素。 queryBy* 应该主要用于根据Kent C Dodds 断言消失

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2020-01-17
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多