npm.io
0.1.0 • Published 2d ago

playwright-step-logger

Licence
MIT
Version
0.1.0
Deps
0
Size
46 kB
Vulns
0
Weekly
0

playwright-step-logger

Logs every Playwright action and assertion as a reporter step with readable, value-bearing titles (which field, what value, which element) — the detail native Playwright steps don't surface. Allure by default; the logger is pluggable.

How it works

  • Assertions — a thin expect wrapper logs a step, then delegates to the real Playwright matcher. Native behavior is preserved (auto-retry, diffs, .not, timeouts); nothing is reimplemented.
  • Actions — a recursive Proxy over a page/locator/frame wraps actions (click, fill, …) in steps, re-proxies returned locators (so chains keep logging), and preserves return values.
  • New matcherstoBeExist / toBeAbsent are added via expect.extend.

Note: built-in matchers are wrapped, not overridden — Playwright's expect.extend cannot replace built-ins. Synchronous value assertions (expect(2).toBe(2)) pass straight through (no step) to keep their sync throw-on-failure semantics; async (Locator/Page/APIResponse) assertions are logged.

Install

npm i -D playwright-step-logger
# optional, for the default Allure logging:
npm i -D allure-js-commons

@playwright/test is a peer dependency.

Usage

Three steps to wire it into a suite:

1. Register once in a setup/fixtures file that loads before tests. Prefer Playwright's test.step as the logger — native steps are captured reliably by allure-playwright across a full multi-test run, whereas allure.step can be dropped:

import { test } from '@playwright/test'
import { registerMatchers } from 'playwright-step-logger'

registerMatchers({
  // Recommended: log through native test.step (guard so it no-ops outside a test).
  step: (title, body) => (getCurrentTestInfo() ? test.step(title, body) : body()),
  defaultTimeout: 45_000,
})
// Simplest alternative: omit `step` to use the built-in Allure default.

2. Use the wrapped expect everywhere assertions are made. The whole suite must import expect from this package (or a re-export of it) — assertions made via @playwright/test's own expect are NOT logged:

// re-export once, then import from there across the suite
// helpers/expect.ts:
export { expect } from 'playwright-step-logger'

3. Wrap pages for action logging.

import { expect, pageHandler } from 'playwright-step-logger'

class SomePage {
  constructor(page: Page) {
    this.page = new Proxy(page, pageHandler) // actions now logged
  }
}

await expect(locator).toHaveText('Hello')   // logged: Check "..." has text "Hello"
await expect(locator).toBeExist()           // custom matcher
Pluggable logger
type StepWrapper = <T>(title: string, body: () => Promise<T>) => Promise<T>
registerMatchers({ step: (title, body) => test.step(title, body) })
Custom step titles (optional)
registerMatchers({
  actionDescriptions: {
    fill: ({ locator, value }) => `Заполнить "${locator}" значением "${value}"`,
  },
  assertionDescriptions: {
    toHaveText: ({ target, args, isNot }) => `Текст "${target}" ${isNot ? '≠' : '='} "${args[0]}"`,
  },
})
Types

For expect(locator).toBeExist() to type-check, ensure the package's ambient types are picked up (e.g. "types": ["playwright-step-logger"] in tsconfig, or any import of the package).

Build (contributors)

npm run build      # tsc -> dist/ (CommonJS + d.ts)
npm run typecheck