Skip to content

Commit

Permalink
Add no-inline-assertions rule (#262)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
JLHwung and sindresorhus committed Jul 5, 2019
1 parent 7ef827e commit b829dbc
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs/rules/no-inline-assertions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Ensure assertions are not called from inline arrow functions

The test implementation should not purely consist of an inline assertion as assertions do not return a value and having them inline also makes the tests less readable.

This rule is fixable. It will wrap the assertion in braces `{}`. It will not do any whitespace or style changes.


## Fail

```js
import test from 'ava';

test('foo', t => t.true(fn()));
```


## Pass

```js
import test from 'ava';

test('foo', t => {
t.true(fn());
});
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ module.exports = {
'ava/no-identical-title': 'error',
'ava/no-ignored-test-files': 'error',
'ava/no-import-test-files': 'error',
'ava/no-inline-assertions': 'error',
'ava/no-invalid-end': 'error',
'ava/no-nested-tests': 'error',
'ava/no-only-test': 'error',
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Configure it in `package.json`.
"ava/no-identical-title": "error",
"ava/no-ignored-test-files": "error",
"ava/no-import-test-files": "error",
"ava/no-inline-assertions": "error",
"ava/no-invalid-end": "error",
"ava/no-nested-tests": "error",
"ava/no-only-test": "error",
Expand Down Expand Up @@ -83,6 +84,7 @@ The rules will only activate in test files.
- [no-identical-title](docs/rules/no-identical-title.md) - Ensure no tests have the same title.
- [no-ignored-test-files](docs/rules/no-ignored-test-files.md) - Ensure no tests are written in ignored files.
- [no-import-test-files](docs/rules/no-import-test-files.md) - Ensure no test files are imported anywhere.
- [no-inline-assertions](docs/rules/no-inline-assertions.md) - Ensure assertions are not called from inline arrow functions. *(fixable)*
- [no-invalid-end](docs/rules/no-invalid-end.md) - Ensure `t.end()` is only called inside `test.cb()`.
- [no-nested-tests](docs/rules/no-nested-tests.md) - Ensure no tests are nested.
- [no-only-test](docs/rules/no-only-test.md) - Ensure no `test.only()` are present. *(fixable)*
Expand Down
46 changes: 46 additions & 0 deletions rules/no-inline-assertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';
const {visitIf} = require('enhance-visitors');
const createAvaRule = require('../create-ava-rule');
const util = require('../util');

const create = context => {
const ava = createAvaRule();

return ava.merge({
CallExpression: visitIf([
ava.isInTestFile,
ava.isTestNode
])(node => {
const functionArgIndex = node.arguments.length - 1;
if (functionArgIndex > 1) {
return;
}

const functionArg = node.arguments[functionArgIndex];

if (!util.isFunctionExpression(functionArg)) {
return;
}

const {body} = functionArg;
if (body.type === 'CallExpression') {
context.report({
node,
message: 'The test implementation should not be an inline arrow function.',
fix: fixer => [fixer.insertTextBefore(body, '{'), fixer.insertTextAfter(body, '}')]
});
}
})
});
};

module.exports = {
create,
meta: {
docs: {
url: util.getDocsUrl(__filename)
},
type: 'suggestion',
fixable: 'code'
}
};
47 changes: 47 additions & 0 deletions test/no-inline-assertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import test from 'ava';
import avaRuleTester from 'eslint-ava-rule-tester';
import rule from '../rules/no-inline-assertions';

const ruleTester = avaRuleTester(test, {
env: {
es6: true
}
});

const errors = [{ruleId: 'no-inline-assertions'}];
const header = 'const test = require(\'ava\');\n';

ruleTester.run('no-todo-test', rule, {
valid: [
// Shouldn't be triggered as the test implementation is not an inline arrow function
header + 'test("my test name", t => {\n t.true(fn()); \n});',
header + 'test("my test name", function (t) { foo(); });',
// Shouldn't be triggered since test body is empty
header + 'test("my test name", () => {});',
header + 'test("my test name", t => {});',
// Shouldn't be triggered since test body is ill-defined
header + 'test("my test name", t => "foo");',
// Shouldn't be triggered since it's not a test file
'test.todo("my test name");',
// Shouldn't be triggered since the signature is incorrect
header + 'test.todo("my test name", "bar");',
header + 'test.todo("my test name", undefined, t => {})'
],
invalid: [
{
code: header + 'test("my test name", t => t.skip());',
errors,
output: header + 'test("my test name", t => {t.skip()});'
},
{
code: header + 'test("my test name", t => t.true(fn()));',
errors,
output: header + 'test("my test name", t => {t.true(fn())});'
},
{
code: header + 'test("my test name", t => \n t.true(fn()));',
errors,
output: header + 'test("my test name", t => \n {t.true(fn())});'
}
]
});

0 comments on commit b829dbc

Please sign in to comment.