@testing-library/react (rtl) 'waitFor' makes only success without await keyword
Asked Answered
L

2

5

await waitFor() makes my test fail but waitFor() makes my test successful (without await).

The official doc said

The async methods return a Promise, so you must always use await or .then(done) when calling them. (https://testing-library.com/docs/guide-disappearance)

I don't know how can I test correctly. do I have to use rerender?

it('toggles active status', async () => {
  render(<List {...listProps} />);
  const targetItem = screen.getByRole('heading', { name: /first/i });

  // de-active color is GRAY2, active color is MINT
  expect(targetItem).toHaveStyle({ color: GRAY2 });

  // click to change the color of targetItem
  // it dispatch action that update listProps
  // So changing listProps makes <List /> re-rendering
  fireEvent.click(targetItem);

  await waitFor(() => {
    // It throws an error because the color is still GRAY2 in jest runner.
    // But, in chrome browser, it's color MINT.
    expect(targetItem).toHaveStyle({ color: MINT }); // fail
  });

  // If not use 'await' keyword, this works well.
  // jest runner knows the color is MINT
  waitFor(() => {
    expect(targetItem).toHaveStyle({ color: MINT });
  });
});
Lumpfish answered 7/1, 2021 at 5:14 Comment(3)
I think the problem is dispatch action. A new way of using rerender not waitFor() makes success. I guess that the results of re-rendering DOM by changing props are not concerns with component test. is it right? or notLumpfish
As the docs say, you should always await for waitFor.The fact that then test passes if you don't use await is because the assertion expect(targetItem).toHaveStyle({ color: MINT }); will not happen. Make sure you're testing the correct behaviour.Devisor
@Devisor yes you're right. I wrote the answer because of the limitation of comment string length.Lumpfish
L
4

If I use waitFor() without await it won't fail, but also isn't truly successful.

expect statement to pass through without testing. waitFor() without await is my misconception. It's always successful even if has to fail.

Finally, I have known that test framework cannot detect results of changing props. The props are passed from Parent Component even if it is in redux store in fact.

In summary, I want to test Child Component. It gets props from Parent Component, Parent gets data to pass props from redux store.

Click event of Child fires dispatch and change store state well. But in test runner, because rendering is isolated, It was seemed to cause an error. Store state was changed but props was passed still not changed So I changed Child data structure not getting props from Parent but getting from store.

Lumpfish answered 9/1, 2021 at 1:9 Comment(0)
G
2

because if you are not awaiting , you are getting a promise, which is a truthy value. now if you do await and the promise resolves to a falsy value only in that case your test case will fail

Goethite answered 7/1, 2022 at 20:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.