eslint-plugin-cypress 4.2.1 → 5.0.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/.node-version +1 -1
- package/.nvmrc +1 -1
- package/CONTRIBUTING.md +25 -4
- package/ESLINTRC-CONFIG.md +3 -143
- package/FLAT-CONFIG.md +1 -3
- package/README.md +26 -19
- package/circle.yml +2 -20
- package/docs/rules/no-chained-get.md +19 -0
- package/eslint.config.mjs +1 -1
- package/lib/flat.js +6 -5
- package/lib/rules/no-chained-get.js +87 -0
- package/package.json +9 -10
- package/test-project/eslint-configs/eslint.default-deprecated.mjs +11 -0
- package/test-project/eslint-configs/eslint.default.mjs +1 -1
- package/test-project/eslint-configs/eslint.globals.mjs +1 -1
- package/test-project/eslint-configs/eslint.recommended.mjs +1 -1
- package/tests/lib/rules/no-chained-get.js +31 -0
- package/jest.config-legacy.js +0 -6
- package/legacy.js +0 -35
- package/tests-legacy/config.js +0 -26
- package/tests-legacy/lib/rules/assertion-before-screenshot.js +0 -35
- package/tests-legacy/lib/rules/no-assigning-return-values.js +0 -38
- package/tests-legacy/lib/rules/no-async-before.js +0 -25
- package/tests-legacy/lib/rules/no-async-tests.js +0 -25
- package/tests-legacy/lib/rules/no-force.js +0 -49
- package/tests-legacy/lib/rules/no-pause.js +0 -37
- package/tests-legacy/lib/rules/no-unnecessary-waiting.js +0 -71
- package/tests-legacy/lib/rules/require-data-selectors.js +0 -31
- package/tests-legacy/lib/rules/unsafe-to-chain-command.js +0 -56
package/.node-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
22.
|
|
1
|
+
22.16.0
|
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
22.
|
|
1
|
+
22.16.0
|
package/CONTRIBUTING.md
CHANGED
|
@@ -34,7 +34,7 @@ To add a new rule:
|
|
|
34
34
|
* Run `npm run lint`
|
|
35
35
|
* Run `npm test` to run [Jest](https://jestjs.io/) (or run `npm start` to run [Jest](https://jestjs.io/) in [watchAll](https://jestjs.io/docs/cli#--watchall) mode where it remains active and reruns when source changes are made)
|
|
36
36
|
* Make sure all tests are passing
|
|
37
|
-
* Add the rule to [
|
|
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))
|
|
39
39
|
* Create a PR from your branch
|
|
40
40
|
|
|
@@ -44,7 +44,28 @@ This plugin uses the ESLint [eslint-doc-generator](https://www.npmjs.com/package
|
|
|
44
44
|
* Install with `npm install eslint-doc-generator -g`
|
|
45
45
|
* Run `eslint-doc-generator` in the root directory of the plugin
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Merging pull requests
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
This information is for Cypress.io Members or Collaborators who merge pull requests:
|
|
50
|
+
|
|
51
|
+
1. When merging a pull request, use the [Squash and merge](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/about-merge-methods-on-github#squashing-your-merge-commits) option to squash all commits into one.
|
|
52
|
+
1. Make sure the commit subject and body follow [semantic commit convention](https://semantic-release.gitbook.io/semantic-release/#commit-message-format), for instance:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
feat: added new parameter
|
|
56
|
+
fix: fixed a bug
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If you need to bump the major version, mark it as breaking change in the body of the commit's message like:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
fix: upgrade dependency X
|
|
63
|
+
|
|
64
|
+
BREAKING CHANGE: requires minimum Node.js 20 to run
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
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).
|
|
69
|
+
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.
|
package/ESLINTRC-CONFIG.md
CHANGED
|
@@ -1,147 +1,7 @@
|
|
|
1
1
|
# Cypress ESLint Plugin - Legacy Config
|
|
2
2
|
|
|
3
|
-
This document
|
|
3
|
+
This document previously described how to use the Cypress ESLint Plugin (`eslint-plugin-cypress`) with an [ESLint legacy config environment](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This form of configuration was deprecated with the release of ESLint `v9` and its use with `eslint-plugin-cypress` is no longer supported.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The use of `eslintrc` configurations with `eslint-plugin-cypress` is deprecated and support will be removed in a future version of this plugin. This is tied in to the ESLint announcement in the blog post [Flat config rollout plans](https://eslint.org/blog/2023/10/flat-config-rollout-plans/) from October 2023 which describes that the `eslintrc` configuration system is planned to be removed in the future ESLint `v10.0.0`. Users are encouraged to migrate to using a [flat configuration](https://eslint.org/docs/latest/use/configure/configuration-files).
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
12
|
-
|
|
13
|
-
Use a minimum ESLint `9.x`.
|
|
14
|
-
|
|
15
|
-
```shell
|
|
16
|
-
npm install eslint eslint-plugin-cypress --save-dev
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
or
|
|
20
|
-
|
|
21
|
-
```shell
|
|
22
|
-
yarn add eslint eslint-plugin-cypress --dev
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Usage
|
|
26
|
-
|
|
27
|
-
To use a deprecated configuration with ESLint `v9`, such as `.eslintrc.json`, you must set the `ESLINT_USE_FLAT_CONFIG` environment variable to `false` (see [ESLint v9 > Configuration Files (Deprecated)](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated)). The following examples use `json` format for the content of the configuration file:
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"plugins": [
|
|
32
|
-
"cypress"
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
You can add rules - see [Rules](./README.md#rules) for a list of the available rules:
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{
|
|
41
|
-
"rules": {
|
|
42
|
-
"cypress/no-assigning-return-values": "error",
|
|
43
|
-
"cypress/no-unnecessary-waiting": "error",
|
|
44
|
-
"cypress/assertion-before-screenshot": "warn",
|
|
45
|
-
"cypress/no-force": "warn",
|
|
46
|
-
"cypress/no-async-tests": "error",
|
|
47
|
-
"cypress/no-async-before": "error",
|
|
48
|
-
"cypress/no-pause": "error",
|
|
49
|
-
"cypress/no-debug": "error"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
You can allow certain globals provided by Cypress:
|
|
55
|
-
|
|
56
|
-
```json
|
|
57
|
-
{
|
|
58
|
-
"env": {
|
|
59
|
-
"cypress/globals": true
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Recommended configuration
|
|
65
|
-
|
|
66
|
-
Use the recommended configuration and you can forego configuring _plugins_, _rules_, and _env_ individually. See [Rules](./README.md#rules) for which rules are included in the recommended configuration.
|
|
67
|
-
|
|
68
|
-
```json
|
|
69
|
-
{
|
|
70
|
-
"extends": [
|
|
71
|
-
"plugin:cypress/recommended"
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Rules
|
|
77
|
-
|
|
78
|
-
See the [Rules](./README.md#rules) list in the main [README](./README.md) document.
|
|
79
|
-
|
|
80
|
-
## Mocha and Chai
|
|
81
|
-
|
|
82
|
-
Cypress is built on top of [Mocha](https://on.cypress.io/guides/references/bundled-libraries#Mocha) and [Chai](https://on.cypress.io/guides/references/bundled-libraries#Chai). See the following sections for information on using ESLint plugins [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-chai-friendly](https://www.npmjs.com/package/eslint-plugin-chai-friendly) together with `eslint-plugin-cypress`.
|
|
83
|
-
|
|
84
|
-
## Mocha `.only` and `.skip`
|
|
85
|
-
|
|
86
|
-
During test spec development, [Mocha exclusive tests](https://mochajs.org/#exclusive-tests) `.only` or [Mocha inclusive tests](https://mochajs.org/#inclusive-tests) `.skip` may be used to control which tests are executed, as described in the Cypress documentation [Excluding and Including Tests](https://on.cypress.io/guides/core-concepts/writing-and-organizing-tests#Excluding-and-Including-Tests). To apply corresponding rules, you can install and use [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha). The rule [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) detects the use of `.only` and the [mocha/no-skipped-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-skipped-tests.md) rule detects the use of `.skip`:
|
|
87
|
-
|
|
88
|
-
```sh
|
|
89
|
-
npm install --save-dev eslint-plugin-mocha
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
In your `.eslintrc.json`:
|
|
93
|
-
|
|
94
|
-
```json
|
|
95
|
-
{
|
|
96
|
-
"plugins": [
|
|
97
|
-
"cypress",
|
|
98
|
-
"mocha"
|
|
99
|
-
],
|
|
100
|
-
"rules": {
|
|
101
|
-
"mocha/no-exclusive-tests": "warn",
|
|
102
|
-
"mocha/no-skipped-tests": "warn"
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Or you can simply use the `cypress/recommended` and `mocha/recommended` configurations together, for example:
|
|
108
|
-
|
|
109
|
-
```json
|
|
110
|
-
{
|
|
111
|
-
"extends": [
|
|
112
|
-
"plugin:cypress/recommended",
|
|
113
|
-
"plugin:mocha/recommended"
|
|
114
|
-
]
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Chai and `no-unused-expressions`
|
|
119
|
-
|
|
120
|
-
Using an assertion such as `expect(value).to.be.true` can fail the ESLint rule `no-unused-expressions` even though it's not an error in this case. To fix this, you can install and use [eslint-plugin-chai-friendly](https://www.npmjs.com/package/eslint-plugin-chai-friendly).
|
|
121
|
-
|
|
122
|
-
```sh
|
|
123
|
-
npm install --save-dev eslint-plugin-chai-friendly
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
In your `.eslintrc.json`:
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"plugins": [
|
|
131
|
-
"cypress",
|
|
132
|
-
"chai-friendly"
|
|
133
|
-
],
|
|
134
|
-
"rules": {
|
|
135
|
-
"no-unused-expressions": 0,
|
|
136
|
-
"chai-friendly/no-unused-expressions": 2
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Or you can simply add its `recommended` config:
|
|
142
|
-
|
|
143
|
-
```json
|
|
144
|
-
{
|
|
145
|
-
"extends": ["plugin:chai-friendly/recommended"]
|
|
146
|
-
}
|
|
147
|
-
```
|
|
7
|
+
Users who were previously using a deprecated configuration environment should migrate to a [flat configuration](https://eslint.org/docs/latest/use/configure/configuration-files).
|
package/FLAT-CONFIG.md
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
# Cypress ESLint Plugin - Flat Config
|
|
2
2
|
|
|
3
|
-
Please refer to the [README](./README.md) document
|
|
4
|
-
|
|
5
|
-
For instructions on using a deprecated [eslintrc-type](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated) config file from previous ESLint `v8` versions and below, please refer to the [ESLINTRC-CONFIG](./ESLINTRC-CONFIG.md) document.
|
|
3
|
+
Please refer to the [README](./README.md) document which describes how to use `eslint-plugin-cypress` with an ESLint `v9` (default) [flat configuration](https://eslint.org/docs/latest/use/configure/configuration-files).
|
package/README.md
CHANGED
|
@@ -18,21 +18,27 @@ yarn add eslint eslint-plugin-cypress --dev
|
|
|
18
18
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
|
-
ESLint `v9` uses a [Flat config file](https://eslint.org/docs/latest/use/configure/configuration-files) format with filename `eslint.config.*js` by default.
|
|
21
|
+
ESLint `v9` uses a [Flat config file](https://eslint.org/docs/latest/use/configure/configuration-files) format with filename `eslint.config.*js` by default. This plugin no longer supports the use of a deprecated [eslintrc-type](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated) config file from previous ESLint versions.
|
|
22
22
|
|
|
23
|
-
To set up a
|
|
23
|
+
To set up a configuration, add a file `eslint.config.mjs` to the root directory of your Cypress project and include the following instructions to import the available configurations using:
|
|
24
24
|
|
|
25
25
|
```shell
|
|
26
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
26
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For backwards compatibility with previous plugin versions `3.3.0` - `4.3.0`, the following equivalent deprecated form is also supported. This is planned to be removed in a future major version:
|
|
30
|
+
|
|
31
|
+
```shell
|
|
32
|
+
import pluginCypress from 'eslint-plugin-cypress/flat' # deprecated
|
|
27
33
|
```
|
|
28
34
|
|
|
29
35
|
## Configurations
|
|
30
36
|
|
|
31
|
-
There are two specific
|
|
37
|
+
There are two specific configurations available:
|
|
32
38
|
|
|
33
39
|
| Configuration | Content |
|
|
34
40
|
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
-
| `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).
|
|
41
|
+
| `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. |
|
|
36
42
|
| `configs.recommended` | enables [recommended Rules](#rules). It includes also `configs.global` (see above). |
|
|
37
43
|
|
|
38
44
|
## Rules
|
|
@@ -50,6 +56,7 @@ These rules enforce some of the [best practices recommended for using Cypress](h
|
|
|
50
56
|
| [no-assigning-return-values](docs/rules/no-assigning-return-values.md) | disallow assigning return values of `cy` calls | ✅ |
|
|
51
57
|
| [no-async-before](docs/rules/no-async-before.md) | disallow using `async`/`await` in Cypress `before` methods | |
|
|
52
58
|
| [no-async-tests](docs/rules/no-async-tests.md) | disallow using `async`/`await` in Cypress test cases | ✅ |
|
|
59
|
+
| [no-chained-get](docs/rules/no-chained-get.md) | disallow chain of `cy.get()` calls | |
|
|
53
60
|
| [no-debug](docs/rules/no-debug.md) | disallow using `cy.debug()` calls | |
|
|
54
61
|
| [no-force](docs/rules/no-force.md) | disallow using `force: true` with action commands | |
|
|
55
62
|
| [no-pause](docs/rules/no-pause.md) | disallow using `cy.pause()` calls | |
|
|
@@ -66,11 +73,11 @@ In the following sections, different examples of possible configuration file con
|
|
|
66
73
|
|
|
67
74
|
### Cypress
|
|
68
75
|
|
|
69
|
-
All rules
|
|
76
|
+
All rules are available by importing from `eslint-plugin-cypress` and can be individually activated.
|
|
70
77
|
- [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`
|
|
71
78
|
|
|
72
79
|
```js
|
|
73
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
80
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
74
81
|
export default [
|
|
75
82
|
{
|
|
76
83
|
plugins: {
|
|
@@ -89,7 +96,7 @@ The `eslint-plugin-cypress` [recommended rules](#rules) `configs.recommended` ar
|
|
|
89
96
|
- [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`
|
|
90
97
|
|
|
91
98
|
```js
|
|
92
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
99
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
93
100
|
export default [
|
|
94
101
|
pluginCypress.configs.recommended,
|
|
95
102
|
{
|
|
@@ -105,7 +112,7 @@ export default [
|
|
|
105
112
|
The `configs.globals` are activated.
|
|
106
113
|
|
|
107
114
|
```js
|
|
108
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
115
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
109
116
|
export default [
|
|
110
117
|
pluginCypress.configs.globals
|
|
111
118
|
]
|
|
@@ -156,34 +163,34 @@ it('waits for a second', () => {
|
|
|
156
163
|
|
|
157
164
|
## Mocha and Chai
|
|
158
165
|
|
|
159
|
-
Cypress is built on top of [Mocha](https://on.cypress.io/
|
|
166
|
+
Cypress is built on top of [Mocha](https://on.cypress.io/app/references/bundled-libraries#Mocha) and [Chai](https://on.cypress.io/app/references/bundled-libraries#Chai). See the following sections for information on using ESLint plugins [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-chai-friendly](https://www.npmjs.com/package/eslint-plugin-chai-friendly) together with `eslint-plugin-cypress`.
|
|
160
167
|
|
|
161
168
|
## Mocha `.only` and `.skip`
|
|
162
169
|
|
|
163
|
-
During test spec development, [Mocha exclusive tests](https://mochajs.org/#exclusive-tests) `.only` or [Mocha inclusive tests](https://mochajs.org/#inclusive-tests) `.skip` may be used to control which tests are executed, as described in the Cypress documentation [Excluding and Including Tests](https://on.cypress.io/
|
|
170
|
+
During test spec development, [Mocha exclusive tests](https://mochajs.org/#exclusive-tests) `.only` or [Mocha inclusive tests](https://mochajs.org/#inclusive-tests) `.skip` may be used to control which tests are executed, as described in the Cypress documentation [Excluding and Including Tests](https://on.cypress.io/app/core-concepts/writing-and-organizing-tests#Excluding-and-Including-Tests). To apply corresponding rules, you can install and use [eslint-plugin-mocha@^11](https://www.npmjs.com/package/eslint-plugin-mocha) plugin version or above. The rule [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) detects the use of `.only` and the [mocha/no-pending-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-pending-tests.md) rule detects the use of `.skip`.
|
|
164
171
|
|
|
165
172
|
### Cypress and Mocha recommended
|
|
166
173
|
|
|
167
|
-
[eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) is added to the example [Cypress recommended](#cypress-recommended). This plugin
|
|
174
|
+
[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`.
|
|
168
175
|
|
|
169
|
-
The settings for individual `mocha` rules from the `configs.
|
|
170
|
-
- [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) and [mocha/no-
|
|
176
|
+
The settings for individual `mocha` rules from the `configs.recommended` option are changed.
|
|
177
|
+
- [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`
|
|
171
178
|
- [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`
|
|
172
179
|
|
|
173
180
|
```shell
|
|
174
|
-
npm install eslint-plugin-mocha@^
|
|
181
|
+
npm install eslint-plugin-mocha@^11 --save-dev
|
|
175
182
|
```
|
|
176
183
|
|
|
177
184
|
```js
|
|
178
185
|
import pluginMocha from 'eslint-plugin-mocha'
|
|
179
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
186
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
180
187
|
export default [
|
|
181
|
-
pluginMocha.configs.
|
|
188
|
+
pluginMocha.configs.recommended,
|
|
182
189
|
pluginCypress.configs.recommended,
|
|
183
190
|
{
|
|
184
191
|
rules: {
|
|
185
192
|
'mocha/no-exclusive-tests': 'error',
|
|
186
|
-
'mocha/no-
|
|
193
|
+
'mocha/no-pending-tests': 'error',
|
|
187
194
|
'mocha/no-mocha-arrows': 'off',
|
|
188
195
|
'cypress/no-unnecessary-waiting': 'off'
|
|
189
196
|
}
|
|
@@ -204,7 +211,7 @@ npm install eslint-plugin-chai-friendly@^1.0.1 --save-dev
|
|
|
204
211
|
```
|
|
205
212
|
|
|
206
213
|
```js
|
|
207
|
-
import pluginCypress from 'eslint-plugin-cypress
|
|
214
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
208
215
|
import pluginChaiFriendly from 'eslint-plugin-chai-friendly'
|
|
209
216
|
export default [
|
|
210
217
|
pluginCypress.configs.recommended,
|
package/circle.yml
CHANGED
|
@@ -3,14 +3,13 @@ version: 2.1
|
|
|
3
3
|
executors:
|
|
4
4
|
docker-executor:
|
|
5
5
|
docker:
|
|
6
|
-
- image: cimg/node:22.
|
|
6
|
+
- image: cimg/node:22.16.0
|
|
7
7
|
resource_class: medium
|
|
8
8
|
|
|
9
9
|
workflows:
|
|
10
10
|
main:
|
|
11
11
|
jobs:
|
|
12
12
|
- lint
|
|
13
|
-
- test-v8
|
|
14
13
|
- test-v9
|
|
15
14
|
|
|
16
15
|
- build-test-project
|
|
@@ -21,6 +20,7 @@ workflows:
|
|
|
21
20
|
config-file: [
|
|
22
21
|
# configurations correspond to examples in README
|
|
23
22
|
'default',
|
|
23
|
+
'default-deprecated', # using deprecated /flat
|
|
24
24
|
'recommended',
|
|
25
25
|
'globals',
|
|
26
26
|
]
|
|
@@ -29,7 +29,6 @@ workflows:
|
|
|
29
29
|
- release:
|
|
30
30
|
requires:
|
|
31
31
|
- lint
|
|
32
|
-
- test-v8
|
|
33
32
|
- test-v9
|
|
34
33
|
- test-test-project
|
|
35
34
|
filters:
|
|
@@ -52,23 +51,6 @@ jobs:
|
|
|
52
51
|
name: Lint code
|
|
53
52
|
command: npm run lint
|
|
54
53
|
|
|
55
|
-
test-v8:
|
|
56
|
-
executor: docker-executor
|
|
57
|
-
steps:
|
|
58
|
-
- checkout
|
|
59
|
-
- run:
|
|
60
|
-
name: Install dependencies
|
|
61
|
-
command: npm ci
|
|
62
|
-
- run:
|
|
63
|
-
name: Install ESLint 8
|
|
64
|
-
command: npm install eslint@8
|
|
65
|
-
- run:
|
|
66
|
-
name: Show ESLint version
|
|
67
|
-
command: npx eslint --version
|
|
68
|
-
- run:
|
|
69
|
-
name: Test ESLint 8
|
|
70
|
-
command: npm run test:legacy
|
|
71
|
-
|
|
72
54
|
test-v9:
|
|
73
55
|
executor: docker-executor
|
|
74
56
|
steps:
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Disallow chain of `cy.get()` calls (`cypress/no-chained-get`)
|
|
2
|
+
|
|
3
|
+
<!-- end auto-generated rule header -->
|
|
4
|
+
This rule disallows the usage of chained `.get()` calls as `cy.get()` always starts its search from the cy.root element.
|
|
5
|
+
|
|
6
|
+
## Rule Details
|
|
7
|
+
|
|
8
|
+
Examples of **incorrect** code for this rule:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
cy.get('parent').get('child')
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Examples of **correct** code for this rule:
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
cy.get('parent')
|
|
18
|
+
.find('child')
|
|
19
|
+
```
|
package/eslint.config.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import mochaPlugin from 'eslint-plugin-mocha'
|
|
|
6
6
|
export default [
|
|
7
7
|
pluginJs.configs.recommended,
|
|
8
8
|
eslintPlugin.configs['flat/recommended'],
|
|
9
|
-
mochaPlugin.configs.
|
|
9
|
+
mochaPlugin.configs.recommended,
|
|
10
10
|
{ignores: ['test-project/']},
|
|
11
11
|
{
|
|
12
12
|
languageOptions: {
|
package/lib/flat.js
CHANGED
|
@@ -5,17 +5,18 @@ const plugin = {
|
|
|
5
5
|
meta: { name, version },
|
|
6
6
|
configs: {},
|
|
7
7
|
rules: {
|
|
8
|
+
'assertion-before-screenshot': require('./rules/assertion-before-screenshot'),
|
|
8
9
|
'no-assigning-return-values': require('./rules/no-assigning-return-values'),
|
|
9
|
-
'unsafe-to-chain-command': require('./rules/unsafe-to-chain-command'),
|
|
10
|
-
'no-unnecessary-waiting': require('./rules/no-unnecessary-waiting'),
|
|
11
10
|
'no-async-before': require('./rules/no-async-before'),
|
|
12
11
|
'no-async-tests': require('./rules/no-async-tests'),
|
|
13
|
-
'
|
|
14
|
-
'
|
|
12
|
+
'no-chained-get': require('./rules/no-chained-get'),
|
|
13
|
+
'no-debug': require('./rules/no-debug'),
|
|
15
14
|
'no-force': require('./rules/no-force'),
|
|
16
15
|
'no-pause': require('./rules/no-pause'),
|
|
17
|
-
'no-
|
|
16
|
+
'no-unnecessary-waiting': require('./rules/no-unnecessary-waiting'),
|
|
18
17
|
'no-xpath': require('./rules/no-xpath'),
|
|
18
|
+
'require-data-selectors': require('./rules/require-data-selectors'),
|
|
19
|
+
'unsafe-to-chain-command': require('./rules/unsafe-to-chain-command'),
|
|
19
20
|
},
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
//------------------------------------------------------------------------------
|
|
4
|
+
// Rule Definition
|
|
5
|
+
//------------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
/** @type {import('eslint').Rule.RuleModule} */
|
|
8
|
+
module.exports = {
|
|
9
|
+
meta: {
|
|
10
|
+
type: 'problem',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'disallow chain of `cy.get()` calls',
|
|
13
|
+
recommended: false,
|
|
14
|
+
url: 'https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/no-chained-get.md',
|
|
15
|
+
},
|
|
16
|
+
fixable: null,
|
|
17
|
+
schema: [],
|
|
18
|
+
messages: {
|
|
19
|
+
unexpected: 'Avoid chaining multiple cy.get() calls',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
create(context) {
|
|
24
|
+
const isRootCypress = (node) => {
|
|
25
|
+
if (
|
|
26
|
+
node.type !== 'CallExpression' ||
|
|
27
|
+
node.callee.type !== 'MemberExpression'
|
|
28
|
+
) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
node.callee.object.type === 'Identifier' &&
|
|
34
|
+
node.callee.object.name === 'cy'
|
|
35
|
+
) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return isRootCypress(node.callee.object);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const hasChainedGet = (node) => {
|
|
43
|
+
// Check if this node is a get() call
|
|
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
|
+
|
|
51
|
+
if (!isGetCall) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const obj = node.callee.object;
|
|
56
|
+
|
|
57
|
+
if (obj.type === 'CallExpression') {
|
|
58
|
+
const objCallee = obj.callee;
|
|
59
|
+
|
|
60
|
+
if (
|
|
61
|
+
objCallee &&
|
|
62
|
+
objCallee.type === 'MemberExpression' &&
|
|
63
|
+
objCallee.property &&
|
|
64
|
+
objCallee.property.type === 'Identifier' &&
|
|
65
|
+
objCallee.property.name === 'get'
|
|
66
|
+
) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return hasChainedGet(obj);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
CallExpression(node) {
|
|
78
|
+
if (isRootCypress(node) && hasChainedGet(node)) {
|
|
79
|
+
context.report({
|
|
80
|
+
node,
|
|
81
|
+
messageId: 'unexpected',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-cypress",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "An ESLint plugin for projects using Cypress",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "./lib/flat.js",
|
|
6
6
|
"exports": {
|
|
7
|
-
".": "./
|
|
7
|
+
".": "./lib/flat.js",
|
|
8
8
|
"./flat": "./lib/flat.js"
|
|
9
9
|
},
|
|
10
10
|
"author": "Cypress-io",
|
|
@@ -26,23 +26,22 @@
|
|
|
26
26
|
"eslint": ">=9"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"globals": "^
|
|
29
|
+
"globals": "^16.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"eslint": "^9.
|
|
32
|
+
"eslint": "^9.27.0",
|
|
33
33
|
"eslint-plugin-eslint-plugin": "^6.4.0",
|
|
34
|
-
"eslint-plugin-mocha": "^
|
|
34
|
+
"eslint-plugin-mocha": "^11.1.0",
|
|
35
35
|
"husky": "^9.1.7",
|
|
36
36
|
"jest": "^29.7.0",
|
|
37
|
-
"semantic-release": "24.2.
|
|
37
|
+
"semantic-release": "24.2.5"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"lint": "eslint
|
|
41
|
-
"lint-fix": "
|
|
40
|
+
"lint": "eslint",
|
|
41
|
+
"lint-fix": "eslint --fix",
|
|
42
42
|
"semantic-release": "semantic-release",
|
|
43
43
|
"start": "npm run test-watch",
|
|
44
44
|
"test": "jest",
|
|
45
|
-
"test:legacy": "jest --config jest.config-legacy.js",
|
|
46
45
|
"test-watch": "jest --watchAll",
|
|
47
46
|
"prepare": "husky"
|
|
48
47
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// eslint-plugin-cypress/flat is deprecated and is identical to
|
|
2
|
+
// eslint-plugin-cypress
|
|
3
|
+
import pluginCypress from 'eslint-plugin-cypress/flat'
|
|
4
|
+
export default [
|
|
5
|
+
pluginCypress.configs.recommended,
|
|
6
|
+
{
|
|
7
|
+
rules: {
|
|
8
|
+
'cypress/no-unnecessary-waiting': 'off'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview disallow chain of `cy.get()` calls
|
|
3
|
+
* @author benoit
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
//------------------------------------------------------------------------------
|
|
8
|
+
// Requirements
|
|
9
|
+
//------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const rule = require("../../../lib/rules/no-chained-get"),
|
|
12
|
+
RuleTester = require("eslint").RuleTester;
|
|
13
|
+
|
|
14
|
+
//------------------------------------------------------------------------------
|
|
15
|
+
// Tests
|
|
16
|
+
//------------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
const ruleTester = new RuleTester();
|
|
19
|
+
ruleTester.run("no-chained-get", rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{ code: "cy.get('div')" },
|
|
22
|
+
{ code: "cy.get('.div').find().get()" },
|
|
23
|
+
{ code: "cy.get('input').should('be.disabled')" },
|
|
24
|
+
],
|
|
25
|
+
invalid: [
|
|
26
|
+
{
|
|
27
|
+
code: "cy.get('div').get('div')",
|
|
28
|
+
errors: [{ messageId: "unexpected" }],
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
});
|
package/jest.config-legacy.js
DELETED
package/legacy.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const globals = require('globals')
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
rules: {
|
|
5
|
-
'no-assigning-return-values': require('./lib/rules/no-assigning-return-values'),
|
|
6
|
-
'unsafe-to-chain-command': require('./lib/rules/unsafe-to-chain-command'),
|
|
7
|
-
'no-unnecessary-waiting': require('./lib/rules/no-unnecessary-waiting'),
|
|
8
|
-
'no-async-before': require('./lib/rules/no-async-before'),
|
|
9
|
-
'no-async-tests': require('./lib/rules/no-async-tests'),
|
|
10
|
-
'assertion-before-screenshot': require('./lib/rules/assertion-before-screenshot'),
|
|
11
|
-
'require-data-selectors': require('./lib/rules/require-data-selectors'),
|
|
12
|
-
'no-force': require('./lib/rules/no-force'),
|
|
13
|
-
'no-pause': require('./lib/rules/no-pause'),
|
|
14
|
-
'no-debug': require('./lib/rules/no-debug'),
|
|
15
|
-
'no-xpath': require('./lib/rules/no-xpath'),
|
|
16
|
-
},
|
|
17
|
-
configs: {
|
|
18
|
-
recommended: require('./lib/config/recommended'),
|
|
19
|
-
},
|
|
20
|
-
environments: {
|
|
21
|
-
globals: {
|
|
22
|
-
globals: Object.assign({
|
|
23
|
-
cy: false,
|
|
24
|
-
Cypress: false,
|
|
25
|
-
expect: false,
|
|
26
|
-
assert: false,
|
|
27
|
-
chai: false,
|
|
28
|
-
}, globals.browser, globals.mocha),
|
|
29
|
-
parserOptions: {
|
|
30
|
-
ecmaVersion: 2019,
|
|
31
|
-
sourceType: 'module',
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
}
|
package/tests-legacy/config.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/* global describe, it, expect */
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
const globals = require('globals')
|
|
5
|
-
const config = require('../legacy.js')
|
|
6
|
-
|
|
7
|
-
describe('environments globals', () => {
|
|
8
|
-
const env = config.environments.globals
|
|
9
|
-
|
|
10
|
-
it('should not mutate globals', () => {
|
|
11
|
-
expect(globals.browser).not.toHaveProperty('cy')
|
|
12
|
-
expect(globals.mocha).not.toHaveProperty('cy')
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should include other globals', () => {
|
|
16
|
-
expect(env.globals).toEqual(expect.objectContaining(globals.browser))
|
|
17
|
-
expect(env.globals).toEqual(expect.objectContaining(globals.mocha))
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('should include cypress globals', () => {
|
|
21
|
-
expect(env.globals).toEqual(expect.objectContaining({
|
|
22
|
-
cy: false,
|
|
23
|
-
Cypress: false,
|
|
24
|
-
}))
|
|
25
|
-
})
|
|
26
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/assertion-before-screenshot')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
const ruleTester = new RuleTester()
|
|
7
|
-
|
|
8
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
-
const parserOptions = { ecmaVersion: 6 }
|
|
10
|
-
|
|
11
|
-
ruleTester.run('assertion-before-screenshot', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
{ code: 'cy.get(".some-element"); cy.screenshot();', parserOptions },
|
|
14
|
-
{ code: 'cy.get(".some-element").should("exist").screenshot();', parserOptions },
|
|
15
|
-
{ code: 'cy.get(".some-element").should("exist").screenshot().click()', parserOptions, errors },
|
|
16
|
-
{ code: 'cy.get(".some-element").should("exist"); if(true) cy.screenshot();', parserOptions },
|
|
17
|
-
{ code: 'if(true) { cy.get(".some-element").should("exist"); cy.screenshot(); }', parserOptions },
|
|
18
|
-
{ code: 'cy.get(".some-element").should("exist"); if(true) { cy.screenshot(); }', parserOptions },
|
|
19
|
-
{ code: 'const a = () => { cy.get(".some-element").should("exist"); cy.screenshot(); }', parserOptions, errors },
|
|
20
|
-
{ code: 'cy.get(".some-element").should("exist").and("be.visible"); cy.screenshot();', parserOptions },
|
|
21
|
-
{ code: 'cy.get(".some-element").contains("Text"); cy.screenshot();', parserOptions },
|
|
22
|
-
],
|
|
23
|
-
|
|
24
|
-
invalid: [
|
|
25
|
-
{ code: 'cy.screenshot()', parserOptions, errors },
|
|
26
|
-
{ code: 'cy.visit("somepage"); cy.screenshot();', parserOptions, errors },
|
|
27
|
-
{ code: 'cy.custom(); cy.screenshot()', parserOptions, errors },
|
|
28
|
-
{ code: 'cy.get(".some-element").click(); cy.screenshot()', parserOptions, errors },
|
|
29
|
-
{ code: 'cy.get(".some-element").click().screenshot()', parserOptions, errors },
|
|
30
|
-
{ code: 'if(true) { cy.get(".some-element").click(); cy.screenshot(); }', parserOptions, errors },
|
|
31
|
-
{ code: 'cy.get(".some-element").click(); if(true) { cy.screenshot(); }', parserOptions, errors },
|
|
32
|
-
{ code: 'cy.get(".some-element"); function a() { cy.screenshot(); }', parserOptions, errors },
|
|
33
|
-
{ code: 'cy.get(".some-element"); const a = () => { cy.screenshot(); }', parserOptions, errors },
|
|
34
|
-
],
|
|
35
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/no-assigning-return-values')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
const ruleTester = new RuleTester()
|
|
7
|
-
|
|
8
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
-
const parserOptions = { ecmaVersion: 6 }
|
|
10
|
-
|
|
11
|
-
ruleTester.run('no-assigning-return-values', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
{ code: 'var foo = true;', parserOptions },
|
|
14
|
-
{ code: 'let foo = true;', parserOptions },
|
|
15
|
-
{ code: 'const foo = true;', parserOptions },
|
|
16
|
-
{ code: 'const foo = bar();', parserOptions },
|
|
17
|
-
{ code: 'const foo = bar().baz();', parserOptions },
|
|
18
|
-
{ code: 'const spy = cy.spy();', parserOptions },
|
|
19
|
-
{ code: 'const spy = cy.spy().as();', parserOptions },
|
|
20
|
-
{ code: 'const stub = cy.stub();', parserOptions },
|
|
21
|
-
{ code: 'const result = cy.now();', parserOptions },
|
|
22
|
-
{ code: 'const state = cy.state();', parserOptions },
|
|
23
|
-
{ code: 'cy.get("foo");', parserOptions },
|
|
24
|
-
{ code: 'cy.contains("foo").click();', parserOptions },
|
|
25
|
-
],
|
|
26
|
-
|
|
27
|
-
invalid: [
|
|
28
|
-
{ code: 'let a = cy.get("foo")', parserOptions, errors },
|
|
29
|
-
{ code: 'const a = cy.get("foo")', parserOptions, errors },
|
|
30
|
-
{ code: 'var a = cy.get("foo")', parserOptions, errors },
|
|
31
|
-
|
|
32
|
-
{ code: 'let a = cy.contains("foo")', parserOptions, errors },
|
|
33
|
-
{ code: 'let a = cy.window()', parserOptions, errors },
|
|
34
|
-
{ code: 'let a = cy.wait("@something")', parserOptions, errors },
|
|
35
|
-
|
|
36
|
-
{ code: 'let a = cy.contains("foo").click()', parserOptions, errors },
|
|
37
|
-
],
|
|
38
|
-
})
|
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
})
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/no-async-tests')
|
|
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-tests', rule, {
|
|
13
|
-
valid: [
|
|
14
|
-
{ code: 'it(\'a test case\', () => { cy.get(\'.someClass\'); })', parserOptions },
|
|
15
|
-
{ code: 'it(\'a test 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: 'it(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
21
|
-
{ code: 'test(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
22
|
-
{ code: 'it(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
23
|
-
{ code: 'test(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
|
|
24
|
-
],
|
|
25
|
-
})
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
//------------------------------------------------------------------------------
|
|
4
|
-
// Requirements
|
|
5
|
-
//------------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
const rule = require('../../../lib/rules/no-force')
|
|
8
|
-
|
|
9
|
-
const RuleTester = require('eslint').RuleTester
|
|
10
|
-
|
|
11
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
12
|
-
const parserOptions = { ecmaVersion: 2018 }
|
|
13
|
-
|
|
14
|
-
//------------------------------------------------------------------------------
|
|
15
|
-
// Tests
|
|
16
|
-
//------------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
let ruleTester = new RuleTester()
|
|
19
|
-
|
|
20
|
-
ruleTester.run('no-force', rule, {
|
|
21
|
-
|
|
22
|
-
valid: [
|
|
23
|
-
{ code: `cy.get('button').click()`, parserOptions },
|
|
24
|
-
{ code: `cy.get('button').click({multiple: true})`, parserOptions },
|
|
25
|
-
{ code: `cy.get('button').dblclick()`, parserOptions },
|
|
26
|
-
{ code: `cy.get('input').type('somth')`, parserOptions },
|
|
27
|
-
{ code: `cy.get('input').type('somth', {anyoption: true})`, parserOptions },
|
|
28
|
-
{ code: `cy.get('input').trigger('click', {anyoption: true})`, parserOptions },
|
|
29
|
-
{ code: `cy.get('input').rightclick({anyoption: true})`, parserOptions },
|
|
30
|
-
{ code: `cy.get('input').check()`, parserOptions },
|
|
31
|
-
{ code: `cy.get('input').select()`, parserOptions },
|
|
32
|
-
{ code: `cy.get('input').focus()`, parserOptions },
|
|
33
|
-
{ code: `cy.document().trigger("keydown", { ...event })`, parserOptions },
|
|
34
|
-
],
|
|
35
|
-
|
|
36
|
-
invalid: [
|
|
37
|
-
{ code: `cy.get('button').click({force: true})`, parserOptions, errors },
|
|
38
|
-
{ code: `cy.get('button').dblclick({force: true})`, parserOptions, errors },
|
|
39
|
-
{ code: `cy.get('input').type('somth', {force: true})`, parserOptions, errors },
|
|
40
|
-
{ code: `cy.get('div').find('.foo').type('somth', {force: true})`, parserOptions, errors },
|
|
41
|
-
{ code: `cy.get('div').find('.foo').find('.bar').click({force: true})`, parserOptions, errors },
|
|
42
|
-
{ code: `cy.get('div').find('.foo').find('.bar').trigger('change', {force: true})`, parserOptions, errors },
|
|
43
|
-
{ code: `cy.get('input').trigger('click', {force: true})`, parserOptions, errors },
|
|
44
|
-
{ code: `cy.get('input').rightclick({force: true})`, parserOptions, errors },
|
|
45
|
-
{ code: `cy.get('input').check({force: true})`, parserOptions, errors },
|
|
46
|
-
{ code: `cy.get('input').select({force: true})`, parserOptions, errors },
|
|
47
|
-
{ code: `cy.get('input').focus({force: true})`, parserOptions, errors },
|
|
48
|
-
],
|
|
49
|
-
})
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
//------------------------------------------------------------------------------
|
|
4
|
-
// Requirements
|
|
5
|
-
//------------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
const rule = require('../../../lib/rules/no-pause')
|
|
8
|
-
|
|
9
|
-
const RuleTester = require('eslint').RuleTester
|
|
10
|
-
|
|
11
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
12
|
-
const parserOptions = { ecmaVersion: 2018 }
|
|
13
|
-
|
|
14
|
-
//------------------------------------------------------------------------------
|
|
15
|
-
// Tests
|
|
16
|
-
//------------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
const ruleTester = new RuleTester()
|
|
19
|
-
|
|
20
|
-
ruleTester.run('no-pause', rule, {
|
|
21
|
-
|
|
22
|
-
valid: [
|
|
23
|
-
{ code: `pause()`, parserOptions },
|
|
24
|
-
{ code: `cy.get('button').dblclick()`, parserOptions },
|
|
25
|
-
],
|
|
26
|
-
|
|
27
|
-
invalid: [
|
|
28
|
-
{ code: `cy.pause()`, parserOptions, errors },
|
|
29
|
-
{ code: `cy.pause({ log: false })`, parserOptions, errors },
|
|
30
|
-
{ code: `cy.get('button').pause()`, parserOptions, errors },
|
|
31
|
-
{
|
|
32
|
-
code: `cy.get('a').should('have.attr', 'href').and('match', /dashboard/).pause()`,
|
|
33
|
-
parserOptions,
|
|
34
|
-
errors
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
})
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/no-unnecessary-waiting')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
const ruleTester = new RuleTester()
|
|
7
|
-
|
|
8
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
-
const parserOptions = { ecmaVersion: 6, sourceType: 'module' }
|
|
10
|
-
|
|
11
|
-
ruleTester.run('no-unnecessary-waiting', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
{ code: 'foo.wait(10)', parserOptions },
|
|
14
|
-
|
|
15
|
-
{ code: 'cy.wait("@someRequest")', parserOptions },
|
|
16
|
-
{ code: 'cy.wait("@someRequest", { log: false })', parserOptions },
|
|
17
|
-
{ code: 'cy.wait("@someRequest").then((xhr) => xhr)', parserOptions },
|
|
18
|
-
{ code: 'cy.wait(["@someRequest", "@anotherRequest"])', parserOptions },
|
|
19
|
-
|
|
20
|
-
{ code: 'cy.clock(5000)', parserOptions },
|
|
21
|
-
{ code: 'cy.scrollTo(0, 10)', parserOptions },
|
|
22
|
-
{ code: 'cy.tick(500)', parserOptions },
|
|
23
|
-
|
|
24
|
-
{ code: 'const someRequest="@someRequest"; cy.wait(someRequest)', parserOptions, errors },
|
|
25
|
-
{ code: 'function customWait (alias = "@someRequest") { cy.wait(alias) }', parserOptions, errors },
|
|
26
|
-
{ code: 'const customWait = (alias = "@someRequest") => { cy.wait(alias) }', parserOptions, errors },
|
|
27
|
-
{ code: 'function customWait (ms) { cy.wait(ms) }', parserOptions, errors },
|
|
28
|
-
{ code: 'const customWait = (ms) => { cy.wait(ms) }', parserOptions, errors },
|
|
29
|
-
|
|
30
|
-
{ code: 'import BAR_BAZ from "bar-baz"; cy.wait(BAR_BAZ)', parserOptions },
|
|
31
|
-
{ code: 'import { FOO_BAR } from "foo-bar"; cy.wait(FOO_BAR)', parserOptions },
|
|
32
|
-
{ code: 'import * as wildcard from "wildcard"; cy.wait(wildcard.value)', parserOptions },
|
|
33
|
-
{ code: 'import { NAME as OTHER_NAME } from "rename"; cy.wait(OTHER_NAME)', parserOptions },
|
|
34
|
-
|
|
35
|
-
// disable the eslint rule
|
|
36
|
-
{
|
|
37
|
-
code: `
|
|
38
|
-
cy.wait(100); // eslint-disable-line no-unnecessary-waiting
|
|
39
|
-
`,
|
|
40
|
-
parserOptions,
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
code: `
|
|
44
|
-
/* eslint-disable-next-line no-unnecessary-waiting */
|
|
45
|
-
cy.wait(100)
|
|
46
|
-
`,
|
|
47
|
-
parserOptions,
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
code: `
|
|
51
|
-
/* eslint-disable no-unnecessary-waiting */
|
|
52
|
-
cy.wait(100)
|
|
53
|
-
/* eslint-enable no-unnecessary-waiting */
|
|
54
|
-
`,
|
|
55
|
-
parserOptions,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
|
|
59
|
-
invalid: [
|
|
60
|
-
{ code: 'cy.wait(0)', parserOptions, errors },
|
|
61
|
-
{ code: 'cy.wait(100)', parserOptions, errors },
|
|
62
|
-
{ code: 'cy.wait(5000)', parserOptions, errors },
|
|
63
|
-
{ code: 'const someNumber=500; cy.wait(someNumber)', parserOptions, errors },
|
|
64
|
-
{ code: 'function customWait (ms = 1) { cy.wait(ms) }', parserOptions, errors },
|
|
65
|
-
{ code: 'const customWait = (ms = 1) => { cy.wait(ms) }', parserOptions, errors },
|
|
66
|
-
|
|
67
|
-
{ code: 'cy.get(".some-element").wait(10)', parserOptions, errors },
|
|
68
|
-
{ code: 'cy.get(".some-element").contains("foo").wait(10)', parserOptions, errors },
|
|
69
|
-
{ code: 'const customWait = (ms = 1) => { cy.get(".some-element").wait(ms) }', parserOptions, errors },
|
|
70
|
-
],
|
|
71
|
-
})
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/require-data-selectors')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
const ruleTester = new RuleTester()
|
|
7
|
-
|
|
8
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
-
const parserOptions = { ecmaVersion: 6 }
|
|
10
|
-
|
|
11
|
-
ruleTester.run('require-data-selectors', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
{ code: 'cy.get(\'[data-cy=submit]\').click()', parserOptions },
|
|
14
|
-
{ code: 'cy.get(\'[data-QA=submit]\')', parserOptions },
|
|
15
|
-
{ code: 'cy.clock(5000)', parserOptions },
|
|
16
|
-
{ code: 'cy.scrollTo(0, 10)', parserOptions },
|
|
17
|
-
{ code: 'cy.tick(500)', parserOptions },
|
|
18
|
-
{ code: 'cy.get(\`[data-cy=${1}]\`)', parserOptions }, // eslint-disable-line no-useless-escape
|
|
19
|
-
{ code: 'cy.get("@my-alias")', parserOptions, errors },
|
|
20
|
-
{ code: 'cy.get(`@my-alias`)', parserOptions, errors },
|
|
21
|
-
],
|
|
22
|
-
|
|
23
|
-
invalid: [
|
|
24
|
-
{ code: 'cy.get(\'[daedta-cy=submit]\').click()', parserOptions, errors },
|
|
25
|
-
{ code: 'cy.get(\'[d-cy=submit]\')', parserOptions, errors },
|
|
26
|
-
{ code: 'cy.get(".btn-large").click()', parserOptions, errors },
|
|
27
|
-
{ code: 'cy.get(".btn-.large").click()', parserOptions, errors },
|
|
28
|
-
{ code: 'cy.get(".a")', parserOptions, errors },
|
|
29
|
-
{ code: 'cy.get(\`[daedta-cy=${1}]\`)', parserOptions, errors }, // eslint-disable-line no-useless-escape
|
|
30
|
-
],
|
|
31
|
-
})
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../../lib/rules/unsafe-to-chain-command')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
const ruleTester = new RuleTester()
|
|
7
|
-
|
|
8
|
-
const errors = [{ messageId: 'unexpected' }]
|
|
9
|
-
const parserOptions = { ecmaVersion: 6 }
|
|
10
|
-
|
|
11
|
-
ruleTester.run('action-ends-chain', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
{
|
|
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
|
-
parserOptions,
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
code: 'cy.focused().should("be.visible");',
|
|
19
|
-
parserOptions,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
code: 'cy.submitBtn().click();',
|
|
23
|
-
parserOptions,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
|
|
27
|
-
invalid: [
|
|
28
|
-
{
|
|
29
|
-
code: 'cy.get("new-todo").type("todo A{enter}").should("have.class", "active");',
|
|
30
|
-
parserOptions,
|
|
31
|
-
errors,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
code: 'cy.get("new-todo").type("todo A{enter}").type("todo B{enter}");',
|
|
35
|
-
parserOptions,
|
|
36
|
-
errors,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
code: 'cy.get("new-todo").focus().should("have.class", "active");',
|
|
40
|
-
parserOptions,
|
|
41
|
-
errors,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
code: 'cy.get("new-todo").customType("todo A{enter}").customClick();',
|
|
45
|
-
options: [{ methods: ['customType', 'customClick'] }],
|
|
46
|
-
parserOptions,
|
|
47
|
-
errors,
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
code: 'cy.get("new-todo").customPress("Enter").customScroll();',
|
|
51
|
-
options: [{ methods: [/customPress/, /customScroll/] }],
|
|
52
|
-
parserOptions,
|
|
53
|
-
errors,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
})
|