# bun:test/expect-expect

> Require every test to make at least one assertion

A test with no assertion passes as long as the code doesn't throw, whether the result is right or wrong. Usually someone forgot the `expect`, or lost it while changing the test.

Calls to `expect` and `expectTypeOf` count as assertions. `test.todo` and `test.skip` aren't checked.

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

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"bun:test/expect-expect" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"bun:test/expect-expect" = ["error", {
  assertFunctionNames = ["expect", "expectTypeOf"],
  additionalTestBlockFunctions = [], # list of strings
}]
```

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

## Examples

Reported:

{/* bad */}
```ts
import { test } from "bun:test";

test("parses the port", () => {
  parseConfig("port = 3000");
});
```

Not reported:

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

test("parses the port", () => {
  expect(parseConfig("port = 3000")).toEqual({ port: 3000 });
});

test.todo("rejects a negative port");

test.skip("reads the file", () => {
  readConfig("app.conf");
});
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `assertFunctionNames` | `["expect", "expectTypeOf"]` | The functions that count as an assertion. Your list replaces the default, so keep `"expect"` in it. |
| `additionalTestBlockFunctions` | `[]` | Other functions to check like `test`, such as your own wrappers around it or a hook like `"afterEach"`. |

### `assertFunctionNames`

The rule doesn't look inside the helpers that a test calls. This test is reported even though `checkUser` calls `expect`:

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

function checkUser(user) {
  expect(user.id).toBeGreaterThan(0);
}

test("creates a user", () => {
  checkUser(createUser());
});
```

Add the helper's name and the test isn't reported anymore:

```toml bunfig.toml
[lint.rules]
"bun:test/expect-expect" = ["error", {
  assertFunctionNames = ["expect", "checkUser"],
}]
```

{/* good {"options": [{"assertFunctionNames": ["expect", "checkUser"]}]} */}
```ts
import { expect, test } from "bun:test";

function checkUser(user) {
  expect(user.id).toBeGreaterThan(0);
}

test("creates a user", () => {
  checkUser(createUser());
});
```

A name can be a chain, such as `request.get.expect`. `*` matches any characters in one part of the chain, and `**` matches any number of parts, including none. Case is ignored.

With `"request.**.expect"` in the list, this isn't reported:

{/* good {"options": [{"assertFunctionNames": ["expect", "request.**.expect"]}]} */}
```ts
import { test } from "bun:test";

test("is healthy", async () => {
  await request(app).get("/health").expect(200);
});
```

### `additionalTestBlockFunctions`

With `["testWithDatabase"]`, calls to that wrapper need an assertion too:

{/* bad {"options": [{"additionalTestBlockFunctions": ["testWithDatabase"]}]} */}
```ts
import { afterAll } from "bun:test";
import { closeDatabase, testWithDatabase } from "./helpers";

afterAll(closeDatabase);

testWithDatabase("saves the user", (db) => {
  db.save(createUser());
});
```

{/* good {"options": [{"additionalTestBlockFunctions": ["testWithDatabase"]}]} */}
```ts
import { afterAll, expect } from "bun:test";
import { closeDatabase, testWithDatabase } from "./helpers";

afterAll(closeDatabase);

testWithDatabase("saves the user", (db) => {
  expect(db.save(createUser())).toBe(true);
});
```

Like every `bun:test` rule, this one only checks files that import something from `bun:test`.
