@empiricalrun/eslint-config
ESLint config for Playwright test repositories (ESLint 9, flat config).
Installation
npm install @empiricalrun/eslint-config --save-dev
The package provides the repo's toolchain: eslint, prettier and typescript (pinned to an exact
version), so npx eslint and npx tsc work without separate installs. Do not add typescript to
the repo's own package.json; upgrade it by upgrading this package.
typescript stays on 5.x because typescript-eslint needs the TypeScript JS API, which TypeScript 7
does not ship.
TypeScript config
{
"extends": "@empiricalrun/eslint-config/tsconfig.json"
}
Usage
Create an eslint.config.mjs file in the root of your project:
export { default } from "@empiricalrun/eslint-config/playwright";
TypeScript files are linted with type information, using the nearest tsconfig.json.
Custom rules
empirical/no-tags-in-name: tags go in thetagoption, not the title.test("login @smoke", ...)is an error; usetest("login", { tag: ["@smoke"] }, ...).empirical/no-hooks-in-shared-modules: notest.beforeEach/afterEach/beforeAll/afterAllat module scope outside test files (*.spec.*,*.test.*,*.setup.*,*.teardown.*). A shared module such asfixtures.tsis evaluated once per worker, so its hooks only run for the first test file each worker imports. Use a fixture with{ auto: true }instead.empirical/no-describe-mode-shorthand: notest.describe.serial(...)ortest.describe.parallel(...). Set the mode inside the block withtest.describe.configure({ mode: "serial" }): Empirical reads the mode fromdescribe.configureto retry and resume a serial group as a unit.
Repo layout
The config enforces the standard test repo layout:
tests/ *.spec.ts, *.setup.ts and *.teardown.ts only
pages/ code that knows the app under test: functions, no classes
lib/ the test repo's machinery shared by all tests: fixtures, test data, utilities
empirical/repo-layout:tests/holds only*.spec.ts,*.setup.tsand*.teardown.ts. Any other file undertests/is an error: a Playwright project that matches a folder collects every file in it as a test file, so the specs that import it fail to load. Folders outsidetests/,pages/andlib/(such asscripts/orunit/) are not checked.empirical/no-helpers-in-specs: no top-level functions or classes in test files. Move them topages/if they drive the app, orlib/if they don't.empirical/no-classes-in-pages:pages/exports functions.import/no-restricted-paths: the rest oflib/never importspages/,pages/never importslib/fixtures/(fixtures import pages, so that would be a cycle), and nothing importstests/.