eslint-plugin-cypress 0.0.0-dev.1109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +80 -0
- package/LICENSE +21 -0
- package/README.md +299 -0
- package/docs/rules/assertion-before-screenshot.md +28 -0
- package/docs/rules/no-and.md +37 -0
- package/docs/rules/no-assigning-return-values.md +11 -0
- package/docs/rules/no-async-before.md +52 -0
- package/docs/rules/no-async-tests.md +55 -0
- package/docs/rules/no-chained-get.md +21 -0
- package/docs/rules/no-debug.md +22 -0
- package/docs/rules/no-force.md +51 -0
- package/docs/rules/no-pause.md +22 -0
- package/docs/rules/no-unnecessary-waiting.md +11 -0
- package/docs/rules/no-xpath.md +34 -0
- package/docs/rules/require-data-selectors.md +59 -0
- package/docs/rules/unsafe-to-chain-command.md +33 -0
- package/lib/config/recommended.js +14 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +65 -0
- package/lib/rules/assertion-before-screenshot.js +99 -0
- package/lib/rules/no-and.js +56 -0
- package/lib/rules/no-assigning-return-values.js +68 -0
- package/lib/rules/no-async-before.js +53 -0
- package/lib/rules/no-async-tests.js +53 -0
- package/lib/rules/no-chained-get.js +71 -0
- package/lib/rules/no-debug.js +52 -0
- package/lib/rules/no-force.js +79 -0
- package/lib/rules/no-pause.js +52 -0
- package/lib/rules/no-unnecessary-waiting.js +95 -0
- package/lib/rules/no-xpath.js +43 -0
- package/lib/rules/require-data-selectors.js +77 -0
- package/lib/rules/unsafe-to-chain-command.js +123 -0
- package/lib/utils/is-root-cypress.js +46 -0
- package/package.json +68 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Contributing to cypress-io/eslint-plugin-cypress
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time to contribute! :smile:
|
|
4
|
+
|
|
5
|
+
## Preparation
|
|
6
|
+
|
|
7
|
+
- Fork and clone this repository
|
|
8
|
+
- Branch from the default `master` branch using a descriptive new branch name
|
|
9
|
+
- Install dependencies with `npm ci`
|
|
10
|
+
|
|
11
|
+
## Rule references
|
|
12
|
+
|
|
13
|
+
- Refer to the [ESLint documentation](https://eslint.org/docs/latest/) and the [Custom Rules](https://eslint.org/docs/latest/extend/custom-rules) page
|
|
14
|
+
|
|
15
|
+
## New rule
|
|
16
|
+
|
|
17
|
+
To add a new rule:
|
|
18
|
+
|
|
19
|
+
- Follow the instructions in the ESLint [generator-eslint](https://www.npmjs.com/package/generator-eslint) documentation to install [Yeoman](https://www.npmjs.com/package/yo) and the generator
|
|
20
|
+
- Run the new rule generator `yo eslint:rule` and answer the questions
|
|
21
|
+
- select "ESLint Plugin"
|
|
22
|
+
- for "Type a short description of this rule" provide text which starts with one of "enforce", "require" or "disallow" (all lower case)
|
|
23
|
+
- Yeoman creates three boilerplate files:
|
|
24
|
+
- `docs/rules/<rule-id>.md`
|
|
25
|
+
- `lib/rules/<rule-id>.js`
|
|
26
|
+
- `test/rules/<rule-id>.js`
|
|
27
|
+
- Run `npm run lint-fix`
|
|
28
|
+
- Address the linting errors by editing `lib/rules/<rule-id>.js`
|
|
29
|
+
- Add a `meta.messages` property (see [MessageIds](https://eslint.org/docs/latest/extend/custom-rules#messageids))
|
|
30
|
+
- Select the appropriate `meta.type` property using `problem`, `suggestion`, or `layout`
|
|
31
|
+
- Complete the new rule by adding content to the three files previously created
|
|
32
|
+
- Run `npx eslint-doc-generator` to generate automated documentation sections (see [Document generation](#document-generation) below)
|
|
33
|
+
- Review documentation changes
|
|
34
|
+
- Run `npm run lint`
|
|
35
|
+
- Run `npm run format`
|
|
36
|
+
- Run `npm test` to run [Vitest](https://vitest.dev/)
|
|
37
|
+
- Make sure all tests are passing
|
|
38
|
+
- Add the rule to [index.js](./lib/index.js)
|
|
39
|
+
- Create a git commit with a commit message similar to: `feat: add rule <description>` (see [commit message conventions](https://github.com/semantic-release/semantic-release#commit-message-format))
|
|
40
|
+
- Create a PR from your branch
|
|
41
|
+
|
|
42
|
+
## Document generation
|
|
43
|
+
|
|
44
|
+
This plugin uses the [eslint-doc-generator](https://www.npmjs.com/package/eslint-doc-generator) package to generate consistent documentation.
|
|
45
|
+
|
|
46
|
+
- Run `npx eslint-doc-generator` in the root directory of the plugin
|
|
47
|
+
|
|
48
|
+
Previous compatibility issues with Windows are resolved, and
|
|
49
|
+
[eslint-doc-generator](https://www.npmjs.com/package/eslint-doc-generator)
|
|
50
|
+
is now installed together with other dependencies through `npm ci`.
|
|
51
|
+
If you previously had [eslint-doc-generator](https://www.npmjs.com/package/eslint-doc-generator) installed globally,
|
|
52
|
+
to work with this repo, you can now uninstall it:
|
|
53
|
+
|
|
54
|
+
- Run `npm uninstall eslint-doc-generator -g` (only if previously installed)
|
|
55
|
+
|
|
56
|
+
## Merging pull requests
|
|
57
|
+
|
|
58
|
+
This information is for Cypress.io Members or Collaborators who merge pull requests:
|
|
59
|
+
|
|
60
|
+
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.
|
|
61
|
+
1. Make sure the commit subject and body follow [semantic commit convention](https://semantic-release.gitbook.io/semantic-release/#commit-message-format), for instance:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
feat: added new parameter
|
|
65
|
+
fix: fixed a bug
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If you need to bump the major version, mark it as breaking change in the body of the commit's message like:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
fix: upgrade dependency X
|
|
72
|
+
|
|
73
|
+
BREAKING CHANGE: requires minimum Node.js 20 to run
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
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).
|
|
77
|
+
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).
|
|
78
|
+
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).
|
|
79
|
+
This means that only `feat:`, `fix:` and `perf:` trigger a new release.
|
|
80
|
+
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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Cypress.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Cypress ESLint Plugin [](https://circleci.com/gh/cypress-io/eslint-plugin-cypress/tree/master)
|
|
2
|
+
|
|
3
|
+
An [ESLint](https://eslint.org) plugin for your [Cypress](https://cypress.io) tests.
|
|
4
|
+
|
|
5
|
+
Note: If you installed ESLint globally then you must also install `eslint-plugin-cypress` globally.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Prerequisites: [ESLint](https://www.npmjs.com/package/eslint) `v10`. Lower versions are no longer supported.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install eslint eslint-plugin-cypress --save-dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
or
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
yarn add eslint eslint-plugin-cypress --dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
ESLint as of `v10` and this plugin no longer support the use of the deprecated [eslintrc-type](https://eslint.org/docs/v9.x/use/configure/configuration-files-deprecated) config file format.
|
|
24
|
+
You must use a [Flat config file](https://eslint.org/docs/latest/use/configure/configuration-files) format.
|
|
25
|
+
|
|
26
|
+
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:
|
|
27
|
+
|
|
28
|
+
```shell
|
|
29
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The configuration `eslint-plugin-cypress/flat`, which was deprecated in plugin version `5.0.0`, is no longer available.
|
|
33
|
+
Migrate to using the equivalent configuration `eslint-plugin-cypress` by dropping the `/flat` suffix.
|
|
34
|
+
|
|
35
|
+
Refer to ESLint `v10` [Configuration File Resolution](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file-resolution) for hierarchical use of configuration files.
|
|
36
|
+
|
|
37
|
+
## Configurations
|
|
38
|
+
|
|
39
|
+
There are two specific configurations available:
|
|
40
|
+
|
|
41
|
+
| Configuration | Content |
|
|
42
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| `configs.globals` | defines globals `cy`, `Cypress`, `expect`, `assert` and `chai` used in Cypress test specs as well as `globals.browser` and `globals.mocha` from [globals](https://www.npmjs.com/package/globals). There are no default rules enabled in this configuration. |
|
|
44
|
+
| `configs.recommended` | enables [recommended Rules](#rules). It includes also `configs.global` (see above). |
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
|
|
48
|
+
These rules enforce some of the [best practices recommended for using Cypress](https://on.cypress.io/best-practices).
|
|
49
|
+
|
|
50
|
+
<!-- prettier-ignore-start -->
|
|
51
|
+
<!-- begin auto-generated rules list -->
|
|
52
|
+
|
|
53
|
+
💼 Configurations enabled in.\
|
|
54
|
+
✅ Set in the `recommended` configuration.\
|
|
55
|
+
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
|
|
56
|
+
❌ Deprecated.
|
|
57
|
+
|
|
58
|
+
| Name | Description | 💼 | 🔧 | ❌ |
|
|
59
|
+
| :----------------------------------------------------------------------- | :-------------------------------------------------------------- | :- | :- | :- |
|
|
60
|
+
| [assertion-before-screenshot](docs/rules/assertion-before-screenshot.md) | require screenshots to be preceded by an assertion | | | |
|
|
61
|
+
| [no-and](docs/rules/no-and.md) | enforce `.should()` over `.and()` for starting assertion chains | | 🔧 | |
|
|
62
|
+
| [no-assigning-return-values](docs/rules/no-assigning-return-values.md) | disallow assigning return values of `cy` calls | ✅ | | |
|
|
63
|
+
| [no-async-before](docs/rules/no-async-before.md) | disallow using `async`/`await` in Cypress `before` methods | | | |
|
|
64
|
+
| [no-async-tests](docs/rules/no-async-tests.md) | disallow using `async`/`await` in Cypress test cases | ✅ | | |
|
|
65
|
+
| [no-chained-get](docs/rules/no-chained-get.md) | disallow chain of `cy.get()` calls | | | |
|
|
66
|
+
| [no-debug](docs/rules/no-debug.md) | disallow using `cy.debug()` calls | | | |
|
|
67
|
+
| [no-force](docs/rules/no-force.md) | disallow using `force: true` with action commands | | | |
|
|
68
|
+
| [no-pause](docs/rules/no-pause.md) | disallow using `cy.pause()` calls | | | |
|
|
69
|
+
| [no-unnecessary-waiting](docs/rules/no-unnecessary-waiting.md) | disallow waiting for arbitrary time periods | ✅ | | |
|
|
70
|
+
| [no-xpath](docs/rules/no-xpath.md) | disallow using `cy.xpath()` calls | | | ❌ |
|
|
71
|
+
| [require-data-selectors](docs/rules/require-data-selectors.md) | require `data-*` attribute selectors | | | |
|
|
72
|
+
| [unsafe-to-chain-command](docs/rules/unsafe-to-chain-command.md) | disallow actions within chains | ✅ | | |
|
|
73
|
+
|
|
74
|
+
<!-- end auto-generated rules list -->
|
|
75
|
+
<!-- prettier-ignore-end -->
|
|
76
|
+
|
|
77
|
+
## Usage examples
|
|
78
|
+
|
|
79
|
+
In the following sections, different examples of possible configuration file contents are given, together with some brief explanations. Adapt these examples according to your needs.
|
|
80
|
+
|
|
81
|
+
### Cypress
|
|
82
|
+
|
|
83
|
+
All rules are available by importing from `eslint-plugin-cypress` and can be individually activated.
|
|
84
|
+
|
|
85
|
+
- [cypress/unsafe-to-chain-command](./docs/rules/unsafe-to-chain-command.md) is activated and set to `error`
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { defineConfig } from 'eslint/config'
|
|
89
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
90
|
+
export default defineConfig([
|
|
91
|
+
{
|
|
92
|
+
plugins: {
|
|
93
|
+
cypress: pluginCypress,
|
|
94
|
+
},
|
|
95
|
+
rules: {
|
|
96
|
+
'cypress/unsafe-to-chain-command': 'error',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
])
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Cypress recommended
|
|
103
|
+
|
|
104
|
+
The `eslint-plugin-cypress` [recommended rules](#rules) `configs.recommended` are activated, except for
|
|
105
|
+
|
|
106
|
+
- [cypress/no-unnecessary-waiting](./docs/rules/no-unnecessary-waiting.md) which is set to `off`
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
import { defineConfig } from 'eslint/config'
|
|
110
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
111
|
+
export default defineConfig([
|
|
112
|
+
{
|
|
113
|
+
files: ['cypress/**/*.js'],
|
|
114
|
+
extends: [pluginCypress.configs.recommended],
|
|
115
|
+
rules: {
|
|
116
|
+
'cypress/no-unnecessary-waiting': 'off',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
])
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Cypress globals
|
|
123
|
+
|
|
124
|
+
The `configs.globals` are activated.
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
import { defineConfig } from 'eslint/config'
|
|
128
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
129
|
+
export default defineConfig([
|
|
130
|
+
{
|
|
131
|
+
files: ['cypress/**/*.js'],
|
|
132
|
+
extends: [pluginCypress.configs.globals],
|
|
133
|
+
},
|
|
134
|
+
])
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Typed Linting
|
|
138
|
+
|
|
139
|
+
You can activate typed linting for increased accuracy, if you want. This is purely optional and all rules continue to work without it. It uses a TypeScript parser to parse your entire project, instead of only the file being linted, which gives the plugin more information to work with. Be aware of the [performance penalty](https://typescript-eslint.io/getting-started/typed-linting/#performance) that this brings with it.
|
|
140
|
+
|
|
141
|
+
First, install the `@typescript-eslint/parser` npm package:
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
npm install @typescript-eslint/parser --save-dev
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
If you already have a TypeScript codebase, you can skip the next step. If not, you need a `tsconfig.json`. The following minimal `tsconfig.json` does not compile or check your code and includes all .js files.
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"include": ["**/*.js"],
|
|
152
|
+
"compilerOptions": {
|
|
153
|
+
"allowJs": true,
|
|
154
|
+
"checkJs": false,
|
|
155
|
+
"noEmit": true
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The last step is to extend your eslint config to use the `typescript-eslint` parser.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
import { defineConfig } from 'eslint/config'
|
|
164
|
+
import typescriptParser from '@typescript-eslint/parser'
|
|
165
|
+
export default defineConfig([
|
|
166
|
+
{
|
|
167
|
+
languageOptions: {
|
|
168
|
+
parser: typescriptParser,
|
|
169
|
+
parserOptions: {
|
|
170
|
+
projectService: true,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
])
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Disable rules
|
|
178
|
+
|
|
179
|
+
You can disable specific rules per file, for a portion of a file, or for a single line. See the [ESLint rules](https://eslint.org/docs/latest/use/configure/rules#disable-rules) documentation. For example ...
|
|
180
|
+
|
|
181
|
+
Disable the `cypress/no-unnecessary-waiting` rule for the entire file by placing this at the start of the file:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
/* eslint-disable cypress/no-unnecessary-waiting */
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Disable the `cypress/no-unnecessary-waiting` rule for only a portion of the file:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
it('waits for a second', () => {
|
|
191
|
+
...
|
|
192
|
+
/* eslint-disable cypress/no-unnecessary-waiting */
|
|
193
|
+
cy.wait(1000)
|
|
194
|
+
/* eslint-enable cypress/no-unnecessary-waiting */
|
|
195
|
+
...
|
|
196
|
+
})
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Disable the `cypress/no-unnecessary-waiting` rule for a specific line:
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
it('waits for a second', () => {
|
|
203
|
+
...
|
|
204
|
+
cy.wait(1000) // eslint-disable-line cypress/no-unnecessary-waiting
|
|
205
|
+
...
|
|
206
|
+
})
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
You can also disable a rule for the next line:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
it('waits for a second', () => {
|
|
213
|
+
...
|
|
214
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
215
|
+
cy.wait(1000)
|
|
216
|
+
...
|
|
217
|
+
})
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Mocha and Chai
|
|
221
|
+
|
|
222
|
+
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`.
|
|
223
|
+
|
|
224
|
+
## Mocha `.only` and `.skip`
|
|
225
|
+
|
|
226
|
+
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`.
|
|
227
|
+
|
|
228
|
+
### Cypress and Mocha recommended
|
|
229
|
+
|
|
230
|
+
[eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) is added to the example [Cypress recommended](#cypress-recommended).
|
|
231
|
+
|
|
232
|
+
The settings for individual `mocha` rules from the `configs.recommended` option are changed.
|
|
233
|
+
|
|
234
|
+
- [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md)
|
|
235
|
+
and [mocha/no-pending-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-pending-tests.md)
|
|
236
|
+
are set to `error` instead of `warn`
|
|
237
|
+
- [mocha/no-mocha-arrows](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-mocha-arrows.md)
|
|
238
|
+
and [mocha/no-async-in-sync-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/documentation/rules/no-async-in-sync-tests.md)
|
|
239
|
+
are set to `off` instead of `error`
|
|
240
|
+
|
|
241
|
+
```shell
|
|
242
|
+
npm install eslint-plugin-mocha --save-dev
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
import { defineConfig } from 'eslint/config'
|
|
247
|
+
import pluginMocha from 'eslint-plugin-mocha'
|
|
248
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
249
|
+
export default defineConfig([
|
|
250
|
+
{
|
|
251
|
+
files: ['cypress/**/*.js'],
|
|
252
|
+
extends: [
|
|
253
|
+
pluginMocha.configs.recommended,
|
|
254
|
+
pluginCypress.configs.recommended,
|
|
255
|
+
],
|
|
256
|
+
rules: {
|
|
257
|
+
'mocha/no-async-in-sync-tests': 'off', // for Cypress compatibility
|
|
258
|
+
'mocha/no-exclusive-tests': 'error',
|
|
259
|
+
'mocha/no-pending-tests': 'error',
|
|
260
|
+
'mocha/no-mocha-arrows': 'off',
|
|
261
|
+
'cypress/no-unnecessary-waiting': 'off',
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
])
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Cypress and Chai recommended
|
|
268
|
+
|
|
269
|
+
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).
|
|
270
|
+
|
|
271
|
+
[eslint-plugin-chai-friendly](https://www.npmjs.com/package/eslint-plugin-chai-friendly) is combined with the Cypress plugin `eslint-plugin-cypress`.
|
|
272
|
+
|
|
273
|
+
The recommended rules for both plugins are used: `pluginCypress.configs.recommended` and `pluginChaiFriendly.configs.recommendedFlat`:
|
|
274
|
+
|
|
275
|
+
```shell
|
|
276
|
+
npm install eslint-plugin-chai-friendly --save-dev
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
import { defineConfig } from 'eslint/config'
|
|
281
|
+
import pluginCypress from 'eslint-plugin-cypress'
|
|
282
|
+
import pluginChaiFriendly from 'eslint-plugin-chai-friendly'
|
|
283
|
+
export default defineConfig([
|
|
284
|
+
{
|
|
285
|
+
files: ['cypress/**/*.js'],
|
|
286
|
+
extends: [
|
|
287
|
+
pluginCypress.configs.recommended,
|
|
288
|
+
pluginChaiFriendly.configs.recommendedFlat,
|
|
289
|
+
],
|
|
290
|
+
rules: {
|
|
291
|
+
'cypress/no-unnecessary-waiting': 'off',
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
])
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Contributing
|
|
298
|
+
|
|
299
|
+
Please see our [Contributing Guideline](./CONTRIBUTING.md) which explains how to contribute rules or other fixes and features to the repo.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# cypress/assertion-before-screenshot
|
|
2
|
+
|
|
3
|
+
📝 Require screenshots to be preceded by an assertion.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
If you take screenshots without assertions then you may get different screenshots depending on timing.
|
|
8
|
+
|
|
9
|
+
For example, if clicking a button makes some network calls and upon success, renders something, then the screenshot may sometimes have the new render and sometimes not.
|
|
10
|
+
|
|
11
|
+
## Rule Details
|
|
12
|
+
|
|
13
|
+
This rule checks there is an assertion making sure your application state is correct before doing a screenshot. This makes sure the result of the screenshot will be consistent.
|
|
14
|
+
|
|
15
|
+
Examples of **incorrect** code for this rule:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
cy.visit('myUrl')
|
|
19
|
+
cy.screenshot()
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Examples of **correct** code for this rule:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
cy.visit('myUrl')
|
|
26
|
+
cy.get('[data-test-id="my-element"]').should('be.visible')
|
|
27
|
+
cy.screenshot()
|
|
28
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# cypress/no-and
|
|
2
|
+
|
|
3
|
+
📝 Enforce `.should()` over `.and()` for starting assertion chains.
|
|
4
|
+
|
|
5
|
+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
|
|
6
|
+
|
|
7
|
+
<!-- end auto-generated rule header -->
|
|
8
|
+
|
|
9
|
+
Cypress's [.and()](https://on.cypress.io/and) is an alias for [.should()](https://on.cypress.io/should). Using `.and()` reads naturally when it follows `.should()` or `.contains()` — it continues an assertion chain like "should be empty **and** be hidden." In other positions, `.should()` is clearer.
|
|
10
|
+
|
|
11
|
+
## Rule Details
|
|
12
|
+
|
|
13
|
+
This rule allows `.and()` only when it immediately follows `.should()`, `.and()`, or `.contains()`. In all other positions, it flags `.and()` and auto-fixes it to `.should()`.
|
|
14
|
+
|
|
15
|
+
Examples of **incorrect** code for this rule:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
cy.get('elem').and('have.text', 'blah')
|
|
19
|
+
cy.get('foo').find('.bar').and('have.class', 'active')
|
|
20
|
+
cy.get('foo').click().and('be.disabled')
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Examples of **correct** code for this rule:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
cy.get('elem').should('have.text', 'blah')
|
|
27
|
+
cy.get('.err').should('be.empty').and('be.hidden')
|
|
28
|
+
cy.contains('Login').and('be.visible')
|
|
29
|
+
cy.get('foo')
|
|
30
|
+
.should('be.visible')
|
|
31
|
+
.and('have.text', 'bar')
|
|
32
|
+
.and('have.class', 'active')
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## When Not To Use It
|
|
36
|
+
|
|
37
|
+
If you prefer using `.and()` interchangeably with `.should()` in all positions, turn this rule off.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# cypress/no-assigning-return-values
|
|
2
|
+
|
|
3
|
+
📝 Disallow assigning return values of `cy` calls.
|
|
4
|
+
|
|
5
|
+
💼 This rule is enabled in the ✅ `recommended` config.
|
|
6
|
+
|
|
7
|
+
<!-- end auto-generated rule header -->
|
|
8
|
+
|
|
9
|
+
## Further Reading
|
|
10
|
+
|
|
11
|
+
See [the Cypress Best Practices guide](https://on.cypress.io/best-practices#Assigning-Return-Values).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# cypress/no-async-before
|
|
2
|
+
|
|
3
|
+
📝 Disallow using `async`/`await` in Cypress `before` methods.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
Cypress commands that return a promise may cause side effects in `before`/`beforeEach` hooks, possibly causing unexpected behavior.
|
|
8
|
+
|
|
9
|
+
## Rule Details
|
|
10
|
+
|
|
11
|
+
This rule disallows using `async` `before` and `beforeEach` functions.
|
|
12
|
+
|
|
13
|
+
Examples of **incorrect** code for this rule:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
describe('my feature', () => {
|
|
17
|
+
before('my test case', async () => {
|
|
18
|
+
await cy.get('.myClass')
|
|
19
|
+
// other operations
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
describe('my feature', () => {
|
|
26
|
+
before('my test case', async () => {
|
|
27
|
+
cy.get('.myClass').click()
|
|
28
|
+
|
|
29
|
+
await someAsyncFunction()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Examples of **correct** code for this rule:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
describe('my feature', () => {
|
|
38
|
+
before('my test case', () => {
|
|
39
|
+
cy.get('.myClass')
|
|
40
|
+
// other operations
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## When Not To Use It
|
|
46
|
+
|
|
47
|
+
If there are genuine use-cases for using `async/await` in your `before` hooks then you may not want to include this rule (or at least demote it to a warning).
|
|
48
|
+
|
|
49
|
+
## Further Reading
|
|
50
|
+
|
|
51
|
+
- [Mixing Async and Sync code](https://on.cypress.io/app/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code)
|
|
52
|
+
- [Commands Are Asynchronous](https://on.cypress.io/app/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# cypress/no-async-tests
|
|
2
|
+
|
|
3
|
+
📝 Disallow using `async`/`await` in Cypress test cases.
|
|
4
|
+
|
|
5
|
+
💼 This rule is enabled in the ✅ `recommended` config.
|
|
6
|
+
|
|
7
|
+
<!-- end auto-generated rule header -->
|
|
8
|
+
|
|
9
|
+
Cypress tests [that return a promise will error](https://docs.cypress.io/app/references/error-messages.html#Cypress-detected-that-you-returned-a-promise-from-a-command-while-also-invoking-one-or-more-cy-commands-in-that-promise) and cannot run successfully.
|
|
10
|
+
An `async` function returns a promise under the hood, so a test using an `async` function will also error.
|
|
11
|
+
|
|
12
|
+
## Rule Details
|
|
13
|
+
|
|
14
|
+
This rule disallows using `async` test functions.
|
|
15
|
+
|
|
16
|
+
Examples of **incorrect** code for this rule:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
describe('my feature', () => {
|
|
20
|
+
it('my test case', async () => {
|
|
21
|
+
await cy.get('.myClass')
|
|
22
|
+
// other operations
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
describe('my feature', () => {
|
|
29
|
+
it('my test case', async () => {
|
|
30
|
+
cy.get('.myClass').click()
|
|
31
|
+
|
|
32
|
+
await someAsyncFunction()
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Examples of **correct** code for this rule:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
describe('my feature', () => {
|
|
41
|
+
it('my test case', () => {
|
|
42
|
+
cy.get('.myClass')
|
|
43
|
+
// other operations
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## When Not To Use It
|
|
49
|
+
|
|
50
|
+
If there are genuine use-cases for using `async/await` in your test cases then you may not want to include this rule (or at least demote it to a warning).
|
|
51
|
+
|
|
52
|
+
## Further Reading
|
|
53
|
+
|
|
54
|
+
- [Mixing Async and Sync code](https://on.cypress.io/app/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code)
|
|
55
|
+
- [Commands Are Asynchronous](https://on.cypress.io/app/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# cypress/no-chained-get
|
|
2
|
+
|
|
3
|
+
📝 Disallow chain of `cy.get()` calls.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
This rule disallows the usage of chained `.get()` calls as `cy.get()` always starts its search from the cy.root element.
|
|
8
|
+
|
|
9
|
+
## Rule Details
|
|
10
|
+
|
|
11
|
+
Examples of **incorrect** code for this rule:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
cy.get('parent').get('child')
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Examples of **correct** code for this rule:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
cy.get('parent').find('child')
|
|
21
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# cypress/no-debug
|
|
2
|
+
|
|
3
|
+
📝 Disallow using `cy.debug()` calls.
|
|
4
|
+
|
|
5
|
+
<!-- end auto-generated rule header -->
|
|
6
|
+
|
|
7
|
+
It is recommended to remove any [cy.debug](https://on.cypress.io/debug) commands before committing specs to avoid other developers getting unexpected results.
|
|
8
|
+
|
|
9
|
+
## Rule Details
|
|
10
|
+
|
|
11
|
+
Examples of **incorrect** code for this rule:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
cy.debug()
|
|
15
|
+
cy.get('selector').debug()
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Examples of **correct** code for this rule:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
cy.get('selector')
|
|
22
|
+
```
|