eslint-plugin-cypress 2.10.3 → 2.11.3

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
@@ -9,6 +9,10 @@ Note: If you installed ESLint globally then you must also install `eslint-plugin
9
9
  ```sh
10
10
  npm install eslint-plugin-cypress --save-dev
11
11
  ```
12
+ or
13
+ ```sh
14
+ yarn add eslint-plugin-cypress --dev
15
+ ```
12
16
 
13
17
  ## Usage
14
18
 
@@ -30,12 +34,13 @@ You can add rules:
30
34
  "cypress/no-assigning-return-values": "error",
31
35
  "cypress/no-unnecessary-waiting": "error",
32
36
  "cypress/assertion-before-screenshot": "warn",
33
- "cypress/no-force": "warn"
37
+ "cypress/no-force": "warn",
38
+ "cypress/no-async-tests": "error"
34
39
  }
35
40
  }
36
41
  ```
37
42
 
38
- You can whitelist globals provided by Cypress:
43
+ You can allow certain globals provided by Cypress:
39
44
 
40
45
  ```json
41
46
  {
@@ -57,6 +62,51 @@ Use the recommended configuration and you can forego configuring _plugins_, _rul
57
62
  }
58
63
  ```
59
64
 
65
+ ## Disable rules
66
+
67
+ You can disable specific rules per file, for a portion of a file, or for a single line.
68
+
69
+ Disable the `cypress/no-unnecessary-waiting` rule for the entire file by placing this at the start of the file:
70
+
71
+ ```js
72
+ /* eslint-disable cypress/no-unnecessary-waiting */
73
+ ```
74
+
75
+ Disable the `cypress/no-unnecessary-waiting` rule for a portion of the file:
76
+
77
+ ```js
78
+ it('waits for a second', () => {
79
+ ...
80
+ /* eslint-disable cypress/no-unnecessary-waiting */
81
+ cy.wait(1000)
82
+ /* eslint-enable cypress/no-unnecessary-waiting */
83
+ ...
84
+ })
85
+ ```
86
+
87
+ Disable the `cypress/no-unnecessary-waiting` rule for a specific line:
88
+
89
+ ```js
90
+ it('waits for a second', () => {
91
+ ...
92
+ cy.wait(1000) // eslint-disable-line cypress/no-unnecessary-waiting
93
+ ...
94
+ })
95
+ ```
96
+
97
+ You can also disable a rule for the next line:
98
+
99
+ ```js
100
+ it('waits for a second', () => {
101
+ ...
102
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
103
+ cy.wait(1000)
104
+ ...
105
+ })
106
+ ```
107
+
108
+ For more, see the [ESLint rules](https://eslint.org/docs/user-guide/configuring/rules) documentation.
109
+
60
110
  ## Rules
61
111
 
62
112
  These rules enforce some of the [best practices recommended for using Cypress](https://on.cypress.io/best-practices).
@@ -69,7 +119,8 @@ Rules with a check mark (✅) are enabled by default while using the `plugin:cyp
69
119
  | :-- | :------------------------------------------------------------------------- | :-------------------------------------------------------------- |
70
120
  | ✅ | [no-assigning-return-values](./docs/rules/no-assigning-return-values.md) | Prevent assigning return values of cy calls |
71
121
  | ✅ | [no-unnecessary-waiting](./docs/rules/no-unnecessary-waiting.md) | Prevent waiting for arbitrary time periods |
72
- | | [no-force](./docs/rules/no-force.md) | Disallow using `force: true` with action commands |
122
+ | ✅ | [no-async-tests](./docs/rules/no-async-tests.md) | Prevent using async/await in Cypress test case |
123
+ | | [no-force](./docs/rules/no-force.md) | Disallow using `force: true` with action commands |
73
124
  | | [assertion-before-screenshot](./docs/rules/assertion-before-screenshot.md) | Ensure screenshots are preceded by an assertion |
74
125
  | | [require-data-selectors](./docs/rules/require-data-selectors.md) | Only allow data-\* attribute selectors (require-data-selectors) |
75
126
 
package/circle.yml CHANGED
@@ -1,13 +1,26 @@
1
- version: 2
1
+ version: 2.1
2
2
 
3
3
  workflows:
4
- version: 2
5
- tests:
4
+ version: 2.1
5
+ main:
6
6
  jobs:
7
- - test
7
+ - lint
8
+ - test-v4
9
+ - test-v5
10
+ - test-v6
11
+ - release:
12
+ requires:
13
+ - lint
14
+ - test-v4
15
+ - test-v5
16
+ - test-v6
17
+ filters:
18
+ branches:
19
+ only:
20
+ - master
8
21
 
9
22
  jobs:
10
- test:
23
+ lint:
11
24
  docker:
12
25
  - image: circleci/node:8
13
26
  steps:
@@ -18,9 +31,51 @@ jobs:
18
31
  - run:
19
32
  name: Lint code
20
33
  command: npm run lint
34
+
35
+ test-v4:
36
+ docker:
37
+ - image: circleci/node:8
38
+ steps:
39
+ - checkout
40
+ - run:
41
+ name: Install dependencies
42
+ command: npm install
43
+ - run:
44
+ name: Test ESLint 4
45
+ command: npm run test:v4
46
+
47
+ test-v5:
48
+ docker:
49
+ - image: circleci/node:8
50
+ steps:
51
+ - checkout
52
+ - run:
53
+ name: Install dependencies
54
+ command: npm install
21
55
  - run:
22
- name: Run tests
23
- command: npm test
56
+ name: Test ESLint 5
57
+ command: npm run test
58
+
59
+ test-v6:
60
+ docker:
61
+ - image: circleci/node:8
62
+ steps:
63
+ - checkout
64
+ - run:
65
+ name: Install dependencies
66
+ command: npm install
67
+ - run:
68
+ name: Test ESLint 6
69
+ command: npm run test:v6
70
+
71
+ release:
72
+ docker:
73
+ - image: circleci/node:8
74
+ steps:
75
+ - checkout
76
+ - run:
77
+ name: Install dependencies
78
+ command: npm install
24
79
  - run:
25
- name: Semantic release
26
- command: npm run semantic-release || true
80
+ name: Run semantic release
81
+ command: npm run semantic-release
@@ -0,0 +1,52 @@
1
+ # Prevent using async/await in Cypress test cases (no-async-tests)
2
+
3
+ Cypress tests [that return a promise will error](https://docs.cypress.io/guides/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. An `async` function returns a promise under the hood, so a test using an `async` function will also error.
4
+
5
+ ## Rule Details
6
+
7
+ This rule disallows using `async` test functions.
8
+
9
+ Examples of **incorrect** code for this rule:
10
+
11
+ ```js
12
+ describe('my feature', () => {
13
+ it('my test case', async () => {
14
+ await cy.get('.myClass')
15
+ // other operations
16
+ })
17
+ })
18
+ ```
19
+
20
+ ```js
21
+ describe('my feature', () => {
22
+ it('my test case', async () => {
23
+ cy
24
+ .get('.myClass')
25
+ .click()
26
+
27
+ await someAsyncFunction()
28
+ })
29
+ })
30
+ ```
31
+
32
+ Examples of **correct** code for this rule:
33
+
34
+ ```js
35
+ describe('my feature', () => {
36
+ it('my test case', () => {
37
+ cy.get('.myClass')
38
+ // other operations
39
+ })
40
+ })
41
+
42
+ ```
43
+
44
+ ## When Not To Use It
45
+
46
+ 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).
47
+
48
+ ## Further Reading
49
+
50
+ - [Commands Are Asynchronous](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)
51
+ - [Commands Are Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Promises)
52
+ - [Commands Are Not Promises](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Not-Promises)
package/index.js CHANGED
@@ -4,6 +4,7 @@ module.exports = {
4
4
  rules: {
5
5
  'no-assigning-return-values': require('./lib/rules/no-assigning-return-values'),
6
6
  'no-unnecessary-waiting': require('./lib/rules/no-unnecessary-waiting'),
7
+ 'no-async-tests': require('./lib/rules/no-async-tests'),
7
8
  'assertion-before-screenshot': require('./lib/rules/assertion-before-screenshot'),
8
9
  'require-data-selectors': require('./lib/rules/require-data-selectors'),
9
10
  'no-force': require('./lib/rules/no-force'),
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ const { defaults } = require('jest-config')
2
+
3
+ module.exports = {
4
+ testMatch: ['**/tests/**/*.[jt]s?(x)'],
5
+ testPathIgnorePatterns: [...defaults.testPathIgnorePatterns, '.history'],
6
+ }
@@ -8,5 +8,6 @@ module.exports = {
8
8
  rules: {
9
9
  'cypress/no-assigning-return-values': 'error',
10
10
  'cypress/no-unnecessary-waiting': 'error',
11
+ 'cypress/no-async-tests': 'error',
11
12
  },
12
13
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * @fileoverview Assert on the page state before taking a screenshot, so the screenshot is consistent
3
- * @author Luke Page
4
- */
5
-
6
1
  'use strict'
7
2
 
8
3
  const assertionCommands = [
@@ -17,7 +12,7 @@ const assertionCommands = [
17
12
  // not an assertion, but unlikely to require waiting for render
18
13
  'scrollIntoView',
19
14
  'scrollTo',
20
- ];
15
+ ]
21
16
 
22
17
  module.exports = {
23
18
  meta: {
@@ -42,19 +37,22 @@ module.exports = {
42
37
  },
43
38
  }
44
39
 
45
- function isRootCypress(node) {
46
- while(node.type === 'CallExpression') {
40
+ function isRootCypress (node) {
41
+ while (node.type === 'CallExpression') {
47
42
  if (node.callee.type !== 'MemberExpression') return false
43
+
48
44
  if (node.callee.object.type === 'Identifier' &&
49
45
  node.callee.object.name === 'cy') {
50
46
  return true
51
47
  }
48
+
52
49
  node = node.callee.object
53
50
  }
51
+
54
52
  return false
55
53
  }
56
54
 
57
- function getPreviousInChain(node) {
55
+ function getPreviousInChain (node) {
58
56
  return node.type === 'CallExpression' &&
59
57
  node.callee.type === 'MemberExpression' &&
60
58
  node.callee.object.type === 'CallExpression' &&
@@ -63,7 +61,7 @@ function getPreviousInChain(node) {
63
61
  node.callee.object.callee.property.name
64
62
  }
65
63
 
66
- function getCallExpressionCypressCommand(node) {
64
+ function getCallExpressionCypressCommand (node) {
67
65
  return isRootCypress(node) &&
68
66
  node.callee.property.type === 'Identifier' &&
69
67
  node.callee.property.name
@@ -73,14 +71,14 @@ function isCallingCyScreenshot (node) {
73
71
  return getCallExpressionCypressCommand(node) === 'screenshot'
74
72
  }
75
73
 
76
- function getPreviousCypressCommand(node) {
74
+ function getPreviousCypressCommand (node) {
77
75
  const previousInChain = getPreviousInChain(node)
78
76
 
79
77
  if (previousInChain) {
80
78
  return previousInChain
81
79
  }
82
80
 
83
- while(node.parent && !node.parent.body) {
81
+ while (node.parent && !node.parent.body) {
84
82
  node = node.parent
85
83
  }
86
84
 
@@ -93,18 +91,20 @@ function getPreviousCypressCommand(node) {
93
91
  // in the case of a function declaration it won't be found
94
92
  if (index < 0) return null
95
93
 
96
- if (index === 0) return getPreviousCypressCommand(node.parent);
94
+ if (index === 0) return getPreviousCypressCommand(node.parent)
97
95
 
98
96
  const previousStatement = body[index - 1]
99
97
 
100
98
  if (previousStatement.type !== 'ExpressionStatement' ||
101
- previousStatement.expression.type !== 'CallExpression')
99
+ previousStatement.expression.type !== 'CallExpression') {
102
100
  return null
101
+ }
103
102
 
104
103
  return getCallExpressionCypressCommand(previousStatement.expression)
105
104
  }
106
105
 
107
106
  function isPreviousAnAssertion (node) {
108
107
  const previousCypressCommand = getPreviousCypressCommand(node)
108
+
109
109
  return assertionCommands.indexOf(previousCypressCommand) >= 0
110
110
  }
@@ -1,18 +1,17 @@
1
- /**
2
- * @fileoverview Prevent assigning return value of cy calls
3
- * @author Elad Shahar
4
- */
5
-
6
1
  'use strict'
7
2
 
8
3
  // safely get nested object property
9
4
  function get (obj, propertyString = '') {
10
5
  const properties = propertyString.split('.')
6
+
11
7
  for (let i = 0; i < properties.length; i++) {
12
8
  const value = (obj || {})[properties[i]]
9
+
13
10
  if (value == null) return value
11
+
14
12
  obj = value
15
13
  }
14
+
16
15
  return obj
17
16
  }
18
17
 
@@ -40,7 +39,7 @@ module.exports = {
40
39
  },
41
40
  }
42
41
 
43
- const whitelistedCommands = {
42
+ const allowedCommands = {
44
43
  now: true,
45
44
  spy: true,
46
45
  state: true,
@@ -57,9 +56,12 @@ function isCypressCommandDeclaration (declarator) {
57
56
 
58
57
  if (!object) return
59
58
  }
59
+
60
60
  const commandName = get(declarator, 'init.callee.property.name')
61
61
 
62
- if (commandName && whitelistedCommands[commandName]) return
62
+ const parent = get(object, 'parent.property.name') || get(declarator, 'id.name')
63
+
64
+ if (commandName && (allowedCommands[commandName] || allowedCommands[parent])) return
63
65
 
64
66
  return object.name === 'cy'
65
67
  }
@@ -0,0 +1,47 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ meta: {
5
+ docs: {
6
+ description: 'Prevent using async/await in Cypress test cases',
7
+ category: 'Possible Errors',
8
+ recommended: true,
9
+ },
10
+ messages: {
11
+ unexpected: 'Avoid using async functions with Cypress tests',
12
+ },
13
+ },
14
+
15
+ create (context) {
16
+ function isTestBlock (callExpressionNode) {
17
+ const { type, name } = callExpressionNode.callee
18
+
19
+ return type === 'Identifier'
20
+ && name === 'it' || name === 'test'
21
+ }
22
+
23
+ function isTestAsync (node) {
24
+ return node.arguments
25
+ && node.arguments.length >= 2
26
+ && node.arguments[1].async === true
27
+ }
28
+
29
+ return {
30
+ Identifier (node) {
31
+ if (node.name === 'cy' || node.name === 'Cypress') {
32
+ const ancestors = context.getAncestors()
33
+ const asyncTestBlocks = ancestors
34
+ .filter((n) => n.type === 'CallExpression')
35
+ .filter(isTestBlock)
36
+ .filter(isTestAsync)
37
+
38
+ if (asyncTestBlocks.length >= 1) {
39
+ asyncTestBlocks.forEach((node) => {
40
+ context.report({ node, messageId: 'unexpected' })
41
+ })
42
+ }
43
+ }
44
+ },
45
+ }
46
+ },
47
+ }
@@ -1,8 +1,3 @@
1
- /**
2
- * @fileoverview Disallow using of \'force: true\' option for click and type calls
3
- * @author Alex Kuznetsov
4
- */
5
-
6
1
  'use strict'
7
2
 
8
3
  //------------------------------------------------------------------------------
@@ -47,7 +42,7 @@ module.exports = {
47
42
 
48
43
  return node.arguments && node.arguments.length &&
49
44
  node.arguments.some((arg) => {
50
- return arg.type === 'ObjectExpression' && arg.properties.some((propNode) => propNode.key.name === 'force')
45
+ return arg.type === 'ObjectExpression' && arg.properties.some((propNode) => propNode.key && propNode.key.name === 'force')
51
46
  })
52
47
  }
53
48
 
@@ -1,8 +1,3 @@
1
- /**
2
- * @fileoverview Prevent waiting for arbitrary time periods
3
- * @author Elad Shahar
4
- */
5
-
6
1
  'use strict'
7
2
 
8
3
  module.exports = {
@@ -61,7 +56,8 @@ function isIdentifierNumberConstArgument (node, scope) {
61
56
 
62
57
  if (node.arguments[0].type !== 'Identifier') return false
63
58
 
64
- const resolvedIdentifier = scope.resolve(node.arguments[0]).resolved
59
+ const identifier = node.arguments[0]
60
+ const resolvedIdentifier = scope.references.find((ref) => ref.identifier === identifier).resolved
65
61
  const definition = resolvedIdentifier.defs[0]
66
62
  const isVariable = definition.type === 'Variable'
67
63
 
@@ -1,7 +1,3 @@
1
- /**
2
- * @fileoverview Use data-* attribute selectors instead of classes or tag names
3
- * @author Sandeep Baldawa
4
- */
5
1
  'use strict'
6
2
 
7
3
  module.exports = {
@@ -40,7 +36,13 @@ function isCallingCyGet (node) {
40
36
  function isDataArgument (node) {
41
37
  return node.arguments.length > 0 &&
42
38
  (
43
- (node.arguments[0].type === 'Literal' && String(node.arguments[0].value).startsWith('[data-')) ||
44
- (node.arguments[0].type === 'TemplateLiteral' && String(node.arguments[0].quasis[0].value.cooked).startsWith('[data-'))
39
+ (node.arguments[0].type === 'Literal' && isAliasOrDataSelector(String(node.arguments[0].value))) ||
40
+ (node.arguments[0].type === 'TemplateLiteral' && isAliasOrDataSelector(String(node.arguments[0].quasis[0].value.cooked)))
45
41
  )
46
42
  }
43
+
44
+ function isAliasOrDataSelector (selector) {
45
+ return ['[data-', '@'].some(function (validValue) {
46
+ return selector.startsWith(validValue)
47
+ })
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-cypress",
3
- "version": "2.10.3",
3
+ "version": "2.11.3",
4
4
  "description": "An ESLint plugin for projects using Cypress",
5
5
  "main": "index.js",
6
6
  "author": "Chris Breiding (chris@cypress.io)",
@@ -35,10 +35,13 @@
35
35
  },
36
36
  "scripts": {
37
37
  "precommit": "npm run lint",
38
- "lint": "eslint *.js",
38
+ "lint": "eslint '*.js' '**/**/*.js'",
39
+ "lint-fix": "npm run lint -- --fix",
39
40
  "semantic-release": "semantic-release",
40
41
  "start": "yarn run test-watch",
41
42
  "test": "jest",
43
+ "test:v4": "npm i eslint@4.x && npm run test",
44
+ "test:v6": "npm i eslint@6.x && npm run test",
42
45
  "test-watch": "jest --watchAll"
43
46
  },
44
47
  "jest": {
package/tests/config.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* global describe, it, expect */
1
2
  'use strict'
2
3
 
3
4
  const globals = require('globals')
@@ -9,17 +10,17 @@ describe('environments globals', () => {
9
10
  it('should not mutate globals', () => {
10
11
  expect(globals.browser).not.toHaveProperty('cy')
11
12
  expect(globals.mocha).not.toHaveProperty('cy')
12
- });
13
+ })
13
14
 
14
15
  it('should include other globals', () => {
15
16
  expect(env.globals).toEqual(expect.objectContaining(globals.browser))
16
17
  expect(env.globals).toEqual(expect.objectContaining(globals.mocha))
17
- });
18
+ })
18
19
 
19
20
  it('should include cypress globals', () => {
20
21
  expect(env.globals).toEqual(expect.objectContaining({
21
22
  cy: false,
22
23
  Cypress: false,
23
24
  }))
24
- });
25
+ })
25
26
  })
@@ -16,6 +16,7 @@ ruleTester.run('no-assigning-return-values', rule, {
16
16
  { code: 'const foo = bar();', parserOptions },
17
17
  { code: 'const foo = bar().baz();', parserOptions },
18
18
  { code: 'const spy = cy.spy();', parserOptions },
19
+ { code: 'const spy = cy.spy().as();', parserOptions },
19
20
  { code: 'const stub = cy.stub();', parserOptions },
20
21
  { code: 'const result = cy.now();', parserOptions },
21
22
  { code: 'const state = cy.state();', parserOptions },
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ const rule = require('../../../lib/rules/no-async-tests')
4
+ const RuleTester = require('eslint').RuleTester
5
+
6
+ const ruleTester = new RuleTester()
7
+
8
+ const errors = [{ messageId: 'unexpected' }]
9
+ // async functions are an ES2017 feature
10
+ const parserOptions = { ecmaVersion: 8 }
11
+
12
+ ruleTester.run('no-async-tests', rule, {
13
+ valid: [
14
+ { code: 'it(\'a test case\', () => { cy.get(\'.someClass\'); })', parserOptions },
15
+ { code: 'it(\'a test case\', async () => { await somethingAsync(); })', parserOptions },
16
+ { code: 'async function nonTestFn () { return await somethingAsync(); }', parserOptions },
17
+ { code: 'const nonTestArrowFn = async () => { await somethingAsync(); }', parserOptions },
18
+ ],
19
+ invalid: [
20
+ { code: 'it(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
21
+ { code: 'test(\'a test case\', async () => { cy.get(\'.someClass\'); })', parserOptions, errors },
22
+ { code: 'it(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
23
+ { code: 'test(\'a test case\', async function () { cy.get(\'.someClass\'); })', parserOptions, errors },
24
+ ],
25
+ })
@@ -9,7 +9,7 @@ const rule = require('../../../lib/rules/no-force')
9
9
  const RuleTester = require('eslint').RuleTester
10
10
 
11
11
  const errors = [{ messageId: 'unexpected' }]
12
- const parserOptions = { ecmaVersion: 6 }
12
+ const parserOptions = { ecmaVersion: 2018 }
13
13
 
14
14
  //------------------------------------------------------------------------------
15
15
  // Tests
@@ -24,12 +24,13 @@ ruleTester.run('no-force', rule, {
24
24
  { code: `cy.get('button').click({multiple: true})`, parserOptions },
25
25
  { code: `cy.get('button').dblclick()`, parserOptions },
26
26
  { code: `cy.get('input').type('somth')`, parserOptions },
27
- { code: `cy.get('input').type('somth', {anyoption: true})`, parserOptions, errors },
28
- { code: `cy.get('input').trigger('click', {anyoption: true})`, parserOptions, errors },
29
- { code: `cy.get('input').rightclick({anyoption: true})`, parserOptions, errors },
30
- { code: `cy.get('input').check()`, parserOptions, errors },
31
- { code: `cy.get('input').select()`, parserOptions, errors },
32
- { code: `cy.get('input').focus()`, parserOptions, errors },
27
+ { code: `cy.get('input').type('somth', {anyoption: true})`, parserOptions },
28
+ { code: `cy.get('input').trigger('click', {anyoption: true})`, parserOptions },
29
+ { code: `cy.get('input').rightclick({anyoption: true})`, parserOptions },
30
+ { code: `cy.get('input').check()`, parserOptions },
31
+ { code: `cy.get('input').select()`, parserOptions },
32
+ { code: `cy.get('input').focus()`, parserOptions },
33
+ { code: `cy.document().trigger("keydown", { ...event })`, parserOptions },
33
34
  ],
34
35
 
35
36
  invalid: [
@@ -26,6 +26,29 @@ ruleTester.run('no-unnecessary-waiting', rule, {
26
26
  { code: 'const customWait = (alias = "@someRequest") => { cy.wait(alias) }', parserOptions, errors },
27
27
  { code: 'function customWait (ms) { cy.wait(ms) }', parserOptions, errors },
28
28
  { code: 'const customWait = (ms) => { cy.wait(ms) }', parserOptions, errors },
29
+
30
+ // disable the eslint rule
31
+ {
32
+ code: `
33
+ cy.wait(100); // eslint-disable-line no-unnecessary-waiting
34
+ `,
35
+ parserOptions,
36
+ },
37
+ {
38
+ code: `
39
+ /* eslint-disable-next-line no-unnecessary-waiting */
40
+ cy.wait(100)
41
+ `,
42
+ parserOptions,
43
+ },
44
+ {
45
+ code: `
46
+ /* eslint-disable no-unnecessary-waiting */
47
+ cy.wait(100)
48
+ /* eslint-enable no-unnecessary-waiting */
49
+ `,
50
+ parserOptions,
51
+ },
29
52
  ],
30
53
 
31
54
  invalid: [
@@ -16,6 +16,8 @@ ruleTester.run('require-data-selectors', rule, {
16
16
  { code: 'cy.scrollTo(0, 10)', parserOptions },
17
17
  { code: 'cy.tick(500)', parserOptions },
18
18
  { code: 'cy.get(\`[data-cy=${1}]\`)', parserOptions },
19
+ { code: 'cy.get("@my-alias")', parserOptions, errors },
20
+ { code: 'cy.get(`@my-alias`)', parserOptions, errors },
19
21
  ],
20
22
 
21
23
  invalid: [