Changelog
[0.4.2] - 2026-11-05
Added
apiLog.curlOnFailedTest(false|true|'last'|'all', defaultfalse): when a test fails, the curl of the last API call made before the failure ('last', the same astrue) or of every call made before it ('all') is recorded whatever its status, so the request that answered201where the test asserted200can 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 ascurl.sh(curl-{n}-…shfor 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 theplaywright-logger-pro.jsonattachment,${VAR}placeholders incurl.sh. It is independent ofcurl(it works withcurl: 'never');details: 'never'leaves the block out,curlFormat.file: falsethe file. A call made after the test had already failed (anafterEachcleanup, steps after a failedexpect.soft) is never the last call. A passing test, a test that fails astest.fail()expects, andformat: '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 typeFailedTestCurl;CallRecord.curlOnFailedTest.- Docs: a
colors: !process.env.CIrecipe 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 whateverapiLog.colorssaid), and the compact output the fixture prints without the reporter followedcurlFormat.colors: 'auto'alone. The fixture now records an explicitcolors(trueorfalse) in theplaywright-logger-pro.jsonattachment, the reporter follows it, and the fixture's own output follows it too. The reporter's owncolorsoption still wins over it ('auto', the default, leaves it to the fixture).colors: falsekeeps the output plain. Withcolorsunset nothing changes: no colours on CI, withNO_COLOR, or when piped. An explicittrueis an override and also beatsNO_COLORand 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 itscurl*.shwhen the test failed). Onlyformat: 'verbose'uses "any non-2xx". The documentation and theApiLoggerConfig.curlcomment 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 filemeta tests (pnpm test:meta) failed in a checkout whose folder is namedplaywright-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/ordist/, and the error stacks were clean). The test now looks for the package'ssrc/anddist/directories and fornode_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 theplaywright-logger-pro.jsonattachment; thecurl*.shscripts are attached only when the test failed or withdetails: '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-publishGitHub 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 afterlist(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/shcurl.sh, exactly as in 0.3. - More values are masked by default (merged with your own lists;
replaceDefaultRedaction: truedrops them; also informat: 'verbose'). Added in 0.4.0, on top of the 0.3 lists: headersproxy-authorizationandx-auth-token; query parametersrefresh_token,key,signatureandsig; and JSON/form body keyspassword,token,accessToken,refreshToken,secret,apiKey,cardToken,cardNumber,cvv,pin,access_token,refresh_token,api_keyandcard_number(the default list was empty). A response field calledtokenorpasswordnow shows***in the log. curlhas a default. In compact output it is'5xx'(it wasfalse): a call with status >= 500 or a network error gets a curl, printed under it when its test failed, and acurl*.shscript attached to the report. A 4xx gets its←block without a curl; usecurl: '4xx+'for that, or'never'to switch curls off.format: 'verbose'keepsfalse.curlalso accepts'5xx','4xx+','always'and'never';true,falseand'on-failure'still work (in compact:'always','never','4xx+').curl: 'always'gives every call a curl in theplaywright-logger-pro.jsonattachment. Thecurl*.shscripts are attached only when the test failed or withdetails: '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.83sfor 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 atbodyPreviewChars), 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 afterlist:reporter: [['list'], ['playwright-logger-pro/reporter']]. Thetestfixture records each call (masked) in aplaywright-logger-pro.jsonattachment; 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
setImmediatelater. See Ordering with the list reporter in the README and the docs. - New
apiLogoptions (also accepted by the reporter, exceptformatandmask):format('compact'|'verbose'),slowThresholdMs(1000),timeColumn(82 |'auto'),details('failed-tests'|'always'|'never'),bodyPreviewChars(200),theme('ansi'|'dark'|'light'),ascii, andmask: { headers, query, bodyKeys }. The reporter also takescurlandcolors. curl.shthat is safe to share. In compact output each failed call getscurl.sh(several:curl-{n}-{METHOD}-{lastPathSegment}.sh) with#!/usr/bin/env bash,set -euo pipefailand, 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 ofcurlFormat.colors: 'auto': none on CI, withNO_COLORor when piped;FORCE_COLORalone does not colour them. npm run demo(three tests against a mock shop API, the scenario of the screenshots) andnpm run screenshots(renders the demo's real output todocs/assets/compact-dark.pngandcompact-light.png;docs/assetsis not published to npm).- Exports: the pure renderer (
renderCalls,renderCallLine,renderDetail,renderFooter,summarize,formatDuration,shortenQuery,bodyPreview),buildCurlParts,envName, and the typesCallRecord,CallsAttachment,CurlMode,DetailsMode,MaskConfig,OutputFormat,ThemeName,ReporterOptions.buildCurl()options gainmask,skipHeaders,truncationMarkerandtruncationNote.
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/shcurl.shand its notice).format: 'verbose'defaultscurltofalse, as in 0.3. curlalso accepts'5xx'(the new default for compact),'4xx+','always'and'never';true,falseand'on-failure'keep working ('always','never','4xx+'in compact).curlFormatin compact:file: falseattaches no scripts,multiline: falseputs the curl on one line,colorsdecides the colours of what the fixture prints without the reporter.logBody: falsekeeps bodies and the response preview out;logHeaders: falsekeeps headers out of the JSON attachment.maxBodyLengthapplies to verbose and to the JSON attachment.- More is masked by default (your own lists are merged with them;
replaceDefaultRedaction: truestill drops them): headersproxy-authorizationandx-auth-token; query parametersrefresh_token,key,signatureandsig; and JSON/form body keys, which used to be empty:password,token,accessToken,refreshToken,secret,apiKey,cardToken,cardNumber,cvv,pin(andaccess_token,refresh_token,api_key,card_number). This also affectsformat: 'verbose'. - Tests with API calls get a
playwright-logger-pro.jsonattachment (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:
curlbold, 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
#000000and#ffffffin 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 whenCOLORTERMistruecolor/24bit,TERMcontains256coloror the terminal reports at least 8 bits, otherwise the 16 basic colours.buildCurl()takes an optionalcolorDepth(8or4) to choose.npm run contrastprints 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 testwhose runner stdout is a terminal now colours the curl in worker output with noPLAYWRIGHT_FORCE_TTYorcurlFormat.colors: true. The runner process (where the spec files import this package; checked on Playwright 1.30, 1.39, 1.48 and the latest) setsPLP_RUNNER_TTY=<runner pid>:<colour depth>when its own stdout is a real terminal and it is not on CI,NO_COLORis unset,FORCE_COLOR/DEBUG_COLORSare not0/falseandTERMis notdumb; 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, resolvedcolors, custom sink, piped output stays plain, also on Playwright 1.30-1.39 whose workers fake a terminal);curlFormat.colors: truestill overrides.package.jsonsideEffectsnow lists the two entry points, since importing them runs this check. - Colour gating. With
curlFormat.colors: 'auto'the curl is coloured only whenNO_COLORis unset (it always wins), the process is not on CI (CIand the common CI service variables), the output is a terminal (process.stdout.isTTY, the runner's own stdout being one, orPLAYWRIGHT_FORCE_TTYset to anything but0/false), the resolvedcolorsis true and the sink is the console.FORCE_COLOR(whichplaywright testsets for its workers, whose stdout is piped) and a top-levelcolors: truealone no longer colour the curl in CI or non-TTY output; piped workers stay plain unlessPLAYWRIGHT_FORCE_TTYorcurlFormat.colors: trueis set. An explicitcurlFormat.colors: trueis an override that bypasses these checks. curlFormatoption (ApiLoggerConfig):colors(true,falseor'auto', the default),multiline(defaulttrue;falseprints a single line with#notes on their own preceding lines) andfile. Invalid values warn once and use the default. New exported typesCurlFormatConfigandResolvedCurlFormat.curl.shper test (with thetestfixture): the plain, redacted curl commands of a test are written tocurl.shin 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()acceptscolors,colorDepthandmultilinein its options (all optional; the signature is backward compatible).
Changed
- With a custom
sinkand no explicitcolors, colours now default to off for all apiLog lines, so ANSI codes do not reach a file sink. An explicitcolors: truekeeps them. Before, a custom sink received colours whenever the environment enabled them. curlFormat.colors: 'auto'follows the resolvedcolorsonly on the default console sink; with a customsinkthe curl is plain unlesscurlFormat.colorsistrue.- Docs: Playwright's HTML report step titles show the full request URLs of
requestcalls (the logger cannot mask them), andredactBodyKeysis 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.stepboundaries, and a duration for every action. See the README section Browser action logging. playwright-logger-pro/fixturesnow provides both loggers. NewbrowserLogoption fixture,browserLoggerfixture (note(),events(),render()),LoggerOptionstype fordefineConfig<LoggerOptions>(), and amergeTeststhat keeps the step integration (Playwright 1.39+).attachBrowserLogger(pageOrContext, config?)for pages you manage yourself (scripts, global setup, a page shared frombeforeAll).- Secret masking by default:
fill()/type()into password-like targets, keyboard input after such a target, literalredact.values, sensitive object keys inside arguments, header/cookie/credential values, URL userinfo passwords, console text and page errors. Opt-inredact.inspectInputTypeDOM probe. One shared sensitive-key list (DEFAULT_SENSITIVE_KEYS) for both loggers. - Outputs: live
print, an'on-failure'block, abrowser-logreport 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
browserLogis 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 withbrowserLog: { 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 intodist/). - On Playwright 1.30–1.48 the step title of a logged request is
apiRequestContext.get(...)again (it wasapiRequestContext.apply(...)). package.jsonexportsnow has per-condition types (.d.mtsforimport,.d.tsforrequire) 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.inspectInputTypestays off by default. - PCL-32: Authorization tokens.
Bearer X/Basic …/Token Xset throughsetExtraHTTPHeaders(or theextraHTTPHeadersoption) also masks the bare tokenX, the decoded Basic password and the values of aCookieheader. - PCL-33 (docs): Playwright-owned artifacts. The README now says that HTML report step titles,
error-context.mdand traces can contain raw values even with traces off, and thatredact.*does not affect them. - PCL-34: malformed
test.steplocation. Stack frames without parentheses (at /abs/file.ts:11:5) no longer keep theatprefix;file://URLs and Windows paths are handled. - PCL-35:
location: truereports the spec file and line instead of this library'sdist/file (library, Playwright and node frames are skipped). - PCL-27 / PCL-28: redirect replay. In a chain of redirects each step's
curlstarts 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
redactQueryParamsdefaults: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'sredactUrllogic and list; newredact.queryParamsadds names.redact.valuesstill applies on top. - PCL-46:
redact.selectorsandredact.keysadd to the defaults instead of replacing them, as apiLog's lists do (#nickno longer un-masks#password/#pin).replaceDefaultRedaction: truein theapiLogoption opts out. Behaviour change: configs that relied on replacing the defaults (to stop masking#pin, say) must now set it. - PCL-36: option validation.
browserLogwarns once on unknown options and on invalid types or values and falls back to the defaults;maxEventsof0, negative or fractional values no longer suppress the failure block. - PCL-37:
inspectInputTypestatus. 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.stringifyforms, each learned secret (typed values,addCookies,setExtraHTTPHeaders,setHTTPCredentials) is now also masked as JSON with escaped slashes (\/), as\uXXXXJSON (PHPjson_encodedefaults, Pythonensure_ascii, every character escaped; lower and upper case hex, surrogate pairs as two escapes) and as legacyescape()(%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.logarguments and fragments typed withkeyboard.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 offbrowserConsoleandnetworkdoes not cover action lines, page errors, dialog text or navigation URLs; for those, add the encoded form toredact.values, or useactions: false,pageErrors: falseornavigation: false(navigationcovers both dialog text and navigation URLs). - PCL-41: expiry and PAN fields.
autocompletecc-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, socompany,panelorexpires instay clear. - PCL-42 (docs): server-set cookies. Cookies set by a
Set-Cookieresponse header are not learned or masked; documented in the limits section. - PCL-43: Playwright 1.64 types.
httpCredentialsmay be an array (one entry per origin); every password in it is collected.mergeTestsis typed so thatsrc/fixtures.tsalso compiles against the 1.30 types. Typecheck and build verified against the lowest supported and the latest@playwright/testtypes. - 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,#panNumberand[name=cardPAN]are detected, as are the placeholdersMM/YYandMM/YYYYand the labels "Valid thru" and "Valid through". The same splitting applies to user-suppliedredact.selectors.company,panel,span,express,expand,pantry,Japan,Expenseand "expires in" stay clear. - PCL-44 (docs): the limits section now says that turning off
browserConsoleandnetworkdoes not cover action lines, page errors, dialog text and navigation URLs (useredact.values,actions: false,pageErrors: falseornavigation: 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 totest.use({ httpCredentials }).
Known limitations
- Secret masking is literal-form based: base64, double encoding, HTML entities, values split across
console.logarguments, and fragments typed withkeyboard.type()mid-field are not detected, and cookies set by the server withSet-Cookieare not masked. Useredact.values, turn off the console and network channels, or avoid logging such values. Turning offbrowserConsoleandnetworkdoes not cover action lines, page errors, dialog text or navigation URLs; for those, add the encoded form toredact.values, or useactions: false,pageErrors: falseornavigation: false(navigationcovers 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>"), theerror-context.mdsnapshot, traces, screenshots and videos. This logger only redacts its own outputs;redact.*does not affect Playwright's. See the README for what helps. test.stepintegration 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 customredact.selectorsentry, orredact.fillValues: 'always'.