eslint-plugin-cypress 5.0.0 → 5.1.0
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/CONTRIBUTING.md +1 -1
- package/lib/flat.js +8 -8
- package/lib/rules/assertion-before-screenshot.js +21 -21
- package/lib/rules/no-assigning-return-values.js +4 -4
- package/lib/rules/no-async-before.js +10 -10
- package/lib/rules/no-async-tests.js +10 -10
- package/lib/rules/no-chained-get.js +32 -32
- package/lib/rules/no-debug.js +18 -19
- package/lib/rules/no-force.js +21 -24
- package/lib/rules/no-pause.js +18 -19
- package/lib/rules/no-unnecessary-waiting.js +13 -13
- package/lib/rules/no-xpath.js +10 -10
- package/lib/rules/require-data-selectors.js +14 -14
- package/lib/rules/unsafe-to-chain-command.js +13 -13
- package/package.json +10 -6
- package/.github/workflows/add-issue-triage-board.yml +0 -12
- package/.github/workflows/triage_closed_issue_comment.yml +0 -9
- package/.husky/pre-commit +0 -1
- package/.node-version +0 -1
- package/.nvmrc +0 -1
- package/ESLINTRC-CONFIG.md +0 -7
- package/FLAT-CONFIG.md +0 -3
- package/circle.yml +0 -137
- package/eslint.config.mjs +0 -26
- package/jest.config.js +0 -6
- package/test-project/README.md +0 -48
- package/test-project/cypress/e2e/1-getting-started/todo.cy.js +0 -143
- package/test-project/cypress/e2e/2-advanced-examples/actions.cy.js +0 -321
- package/test-project/cypress/e2e/2-advanced-examples/aliasing.cy.js +0 -39
- package/test-project/cypress/e2e/2-advanced-examples/assertions.cy.js +0 -176
- package/test-project/cypress/e2e/2-advanced-examples/connectors.cy.js +0 -98
- package/test-project/cypress/e2e/2-advanced-examples/cookies.cy.js +0 -118
- package/test-project/cypress/e2e/2-advanced-examples/cypress_api.cy.js +0 -185
- package/test-project/cypress/e2e/2-advanced-examples/files.cy.js +0 -85
- package/test-project/cypress/e2e/2-advanced-examples/location.cy.js +0 -32
- package/test-project/cypress/e2e/2-advanced-examples/misc.cy.js +0 -90
- package/test-project/cypress/e2e/2-advanced-examples/navigation.cy.js +0 -55
- package/test-project/cypress/e2e/2-advanced-examples/network_requests.cy.js +0 -163
- package/test-project/cypress/e2e/2-advanced-examples/querying.cy.js +0 -114
- package/test-project/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +0 -204
- package/test-project/cypress/e2e/2-advanced-examples/storage.cy.js +0 -117
- package/test-project/cypress/e2e/2-advanced-examples/traversal.cy.js +0 -121
- package/test-project/cypress/e2e/2-advanced-examples/utilities.cy.js +0 -107
- package/test-project/cypress/e2e/2-advanced-examples/viewport.cy.js +0 -58
- package/test-project/cypress/e2e/2-advanced-examples/waiting.cy.js +0 -30
- package/test-project/cypress/e2e/2-advanced-examples/window.cy.js +0 -22
- package/test-project/cypress/fixtures/example.json +0 -5
- package/test-project/cypress/support/commands.js +0 -25
- package/test-project/cypress/support/e2e.js +0 -17
- package/test-project/cypress.config.js +0 -9
- package/test-project/eslint-configs/eslint.default-deprecated.mjs +0 -11
- package/test-project/eslint-configs/eslint.default.mjs +0 -9
- package/test-project/eslint-configs/eslint.globals.mjs +0 -4
- package/test-project/eslint-configs/eslint.recommended.mjs +0 -9
- package/test-project/eslint.config.mjs +0 -9
- package/test-project/package.json +0 -9
- package/tests/config.js +0 -26
- package/tests/lib/rules/assertion-before-screenshot.js +0 -34
- package/tests/lib/rules/no-assigning-return-values.js +0 -37
- package/tests/lib/rules/no-async-before.js +0 -23
- package/tests/lib/rules/no-async-tests.js +0 -23
- package/tests/lib/rules/no-chained-get.js +0 -31
- package/tests/lib/rules/no-debug.js +0 -23
- package/tests/lib/rules/no-force.js +0 -39
- package/tests/lib/rules/no-pause.js +0 -23
- package/tests/lib/rules/no-unnecessary-waiting.js +0 -47
- package/tests/lib/rules/no-xpath.js +0 -30
- package/tests/lib/rules/require-data-selectors.js +0 -30
- package/tests/lib/rules/unsafe-to-chain-command.js +0 -34
package/CONTRIBUTING.md
CHANGED
|
@@ -32,7 +32,7 @@ To add a new rule:
|
|
|
32
32
|
* Run `eslint-doc-generator` to generate automated documentation sections (see [Document generation](#document-generation) below)
|
|
33
33
|
* Review documentation changes
|
|
34
34
|
* Run `npm run lint`
|
|
35
|
-
* Run `npm test` to run [
|
|
35
|
+
* Run `npm test` to run [Vitest](https://vitest.dev/)
|
|
36
36
|
* Make sure all tests are passing
|
|
37
37
|
* Add the rule to [flat.js](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/lib/flat.js)
|
|
38
38
|
* Create a git commit with a commit message similar to: `feat: add rule <description>` (see [commit message conventions](https://github.com/semantic-release/semantic-release#commit-message-format))
|
package/lib/flat.js
CHANGED
|
@@ -20,8 +20,8 @@ const plugin = {
|
|
|
20
20
|
},
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const commonGlobals
|
|
24
|
-
Object.assign({
|
|
23
|
+
const commonGlobals
|
|
24
|
+
= Object.assign({
|
|
25
25
|
cy: false,
|
|
26
26
|
Cypress: false,
|
|
27
27
|
expect: false,
|
|
@@ -33,20 +33,20 @@ Object.assign(plugin.configs, {
|
|
|
33
33
|
globals: {
|
|
34
34
|
name: 'cypress/globals',
|
|
35
35
|
plugins: {
|
|
36
|
-
cypress: plugin
|
|
36
|
+
cypress: plugin,
|
|
37
37
|
},
|
|
38
38
|
languageOptions: {
|
|
39
39
|
globals:
|
|
40
40
|
commonGlobals,
|
|
41
|
-
}
|
|
42
|
-
}
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
Object.assign(plugin.configs, {
|
|
46
46
|
recommended: {
|
|
47
47
|
name: 'cypress/recommended',
|
|
48
48
|
plugins: {
|
|
49
|
-
cypress: plugin
|
|
49
|
+
cypress: plugin,
|
|
50
50
|
},
|
|
51
51
|
rules: {
|
|
52
52
|
'cypress/no-assigning-return-values': 'error',
|
|
@@ -57,8 +57,8 @@ Object.assign(plugin.configs, {
|
|
|
57
57
|
languageOptions: {
|
|
58
58
|
globals:
|
|
59
59
|
commonGlobals,
|
|
60
|
-
}
|
|
61
|
-
}
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
module.exports = plugin
|
|
@@ -28,9 +28,9 @@ module.exports = {
|
|
|
28
28
|
unexpected: 'Make an assertion on the page state before taking a screenshot',
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
|
-
create
|
|
31
|
+
create(context) {
|
|
32
32
|
return {
|
|
33
|
-
CallExpression
|
|
33
|
+
CallExpression(node) {
|
|
34
34
|
if (isCallingCyScreenshot(node) && !isPreviousAnAssertion(node)) {
|
|
35
35
|
context.report({ node, messageId: 'unexpected' })
|
|
36
36
|
}
|
|
@@ -39,12 +39,12 @@ module.exports = {
|
|
|
39
39
|
},
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function isRootCypress
|
|
42
|
+
function isRootCypress(node) {
|
|
43
43
|
while (node.type === 'CallExpression') {
|
|
44
44
|
if (node.callee.type !== 'MemberExpression') return false
|
|
45
45
|
|
|
46
|
-
if (node.callee.object.type === 'Identifier'
|
|
47
|
-
|
|
46
|
+
if (node.callee.object.type === 'Identifier'
|
|
47
|
+
&& node.callee.object.name === 'cy') {
|
|
48
48
|
return true
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -54,26 +54,26 @@ function isRootCypress (node) {
|
|
|
54
54
|
return false
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function getPreviousInChain
|
|
58
|
-
return node.type === 'CallExpression'
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
function getPreviousInChain(node) {
|
|
58
|
+
return node.type === 'CallExpression'
|
|
59
|
+
&& node.callee.type === 'MemberExpression'
|
|
60
|
+
&& node.callee.object.type === 'CallExpression'
|
|
61
|
+
&& node.callee.object.callee.type === 'MemberExpression'
|
|
62
|
+
&& node.callee.object.callee.property.type === 'Identifier'
|
|
63
|
+
&& node.callee.object.callee.property.name
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function getCallExpressionCypressCommand
|
|
67
|
-
return isRootCypress(node)
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
function getCallExpressionCypressCommand(node) {
|
|
67
|
+
return isRootCypress(node)
|
|
68
|
+
&& node.callee.property.type === 'Identifier'
|
|
69
|
+
&& node.callee.property.name
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function isCallingCyScreenshot
|
|
72
|
+
function isCallingCyScreenshot(node) {
|
|
73
73
|
return getCallExpressionCypressCommand(node) === 'screenshot'
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
function getPreviousCypressCommand
|
|
76
|
+
function getPreviousCypressCommand(node) {
|
|
77
77
|
const previousInChain = getPreviousInChain(node)
|
|
78
78
|
|
|
79
79
|
if (previousInChain) {
|
|
@@ -97,15 +97,15 @@ function getPreviousCypressCommand (node) {
|
|
|
97
97
|
|
|
98
98
|
const previousStatement = body[index - 1]
|
|
99
99
|
|
|
100
|
-
if (previousStatement.type !== 'ExpressionStatement'
|
|
101
|
-
|
|
100
|
+
if (previousStatement.type !== 'ExpressionStatement'
|
|
101
|
+
|| previousStatement.expression.type !== 'CallExpression') {
|
|
102
102
|
return null
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
return getCallExpressionCypressCommand(previousStatement.expression)
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function isPreviousAnAssertion
|
|
108
|
+
function isPreviousAnAssertion(node) {
|
|
109
109
|
const previousCypressCommand = getPreviousCypressCommand(node)
|
|
110
110
|
|
|
111
111
|
return assertionCommands.indexOf(previousCypressCommand) >= 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// safely get nested object property
|
|
4
|
-
function get
|
|
4
|
+
function get(obj, propertyString = '') {
|
|
5
5
|
const properties = propertyString.split('.')
|
|
6
6
|
|
|
7
7
|
for (let i = 0; i < properties.length; i++) {
|
|
@@ -29,9 +29,9 @@ module.exports = {
|
|
|
29
29
|
unexpected: 'Do not assign the return value of a Cypress command',
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
|
-
create
|
|
32
|
+
create(context) {
|
|
33
33
|
return {
|
|
34
|
-
VariableDeclaration
|
|
34
|
+
VariableDeclaration(node) {
|
|
35
35
|
if (node.declarations.some(isCypressCommandDeclaration)) {
|
|
36
36
|
context.report({ node, messageId: 'unexpected' })
|
|
37
37
|
}
|
|
@@ -47,7 +47,7 @@ const allowedCommands = {
|
|
|
47
47
|
stub: true,
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
function isCypressCommandDeclaration
|
|
50
|
+
function isCypressCommandDeclaration(declarator) {
|
|
51
51
|
let object = get(declarator, 'init.callee.object')
|
|
52
52
|
|
|
53
53
|
if (!object) return
|
|
@@ -15,31 +15,31 @@ module.exports = {
|
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
|
|
18
|
-
create
|
|
19
|
-
function isBeforeBlock
|
|
18
|
+
create(context) {
|
|
19
|
+
function isBeforeBlock(callExpressionNode) {
|
|
20
20
|
const { type, name } = callExpressionNode.callee
|
|
21
21
|
|
|
22
22
|
return type === 'Identifier'
|
|
23
|
-
|
|
23
|
+
&& (name === 'before' || name === 'beforeEach')
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function isBeforeAsync
|
|
26
|
+
function isBeforeAsync(node) {
|
|
27
27
|
return node.arguments
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
&& node.arguments.length >= 2
|
|
29
|
+
&& node.arguments[1].async === true
|
|
30
30
|
}
|
|
31
31
|
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
|
-
Identifier
|
|
34
|
+
Identifier(node) {
|
|
35
35
|
if (node.name === 'cy' || node.name === 'Cypress') {
|
|
36
36
|
const ancestors = sourceCode.getAncestors
|
|
37
37
|
? sourceCode.getAncestors(node)
|
|
38
38
|
: context.getAncestors()
|
|
39
39
|
const asyncTestBlocks = ancestors
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
.filter((n) => n.type === 'CallExpression')
|
|
41
|
+
.filter(isBeforeBlock)
|
|
42
|
+
.filter(isBeforeAsync)
|
|
43
43
|
|
|
44
44
|
if (asyncTestBlocks.length >= 1) {
|
|
45
45
|
asyncTestBlocks.forEach((node) => {
|
|
@@ -15,31 +15,31 @@ module.exports = {
|
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
|
|
18
|
-
create
|
|
19
|
-
function isTestBlock
|
|
18
|
+
create(context) {
|
|
19
|
+
function isTestBlock(callExpressionNode) {
|
|
20
20
|
const { type, name } = callExpressionNode.callee
|
|
21
21
|
|
|
22
22
|
return type === 'Identifier'
|
|
23
|
-
|
|
23
|
+
&& (name === 'it' || name === 'test')
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function isTestAsync
|
|
26
|
+
function isTestAsync(node) {
|
|
27
27
|
return node.arguments
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
&& node.arguments.length >= 2
|
|
29
|
+
&& node.arguments[1].async === true
|
|
30
30
|
}
|
|
31
31
|
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
|
-
Identifier
|
|
34
|
+
Identifier(node) {
|
|
35
35
|
if (node.name === 'cy' || node.name === 'Cypress') {
|
|
36
36
|
const ancestors = sourceCode.getAncestors
|
|
37
37
|
? sourceCode.getAncestors(node)
|
|
38
38
|
: context.getAncestors()
|
|
39
39
|
const asyncTestBlocks = ancestors
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
.filter((n) => n.type === 'CallExpression')
|
|
41
|
+
.filter(isTestBlock)
|
|
42
|
+
.filter(isTestAsync)
|
|
43
43
|
|
|
44
44
|
if (asyncTestBlocks.length >= 1) {
|
|
45
45
|
asyncTestBlocks.forEach((node) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// ------------------------------------------------------------------------------
|
|
4
4
|
// Rule Definition
|
|
5
|
-
|
|
5
|
+
// ------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
7
|
/** @type {import('eslint').Rule.RuleModule} */
|
|
8
8
|
module.exports = {
|
|
@@ -23,55 +23,55 @@ module.exports = {
|
|
|
23
23
|
create(context) {
|
|
24
24
|
const isRootCypress = (node) => {
|
|
25
25
|
if (
|
|
26
|
-
node.type !== 'CallExpression'
|
|
27
|
-
node.callee.type !== 'MemberExpression'
|
|
26
|
+
node.type !== 'CallExpression'
|
|
27
|
+
|| node.callee.type !== 'MemberExpression'
|
|
28
28
|
) {
|
|
29
|
-
return false
|
|
29
|
+
return false
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
if (
|
|
33
|
-
node.callee.object.type === 'Identifier'
|
|
34
|
-
node.callee.object.name === 'cy'
|
|
33
|
+
node.callee.object.type === 'Identifier'
|
|
34
|
+
&& node.callee.object.name === 'cy'
|
|
35
35
|
) {
|
|
36
|
-
return true
|
|
36
|
+
return true
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
return isRootCypress(node.callee.object)
|
|
40
|
-
}
|
|
39
|
+
return isRootCypress(node.callee.object)
|
|
40
|
+
}
|
|
41
41
|
|
|
42
42
|
const hasChainedGet = (node) => {
|
|
43
43
|
// Check if this node is a get() call
|
|
44
|
-
const isGetCall
|
|
45
|
-
node.callee
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const isGetCall
|
|
45
|
+
= node.callee
|
|
46
|
+
&& node.callee.type === 'MemberExpression'
|
|
47
|
+
&& node.callee.property
|
|
48
|
+
&& node.callee.property.type === 'Identifier'
|
|
49
|
+
&& node.callee.property.name === 'get'
|
|
50
50
|
|
|
51
51
|
if (!isGetCall) {
|
|
52
|
-
return false
|
|
52
|
+
return false
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const obj = node.callee.object
|
|
55
|
+
const obj = node.callee.object
|
|
56
56
|
|
|
57
57
|
if (obj.type === 'CallExpression') {
|
|
58
|
-
const objCallee = obj.callee
|
|
58
|
+
const objCallee = obj.callee
|
|
59
59
|
|
|
60
60
|
if (
|
|
61
|
-
objCallee
|
|
62
|
-
objCallee.type === 'MemberExpression'
|
|
63
|
-
objCallee.property
|
|
64
|
-
objCallee.property.type === 'Identifier'
|
|
65
|
-
objCallee.property.name === 'get'
|
|
61
|
+
objCallee
|
|
62
|
+
&& objCallee.type === 'MemberExpression'
|
|
63
|
+
&& objCallee.property
|
|
64
|
+
&& objCallee.property.type === 'Identifier'
|
|
65
|
+
&& objCallee.property.name === 'get'
|
|
66
66
|
) {
|
|
67
|
-
return true
|
|
67
|
+
return true
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
return hasChainedGet(obj)
|
|
70
|
+
return hasChainedGet(obj)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
return false
|
|
74
|
-
}
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
75
|
|
|
76
76
|
return {
|
|
77
77
|
CallExpression(node) {
|
|
@@ -79,9 +79,9 @@ module.exports = {
|
|
|
79
79
|
context.report({
|
|
80
80
|
node,
|
|
81
81
|
messageId: 'unexpected',
|
|
82
|
-
})
|
|
82
|
+
})
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
|
-
}
|
|
85
|
+
}
|
|
86
86
|
},
|
|
87
|
-
}
|
|
87
|
+
}
|
package/lib/rules/no-debug.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// ------------------------------------------------------------------------------
|
|
4
4
|
// Rule Definition
|
|
5
|
-
|
|
5
|
+
// ------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
meta: {
|
|
@@ -20,37 +20,36 @@ module.exports = {
|
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
create
|
|
24
|
-
|
|
23
|
+
create(context) {
|
|
25
24
|
// variables should be defined here
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
// ----------------------------------------------------------------------
|
|
28
27
|
// Helpers
|
|
29
|
-
|
|
30
|
-
function isCallingDebug
|
|
31
|
-
return node.callee
|
|
32
|
-
node.callee.property
|
|
33
|
-
node.callee.property.type === 'Identifier'
|
|
34
|
-
node.callee.property.name === 'debug'
|
|
28
|
+
// ----------------------------------------------------------------------
|
|
29
|
+
function isCallingDebug(node) {
|
|
30
|
+
return node.callee
|
|
31
|
+
&& node.callee.property
|
|
32
|
+
&& node.callee.property.type === 'Identifier'
|
|
33
|
+
&& node.callee.property.name === 'debug'
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
function isCypressCall
|
|
36
|
+
function isCypressCall(node) {
|
|
38
37
|
if (!node.callee || node.callee.type !== 'MemberExpression') {
|
|
39
|
-
return false
|
|
38
|
+
return false
|
|
40
39
|
}
|
|
41
40
|
if (node.callee.object.type === 'Identifier' && node.callee.object.name === 'cy') {
|
|
42
|
-
return true
|
|
41
|
+
return true
|
|
43
42
|
}
|
|
44
|
-
return isCypressCall(node.callee.object)
|
|
43
|
+
return isCypressCall(node.callee.object)
|
|
45
44
|
}
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
|
|
46
|
+
// ----------------------------------------------------------------------
|
|
48
47
|
// Public
|
|
49
|
-
|
|
48
|
+
// ----------------------------------------------------------------------
|
|
50
49
|
|
|
51
50
|
return {
|
|
52
51
|
|
|
53
|
-
CallExpression
|
|
52
|
+
CallExpression(node) {
|
|
54
53
|
if (isCypressCall(node) && isCallingDebug(node)) {
|
|
55
54
|
context.report({ node, messageId: 'unexpected' })
|
|
56
55
|
}
|
package/lib/rules/no-force.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// ------------------------------------------------------------------------------
|
|
4
4
|
// Rule Definition
|
|
5
|
-
|
|
5
|
+
// ------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
meta: {
|
|
@@ -20,39 +20,36 @@ module.exports = {
|
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
create
|
|
24
|
-
|
|
23
|
+
create(context) {
|
|
25
24
|
// variables should be defined here
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
// ----------------------------------------------------------------------
|
|
28
27
|
// Helpers
|
|
29
|
-
|
|
30
|
-
function isCallingClickOrType
|
|
28
|
+
// ----------------------------------------------------------------------
|
|
29
|
+
function isCallingClickOrType(node) {
|
|
31
30
|
const allowedMethods = ['click', 'dblclick', 'type', 'trigger', 'check', 'rightclick', 'focus', 'select']
|
|
32
31
|
|
|
33
|
-
return node.property && node.property.type === 'Identifier'
|
|
34
|
-
|
|
32
|
+
return node.property && node.property.type === 'Identifier'
|
|
33
|
+
&& allowedMethods.includes(node.property.name)
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
function isCypressCall
|
|
38
|
-
return node.callee.type === 'MemberExpression'
|
|
39
|
-
node.callee.object.type === 'Identifier'
|
|
40
|
-
node.callee.object.name === 'cy'
|
|
36
|
+
function isCypressCall(node) {
|
|
37
|
+
return node.callee.type === 'MemberExpression'
|
|
38
|
+
&& node.callee.object.type === 'Identifier'
|
|
39
|
+
&& node.callee.object.name === 'cy'
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
function hasOptionForce
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
42
|
+
function hasOptionForce(node) {
|
|
43
|
+
return node.arguments && node.arguments.length
|
|
44
|
+
&& node.arguments.some((arg) => {
|
|
45
|
+
return arg.type === 'ObjectExpression' && arg.properties.some((propNode) => propNode.key && propNode.key.name === 'force')
|
|
46
|
+
})
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
function deepCheck
|
|
49
|
+
function deepCheck(node, checkFunc) {
|
|
52
50
|
let currentNode = node
|
|
53
51
|
|
|
54
52
|
while (currentNode.parent) {
|
|
55
|
-
|
|
56
53
|
if (checkFunc(currentNode.parent)) {
|
|
57
54
|
return true
|
|
58
55
|
}
|
|
@@ -63,13 +60,13 @@ module.exports = {
|
|
|
63
60
|
return false
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
// ----------------------------------------------------------------------
|
|
67
64
|
// Public
|
|
68
|
-
|
|
65
|
+
// ----------------------------------------------------------------------
|
|
69
66
|
|
|
70
67
|
return {
|
|
71
68
|
|
|
72
|
-
CallExpression
|
|
69
|
+
CallExpression(node) {
|
|
73
70
|
if (isCypressCall(node) && deepCheck(node, isCallingClickOrType) && deepCheck(node, hasOptionForce)) {
|
|
74
71
|
context.report({ node, messageId: 'unexpected' })
|
|
75
72
|
}
|
package/lib/rules/no-pause.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// ------------------------------------------------------------------------------
|
|
4
4
|
// Rule Definition
|
|
5
|
-
|
|
5
|
+
// ------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
meta: {
|
|
@@ -20,37 +20,36 @@ module.exports = {
|
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
create
|
|
24
|
-
|
|
23
|
+
create(context) {
|
|
25
24
|
// variables should be defined here
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
// ----------------------------------------------------------------------
|
|
28
27
|
// Helpers
|
|
29
|
-
|
|
30
|
-
function isCallingPause
|
|
31
|
-
return node.callee
|
|
32
|
-
node.callee.property
|
|
33
|
-
node.callee.property.type === 'Identifier'
|
|
34
|
-
node.callee.property.name === 'pause'
|
|
28
|
+
// ----------------------------------------------------------------------
|
|
29
|
+
function isCallingPause(node) {
|
|
30
|
+
return node.callee
|
|
31
|
+
&& node.callee.property
|
|
32
|
+
&& node.callee.property.type === 'Identifier'
|
|
33
|
+
&& node.callee.property.name === 'pause'
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
function isCypressCall
|
|
36
|
+
function isCypressCall(node) {
|
|
38
37
|
if (!node.callee || node.callee.type !== 'MemberExpression') {
|
|
39
|
-
return false
|
|
38
|
+
return false
|
|
40
39
|
}
|
|
41
40
|
if (node.callee.object.type === 'Identifier' && node.callee.object.name === 'cy') {
|
|
42
|
-
return true
|
|
41
|
+
return true
|
|
43
42
|
}
|
|
44
|
-
return isCypressCall(node.callee.object)
|
|
43
|
+
return isCypressCall(node.callee.object)
|
|
45
44
|
}
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
|
|
46
|
+
// ----------------------------------------------------------------------
|
|
48
47
|
// Public
|
|
49
|
-
|
|
48
|
+
// ----------------------------------------------------------------------
|
|
50
49
|
|
|
51
50
|
return {
|
|
52
51
|
|
|
53
|
-
CallExpression
|
|
52
|
+
CallExpression(node) {
|
|
54
53
|
if (isCypressCall(node) && isCallingPause(node)) {
|
|
55
54
|
context.report({ node, messageId: 'unexpected' })
|
|
56
55
|
}
|
|
@@ -14,11 +14,11 @@ module.exports = {
|
|
|
14
14
|
unexpected: 'Do not wait for arbitrary time periods',
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
|
-
create
|
|
17
|
+
create(context) {
|
|
18
18
|
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
19
19
|
|
|
20
20
|
return {
|
|
21
|
-
CallExpression
|
|
21
|
+
CallExpression(node) {
|
|
22
22
|
if (isCallingCyWait(node)) {
|
|
23
23
|
const scope = sourceCode.getScope
|
|
24
24
|
? sourceCode.getScope(node)
|
|
@@ -33,7 +33,7 @@ module.exports = {
|
|
|
33
33
|
},
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function nodeIsCalledByCy
|
|
36
|
+
function nodeIsCalledByCy(node) {
|
|
37
37
|
if (node.type === 'Identifier' && node.name === 'cy') return true
|
|
38
38
|
|
|
39
39
|
if (typeof node.callee === 'undefined' || typeof node.callee.object === 'undefined') {
|
|
@@ -43,20 +43,20 @@ function nodeIsCalledByCy (node) {
|
|
|
43
43
|
return nodeIsCalledByCy(node.callee.object)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
function isCallingCyWait
|
|
47
|
-
return node.callee.type === 'MemberExpression'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
function isCallingCyWait(node) {
|
|
47
|
+
return node.callee.type === 'MemberExpression'
|
|
48
|
+
&& nodeIsCalledByCy(node)
|
|
49
|
+
&& node.callee.property.type === 'Identifier'
|
|
50
|
+
&& node.callee.property.name === 'wait'
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function isNumberArgument
|
|
54
|
-
return node.arguments.length > 0
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
function isNumberArgument(node) {
|
|
54
|
+
return node.arguments.length > 0
|
|
55
|
+
&& node.arguments[0].type === 'Literal'
|
|
56
|
+
&& typeof (node.arguments[0].value) === 'number'
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function isIdentifierNumberConstArgument
|
|
59
|
+
function isIdentifierNumberConstArgument(node, scope) {
|
|
60
60
|
if (node.arguments.length === 0) return false
|
|
61
61
|
|
|
62
62
|
if (node.arguments[0].type !== 'Identifier') return false
|