🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

pw-eslint

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pw-eslint

AST-based static analysis CLI for Playwright test files

latest
Source
npmnpm
Version
0.2.3
Version published
Maintainers
1
Created
Source

pw-eslint

AST-based static analysis CLI for Playwright test files and Page Object Models.

npm version License: MIT

Installation

npm install -g pw-eslint

Usage

# Analyze the current directory
pw-eslint .

# Analyze a specific path
pw-eslint src/tests

# Auto-fix fixable violations
pw-eslint . --fix

# Preview fixes without writing
pw-eslint . --dry-run

# Output as JSON
pw-eslint . --format json

# Only show errors (suppress warnings)
pw-eslint . --quiet

# Filter by rule category
pw-eslint . --category flakiness

# Analyze only git-staged files
pw-eslint . --staged

# Generate a config file
pw-eslint --init

# Explain a rule
pw-eslint explain no-hard-wait

# List all rules
pw-eslint explain --list

# Compare against a baseline
pw-eslint . --format json > baseline.json
# ... make changes ...
pw-eslint . --compare baseline.json

CLI Flags

FlagDescriptionDefault
[path]Path to analyze (file or directory).
--format <fmt>Output format: pretty, json, junit, githubpretty
--fixApply auto-fixes in placefalse
--dry-runPreview fixes as a unified difffalse
--rule <id...>Run only the specified rule(s) (repeatable)all enabled rules
--category <name...>Run only rules in the specified category(s) (repeatable)all categories
--severity <level>Filter output to error or warnall
--quietShow only error findings (same as --severity error)false
--no-colorDisable colored outputfalse
--config <path>Path to a specific config fileauto-discovered
--stagedAnalyze only git-staged filesfalse
--output-file <path>Write report to a file instead of stdoutstdout
--max-warnings <n>Exit 1 if warning count exceeds thresholdunlimited
--compare <path>Compare against a baseline JSON for regression detectiondisabled
--initGenerate .pw-eslintrc.json with all rules
--init-config <path>Custom path for generated config file.pw-eslintrc.json

Configuration

Create .pw-eslintrc.json at your project root (next to package.json):

{
  "include": ["**/*.spec.ts"],
  "exclude": ["node_modules", "dist"],
  "pageObjectPattern": "pages/**/*.ts",
  "specPattern": "**/*.spec.ts",
  "rules": {
    "no-hard-wait": "error",
    "deep-locator": ["warn", { "maxDepth": 3 }],
    "unawaited-action": "error",
    "web-first-assertion": "error",
    "leaky-page-object": "warn",
    "zombie-locator": "warn",
    "no-page-pause": "error",
    "no-focused-test": "error",
    "no-hardcoded-base-url": "warn",
    "no-hardcoded-timeout": ["warn", { "maxTimeout": 5000 }],
    "no-console-in-test": "warn",
    "no-skipped-test": "warn"
  }
}

You can also generate a starter config with pw-eslint --init.

Config Schema

KeyTypeDescription
includestring[]Glob patterns for files to analyze
excludestring[]Glob patterns for files to exclude
pageObjectPatternstringGlob for Page Object Model files
specPatternstringGlob for test spec files
rulesobjectRule severities — "error", "warn", "off", or ["warn", { options }]
failOn"error" | "warn"Exit 1 when findings of this severity exist (default: "error")
maxWarningsnumberMax warnings before exit 1 (default: unlimited)
categoryFilterstring[]Run only rules in the specified categories
overridesOverrideEntry[]Per-directory rule overrides (see below)

Per-Directory Overrides

Override rule severity for specific file patterns:

{
  "overrides": [
    {
      "files": ["tests/smoke/**"],
      "rules": { "no-hard-wait": "warn" }
    },
    {
      "files": ["tests/e2e/**"],
      "rules": { "no-hardcoded-timeout": "off" }
    }
  ]
}

The first matching override wins. Unspecified rules inherit the global config.

Built-in Rules

Rule IDDefaultFixableCategoryDescription
no-hard-waiterrorYesflakinessDisallows page.waitForTimeout() and bare setTimeout()
deep-locatorwarnNoflakinessFlags locator chains deeper than maxDepth (default: 3)
unawaited-actionerrorNoflakinessFlags Playwright actions called without await
zombie-locatorwarnNoflakinessFlags locators assigned but never used
web-first-assertionerrorYescorrectnessEnforces web-first assertions (expect(locator).toBeVisible()) over manual waits
leaky-page-objectwarnNohygieneFlags Page Object methods that return raw Playwright types
no-page-pauseerrorYeshygieneFlags page.pause() debug calls left in test code
no-focused-testerrorYesstyleFlags test.only() / it.only() / describe.only()
no-hardcoded-base-urlwarnNohygieneFlags hardcoded http:// / https:// URLs in page.goto()
no-hardcoded-timeoutwarnNohygieneFlags hardcoded timeout values (configurable maxTimeout)
no-console-in-testwarnNohygieneFlags console.log/warn/error/debug/info in spec files
no-skipped-testwarnYesstyleFlags test.skip() and test.fixme()

Rule Categories

Rules are grouped into four categories for filtering with --category:

