React-testing-library: Cannot avoid "Warning: You seem to have overlapping act() calls"

Created on 9 Mar 2020  路  10Comments  路  Source: testing-library/react-testing-library

  • @testing-library/react version: 9.4.0
  • react version: 16.9.0
  • node version: 12.4.0
  • npm (or yarn) version: 6.13.7

Relevant code or config:

// UserProfile component
...
<Text data-testid="licenseExpiration">
  {licenseExpiration.format(dateFormat)}{" "}
  <StatusIcon value={isLicenseValid} />
</Text>
<Text strong>Vigencia de seguro:</Text>
<Text data-testid="insuranceExpiration">
  {insuranceExpiration.format(dateFormat)}{" "}
  <StatusIcon value={isInsuranceValid} />
</Text>
<Text strong>Vigencia de placas:</Text>
  <Text data-testid="platesExpiration">
  {platesExpiration.format(dateFormat)}{" "}
  <StatusIcon value={arePlatesValid} />
</Text>
...

// StatusIcon component
function StatusIcon({ value, ...props }) {
  return value ? (
    <Icon
      data-testid="status-true"
      type="check-circle"
      {...props}
    />
  ) : (
    <Icon
      data-testid="status-false"
      type="close-circle"
      {...props}
    />
  );
}

...
// Test

it("should show the correct status Icon when license, plates or insurance are valid", () => {
    const user = {
      ...user,
      licenseExpiration: moment().add(10, "days"),
      vehicle: {
        ...user.vehicle,
        insuranceExpiration: moment().add(10, "day"),
        platesExpiration: moment().add(10, "day")
      }
    };
    const vehicle = user.vehicle;
    const { getByTestId } = render(
      <UserProfile user={user} />
    );

    const licenseExpirationWrapper = within(getByTestId("licenseExpiration"));
    const isLicenseValid = moment(user.licenseExpiration) > moment();
    licenseExpirationWrapper.findByTestId(`status-${isLicenseValid}`);

    const insuranceExpirationWrapper = within(getByTestId("insuranceExpiration"));
    const isInsuranceValid = moment(vehicle.insuranceExpiration) > moment();
    insuranceExpirationWrapper.findByTestId(`status-${isInsuranceValid}`);

    const platesExpirationWrapper = within(getByTestId("platesExpiration"));
    const arePlatesValid = moment(vehicle.platesExpiration) > moment();
    platesExpirationWrapper.findByTestId(`status-${arePlatesValid}`);
  });

What you did:

I'm not doing anything async, it's just a component that shows some user information and I need to test that it's showing the correct icon depending if the plates, insurance or license is expired.

What happened:

I'm getting this warning: Warning: You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one.

If I remove two of the assertions, leaving only one, the warning goes away

    const licenseExpirationWrapper = within(getByTestId("licenseExpiration"));
    const isLicenseValid = moment(user.licenseExpiration) > moment();
    licenseExpirationWrapper.findByTestId(`status-${isLicenseValid}`);
    // This Works   

    // const insuranceExpirationWrapper = within(getByTestId("insuranceExpiration"));
    // const isInsuranceValid = moment(vehicle.insuranceExpiration) > moment();
    // insuranceExpirationWrapper.findByTestId(`status-${isInsuranceValid}`);

    // const platesExpirationWrapper = within(getByTestId("platesExpiration"));
    // const arePlatesValid = moment(vehicle.platesExpiration) > moment();
    // platesExpirationWrapper.findByTestId(`status-${arePlatesValid}`);

Reproduction:

https://codesandbox.io/s/react-testing-library-demo-sp1y5

Problem description:

Suggested solution:

Most helpful comment

Actually, I believe the problem here is that the code is not awaiting the result of findBy* queries. It should be resolved with:

    const licenseExpirationWrapper = within(getByTestId("licenseExpiration"));
    const isLicenseValid = moment(user.licenseExpiration) > moment();
    await licenseExpirationWrapper.findByTestId(`status-${isLicenseValid}`);

    const insuranceExpirationWrapper = within(getByTestId("insuranceExpiration"));
    const isInsuranceValid = moment(vehicle.insuranceExpiration) > moment();
    await insuranceExpirationWrapper.findByTestId(`status-${isInsuranceValid}`);

    const platesExpirationWrapper = within(getByTestId("platesExpiration"));
    const arePlatesValid = moment(vehicle.platesExpiration) > moment();
    await platesExpirationWrapper.findByTestId(`status-${arePlatesValid}`);

And the test function will need to be async.

All 10 comments

This will be hard to debug without having the full source of your UserProfile component and every component it renders. Are you sure you're not using an use(Layout)Effect?

This will be hard to debug without having the full source of your UserProfile component and every component it renders. Are you sure you're not using an use(Layout)Effect?

Let me create a Sandbox

Not sure what's happening. Please reduce the codesandbox so that you use no third-party libraries other than react and testing-library (no antd, styled-components etc).

Done, I removed antd, styled-components, and moment but I'm still getting the same warning.

Done, I removed antd, styled-components, and moment but I'm still getting the same warning.

One last question: Does this happen locally as well? I think I remember codesandbox having issues.

Done, I removed antd, styled-components, and moment but I'm still getting the same warning.

One last question: Does this happen locally as well? I think I remember codesandbox having issues.

Yes, it still does.

@HugoLiconV according to the findBy* doc you are triggering three promises, hence why the message you are getting.

You'd have to either wrap the call with a wait() or replace the findBy* by getBy* which in this case fits into your test.

Actually, I believe the problem here is that the code is not awaiting the result of findBy* queries. It should be resolved with:

    const licenseExpirationWrapper = within(getByTestId("licenseExpiration"));
    const isLicenseValid = moment(user.licenseExpiration) > moment();
    await licenseExpirationWrapper.findByTestId(`status-${isLicenseValid}`);

    const insuranceExpirationWrapper = within(getByTestId("insuranceExpiration"));
    const isInsuranceValid = moment(vehicle.insuranceExpiration) > moment();
    await insuranceExpirationWrapper.findByTestId(`status-${isInsuranceValid}`);

    const platesExpirationWrapper = within(getByTestId("platesExpiration"));
    const arePlatesValid = moment(vehicle.platesExpiration) > moment();
    await platesExpirationWrapper.findByTestId(`status-${arePlatesValid}`);

And the test function will need to be async.

Thanks, @carlosnufe @kentcdodds that was the problem

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaredmeakin picture jaredmeakin  路  3Comments

jalvarado91 picture jalvarado91  路  3Comments

nagacoder picture nagacoder  路  3Comments

jakeboone02 picture jakeboone02  路  3Comments

addamove picture addamove  路  3Comments