Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat(no-export): new rule for no-export (#307)
- Loading branch information
Showing
5 changed files
with
146 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# no export from test file (no-export) | ||
|
||
Prevents exports from test files. If a file has at least 1 test in it, then this | ||
rule will prevent exports. | ||
|
||
## Rule Details | ||
|
||
This rule aims to eliminate duplicate runs of tests by exporting things from | ||
test files. If you import from a test file, then all the tests in that file will | ||
be run in each imported instance, so bottom line, don't export from a test, but | ||
instead move helper functions into a seperate file when they need to be shared | ||
across tests. | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
export function myHelper() {} | ||
|
||
module.exports = function() {}; | ||
|
||
module.exports = { | ||
something: 'that should be moved to a non-test file', | ||
}; | ||
|
||
describe('a test', () => { | ||
expect(1).toBe(1); | ||
}); | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
function myHelper() {} | ||
|
||
const myThing = { | ||
something: 'that can live here', | ||
}; | ||
|
||
describe('a test', () => { | ||
expect(1).toBe(1); | ||
}); | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
Don't use this rule on non-jest test files. |
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,50 @@ | ||
import { RuleTester } from 'eslint'; | ||
import rule from '../no-export'; | ||
|
||
const ruleTester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 2015, | ||
sourceType: 'module', | ||
}, | ||
}); | ||
|
||
ruleTester.run('no-export', rule, { | ||
valid: [ | ||
'describe("a test", () => { expect(1).toBe(1); })', | ||
'window.location = "valid"', | ||
'module.somethingElse = "foo";', | ||
'export const myThing = "valid"', | ||
'export default function () {}', | ||
'module.exports = function(){}', | ||
'module.exports.myThing = "valid";', | ||
], | ||
invalid: [ | ||
{ | ||
code: | ||
'export const myThing = "invalid"; test("a test", () => { expect(1).toBe(1);});', | ||
parserOptions: { sourceType: 'module' }, | ||
errors: [{ endColumn: 34, column: 1, messageId: 'unexpectedExport' }], | ||
}, | ||
{ | ||
code: | ||
'export default function() {}; test("a test", () => { expect(1).toBe(1);});', | ||
parserOptions: { sourceType: 'module' }, | ||
errors: [{ endColumn: 29, column: 1, messageId: 'unexpectedExport' }], | ||
}, | ||
{ | ||
code: | ||
'module.exports["invalid"] = function() {}; test("a test", () => { expect(1).toBe(1);});', | ||
errors: [{ endColumn: 26, column: 1, messageId: 'unexpectedExport' }], | ||
}, | ||
{ | ||
code: | ||
'module.exports = function() {}; ; test("a test", () => { expect(1).toBe(1);});', | ||
errors: [{ endColumn: 15, column: 1, messageId: 'unexpectedExport' }], | ||
}, | ||
{ | ||
code: | ||
'module.export.invalid = function() {}; ; test("a test", () => { expect(1).toBe(1);});', | ||
errors: [{ endColumn: 22, column: 1, messageId: 'unexpectedExport' }], | ||
}, | ||
], | ||
}); |
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,47 @@ | ||
import { getDocsUrl, isTestCase } from './util'; | ||
|
||
export default { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl(__filename), | ||
}, | ||
messages: { | ||
unexpectedExport: `Do not export from a test file.`, | ||
}, | ||
schema: [], | ||
}, | ||
create(context) { | ||
const exportNodes = []; | ||
let hasTestCase = false; | ||
|
||
return { | ||
'Program:exit'() { | ||
if (hasTestCase && exportNodes.length > 0) { | ||
for (let node of exportNodes) { | ||
context.report({ node, messageId: 'unexpectedExport' }); | ||
} | ||
} | ||
}, | ||
|
||
CallExpression(node) { | ||
if (isTestCase(node)) { | ||
hasTestCase = true; | ||
} | ||
}, | ||
'ExportNamedDeclaration, ExportDefaultDeclaration'(node) { | ||
exportNodes.push(node); | ||
}, | ||
'AssignmentExpression > MemberExpression'(node) { | ||
let { object, property } = node; | ||
|
||
if (object.type === 'MemberExpression') { | ||
({ object, property } = object); | ||
} | ||
|
||
if (object.name === 'module' && /^exports?$/.test(property.name)) { | ||
exportNodes.push(node); | ||
} | ||
}, | ||
}; | ||
}, | ||
}; |