eslint-plugin-cypress 6.3.1 → 6.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -139,6 +139,46 @@ export default defineConfig([
|
|
|
139
139
|
])
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
### Typed Linting
|
|
143
|
+
|
|
144
|
+
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.
|
|
145
|
+
|
|
146
|
+
First, install the `@typescript-eslint/parser` npm package:
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
npm install @typescript-eslint/parser --save-dev
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
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.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"include": ["**/*.js"],
|
|
157
|
+
"compilerOptions": {
|
|
158
|
+
"allowJs": true,
|
|
159
|
+
"checkJs": false,
|
|
160
|
+
"noEmit": true
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The last step is to extend your eslint config to use the `typescript-eslint` parser.
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
import { defineConfig } from 'eslint/config'
|
|
169
|
+
import typescriptParser from '@typescript-eslint/parser'
|
|
170
|
+
export default defineConfig([
|
|
171
|
+
{
|
|
172
|
+
languageOptions: {
|
|
173
|
+
parser: typescriptParser,
|
|
174
|
+
parserOptions: {
|
|
175
|
+
projectService: true,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
])
|
|
180
|
+
```
|
|
181
|
+
|
|
142
182
|
## Disable rules
|
|
143
183
|
|
|
144
184
|
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 ...
|
|
@@ -16,6 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- end auto-generated rule options list -->
|
|
18
18
|
|
|
19
|
+
## Typed Linting
|
|
20
|
+
|
|
21
|
+
If [Typed Linting](../../README.md#typed-linting) is enabled, this rule also catches unsafe chaining even when the Cypress chain was started from a helper function.
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
function getTodo() {
|
|
25
|
+
return cy.get('.todo')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getTodo().type('todo A{enter}').type('todo B{enter}')
|
|
29
|
+
```
|
|
30
|
+
|
|
19
31
|
## Further Reading
|
|
20
32
|
|
|
21
33
|
See [retry-ability guide](https://docs.cypress.io/app/core-concepts/retry-ability#Actions-should-be-at-the-end-of-chains-not-the-middle).
|
|
@@ -3,26 +3,44 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Whether `node` is a CallExpression that belongs to a Cypress command chain
|
|
5
5
|
* rooted at `cy` (walks `callee.object` through nested calls).
|
|
6
|
+
* If type information are available, additionally checks the return type of helper functions.
|
|
6
7
|
*
|
|
7
8
|
* @param {import('estree').Node} node
|
|
8
9
|
* @returns {boolean}
|
|
9
10
|
*/
|
|
10
|
-
|
|
11
|
-
if (
|
|
12
|
-
node.type !== 'CallExpression'
|
|
13
|
-
|| node.callee.type !== 'MemberExpression'
|
|
14
|
-
) {
|
|
11
|
+
const isRootCypress = (node, context) => {
|
|
12
|
+
if (node.type !== 'CallExpression') {
|
|
15
13
|
return false
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
&& node.callee.object.name === 'cy'
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
const calleeType = node.callee.type
|
|
17
|
+
if (calleeType === 'MemberExpression') {
|
|
18
|
+
if (node.callee.object.type === 'Identifier' && node.callee.object.name === 'cy') {
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return isRootCypress(node.callee.object, context)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (calleeType === 'Identifier') {
|
|
26
|
+
const services = context?.sourceCode?.parserServices
|
|
27
|
+
if (services?.program && services.esTreeNodeToTSNodeMap) {
|
|
28
|
+
const checker = services.program.getTypeChecker()
|
|
29
|
+
const tsNode = services.esTreeNodeToTSNodeMap.get(node)
|
|
30
|
+
if (tsNode) {
|
|
31
|
+
const signature = checker.getResolvedSignature(tsNode)
|
|
32
|
+
if (signature) {
|
|
33
|
+
const returnType = checker.getReturnTypeOfSignature(signature)
|
|
34
|
+
const symbol = returnType.getSymbol()
|
|
35
|
+
if (symbol) {
|
|
36
|
+
return checker.getFullyQualifiedName(symbol) === 'Cypress.Chainable'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
23
41
|
}
|
|
24
42
|
|
|
25
|
-
return
|
|
43
|
+
return false
|
|
26
44
|
}
|
|
27
45
|
|
|
28
46
|
module.exports = { isRootCypress }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-cypress",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.1",
|
|
4
4
|
"description": "An ESLint plugin for projects using Cypress",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -28,22 +28,30 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/cypress-io/eslint-plugin-cypress#readme",
|
|
30
30
|
"peerDependencies": {
|
|
31
|
+
"@typescript-eslint/parser": ">=8",
|
|
31
32
|
"eslint": ">=9"
|
|
32
33
|
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@typescript-eslint/parser": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
33
39
|
"dependencies": {
|
|
34
|
-
"globals": "^17.
|
|
40
|
+
"globals": "^17.6.0"
|
|
35
41
|
},
|
|
36
42
|
"devDependencies": {
|
|
37
43
|
"@eslint/js": "^10.0.1",
|
|
38
44
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
39
|
-
"eslint": "^
|
|
40
|
-
"
|
|
45
|
+
"@typescript-eslint/rule-tester": "^8.59.2",
|
|
46
|
+
"cypress": "^15.14.2",
|
|
47
|
+
"eslint": "^10.3.0",
|
|
48
|
+
"eslint-plugin-eslint-plugin": "^7.3.3",
|
|
41
49
|
"eslint-plugin-mocha": "^11.2.0",
|
|
42
50
|
"husky": "^9.1.7",
|
|
43
|
-
"prettier": "^3.8.
|
|
51
|
+
"prettier": "^3.8.3",
|
|
44
52
|
"typescript": "^5.9.3",
|
|
45
|
-
"typescript-eslint": "^8.
|
|
46
|
-
"vitest": "^4.1.
|
|
53
|
+
"typescript-eslint": "^8.59.2",
|
|
54
|
+
"vitest": "^4.1.5"
|
|
47
55
|
},
|
|
48
56
|
"scripts": {
|
|
49
57
|
"lint": "eslint",
|