eslint-plugin-cypress 5.1.0 → 5.1.1
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 +25 -23
- package/README.md +22 -17
- package/docs/rules/assertion-before-screenshot.md +6 -5
- package/docs/rules/no-assigning-return-values.md +1 -0
- package/docs/rules/no-async-before.md +7 -8
- package/docs/rules/no-async-tests.md +8 -9
- package/docs/rules/no-chained-get.md +2 -2
- package/docs/rules/no-debug.md +3 -2
- package/docs/rules/no-force.md +14 -13
- package/docs/rules/no-pause.md +3 -2
- package/docs/rules/no-unnecessary-waiting.md +1 -0
- package/docs/rules/no-xpath.md +2 -2
- package/docs/rules/require-data-selectors.md +14 -4
- package/docs/rules/unsafe-to-chain-command.md +2 -1
- package/lib/rules/require-data-selectors.js +39 -8
- package/lib/rules/unsafe-to-chain-command.js +1 -1
- package/package.json +4 -1
package/CONTRIBUTING.md
CHANGED
|
@@ -4,45 +4,47 @@ Thanks for taking the time to contribute! :smile:
|
|
|
4
4
|
|
|
5
5
|
## Preparation
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
- Fork and clone this repository
|
|
8
|
+
- Branch from the default `master` branch using a descriptive new branch name
|
|
9
|
+
- Install dependencies with `npm ci`
|
|
10
10
|
|
|
11
11
|
## Rule references
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- Refer to the [ESLint documentation](https://eslint.org/docs/latest/) and the [Custom Rules](https://eslint.org/docs/latest/extend/custom-rules) page
|
|
14
14
|
|
|
15
15
|
## New rule
|
|
16
16
|
|
|
17
17
|
To add a new rule:
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
- Follow the instructions in the ESLint [generator-eslint](https://www.npmjs.com/package/generator-eslint) documentation to install [Yeoman](https://www.npmjs.com/package/yo) and the generator
|
|
20
|
+
- Run the new rule generator `yo eslint:rule` and answer the questions
|
|
21
21
|
- select "ESLint Plugin"
|
|
22
22
|
- for "Type a short description of this rule" provide text which starts with one of "enforce", "require" or "disallow" (all lower case)
|
|
23
|
-
|
|
23
|
+
- Yeoman creates three boilerplate files:
|
|
24
24
|
- `docs/rules/<rule-id>.md`
|
|
25
25
|
- `lib/rules/<rule-id>.js`
|
|
26
26
|
- `test/rules/<rule-id>.js`
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
- Run `npm run lint-fix`
|
|
28
|
+
- Address the linting errors by editing `lib/rules/<rule-id>.js`
|
|
29
29
|
- Add a `meta.messages` property (see [MessageIds](https://eslint.org/docs/latest/extend/custom-rules#messageids))
|
|
30
30
|
- Select the appropriate `meta.type` property using `problem`, `suggestion`, or `layout`
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
- Complete the new rule by adding content to the three files previously created
|
|
32
|
+
- Run `eslint-doc-generator` to generate automated documentation sections (see [Document generation](#document-generation) below)
|
|
33
|
+
- Review documentation changes
|
|
34
|
+
- Run `npm run lint`
|
|
35
|
+
- Run `npm run format`
|
|
36
|
+
- Run `npm test` to run [Vitest](https://vitest.dev/)
|
|
37
|
+
- Make sure all tests are passing
|
|
38
|
+
- Add the rule to [flat.js](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/lib/flat.js)
|
|
39
|
+
- 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))
|
|
40
|
+
- Create a PR from your branch
|
|
40
41
|
|
|
41
42
|
## Document generation
|
|
42
43
|
|
|
43
44
|
This plugin uses the ESLint [eslint-doc-generator](https://www.npmjs.com/package/eslint-doc-generator) to generate consistent documentation.
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
- Install with `npm install eslint-doc-generator -g`
|
|
47
|
+
- Run `eslint-doc-generator` in the root directory of the plugin
|
|
46
48
|
|
|
47
49
|
## Merging pull requests
|
|
48
50
|
|
|
@@ -65,7 +67,7 @@ This information is for Cypress.io Members or Collaborators who merge pull reque
|
|
|
65
67
|
```
|
|
66
68
|
|
|
67
69
|
1. New versions of this module will be released automatically by the CI pipeline when any PR with a triggering commit message is merged to the `master` branch: see the `release` job of [circle.yml](circle.yml).
|
|
68
|
-
This will create a new [GitHub release](https://github.com/cypress-io/eslint-plugin-cypress/releases) and publish it to [eslint-plugin-cypress](https://www.npmjs.com/package/eslint-plugin-cypress) on the [npm registry](https://docs.npmjs.com/about-the-public-npm-registry).
|
|
70
|
+
This will create a new [GitHub release](https://github.com/cypress-io/eslint-plugin-cypress/releases) and publish it to [eslint-plugin-cypress](https://www.npmjs.com/package/eslint-plugin-cypress) on the [npm registry](https://docs.npmjs.com/about-the-public-npm-registry).
|
|
69
71
|
1. The module's CI is configured to use the [default Angular release rules](https://github.com/semantic-release/commit-analyzer/blob/master/lib/default-release-rules.js).
|
|
70
|
-
This means that only `feat:`, `fix:` and `perf:` trigger a new release.
|
|
71
|
-
Other Angular commit types listed in the [Angular commit message guidelines](https://github.com/angular/angular/blob/main/contributing-docs/commit-message-guidelines.md) can be used for documentation purposes, however they are ignored by the currently configured release process.
|
|
72
|
+
This means that only `feat:`, `fix:` and `perf:` trigger a new release.
|
|
73
|
+
Other Angular commit types listed in the [Angular commit message guidelines](https://github.com/angular/angular/blob/main/contributing-docs/commit-message-guidelines.md) can be used for documentation purposes, however they are ignored by the currently configured release process.
|
package/README.md
CHANGED
|
@@ -11,7 +11,9 @@ Prerequisites: [ESLint](https://www.npmjs.com/package/eslint) `v9`. Lower versio
|
|
|
11
11
|
```sh
|
|
12
12
|
npm install eslint eslint-plugin-cypress --save-dev
|
|
13
13
|
```
|
|
14
|
+
|
|
14
15
|
or
|
|
16
|
+
|
|
15
17
|
```sh
|
|
16
18
|
yarn add eslint eslint-plugin-cypress --dev
|
|
17
19
|
```
|
|
@@ -36,15 +38,16 @@ import pluginCypress from 'eslint-plugin-cypress/flat' # deprecated
|
|
|
36
38
|
|
|
37
39
|
There are two specific configurations available:
|
|
38
40
|
|
|
39
|
-
| Configuration | Content
|
|
40
|
-
| --------------------- |
|
|
41
|
+
| Configuration | Content |
|
|
42
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
41
43
|
| `configs.globals` | defines globals `cy`, `Cypress`, `expect`, `assert` and `chai` used in Cypress test specs as well as `globals.browser` and `globals.mocha` from [globals](https://www.npmjs.com/package/globals). There are no default rules enabled in this configuration. |
|
|
42
|
-
| `configs.recommended` | enables [recommended Rules](#rules). It includes also `configs.global` (see above).
|
|
44
|
+
| `configs.recommended` | enables [recommended Rules](#rules). It includes also `configs.global` (see above). |
|
|
43
45
|
|
|
44
46
|
## Rules
|
|
45
47
|
|
|
46
48
|
These rules enforce some of the [best practices recommended for using Cypress](https://on.cypress.io/best-practices).
|
|
47
49
|
|
|
50
|
+
<!-- prettier-ignore-start -->
|
|
48
51
|
<!-- begin auto-generated rules list -->
|
|
49
52
|
|
|
50
53
|
💼 Configurations enabled in.\
|
|
@@ -66,6 +69,7 @@ These rules enforce some of the [best practices recommended for using Cypress](h
|
|
|
66
69
|
| [unsafe-to-chain-command](docs/rules/unsafe-to-chain-command.md) | disallow actions within chains | ✅ |
|
|
67
70
|
|
|
68
71
|
<!-- end auto-generated rules list -->
|
|
72
|
+
<!-- prettier-ignore-end -->
|
|
69
73
|
|
|
70
74
|
## Usage examples
|
|
71
75
|
|
|
@@ -74,6 +78,7 @@ In the following sections, different examples of possible configuration file con
|
|
|
74
78
|
### Cypress
|
|
75
79
|
|
|
76
80
|
All rules are available by importing from `eslint-plugin-cypress` and can be individually activated.
|
|
81
|
+
|
|
77
82
|
- [cypress/unsafe-to-chain-command](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/unsafe-to-chain-command.md) is activated and set to `error`
|
|
78
83
|
|
|
79
84
|
```js
|
|
@@ -81,18 +86,19 @@ import pluginCypress from 'eslint-plugin-cypress'
|
|
|
81
86
|
export default [
|
|
82
87
|
{
|
|
83
88
|
plugins: {
|
|
84
|
-
cypress: pluginCypress
|
|
89
|
+
cypress: pluginCypress,
|
|
85
90
|
},
|
|
86
91
|
rules: {
|
|
87
|
-
'cypress/unsafe-to-chain-command': 'error'
|
|
88
|
-
}
|
|
89
|
-
}
|
|
92
|
+
'cypress/unsafe-to-chain-command': 'error',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
90
95
|
]
|
|
91
96
|
```
|
|
92
97
|
|
|
93
98
|
### Cypress recommended
|
|
94
99
|
|
|
95
100
|
The `eslint-plugin-cypress` [recommended rules](#rules) `configs.recommended` are activated, except for
|
|
101
|
+
|
|
96
102
|
- [cypress/no-unnecessary-waiting](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/no-unnecessary-waiting.md) which is set to `off`
|
|
97
103
|
|
|
98
104
|
```js
|
|
@@ -101,9 +107,9 @@ export default [
|
|
|
101
107
|
pluginCypress.configs.recommended,
|
|
102
108
|
{
|
|
103
109
|
rules: {
|
|
104
|
-
'cypress/no-unnecessary-waiting': 'off'
|
|
105
|
-
}
|
|
106
|
-
}
|
|
110
|
+
'cypress/no-unnecessary-waiting': 'off',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
107
113
|
]
|
|
108
114
|
```
|
|
109
115
|
|
|
@@ -113,9 +119,7 @@ The `configs.globals` are activated.
|
|
|
113
119
|
|
|
114
120
|
```js
|
|
115
121
|
import pluginCypress from 'eslint-plugin-cypress'
|
|
116
|
-
export default [
|
|
117
|
-
pluginCypress.configs.globals
|
|
118
|
-
]
|
|
122
|
+
export default [pluginCypress.configs.globals]
|
|
119
123
|
```
|
|
120
124
|
|
|
121
125
|
## Disable rules
|
|
@@ -174,6 +178,7 @@ During test spec development, [Mocha exclusive tests](https://mochajs.org/#exclu
|
|
|
174
178
|
[eslint-plugin-mocha@^11](https://www.npmjs.com/package/eslint-plugin-mocha) is added to the example [Cypress recommended](#cypress-recommended). This version of the plugin supports only flat file configurations with the option `configs.recommended`.
|
|
175
179
|
|
|
176
180
|
The settings for individual `mocha` rules from the `configs.recommended` option are changed.
|
|
181
|
+
|
|
177
182
|
- [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) and [mocha/no-pending-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-pending-tests.md) are set to `error` instead of `warn`
|
|
178
183
|
- [mocha/no-mocha-arrows](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-mocha-arrows.md) is set to `off` instead of `error`
|
|
179
184
|
|
|
@@ -192,9 +197,9 @@ export default [
|
|
|
192
197
|
'mocha/no-exclusive-tests': 'error',
|
|
193
198
|
'mocha/no-pending-tests': 'error',
|
|
194
199
|
'mocha/no-mocha-arrows': 'off',
|
|
195
|
-
'cypress/no-unnecessary-waiting': 'off'
|
|
196
|
-
}
|
|
197
|
-
}
|
|
200
|
+
'cypress/no-unnecessary-waiting': 'off',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
198
203
|
]
|
|
199
204
|
```
|
|
200
205
|
|
|
@@ -220,7 +225,7 @@ export default [
|
|
|
220
225
|
rules: {
|
|
221
226
|
'cypress/no-unnecessary-waiting': 'off',
|
|
222
227
|
},
|
|
223
|
-
}
|
|
228
|
+
},
|
|
224
229
|
]
|
|
225
230
|
```
|
|
226
231
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Require screenshots to be preceded by an assertion (`cypress/assertion-before-screenshot`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
If you take screenshots without assertions then you may get different screenshots depending on timing.
|
|
5
6
|
|
|
6
7
|
For example, if clicking a button makes some network calls and upon success, renders something, then the screenshot may sometimes have the new render and sometimes not.
|
|
@@ -12,14 +13,14 @@ This rule checks there is an assertion making sure your application state is cor
|
|
|
12
13
|
Examples of **incorrect** code for this rule:
|
|
13
14
|
|
|
14
15
|
```js
|
|
15
|
-
cy.visit('myUrl')
|
|
16
|
-
cy.screenshot()
|
|
16
|
+
cy.visit('myUrl')
|
|
17
|
+
cy.screenshot()
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
Examples of **correct** code for this rule:
|
|
20
21
|
|
|
21
22
|
```js
|
|
22
|
-
cy.visit('myUrl')
|
|
23
|
-
cy.get('[data-test-id="my-element"]').should('be.visible')
|
|
24
|
-
cy.screenshot()
|
|
23
|
+
cy.visit('myUrl')
|
|
24
|
+
cy.get('[data-test-id="my-element"]').should('be.visible')
|
|
25
|
+
cy.screenshot()
|
|
25
26
|
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Disallow using `async`/`await` in Cypress `before` methods (`cypress/no-async-before`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
Cypress commands that return a promise may cause side effects in `before`/`beforeEach` hooks, possibly causing unexpected behavior.
|
|
5
6
|
|
|
6
7
|
## Rule Details
|
|
@@ -11,7 +12,7 @@ Examples of **incorrect** code for this rule:
|
|
|
11
12
|
|
|
12
13
|
```js
|
|
13
14
|
describe('my feature', () => {
|
|
14
|
-
before('my test case', async ()
|
|
15
|
+
before('my test case', async () => {
|
|
15
16
|
await cy.get('.myClass')
|
|
16
17
|
// other operations
|
|
17
18
|
})
|
|
@@ -20,10 +21,8 @@ describe('my feature', () => {
|
|
|
20
21
|
|
|
21
22
|
```js
|
|
22
23
|
describe('my feature', () => {
|
|
23
|
-
before('my test case', async ()
|
|
24
|
-
cy
|
|
25
|
-
.get('.myClass')
|
|
26
|
-
.click()
|
|
24
|
+
before('my test case', async () => {
|
|
25
|
+
cy.get('.myClass').click()
|
|
27
26
|
|
|
28
27
|
await someAsyncFunction()
|
|
29
28
|
})
|
|
@@ -34,7 +33,7 @@ Examples of **correct** code for this rule:
|
|
|
34
33
|
|
|
35
34
|
```js
|
|
36
35
|
describe('my feature', () => {
|
|
37
|
-
before('my test case', ()
|
|
36
|
+
before('my test case', () => {
|
|
38
37
|
cy.get('.myClass')
|
|
39
38
|
// other operations
|
|
40
39
|
})
|
|
@@ -47,5 +46,5 @@ If there are genuine use-cases for using `async/await` in your `before` hooks th
|
|
|
47
46
|
|
|
48
47
|
## Further Reading
|
|
49
48
|
|
|
50
|
-
- [Mixing Async and Sync code](https://on.cypress.io/
|
|
51
|
-
- [Commands Are Asynchronous](https://on.cypress.io/
|
|
49
|
+
- [Mixing Async and Sync code](https://on.cypress.io/app/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code)
|
|
50
|
+
- [Commands Are Asynchronous](https://on.cypress.io/app/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
💼 This rule is enabled in the ✅ `recommended` config.
|
|
4
4
|
|
|
5
5
|
<!-- end auto-generated rule header -->
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
Cypress tests [that return a promise will error](https://docs.cypress.io/app/references/error-messages.html#Cypress-detected-that-you-returned-a-promise-from-a-command-while-also-invoking-one-or-more-cy-commands-in-that-promise) and cannot run successfully.
|
|
7
8
|
An `async` function returns a promise under the hood, so a test using an `async` function will also error.
|
|
8
9
|
|
|
9
10
|
## Rule Details
|
|
@@ -14,7 +15,7 @@ Examples of **incorrect** code for this rule:
|
|
|
14
15
|
|
|
15
16
|
```js
|
|
16
17
|
describe('my feature', () => {
|
|
17
|
-
it('my test case', async ()
|
|
18
|
+
it('my test case', async () => {
|
|
18
19
|
await cy.get('.myClass')
|
|
19
20
|
// other operations
|
|
20
21
|
})
|
|
@@ -23,10 +24,8 @@ describe('my feature', () => {
|
|
|
23
24
|
|
|
24
25
|
```js
|
|
25
26
|
describe('my feature', () => {
|
|
26
|
-
it('my test case', async ()
|
|
27
|
-
cy
|
|
28
|
-
.get('.myClass')
|
|
29
|
-
.click()
|
|
27
|
+
it('my test case', async () => {
|
|
28
|
+
cy.get('.myClass').click()
|
|
30
29
|
|
|
31
30
|
await someAsyncFunction()
|
|
32
31
|
})
|
|
@@ -37,7 +36,7 @@ Examples of **correct** code for this rule:
|
|
|
37
36
|
|
|
38
37
|
```js
|
|
39
38
|
describe('my feature', () => {
|
|
40
|
-
it('my test case', ()
|
|
39
|
+
it('my test case', () => {
|
|
41
40
|
cy.get('.myClass')
|
|
42
41
|
// other operations
|
|
43
42
|
})
|
|
@@ -50,5 +49,5 @@ If there are genuine use-cases for using `async/await` in your test cases then y
|
|
|
50
49
|
|
|
51
50
|
## Further Reading
|
|
52
51
|
|
|
53
|
-
- [Mixing Async and Sync code](https://on.cypress.io/
|
|
54
|
-
- [Commands Are Asynchronous](https://on.cypress.io/
|
|
52
|
+
- [Mixing Async and Sync code](https://on.cypress.io/app/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code)
|
|
53
|
+
- [Commands Are Asynchronous](https://on.cypress.io/app/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Disallow chain of `cy.get()` calls (`cypress/no-chained-get`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
This rule disallows the usage of chained `.get()` calls as `cy.get()` always starts its search from the cy.root element.
|
|
5
6
|
|
|
6
7
|
## Rule Details
|
|
@@ -14,6 +15,5 @@ cy.get('parent').get('child')
|
|
|
14
15
|
Examples of **correct** code for this rule:
|
|
15
16
|
|
|
16
17
|
```js
|
|
17
|
-
cy.get('parent')
|
|
18
|
-
.find('child')
|
|
18
|
+
cy.get('parent').find('child')
|
|
19
19
|
```
|
package/docs/rules/no-debug.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Disallow using `cy.debug()` calls (`cypress/no-debug`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
It is recommended to remove any [cy.debug](https://on.cypress.io/debug) commands before committing specs to avoid other developers getting unexpected results.
|
|
5
6
|
|
|
6
7
|
## Rule Details
|
|
@@ -8,8 +9,8 @@ It is recommended to remove any [cy.debug](https://on.cypress.io/debug) commands
|
|
|
8
9
|
Examples of **incorrect** code for this rule:
|
|
9
10
|
|
|
10
11
|
```js
|
|
11
|
-
cy.debug()
|
|
12
|
-
cy.get('selector').debug()
|
|
12
|
+
cy.debug()
|
|
13
|
+
cy.get('selector').debug()
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
Examples of **correct** code for this rule:
|
package/docs/rules/no-force.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Disallow using `force: true` with action commands (`cypress/no-force`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
Using `force: true` on inputs appears to be confusing rather than helpful.
|
|
5
6
|
It usually silences the actual problem instead of providing a way to overcome it.
|
|
6
|
-
See [Cypress Core Concepts](https://docs.cypress.io/
|
|
7
|
+
See [Cypress Core Concepts](https://docs.cypress.io/app/core-concepts/interacting-with-elements.html#Forcing).
|
|
7
8
|
|
|
8
9
|
If enabling this rule, it's recommended to set the severity to `warn`.
|
|
9
10
|
|
|
@@ -18,26 +19,26 @@ and [`.trigger()`](https://on.cypress.io/trigger).
|
|
|
18
19
|
Examples of **incorrect** code for this rule:
|
|
19
20
|
|
|
20
21
|
```js
|
|
21
|
-
cy.get('button').click({force: true})
|
|
22
|
-
cy.get('button').dblclick({force: true})
|
|
23
|
-
cy.get('input').type('somth', {force: true})
|
|
24
|
-
cy.get('div').find('.foo').find('.bar').trigger('change', {force: true})
|
|
25
|
-
cy.get('input').trigger('click', {force: true})
|
|
26
|
-
cy.get('input').rightclick({force: true})
|
|
27
|
-
cy.get('input').check({force: true})
|
|
28
|
-
cy.get('input').select({force: true})
|
|
29
|
-
cy.get('input').focus({force: true})
|
|
22
|
+
cy.get('button').click({ force: true })
|
|
23
|
+
cy.get('button').dblclick({ force: true })
|
|
24
|
+
cy.get('input').type('somth', { force: true })
|
|
25
|
+
cy.get('div').find('.foo').find('.bar').trigger('change', { force: true })
|
|
26
|
+
cy.get('input').trigger('click', { force: true })
|
|
27
|
+
cy.get('input').rightclick({ force: true })
|
|
28
|
+
cy.get('input').check({ force: true })
|
|
29
|
+
cy.get('input').select({ force: true })
|
|
30
|
+
cy.get('input').focus({ force: true })
|
|
30
31
|
```
|
|
31
32
|
|
|
32
33
|
Examples of **correct** code for this rule:
|
|
33
34
|
|
|
34
35
|
```js
|
|
35
36
|
cy.get('button').click()
|
|
36
|
-
cy.get('button').click({multiple: true})
|
|
37
|
+
cy.get('button').click({ multiple: true })
|
|
37
38
|
cy.get('button').dblclick()
|
|
38
39
|
cy.get('input').type('somth')
|
|
39
|
-
cy.get('input').trigger('click', {anyoption: true})
|
|
40
|
-
cy.get('input').rightclick({anyoption: true})
|
|
40
|
+
cy.get('input').trigger('click', { anyoption: true })
|
|
41
|
+
cy.get('input').rightclick({ anyoption: true })
|
|
41
42
|
cy.get('input').check()
|
|
42
43
|
cy.get('input').select()
|
|
43
44
|
cy.get('input').focus()
|
package/docs/rules/no-pause.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Disallow using `cy.pause()` calls (`cypress/no-pause`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
It is recommended to remove any [cy.pause](https://on.cypress.io/pause) commands before committing specs to avoid other developers getting unexpected results.
|
|
5
6
|
|
|
6
7
|
## Rule Details
|
|
@@ -8,8 +9,8 @@ It is recommended to remove any [cy.pause](https://on.cypress.io/pause) commands
|
|
|
8
9
|
Examples of **incorrect** code for this rule:
|
|
9
10
|
|
|
10
11
|
```js
|
|
11
|
-
cy.pause()
|
|
12
|
-
cy.get('selector').pause()
|
|
12
|
+
cy.pause()
|
|
13
|
+
cy.get('selector').pause()
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
Examples of **correct** code for this rule:
|
package/docs/rules/no-xpath.md
CHANGED
|
@@ -15,11 +15,11 @@ cy.xpath('//div[@class=\"container\"]').click()
|
|
|
15
15
|
Examples of **correct** code for this rule:
|
|
16
16
|
|
|
17
17
|
```js
|
|
18
|
-
cy.get('[data-cy="container"]').click()
|
|
18
|
+
cy.get('[data-cy="container"]').click()
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Further Reading
|
|
22
22
|
|
|
23
23
|
Both `@cypress/xpath` and `cypress-xpath` are deprecated.
|
|
24
24
|
|
|
25
|
-
See [the Cypress Best Practices guide](https://docs.cypress.io/
|
|
25
|
+
See [the Cypress Best Practices guide](https://docs.cypress.io/app/core-concepts/best-practices.html#Selecting-Elements).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Require `data-*` attribute selectors (`cypress/require-data-selectors`)
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
4
5
|
Require `cy.get` to use only selectors that target `data-*` attributes.
|
|
5
6
|
|
|
6
7
|
> Note: If you use this rule, consider only using the `warn` error level, since using `data-*` attribute selectors may not always be possible.
|
|
@@ -10,11 +11,14 @@ Require `cy.get` to use only selectors that target `data-*` attributes.
|
|
|
10
11
|
Examples of **incorrect** code for this rule:
|
|
11
12
|
|
|
12
13
|
```js
|
|
13
|
-
cy.get(
|
|
14
|
+
cy.get('.a')
|
|
14
15
|
cy.get('[daedta-cy=submit]').click()
|
|
15
16
|
cy.get('[d-cy=submit]')
|
|
16
|
-
cy.get(
|
|
17
|
-
cy.get(
|
|
17
|
+
cy.get('.btn-large').click()
|
|
18
|
+
cy.get('.btn-.large').click()
|
|
19
|
+
|
|
20
|
+
const CLASS_SELECTOR = ".my-class";
|
|
21
|
+
cy.get(CLASS_SELECTOR)
|
|
18
22
|
```
|
|
19
23
|
|
|
20
24
|
Examples of **correct** code for this rule:
|
|
@@ -22,8 +26,14 @@ Examples of **correct** code for this rule:
|
|
|
22
26
|
```js
|
|
23
27
|
cy.get('[data-cy=submit]').click()
|
|
24
28
|
cy.get('[data-QA=submit]')
|
|
29
|
+
cy.get(`[data-QA=submit]`)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
const ASSESSMENT_SUBMIT = "[data-cy=assessment-submit]"
|
|
34
|
+
cy.get(ASSESSMENT_SUBMIT).click()
|
|
25
35
|
```
|
|
26
36
|
|
|
27
37
|
## Further Reading
|
|
28
38
|
|
|
29
|
-
See [the Cypress Best Practices guide](https://docs.cypress.io/
|
|
39
|
+
See [the Cypress Best Practices guide](https://docs.cypress.io/app/core-concepts/best-practices.html#Selecting-Elements).
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
💼 This rule is enabled in the ✅ `recommended` config.
|
|
4
4
|
|
|
5
5
|
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
6
7
|
### Options
|
|
7
8
|
|
|
8
9
|
<!-- begin auto-generated rule options list -->
|
|
@@ -15,4 +16,4 @@
|
|
|
15
16
|
|
|
16
17
|
## Further Reading
|
|
17
18
|
|
|
18
|
-
See [retry-ability guide](https://docs.cypress.io/
|
|
19
|
+
See [retry-ability guide](https://docs.cypress.io/app/core-concepts/retry-ability#Actions-should-be-at-the-end-of-chains-not-the-middle).
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
3
2
|
module.exports = {
|
|
4
3
|
meta: {
|
|
5
4
|
type: 'suggestion',
|
|
@@ -16,9 +15,29 @@ module.exports = {
|
|
|
16
15
|
},
|
|
17
16
|
|
|
18
17
|
create(context) {
|
|
18
|
+
const variablesSet = new Set()
|
|
19
19
|
return {
|
|
20
|
+
VariableDeclarator(node) {
|
|
21
|
+
if (node.init && node.id && node.id.type === 'Identifier') {
|
|
22
|
+
let selectorValue = null
|
|
23
|
+
|
|
24
|
+
if (node.init.type === 'Literal' && typeof node.init.value === 'string') {
|
|
25
|
+
selectorValue = node.init.value
|
|
26
|
+
}
|
|
27
|
+
else if (node.init.type === 'TemplateLiteral'
|
|
28
|
+
&& node.init.expressions.length === 0
|
|
29
|
+
&& node.init.quasis.length === 1) {
|
|
30
|
+
selectorValue = node.init.quasis[0].value.cooked
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (selectorValue && isAliasOrDataSelector(selectorValue)) {
|
|
34
|
+
variablesSet.add(node.id.name)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
|
|
20
39
|
CallExpression(node) {
|
|
21
|
-
if (isCallingCyGet(node) && !isDataArgument(node)) {
|
|
40
|
+
if (isCallingCyGet(node) && !isDataArgument(node, variablesSet)) {
|
|
22
41
|
context.report({ node, messageId: 'unexpected' })
|
|
23
42
|
}
|
|
24
43
|
},
|
|
@@ -34,12 +53,24 @@ function isCallingCyGet(node) {
|
|
|
34
53
|
&& node.callee.property.name === 'get'
|
|
35
54
|
}
|
|
36
55
|
|
|
37
|
-
function isDataArgument(node) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
function isDataArgument(node, dataVariables) {
|
|
57
|
+
if (node.arguments.length === 0) return false
|
|
58
|
+
|
|
59
|
+
const firstArg = node.arguments[0]
|
|
60
|
+
|
|
61
|
+
if (firstArg.type === 'Literal') {
|
|
62
|
+
return isAliasOrDataSelector(String(firstArg.value))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (firstArg.type === 'TemplateLiteral') {
|
|
66
|
+
return isAliasOrDataSelector(String(firstArg.quasis[0].value.cooked))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (firstArg.type === 'Identifier') {
|
|
70
|
+
return dataVariables.has(firstArg.name)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false
|
|
43
74
|
}
|
|
44
75
|
|
|
45
76
|
function isAliasOrDataSelector(selector) {
|
|
@@ -7,7 +7,7 @@ const DESCRIPTION = 'disallow actions within chains'
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Commands listed in the documentation with text: 'It is unsafe to chain further commands that rely on the subject after xxx.'
|
|
10
|
-
* See {@link https://docs.cypress.io/
|
|
10
|
+
* See {@link https://docs.cypress.io/app/core-concepts/retry-ability#Actions-should-be-at-the-end-of-chains-not-the-middle Actions should be at the end of chains, not the middle}
|
|
11
11
|
* for more information.
|
|
12
12
|
*
|
|
13
13
|
* @type {string[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-cypress",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "An ESLint plugin for projects using Cypress",
|
|
5
5
|
"main": "./lib/flat.js",
|
|
6
6
|
"exports": {
|
|
@@ -39,12 +39,15 @@
|
|
|
39
39
|
"eslint-plugin-eslint-plugin": "^6.4.0",
|
|
40
40
|
"eslint-plugin-mocha": "^11.1.0",
|
|
41
41
|
"husky": "^9.1.7",
|
|
42
|
+
"prettier": "^3.5.3",
|
|
42
43
|
"semantic-release": "24.2.5",
|
|
43
44
|
"vitest": "^3.1.4"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
47
|
"lint": "eslint",
|
|
47
48
|
"lint-fix": "eslint --fix",
|
|
49
|
+
"format": "prettier --write .",
|
|
50
|
+
"format:check": "prettier --check .",
|
|
48
51
|
"semantic-release": "semantic-release",
|
|
49
52
|
"test": "vitest run",
|
|
50
53
|
"prepare": "husky"
|