CategoryRulesPurpose
flakinessno-hard-wait, deep-locator, unawaited-action, zombie-locatorPrevent flaky tests
correctnessweb-first-assertionEnforce correct Playwright patterns
hygieneleaky-page-object, no-page-pause, no-hardcoded-base-url, no-hardcoded-timeout, no-console-in-testKeep code clean
styleno-focused-test, no-skipped-testEnforce consistent style

Rule-Specific Options

Some rules accept configuration options:

{
  "rules": {
    "deep-locator": ["warn", { "maxDepth": 4 }],
    "no-hardcoded-timeout": ["warn", { "maxTimeout": 5000 }]
  }
}
RuleOptionTypeDefaultDescription
deep-locatormaxDepthnumber3Maximum allowed locator chain depth
no-hardcoded-timeoutmaxTimeoutnumber0Only flag timeouts exceeding this value (0 = flag all)

Auto-Fix

Five rules support automatic fixing:

RuleFix Action
no-hard-waitReplaces page.waitForTimeout() with a TODO comment
web-first-assertionRewrites expect(await loc.isVisible()).toBe(true) to await expect(loc).toBeVisible()
no-page-pauseRemoves page.pause() statements
no-focused-testRemoves .only modifier (test.only() -> test())
no-skipped-testRemoves .skip / .fixme modifier (test.skip() -> test())
# Apply fixes
pw-eslint . --fix

# Preview fixes as diff
pw-eslint . --dry-run

All fixes are idempotent — running --fix twice produces the same result.

Inline Disable Comments

Suppress a finding on the next line:

// pw-eslint-disable-next-line no-hard-wait
await page.waitForTimeout(1000);

Suppress multiple rules:

// pw-eslint-disable-next-line no-hard-wait, deep-locator
await page.locator('div > span > a').waitForTimeout(1000);

Rule IDs are case-insensitive.

Rule Explain

Get detailed rationale, examples, and fix guidance for any rule:

pw-eslint explain no-hard-wait
pw-eslint explain --list

The explain command shows:

  • Rule description and rationale
  • Code examples of violations
  • Fix guidance
  • Category and severity

CI Integration

GitHub Actions Annotations

Use --format github to produce inline annotations in GitHub Actions:

- run: npx pw-eslint . --format github

Staged Files (Pre-Commit)

Analyze only git-staged files:

pw-eslint . --staged

Write Report to File

pw-eslint . --format junit --output-file reports/pw-eslint.xml

Warning Threshold

Fail the build if warnings exceed a limit:

pw-eslint . --max-warnings 10

Fail on Warnings

Configure when the CLI exits with code 1:

{
  "failOn": "warn"
}

Baseline Comparison

Save current findings as a baseline, then detect regressions:

# Save baseline
pw-eslint . --format json > baseline.json

# Later, compare against baseline
pw-eslint . --compare baseline.json

With --compare:

  • Exit 0 if no new violations were introduced
  • Exit 1 if new violations exist (regressions)
  • Fixed violations are reported but don't affect exit code

Custom Rules

Custom rules are loaded from .pw-eslint/rules/*.js relative to your project root.

Security Warning: Custom rules are trusted code. They run in the same Node.js process as the CLI with no sandboxing. Do not load rules from untrusted sources. Only use rules written and reviewed by your own team.

Rule File Structure

Each rule file must export a RuleDefinition object as its default export:

// .pw-eslint/rules/no-console-log.js
export default {
  apiVersion: 1,
  id: 'no-console-log',
  description: 'Disallows console.log in test files',
  defaultSeverity: 'warn',
  fixable: false,
  check(context) {
    const calls = context.sourceFile.getDescendantsOfKind(/* SyntaxKind.CallExpression */ 213);
    for (const call of calls) {
      if (call.getExpression().getText() === 'console.log') {
        context.report(call, 'Avoid console.log in tests');
      }
    }
  },
};

RuleDefinition Interface

interface RuleDefinition {
  apiVersion: 1; // must be exactly 1
  id: string; // unique rule identifier
  description: string; // human-readable description
  defaultSeverity: 'error' | 'warn'; // default severity when enabled
  fixable: boolean; // whether fix() is implemented
  category?: string; // rule category for filtering
  explain?: RuleExplainData; // rationale, examples, fix guidance
  check(context: RuleContext): void; // analysis logic
  fix?(context: FixContext): void; // optional auto-fix logic
}

RuleContext Interface

interface RuleContext {
  sourceFile: SourceFile; // ts-morph SourceFile
  project: Project; // ts-morph Project
  config: ResolvedConfig; // resolved CLI config
  report(node: Node, message: string, suggestion?: string): void;
}

Configuring Custom Rules

Once a custom rule file exists, configure it in .pw-eslintrc.json just like any built-in rule:

{
  "rules": {
    "no-console-log": "warn"
  }
}

API Versioning

The apiVersion field guards against breaking changes. The current supported version is 1. If you upgrade the CLI and the API changes, the CLI will exit with code 2 and tell you which rule needs updating.

Exit Codes

CodeMeaning
0Success — no violations matching failOn severity
1Analysis completed — violations found, --max-warnings exceeded, or regressions detected with --compare
2Configuration error, plugin load failure, file not found, or usage error

Security

pw-eslint requires filesystem access to read configurations and analyze test files. If you're using this as a library and want to restrict access, see SECURITY.md for how to provide a custom FileSystem implementation.

License

MIT — see LICENSE.

FAQs

Package last updated on 30 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts