Skip to main content

Command Palette

Search for a command to run...

Custom ESLint rules #4/5: how to test custom rules

Because tests are a must, right?

Published
3 min read
Custom ESLint rules #4/5: how to test custom rules
G

A collaborative Front End Software Developer with 17 years of experience, including 7 years focused on cutting-edge web development. Driven by a passion for continual learning.

No pineapple pizza must be allowed in our code. That is why, in the previous bite, we created a custom ESLint plugin with a dedicated rule to forbid it. It's now time to test it!

Create ESLint plugin unit tests

Install eslint as devDependency and create the test file and test entry point file.

yummy-pizza $ npm i eslint -D -w eslint-plugin-pizza
yummy-pizza $ touch ./packages/eslint-plugin-pizza/rules/no-pineapple-pizza.test.js ./packages/eslint-plugin-pizza/pizza-rules-test-entrypoint.js

Your layout should look like this:

yummy-pizza/
├─ packages/
│  ├─ eslint-plugin-pizza/
│  │  ├─ rules/
│  │  │  ├─ no-pineapple-pizza.js
│  │  │  ├─ no-pineapple-pizza.test.js
│  │  ├─ pizza-rules-test-entrypoint.js
│  │  ├─ package.json
│  ├─ app/
│  │  ├─ src/
│  │  ├─ package.json
├─ package.json
  • no-pineapple-pizza.test.js is our test file

  • pizza-rules-test-entrypoint.js is the file that will be executed by npm t command and that will run our tests

Set up test script in ESLint plugin's package.json to call our entry point.

// yummy-pizza/eslint-plugin-pizza/package.json

{
  "name": "eslint-plugin-pizza",
  "version": "1.0.0",
  "description": "Custom ESLint plugin for pizza",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "test": "node ./pizza-rules-test-entrypoint.js"
  },
  "author": "Gabriele Buffolino",
  "license": "ISC",
  "devDependencies": {
    "eslint": "^8.53.0"
  }
}

Our test entry point file will just import our test files one by one and that's it! It's job is done!

// yummy-pizza/eslint-plugin-pizza/pizza-rules-test-entrypoint.js

import "./rules/no-pineapple-pizza.test.js";

Now we need to define our rule test. Be sure to refer to official docs, but the main gotchas are:

  • you need a RuleTester object

  • you need to invoke its run method passing in

    • the rule name

    • the rule code that should be tested

    • an object containing what code must be considered valid and what invalid

    • for fixable rules, we need to provide also how we expect the invalid code to be fixed


// yummy-pizza/packages/eslint-plugin-pizza/rules/no-pineapple-pizza.test.js

import rule from "./no-pineapple-pizza.js";
import { RuleTester } from "eslint";

const ruleTester = new RuleTester({
  // Must use at least ecmaVersion 2015 because
  // that's when `const` was introduced.
  parserOptions: { ecmaVersion: 2015 },
});

ruleTester.run(
  "no-pineapple-pizza", // rule name
  rule, // rule code
  {
    valid: [
      {
        // valid code
        code: "const yummyPizza = eatPizzaMargherita();",
      },
    ],
    // 'invalid' checks cases that should not pass
    invalid: [
      {
        // code that should be marked as error
        code: "const yummyPizza = eatPineapplePizza();",
        // what should we expect as fix
        output: "const yummyPizza = eatPizzaMargherita();",
        // one error should be detected
        errors: 1,
      },
    ],
  }
);
// share our joy for success
console.log(`[SUCCESS] no-pineapple-pizza`);

Final step: define test script in the root package.json. Using --workspaces and --if-present combined, we will run all packages test scripts and won't error if not present.

// yummy-pizza/package.json

{
  "name": "yummy-pizza",
  "version": "1.0.0",
  "description": "Sample of custom ESLint plugin definition",
  "scripts": {
    "test": "npm run test --workspaces --if-present"
  },
  "author": "Gabriele Buffolino",
  "license": "ISC",
  "workspaces": [
    "packages/*"
  ]
}

Run npm t (short for npm run test) and...

yummy-pizza $ npm t

> yummy-pizza@1.0.0 test
> npm t --workspaces --if-present


> eslint-plugin-pizza@1.0.0 test
> node ./pizza-rules-test-entrypoint.js

[SUCCESS] no-pineapple-pizza

...it works!

In the next bite, we will have a look at how to install our plugin and use it across our application.

References

How to create a custom ESLint plugin

Part 4 of 5

Custom ESLint rules allows to enforce good coding habits specific for your project. In this series, we'll cover how to create and use a custom ESLint plugin with our own ruleset.

Up next

Custom ESLint rules #5/5: use our plugin

Or how to nuke pineapple pizza code.