# bun:test/valid-describe-callback

> Require `describe` to get a callback that is a function with no parameters

`bun test` runs the `describe` callback to collect the tests inside it. Without a callback there's nothing to collect. The callback isn't a test, so it has no `done` to call.

This rule is on by default in files that import from `"bun:test"`.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

On by default as an error. To turn it off:

```toml bunfig.toml
[lint.rules]
"bun:test/valid-describe-callback" = "off" # or "warn"
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 3} */}
```ts
import { describe, test } from "bun:test";

describe("cart"); // no callback

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

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

Not reported:

{/* good */}
```ts
import { describe, expect, test } from "bun:test";

describe("cart", () => {
  test("adds an item", () => {
    expect(add(item).length).toBe(1);
  });
});
```

An `async` callback is allowed, because `bun test` waits for the promise it returns:

{/* good */}
```ts
import { describe, expect, test } from "bun:test";

describe("checkout", async () => {
  const rates = await loadRates();

  test("adds the tax", () => {
    expect(total(100, rates)).toBe(108);
  });
});
```

`describe.todo` and `describe.skip` only need a title. A callback passed by name is assumed to be a function:

{/* good */}
```ts
import { describe } from "bun:test";
import { cartTests } from "./shared";

describe.todo("refunds");
describe.skip("exports");

describe("cart", cartTests);
```

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

{/* good */}
```ts
import { describe, expect, test } from "bun:test";

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