-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: add linting rule for before/beforeEach just like the async test…
… rule (#151) * Feat: add linting rule for before/beforeEach just like the async rule for test * Fix the unit test * Fix the unit test * Update docs/rules/no-async-before.md Co-authored-by: Bill Glesias <[email protected]> * Update docs/rules/no-async-before.md Co-authored-by: Bill Glesias <[email protected]> --------- Co-authored-by: Bill Glesias <[email protected]>
- Loading branch information
1 parent
1c79609
commit 8628331
Showing
4 changed files
with
125 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
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,52 @@ | ||
# Prevent using async/await in Cypress test cases (no-async-tests) | ||
|
||
Cypress commands that return a promise may cause side effects in before/beforeEach hooks, possibly causing unexpected behavior. | ||
|
||
## Rule Details | ||
|
||
This rule disallows using `async` `before` and `beforeEach` functions. | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
describe('my feature', () => { | ||
before('my test case', async () => { | ||
await cy.get('.myClass') | ||
// other operations | ||
}) | ||
}) | ||
``` | ||
|
||
```js | ||
describe('my feature', () => { | ||
before('my test case', async () => { | ||
cy | ||
.get('.myClass') | ||
.click() | ||
|
||
await someAsyncFunction() | ||
}) | ||
}) | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
describe('my feature', () => { | ||
before('my test case', () => { | ||
cy.get('.myClass') | ||
// other operations | ||
}) | ||
}) | ||
|
||
``` | ||
|
||
## When Not To Use It | ||
|
||
If there are genuine use-cases for using `async/await` in your before then you may not want to include this rule (or at least demote it to a warning). | ||
|
||
## Further Reading | ||
|
||
- [Commands Are Asynchronous](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous) | ||
- [Commands Are Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Promises) | ||
- [Commands Are Not Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Not-Promises) |
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' | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Prevent using async/await in Cypress before methods', | ||
category: 'Possible Errors', | ||
recommended: true, | ||
}, | ||
messages: { | ||
unexpected: 'Avoid using async functions with Cypress before / beforeEach functions', | ||
}, | ||
}, | ||
|
||
create (context) { | ||
function isBeforeBlock (callExpressionNode) { | ||
const { type, name } = callExpressionNode.callee | ||
|
||
return type === 'Identifier' | ||
&& name === 'before' || name === 'beforeEach' | ||
} | ||
|
||
function isBeforeAsync (node) { | ||
return node.arguments | ||
&& node.arguments.length >= 2 | ||
&& node.arguments[1].async === true | ||
} | ||
|
||
return { | ||
Identifier (node) { | ||
if (node.name === 'cy' || node.name === 'Cypress') { | ||
const ancestors = context.getAncestors() | ||
const asyncTestBlocks = ancestors | ||
.filter((n) => n.type === 'CallExpression') | ||
.filter(isBeforeBlock) | ||
.filter(isBeforeAsync) | ||
|
||
if (asyncTestBlocks.length >= 1) { | ||
asyncTestBlocks.forEach((node) => { | ||
context.report({ node, messageId: 'unexpected' }) | ||
}) | ||
} | ||
} | ||
}, | ||
} | ||
}, | ||
} |
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,25 @@ | ||
'use strict' | ||
|
||
const rule = require('../../../lib/rules/no-async-before') | ||
const RuleTester = require('eslint').RuleTester | ||
|
||
const ruleTester = new RuleTester() | ||
|
||
const errors = [{ messageId: 'unexpected' }] | ||
// async functions are an ES2017 feature | ||
const parserOptions = { ecmaVersion: 8 } | ||
|
||
ruleTester.run('no-async-before', rule, { | ||
valid: [ | ||
{ code: 'before(\'a before case\', () => { cy.get(\'.someClass\'); })', parserOptions }, | ||
{ code: 'before(\'a before case\', async () => { await somethingAsync(); })', parserOptions }, | ||
{ code: 'async function nonTestFn () { return await somethingAsync(); }', parserOptions }, | ||
{ code: 'const nonTestArrowFn = async () => { await somethingAsync(); }', parserOptions }, | ||
], | ||
invalid: [ | ||
{ code: 'before(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors }, | ||
{ code: 'beforeEach(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors }, | ||
{ code: 'before(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors }, | ||
{ code: 'beforeEach(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors }, | ||
], | ||
}) |