eslint-plugin-cypress 4.3.0 → 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 CHANGED
@@ -1 +1 @@
1
- 22.11.0
1
+ 22.16.0
package/.nvmrc CHANGED
@@ -1 +1 @@
1
- 22.11.0
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 [legacy.js](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/legacy.js) and to [flat.js](https://github.com/cypress-io/eslint-plugin-cypress/blob/master/lib/flat.js)
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,11 +44,6 @@ 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
- ## Legacy tests
48
-
49
- * The directory [tests-legacy](https://github.com/cypress-io/eslint-plugin-cypress/tree/master/tests-legacy) contains tests which are compatible with the legacy [ESLint v8 RuleTester](https://eslint.org/docs/v8.x/integrate/nodejs-api#ruletester) utility. It is not expected to add new rules to this set of tests.
50
- * The directory [tests](https://github.com/cypress-io/eslint-plugin-cypress/tree/master/tests) is for tests compatible with the current [ESLint RuleTester](https://eslint.org/docs/latest/integrate/nodejs-api#ruletester).
51
-
52
47
  ## Merging pull requests
53
48
 
54
49
  This information is for Cypress.io Members or Collaborators who merge pull requests:
@@ -1,147 +1,7 @@
1
1
  # Cypress ESLint Plugin - Legacy Config
2
2
 
3
- This document supplements the [README](./README.md) document and describes how to use the Cypress ESLint Plugin (`eslint-plugin-cypress`) in a [deprecated ESLint legacy config environment](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated). The use of flat configurations with this plugin is described in the [README](./README.md) 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
- Usage with ESLint `9.x` is described.
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
- ## Deprecations
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 where the previous contents of this document, describing how to use `eslint-plugin-cypress` with an ESLint `v9` (default) [flat configuration](https://eslint.org/docs/latest/use/configure/configuration-files), can now be found.
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. For instructions on using a deprecated [eslintrc-type](https://eslint.org/docs/latest/use/configure/configuration-files-deprecated) config file from previous ESLint versions, please refer to the [ESLINTRC-CONFIG](./ESLINTRC-CONFIG.md) document.
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 flat configuration, add a file `eslint.config.mjs` to the root directory of your Cypress project and include the following instructions to import the available flat configurations using:
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/flat'
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 flat configurations available:
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). This version no longer specifies `languageOptions` for `ecmaVersion` and `sourceType` - see ESLint [JavaScript languageOptions](https://eslint.org/docs/latest/use/configure/language-options#specifying-javascript-options). There are no default rules enabled in this configuration. |
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
@@ -67,11 +73,11 @@ In the following sections, different examples of possible configuration file con
67
73
 
68
74
  ### Cypress
69
75
 
70
- All rules from `eslint-plugin-cypress` are available through `eslint-plugin-cypress/flat` and can be individually activated.
76
+ All rules are available by importing from `eslint-plugin-cypress` and can be individually activated.
71
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`
72
78
 
73
79
  ```js
74
- import pluginCypress from 'eslint-plugin-cypress/flat'
80
+ import pluginCypress from 'eslint-plugin-cypress'
75
81
  export default [
76
82
  {
77
83
  plugins: {
@@ -90,7 +96,7 @@ The `eslint-plugin-cypress` [recommended rules](#rules) `configs.recommended` ar
90
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`
91
97
 
92
98
  ```js
93
- import pluginCypress from 'eslint-plugin-cypress/flat'
99
+ import pluginCypress from 'eslint-plugin-cypress'
94
100
  export default [
95
101
  pluginCypress.configs.recommended,
96
102
  {
@@ -106,7 +112,7 @@ export default [
106
112
  The `configs.globals` are activated.
107
113
 
108
114
  ```js
109
- import pluginCypress from 'eslint-plugin-cypress/flat'
115
+ import pluginCypress from 'eslint-plugin-cypress'
110
116
  export default [
111
117
  pluginCypress.configs.globals
112
118
  ]
@@ -157,34 +163,34 @@ it('waits for a second', () => {
157
163
 
158
164
  ## Mocha and Chai
159
165
 
160
- 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`.
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`.
161
167
 
162
168
  ## Mocha `.only` and `.skip`
163
169
 
164
- 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`.
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`.
165
171
 
166
172
  ### Cypress and Mocha recommended
167
173
 
168
- [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) is added to the example [Cypress recommended](#cypress-recommended). This plugin offers a flat file recommended option `configs.flat.recommended`.
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`.
169
175
 
170
- The settings for individual `mocha` rules from the `configs.flat.recommended` option are changed.
171
- - [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) and [mocha/no-skipped-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-skipped-tests.md) are set to `error` instead of `warn`
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`
172
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`
173
179
 
174
180
  ```shell
175
- npm install eslint-plugin-mocha@^10.5.0 --save-dev
181
+ npm install eslint-plugin-mocha@^11 --save-dev
176
182
  ```
177
183
 
178
184
  ```js
179
185
  import pluginMocha from 'eslint-plugin-mocha'
180
- import pluginCypress from 'eslint-plugin-cypress/flat'
186
+ import pluginCypress from 'eslint-plugin-cypress'
181
187
  export default [
182
- pluginMocha.configs.flat.recommended,
188
+ pluginMocha.configs.recommended,
183
189
  pluginCypress.configs.recommended,
184
190
  {
185
191
  rules: {
186
192
  'mocha/no-exclusive-tests': 'error',
187
- 'mocha/no-skipped-tests': 'error',
193
+ 'mocha/no-pending-tests': 'error',
188
194
  'mocha/no-mocha-arrows': 'off',
189
195
  'cypress/no-unnecessary-waiting': 'off'
190
196
  }
@@ -205,7 +211,7 @@ npm install eslint-plugin-chai-friendly@^1.0.1 --save-dev
205
211
  ```
206
212
 
207
213
  ```js
208
- import pluginCypress from 'eslint-plugin-cypress/flat'
214
+ import pluginCypress from 'eslint-plugin-cypress'
209
215
  import pluginChaiFriendly from 'eslint-plugin-chai-friendly'
210
216
  export default [
211
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.14.0
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:
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.flat.recommended,
9
+ mochaPlugin.configs.recommended,
10
10
  {ignores: ['test-project/']},
11
11
  {
12
12
  languageOptions: {
package/lib/flat.js CHANGED
@@ -5,18 +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
- 'assertion-before-screenshot': require('./rules/assertion-before-screenshot'),
14
- 'require-data-selectors': require('./rules/require-data-selectors'),
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-debug': require('./rules/no-debug'),
16
+ 'no-unnecessary-waiting': require('./rules/no-unnecessary-waiting'),
18
17
  'no-xpath': require('./rules/no-xpath'),
19
- 'no-chained-get': require('./rules/no-chained-get'),
18
+ 'require-data-selectors': require('./rules/require-data-selectors'),
19
+ 'unsafe-to-chain-command': require('./rules/unsafe-to-chain-command'),
20
20
  },
21
21
  }
22
22
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "eslint-plugin-cypress",
3
- "version": "4.3.0",
3
+ "version": "5.0.0",
4
4
  "description": "An ESLint plugin for projects using Cypress",
5
- "main": "legacy.js",
5
+ "main": "./lib/flat.js",
6
6
  "exports": {
7
- ".": "./legacy.js",
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": "^15.15.0"
29
+ "globals": "^16.2.0"
30
30
  },
31
31
  "devDependencies": {
32
- "eslint": "^9.24.0",
32
+ "eslint": "^9.27.0",
33
33
  "eslint-plugin-eslint-plugin": "^6.4.0",
34
- "eslint-plugin-mocha": "^10.5.0",
34
+ "eslint-plugin-mocha": "^11.1.0",
35
35
  "husky": "^9.1.7",
36
36
  "jest": "^29.7.0",
37
- "semantic-release": "24.2.3"
37
+ "semantic-release": "24.2.5"
38
38
  },
39
39
  "scripts": {
40
- "lint": "eslint \"*.js\" \"**/**/*.js\"",
41
- "lint-fix": "npm run 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
+ ]
@@ -1,4 +1,4 @@
1
- import pluginCypress from 'eslint-plugin-cypress/flat'
1
+ import pluginCypress from 'eslint-plugin-cypress'
2
2
  export default [
3
3
  pluginCypress.configs.recommended,
4
4
  {
@@ -1,4 +1,4 @@
1
- import pluginCypress from 'eslint-plugin-cypress/flat'
1
+ import pluginCypress from 'eslint-plugin-cypress'
2
2
  export default [
3
3
  pluginCypress.configs.globals
4
4
  ]
@@ -1,4 +1,4 @@
1
- import pluginCypress from 'eslint-plugin-cypress/flat'
1
+ import pluginCypress from 'eslint-plugin-cypress'
2
2
  export default [
3
3
  pluginCypress.configs.recommended,
4
4
  {
@@ -1,6 +0,0 @@
1
- const { defaults } = require('jest-config')
2
-
3
- module.exports = {
4
- testMatch: ['**/tests-legacy/**/*.[jt]s?(x)'],
5
- testPathIgnorePatterns: [...defaults.testPathIgnorePatterns, '.history'],
6
- }
package/legacy.js DELETED
@@ -1,36 +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
- 'no-chained-get': require('./lib/rules/no-chained-get'),
17
- },
18
- configs: {
19
- recommended: require('./lib/config/recommended'),
20
- },
21
- environments: {
22
- globals: {
23
- globals: Object.assign({
24
- cy: false,
25
- Cypress: false,
26
- expect: false,
27
- assert: false,
28
- chai: false,
29
- }, globals.browser, globals.mocha),
30
- parserOptions: {
31
- ecmaVersion: 2019,
32
- sourceType: 'module',
33
- },
34
- },
35
- },
36
- }
@@ -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
- })