Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ These rules enforce some of the [best practices recommended for using Cypress](h
| [no-force](docs/rules/no-force.md) | disallow using `force: true` with action commands | |
| [no-pause](docs/rules/no-pause.md) | disallow using `cy.pause()` calls | |
| [no-unnecessary-waiting](docs/rules/no-unnecessary-waiting.md) | disallow waiting for arbitrary time periods | ✅ |
| [no-xpath](docs/rules/no-xpath.md) | disallow using `cy.xpath()` calls | |
| [require-data-selectors](docs/rules/require-data-selectors.md) | require `data-*` attribute selectors | |
| [unsafe-to-chain-command](docs/rules/unsafe-to-chain-command.md) | disallow actions within chains | ✅ |

Expand Down
25 changes: 25 additions & 0 deletions docs/rules/no-xpath.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Disallow using `cy.xpath()` calls (`cypress/no-xpath`)

<!-- end auto-generated rule header -->

This rule disallows the usage of `cy.xpath()` for selecting elements.

## Rule Details

Examples of **incorrect** code for this rule:

```js
cy.xpath('//div[@class=\"container\"]').click()
```

Examples of **correct** code for this rule:

```js
cy.get('[data-cy="container"]').click();
```

## Further Reading

Both `@cypress/xpath` and `cypress-xpath` are deprecated.

See [the Cypress Best Practices guide](https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements).
1 change: 1 addition & 0 deletions legacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
'no-force': require('./lib/rules/no-force'),
'no-pause': require('./lib/rules/no-pause'),
'no-debug': require('./lib/rules/no-debug'),
'no-xpath': require('./lib/rules/no-xpath'),
},
configs: {
recommended: require('./lib/config/recommended'),
Expand Down
1 change: 1 addition & 0 deletions lib/flat.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const plugin = {
'no-force': require('./rules/no-force'),
'no-pause': require('./rules/no-pause'),
'no-debug': require('./rules/no-debug'),
'no-xpath': require('./rules/no-xpath'),
},
}

Expand Down
35 changes: 35 additions & 0 deletions lib/rules/no-xpath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'disallow using `cy.xpath()` calls',
recommended: false,
url: 'https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/no-xpath.md'
},
fixable: null, // Or `code` or `whitespace`
schema: [], // Add a schema if the rule has options
messages: {
unexpected: 'Avoid using cy.xpath command',
},
},

create (context) {
return {
CallExpression (node) {
if (isCallingCyXpath(node)) {
context.report({ node, messageId: 'unexpected' })
}
},
}
},
};

function isCallingCyXpath (node) {
return node.callee.type === 'MemberExpression' &&
node.callee.object.type === 'Identifier' &&
node.callee.object.name === 'cy' &&
node.callee.property.type === 'Identifier' &&
node.callee.property.name === 'xpath'
}
30 changes: 30 additions & 0 deletions tests/lib/rules/no-xpath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/no-xpath"),
RuleTester = require("eslint").RuleTester;

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester();
ruleTester.run("no-xpath", rule, {
valid: [
{ code: 'cy.get("button").click({force: true})' },
],

invalid: [
{
code: "cy.xpath('//div[@class=\"container\"]/p[1]').click()",
errors: [{ messageId: "unexpected" }],
},
{
code: "cy.xpath('//p[1]').should('exist')",
errors: [{ messageId: "unexpected" }]
}
],
});