ESLint Rule Tester
Write custom ESLint rule visitors and test them against JavaScript code instantly
Configuration
Load example rule:
Rule Definition
Write the visitor object returned by create(context). Use context.report({ node, message }) to flag violations.
Supported node types (29)
IdentifierLiteralTemplateLiteralCallExpressionMemberExpressionNewExpressionVariableDeclarationFunctionDeclarationFunctionExpressionArrowFunctionExpressionClassDeclarationBinaryExpressionLogicalExpressionAssignmentExpressionUpdateExpressionUnaryExpressionAwaitExpressionIfStatementWhileStatementForStatementReturnStatementThrowStatementTryStatementDebuggerStatementImportDeclarationExportNamedDeclarationExportDefaultDeclarationThisExpressionSuperTest Code
Paste the JavaScript code you want to lint with your rule.
Violations
2 violationsUnexpected console statement.
CallExpression
Unexpected console statement.
CallExpression
Visitor matched: CallExpression
Your team bans console.log in production code but the built-in no-console rule is too strict — it also flags console.error and console.warn which you want to keep. You need a custom rule that only flags console.log and console.debug. Writing it means setting up a test project with RuleTester, creating a meta object, writing the AST visitor, running tests — 30 minutes of scaffolding before you write a single line of rule logic. You need a sandbox where you paste the visitor code and test it against a snippet instantly.
Why This Tester (Not the ESLint Config Generator)
PureDevTools has an ESLint Config Generator for building complete configuration files with rule toggles and plugin setup. This tool is for writing and testing custom rule logic — write an AST visitor pattern, paste JavaScript test code, and instantly see which lines get flagged with messages and severity levels. No Node.js, no npm install, no test scaffolding. Everything runs in your browser; no data is sent anywhere.
What Is This Tool?
The ESLint Rule Tester lets you write and test custom ESLint rule logic directly in your browser — no Node.js, no npm install, no configuration files required. Write a rule visitor, paste some JavaScript test code, and instantly see which lines would be flagged, along with the error messages and severity level.
This is ideal for learning how ESLint rules work, prototyping new rules before integrating them into a project, or understanding existing rule behaviour by testing edge cases.
How ESLint Rules Work
ESLint uses an AST (Abstract Syntax Tree) visitor pattern to analyze code. Every JavaScript file is parsed into a tree of nodes — each representing a construct like a variable declaration, function call, or binary expression. A rule registers handler functions for specific node types, and ESLint calls those handlers as it traverses the tree.
A minimal ESLint rule looks like:
module.exports = {
create(context) {
return {
Identifier(node) {
if (node.name === "eval") {
context.report({ node, message: "eval() is not allowed." });
}
}
};
}
};
In this tool, you write only the visitor object — the object returned by create(context). The context variable is provided automatically and has a report() method you can call to flag violations.
How to Use This Tool
1. Choose a Severity
Select error (red), warn (yellow), or off (disabled) from the severity dropdown. This controls how violations are displayed. Setting it to off disables rule checking entirely.
2. Load an Example Rule (Optional)
Click any of the example buttons to load a pre-built rule:
- no-console — flags
console.log(),console.error(), and otherconsole.*calls - no-eval — flags
eval()function calls - no-var — flags
vardeclarations (useletorconstinstead) - eqeqeq — flags
==and!=operators (use===and!==) - no-debugger — flags
debuggerstatements
3. Write Your Rule
Edit the rule definition in the Rule Definition editor. The rule must be a JavaScript object expression where keys are AST node type names and values are visitor functions:
{
CallExpression(node) {
if (node.callee.name === "require") {
context.report({
node,
message: "Use ES module import instead of require()."
});
}
}
}
4. Write Test Code
Paste or type JavaScript code in the Test Code editor. This is the code your rule will be evaluated against.
5. View Results
The Violations panel shows every flagged location with:
- Line and column number (1-indexed)
- Severity badge (ERROR or WARN)
- Message from your
context.report()call
If no violations are found, a “No violations” message confirms the rule passed cleanly.
Supported AST Node Types
This tool supports the most common ESLint-relevant node types:
| Node Type | What It Represents |
|---|---|
Identifier | Any named reference: variables, function names, property names |
Literal | String, number, boolean, or null literals |
TemplateLiteral | Template strings with backticks |
CallExpression | Function calls: foo(), obj.method() |
MemberExpression | Property access: obj.prop, arr[0] |
NewExpression | Constructor calls: new Foo() |
VariableDeclaration | var, let, or const declarations |
FunctionDeclaration | Named function declarations |
FunctionExpression | Anonymous functions in expressions |
ArrowFunctionExpression | Arrow functions (=>) |
ClassDeclaration | Class declarations |
BinaryExpression | Operators: ==, !==, <, +, etc. |
LogicalExpression | &&, ||, ?? |
AssignmentExpression | =, +=, -=, etc. |
UpdateExpression | ++ or -- |
UnaryExpression | !, ~, typeof, void, delete |
AwaitExpression | await expressions |
IfStatement | if blocks |
WhileStatement | while loops |
ForStatement | for loops |
ReturnStatement | return statements |
ThrowStatement | throw statements |
TryStatement | try blocks |
DebuggerStatement | debugger statements |
ImportDeclaration | ES module import statements |
ExportNamedDeclaration | Named export declarations |
ExportDefaultDeclaration | export default declarations |
Writing Effective Rules
Accessing Node Properties
Each node type exposes relevant properties:
Identifier
Identifier(node) {
// node.name — the identifier's string name
if (node.name === "window") { ... }
}
CallExpression
CallExpression(node) {
// node.callee — the function being called (Identifier or MemberExpression)
// node.callee.name — for simple calls like foo()
// node.callee.object.name — for method calls like obj.method()
// node.callee.property.name — the method name
if (node.callee.type === "MemberExpression" &&
node.callee.object.name === "console") { ... }
}
VariableDeclaration
VariableDeclaration(node) {
// node.kind — "var", "let", or "const"
if (node.kind === "var") { ... }
}
BinaryExpression
BinaryExpression(node) {
// node.operator — "==", "!=", "===", "!==", "<", ">", etc.
if (node.operator === "==" || node.operator === "!=") { ... }
}
Literal
Literal(node) {
// node.value — the literal's actual value (string, number, boolean, or null)
if (typeof node.value === "string" && node.value.includes("TODO")) { ... }
}
Reporting Violations
Use context.report() to flag a violation:
context.report({
node, // Required: the offending node (sets line/column automatically)
message: "..." // Required: the error message to display
});
You can also pass a loc object to target a specific location:
context.report({
loc: { line: 3, column: 5 },
message: "Custom location message"
});
Example: No Magic Numbers
Here is a custom rule that flags numeric literals (except 0 and 1) used outside of variable declarations:
{
Literal(node) {
if (
typeof node.value === "number" &&
node.value !== 0 &&
node.value !== 1 &&
node.value !== -1
) {
context.report({
node,
message: `Magic number ${node.value} — extract to a named constant.`
});
}
}
}
Frequently Asked Questions
Is my code sent to any server?
No. All processing happens entirely in your browser using JavaScript. Your rule definitions and test code never leave your device.
Why do I only write the visitor object, not the full rule?
For simplicity. A full ESLint rule module includes metadata (type, schema, messages). This tool focuses on the visitor logic — the part that does the actual analysis. The context object is provided automatically.
What is the visitor pattern?
The visitor pattern is a software design pattern where an object (the “visitor”) has methods that are called for different node types as a tree is traversed. ESLint uses this to allow rules to react to specific JavaScript constructs without implementing a full traversal loop themselves.
Can I test multiple visitor functions in one rule?
Yes. Add multiple methods to the same visitor object:
{
VariableDeclaration(node) {
if (node.kind === "var") {
context.report({ node, message: "Use const or let." });
}
},
DebuggerStatement(node) {
context.report({ node, message: "Remove debugger statement." });
}
}
How does this compare to the ESLint RuleTester utility?
ESLint provides a RuleTester class for automated testing in Node.js environments. This tool offers an interactive, visual alternative for learning and prototyping — no setup required. For production rule development, use ESLint’s official RuleTester in your test suite.
Why are some node properties missing?
This tool uses a simplified JavaScript parser optimized for common ESLint use cases. It correctly identifies node types and key properties (name, kind, operator, callee, object, property), but does not produce a full Espree AST. For production ESLint rule development, the actual Espree parser provides complete AST fidelity.