This rule raises an issue when a test or lifecycle-hook callback is declared async and also accepts a completion callback such as done.

Why is this an issue?

Asynchronous tests and hooks must use a single completion style.

In Jest, Mocha, and Jasmine, a test or hook can finish in one of two ways:

A callback that does both mixes these contracts. The framework has to choose between the callback and the returned promise, which is unsupported or ambiguous. Depending on the framework and the code path, this can fail immediately, hang until timeout, or report failures in a confusing way.

Choose the style that matches the body of the callback:

Exceptions

This rule does not raise on modifier-based skipped tests such as it.skip(…​) or test.skip(…​).

Code examples

Noncompliant code example

it("loads the configuration", async done => { // Noncompliant: this test uses both promise completion and the "done" callback
  const config = await loadConfig();
  expect(config.port).toBe(3000);
  done();
});

Compliant solution

it("loads the configuration", async () => {
  const config = await loadConfig();
  expect(config.port).toBe(3000);
});

Noncompliant code example

beforeEach(async done => { // Noncompliant: this hook is callback-based, so "async" is misleading
  connectToDatabase(error => {
    done(error);
  });
});

Compliant solution

beforeEach(done => {
  connectToDatabase(error => {
    done(error);
  });
});

Resources

Documentation