test-rule

SkillDev tools

Write 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.

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

RuleTesterUse When
DefaultParserRuleTesterPure JavaScript rules, no TypeScript syntax
NoTypeCheckingRuleTesterJS/TS rules that don't need type information
RuleTesterRules requiring TypeScript type information
RuleTester with @babel/eslint-parserLegacy 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

SyntaxEffect
// 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@qfDelete 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