diff --git a/README.md b/README.md index 9b1593d..f168f0f 100644 --- a/README.md +++ b/README.md @@ -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": { diff --git a/examples/.eslintrc b/examples/.eslintrc deleted file mode 100644 index c2133f0..0000000 --- a/examples/.eslintrc +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": ["plugin:playwright/recommended"], - "parserOptions": { - "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 - } - ] - } -} diff --git a/examples/eslint.config.js b/examples/eslint.config.js new file mode 100644 index 0000000..cf9f0a1 --- /dev/null +++ b/examples/eslint.config.js @@ -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, + }, + ], + }, + }, +]; diff --git a/examples/package.json b/examples/package.json index 284d908..2d5f911 100644 --- a/examples/package.json +++ b/examples/package.json @@ -6,7 +6,7 @@ }, "dependencies": { "@playwright/test": "^1.38.1", - "eslint": "^8.50.0", - "eslint-plugin-playwright": "workspace:*" + "eslint": "^8.51.0", + "eslint-plugin-playwright": "file:../" } } diff --git a/package.json b/package.json index f7fcd24..6b6894f 100644 --- a/package.json +++ b/package.json @@ -45,5 +45,8 @@ "eslint-plugin-jest": { "optional": true } + }, + "dependencies": { + "globals": "^13.23.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 03bb976..086ee5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: eslint-plugin-jest: specifier: '>=25' version: 25.0.0(@typescript-eslint/eslint-plugin@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + globals: + specifier: ^13.23.0 + version: 13.23.0 devDependencies: '@mskelton/eslint-config': specifier: ^8.4.0 @@ -58,11 +61,11 @@ importers: specifier: ^1.38.1 version: 1.38.1 eslint: - specifier: ^8.50.0 - version: 8.50.0 + specifier: ^8.51.0 + version: 8.51.0 eslint-plugin-playwright: - specifier: workspace:* - version: link:.. + specifier: file:../ + version: file:(eslint@8.51.0) packages: @@ -423,6 +426,16 @@ packages: eslint: 8.50.0 eslint-visitor-keys: 3.4.3 + /@eslint-community/eslint-utils@4.4.0(eslint@8.51.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.51.0 + eslint-visitor-keys: 3.4.3 + dev: false + /@eslint-community/regexpp@4.9.0: resolution: {integrity: sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -434,7 +447,7 @@ packages: ajv: 6.12.6 debug: 4.3.4 espree: 9.6.1 - globals: 13.22.0 + globals: 13.23.0 ignore: 5.2.4 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -447,6 +460,11 @@ packages: resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/js@8.51.0: + resolution: {integrity: sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: false + /@humanwhocodes/config-array@0.11.11: resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} engines: {node: '>=10.10.0'} @@ -485,7 +503,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -506,14 +524,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.8.6) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -541,7 +559,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 jest-mock: 29.7.0 dev: true @@ -568,7 +586,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.7.1 + '@types/node': 20.8.6 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -601,7 +619,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -689,7 +707,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.2 - '@types/node': 20.7.1 + '@types/node': 20.8.6 '@types/yargs': 17.0.25 chalk: 4.1.2 dev: true @@ -1055,7 +1073,7 @@ packages: /@types/graceful-fs@4.1.7: resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.8.6 dev: true /@types/istanbul-lib-coverage@2.0.4: @@ -1081,8 +1099,10 @@ packages: /@types/json-schema@7.0.13: resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} - /@types/node@20.7.1: - resolution: {integrity: sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==} + /@types/node@20.8.6: + resolution: {integrity: sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==} + dependencies: + undici-types: 5.25.3 dev: true /@types/normalize-package-data@2.4.2: @@ -1820,7 +1840,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.8.6) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -2073,6 +2093,51 @@ packages: file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 + globals: 13.23.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + /eslint@8.51.0: + resolution: {integrity: sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) + '@eslint-community/regexpp': 4.9.0 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.51.0 + '@humanwhocodes/config-array': 0.11.11 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 globals: 13.22.0 graphemer: 1.4.0 ignore: 5.2.4 @@ -2090,6 +2155,7 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color + dev: false /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} @@ -2391,6 +2457,13 @@ packages: engines: {node: '>=8'} dependencies: type-fest: 0.20.2 + dev: false + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -2728,7 +2801,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -2766,7 +2839,7 @@ packages: create-jest: 29.7.0 exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.7.1) + jest-config: 29.7.0(@types/node@20.8.6) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -2777,7 +2850,7 @@ packages: - ts-node dev: true - /jest-config@29.7.0(@types/node@20.7.1): + /jest-config@29.7.0(@types/node@20.8.6): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -2792,7 +2865,7 @@ packages: '@babel/core': 7.23.0 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 babel-jest: 29.7.0(@babel/core@7.23.0) chalk: 4.1.2 ci-info: 3.8.0 @@ -2852,7 +2925,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 jest-mock: 29.7.0 jest-util: 29.7.0 dev: true @@ -2868,7 +2941,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.7 - '@types/node': 20.7.1 + '@types/node': 20.8.6 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -2919,7 +2992,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 jest-util: 29.7.0 dev: true @@ -2974,7 +3047,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3005,7 +3078,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3057,7 +3130,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -3082,7 +3155,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.7.1 + '@types/node': 20.8.6 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3094,7 +3167,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.7.1 + '@types/node': 20.8.6 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -4359,6 +4432,10 @@ packages: dev: true optional: true + /undici-types@5.25.3: + resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} + dev: true + /unicode-emoji-modifier-base@1.0.0: resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} engines: {node: '>=4'} @@ -4501,3 +4578,18 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} dev: true + + file:(eslint@8.51.0): + resolution: {directory: '', type: directory} + id: 'file:' + name: eslint-plugin-playwright + peerDependencies: + eslint: '>=7' + eslint-plugin-jest: '>=25' + peerDependenciesMeta: + eslint-plugin-jest: + optional: true + dependencies: + eslint: 8.51.0 + globals: 13.23.0 + dev: false diff --git a/src/index.ts b/src/index.ts index a1d8f11..439e790 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import * as globals from 'globals'; import expectExpect from './rules/expect-expect'; import maxNestedDescribe from './rules/max-nested-describe'; import missingPlaywrightAwait from './rules/missing-playwright-await'; @@ -27,70 +28,8 @@ import requireSoftAssertions from './rules/require-soft-assertions'; import requireTopLevelDescribe from './rules/require-top-level-describe'; import validExpect from './rules/valid-expect'; -const recommended = { - env: { - 'shared-node-browser': true, - }, - plugins: ['playwright'], - rules: { - 'no-empty-pattern': 'off', - 'playwright/expect-expect': 'warn', - 'playwright/max-nested-describe': 'warn', - 'playwright/missing-playwright-await': 'error', - 'playwright/no-conditional-in-test': 'warn', - 'playwright/no-element-handle': 'warn', - 'playwright/no-eval': 'warn', - 'playwright/no-focused-test': 'error', - 'playwright/no-force-option': 'warn', - 'playwright/no-nested-step': 'warn', - 'playwright/no-networkidle': 'error', - 'playwright/no-page-pause': 'warn', - 'playwright/no-skipped-test': 'warn', - 'playwright/no-useless-await': 'warn', - 'playwright/no-useless-not': 'warn', - 'playwright/no-wait-for-timeout': 'warn', - 'playwright/prefer-web-first-assertions': 'error', - 'playwright/valid-expect': 'error', - }, -}; - -export = { - configs: { - 'jest-playwright': { - env: { - jest: true, - 'shared-node-browser': true, - }, - globals: { - browser: true, - browserName: true, - context: true, - deviceName: true, - jestPlaywright: true, - page: true, - }, - plugins: ['jest', 'playwright'], - rules: { - 'jest/no-standalone-expect': [ - 'error', - { - additionalTestBlockFunctions: [ - 'test.jestPlaywrightDebug', - 'it.jestPlaywrightDebug', - 'test.jestPlaywrightSkip', - 'it.jestPlaywrightSkip', - 'test.jestPlaywrightConfig', - 'it.jestPlaywrightConfig', - ], - }, - ], - 'playwright/missing-playwright-await': 'error', - 'playwright/no-page-pause': 'warn', - }, - }, - 'playwright-test': recommended, - recommended, - }, +const index = { + configs: {}, rules: { 'expect-expect': expectExpect, 'max-nested-describe': maxNestedDescribe, @@ -122,3 +61,111 @@ export = { 'valid-expect': validExpect, }, }; + +const sharedConfig = { + rules: { + 'no-empty-pattern': 'off', + 'playwright/expect-expect': 'warn', + 'playwright/max-nested-describe': 'warn', + 'playwright/missing-playwright-await': 'error', + 'playwright/no-conditional-in-test': 'warn', + 'playwright/no-element-handle': 'warn', + 'playwright/no-eval': 'warn', + 'playwright/no-focused-test': 'error', + 'playwright/no-force-option': 'warn', + 'playwright/no-nested-step': 'warn', + 'playwright/no-networkidle': 'error', + 'playwright/no-page-pause': 'warn', + 'playwright/no-skipped-test': 'warn', + 'playwright/no-useless-await': 'warn', + 'playwright/no-useless-not': 'warn', + 'playwright/no-wait-for-timeout': 'warn', + 'playwright/prefer-web-first-assertions': 'error', + 'playwright/valid-expect': 'error', + }, +}; + +const legacyConfig = { + ...sharedConfig, + env: { + 'shared-node-browser': true, + }, + plugins: ['playwright'], +}; + +const flatConfig = { + ...sharedConfig, + languageOptions: { + globals: globals['shared-node-browser'], + }, + plugins: { + playwright: index, + }, +}; + +const sharedJestConfig = { + rules: { + 'jest/no-standalone-expect': [ + 'error', + { + additionalTestBlockFunctions: [ + 'test.jestPlaywrightDebug', + 'it.jestPlaywrightDebug', + 'test.jestPlaywrightSkip', + 'it.jestPlaywrightSkip', + 'test.jestPlaywrightConfig', + 'it.jestPlaywrightConfig', + ], + }, + ], + 'playwright/missing-playwright-await': 'error', + 'playwright/no-page-pause': 'warn', + }, +}; + +const legacyJestConfig = { + ...sharedJestConfig, + env: { + jest: true, + 'shared-node-browser': true, + }, + globals: { + browser: true, + browserName: true, + context: true, + deviceName: true, + jestPlaywright: true, + page: true, + }, + plugins: ['jest', 'playwright'], +}; + +const jestConfig = { + ...sharedJestConfig, + languageOptions: { + globals: { + ...globals['shared-node-browser'], + ...globals.jest, + browser: 'writable', + browserName: 'writable', + context: 'writable', + deviceName: 'writable', + jestPlaywright: 'writable', + page: 'writable', + }, + }, + plugins: { + playwright: index, + }, +}; + +export = { + ...index, + configs: { + 'flat/jest-playwright': jestConfig, + 'flat/recommended': flatConfig, + 'jest-playwright': legacyJestConfig, + 'playwright-test': legacyConfig, + recommended: legacyConfig, + }, +};