Skip to content

Commit 9dd7fc1

Browse files
committed
chore(release v1.23.0): introduce shareable ESLint config for Playwright TypeScript projects, update Node.js requirement, and enhance documentation and update dependencies
1 parent f1be8f4 commit 9dd7fc1

7 files changed

Lines changed: 480 additions & 348 deletions

File tree

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# Changelog
22

3+
## [1.23.0] - 2026-02-13
4+
5+
### Added
6+
7+
- **Shareable ESLint config:** New flat config at `config/eslint.config.cjs` for Playwright TypeScript projects. Consume it via `vasu-playwright-utils/eslint` in your `eslint.config.js` and override rules as needed.
8+
- **README:** New [ESLint](#eslint) section with usage, spreading the config, and examples for overriding rules and file-specific overrides.
9+
- **Sample config:** `eslint.config.sample.mjs` (ESM) showing how to extend the shareable config and override rules.
10+
11+
### Changed
12+
13+
- **Engines:** Node.js requirement updated from `>=18.0.0` to `>=20.0.0`.
14+
- **Package:** Export `"./eslint"` added;
15+
- **Shareable ESLint config:** JSDoc rules `jsdoc/check-alignment` and `jsdoc/check-indentation` set to `off`. Project root resolution fixed to use `require('process').cwd()` to avoid lint errors in the config file.
16+
- **Local ESLint (eslint.config.js):** JSDoc rules `jsdoc/check-alignment` and `jsdoc/check-indentation` overridden to `warn` in this repo (base config stays `off` for consumers).
17+
18+
### Updated Dependencies
19+
20+
- `@types/node`: ^25.2.3 → ^25.3.1
21+
- `@typescript-eslint/eslint-plugin`, `@typescript-eslint/parser`: ^8.55.0 → ^8.56.1
22+
- `dotenv`: ^17.2.4 → ^17.3.1
23+
- `eslint`: ^9.39.2 → ^9.39.3
24+
- `eslint-plugin-jsdoc`: ^62.5.4 → ^62.7.1
25+
- `eslint-plugin-playwright`: ^2.5.1 → ^2.7.1
26+
- `rimraf`: ^6.1.2 → ^6.1.3
27+
328
## [1.22.2] - 2026-02-10
429

530
### Fixed

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
- [Installation](#installation)
1515
- [Usage](#usage)
16+
- [ESLint](#eslint)
1617
- [License](#license)
1718

1819
## Installation
@@ -33,6 +34,53 @@ import { click, fill } from 'vasu-playwright-utils';
3334
// Your code here
3435
```
3536

37+
## ESLint
38+
39+
This library ships a shareable ESLint config for Playwright TypeScript projects. Install the library (it includes the required ESLint plugins), then extend the config in your project and override any rules as needed.
40+
41+
### Using the config
42+
43+
1. Use **ESLint 9 flat config** (`eslint.config.js` at your project root).
44+
45+
2. In your `eslint.config.js`, spread the library config:
46+
47+
```javascript
48+
const playwrightLibConfig = require('vasu-playwright-utils/eslint');
49+
50+
module.exports = [...playwrightLibConfig];
51+
```
52+
53+
3. Ensure your project has a `tsconfig.json` at the root (the config uses it for TypeScript parsing).
54+
55+
### Overriding rules
56+
57+
Add config objects after the spread to override or relax rules:
58+
59+
```javascript
60+
const playwrightLibConfig = require('vasu-playwright-utils/eslint');
61+
62+
module.exports = [
63+
...playwrightLibConfig,
64+
// Override specific rules
65+
{
66+
rules: {
67+
'playwright/no-focused-test': 'warn',
68+
'playwright/no-wait-for-timeout': 'off',
69+
'no-console': 'off',
70+
},
71+
},
72+
// Or override only for certain files
73+
{
74+
files: ['tests/**/*.ts'],
75+
rules: {
76+
'playwright/expect-expect': 'error',
77+
},
78+
},
79+
];
80+
```
81+
82+
Later entries in the config array override earlier ones, so your overrides take precedence.
83+
3684
## Issues and Feedback
3785

3886
If you encounter any issues or have feedback, please [Raise an Issue](https://github.com/vasu31dev/playwright-ts-lib/issues) on GitHub.

eslint.config.base.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/**
2+
* Shareable ESLint config for Playwright TypeScript projects.
3+
* Single source of truth: used by this repo (via eslint.config.js) and by consumers (vasu-playwright-utils/eslint).
4+
*
5+
* @example
6+
* // eslint.config.js (in your project)
7+
* const playwrightLibConfig = require('vasu-playwright-utils/eslint');
8+
* module.exports = [
9+
* ...playwrightLibConfig,
10+
* { rules: { 'playwright/no-focused-test': 'warn' } },
11+
* ];
12+
*/
13+
14+
const typescript = require('@typescript-eslint/eslint-plugin');
15+
const typescriptParser = require('@typescript-eslint/parser');
16+
const prettier = require('eslint-plugin-prettier');
17+
const importPlugin = require('eslint-plugin-import');
18+
const jsdoc = require('eslint-plugin-jsdoc');
19+
const playwright = require('eslint-plugin-playwright');
20+
const js = require('@eslint/js');
21+
22+
// Works in this repo and when required from other projects (consumer's cwd)
23+
const projectRoot = require('process').cwd();
24+
25+
module.exports = [
26+
{
27+
ignores: [
28+
'node_modules/**',
29+
'dist/**',
30+
'build/**',
31+
'coverage/**',
32+
'.husky/**',
33+
'**/*.js',
34+
'package-lock.json',
35+
],
36+
},
37+
js.configs.recommended,
38+
{
39+
files: ['**/*.ts'],
40+
languageOptions: {
41+
parser: typescriptParser,
42+
parserOptions: {
43+
project: './tsconfig.json',
44+
tsconfigRootDir: projectRoot,
45+
},
46+
globals: {
47+
console: 'readonly',
48+
process: 'readonly',
49+
Buffer: 'readonly',
50+
__dirname: 'readonly',
51+
__filename: 'readonly',
52+
global: 'readonly',
53+
module: 'readonly',
54+
require: 'readonly',
55+
exports: 'readonly',
56+
},
57+
},
58+
plugins: {
59+
'@typescript-eslint': typescript,
60+
prettier,
61+
import: importPlugin,
62+
jsdoc,
63+
playwright,
64+
},
65+
settings: { 'import/resolver': { typescript: { alwaysTryTypes: true } } },
66+
rules: {
67+
// Prettier Rules
68+
'prettier/prettier': 'error',
69+
'no-trailing-spaces': 'error',
70+
'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0 }],
71+
'eol-last': ['error', 'always'],
72+
73+
// TypeScript Rules - Base
74+
...typescript.configs['eslint-recommended'].overrides[0].rules,
75+
...typescript.configs.recommended.rules,
76+
'@typescript-eslint/no-unsafe-assignment': 'warn',
77+
'@typescript-eslint/no-unsafe-member-access': 'warn',
78+
'@typescript-eslint/no-unsafe-return': 'warn',
79+
'@typescript-eslint/no-unsafe-call': 'warn',
80+
'@typescript-eslint/no-floating-promises': 'error',
81+
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
82+
'@typescript-eslint/no-explicit-any': 'warn',
83+
'@typescript-eslint/explicit-module-boundary-types': 'off',
84+
85+
// TypeScript Rules - Additional Strict Rules
86+
'@typescript-eslint/no-unused-vars': [
87+
'error',
88+
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
89+
],
90+
'@typescript-eslint/no-unused-expressions': 'error',
91+
'@typescript-eslint/no-empty-function': 'warn',
92+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
93+
'@typescript-eslint/prefer-optional-chain': 'error',
94+
'@typescript-eslint/prefer-as-const': 'error',
95+
'@typescript-eslint/no-non-null-assertion': 'warn',
96+
'@typescript-eslint/no-duplicate-enum-values': 'error',
97+
'@typescript-eslint/no-inferrable-types': [
98+
'error',
99+
{ ignoreParameters: false, ignoreProperties: false },
100+
],
101+
102+
// Import Rules
103+
'import/no-unresolved': 'error',
104+
'import/named': 'error',
105+
'import/default': 'error',
106+
'import/no-absolute-path': 'error',
107+
'import/no-self-import': 'error',
108+
'import/first': 'error',
109+
'import/no-mutable-exports': 'error',
110+
'sort-imports': ['error', { ignoreDeclarationSort: true }],
111+
112+
// General Rules - Best Practices
113+
'require-await': 'off',
114+
'@typescript-eslint/require-await': 'error',
115+
'@typescript-eslint/await-thenable': 'error',
116+
'@typescript-eslint/no-misused-promises': 'error',
117+
complexity: ['warn', { max: 11 }],
118+
'no-console': ['warn', { allow: ['warn', 'error', 'info'] }],
119+
'no-debugger': 'error',
120+
'no-var': 'error',
121+
'prefer-const': 'error',
122+
'prefer-template': 'error',
123+
'object-shorthand': 'error',
124+
'no-lonely-if': 'error',
125+
'no-useless-return': 'error',
126+
'no-nested-ternary': 'warn',
127+
eqeqeq: ['error', 'always', { null: 'ignore' }],
128+
'no-throw-literal': 'error',
129+
130+
// JSDoc Rules
131+
'jsdoc/check-alignment': 'off',
132+
'jsdoc/check-indentation': 'off',
133+
134+
// Playwright recommended rules
135+
...playwright.configs['playwright-test'].rules,
136+
137+
// Playwright Rules
138+
'playwright/missing-playwright-await': 'error',
139+
'playwright/no-focused-test': 'error',
140+
'playwright/valid-expect': 'error',
141+
'playwright/prefer-web-first-assertions': 'error',
142+
'playwright/no-useless-await': 'error',
143+
'playwright/no-page-pause': 'error',
144+
'playwright/no-element-handle': 'error',
145+
'playwright/no-eval': 'error',
146+
'playwright/prefer-to-be': 'error',
147+
'playwright/prefer-to-contain': 'error',
148+
'playwright/prefer-to-have-length': 'error',
149+
'playwright/no-wait-for-timeout': 'warn',
150+
'playwright/no-useless-not': 'warn',
151+
'playwright/require-top-level-describe': 'off',
152+
'playwright/expect-expect': 'off',
153+
'playwright/no-conditional-in-test': 'off',
154+
'playwright/no-skipped-test': 'off',
155+
'playwright/consistent-spacing-between-blocks': 'off',
156+
},
157+
},
158+
];

eslint.config.js

Lines changed: 9 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,13 @@
1-
const typescript = require('@typescript-eslint/eslint-plugin');
2-
const typescriptParser = require('@typescript-eslint/parser');
3-
const prettier = require('eslint-plugin-prettier');
4-
const importPlugin = require('eslint-plugin-import');
5-
const jsdoc = require('eslint-plugin-jsdoc');
6-
const playwright = require('eslint-plugin-playwright');
7-
const js = require('@eslint/js');
1+
/**
2+
* This repo's ESLint config: base config + local overrides.
3+
* Edit eslint.config.base.js to change rules; that file is also published as vasu-playwright-utils/eslint.
4+
*/
5+
const base = require('./eslint.config.base.js');
86

97
module.exports = [
10-
{ ignores: ['node_modules/**', '.husky/**', '**/*.js', 'package-lock.json', 'dist/**/*'] },
11-
js.configs.recommended,
12-
{
13-
files: ['**/*.ts'],
14-
languageOptions: {
15-
parser: typescriptParser,
16-
parserOptions: { project: './tsconfig.json', tsconfigRootDir: __dirname },
17-
globals: {
18-
console: 'readonly',
19-
process: 'readonly',
20-
Buffer: 'readonly',
21-
__dirname: 'readonly',
22-
__filename: 'readonly',
23-
global: 'readonly',
24-
module: 'readonly',
25-
require: 'readonly',
26-
exports: 'readonly',
27-
},
28-
},
29-
plugins: {
30-
'@typescript-eslint': typescript,
31-
prettier: prettier,
32-
import: importPlugin,
33-
jsdoc: jsdoc,
34-
playwright: playwright,
35-
},
36-
settings: { 'import/resolver': { typescript: { alwaysTryTypes: true } } },
37-
rules: {
38-
// Prettier Rules
39-
'prettier/prettier': 'error',
40-
'no-trailing-spaces': 'error',
41-
'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0 }],
42-
'eol-last': ['error', 'always'],
43-
44-
// TypeScript Rules - Base
45-
...typescript.configs['eslint-recommended'].overrides[0].rules,
46-
...typescript.configs.recommended.rules,
47-
'@typescript-eslint/no-unsafe-assignment': 'warn',
48-
'@typescript-eslint/no-unsafe-member-access': 'warn',
49-
'@typescript-eslint/no-unsafe-return': 'warn',
50-
'@typescript-eslint/no-unsafe-call': 'warn',
51-
'@typescript-eslint/no-floating-promises': 'error',
52-
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
53-
'@typescript-eslint/no-explicit-any': 'warn',
54-
'@typescript-eslint/explicit-module-boundary-types': 'off',
55-
56-
// TypeScript Rules - Additional Strict Rules
57-
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
58-
'@typescript-eslint/no-unused-expressions': 'error',
59-
'@typescript-eslint/no-empty-function': 'warn',
60-
'@typescript-eslint/prefer-nullish-coalescing': 'error',
61-
'@typescript-eslint/prefer-optional-chain': 'error',
62-
'@typescript-eslint/prefer-as-const': 'error',
63-
'@typescript-eslint/no-non-null-assertion': 'warn',
64-
'@typescript-eslint/no-duplicate-enum-values': 'error',
65-
'@typescript-eslint/no-inferrable-types': ['error', { ignoreParameters: false, ignoreProperties: false }],
66-
67-
// Import Rules
68-
'import/no-unresolved': 'error',
69-
'import/named': 'error',
70-
'import/default': 'error',
71-
'import/no-absolute-path': 'error',
72-
'import/no-self-import': 'error',
73-
// 'import/no-duplicates': 'error',
74-
'import/first': 'error',
75-
'import/no-mutable-exports': 'error',
76-
'sort-imports': ['error', { ignoreDeclarationSort: true }],
77-
78-
// General Rules - Best Practices
79-
'require-await': 'off', // Turned off in favor of @typescript-eslint version
80-
'@typescript-eslint/require-await': 'error',
81-
'@typescript-eslint/await-thenable': 'error',
82-
'@typescript-eslint/no-misused-promises': 'error',
83-
complexity: ['warn', { max: 11 }],
84-
'no-console': ['warn', { allow: ['warn', 'error', 'info'] }],
85-
'no-debugger': 'error',
86-
'no-var': 'error',
87-
'prefer-const': 'error',
88-
'prefer-template': 'error',
89-
'object-shorthand': 'error',
90-
// 'no-else-return': ['error', { allowElseIf: false }],
91-
'no-lonely-if': 'error',
92-
'no-useless-return': 'error',
93-
'no-nested-ternary': 'warn',
94-
eqeqeq: ['error', 'always', { null: 'ignore' }],
95-
'no-throw-literal': 'error',
96-
97-
// JSDoc Rules
98-
'jsdoc/check-alignment': 'warn',
99-
'jsdoc/check-indentation': 'warn',
100-
101-
// Playwright recommended rules (from plugin:playwright/playwright-test)
102-
...playwright.configs['playwright-test'].rules,
103-
104-
// Playwright Rules
105-
'playwright/missing-playwright-await': ['error'],
106-
'playwright/no-focused-test': 'error',
107-
'playwright/valid-expect': 'error',
108-
'playwright/prefer-web-first-assertions': 'error',
109-
'playwright/no-useless-await': 'error',
110-
'playwright/no-page-pause': 'error',
111-
'playwright/no-element-handle': 'error',
112-
'playwright/no-eval': 'error',
113-
'playwright/prefer-to-be': 'error',
114-
'playwright/prefer-to-contain': 'error',
115-
'playwright/prefer-to-have-length': 'error',
116-
'playwright/no-wait-for-timeout': 'warn',
117-
'playwright/no-useless-not': 'warn',
118-
'playwright/require-top-level-describe': 'off',
119-
'playwright/expect-expect': 'off',
120-
'playwright/no-conditional-in-test': 'off',
121-
'playwright/no-skipped-test': 'off',
122-
'playwright/consistent-spacing-between-blocks': 'off',
123-
},
124-
},
8+
...base,
9+
// Repo-specific: JSDoc alignment/indentation as warn (base has them off for consumers)
10+
{ rules: { 'jsdoc/check-alignment': 'warn', 'jsdoc/check-indentation': 'warn' } },
11+
// Repo-specific: stricter module boundary types in src
12512
{ files: ['src/**/*.ts'], rules: { '@typescript-eslint/explicit-module-boundary-types': 'warn' } },
12613
];

0 commit comments

Comments
 (0)