Skip to main content

Changelog

[0.4.2] - 2026-11-05​

Added​

  • apiLog.curlOnFailedTest (false | true | 'last' | 'all', default false): when a test fails, the curl of the last API call made before the failure ('last', the same as true) or of every call made before it ('all') is recorded whatever its status, so the request that answered 201 where the test asserted 200 can be replayed. Compact output only. The call gets a │ block under its line with the response (← 201 Created {…}), the curl and ↳ replay: curl.sh attached to the HTML report; the script is attached as curl.sh (curl-{n}-…sh for several). The status chip keeps its success colour and the gutter is neutral. The curl is masked exactly like every other one: *** on the console and in the playwright-logger-pro.json attachment, ${VAR} placeholders in curl.sh. It is independent of curl (it works with curl: 'never'); details: 'never' leaves the block out, curlFormat.file: false the file. A call made after the test had already failed (an afterEach cleanup, steps after a failed expect.soft) is never the last call. A passing test, a test that fails as test.fail() expects, and format: 'verbose' are unchanged; with the option off (the default) nothing is built or recorded differently. With it on, a curl is built for every call (about 0.1 ms per call against a loopback server) and only the last one is kept. New type FailedTestCurl; CallRecord.curlOnFailedTest.
  • Docs: a colors: !process.env.CI recipe for the VS Code play button, and the equivalent reporter option ['playwright-logger-pro/reporter', { colors: !process.env.CI }], in the README and the docs site (Compact output, Troubleshooting, CI recipes, Configuration).

Fixed​

  • An explicit apiLog: { colors: true } now colours the compact output. It used to colour only the verbose lines: the reporter detected a terminal by itself (so a piped run, such as the VS Code play button, was plain whatever apiLog.colors said), and the compact output the fixture prints without the reporter followed curlFormat.colors: 'auto' alone. The fixture now records an explicit colors (true or false) in the playwright-logger-pro.json attachment, the reporter follows it, and the fixture's own output follows it too. The reporter's own colors option still wins over it ('auto', the default, leaves it to the fixture). colors: false keeps the output plain. With colors unset nothing changes: no colours on CI, with NO_COLOR, or when piped. An explicit true is an override and also beats NO_COLOR and CI, as it already did for the verbose lines. Without the reporter, a piped runner still shows no colour: Playwright strips the ANSI codes from a worker's output when its own output is not coloured, so register the reporter.
  • Docs and types only: curl: 'on-failure' was documented as "any status that is not 2xx". In compact output (the default) it is '4xx+': the console shows curls for status >= 400 and network errors (a 1xx/3xx response also gets its curl*.sh when the test failed). Only format: 'verbose' uses "any non-2xx". The documentation and the ApiLoggerConfig.curl comment now say so. No behaviour change.

[0.4.1] - 2026-11-03​

No change to the published code or its behaviour.

Fixed​

  • The step and error locations point at the spec file meta tests (pnpm test:meta) failed in a checkout whose folder is named playwright-logger-pro: they took the package name anywhere in a stack frame for a frame of the library, and the spec's own path contained it. The logger was not at fault (it finds its own frames by their directory, src/ or dist/, and the error stacks were clean). The test now looks for the package's src/ and dist/ directories and for node_modules/playwright-logger-pro/, and a unit test checks that a user frame survives in a checkout with that name.

Changed​

  • README: the dark and light screenshots are plain Markdown images, so they render on the npm package page.
  • Docs only: what curl: 'always' does is now described as it works. Every call gets a curl in the playwright-logger-pro.json attachment; the curl*.sh scripts are attached only when the test failed or with details: 'always'; the compact console prints curls only under failed calls (status >= 400 or a network error), as in 0.4.0. No code change.
  • Docs: the From 0.3 to 0.4 section of the migration page is rewritten (the note below), and the docs home page no longer says that API logging prints everything live and has no curl.
  • Repository: the unused npm-publish GitHub environment is removed. Releases use npm trusted publishing and name no environment.

Upgrading from 0.3 to 0.4​

