Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add no-mocks-import rule (#246)
- Loading branch information
Showing
6 changed files
with
161 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Disallow manually importing from `__mocks__` (no-mocks-import) | ||
|
||
When using `jest.mock`, your tests (just like the code being tested) should | ||
import from `./x`, not `./__mocks__/x`. Not following this rule can lead to | ||
confusion, because you will have multiple instances of the mocked module: | ||
|
||
```js | ||
jest.mock('./x'); | ||
const x1 = require('./x'); | ||
const x2 = require('./__mocks__/x'); | ||
|
||
test('x', () => { | ||
expect(x1).toBe(x2); // fails! They are both instances of `./__mocks__/x`, but not referentially equal | ||
}); | ||
``` | ||
|
||
### Rule details | ||
|
||
This rule reports imports from a path containing a `__mocks__` component. | ||
|
||
Example violations: | ||
|
||
```js | ||
import thing from './__mocks__/index'; | ||
require('./__mocks__/index'); | ||
require('__mocks__'); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
'use strict'; | ||
|
||
const rule = require('../no-mocks-import.js'); | ||
const { RuleTester } = require('eslint'); | ||
const ruleTester = new RuleTester(); | ||
const message = `Mocks should not be manually imported from a __mocks__ directory. Instead use jest.mock and import from the original module path.`; | ||
|
||
ruleTester.run('no-mocks-import', rule, { | ||
valid: [ | ||
{ | ||
code: 'import something from "something"', | ||
parserOptions: { sourceType: 'module' }, | ||
}, | ||
'require("somethingElse")', | ||
'require("./__mocks__.js")', | ||
'require("./__mocks__x")', | ||
'require("./__mocks__x/x")', | ||
'require("./x__mocks__")', | ||
'require("./x__mocks__/x")', | ||
'require()', | ||
'entirelyDifferent(fn)', | ||
], | ||
invalid: [ | ||
{ | ||
code: 'require("./__mocks__")', | ||
errors: [ | ||
{ | ||
endColumn: 22, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'require("./__mocks__/")', | ||
errors: [ | ||
{ | ||
endColumn: 23, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'require("./__mocks__/index")', | ||
errors: [ | ||
{ | ||
endColumn: 28, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'require("__mocks__")', | ||
errors: [ | ||
{ | ||
endColumn: 20, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'require("__mocks__/")', | ||
errors: [ | ||
{ | ||
endColumn: 21, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'require("__mocks__/index")', | ||
errors: [ | ||
{ | ||
endColumn: 26, | ||
column: 9, | ||
message, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'import thing from "./__mocks__/index"', | ||
parserOptions: { sourceType: 'module' }, | ||
errors: [ | ||
{ | ||
endColumn: 38, | ||
column: 1, | ||
message, | ||
}, | ||
], | ||
}, | ||
], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
'use strict'; | ||
|
||
const { posix } = require('path'); | ||
const { getDocsUrl } = require('./util'); | ||
|
||
const mocksDirName = '__mocks__'; | ||
const message = `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use jest.mock and import from the original module path.`; | ||
|
||
const isMockPath = path => path.split(posix.sep).includes(mocksDirName); | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl(__filename), | ||
}, | ||
}, | ||
create(context) { | ||
return { | ||
ImportDeclaration(node) { | ||
if (isMockPath(node.source.value)) { | ||
context.report({ node, message }); | ||
} | ||
}, | ||
'CallExpression[callee.name="require"]'(node) { | ||
if (node.arguments.length && isMockPath(node.arguments[0].value)) { | ||
context.report({ | ||
loc: node.arguments[0].loc, | ||
message, | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
}; |