Skip to content

Commit

Permalink
Merge branch 'master' into fix/issue-with-unsafe-to-chain-command-tha…
Browse files Browse the repository at this point in the history
…t-is-not-action
  • Loading branch information
gkorakas-eli committed May 1, 2024
2 parents b400d55 + 7fe8a49 commit 8821de0
Show file tree
Hide file tree
Showing 31 changed files with 13,583 additions and 19,642 deletions.
30 changes: 30 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
"env": {
"node": true,
"es6": true
},
"plugins": [
"eslint-plugin",
"n",
"mocha"
],
"extends": [
"eslint:recommended",
"plugin:eslint-plugin/recommended",
"plugin:n/recommended",
"plugin:mocha/recommended"
],
"rules": {
"eslint-plugin/require-meta-docs-url":
["error", { "pattern": "https://github.com/cypress-io/eslint-plugin-cypress/blob/master/docs/rules/{{name}}.md" }],
"eslint-plugin/require-meta-docs-description": "error",
"n/no-extraneous-require":
["error", { "allowModules": ["jest-config"] }],
"no-redeclare": "off",
"mocha/no-mocha-arrows": "off",
"mocha/no-setup-in-describe": "off"
},
"parserOptions": {
"ecmaVersion": 2020
}
}
8 changes: 0 additions & 8 deletions .eslintrc.json

This file was deleted.

1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run lint
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.12.2
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.12.2
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Contributing to cypress-io/eslint-plugin-cypress

Thanks for taking the time to contribute! :smile:

