Skip to content

Commit 1ae902a

Browse files
committedMar 2, 2025·
feat: add rule disallow usage of cypress-xpath
1 parent 19842d3 commit 1ae902a

File tree

5 files changed

+95
-0
lines changed

5 files changed

+95
-0
lines changed
 

‎docs/rules/no-xpath.md

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Disallow usage of cypress xpath (`no-xpath`)
2+
3+
This rule disallow the usage of cypress-xpath for selecting elements.
4+
5+
6+
Examples of **incorrect** code for this rule:
7+
8+
```js
9+
10+
cy.xpath('//div[@class=\"container\"]').click()
11+
```
12+
13+
Examples of **correct** code for this rule:
14+
15+
16+
```js
17+
18+
cy.get('[data-cy="container"]').click();
19+
```
20+
21+
22+
## Further Reading
23+
24+
`cypress-xpath` package has been deprecated since Oct 13, 2022.
25+
26+
27+
See [the Cypress Best Practices guide](https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements).

‎legacy.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
'no-force': require('./lib/rules/no-force'),
1313
'no-pause': require('./lib/rules/no-pause'),
1414
'no-debug': require('./lib/rules/no-debug'),
15+
'no-xpath': require('./lib/rules/no-xpath'),
1516
},
1617
configs: {
1718
recommended: require('./lib/config/recommended'),

‎lib/flat.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const plugin = {
1515
'no-force': require('./rules/no-force'),
1616
'no-pause': require('./rules/no-pause'),
1717
'no-debug': require('./rules/no-debug'),
18+
'no-xpath': require('./rules/no-xpath'),
1819
},
1920
}
2021

‎lib/rules/no-xpath.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict'
2+
3+
module.exports = {
4+
meta: {
5+
type: 'suggestion',
6+
docs: {
7+
description: "disallow usage of xpath in selector",
8+
recommended: false,
9+
url: "https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/no-xpath.md"
10+
},
11+
fixable: null, // Or `code` or `whitespace`
12+
schema: [], // Add a schema if the rule has options
13+
messages: {
14+
unexpected: 'avoid using cypress xpath',
15+
},
16+
},
17+
18+
create (context) {
19+
return {
20+
CallExpression (node) {
21+
if (isCallingCyXpath(node)) {
22+
context.report({ node, messageId: 'unexpected' })
23+
}
24+
},
25+
}
26+
},
27+
};
28+
29+
function isCallingCyXpath (node) {
30+
return node.callee.type === 'MemberExpression' &&
31+
node.callee.object.type === 'Identifier' &&
32+
node.callee.object.name === 'cy' &&
33+
node.callee.property.type === 'Identifier' &&
34+
node.callee.property.name === 'xpath'
35+
}

‎tests/lib/rules/no-xpath.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use strict";
2+
3+
//------------------------------------------------------------------------------
4+
// Requirements
5+
//------------------------------------------------------------------------------
6+
7+
const rule = require("../../../lib/rules/no-xpath"),
8+
RuleTester = require("eslint").RuleTester;
9+
10+
//------------------------------------------------------------------------------
11+
// Tests
12+
//------------------------------------------------------------------------------
13+
14+
const ruleTester = new RuleTester();
15+
ruleTester.run("no-xpath", rule, {
16+
valid: [
17+
{ code: 'cy.wait("@someRequest")' },
18+
{ code: 'cy.get("button").click({force: true})' },
19+
],
20+
21+
invalid: [
22+
{
23+
code: "cy.xpath('//div[@class=\"container\"]/p[1]').click()",
24+
errors: [{ messageId: "unexpected" }],
25+
},
26+
{
27+
code: "cy.xpath('//p[1]').should('exist')",
28+
errors: [{ messageId: "unexpected" }]
29+
}
30+
],
31+
});

0 commit comments

Comments
 (0)
Please sign in to comment.