test-rule
SkillDev toolsWrite and run tests for a SonarJS rule. Use when working on rule tests, writing test fixtures, or running unit tests for a specific rule.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the test-rule skill
What this skill tells your AI
The instructions your AI receives, as published by sonarsource/sonarjs in .claude/skills/test-rule/SKILL.md and read by ahel’s review.
Running Tests
npx tsx --test packages/analysis/src/jsts/rules/S1234/**/*.test.ts
Replace S1234 with the actual rule number. Do not run the full test suite (npm run bridge:test) — it takes too long.
RuleTester Selection
| RuleTester | Use When |
|---|---|
DefaultParserRuleTester | Pure JavaScript rules, no TypeScript syntax |
NoTypeCheckingRuleTester | JS/TS rules that don't need type information |
RuleTester | Rules requiring TypeScript type information |
RuleTester with @babel/eslint-parser | Legacy JavaScript or Babel-specific syntax (e.g. Flow types, decorator proposals) |
Comment-Based Tests (preferred)
Test files are named *.fixture.* (e.g., cb.fixture.js, cb.fixture.ts) and live in the rule folder.
Basic Syntax
some.clean.code(); // no issue
some.faulty.code(); // Noncompliant {{Message to assert}}
// ^^^^^^
The // ^^^^^^ underline marks the primary location (optional but recommended).
With Quick Fixes
some.faulty.code(); // Noncompliant [[qf1]] {{Message}}
// fix@qf1 {{Suggestion description}}
// edit@qf1 [[sc=1;ec=5]] {{replacement text}}
For ESLint fixes (not suggestions), use ! suffix: [[qf1!]]. ESLint fixes must not have a fix@ comment.
Secondary Locations
context.report({
node,
message: toEncodedMessage(message, [secondaryNode], ['secondary message']),
});
In fixture:
primary.node(); // Noncompliant {{primary message}}
secondary.node(); // ^^^^^^^^^^^^^^< {{secondary message}}
Arrow direction: < means secondary is after primary; > means secondary is before primary.
Line Reference Modifiers
// Noncompliant@+1 {{message}} ← issue is on next line
some.faulty.code();
// Noncompliant@-1 ← issue is on previous line
some.faulty.code();
some.faulty.code(); // Noncompliant@2 ← absolute line number
Rule Options in Tests
Add a cb.options.json file in the rule folder:
[7, { "ignoreIIFE": true }]
Package.json Dependency Testing
process.chdir(__dirname); // use local package.json for dependency detection
ESLint RuleTester Format
For rules needing TypeScript type checking:
import { RuleTester } from '../../../tests/tools/testers/rule-tester.js';
const ruleTester = new RuleTester();
ruleTester.run('rule-name', rule, {
valid: [{ code: 'valid code here' }],
invalid: [
{
code: 'invalid code here',
errors: [{ messageId: 'errorKey' }],
},
],
});
Quick Fix Operation Syntax
| Syntax | Effect |
|---|---|
// edit@qf [[sc=1;ec=5]] {{text}} | Replace column 1–5 with text |
// edit@qf {{whole line replacement}} | Replace entire line |
// add@qf {{new line content}} | Add new line after issue line |
// del@qf | Delete the line |
// add@qf@+1 {{content}} | Add after line+1 |
Multiple Issues / Multiple Quick Fixes
// Three issues, fix for 1st and 3rd:
code(); // Noncompliant [[qf1,,qf3]] {{msg1}} {{msg2}} {{msg3}}
// edit@qf1 {{fix for msg1}}
// edit@qf3 {{fix for msg3}}
// Or with explicit index:
code(); // Noncompliant [[qf1,qf3=2]] {{msg1}} {{msg2}} {{msg3}}
Signals
- GitHub stars
- 1k
- Forks
- 192
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
test-rule- Source
- github.com/sonarsource/sonarjs