-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rule): add 'require-data-selectors' rule (#30)
Only allow `[data-*]` attribute selectors on `cy.get`
- Loading branch information
1 parent
7fabf07
commit a4a0e8e
Showing
4 changed files
with
96 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## Only allow `data-*` attribute selectors (require-data-selectors) | ||
only allow `cy.get` to allow selectors that target `data-*` attributes | ||
|
||
See [the Cypress Best Practices guide](https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements). | ||
|
||
> Note: If you use this rule, consider only using the `warn` error level, since using `data-*` attribute selectors may not always be possible. | ||
### Rule Details | ||
|
||
examples of **incorrect** code with `require-data-selectors`: | ||
```js | ||
cy.get(".a") | ||
cy.get('[daedta-cy=submit]').click() | ||
cy.get('[d-cy=submit]') | ||
cy.get(".btn-large").click() | ||
cy.get(".btn-.large").click() | ||
``` | ||
|
||
examples of **correct** code with `require-data-selectors`: | ||
```js | ||
cy.get('[data-cy=submit]').click() | ||
cy.get('[data-QA=submit]') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* @fileoverview Use data-* attribute selectors instead of classes or tag names | ||
* @author Sandeep Baldawa | ||
*/ | ||
'use strict' | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Use data-* attributes to provide context to your selectors and insulate them from CSS or JS changes https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements', | ||
category: 'Possible Errors', | ||
recommended: false, | ||
url: 'https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements', | ||
}, | ||
schema: [], | ||
messages: { | ||
unexpected: 'use data-* attribute selectors instead of classes or tag names', | ||
}, | ||
}, | ||
|
||
create (context) { | ||
return { | ||
CallExpression (node) { | ||
if (isCallingCyGet(node) && !isDataArgument(node)) { | ||
context.report({ node, messageId: 'unexpected' }) | ||
} | ||
}, | ||
} | ||
}, | ||
} | ||
|
||
function isCallingCyGet (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 === 'get' | ||
} | ||
|
||
function isDataArgument (node) { | ||
return node.arguments.length > 0 && | ||
node.arguments[0].type === 'Literal' && | ||
String(node.arguments[0].value).startsWith('[data-') | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
'use strict' | ||
|
||
const rule = require('../../../lib/rules/require-data-selectors') | ||
const RuleTester = require('eslint').RuleTester | ||
|
||
const ruleTester = new RuleTester() | ||
|
||
const errors = [{ messageId: 'unexpected' }] | ||
const parserOptions = { ecmaVersion: 6 } | ||
|
||
ruleTester.run('no-dynamic-id-classes', rule, { | ||
valid: [ | ||
{ code: 'cy.get(\'[data-cy=submit]\').click()', parserOptions }, | ||
{ code: 'cy.get(\'[data-QA=submit]\')', parserOptions }, | ||
{ code: 'cy.clock(5000)', parserOptions }, | ||
{ code: 'cy.scrollTo(0, 10)', parserOptions }, | ||
{ code: 'cy.tick(500)', parserOptions }, | ||
], | ||
|
||
invalid: [ | ||
{ code: 'cy.get(\'[daedta-cy=submit]\').click()', parserOptions, errors }, | ||
{ code: 'cy.get(\'[d-cy=submit]\')', parserOptions, errors }, | ||
{ code: 'cy.get(".btn-large").click()', parserOptions, errors }, | ||
{ code: 'cy.get(".btn-.large").click()', parserOptions, errors }, | ||
{ code: 'cy.get(".a")', parserOptions, errors }, | ||
], | ||
}) |