Skip to content

Commit 49318be

Browse files
committed
Add Playwright plugin config
1 parent 30aec38 commit 49318be

File tree

14 files changed

+216
-2
lines changed

14 files changed

+216
-2
lines changed

.github/ISSUE_TEMPLATE/bug-report.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ body:
4949
- Jest
5050
- Vitest
5151
- Cypress
52+
- Playwright
5253
- Storybook
5354
validations:
5455
required: true

.github/ISSUE_TEMPLATE/change-request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ body:
4747
- Jest
4848
- Vitest
4949
- Cypress
50+
- Playwright
5051
- Storybook
5152
validations:
5253
required: true

.github/ISSUE_TEMPLATE/feature-request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ body:
4747
- Jest
4848
- Vitest
4949
- Cypress
50+
- Playwright
5051
- Storybook
5152
validations:
5253
required: true

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Recommended ESLint presets by [Code PushUp](https://github.com/code-pushup/cli/t
2020
| ![jest](./docs/icons/material/jest.png) | [jest](./docs/jest.md) | Config for projects using **Jest** for testing. |
2121
| ![vitest](./docs/icons/material/vitest.png) | [vitest](./docs/vitest.md) | Config for projects using **Vitest** for testing. |
2222
| ![cypress](./docs/icons/material/cypress.png) | [cypress](./docs/cypress.md) | Config for projects using **Cypress** for testing. |
23+
| ![playwright](./docs/icons/material/playwright.png) | [playwright](./docs/playwright.md) | Config for projects using **Playwright** for testing. |
2324
| ![storybook](./docs/icons/material/storybook.png) | [storybook](./docs/storybook.md) | Config for projects using **Storybook** for UI components. |
2425

2526
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
8990
| ![jest](./docs/icons/material/jest.png) | [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) | `^28.8.0` | |
9091
| ![test](./docs/icons/icons8/test.png) | [eslint-plugin-jest-formatting](https://www.npmjs.com/package/eslint-plugin-jest-formatting) | `^3.0.0` | |
9192
| ![nodejs](./docs/icons/material/nodejs.png) | [eslint-plugin-n](https://www.npmjs.com/package/eslint-plugin-n) | `>=17.0.0` | |
93+
| ![playwright](./docs/icons/material/playwright.png) | [eslint-plugin-playwright](https://www.npmjs.com/package/eslint-plugin-playwright) | `>=2.1.0` | |
9294
| ![rxjs](./docs/icons/other/rxjs.png) | [eslint-plugin-rxjs-x](https://www.npmjs.com/package/eslint-plugin-rxjs-x) | `>=0.6.0` | |
9395
| ![storybook](./docs/icons/material/storybook.png) | [eslint-plugin-storybook](https://www.npmjs.com/package/eslint-plugin-storybook) | `>=0.10.0` | |
9496
| ![vitest](./docs/icons/material/vitest.png) | [eslint-plugin-vitest](https://www.npmjs.com/package/eslint-plugin-vitest) | `>=0.5.0` | |

docs/icons/material/playwright.png

786 Bytes
Loading

docs/playwright.md

Lines changed: 73 additions & 0 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 32 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"eslint-plugin-jest": "^28.8.0",
5151
"eslint-plugin-jest-formatting": "^3.0.0",
5252
"eslint-plugin-n": ">=17.0.0",
53+
"eslint-plugin-playwright": ">=2.1.0",
5354
"eslint-plugin-promise": ">=6.4.0",
5455
"eslint-plugin-rxjs-x": ">=0.6.0",
5556
"eslint-plugin-sonarjs": "^1.0.4",
@@ -84,6 +85,9 @@
8485
"eslint-plugin-n": {
8586
"optional": true
8687
},
88+
"eslint-plugin-playwright": {
89+
"optional": true
90+
},
8791
"eslint-plugin-rxjs-x": {
8892
"optional": true
8993
},
@@ -111,6 +115,7 @@
111115
"eslint-plugin-jest": "^28.8.0",
112116
"eslint-plugin-jest-formatting": "^3.1.0",
113117
"eslint-plugin-n": "^17.0.0",
118+
"eslint-plugin-playwright": "^2.1.0",
114119
"eslint-plugin-promise": "^6.4.0",
115120
"eslint-plugin-rxjs-x": "^0.6.1",
116121
"eslint-plugin-sonarjs": "^1.0.4",

scripts/helpers/configs.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const configDescriptions = {
1313
jest: md`Config for projects using ${md.bold('Jest')} for testing.`,
1414
vitest: md`Config for projects using ${md.bold('Vitest')} for testing.`,
1515
cypress: md`Config for projects using ${md.bold('Cypress')} for testing.`,
16+
playwright: md`Config for projects using ${md.bold('Playwright')} for testing.`,
1617
storybook: md`Config for projects using ${md.bold('Storybook')} for UI components.`,
1718
};
1819

@@ -31,6 +32,7 @@ const configIcons = {
3132
jest: 'material/jest',
3233
vitest: 'material/vitest',
3334
cypress: 'material/cypress',
35+
playwright: 'material/playwright',
3436
storybook: 'material/storybook',
3537
};
3638

@@ -40,6 +42,7 @@ const configPatterns = {
4042
jest: '*.test.ts',
4143
vitest: '*.test.ts',
4244
cypress: '*.cy.ts',
45+
playwright: '*.spec.ts',
4346
storybook: '*.stories.ts',
4447
};
4548

@@ -50,7 +53,7 @@ const configExtraPatterns = {
5053
};
5154

5255
/** @type {(keyof typeof configDescriptions)[]} */
53-
const testConfigs = ['jest', 'vitest', 'cypress'];
56+
const testConfigs = ['jest', 'vitest', 'cypress', 'playwright'];
5457

5558
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.`;
5659

scripts/helpers/plugins.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const pluginIcons = {
1616
'jest-formatting': 'icons8/test',
1717
n: 'material/nodejs',
1818
'no-secrets': 'icons8/secure',
19+
playwright: 'material/playwright',
1920
promise: 'icons8/promise',
2021
react: 'material/react',
2122
'react-hooks': 'material/react_ts',
@@ -47,6 +48,8 @@ const pluginDocsUrls = {
4748
'https://github.com/dangreenisrael/eslint-plugin-jest-formatting#readme',
4849
n: 'https://github.com/eslint-community/eslint-plugin-n#readme',
4950
'no-secrets': 'https://github.com/nickdeis/eslint-plugin-no-secrets#readme',
51+
playwright:
52+
'https://github.com/playwright-community/eslint-plugin-playwright#readme',
5053
promise: 'https://github.com/eslint-community/eslint-plugin-promise#readme',
5154
react: 'https://github.com/jsx-eslint/eslint-plugin-react#readme',
5255
'react-hooks':

scripts/helpers/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type Icon =
4646
| 'material/javascript'
4747
| 'material/jest'
4848
| 'material/nodejs'
49+
| 'material/playwright'
4950
| 'material/react_ts'
5051
| 'material/react'
5152
| 'material/storybook'

src/configs/playwright.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @ts-check
2+
3+
import playwright from 'eslint-plugin-playwright';
4+
import tseslint from 'typescript-eslint';
5+
import { PLAYWRIGHT_FILE_PATTERNS } from '../lib/patterns.js';
6+
7+
export default tseslint.config({
8+
files: PLAYWRIGHT_FILE_PATTERNS,
9+
extends: [
10+
playwright.configs['flat/recommended'],
11+
{
12+
name: 'code-pushup/playwright/customized',
13+
rules: {
14+
'playwright/no-conditional-expect': 'warn',
15+
'playwright/no-conditional-in-test': 'warn',
16+
},
17+
},
18+
{
19+
name: 'code-pushup/playwright/additional',
20+
rules: {
21+
'playwright/no-commented-out-tests': 'warn',
22+
'playwright/no-duplicate-hooks': 'warn',
23+
'playwright/no-focused-test': 'warn',
24+
'playwright/no-nested-step': 'warn',
25+
'playwright/prefer-comparison-matcher': 'warn',
26+
'playwright/prefer-equality-matcher': 'warn',
27+
'playwright/prefer-hooks-in-order': 'warn',
28+
'playwright/prefer-hooks-on-top': 'warn',
29+
'playwright/prefer-native-locators': 'warn',
30+
'playwright/prefer-locator': 'warn',
31+
'playwright/prefer-to-be': 'warn',
32+
'playwright/prefer-to-contain': 'warn',
33+
'playwright/prefer-to-have-count': 'warn',
34+
'playwright/prefer-to-have-length': 'warn',
35+
'playwright/require-hook': 'warn',
36+
'playwright/require-to-throw-message': 'warn',
37+
},
38+
},
39+
],
40+
});

src/lib/patterns.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ export const CYPRESS_FILE_PATTERNS = [
7272
'**/e2e/**/*.[jt]s?(x)',
7373
];
7474

75+
export const PLAYWRIGHT_FILE_PATTERNS = [
76+
'**/*.+(test|spec).[jt]s?(x)',
77+
'**/*.po.[jt]s?(x)',
78+
'**/e2e/**/*.[jt]s?(x)',
79+
];
80+
7581
export const NODE_FILE_PATTERNS = ['**/*.ts', '**/*.js'];
7682

7783
export const GRAPHQL_FILE_PATTERNS = ['**/*.graphql'];

tests/configs/playwright.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// @ts-check
2+
3+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
4+
import { createLintUtils } from '../helpers/lint-utils';
5+
6+
describe('playwright config', () => {
7+
const { setup, teardown, loadConfig } = createLintUtils(
8+
'playwright',
9+
'*.spec.ts',
10+
);
11+
12+
beforeAll(setup);
13+
14+
afterAll(teardown);
15+
16+
it('should not include playwright rules for non-test file', async () => {
17+
const config = await loadConfig('components/Button.tsx');
18+
expect(Object.keys(config?.rules ?? {}).join(',')).not.toContain(
19+
'playwright/',
20+
);
21+
});
22+
23+
it('should include playwright rules for test file', async () => {
24+
const config = await loadConfig('components/login.test.ts');
25+
expect(Object.keys(config.rules ?? {}).join(',')).toContain('playwright/');
26+
});
27+
28+
it('should include playwright rules for test folder', async () => {
29+
const config = await loadConfig('e2e/dashboard/subscription.ts');
30+
expect(Object.keys(config.rules ?? {}).join(',')).toContain('playwright/');
31+
});
32+
33+
it('should have rule from extended recommended playwright config', async () => {
34+
const config = await loadConfig();
35+
expect(config.rules).toHaveProperty('playwright/valid-expect');
36+
});
37+
38+
it('should have explicitly added rule', async () => {
39+
const config = await loadConfig();
40+
expect(config.rules).toHaveProperty('playwright/prefer-native-locators');
41+
});
42+
43+
it('should have customized severity level for rule from extended config', async () => {
44+
const config = await loadConfig();
45+
expect(config.rules?.['playwright/no-conditional-expect']).toEqual([1]);
46+
});
47+
});

0 commit comments

Comments
 (0)