0
# Rule Testing Engine
1
2
Core rule testing functionality providing comprehensive test execution, validation, and reporting for ESLint rules with enhanced TypeScript support.
3
4
## Capabilities
5
6
### RuleTester Class
7
8
The main class for testing ESLint rules with TypeScript integration and advanced validation features.
9
10
```typescript { .api }
11
/**
12
* Rule testing engine that extends ESLint's native testing with TypeScript support
13
*/
14
class RuleTester extends TestFramework {
15
/**
16
* Creates a new RuleTester instance with optional configuration
17
* @param testerConfig - Configuration extending ESLint's flat config with TypeScript options
18
*/
19
constructor(testerConfig?: RuleTesterConfig);
20
}
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import { RuleTester } from "@typescript-eslint/rule-tester";
27
28
// Basic usage with default TypeScript parser
29
const ruleTester = new RuleTester();
30
31
// Advanced configuration with custom options
32
const ruleTester = new RuleTester({
33
defaultFilenames: {
34
ts: "test.ts",
35
tsx: "test.tsx",
36
},
37
languageOptions: {
38
parserOptions: {
39
project: "./tsconfig.json",
40
ecmaFeatures: {
41
jsx: true,
42
},
43
},
44
},
45
dependencyConstraints: {
46
typescript: ">=4.0.0",
47
},
48
});
49
50
// Configuration for specific test environments
51
const ruleTester = new RuleTester({
52
languageOptions: {
53
globals: {
54
window: "readonly",
55
document: "readonly",
56
},
57
env: {
58
browser: true,
59
es2022: true,
60
},
61
},
62
});
63
```
64
65
### Rule Execution
66
67
Executes comprehensive tests for a rule with both valid and invalid test cases.
68
69
```typescript { .api }
70
/**
71
* Runs tests for a specific rule with both valid and invalid test cases
72
* @param ruleName - Name of the rule being tested
73
* @param rule - The rule module to test
74
* @param test - Object containing arrays of valid and invalid test cases
75
*/
76
run<MessageIds extends string, Options extends readonly unknown[]>(
77
ruleName: string,
78
rule: RuleModule<MessageIds, Options>,
79
test: RunTests<MessageIds, Options>
80
): void;
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
import { RuleTester } from "@typescript-eslint/rule-tester";
87
import { myRule } from "./my-rule";
88
89
const ruleTester = new RuleTester();
90
91
ruleTester.run("my-rule", myRule, {
92
valid: [
93
// Simple string test cases
94
"const x = 1;",
95
"function foo() { return 'hello'; }",
96
97
// Complex test cases with configuration
98
{
99
code: "interface User { name: string; }",
100
name: "interface declaration",
101
languageOptions: {
102
parserOptions: {
103
project: "./tsconfig.json",
104
},
105
},
106
},
107
108
// Test with specific options
109
{
110
code: "type Status = 'active' | 'inactive';",
111
options: [{ allowUnionTypes: true }],
112
},
113
],
114
invalid: [
115
{
116
code: "var x = 1;",
117
errors: [{ messageId: "noVar", line: 1, column: 1 }],
118
output: "const x = 1;",
119
},
120
121
// Multi-pass autofix
122
{
123
code: "var a = 1; var b = 2;",
124
errors: [
125
{ messageId: "noVar", line: 1, column: 1 },
126
{ messageId: "noVar", line: 1, column: 12 },
127
],
128
output: ["let a = 1; var b = 2;", "let a = 1; let b = 2;"],
129
},
130
131
// Test with suggestions
132
{
133
code: "function foo(x: any) { return x; }",
134
errors: [{
135
messageId: "noAny",
136
suggestions: [{
137
messageId: "useUnknown",
138
output: "function foo(x: unknown) { return x; }",
139
}],
140
}],
141
},
142
],
143
});
144
```
145
146
### Rule Definition
147
148
Registers a rule for testing within the RuleTester instance.
149
150
```typescript { .api }
151
/**
152
* Defines a rule for testing with the given name and rule module
153
* @param name - The name to register the rule under
154
* @param rule - The rule module (function or object with create method)
155
*/
156
defineRule(name: string, rule: AnyRuleModule): void;
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
import { RuleTester } from "@typescript-eslint/rule-tester";
163
164
const ruleTester = new RuleTester();
165
166
// Define a custom rule
167
ruleTester.defineRule("no-var", {
168
meta: {
169
type: "suggestion",
170
docs: {
171
description: "disallow var declarations",
172
},
173
fixable: "code",
174
messages: {
175
noVar: "Use 'const' or 'let' instead of 'var'",
176
},
177
},
178
create(context) {
179
return {
180
VariableDeclaration(node) {
181
if (node.kind === "var") {
182
context.report({
183
node,
184
messageId: "noVar",
185
fix(fixer) {
186
return fixer.replaceText(node, node.source().replace("var", "const"));
187
},
188
});
189
}
190
},
191
};
192
},
193
});
194
195
// Use the defined rule in tests
196
ruleTester.run("no-var", ruleTester.rules["no-var"], {
197
valid: ["const x = 1;"],
198
invalid: [{
199
code: "var x = 1;",
200
errors: [{ messageId: "noVar" }],
201
output: "const x = 1;",
202
}],
203
});
204
```
205
206
## Test Framework Integration
207
208
The RuleTester integrates with various test frameworks through inherited properties that can be customized.
209
210
### Framework Properties
211
212
```typescript { .api }
213
/**
214
* Test framework integration properties (inherited from TestFramework)
215
*/
216
class RuleTester {
217
/** Function that runs after all tests complete */
218
static afterAll: AfterAll;
219
220
/** Function to create test groupings */
221
static describe: RuleTesterTestFrameworkFunction;
222
223
/** Function to skip test groupings */
224
static describeSkip: RuleTesterTestFrameworkFunctionBase;
225
226
/** Function to create individual tests */
227
static it: RuleTesterTestFrameworkItFunction;
228
229
/** Function to run tests exclusively */
230
static itOnly: RuleTesterTestFrameworkFunctionBase;
231
232
/** Function to skip individual tests */
233
static itSkip: RuleTesterTestFrameworkFunctionBase;
234
}
235
```
236
237
**Usage Examples:**
238
239
```typescript
240
import { RuleTester } from "@typescript-eslint/rule-tester";
241
242
// Custom test framework integration (e.g., for Mocha)
243
RuleTester.describe = (title, fn) => {
244
describe(title, fn);
245
};
246
247
RuleTester.it = (title, fn) => {
248
it(title, fn);
249
};
250
251
RuleTester.itOnly = (title, fn) => {
252
it.only(title, fn);
253
};
254
255
// For Jest (usually works by default)
256
RuleTester.describe = describe;
257
RuleTester.it = test;
258
RuleTester.itOnly = test.only;
259
```
260
261
## Type Definitions
262
263
```typescript { .api }
264
type RuleModule<MessageIds extends string, Options extends readonly unknown[]> = {
265
meta: RuleMeta<MessageIds>;
266
create: (context: RuleContext<MessageIds, Options>) => RuleListener;
267
};
268
269
type AnyRuleModule = RuleModule<string, readonly unknown[]>;
270
271
type AnyRuleCreateFunction = (context: any) => RuleListener;
272
273
interface RuleMeta<MessageIds extends string> {
274
type: "problem" | "suggestion" | "layout";
275
docs?: {
276
description: string;
277
category?: string;
278
recommended?: boolean;
279
url?: string;
280
};
281
fixable?: "code" | "whitespace";
282
hasSuggestions?: boolean;
283
messages: Record<MessageIds, string>;
284
schema?: JSONSchema.JSONSchema4 | JSONSchema.JSONSchema4[];
285
}
286
287
interface RuleListener {
288
[key: string]: ((node: any) => void) | undefined;
289
}
290
```