CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-typescript-eslint--rule-tester

Tooling to test ESLint rules with comprehensive TypeScript support and advanced testing capabilities

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

Helper functions for test case formatting and test framework integration.

Capabilities

Code Formatting Control

Template tag function to mark code samples as "should not format with prettier" for plugin-test-formatting lint rule compliance.

/**
 * Simple no-op template tag to mark code samples as "should not format with prettier"
 * for the plugin-test-formatting lint rule
 * @param raw - Template strings array from template literal
 * @param keys - Interpolated values from template literal
 * @returns The original string with interpolations applied
 */
function noFormat(raw: TemplateStringsArray, ...keys: string[]): string;

Usage Examples:

import { noFormat } from "@typescript-eslint/rule-tester";

// Mark test code that should not be formatted by prettier
const testCode = noFormat`
  const   x    =     1   ;  // Intentionally poorly formatted
  function   foo(  )  {  return   'hello'  ;  }
`;

// Use in test cases where formatting matters for the rule being tested
const ruleTester = new RuleTester();

ruleTester.run("spacing-rule", spacingRule, {
  valid: [
    // Normal test case (may be formatted by prettier)
    "const x = 1;",
    
    // Test case with specific formatting that should be preserved
    noFormat`const   x   =   1;   // This spacing is intentional`,
  ],
  invalid: [
    {
      code: noFormat`var   x=1;`, // Preserve original formatting for testing
      errors: [{ messageId: "noVar" }],
      output: noFormat`const   x=1;`, // Preserve formatting in expected output
    },
  ],
});

Practical Use Cases

Real-world scenarios where noFormat is essential for rule testing.

Whitespace and Formatting Rules:

import { RuleTester, noFormat } from "@typescript-eslint/rule-tester";

const ruleTester = new RuleTester();

// Testing a rule that enforces specific spacing
ruleTester.run("object-spacing", objectSpacingRule, {
  valid: [
    // These should preserve exact spacing for testing
    noFormat`const obj = {  key: 'value'  };`, // Valid spacing
    noFormat`const arr = [  1, 2, 3  ];`,      // Valid array spacing
  ],
  invalid: [
    {
      code: noFormat`const obj = { key:'value' };`, // Invalid: no space after colon
      errors: [{ messageId: "missingSpaceAfterColon" }],
      output: noFormat`const obj = { key: 'value' };`, // Fixed spacing
    },
    {
      code: noFormat`const obj = {key: 'value'};`, // Invalid: no spaces inside braces
      errors: [{ messageId: "missingSpaceInsideBraces" }],
      output: noFormat`const obj = { key: 'value' };`, // Fixed spacing
    },
  ],
});

Indentation Rules:

// Testing indentation rules where exact whitespace matters
ruleTester.run("indent-rule", indentRule, {
  valid: [
    noFormat`
function foo() {
    return {
        prop: 'value',
        nested: {
            deep: 'value'
        }
    };
}`,
  ],
  invalid: [
    {
      code: noFormat`
function foo() {
  return {
      prop: 'value',
    nested: {
        deep: 'value'
    }
  };
}`,
      errors: [
        { messageId: "wrongIndentation", line: 4 },
        { messageId: "wrongIndentation", line: 5 },
      ],
      output: noFormat`
function foo() {
    return {
        prop: 'value',
        nested: {
            deep: 'value'
        }
    };
}`,
    },
  ],
});

Comment Formatting Rules:

// Testing rules that care about comment formatting
ruleTester.run("comment-spacing", commentSpacingRule, {
  valid: [
    noFormat`const x = 1; // This is a comment`,
    noFormat`const y = 2;  //  This has extra spaces`,
  ],
  invalid: [
    {
      code: noFormat`const x = 1;//No space before comment`,
      errors: [{ messageId: "spaceBeforeComment" }],
      output: noFormat`const x = 1; //No space before comment`,
    },
    {
      code: noFormat`const x = 1; //No space after slashes`,
      errors: [{ messageId: "spaceAfterSlashes" }],
      output: noFormat`const x = 1; // No space after slashes`,
    },
  ],
});

String Literal Formatting:

// Testing rules about string formatting where quotes and escaping matter
ruleTester.run("string-format", stringFormatRule, {
  valid: [
    noFormat`const str = "hello world";`,
    noFormat`const template = \`Hello \${name}\`;`,
  ],
  invalid: [
    {
      code: noFormat`const str = 'hello world';`, // Single quotes
      errors: [{ messageId: "useDoubleQuotes" }],
      output: noFormat`const str = "hello world";`, // Fixed to double quotes
    },
    {
      code: noFormat`const str = "hello\\nworld";`, // Escaped newline
      errors: [{ messageId: "useTemplateForMultiline" }],
      output: noFormat`const str = \`hello
world\`;`, // Convert to template literal
    },
  ],
});

Semicolon and ASI Rules:

// Testing automatic semicolon insertion rules
ruleTester.run("semicolon-rule", semicolonRule, {
  valid: [
    noFormat`const x = 1;`,
    noFormat`
const a = 1
const b = 2;`, // Mixed semicolon usage
  ],
  invalid: [
    {
      code: noFormat`
const x = 1
const y = 2`, // Missing semicolons
      errors: [
        { messageId: "missingSemicolon", line: 2 },
        { messageId: "missingSemicolon", line: 3 },
      ],
      output: noFormat`
const x = 1;
const y = 2;`,
    },
  ],
});

Integration with Prettier

The noFormat function is specifically designed to work with prettier and linting tools that enforce code formatting.

Without noFormat (problematic):

// This test might fail if prettier reformats the code
const testCode = `const   x   =   1;`; // prettier will normalize this

ruleTester.run("spacing-rule", spacingRule, {
  invalid: [
    {
      code: testCode, // May be reformatted, breaking the test
      errors: [{ messageId: "badSpacing" }],
    },
  ],
});

With noFormat (correct):

// This test preserves exact formatting
const testCode = noFormat`const   x   =   1;`; // formatting preserved

ruleTester.run("spacing-rule", spacingRule, {
  invalid: [
    {
      code: testCode, // Exact formatting maintained
      errors: [{ messageId: "badSpacing" }],
    },
  ],
});

Template Literal Features

The noFormat function supports all template literal features including interpolation.

// Dynamic test generation with preserved formatting
function generateFormattingTest(varName: string, spacing: string) {
  return noFormat`const${spacing}${varName}${spacing}=${spacing}1;`;
}

const tests = [
  {
    code: generateFormattingTest("x", "   "), // "const   x   =   1;"
    errors: [{ messageId: "badSpacing" }],
  },
  {
    code: generateFormattingTest("y", ""), // "const y = 1;"
    errors: [{ messageId: "noSpacing" }],
  },
];

// Template literals with complex interpolation
const complexTest = noFormat`
function ${functionName}(${params}) {
    ${body}
}`;

Technical Implementation

The noFormat function is implemented as a simple template tag that preserves the original string structure:

function noFormat(raw: TemplateStringsArray, ...keys: string[]): string {
  return String.raw({ raw }, ...keys);
}

This implementation:

  • Uses String.raw() to prevent escape sequence processing
  • Preserves all whitespace and formatting exactly as written
  • Supports template literal interpolation with ${...} syntax
  • Returns the exact string that would result from the template literal
  • Has no runtime overhead beyond string concatenation

Install with Tessl CLI

npx tessl i tessl/npm-typescript-eslint--rule-tester

docs

dependency-constraints.md

global-configuration.md

index.md

rule-testing.md

test-cases.md

utilities.md

tile.json