How to use ESLint with Jest

2019-03-08 17:25发布

问题:

I'm attempting to use the ESLint linter with the Jest testing framework.

Jest tests run with some globals like jest, which I'll need to tell the linter about; but the tricky thing is the directory structure, with Jest the tests are embedded with the source code in __tests__ folders, so the directory structure looks something like:

src
    foo
        foo.js
        __tests__
            fooTest.js
    bar
        bar.js
        __tests__
            barTest.js

Normally, I'd have all my tests under a single dir, and I could just add an .eslintrc file there to add the globals... but I certainly don't want to add a .eslintrc file to every single __test__ dir.

For now, I've just added the test globals to the global .eslintrc file, but since that means I could now reference jest in non-testing code, that doesn't seem like the "right" solution.

Is there a way to get eslint to apply rules based on some pattern based on the directory name, or something like that?

回答1:

The docs show you are now able to add:

"env": {
    "jest": true
}

To your .eslintrc which will add all the jest related things to your environment, eliminating the linter errors/warnings.

Hope that helps!



回答2:

ESLint supports this as of version >= 4:

/*
.eslintrc.js
*/
const ERROR = 2;
const WARN = 1;

module.exports = {
  extends: "eslint:recommended",
  env: {
    es6: true
  },
  overrides: [
    {
      files: [
        "**/*.test.js"
      ],
      env: {
        jest: true // now **/*.test.js files' env has both es6 *and* jest
      },
      // Can't extend in overrides: https://github.com/eslint/eslint/issues/8813
      // "extends": ["plugin:jest/recommended"]
      plugins: ["jest"],
      rules: {
        "jest/no-disabled-tests": "warn",
        "jest/no-focused-tests": "error",
        "jest/no-identical-title": "error",
        "jest/prefer-to-have-length": "warn",
        "jest/valid-expect": "error"
      }
    }
  ],
};

Here is a workaround (from another answer on here, vote it up!) for the "extend in overrides" limitation of eslint config :

overrides: [
  Object.assign(
    {
      files: [ '**/*.test.js' ],
      env: { jest: true },
      plugins: [ 'jest' ],
    },
    require('eslint-plugin-jest').configs.recommended
  )
]

From https://github.com/eslint/eslint/issues/8813#issuecomment-320448724



回答3:

You can also set the test env in your test file as follows:

/* eslint-env jest */

describe(() => {
  /* ... */
})


回答4:

To complete Zachary's answer, here is a workaround for the "extend in overrides" limitation of eslint config :

overrides: [
  Object.assign(
    {
      files: [ '**/*.test.js' ],
      env: { jest: true },
      plugins: [ 'jest' ],
    },
    require('eslint-plugin-jest').configs.recommended
  )
]

From https://github.com/eslint/eslint/issues/8813#issuecomment-320448724



回答5:

Pattern based configs are scheduled for 2.0.0 release of ESLint. For now, however, you will have to create two separate tasks (as mentioned in the comments). One for tests and one for the rest of the code and run both of them, while providing different .eslintrc files.

P.S. There's a jest environment coming in the next release of ESLint, it will register all of the necessary globals.



回答6:

Add environment only for __tests__ folder

You could add a .eslintrc.yml file in your __tests__ folders, that extends you basic configuration:

extends: <relative_path to .eslintrc>
env:
    jest: true

If you have only one __tests__folder, this solution is the best since it scope jest environment only where it is needed.

Dealing with many test folders

If you have more test folders (OPs case), I'd still suggest to add those files. And if you have tons of those folders can add them with a simple zsh script:

#!/usr/bin/env zsh

for folder in **/__tests__/ ;do
    count=$(($(tr -cd '/' <<< $folder | wc -c)))
    echo $folder : $count
    cat <<EOF > $folder.eslintrc.yml
extends: $(printf '../%.0s' {1..$count}).eslintrc
env:
    jest: true
EOF
done

This script will look for __tests__ folders and add a .eslintrc.yml file with to configuration shown above. This script has to be launched within the folder containing your parent .eslintrc.



回答7:

In your .eslintignore file add the following value:

**/__tests__/

This should ignore all instances of the __tests__ directory and their children.