Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: playwright-community/eslint-plugin-playwright
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.16.0
Choose a base ref
...
head repository: playwright-community/eslint-plugin-playwright
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.17.0
Choose a head ref
  • 5 commits
  • 40 files changed
  • 2 contributors

Commits on Sep 27, 2023

  1. Copy the full SHA
    d5e0a03 View commit details

Commits on Sep 28, 2023

  1. build(deps): upgrade dependencies (#164)

    * build(deps): upgrade dependencies
    
    * style: run format
    
    * Dedupe
    
    ---------
    
    Co-authored-by: Mark Skelton <mdskelton99@gmail.com>
    nix6839 and mskelton authored Sep 28, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6aeff37 View commit details
  2. feat: Add prefer-to-have-count rule (#165)

    * feat: Add `prefer-to-have-count` rule
    
    * docs: add `prefer-to-have-count` to the README
    nix6839 authored Sep 28, 2023
    Copy the full SHA
    82a518a View commit details
  3. chore: Fix lint

    mskelton committed Sep 28, 2023
    Copy the full SHA
    a62b551 View commit details

Commits on Oct 15, 2023

  1. Support flat config (#169)

    * feat: Support flat config
    
    * chore: Update examples to flat config
    
    * chore: Update docs
    
    * chore: Fix docs
    mskelton authored Oct 15, 2023
    Copy the full SHA
    01bd627 View commit details
Showing with 1,771 additions and 1,510 deletions.
  1. +9 −1 .eslintrc
  2. +82 −18 README.md
  3. +1 −1 docs/rules/no-eval.md
  4. +23 −0 docs/rules/prefer-to-have-count.md
  5. +0 −21 examples/.eslintrc
  6. +25 −0 examples/eslint.config.js
  7. +3 −3 examples/package.json
  8. +1 −1 jest.config.js
  9. +16 −14 package.json
  10. +1,265 −1,290 pnpm-lock.yaml
  11. +113 −64 src/index.ts
  12. +2 −2 src/rules/expect-expect.ts
  13. +1 −1 src/rules/missing-playwright-await.ts
  14. +5 −2 src/rules/no-element-handle.ts
  15. +1 −1 src/rules/no-force-option.ts
  16. +1 −1 src/rules/no-useless-not.ts
  17. +1 −1 src/rules/no-wait-for-timeout.ts
  18. +1 −1 src/rules/prefer-lowercase-title.ts
  19. +1 −1 src/rules/prefer-strict-equal.ts
  20. +3 −3 src/rules/prefer-to-be.ts
  21. +5 −5 src/rules/prefer-to-contain.ts
  22. +65 −0 src/rules/prefer-to-have-count.ts
  23. +8 −5 src/rules/prefer-web-first-assertions.ts
  24. +5 −5 src/utils/ast.ts
  25. +2 −2 src/utils/fixer.ts
  26. +1 −2 src/utils/misc.ts
  27. +1 −1 src/utils/parseExpectCall.ts
  28. +13 −13 test/spec/expect-expect.spec.ts
  29. +1 −1 test/spec/max-nested-describe.spec.ts
  30. +3 −3 test/spec/missing-playwright-await.spec.ts
  31. +1 −1 test/spec/no-conditional-in-test.spec.ts
  32. +2 −2 test/spec/no-element-handle.spec.ts
  33. +12 −12 test/spec/no-eval.spec.ts
  34. +6 −6 test/spec/no-force-option.spec.ts
  35. +1 −1 test/spec/no-nested-step.spec.ts
  36. +3 −3 test/spec/no-raw-locators.spec.ts
  37. +1 −1 test/spec/prefer-lowercase-title.spec.ts
  38. +66 −0 test/spec/prefer-to-have-count.spec.ts
  39. +20 −20 test/spec/prefer-web-first-assertions.spec.ts
  40. +1 −1 test/spec/require-top-level-describe.spec.ts
10 changes: 9 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
"extends": "@mskelton"
"extends": "@mskelton",
"overrides": [
{
"files": "**/*.spec.ts",
"rules": {
"no-template-curly-in-string": "off"
}
}
]
}
100 changes: 82 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -33,6 +33,26 @@ This plugin bundles two configurations to work with both `@playwright/test` or

### With [Playwright test runner](https://playwright.dev/docs/writing-tests)

[Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new)
(**eslint.config.js**)

```javascript
import playwright from 'eslint-plugin-playwright';

export default [
playwright.configs['flat/recommended'],
{
rules: {
// Customize Playwright rules
// ...
},
},
];
```

[Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files)
(**.eslintrc**)

```json
{
"extends": ["plugin:playwright/recommended"]
@@ -41,6 +61,30 @@ This plugin bundles two configurations to work with both `@playwright/test` or

### With [Jest Playwright](https://github.com/playwright-community/jest-playwright)

[Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new)
(**eslint.config.js**)

```javascript
import playwright from 'eslint-plugin-playwright';
import jest from 'eslint-plugin-jest';

export default [
playwright.configs['flat/jest-playwright'],
{
plugins: {
jest,
},
rules: {
// Customize Playwright rules
// ...
},
},
];
```

[Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files)
(**.eslintrc**)

```json
{
"extends": ["plugin:playwright/jest-playwright"]
@@ -63,6 +107,24 @@ under the `playwright` key. It supports the following settings:

You can configure these settings like so:

[Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new)
(**eslint.config.js**)

```javascript
export default [
{
settings: {
playwright: {
additionalAssertFunctionNames: ['assertCustomCondition'],
},
},
},
];
```

[Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files)
(**.eslintrc**)

```json
{
"settings": {
@@ -81,31 +143,33 @@ command line option.\
💡: Some problems reported by this rule are manually fixable by editor
[suggestions](https://eslint.org/docs/latest/developer-guide/working-with-rules#providing-suggestions).

| | 🔧 | 💡 | Rule | Description |
|| 🔧 | 💡 | Rule | Description |
| :-: | :-: | :-: | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| | | | [expect-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/expect-expect.md) | Enforce assertion to be made in a test body |
| | | | [max-nested-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls |
| | 🔧 | | [missing-playwright-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/missing-playwright-await.md) | Enforce Playwright APIs to be awaited |
| | | | [no-conditional-in-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests |
| | | 💡 | [no-element-handle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-element-handle.md) | Disallow usage of element handles |
| | | | [no-eval](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-eval.md) | Disallow usage of `page.$eval` and `page.$$eval` |
| | | 💡 | [no-focused-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-focused-test.md) | Disallow usage of `.only` annotation |
| | | | [no-force-option](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-force-option.md) | Disallow usage of the `{ force: true }` option |
| | | | [no-nested-step](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nested-step.md) | Disallow nested `test.step()` methods |
| | | | [no-networkidle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-networkidle.md) | Disallow usage of the `networkidle` option |
|| | | [expect-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/expect-expect.md) | Enforce assertion to be made in a test body |
|| | | [max-nested-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls |
|| 🔧 | | [missing-playwright-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/missing-playwright-await.md) | Enforce Playwright APIs to be awaited |
|| | | [no-conditional-in-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests |
|| | 💡 | [no-element-handle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-element-handle.md) | Disallow usage of element handles |
|| | | [no-eval](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-eval.md) | Disallow usage of `page.$eval` and `page.$$eval` |
|| | 💡 | [no-focused-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-focused-test.md) | Disallow usage of `.only` annotation |
|| | | [no-force-option](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-force-option.md) | Disallow usage of the `{ force: true }` option |
|| | | [no-nested-step](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nested-step.md) | Disallow nested `test.step()` methods |
|| | | [no-networkidle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-networkidle.md) | Disallow usage of the `networkidle` option |
| | | | [no-nth-methods](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nth-methods.md) | Disallow usage of `first()`, `last()`, and `nth()` methods |
|| | | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause` |
|| 🔧 | | [no-useless-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-await.md) | Disallow unnecessary `await`s for Playwright methods |
|| | | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause` |
| | | | [no-raw-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-raw-locators.md) | Disallow using raw locators |
|| 🔧 | | [no-useless-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-await.md) | Disallow unnecessary `await`s for Playwright methods |
| | | | [no-restricted-matchers](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers |
| | | 💡 | [no-skipped-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-skipped-test.md) | Disallow usage of the `.skip` annotation |
| | 🔧 | | [no-useless-not](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-not.md) | Disallow usage of `not` matchers when a specific matcher exists |
| | | 💡 | [no-wait-for-timeout](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-timeout.md) | Disallow usage of `page.waitForTimeout` |
|| | 💡 | [no-skipped-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-skipped-test.md) | Disallow usage of the `.skip` annotation |
|| 🔧 | | [no-useless-not](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-not.md) | Disallow usage of `not` matchers when a specific matcher exists |
|| | 💡 | [no-wait-for-timeout](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-timeout.md) | Disallow usage of `page.waitForTimeout` |
| | | 💡 | [prefer-strict-equal](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` |
| | 🔧 | | [prefer-lowercase-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names |
| | 🔧 | | [prefer-to-be](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-be.md) | Suggest using `toBe()` |
| | 🔧 | | [prefer-to-contain](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-contain.md) | Suggest using `toContain()` |
| | 🔧 | | [prefer-to-have-count](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-count.md) | Suggest using `toHaveCount()` |
| | 🔧 | | [prefer-to-have-length](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` |
| | 🔧 | | [prefer-web-first-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-web-first-assertions.md) | Suggest using web first assertions |
|| 🔧 | | [prefer-web-first-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-web-first-assertions.md) | Suggest using web first assertions |
| | | | [require-top-level-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `test.describe` block |
| | 🔧 | | [require-soft-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-soft-assertions.md) | Require assertions to use `expect.soft()` |
| | | | [valid-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect.md) | Enforce valid `expect()` usage |
|| | | [valid-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect.md) | Enforce valid `expect()` usage |
2 changes: 1 addition & 1 deletion docs/rules/no-eval.md
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ const searchValue = await page.$eval('#search', (el) => el.value);
const divCounts = await page.$$eval(
'div',
(divs, min) => divs.length >= min,
10
10,
);

await page.$eval('#search', (el) => el.value);
23 changes: 23 additions & 0 deletions docs/rules/prefer-to-have-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Suggest using `toHaveCount()` (`prefer-to-have-count`)

In order to have a better failure message, `toHaveCount()` should be used upon
asserting expectations on locators `count()` method.

## Rule details

This rule triggers a warning if `toBe()`, `toEqual()` or `toStrictEqual()` is
used to assert locators `count()` method.

The following patterns are considered warnings:

```javascript
expect(await files.count()).toBe(1);
expect(await files.count()).toEqual(1);
expect(await files.count()).toStrictEqual(1);
```

The following pattern is **not** a warning:

```javascript
await expect(files).toHaveCount(1);
```
21 changes: 0 additions & 21 deletions examples/.eslintrc

This file was deleted.

25 changes: 25 additions & 0 deletions examples/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import playwright from 'eslint-plugin-playwright';

export default [
playwright.configs['flat/recommended'],
{
languageOptions: {
sourceType: 'module',
ecmaVersion: 2022,
},
rules: {
'playwright/prefer-lowercase-title': 'warn',
'playwright/prefer-to-be': 'warn',
'playwright/prefer-to-have-length': 'warn',
'playwright/prefer-strict-equal': 'warn',
'playwright/max-nested-describe': ['warn', { max: 1 }],
'playwright/no-restricted-matchers': [
'error',
{
toBeFalsy: 'Use `toBe(false)` instead.',
not: null,
},
],
},
},
];
6 changes: 3 additions & 3 deletions examples/package.json
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@
"lint": "eslint ."
},
"dependencies": {
"@playwright/test": "^1.35.1",
"eslint": "^8.43.0",
"eslint-plugin-playwright": "workspace:*"
"@playwright/test": "^1.38.1",
"eslint": "^8.51.0",
"eslint-plugin-playwright": "file:../"
}
}
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
30 changes: 16 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"name": "eslint-plugin-playwright",
"description": "ESLint plugin for Playwright testing.",
"version": "0.0.0-semantically-released",
"packageManager": "pnpm@8.4.0",
"packageManager": "pnpm@8.8.0",
"main": "lib/index.js",
"repository": "https://github.com/playwright-community/eslint-plugin-playwright",
"author": "Mark Skelton <mark@mskelton.dev>",
@@ -23,20 +23,19 @@
"ts": "tsc"
},
"devDependencies": {
"@mskelton/eslint-config": "^8.0.0",
"@types/dedent": "^0.7.0",
"@types/eslint": "^8.40.2",
"@types/estree": "^1.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.11",
"dedent": "^0.7.0",
"eslint": "^8.43.0",
"@mskelton/eslint-config": "^8.4.0",
"@types/eslint": "^8.44.3",
"@types/estree": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^6.7.3",
"@typescript-eslint/parser": "^6.7.3",
"dedent": "^1.5.1",
"eslint": "^8.50.0",
"eslint-plugin-sort": "^2.10.0",
"jest": "^29.5.0",
"prettier": "^2.8.8",
"semantic-release": "^21.0.5",
"ts-jest": "^29.1.0",
"typescript": "^5.1.3"
"jest": "^29.7.0",
"prettier": "^3.0.3",
"semantic-release": "^22.0.5",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
},
"peerDependencies": {
"eslint": ">=7",
@@ -46,5 +45,8 @@
"eslint-plugin-jest": {
"optional": true
}
},
"dependencies": {
"globals": "^13.23.0"
}
}
Loading