0.4.0 changed defaults. Nothing needs to change for the code to run, but the output and some logged values differ:

  • Compact is the default output. An API call prints one line, and a failed request gets a │ block under it when its test failed. Register the reporter after list (reporter: [['list'], ['playwright-logger-pro/reporter']]) to get the layout and the total line; without it the fixture prints the lines itself.
  • Restore the 0.3 output with apiLog: { format: 'verbose' }. That brings back headers, bodies, response, curl and the #!/bin/sh curl.sh, exactly as in 0.3.
  • More values are masked by default (merged with your own lists; replaceDefaultRedaction: true drops them; also in format: 'verbose'). Added in 0.4.0, on top of the 0.3 lists: headers proxy-authorization and x-auth-token; query parameters refresh_token, key, signature and sig; and JSON/form body keys password, token, accessToken, refreshToken, secret, apiKey, cardToken, cardNumber, cvv, pin, access_token, refresh_token, api_key and card_number (the default list was empty). A response field called token or password now shows *** in the log.
  • curl has a default. In compact output it is '5xx' (it was false): a call with status >= 500 or a network error gets a curl, printed under it when its test failed, and a curl*.sh script attached to the report. A 4xx gets its ← block without a curl; use curl: '4xx+' for that, or 'never' to switch curls off. format: 'verbose' keeps false. curl also accepts '5xx', '4xx+', 'always' and 'never'; true, false and 'on-failure' still work (in compact: 'always', 'never', '4xx+').
  • curl: 'always' gives every call a curl in the playwright-logger-pro.json attachment. The curl*.sh scripts are attached only when the test failed or with details: 'always'. The console prints a curl only under failed calls.

See From 0.3 to 0.4 in the migration page of the docs.

[0.4.0] - 2026-10-31​

