eslint-plugin-cypress 2.14.0 → 2.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +4 -0
- package/.node-version +1 -0
- package/.nvmrc +1 -0
- package/README.md +1 -0
- package/circle.yml +17 -8
- package/docs/rules/no-async-before.md +52 -0
- package/lib/rules/no-async-before.js +47 -0
- package/lib/rules/unsafe-to-chain-command.js +1 -1
- package/package.json +6 -7
- package/tests/lib/rules/no-async-before.js +25 -0
- package/tests/lib/rules/unsafe-to-chain-command.js +9 -0
package/.node-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
16.15.0
|
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
16.15.0
|
package/README.md
CHANGED
package/circle.yml
CHANGED
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
- checkout
|
|
28
28
|
- run:
|
|
29
29
|
name: Install dependencies
|
|
30
|
-
command: npm
|
|
30
|
+
command: npm ci
|
|
31
31
|
- run:
|
|
32
32
|
name: Lint code
|
|
33
33
|
command: npm run lint
|
|
@@ -39,10 +39,13 @@ jobs:
|
|
|
39
39
|
- checkout
|
|
40
40
|
- run:
|
|
41
41
|
name: Install dependencies
|
|
42
|
-
command: npm
|
|
42
|
+
command: npm ci
|
|
43
|
+
- run:
|
|
44
|
+
name: Install ESLint 4
|
|
45
|
+
command: npm install eslint@4
|
|
43
46
|
- run:
|
|
44
47
|
name: Test ESLint 4
|
|
45
|
-
command: npm
|
|
48
|
+
command: npm test
|
|
46
49
|
|
|
47
50
|
test-v5:
|
|
48
51
|
docker:
|
|
@@ -51,10 +54,13 @@ jobs:
|
|
|
51
54
|
- checkout
|
|
52
55
|
- run:
|
|
53
56
|
name: Install dependencies
|
|
54
|
-
command: npm
|
|
57
|
+
command: npm ci
|
|
58
|
+
- run:
|
|
59
|
+
name: Install ESLint 5
|
|
60
|
+
command: npm install eslint@5
|
|
55
61
|
- run:
|
|
56
62
|
name: Test ESLint 5
|
|
57
|
-
command: npm
|
|
63
|
+
command: npm test
|
|
58
64
|
|
|
59
65
|
test-v6:
|
|
60
66
|
docker:
|
|
@@ -63,10 +69,13 @@ jobs:
|
|
|
63
69
|
- checkout
|
|
64
70
|
- run:
|
|
65
71
|
name: Install dependencies
|
|
66
|
-
command: npm
|
|
72
|
+
command: npm ci
|
|
73
|
+
- run:
|
|
74
|
+
name: Install ESLint 6
|
|
75
|
+
command: npm install eslint@6
|
|
67
76
|
- run:
|
|
68
77
|
name: Test ESLint 6
|
|
69
|
-
command: npm
|
|
78
|
+
command: npm test
|
|
70
79
|
|
|
71
80
|
release:
|
|
72
81
|
docker:
|
|
@@ -75,7 +84,7 @@ jobs:
|
|
|
75
84
|
- checkout
|
|
76
85
|
- run:
|
|
77
86
|
name: Install dependencies
|
|
78
|
-
command: npm
|
|
87
|
+
command: npm ci
|
|
79
88
|
- run:
|
|
80
89
|
name: Run semantic release
|
|
81
90
|
command: npm run semantic-release
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Prevent using async/await in Cypress test cases (no-async-tests)
|
|
2
|
+
|
|
3
|
+
Cypress commands that return a promise may cause side effects in before/beforeEach hooks, possibly causing unexpected behavior.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
This rule disallows using `async` `before` and `beforeEach` functions.
|
|
8
|
+
|
|
9
|
+
Examples of **incorrect** code for this rule:
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
describe('my feature', () => {
|
|
13
|
+
before('my test case', async () => {
|
|
14
|
+
await cy.get('.myClass')
|
|
15
|
+
// other operations
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
describe('my feature', () => {
|
|
22
|
+
before('my test case', async () => {
|
|
23
|
+
cy
|
|
24
|
+
.get('.myClass')
|
|
25
|
+
.click()
|
|
26
|
+
|
|
27
|
+
await someAsyncFunction()
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Examples of **correct** code for this rule:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
describe('my feature', () => {
|
|
36
|
+
before('my test case', () => {
|
|
37
|
+
cy.get('.myClass')
|
|
38
|
+
// other operations
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## When Not To Use It
|
|
45
|
+
|
|
46
|
+
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).
|
|
47
|
+
|
|
48
|
+
## Further Reading
|
|
49
|
+
|
|
50
|
+
- [Commands Are Asynchronous](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
|
|
51
|
+
- [Commands Are Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Promises)
|
|
52
|
+
- [Commands Are Not Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Not-Promises)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
meta: {
|
|
5
|
+
docs: {
|
|
6
|
+
description: 'Prevent using async/await in Cypress before methods',
|
|
7
|
+
category: 'Possible Errors',
|
|
8
|
+
recommended: true,
|
|
9
|
+
},
|
|
10
|
+
messages: {
|
|
11
|
+
unexpected: 'Avoid using async functions with Cypress before / beforeEach functions',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
create (context) {
|
|
16
|
+
function isBeforeBlock (callExpressionNode) {
|
|
17
|
+
const { type, name } = callExpressionNode.callee
|
|
18
|
+
|
|
19
|
+
return type === 'Identifier'
|
|
20
|
+
&& name === 'before' || name === 'beforeEach'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isBeforeAsync (node) {
|
|
24
|
+
return node.arguments
|
|
25
|
+
&& node.arguments.length >= 2
|
|
26
|
+
&& node.arguments[1].async === true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
Identifier (node) {
|
|
31
|
+
if (node.name === 'cy' || node.name === 'Cypress') {
|
|
32
|
+
const ancestors = context.getAncestors()
|
|
33
|
+
const asyncTestBlocks = ancestors
|
|
34
|
+
.filter((n) => n.type === 'CallExpression')
|
|
35
|
+
.filter(isBeforeBlock)
|
|
36
|
+
.filter(isBeforeAsync)
|
|
37
|
+
|
|
38
|
+
if (asyncTestBlocks.length >= 1) {
|
|
39
|
+
asyncTestBlocks.forEach((node) => {
|
|
40
|
+
context.report({ node, messageId: 'unexpected' })
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-cypress",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.2",
|
|
4
4
|
"description": "An ESLint plugin for projects using Cypress",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Cypress-io",
|
|
@@ -27,22 +27,21 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@cypress/eslint-plugin-dev": "3.2.0",
|
|
29
29
|
"@cypress/eslint-plugin-json": "3.2.1",
|
|
30
|
-
"condition-circle": "2.0.2",
|
|
31
30
|
"eslint": "^5.7.0",
|
|
32
|
-
"husky": "^
|
|
31
|
+
"husky": "^8.0.3",
|
|
33
32
|
"jest": "^24.8.0",
|
|
34
|
-
"semantic-release": "
|
|
33
|
+
"semantic-release": "19.0.3"
|
|
35
34
|
},
|
|
36
35
|
"scripts": {
|
|
37
|
-
"
|
|
38
|
-
"lint": "eslint '*.js' '**/**/*.js'",
|
|
36
|
+
"lint": "eslint \"*.js\" \"**/**/*.js\"",
|
|
39
37
|
"lint-fix": "npm run lint -- --fix",
|
|
40
38
|
"semantic-release": "semantic-release",
|
|
41
39
|
"start": "yarn run test-watch",
|
|
42
40
|
"test": "jest",
|
|
43
41
|
"test:v4": "npm i eslint@4.x && npm run test",
|
|
44
42
|
"test:v6": "npm i eslint@6.x && npm run test",
|
|
45
|
-
"test-watch": "jest --watchAll"
|
|
43
|
+
"test-watch": "jest --watchAll",
|
|
44
|
+
"prepare": "husky install"
|
|
46
45
|
},
|
|
47
46
|
"jest": {
|
|
48
47
|
"testMatch": [
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const rule = require('../../../lib/rules/no-async-before')
|
|
4
|
+
const RuleTester = require('eslint').RuleTester
|
|
5
|
+
|
|
6
|
+
const ruleTester = new RuleTester()
|
|
7
|
+
|
|
8
|
+
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
+
// async functions are an ES2017 feature
|
|
10
|
+
const parserOptions = { ecmaVersion: 8 }
|
|
11
|
+
|
|
12
|
+
ruleTester.run('no-async-before', rule, {
|
|
13
|
+
valid: [
|
|
14
|
+
{ code: 'before(\'a before case\', () => { cy.get(\'.someClass\'); })', parserOptions },
|
|
15
|
+
{ code: 'before(\'a before case\', async () => { await somethingAsync(); })', parserOptions },
|
|
16
|
+
{ code: 'async function nonTestFn () { return await somethingAsync(); }', parserOptions },
|
|
17
|
+
{ code: 'const nonTestArrowFn = async () => { await somethingAsync(); }', parserOptions },
|
|
18
|
+
],
|
|
19
|
+
invalid: [
|
|
20
|
+
{ code: 'before(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
21
|
+
{ code: 'beforeEach(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
22
|
+
{ code: 'before(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
23
|
+
{ code: 'beforeEach(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
24
|
+
],
|
|
25
|
+
})
|
|
@@ -14,6 +14,10 @@ ruleTester.run('action-ends-chain', rule, {
|
|
|
14
14
|
code: 'cy.get("new-todo").type("todo A{enter}"); cy.get("new-todo").type("todo B{enter}"); cy.get("new-todo").should("have.class", "active");',
|
|
15
15
|
parserOptions,
|
|
16
16
|
},
|
|
17
|
+
{
|
|
18
|
+
code: 'cy.focused().should("be.visible");',
|
|
19
|
+
parserOptions,
|
|
20
|
+
},
|
|
17
21
|
],
|
|
18
22
|
|
|
19
23
|
invalid: [
|
|
@@ -27,6 +31,11 @@ ruleTester.run('action-ends-chain', rule, {
|
|
|
27
31
|
parserOptions,
|
|
28
32
|
errors,
|
|
29
33
|
},
|
|
34
|
+
{
|
|
35
|
+
code: 'cy.get("new-todo").focus().should("have.class", "active");',
|
|
36
|
+
parserOptions,
|
|
37
|
+
errors,
|
|
38
|
+
},
|
|
30
39
|
{
|
|
31
40
|
code: 'cy.get("new-todo").customType("todo A{enter}").customClick();',
|
|
32
41
|
parserOptions,
|