API logs and replayable curl
Every request.get/post/… prints its request and response with timing, headers and bodies. Turn on curl: 'on-failure' and get a command you can paste into a shell, including multipart, redirects and cookies.
Colourful API request logs with replayable curl, and a per-test browser timeline with secrets masked, quiet while tests pass and attached to the report when they fail.
npm i -D playwright-logger-pro
Running 3 tests using 1 worker
✓ 1 [chromium] › cart.spec.ts:8:5 › adds product to cart (1.2s)
GET 200 https://api.shop.test/v1/products?page=2&limit=20 148ms
POST 201 https://api.shop.test/v1/cart/items 86ms
PUT 200 https://api.shop.test/v1/cart/items/42 95ms
✘ 2 [chromium] › checkout.spec.ts:21:5 › places an order (2.4s)
GET 404 https://api.shop.test/v1/orders/99999 70ms
│ ← 404 Not Found {"error":"order not found"}
POST 500 https://api.shop.test/v1/checkout?token=***¤cy=EUR ▲ 1.83s
│ ← 500 Internal Server Error {"error":"payment gateway timeout"}
│
│ curl -X POST 'https://api.shop.test/v1/checkout?token=***¤cy=EUR' \
│ -H 'Authorization: ***' \
│ -H 'Content-Type: application/json' \
│ --data-raw '{"cartId":"c_812","cardToken":"***"}'
│
│ ↳ replay: curl.sh attached to the HTML report
✓ 3 [chromium] › profile.spec.ts:14:5 › updates profile and clears sessions (653ms)
PATCH 204 https://api.shop.test/v1/users/7 65ms
DELETE 204 https://api.shop.test/v1/sessions/old 44ms
GET 304 https://cdn.shop.test/assets/catalog.json 10ms
1 failed
[chromium] › checkout.spec.ts:21:5 › places an order
2 passed (5.4s)
8 requests · 2 errors · 1 slow ≥1sEvery request.get/post/… prints its request and response with timing, headers and bodies. Turn on curl: 'on-failure' and get a command you can paste into a shell, including multipart, redirects and cookies.
Clicks, fills, navigations, console messages, page errors, dialogs and test.step markers, each with a duration. Quiet while a test passes; printed and attached to the report when it fails.
Authorization headers, cookies, token-like query parameters and password fields are masked, and so is anything you list in redact.values. Values you type into a sensitive field are learned for the rest of the test.
One block, printed once and attached to the report as browser-log. Passwords stay ***.
── browser log · login.spec.ts › rejects a wrong password · failed ──
+0.874s page#1 opened
+0.878s ✓ page.goto('/login') 103ms
+0.983s ▸ Log in
+0.986s │ ✓ getByLabel('Email').fill('jo@example.com') 78ms
+1.065s │ ✓ getByLabel('Password').fill(***) 19ms
+1.085s │ ✓ getByRole('button', { name: 'Sign in' }).click() 54ms
+1.139s ⚠ console.error Failed to load resource: the server responded with a status of 401 (Unauthorized) (session:0)
+1.139s ◂ Log in passed 156ms
+1.140s ✗ locator('.toast-success').click({ timeout: 1500 }) 1501ms TimeoutError: frame.click: Timeout 1500ms exceeded.
+2.653s page#1 closed