jest/valid-describe-callback

Require describe to get a title and a plain synchronous callback

Jest runs the describe callback right away to collect the tests inside it. It doesn't wait for a promise, so a test declared after an await isn't collected. It doesn't pass any arguments to the callback, and the callback must not return a value.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"jest/valid-describe-callback" = "error" # or "warn"

Examples#

example.ts1 problem
import { describe, expect, test } from "@jest/globals";

describe("cart", async () => {
  const items = await loadItems();

  test("has items", () => {
    expect(items.length).toBeGreaterThan(0);
  });
});
example.ts5 problems
import { describe, test } from "@jest/globals";

describe("cart"); // no callback

describe("cart", "adds an item"); // not a function

describe("cart", (done) => {
  test("adds an item", () => {});
  done(); // the callback gets no arguments
});

describe("cart", () => {
  return test("adds an item", () => {});
});

describe("cart", () => test("adds an item", () => {})); // returns the result of `test()`
example.tsNo problems
import { beforeAll, describe, expect, test } from "@jest/globals";

describe("cart", () => {
  let items;

  beforeAll(async () => {
    items = await loadItems();
  });

  test("has items", () => {
    expect(items.length).toBeGreaterThan(0);
  });
});

The describe.each callback gets a row's values, so it can have parameters:

example.tsNo problems
import { describe, expect, test } from "@jest/globals";

describe.each([1, 2, 3])("cart with %i items", (count) => {
  test("counts them", () => {
    expect(fill(count).length).toBe(count);
  });
});

When not to use it#

The rule only looks at the call, so a callback passed by name is reported as not being a function. Turn the rule off if you share groups of tests that way:

example.ts1 problem
import { describe } from "@jest/globals";
import { cartTests } from "./shared";

describe("cart", cartTests);