-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
use-t-throws-async-well
rule (#278)
Co-authored-by: Sindre Sorhus <[email protected]>
- Loading branch information
1 parent
d9f9a49
commit eea71c3
Showing
5 changed files
with
156 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Ensure that `t.throwsAsync()` and `t.notThrowsAsync()` are awaited | ||
|
||
When you use the `t.throwsAsync()` and `t.notThrowsAsync()` assertions, you must await the promise they return. If the test function completes before the assertions do, the test will fail. | ||
|
||
This rule is fixable inside `async` functions. It will insert `await` before `t.throwsAsync()` and `t.notThrowsAsync()`. | ||
|
||
## Fail | ||
|
||
```js | ||
import test from 'ava'; | ||
|
||
test('main', t => { | ||
t.throwsAsync(somePromise); | ||
t.notThrowsAsync(somePromise); | ||
}); | ||
``` | ||
|
||
## Pass | ||
|
||
```js | ||
import test from 'ava'; | ||
|
||
test('main', t => { | ||
await t.throwsAsync(somePromise); | ||
await t.notThrowsAsync(somePromise); | ||
const p = t.throwsAsync(somePromise); | ||
t.throwsAsync(somePromise).then(…); | ||
}); | ||
``` |
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,47 @@ | ||
'use strict'; | ||
const {visitIf} = require('enhance-visitors'); | ||
const util = require('../util'); | ||
const createAvaRule = require('../create-ava-rule'); | ||
|
||
const create = context => { | ||
const ava = createAvaRule(); | ||
|
||
return ava.merge({ | ||
CallExpression: visitIf([ | ||
ava.isInTestFile, | ||
ava.isInTestNode | ||
])(node => { | ||
if ( | ||
node.parent.type === 'ExpressionStatement' && | ||
node.callee.type === 'MemberExpression' && | ||
(node.callee.property.name === 'throwsAsync' || node.callee.property.name === 'notThrowsAsync') && | ||
node.callee.object.name === 't' | ||
) { | ||
const message = `Use \`await\` with \`t.${node.callee.property.name}()\`.`; | ||
if (ava.isInTestNode().arguments[0].async) { | ||
context.report({ | ||
node, | ||
message, | ||
fix: fixer => fixer.replaceText(node.callee, `await ${context.getSourceCode().getText(node.callee)}`) | ||
}); | ||
} else { | ||
context.report({ | ||
node, | ||
message | ||
}); | ||
} | ||
} | ||
}) | ||
}); | ||
}; | ||
|
||
module.exports = { | ||
create, | ||
meta: { | ||
docs: { | ||
url: util.getDocsUrl(__filename) | ||
}, | ||
fixable: 'code', | ||
type: 'problem' | ||
} | ||
}; |
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,77 @@ | ||
import test from 'ava'; | ||
import avaRuleTester from 'eslint-ava-rule-tester'; | ||
import rule from '../rules/use-t-throws-async-well'; | ||
|
||
const ruleTester = avaRuleTester(test, { | ||
parserOptions: { | ||
ecmaVersion: 2020 | ||
} | ||
}); | ||
|
||
const header = 'const test = require(\'ava\');\n'; | ||
|
||
function asyncTestCase(contents, prependHeader) { | ||
const content = `test(async t => { ${contents} });`; | ||
|
||
if (prependHeader !== false) { | ||
return header + content; | ||
} | ||
|
||
return content; | ||
} | ||
|
||
function syncTestCase(contents, prependHeader) { | ||
const content = `test(t => { ${contents} });`; | ||
|
||
if (prependHeader !== false) { | ||
return header + content; | ||
} | ||
|
||
return content; | ||
} | ||
|
||
ruleTester.run('use-t-throws-async-well', rule, { | ||
valid: [ | ||
asyncTestCase('await t.throwsAsync(f)'), | ||
asyncTestCase('await t.notThrowsAsync(f)'), | ||
asyncTestCase('t.throws(f)'), | ||
asyncTestCase('t.notThrows(f)'), | ||
asyncTestCase('f(t.throwsAsync(f))'), | ||
asyncTestCase('let p = t.throwsAsync(f)'), | ||
asyncTestCase('p = t.throwsAsync(f)'), | ||
asyncTestCase('t.throwsAsync(f)', false), // Shouldn't be triggered since it's not a test file | ||
syncTestCase('t.throwsAsync(f)', false) // Shouldn't be triggered since it's not a test file | ||
], | ||
invalid: [ | ||
{ | ||
code: syncTestCase('t.throwsAsync(f)'), | ||
errors: [{ | ||
ruleId: 'use-t-throws-async-well', | ||
message: 'Use `await` with `t.throwsAsync()`.' | ||
}] | ||
}, | ||
{ | ||
code: syncTestCase('t.notThrowsAsync(f)'), | ||
errors: [{ | ||
ruleId: 'use-t-throws-async-well', | ||
message: 'Use `await` with `t.notThrowsAsync()`.' | ||
}] | ||
}, | ||
{ | ||
code: asyncTestCase('t.throwsAsync(f)'), | ||
output: asyncTestCase('await t.throwsAsync(f)'), | ||
errors: [{ | ||
ruleId: 'use-t-throws-async-well', | ||
message: 'Use `await` with `t.throwsAsync()`.' | ||
}] | ||
}, | ||
{ | ||
code: asyncTestCase('t.notThrowsAsync(f)'), | ||
output: asyncTestCase('await t.notThrowsAsync(f)'), | ||
errors: [{ | ||
ruleId: 'use-t-throws-async-well', | ||
message: 'Use `await` with `t.notThrowsAsync()`.' | ||
}] | ||
} | ||
] | ||
}); |