Added​

  • Compact output, the new default. An API call prints one line: METHOD STATUS URL TIMING, host dimmed, masked values ***, ▲ 1.83s for a slow call, and a coloured chip for a 4xx (yellow), 5xx and network error (red, ERR). A request with status >= 400 or no response gets a │ block directly under its line when its test failed: ← 404 Not Found {body} (one line, cut at bodyPreviewChars), and for 5xx and network errors the curl and ↳ replay: curl.sh attached to the HTML report. A 404 in a passing test keeps its chip and gets no block. After Playwright's summary a total line: 8 requests · 2 errors · 1 slow ≥1s.
  • playwright-logger-pro/reporter. Register it after list: reporter: [['list'], ['playwright-logger-pro/reporter']]. The test fixture records each call (masked) in a playwright-logger-pro.json attachment; the reporter, in the runner process, prints it under the test's result line. Printing from the workers cannot give that layout (their output comes before the result line and interleaves between parallel tests). Without the reporter the fixture prints the lines itself, above the result line.
  • Terminal safety. In a terminal the list reporter rewrites its result lines in place by row count, so extra lines printed while another test runs would garble them. The reporter holds its lines until no test is running and then prints them with a title line; with one worker, and without a terminal, nothing is held. Without colours the list reporter finishes lines on the next tick, so the reporter prints one setImmediate later. See Ordering with the list reporter in the README and the docs.
  • New apiLog options (also accepted by the reporter, except format and mask): format ('compact' | 'verbose'), slowThresholdMs (1000), timeColumn (82 | 'auto'), details ('failed-tests' | 'always' | 'never'), bodyPreviewChars (200), theme ('ansi' | 'dark' | 'light'), ascii, and mask: { headers, query, bodyKeys }. The reporter also takes curl and colors.
  • curl.sh that is safe to share. In compact output each failed call gets curl.sh (several: curl-{n}-{METHOD}-{lastPathSegment}.sh) with #!/usr/bin/env bash, set -euo pipefail and, for every masked value, a "${NAME}" placeholder (UPPER_SNAKE_CASE of its key: ${AUTHORIZATION}, ${TOKEN}, ${CARD_TOKEN}) with a : "${NAME:?export NAME first}" guard. No secret is ever written. The script has the whole body; the terminal cuts bodies over 2 KB with …. Headers curl adds itself (host, content-length, connection, accept-encoding) are left out.
  • No-colour mode keeps failures visible: the status column is 5 wide (200, [404]). ascii: true (automatic on legacy Windows consoles) uses | <- ^ -> ok x. Colours follow the 0.3 rules of curlFormat.colors: 'auto': none on CI, with NO_COLOR or when piped; FORCE_COLOR alone does not colour them.
  • npm run demo (three tests against a mock shop API, the scenario of the screenshots) and npm run screenshots (renders the demo's real output to docs/assets/compact-dark.png and compact-light.png; docs/assets is not published to npm).
  • Exports: the pure renderer (renderCalls, renderCallLine, renderDetail, renderFooter, summarize, formatDuration, shortenQuery, bodyPreview), buildCurlParts, envName, and the types CallRecord, CallsAttachment, CurlMode, DetailsMode, MaskConfig, OutputFormat, ThemeName, ReporterOptions. buildCurl() options gain mask, skipHeaders, truncationMarker and truncationNote.

Changed​

  • Default output. API calls print in the compact format instead of the line-by-line one. Migration: set apiLog: { format: 'verbose' } to keep the 0.3 output exactly (headers, bodies, response, curl, the #!/bin/sh curl.sh and its notice). format: 'verbose' defaults curl to false, as in 0.3.
  • curl also accepts '5xx' (the new default for compact), '4xx+', 'always' and 'never'; true, false and 'on-failure' keep working ('always', 'never', '4xx+' in compact).
  • curlFormat in compact: file: false attaches no scripts, multiline: false puts the curl on one line, colors decides the colours of what the fixture prints without the reporter. logBody: false keeps bodies and the response preview out; logHeaders: false keeps headers out of the JSON attachment. maxBodyLength applies to verbose and to the JSON attachment.
  • More is masked by default (your own lists are merged with them; replaceDefaultRedaction: true still drops them): headers proxy-authorization and x-auth-token; query parameters refresh_token, key, signature and sig; and JSON/form body keys, which used to be empty: password, token, accessToken, refreshToken, secret, apiKey, cardToken, cardNumber, cvv, pin (and access_token, refresh_token, api_key, card_number). This also affects format: 'verbose'.
  • Tests with API calls get a playwright-logger-pro.json attachment (masked records).
  • Docs site: the home page shows the compact output with its 500 detail block (regenerate with node website/scripts/gen-doc-samples.mjs); new page Compact output & the reporter.

[0.3.1] - 2026-10-31​

Changed​

  • Metadata and docs only, no code or behaviour changes: new npm keywords, a description that starts with "Playwright logger", and links to the npm package in the README and the documentation intro and installation pages.

[0.3.0] - 2026-10-30​

Added​

  • Coloured curl output. The curl printed to the console is coloured: curl bold, a colour each for the method, the URL, query parameter and header names, JSON keys and strings (when the body is valid JSON) and # comments, and *** in bold + inverse video. Flags, \ continuations, quotes and punctuation keep the default foreground. No white, yellow, cyan or dim text. Removing the ANSI codes always gives exactly the plain command, and with colours off the output is byte-identical to before.
  • Palette that reads on black and white terminals. Every colour is chosen from the default xterm palettes so that its WCAG contrast is at least 4.5:1 on both #000000 and #ffffff in the 256-colour palette (38;5;N: 63, 29, 98, 131, 163, 243) and at least 3:1 in the 16-colour fallback (blue 12, magenta 5 and 13, red 1 and 9, grey 8; the 16 colours have no green that reaches 3:1 on white, so POST and strings are not green there). The 256-colour palette is used when COLORTERM is truecolor/24bit, TERM contains 256color or the terminal reports at least 8 bits, otherwise the 16 basic colours. buildCurl() takes an optional colorDepth (8 or 4) to choose. npm run contrast prints the ratios of every element on both backgrounds and a unit test enforces the limits.
  • Coloured curl by default in a local terminal. A plain npx playwright test whose runner stdout is a terminal now colours the curl in worker output with no PLAYWRIGHT_FORCE_TTY or curlFormat.colors: true. The runner process (where the spec files import this package; checked on Playwright 1.30, 1.39, 1.48 and the latest) sets PLP_RUNNER_TTY=<runner pid>:<colour depth> when its own stdout is a real terminal and it is not on CI, NO_COLOR is unset, FORCE_COLOR/DEBUG_COLORS are not 0/false and TERM is not dumb; workers inherit it and trust it only when the pid is their parent's, so a copy inherited by a nested run or set by hand is ignored. Every other gate still applies (CI, NO_COLOR, TERM=dumb, resolved colors, custom sink, piped output stays plain, also on Playwright 1.30-1.39 whose workers fake a terminal); curlFormat.colors: true still overrides. package.json sideEffects now lists the two entry points, since importing them runs this check.
  • Colour gating. With curlFormat.colors: 'auto' the curl is coloured only when NO_COLOR is unset (it always wins), the process is not on CI (CI and the common CI service variables), the output is a terminal (process.stdout.isTTY, the runner's own stdout being one, or PLAYWRIGHT_FORCE_TTY set to anything but 0/false), the resolved colors is true and the sink is the console. FORCE_COLOR (which playwright test sets for its workers, whose stdout is piped) and a top-level colors: true alone no longer colour the curl in CI or non-TTY output; piped workers stay plain unless PLAYWRIGHT_FORCE_TTY or curlFormat.colors: true is set. An explicit curlFormat.colors: true is an override that bypasses these checks.
  • curlFormat option (ApiLoggerConfig): colors (true, false or 'auto', the default), multiline (default true; false prints a single line with # notes on their own preceding lines) and file. Invalid values warn once and use the default. New exported types CurlFormatConfig and ResolvedCurlFormat.
  • curl.sh per test (with the test fixture): the plain, redacted curl commands of a test are written to curl.sh in the test's output directory and attached to the report. The header is #!/bin/sh, # <spec file relative to rootDir/testDir>:<line> (control characters and escape sequences removed) and a generic comment; the test title is not written (it can carry secrets or terminal escape sequences). One line goes through the sink: curl.sh: attached to the test report (see "curl.sh" in the HTML report; also saved in this test's output folder); it names no path, because Playwright's output folder is derived from the title. curlFormat: { file: false } turns it off. Redaction is the same as for the printed curl; there is no unredacted mode.
  • buildCurl() accepts colors, colorDepth and multiline in its options (all optional; the signature is backward compatible).

Changed​

  • With a custom sink and no explicit colors, colours now default to off for all apiLog lines, so ANSI codes do not reach a file sink. An explicit colors: true keeps them. Before, a custom sink received colours whenever the environment enabled them.
  • curlFormat.colors: 'auto' follows the resolved colors only on the default console sink; with a custom sink the curl is plain unless curlFormat.colors is true.
  • Docs: Playwright's HTML report step titles show the full request URLs of request calls (the logger cannot mask them), and redactBodyKeys is empty by default and masks JSON/form keys only (XML and raw text bodies are not scrubbed). Behaviour unchanged.

[0.2.0] - 2026-10-30​

Added​

  • Browser action logging (browserLog). A per-test timeline of what the test did in the browser: actions on page, frame, locator, keyboard, mouse, touchscreen, context and browser, navigations, console messages, page errors, popups, downloads, dialogs, optional network, test.step boundaries, and a duration for every action. See the README section Browser action logging.
  • playwright-logger-pro/fixtures now provides both loggers. New browserLog option fixture, browserLogger fixture (note(), events(), render()), LoggerOptions type for defineConfig<LoggerOptions>(), and a mergeTests that keeps the step integration (Playwright 1.39+).
  • attachBrowserLogger(pageOrContext, config?) for pages you manage yourself (scripts, global setup, a page shared from beforeAll).
  • Secret masking by default: fill()/type() into password-like targets, keyboard input after such a target, literal redact.values, sensitive object keys inside arguments, header/cookie/credential values, URL userinfo passwords, console text and page errors. Opt-in redact.inspectInputType DOM probe. One shared sensitive-key list (DEFAULT_SENSITIVE_KEYS) for both loggers.
  • Outputs: live print, an 'on-failure' block, a browser-log report attachment (text or JSONL), and per-test files (file, fileFormat, fileDir). ANSI never reaches files or attachments.
  • apiLog lines are copied into the browser log's attachment and files (includeApiLog), never printed twice.
  • Documentation site (Docusaurus, GitHub Pages) with guides, configuration reference, API docs, migration notes and offline search; the changelog page is generated from this file.
  • CI matrix (Playwright 1.30 / 1.39 / 1.48 / latest, Chromium; latest also Firefox and WebKit), a weekly prototype-drift job, a package check (publint, attw, CJS and ESM smoke tests) and an overhead benchmark.

Changed​

  • browserLog is enabled by default, with quiet defaults: nothing is printed or attached while a test passes; on failure the timeline is printed once and attached to the report. Opt out per project or suite with browserLog: { enabled: false }. When disabled, no page-level patch or listener is installed for that test.
  • Step locations stay in your spec file. Wrapper frames of this library are hidden from Playwright's stack attribution, which also fixes request.* steps and errors of the existing apiLog fixture (they used to point into dist/).
  • On Playwright 1.30–1.48 the step title of a logged request is apiRequestContext.get(...) again (it was apiRequestContext.apply(...)).
  • package.json exports now has per-condition types (.d.mts for import, .d.ts for require) and exposes ./package.json; the build targets Node 16 syntax and ships shims for __dirname/import.meta.url.
  • redactHeaders() accepts an optional third argument (the mask, default ***).

Fixed (QA findings on this release)​

  • PCL-30 (critical): typed secrets are learned. A value typed into a field that is masked in its action line (fill, type, pressSequentially, keyboard.type, insertText, prompt answers) is now masked everywhere the logger outputs, for the rest of the test: console messages, page errors, network and navigation URLs (query strings included, also percent-encoded), dialog text, notes, attachment, files, JSONL and sink events. Values shorter than 4 characters are not learned.
  • PCL-31: card fields. #card, [name=cardnumber], [autocomplete=cc-number], getByLabel('Card'), getByLabel('Credit card'), #cvc, #securityCode, #totp … are detected from the selector. inspectInputType stays off by default.
  • PCL-32: Authorization tokens. Bearer X / Basic … / Token X set through setExtraHTTPHeaders (or the extraHTTPHeaders option) also masks the bare token X, the decoded Basic password and the values of a Cookie header.
  • PCL-33 (docs): Playwright-owned artifacts. The README now says that HTML report step titles, error-context.md and traces can contain raw values even with traces off, and that redact.* does not affect them.
  • PCL-34: malformed test.step location. Stack frames without parentheses (at /abs/file.ts:11:5) no longer keep the at prefix; file:// URLs and Windows paths are handled.
  • PCL-35: location: true reports the spec file and line instead of this library's dist/ file (library, Playwright and node frames are skipped).
  • PCL-27 / PCL-28: redirect replay. In a chain of redirects each step's curl starts from the previous step's request, so a body dropped by a 301/302/303 no longer comes back on a later 307/308. Headers follow the redirect rules of the installed Playwright (Cookie and cross-origin Authorization handling differ between 1.30–1.31, 1.32–1.59 and 1.60+).
  • PCL-47: query strings in browserLog URLs. Values of sensitive query parameters (apiLog's redactQueryParams defaults: api_key, apikey, token, access_token, password, secret) are masked by default in every URL browserLog prints: action arguments, navigations and redirect targets, popups, downloads, network lines and URLs in console text and errors. It shares apiLog's redactUrl logic and list; new redact.queryParams adds names. redact.values still applies on top.
  • PCL-46: redact.selectors and redact.keys add to the defaults instead of replacing them, as apiLog's lists do (#nick no longer un-masks #password/#pin). replaceDefaultRedaction: true in the apiLog option opts out. Behaviour change: configs that relied on replacing the defaults (to stop masking #pin, say) must now set it.
  • PCL-36: option validation. browserLog warns once on unknown options and on invalid types or values and falls back to the defaults; maxEvents of 0, negative or fractional values no longer suppress the failure block.
  • PCL-37: inspectInputType status. A fill that completed is reported as completed (value still masked) when the test ends before the probe answers, not as "still pending".
  • PCL-38: chronological timeline. Actions are ordered by their start, followed by the events that happened while they ran, in the stored events, the failure block and live output. A page's "opened" line carries the time the page appeared.
  • PCL-39 (critical): more spellings of a learned secret are masked. On top of the literal value and the percent-encoded and plain JSON.stringify forms, each learned secret (typed values, addCookies, setExtraHTTPHeaders, setHTTPCredentials) is now also masked as JSON with escaped slashes (\/), as \uXXXX JSON (PHP json_encode defaults, Python ensure_ascii, every character escaped; lower and upper case hex, surrogate pairs as two escapes) and as legacy escape() (%XX / %uXXXX, both hex cases). The variants are computed once when a secret is learned and deduplicated. The README lists exactly these forms.
  • PCL-40 (docs): masking is literal-form based. Base64, double encoding, HTML entities, values split across console.log arguments and fragments typed with keyboard.type() mid-field are not detected; the README limits section says so and what to do instead (redact.values, turning off the console and network channels, not logging such values). Turning off browserConsole and network does not cover action lines, page errors, dialog text or navigation URLs; for those, add the encoded form to redact.values, or use actions: false, pageErrors: false or navigation: false (navigation covers both dialog text and navigation URLs).
  • PCL-41: expiry and PAN fields. autocomplete cc-exp, cc-exp-month, cc-exp-year, cc-csc, and names, ids, labels or placeholders such as "Expiry date", "Expiration", "Exp date", "card expiry", "PAN" and "card number" are treated as sensitive. Whole words only, so company, panel or expires in stay clear.
  • PCL-42 (docs): server-set cookies. Cookies set by a Set-Cookie response header are not learned or masked; documented in the limits section.
  • PCL-43: Playwright 1.64 types. httpCredentials may be an array (one entry per origin); every password in it is collected. mergeTests is typed so that src/fixtures.ts also compiles against the 1.30 types. Typecheck and build verified against the lowest supported and the latest @playwright/test types.
  • PCL-44: expiry and PAN detection reads camelCase. Selector, name, id, placeholder and label text is split on camelCase boundaries and on _, - and space before matching, so #cardExpDate, #panNumber and [name=cardPAN] are detected, as are the placeholders MM/YY and MM/YYYY and the labels "Valid thru" and "Valid through". The same splitting applies to user-supplied redact.selectors. company, panel, span, express, expand, pantry, Japan, Expense and "expires in" stay clear.
  • PCL-44 (docs): the limits section now says that turning off browserConsole and network does not cover action lines, page errors, dialog text and navigation URLs (use redact.values, actions: false, pageErrors: false or navigation: false), that a value mixing escaped and literal forms or upper- and lower-case hex is not matched (case is per value), and how to pass an array to test.use({ httpCredentials }).

Known limitations​

  • Secret masking is literal-form based: base64, double encoding, HTML entities, values split across console.log arguments, and fragments typed with keyboard.type() mid-field are not detected, and cookies set by the server with Set-Cookie are not masked. Use redact.values, turn off the console and network channels, or avoid logging such values. Turning off browserConsole and network does not cover action lines, page errors, dialog text or navigation URLs; for those, add the encoded form to redact.values, or use actions: false, pageErrors: false or navigation: false (navigation covers both dialog text and navigation URLs).
  • Playwright's own artifacts record raw action parameters and page state, even with traces off: HTML report step titles (newer versions: Fill "<value>"), the error-context.md snapshot, traces, screenshots and videos. This logger only redacts its own outputs; redact.* does not affect Playwright's. See the README for what helps.
  • test.step integration needs Playwright 1.48+ (older versions cannot keep the step location); actions are still logged there, without step markers.
  • A password field whose selector, label and placeholder do not look like one is only detected with redact.inspectInputType: true, redact.values, a custom redact.selectors entry, or redact.fillValues: 'always'.