Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(rules): add no-test-prefixes rule (#70)
Fixes #63
  • Loading branch information
ranyitz authored and SimenB committed Feb 12, 2018
1 parent 178744b commit a12a2d2
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 15 deletions.
31 changes: 16 additions & 15 deletions README.md
Expand Up @@ -78,21 +78,22 @@ for more information about extending configuration files.

## Rules

| Rule | Description | Recommended | Fixable |
| ------------------------------------------------------------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce consistent test or it keyword | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | Disallow large snapshots | | |
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | |
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | | |
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | | |
| Rule | Description | Recommended | Fixable |
| ------------------------------------------------------------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce consistent test or it keyword | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | Disallow large snapshots | | |
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Disallow using `f` & `x` prefixes to define focused/skipped tests | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | | ![fixable](https://img.shields.io/badge/-fixable-green.svg) |
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | |
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | | |
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | |
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | | |

## Credit

Expand Down
32 changes: 32 additions & 0 deletions docs/rules/no-test-prefixes.md
@@ -0,0 +1,32 @@
# Use `.only` and `.skip` over `f` and `x` (no-test-prefixes)

Jest allows you to choose how you want to define focused and skipped tests, with
multiple permutations for each:

* **only & skip:** `it.only`, `test.only`, `describe.only`, `it.skip`,
`test.skip`, `describe.skip`.
* **'f' & 'x':** `fit`, `fdescribe`, `xit`, `xtest`, `xdescribe`.

This rule enforces usages from the **only & skip** list.

## Rule details

This rule triggers a warning if you use one of the keywords from the **'f' &
'x'** list to focus/skip a test.

```js
/*eslint jest/no-test-prefixes: "error"*/

it.only('foo'); // valid
test.only('foo'); // valid
describe.only('foo'); // valid
it.skip('foo'); // valid
test.skip('foo'); // valid
describe.skip('foo'); // valid

fit('foo'); // invalid
fdescribe('foo'); // invalid
xit('foo'); // invalid
xtest('foo'); // invalid
xdescribe('foo'); // invalid
```
2 changes: 2 additions & 0 deletions index.js
Expand Up @@ -6,6 +6,7 @@ const noFocusedTests = require('./rules/no-focused-tests');
const noHooks = require('./rules/no-hooks');
const noIdenticalTitle = require('./rules/no-identical-title');
const noLargeSnapshots = require('./rules/no-large-snapshots');
const noTestPrefixes = require('./rules/no-test-prefixes');
const preferToBeNull = require('./rules/prefer-to-be-null');
const preferToBeUndefined = require('./rules/prefer-to-be-undefined');
const preferToHaveLength = require('./rules/prefer-to-have-length');
Expand Down Expand Up @@ -65,6 +66,7 @@ module.exports = {
'no-hooks': noHooks,
'no-identical-title': noIdenticalTitle,
'no-large-snapshots': noLargeSnapshots,
'no-test-prefixes': noTestPrefixes,
'prefer-to-be-null': preferToBeNull,
'prefer-to-be-undefined': preferToBeUndefined,
'prefer-to-have-length': preferToHaveLength,
Expand Down
48 changes: 48 additions & 0 deletions rules/__tests__/no-test-prefixes.test.js
@@ -0,0 +1,48 @@
'use strict';

const RuleTester = require('eslint').RuleTester;
const rules = require('../..').rules;

const ruleTester = new RuleTester();

ruleTester.run('no-test-prefixes', rules['no-test-prefixes'], {
valid: [
'describe("foo", function () {})',
'it("foo", function () {})',
'test("foo", function () {})',
'describe.only("foo", function () {})',
'it.only("foo", function () {})',
'test.only("foo", function () {})',
'describe.skip("foo", function () {})',
'it.skip("foo", function () {})',
'test.skip("foo", function () {})',
'foo()',
],
invalid: [
{
code: 'fdescribe("foo", function () {})',
errors: [{ message: 'Use "describe.only" instead', column: 1, line: 1 }],
output: 'describe.only("foo", function () {})',
},
{
code: 'fit("foo", function () {})',
errors: [{ message: 'Use "it.only" instead', column: 1, line: 1 }],
output: 'it.only("foo", function () {})',
},
{
code: 'xdescribe("foo", function () {})',
errors: [{ message: 'Use "describe.skip" instead', column: 1, line: 1 }],
output: 'describe.skip("foo", function () {})',
},
{
code: 'xit("foo", function () {})',
errors: [{ message: 'Use "it.skip" instead', column: 1, line: 1 }],
output: 'it.skip("foo", function () {})',
},
{
code: 'xtest("foo", function () {})',
errors: [{ message: 'Use "test.skip" instead', column: 1, line: 1 }],
output: 'test.skip("foo", function () {})',
},
],
});
49 changes: 49 additions & 0 deletions rules/no-test-prefixes.js
@@ -0,0 +1,49 @@
'use strict';

const getNodeName = require('./util').getNodeName;
const isTestCase = require('./util').isTestCase;
const isDescribe = require('./util').isDescribe;

module.exports = {
meta: {
docs: {
url:
'https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-test-prefixes.md',
},
fixable: 'code',
},
create(context) {
return {
CallExpression: node => {
const nodeName = getNodeName(node.callee);

if (!isDescribe(node) && !isTestCase(node)) return;

const preferredNodeName = getPreferredNodeName(nodeName);

if (!preferredNodeName) return;

context.report({
message: 'Use "{{ preferredNodeName }}" instead',
node: node.callee,
data: { preferredNodeName },
fix(fixer) {
return [fixer.replaceText(node.callee, preferredNodeName)];
},
});
},
};
},
};

function getPreferredNodeName(nodeName) {
const firstChar = nodeName.charAt(0);

if (firstChar === 'f') {
return nodeName.slice(1) + '.only';
}

if (firstChar === 'x') {
return nodeName.slice(1) + '.skip';
}
}

0 comments on commit a12a2d2

Please sign in to comment.