# bun:test/valid-title

> Require test and `describe` titles to be non-empty, with no stray spaces or repeated prefix

The title is how you find a test in the output when it fails. This rule reports a title that's empty, starts or ends with a space, or repeats its function's name, as in `test("test adds an item")`. It also reports a test title that isn't a string. You can add your own naming rules with options.

`--fix` removes the spaces and the repeated word. It doesn't change anything in a file that uses `toMatchSnapshot()` or `toThrowErrorMatchingSnapshot()`, because snapshots are stored under their test's title.

{/* 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/valid-title" = "error" # or "warn"
```

Every option, set to its default. The ones that are commented out are unset by default.

```toml bunfig.toml
[lint.rules]
"bun:test/valid-title" = ["error", {
  allowArguments = false,
  ignoreTypeOfDescribeName = true,
  ignoreTypeOfTestName = false,
  ignoreSpaces = false,
  disallowedWords = [], # list of strings
  # mustMatch = <string, list of strings or object>,
  # mustNotMatch = <string, list of strings or object>,
}]
```

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

## Examples

Reported:

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

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

Not reported:

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

describe("cart", () => {
  test("adds an item", () => {});
  test(`removes ${count} items`, () => {});
  test("responds to " + path, () => {});
});
```

`bun test` accepts a function, a class or a number as a `describe` title, so that's allowed by default:

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

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

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `allowArguments` | `false` | Allow a title that's a plain variable, such as `title`. |
| `ignoreTypeOfDescribeName` | `true` | Allow a `describe` title that isn't a string. |
| `ignoreTypeOfTestName` | `false` | Allow a `test` or `it` title that isn't a string. |
| `ignoreSpaces` | `false` | Allow spaces at the start and the end. |
| `disallowedWords` | `[]` | Whole words that a title can't contain. Case doesn't matter. |
| `mustMatch` | none | A pattern that every title must match. |
| `mustNotMatch` | none | A pattern that no title can match. |

A variable as a test title is reported by default, because the rule can't tell what it holds:

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

test(title, () => {});
```

{/* good {"options": [{"allowArguments": true}]} */}
```ts
import { test } from "bun:test";

test(title, () => {});
```

{/* bad {"options": [{"ignoreTypeOfDescribeName": false}]} */}
```ts
import { describe, test } from "bun:test";

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

{/* bad {"options": [{"disallowedWords": ["should"]}]} */}
```ts
import { test } from "bun:test";

test("Should add an item", () => {});
```

`mustMatch` and `mustNotMatch` take a regular expression as a string, either `"^adds "` or `"/^adds /i"`. `i` is the only flag that has an effect. To set the report's message, pass `[pattern, message]`:

{/* bad {"options": [{"mustNotMatch": ["\\.$", "Do not end a title with a period"]}]} */}
```ts
import { test } from "bun:test";

test("adds an item.", () => {});
```

To use a different pattern for `describe`, `test` and `it`, pass an object. Each value is a pattern. A function that isn't in the object isn't checked:

{/* bad {"options": [{"mustMatch": {"it": "^should "}}], "count": 1} */}
```ts
import { it, test } from "bun:test";

it("adds an item", () => {});

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