To add a new rule:
* Fork and clone this repository
* Generate a new rule (a [yeoman generator](https://github.com/eslint/generator-eslint) is available)
* Write test scenarios then implement logic
* Describe the rule in the generated `docs` file
* Run `npm test` to run [Jest](https://jestjs.io/) or
* Run `npm start` to run [Jest](https://jestjs.io/) in [watchAll](https://jestjs.io/docs/cli#--watchall) mode where it remains active and reruns when source changes are made
* Make sure all tests are passing
* Add the rule to the [README](README.md) file
* Create a PR

Use the following commit message conventions: https://github.com/semantic-release/semantic-release#commit-message-format
83 changes: 59 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Note: If you installed ESLint globally then you must also install `eslint-plugin

## Installation

Prerequisites: [ESLint](https://www.npmjs.com/package/eslint) `v7` or `v8`. ESLint `v9` is **not** supported yet.

```sh
npm install eslint-plugin-cypress --save-dev
```
Expand Down Expand Up @@ -36,6 +38,7 @@ You can add rules:
"cypress/assertion-before-screenshot": "warn",
"cypress/no-force": "warn",
"cypress/no-async-tests": "error",
"cypress/no-async-before": "error",
"cypress/no-pause": "error"
}
}
Expand Down Expand Up @@ -112,20 +115,62 @@ For more, see the [ESLint rules](https://eslint.org/docs/user-guide/configuring/

These rules enforce some of the [best practices recommended for using Cypress](https://on.cypress.io/best-practices).

Rules with a check mark (✅) are enabled by default while using the `plugin:cypress/recommended` config.
<!-- begin auto-generated rules list -->

💼 Configurations enabled in.\
✅ Set in the `recommended` configuration.

| Name | Description | 💼 |
| :----------------------------------------------------------------------- | :--------------------------------------------------------- | :- |
| [assertion-before-screenshot](docs/rules/assertion-before-screenshot.md) | require screenshots to be preceded by an assertion | |
| [no-assigning-return-values](docs/rules/no-assigning-return-values.md) | disallow assigning return values of `cy` calls ||
| [no-async-before](docs/rules/no-async-before.md) | disallow using `async`/`await` in Cypress `before` methods | |
| [no-async-tests](docs/rules/no-async-tests.md) | disallow using `async`/`await` in Cypress test cases ||
| [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 ||
| [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 ||

<!-- end auto-generated rules list -->

## Mocha and Chai

Cypress is built on top of [Mocha](https://on.cypress.io/guides/references/bundled-libraries#Mocha) and [Chai](https://on.cypress.io/guides/references/bundled-libraries#Chai). See the following sections for information on using ESLint plugins [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-chai-friendly](https://www.npmjs.com/package/eslint-plugin-chai-friendly) together with `eslint-plugin-cypress`.

## Mocha `.only` and `.skip`

During test spec development, [Mocha exclusive tests](https://mochajs.org/#exclusive-tests) `.only` or [Mocha inclusive tests](https://mochajs.org/#inclusive-tests) `.skip` may be used to control which tests are executed, as described in the Cypress documentation [Excluding and Including Tests](https://on.cypress.io/guides/core-concepts/writing-and-organizing-tests#Excluding-and-Including-Tests). To apply corresponding rules, you can install and use [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha). The rule [mocha/no-exclusive-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-exclusive-tests.md) detects the use of `.only` and the [mocha/no-skipped-tests](https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/no-skipped-tests.md) rule detects the use of `.skip`:

```sh
npm install --save-dev eslint-plugin-mocha
```

In your `.eslintrc.json`:

```json
{
"plugins": [
"cypress",
"mocha"
],
"rules": {
"mocha/no-exclusive-tests": "warn",
"mocha/no-skipped-tests": "warn"
}
}
```

**NOTE**: These rules currently require eslint 5.0 or greater. If you would like support added for eslint 4.x, please 👍 [this issue](https://github.com/cypress-io/eslint-plugin-cypress/issues/14).
Or you can simply use the `cypress/recommended` and `mocha/recommended` configurations together, for example:

| | Rule ID | Description |
| :-- | :------------------------------------------------------------------------- | :-------------------------------------------------------------- |
|| [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) |
| | [no-pause](./docs/rules/no-pause.md) | Disallow `cy.pause()` parent command |
```json
{
"extends": [
"plugin:cypress/recommended",
"plugin:mocha/recommended"
]
}
```

## Chai and `no-unused-expressions`

Expand Down Expand Up @@ -158,16 +203,6 @@ Or you can simply add its `recommended` config:
}
```

## Contribution Guide

To add a new rule:
* Fork and clone this repository
* Generate a new rule (a [yeoman generator](https://github.com/eslint/generator-eslint) is available)
* Run `yarn start` or `npm start`
* Write test scenarios then implement logic
* Describe the rule in the generated `docs` file
* Make sure all tests are passing
* Add the rule to this README
* Create a PR
## Contributing

Use the following commit message conventions: https://github.com/semantic-release/semantic-release#commit-message-format
Please see our [Contributing Guideline](./CONTRIBUTING.md) which explains how to contribute rules or other fixes and features to the repo.
64 changes: 34 additions & 30 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ workflows:
main:
jobs:
- lint
- test-v4
- test-v5
- test-v6
- test-v7
- test-v8
- release:
requires:
- lint
- test-v4
- test-v5
- test-v6
- test-v7
- test-v8
filters:
branches:
only:
Expand All @@ -22,60 +20,66 @@ workflows:
jobs:
lint:
docker:
- image: circleci/node:16
- image: cimg/node:20.12.2
steps:
- checkout
- run:
name: Install dependencies
command: npm install
command: npm ci
- run:
name: Show ESLint version
command: npx eslint --version
- run:
name: Lint code
command: npm run lint

test-v4:
test-v7:
docker:
- image: circleci/node:16
- image: cimg/node:20.12.2
steps:
- checkout
- run:
name: Install dependencies
command: npm install
command: npm ci
- run:
name: Test ESLint 4
command: npm run test:v4

test-v5:
docker:
- image: circleci/node:16
steps:
- checkout
name: Remove unneeded plugins # minimum eslint@8.23.0 required
command: npm uninstall eslint-plugin-eslint-plugin eslint-plugin-n
- run:
name: Install dependencies
command: npm install
name: Install ESLint 7
command: npm install eslint@7
- run:
name: Show ESLint version
command: npx eslint --version
- run:
name: Test ESLint 5
command: npm run test
name: Test ESLint 7
command: npm test

test-v6:
test-v8:
docker:
- image: circleci/node:16
- image: cimg/node:20.12.2
steps:
- checkout
- run:
name: Install dependencies
command: npm install
command: npm ci
- run:
name: Install ESLint 8
command: npm install eslint@8
- run:
name: Show ESLint version
command: npx eslint --version
- run:
name: Test ESLint 6
command: npm run test:v6
name: Test ESLint 8
command: npm test

release:
docker:
- image: circleci/node:16
- image: cimg/node:20.12.2
steps:
- checkout
- run:
name: Install dependencies
command: npm install
command: npm ci
- run:
name: Run semantic release
command: npm run semantic-release
9 changes: 6 additions & 3 deletions docs/rules/assertion-before-screenshot.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
## Assertion Before Screenshot
# Require screenshots to be preceded by an assertion (`cypress/assertion-before-screenshot`)

<!-- end auto-generated rule header -->
If you take screenshots without assertions then you may get different screenshots depending on timing.

For example, if clicking a button makes some network calls and upon success, renders something, then the screenshot may sometimes have the new render and sometimes not.

## Rule Details

This rule checks there is an assertion making sure your application state is correct before doing a screenshot. This makes sure the result of the screenshot will be consistent.

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

```js
cy.visit('myUrl');
cy.screenshot();
```

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

```js
cy.visit('myUrl');
Expand Down
7 changes: 6 additions & 1 deletion docs/rules/no-assigning-return-values.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## No Assigning Return Values
# Disallow assigning return values of `cy` calls (`cypress/no-assigning-return-values`)

💼 This rule is enabled in the ✅ `recommended` config.

<!-- end auto-generated rule header -->
## Further Reading

See [the Cypress Best Practices guide](https://on.cypress.io/best-practices#Assigning-Return-Values).
51 changes: 51 additions & 0 deletions docs/rules/no-async-before.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Disallow using `async`/`await` in Cypress `before` methods (`cypress/no-async-before`)

<!-- end auto-generated rule header -->
Cypress commands that return a promise may cause side effects in `before`/`beforeEach` hooks, possibly causing unexpected behavior.

## Rule Details

This rule disallows using `async` `before` and `beforeEach` functions.

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

```js
describe('my feature', () => {
before('my test case', async () => {
await cy.get('.myClass')
// other operations
})
})
```

```js
describe('my feature', () => {
before('my test case', async () => {
cy
.get('.myClass')
.click()

await someAsyncFunction()
})
})
```

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

```js
describe('my feature', () => {
before('my test case', () => {
cy.get('.myClass')
// other operations
})
})
```

## When Not To Use It

If there are genuine use-cases for using `async/await` in your `before` hooks then you may not want to include this rule (or at least demote it to a warning).

## Further Reading

- [Mixing Async and Sync code](https://on.cypress.io/guides/core-concepts/introduction-to-cypress#Mixing-Async-and-Sync-code)
- [Commands Are Asynchronous](https://on.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous)

0 comments on commit 8821de0

Please sign in to comment.