diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index acbbad9..88d8f44 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -49,6 +49,7 @@ body:
- Jest
- Vitest
- Cypress
+ - Playwright
- Storybook
validations:
required: true
diff --git a/.github/ISSUE_TEMPLATE/change-request.yml b/.github/ISSUE_TEMPLATE/change-request.yml
index 2c7c123..7ce4cbd 100644
--- a/.github/ISSUE_TEMPLATE/change-request.yml
+++ b/.github/ISSUE_TEMPLATE/change-request.yml
@@ -47,6 +47,7 @@ body:
- Jest
- Vitest
- Cypress
+ - Playwright
- Storybook
validations:
required: true
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
index 9bbd9a5..d60d659 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.yml
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -47,6 +47,7 @@ body:
- Jest
- Vitest
- Cypress
+ - Playwright
- Storybook
validations:
required: true
diff --git a/README.md b/README.md
index a08aac8..7968085 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ Recommended ESLint presets by [Code PushUp](https://github.com/code-pushup/cli/t
|  | [jest](./docs/jest.md) | Config for projects using **Jest** for testing. |
|  | [vitest](./docs/vitest.md) | Config for projects using **Vitest** for testing. |
|  | [cypress](./docs/cypress.md) | Config for projects using **Cypress** for testing. |
+|  | [playwright](./docs/playwright.md) | Config for projects using **Playwright** for testing. |
|  | [storybook](./docs/storybook.md) | Config for projects using **Storybook** for UI components. |
Some configs extend other configs, as illustrated below. So, for example, extending `angular` config implicitly extends `typescript` and `javascript` configs as well.
@@ -89,6 +90,7 @@ All peer dependencies used by `@code-pushup/eslint-config` are listed below, alo
|  | [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) | `^28.8.0` | |
|  | [eslint-plugin-jest-formatting](https://www.npmjs.com/package/eslint-plugin-jest-formatting) | `^3.0.0` | |
|  | [eslint-plugin-n](https://www.npmjs.com/package/eslint-plugin-n) | `>=17.0.0` | |
+|  | [eslint-plugin-playwright](https://www.npmjs.com/package/eslint-plugin-playwright) | `^2.1.0` | |
|  | [eslint-plugin-rxjs-x](https://www.npmjs.com/package/eslint-plugin-rxjs-x) | `>=0.6.0` | |
|  | [eslint-plugin-storybook](https://www.npmjs.com/package/eslint-plugin-storybook) | `>=0.10.0` | |
|  | [eslint-plugin-vitest](https://www.npmjs.com/package/eslint-plugin-vitest) | `>=0.5.0` | |
diff --git a/docs/icons/material/playwright.png b/docs/icons/material/playwright.png
new file mode 100644
index 0000000..6a89917
Binary files /dev/null and b/docs/icons/material/playwright.png differ
diff --git a/docs/playwright.md b/docs/playwright.md
new file mode 100644
index 0000000..63a1362
--- /dev/null
+++ b/docs/playwright.md
@@ -0,0 +1,75 @@
+# `playwright` config
+
+Config for projects using **Playwright** for testing.
+
+## 🏗️ Setup
+
+1. If you haven't already, make sure to [install `@code-pushup/eslint-config` and its required peer dependencies](../README.md#🏗️-setup).
+2. Since this plugin requires additional peer dependencies, you have to install them as well:
+
+ ```sh
+ npm install -D eslint-plugin-{jest-formatting,playwright}
+ ```
+
+3. Add to your `eslint.config.js` file:
+
+ ```js
+ import playwright from '@code-pushup/eslint-config/playwright.js';
+ import tseslint from 'typescript-eslint';
+
+ export default tseslint.config(...playwright);
+ ```
+
+## 📏 Rules (40)
+
+> 🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+
+### 🚨 Errors (8)
+
+| Plugin | Rule | Options | Autofix | Overrides |
+| :-----------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | :-----: | :-------: |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [missing-playwright-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/missing-playwright-await.md)
Identify false positives when async Playwright APIs are not properly awaited. | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-networkidle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-networkidle.md)
Prevent usage of the networkidle option | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-unsafe-references](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-unsafe-references.md)
Prevent unsafe variable references in page.evaluate() | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-web-first-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-web-first-assertions.md)
Prefer web first assertions | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [valid-describe-callback](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-describe-callback.md)
Enforce valid `describe()` callback | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [valid-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect.md)
Enforce valid `expect()` usage | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [valid-expect-in-promise](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect-in-promise.md)
Require promises that have expectations in their chain to be valid | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [valid-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-title.md)
Enforce valid titles | | 🔧 | |
+
+### ⚠️ Warnings (32)
+
+| Plugin | Rule | Options | Autofix | Overrides |
+| :-----------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | :-----: | :-------: |
+| [](https://github.com/dangreenisrael/eslint-plugin-jest-formatting#readme) | padding-around-describe-blocks
| | 🔧 | |
+| [](https://github.com/dangreenisrael/eslint-plugin-jest-formatting#readme) | padding-around-test-blocks
| | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [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 | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [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 | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-commented-out-tests](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-commented-out-tests.md)
Disallow commented out tests | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-conditional-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-expect.md)
Disallow calling `expect` conditionally | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [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 | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-duplicate-hooks](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-duplicate-hooks.md)
Disallow duplicate setup and teardown hooks | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-element-handle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-element-handle.md)
The use of ElementHandle is discouraged, use Locator instead | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-eval](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-eval.md)
The use of `page.$eval` and `page.$$eval` are discouraged, use `locator.evaluate` or `locator.evaluateAll` instead | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-focused-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-focused-test.md)
Prevent usage of `.only()` focus test annotation | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-force-option](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-force-option.md)
Prevent usage of `{ force: true }` option. | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-nested-step](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nested-step.md)
Disallow nested `test.step()` methods | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md)
Prevent usage of page.pause() | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-skipped-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-skipped-test.md)
Prevent usage of the `.skip()` skip test annotation. | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-standalone-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-standalone-expect.md)
Disallow using `expect` outside of `test` blocks | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-useless-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-await.md)
Disallow unnecessary awaits for Playwright methods | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [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 more specific matcher exists | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-wait-for-selector](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-selector.md)
Prevent usage of page.waitForSelector() | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [no-wait-for-timeout](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-timeout.md)
Prevent usage of page.waitForTimeout() | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-comparison-matcher](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-comparision-matcher.md)
Suggest using the built-in comparison matchers | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-equality-matcher](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-equality-matcher.md)
Suggest using the built-in equality matchers | | 💡 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-hooks-in-order](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-in-order.md)
Prefer having hooks in a consistent order | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-hooks-on-top](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-on-top.md)
Suggest having hooks before any test cases | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-locator](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-locator.md)
Suggest locators over page methods | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-native-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-native-locators.md)
Prefer native locator functions | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-to-be](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-be.md)
Suggest using `toBe()` for primitive literals | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-to-contain](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-contain.md)
Suggest using toContain() | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-to-have-count](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-count.md)
Suggest using `toHaveCount()` | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [prefer-to-have-length](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-length.md)
Suggest using `toHaveLength()` | | 🔧 | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [require-hook](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-hook.md)
Require setup and teardown code to be within a hook | | | |
+| [](https://github.com/playwright-community/eslint-plugin-playwright#readme) | [require-to-throw-message](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-to-throw-message.md)
Require a message for `toThrow()` | | | |
diff --git a/package-lock.json b/package-lock.json
index fb5beca..9f648ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"eslint-plugin-jest": "^28.8.0",
"eslint-plugin-jest-formatting": "^3.1.0",
"eslint-plugin-n": "^17.0.0",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-promise": "^6.4.0",
"eslint-plugin-rxjs-x": "^0.6.1",
"eslint-plugin-sonarjs": "^1.0.4",
@@ -54,7 +55,7 @@
"eslint-plugin-jest-formatting": "^3.0.0",
"eslint-plugin-n": ">=17.0.0",
"eslint-plugin-promise": ">=6.4.0",
- "eslint-plugin-rxjs-x": ">=0.2.4",
+ "eslint-plugin-rxjs-x": ">=0.6.0",
"eslint-plugin-sonarjs": "^1.0.4",
"eslint-plugin-storybook": ">=0.10.0",
"eslint-plugin-unicorn": ">=50.0.0",
@@ -5555,6 +5556,36 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/eslint-plugin-playwright": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.1.0.tgz",
+ "integrity": "sha512-wMbHOehofSB1cBdzz2CLaCYaKNLeTQ0YnOW+7AHa281TJqlpEJUBgTHbRUYOUxiXphfWwOyTPvgr6vvEmArbSA==",
+ "dev": true,
+ "dependencies": {
+ "globals": "^13.23.0"
+ },
+ "engines": {
+ "node": ">=16.6.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.40.0"
+ }
+ },
+ "node_modules/eslint-plugin-playwright/node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/eslint-plugin-promise": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.4.0.tgz",
diff --git a/package.json b/package.json
index 2317081..f642d95 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
"eslint-plugin-jest": "^28.8.0",
"eslint-plugin-jest-formatting": "^3.0.0",
"eslint-plugin-n": ">=17.0.0",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-promise": ">=6.4.0",
"eslint-plugin-rxjs-x": ">=0.6.0",
"eslint-plugin-sonarjs": "^1.0.4",
@@ -84,6 +85,9 @@
"eslint-plugin-n": {
"optional": true
},
+ "eslint-plugin-playwright": {
+ "optional": true
+ },
"eslint-plugin-rxjs-x": {
"optional": true
},
@@ -111,6 +115,7 @@
"eslint-plugin-jest": "^28.8.0",
"eslint-plugin-jest-formatting": "^3.1.0",
"eslint-plugin-n": "^17.0.0",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-promise": "^6.4.0",
"eslint-plugin-rxjs-x": "^0.6.1",
"eslint-plugin-sonarjs": "^1.0.4",
diff --git a/scripts/helpers/configs.js b/scripts/helpers/configs.js
index 9609935..4ff9101 100644
--- a/scripts/helpers/configs.js
+++ b/scripts/helpers/configs.js
@@ -13,6 +13,7 @@ const configDescriptions = {
jest: md`Config for projects using ${md.bold('Jest')} for testing.`,
vitest: md`Config for projects using ${md.bold('Vitest')} for testing.`,
cypress: md`Config for projects using ${md.bold('Cypress')} for testing.`,
+ playwright: md`Config for projects using ${md.bold('Playwright')} for testing.`,
storybook: md`Config for projects using ${md.bold('Storybook')} for UI components.`,
};
@@ -31,6 +32,7 @@ const configIcons = {
jest: 'material/jest',
vitest: 'material/vitest',
cypress: 'material/cypress',
+ playwright: 'material/playwright',
storybook: 'material/storybook',
};
@@ -40,6 +42,7 @@ const configPatterns = {
jest: '*.test.ts',
vitest: '*.test.ts',
cypress: '*.cy.ts',
+ playwright: '*.spec.ts',
storybook: '*.stories.ts',
};
@@ -50,7 +53,7 @@ const configExtraPatterns = {
};
/** @type {(keyof typeof configDescriptions)[]} */
-const testConfigs = ['jest', 'vitest', 'cypress'];
+const testConfigs = ['jest', 'vitest', 'cypress', 'playwright'];
const tsConfigDocsReference = md`Refer to ${md.link('./typescript.md#🏗️-setup', "step 3 in TypeScript config's setup docs")} for how to set up tsconfig properly.`;
diff --git a/scripts/helpers/plugins.js b/scripts/helpers/plugins.js
index 9b47391..0b6fef8 100644
--- a/scripts/helpers/plugins.js
+++ b/scripts/helpers/plugins.js
@@ -16,6 +16,7 @@ const pluginIcons = {
'jest-formatting': 'icons8/test',
n: 'material/nodejs',
'no-secrets': 'icons8/secure',
+ playwright: 'material/playwright',
promise: 'icons8/promise',
react: 'material/react',
'react-hooks': 'material/react_ts',
@@ -47,6 +48,8 @@ const pluginDocsUrls = {
'https://github.com/dangreenisrael/eslint-plugin-jest-formatting#readme',
n: 'https://github.com/eslint-community/eslint-plugin-n#readme',
'no-secrets': 'https://github.com/nickdeis/eslint-plugin-no-secrets#readme',
+ playwright:
+ 'https://github.com/playwright-community/eslint-plugin-playwright#readme',
promise: 'https://github.com/eslint-community/eslint-plugin-promise#readme',
react: 'https://github.com/jsx-eslint/eslint-plugin-react#readme',
'react-hooks':
diff --git a/scripts/helpers/types.d.ts b/scripts/helpers/types.d.ts
index dc9537a..b5b26bc 100644
--- a/scripts/helpers/types.d.ts
+++ b/scripts/helpers/types.d.ts
@@ -46,6 +46,7 @@ export type Icon =
| 'material/javascript'
| 'material/jest'
| 'material/nodejs'
+ | 'material/playwright'
| 'material/react_ts'
| 'material/react'
| 'material/storybook'
diff --git a/src/configs/playwright.js b/src/configs/playwright.js
new file mode 100644
index 0000000..d9f6f09
--- /dev/null
+++ b/src/configs/playwright.js
@@ -0,0 +1,52 @@
+// @ts-check
+
+import * as jestFormatting from 'eslint-plugin-jest-formatting';
+import playwright from 'eslint-plugin-playwright';
+import tseslint from 'typescript-eslint';
+import { PLAYWRIGHT_FILE_PATTERNS } from '../lib/patterns.js';
+
+export default tseslint.config({
+ files: PLAYWRIGHT_FILE_PATTERNS,
+ extends: [
+ playwright.configs['flat/recommended'],
+ {
+ name: 'code-pushup/playwright/jest-formatting',
+ plugins: {
+ 'jest-formatting': jestFormatting,
+ },
+ rules: {
+ 'jest-formatting/padding-around-describe-blocks': 'warn',
+ 'jest-formatting/padding-around-test-blocks': 'warn',
+ },
+ },
+ {
+ name: 'code-pushup/playwright/customized',
+ rules: {
+ 'playwright/no-conditional-expect': 'warn',
+ 'playwright/no-conditional-in-test': 'warn',
+ 'playwright/no-focused-test': 'warn',
+ 'playwright/no-standalone-expect': 'warn',
+ },
+ },
+ {
+ name: 'code-pushup/playwright/additional',
+ rules: {
+ 'playwright/no-commented-out-tests': 'warn',
+ 'playwright/no-duplicate-hooks': 'warn',
+ 'playwright/no-nested-step': 'warn',
+ 'playwright/prefer-comparison-matcher': 'warn',
+ 'playwright/prefer-equality-matcher': 'warn',
+ 'playwright/prefer-hooks-in-order': 'warn',
+ 'playwright/prefer-hooks-on-top': 'warn',
+ 'playwright/prefer-native-locators': 'warn',
+ 'playwright/prefer-locator': 'warn',
+ 'playwright/prefer-to-be': 'warn',
+ 'playwright/prefer-to-contain': 'warn',
+ 'playwright/prefer-to-have-count': 'warn',
+ 'playwright/prefer-to-have-length': 'warn',
+ 'playwright/require-hook': 'warn',
+ 'playwright/require-to-throw-message': 'warn',
+ },
+ },
+ ],
+});
diff --git a/src/lib/patterns.js b/src/lib/patterns.js
index 967bf40..9af0a14 100644
--- a/src/lib/patterns.js
+++ b/src/lib/patterns.js
@@ -69,7 +69,13 @@ export const HTML_FILE_PATTERNS = ['**/*.html'];
export const CYPRESS_FILE_PATTERNS = [
'**/*.cy.[jt]s?(x)',
- '**/e2e/**/*.[jt]s?(x)',
+ '**/?(*-)e2e/**/*.[jt]s?(x)',
+];
+
+export const PLAYWRIGHT_FILE_PATTERNS = [
+ '**/*.+(test|spec).[jt]s?(x)',
+ '**/*.po.[jt]s?(x)',
+ '**/?(*-)e2e/**/*.[jt]s?(x)',
];
export const NODE_FILE_PATTERNS = ['**/*.ts', '**/*.js'];
diff --git a/tests/configs/cypress.spec.js b/tests/configs/cypress.spec.js
index 6ab05cd..5c121df 100644
--- a/tests/configs/cypress.spec.js
+++ b/tests/configs/cypress.spec.js
@@ -1,30 +1,36 @@
// @ts-check
-import { afterAll, beforeAll, describe, expect, test } from 'vitest';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createLintUtils } from '../helpers/lint-utils';
describe('cypress config', () => {
const { setup, teardown, loadConfig } = createLintUtils('cypress', '*.cy.js');
beforeAll(setup);
+
afterAll(teardown);
- test('should not include Cypress rules for non-Cypress file', async () => {
+ it('should not include Cypress rules for non-Cypress file', async () => {
const config = await loadConfig('auth.spec.js');
expect(Object.keys(config.rules ?? {}).join(',')).not.toContain('cypress/');
});
- test('should include cypress rules for Cypress file', async () => {
- const config = await loadConfig('e2e/login.cy.js');
+ it('should include cypress rules for Cypress file', async () => {
+ const config = await loadConfig('app/submit-form.cy.js');
+ expect(Object.keys(config.rules ?? {}).join(',')).toContain('cypress/');
+ });
+
+ it('should include cypress rules for Cypress folder', async () => {
+ const config = await loadConfig('app-e2e/login.js');
expect(Object.keys(config.rules ?? {}).join(',')).toContain('cypress/');
});
- test('should have rule from extended recommended cypress config', async () => {
+ it('should have rule from extended recommended cypress config', async () => {
const config = await loadConfig();
expect(config.rules).toHaveProperty('cypress/no-unnecessary-waiting');
});
- test('should have explicitly added rule', async () => {
+ it('should have explicitly added rule', async () => {
const config = await loadConfig();
expect(config.rules).toHaveProperty('cypress/no-force');
});
diff --git a/tests/configs/playwright.spec.js b/tests/configs/playwright.spec.js
new file mode 100644
index 0000000..2bcd233
--- /dev/null
+++ b/tests/configs/playwright.spec.js
@@ -0,0 +1,59 @@
+// @ts-check
+
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+import { createLintUtils } from '../helpers/lint-utils';
+
+describe('playwright config', () => {
+ const { setup, teardown, loadConfig } = createLintUtils(
+ 'playwright',
+ '*.spec.ts',
+ );
+
+ beforeAll(setup);
+
+ afterAll(teardown);
+
+ it('should not include playwright rules for non-test file', async () => {
+ const config = await loadConfig('components/Button.tsx');
+ expect(Object.keys(config?.rules ?? {}).join(',')).not.toContain(
+ 'playwright/',
+ );
+ });
+
+ it('should include playwright rules for test file', async () => {
+ const config = await loadConfig('components/login.test.ts');
+ expect(Object.keys(config.rules ?? {}).join(',')).toContain('playwright/');
+ });
+
+ it('should include playwright rules for page object file', async () => {
+ const config = await loadConfig('components/login.po.ts');
+ expect(Object.keys(config.rules ?? {}).join(',')).toContain('playwright/');
+ });
+
+ it('should include playwright rules for test folder', async () => {
+ const config = await loadConfig('website-e2e/dashboard/subscription.ts');
+ expect(Object.keys(config.rules ?? {}).join(',')).toContain('playwright/');
+ });
+
+ it('should have rule from extended recommended playwright config', async () => {
+ const config = await loadConfig();
+ expect(config.rules).toHaveProperty('playwright/valid-expect');
+ });
+
+ it('should have explicitly added rule', async () => {
+ const config = await loadConfig();
+ expect(config.rules).toHaveProperty('playwright/prefer-native-locators');
+ });
+
+ it('should include jest formatting rule', async () => {
+ const config = await loadConfig();
+ expect(Object.keys(config.rules ?? {}).join(',')).toContain(
+ 'jest-formatting/',
+ );
+ });
+
+ it('should have customized severity level for rule from extended config', async () => {
+ const config = await loadConfig();
+ expect(config.rules?.['playwright/no-conditional-expect']).toEqual([1]);
+ });
+});