Skip to content

Commit

Permalink
Merge branch 'master' into no-unnecessary-waiting-support-import-bind…
Browse files Browse the repository at this point in the history
…ings
  • Loading branch information
emilyrohrbough committed Apr 10, 2023
2 parents 58ae363 + 402c59a commit bd3bc83
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 2 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/add-issue-triage-board.yml
@@ -0,0 +1,12 @@
name: 'Add issue/PR to Triage Board'
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
add-to-triage-project-board:
uses: cypress-io/cypress/.github/workflows/triage_add_to_project.yml@develop
secrets: inherit
9 changes: 9 additions & 0 deletions .github/workflows/triage_closed_issue_comment.yml
@@ -0,0 +1,9 @@
name: 'Handle Comment Workflow'
on:
issue_comment:
types:
- created
jobs:
closed-issue-comment:
uses: cypress-io/cypress/.github/workflows/triage_handle_new_comments.yml@develop
secrets: inherit
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -73,7 +73,7 @@ Disable the `cypress/no-unnecessary-waiting` rule for the entire file by placing
/* eslint-disable cypress/no-unnecessary-waiting */
```

Disable the `cypress/no-unnecessary-waiting` rule for a portion of the file:
Disable the `cypress/no-unnecessary-waiting` rule for only a portion of the file:

```js
it('waits for a second', () => {
Expand Down Expand Up @@ -121,6 +121,7 @@ Rules with a check mark (✅) are enabled by default while using the `plugin:cyp
|| [no-assigning-return-values](./docs/rules/no-assigning-return-values.md) | Prevent assigning return values of cy calls |
|| [no-unnecessary-waiting](./docs/rules/no-unnecessary-waiting.md) | Prevent waiting for arbitrary time periods |
|| [no-async-tests](./docs/rules/no-async-tests.md) | Prevent using async/await in Cypress test case |
|| [unsafe-to-chain-command](./docs/rules/unsafe-to-chain-command.md) | Prevent chaining from unsafe to chain commands |
| | [no-force](./docs/rules/no-force.md) | Disallow using `force: true` with action commands |
| | [assertion-before-screenshot](./docs/rules/assertion-before-screenshot.md) | Ensure screenshots are preceded by an assertion |
| | [require-data-selectors](./docs/rules/require-data-selectors.md) | Only allow data-\* attribute selectors (require-data-selectors) |
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/no-unnecessary-waiting.md
@@ -1,3 +1,3 @@
## No Assigning Return Values
## No Unnecessary Waiting

See [the Cypress Best Practices guide](https://on.cypress.io/best-practices#Unnecessary-Waiting).
3 changes: 3 additions & 0 deletions docs/rules/unsafe-to-chain-command.md
@@ -0,0 +1,3 @@
## Unsafe to chain command

See [retry-ability guide](https://docs.cypress.io/guides/core-concepts/retry-ability#Actions-should-be-at-the-end-of-chains-not-the-middle).
1 change: 1 addition & 0 deletions index.js
Expand Up @@ -3,6 +3,7 @@ const globals = require('globals')
module.exports = {
rules: {
'no-assigning-return-values': require('./lib/rules/no-assigning-return-values'),
'unsafe-to-chain-command': require('./lib/rules/unsafe-to-chain-command'),
'no-unnecessary-waiting': require('./lib/rules/no-unnecessary-waiting'),
'no-async-tests': require('./lib/rules/no-async-tests'),
'assertion-before-screenshot': require('./lib/rules/assertion-before-screenshot'),
Expand Down
1 change: 1 addition & 0 deletions lib/config/recommended.js
Expand Up @@ -9,5 +9,6 @@ module.exports = {
'cypress/no-assigning-return-values': 'error',
'cypress/no-unnecessary-waiting': 'error',
'cypress/no-async-tests': 'error',
'cypress/unsafe-to-chain-command': 'error',
},
}
47 changes: 47 additions & 0 deletions lib/rules/unsafe-to-chain-command.js
@@ -0,0 +1,47 @@
'use strict'

module.exports = {
meta: {
docs: {
description: 'Actions should be in the end of chains, not in the middle',
category: 'Possible Errors',
recommended: true,
url: 'https://docs.cypress.io/guides/core-concepts/retry-ability#Actions-should-be-at-the-end-of-chains-not-the-middle',
},
schema: [],
messages: {
unexpected: 'It is unsafe to chain further commands that rely on the subject after this command. It is best to split the chain, chaining again from `cy.` in a next command line.',
},
},
create (context) {
return {
CallExpression (node) {
if (isRootCypress(node) && isActionUnsafeToChain(node) && node.parent.type === 'MemberExpression') {
context.report({ node, messageId: 'unexpected' })
}
},
}
},
}

function isRootCypress (node) {
while (node.type === 'CallExpression') {
if (node.callee.type !== 'MemberExpression') return false

if (node.callee.object.type === 'Identifier' &&
node.callee.object.name === 'cy') {
return true
}

node = node.callee.object
}

return false
}

function isActionUnsafeToChain (node) {
// commands listed in the documentation with text: 'It is unsafe to chain further commands that rely on the subject after xxx'
const unsafeToChainActions = ['blur', 'clear', 'click', 'check', 'dblclick', 'each', 'focus', 'rightclick', 'screenshot', 'scrollIntoView', 'scrollTo', 'select', 'selectFile', 'spread', 'submit', 'type', 'trigger', 'uncheck', 'within']

return node.callee && node.callee.property && node.callee.property.type === 'Identifier' && unsafeToChainActions.includes(node.callee.property.name)
}
20 changes: 20 additions & 0 deletions tests/lib/rules/unsafe-to-chain-command.js
@@ -0,0 +1,20 @@
'use strict'

const rule = require('../../../lib/rules/unsafe-to-chain-command')
const RuleTester = require('eslint').RuleTester

const ruleTester = new RuleTester()

const errors = [{ messageId: 'unexpected' }]
const parserOptions = { ecmaVersion: 6 }

ruleTester.run('action-ends-chain', rule, {
valid: [
{ code: 'cy.get("new-todo").type("todo A{enter}"); cy.get("new-todo").type("todo B{enter}"); cy.get("new-todo").should("have.class", "active");', parserOptions },
],

invalid: [
{ code: 'cy.get("new-todo").type("todo A{enter}").should("have.class", "active");', parserOptions, errors },
{ code: 'cy.get("new-todo").type("todo A{enter}").type("todo B{enter}");', parserOptions, errors },
],
})

0 comments on commit bd3bc83

Please sign in to comment.