# testing

Specifies a rule with cases: valid texts that must report nothing, and invalid texts with the messages, positions and fixed text they must produce. [`testRule`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-testRule) declares one `node:test` test per case, so the specs run under `node --test` or any runner built on it.

## Usage

```typescript
import { testRule } from '@hyperfrontend/linter/testing'
import rule from './no-debugger'

testRule(rule, {
  valid: [{ name: 'a plain call', path: '/project/src/a.ts', text: 'run()\n' }],
  invalid: [
    {
      name: 'a debugger statement',
      path: '/project/src/a.ts',
      text: 'debugger\n',
      errors: [{ message: 'Remove the debugger.', line: 1, column: 1 }],
      output: null,
    },
  ],
})
```

Each case names the absolute `path` the text is linted as; the project root is the path's directory unless [`root`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-RuleCase-prop-root) says otherwise. A case can pass [`options`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-RuleCase-prop-options), [`settings`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-RuleCase-prop-settings) and [`language`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-RuleCase-prop-language) the way a configuration block would. On an invalid case, [`output`](https://www.hyperfrontend.dev/docs/libraries/linter/testing/#api-InvalidCase-prop-output) is the text after the rule's fixes, `null` when the rule must offer no fix, and unchecked when absent.

## API Reference

### Functions

#### testRule

```typescript
function testRule(rule: RuleModule, cases: RuleCases): void
```

Declares the tests of a rule.

**Parameters**

| Name | Type | Description |
| --- | --- | --- |
| `rule` | `RuleModule` | The rule under test |
| `cases` | `RuleCases` | Its valid and invalid cases |

**Example: Specify a rule with one valid and one invalid case**

```ts
import { testRule } from '@hyperfrontend/linter/testing'
import rule from './no-debugger'

testRule(rule, {
  valid: [{ name: 'a plain call', path: '/project/a.ts', text: 'run()\n' }],
  invalid: [
    {
      name: 'a debugger statement',
      path: '/project/a.ts',
      text: 'debugger\n',
      errors: [{ message: "Unexpected 'debugger' statement.", line: 1, column: 1 }],
    },
  ],
})
```

### Interfaces

#### ExpectedError

A message the rule must report.

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| `readonly message` | `string` | The text shown to the user. |
| `readonly line` | `number` | The 1-based start line, or null for a problem about the file as a whole. |
| `readonly column` | `number` | The 1-based start column, or null for a problem about the file as a whole. |
| `readonly endLine?` | `number` | The 1-based end line, when checked; null for a problem without a range. |
| `readonly endColumn?` | `number` | The 1-based end column, when checked; null for a problem without a range. |

#### InvalidCase

A text the rule must report on.

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| `readonly name` | `string` | The test's name. |
| `readonly path` | `string` | The absolute path the text is linted as; its directory is the project root unless `root` says otherwise. |
| `readonly root?` | `string` | The project root, absolute, when it is not the file's directory. |
| `readonly text` | `string` | The text. |
| `readonly options?` | `unknown` | The rule's options. |
| `readonly settings?` | `Readonly<Record<string, unknown>>` | The settings. |
| `readonly language?` | `Partial<LanguageSettings>` | How the text is read, where it differs from the default. |
| `readonly errors` | `unknown` | The messages, in position order. |
| `readonly output?` | `string` | The text after the rule's fixes when it fixes, null when it must offer no fix; unchecked when absent. |

#### RuleCase

A text the rule reads.

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| `readonly name` | `string` | The test's name. |
| `readonly path` | `string` | The absolute path the text is linted as; its directory is the project root unless `root` says otherwise. |
| `readonly root?` | `string` | The project root, absolute, when it is not the file's directory. |
| `readonly text` | `string` | The text. |
| `readonly options?` | `unknown` | The rule's options. |
| `readonly settings?` | `Readonly<Record<string, unknown>>` | The settings. |
| `readonly language?` | `Partial<LanguageSettings>` | How the text is read, where it differs from the default. |

#### RuleCases

The cases of one rule.

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| `readonly valid` | `unknown` | Texts that must report nothing. |
| `readonly invalid` | `unknown` | Texts that must report. |

---

Canonical page: https://www.hyperfrontend.dev/docs/libraries/linter/testing/
This file: https://www.hyperfrontend.dev/docs/libraries/linter/testing.md
Documentation index: https://www.hyperfrontend.dev/llms.txt
