@testrelic/playwright-analytics 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +201 -164
  2. package/package.json +24 -3
package/README.md CHANGED
@@ -1,42 +1,29 @@
1
- # @testrelic/playwright-analytics
1
+ # TestRelic
2
2
 
3
- A Playwright custom reporter and navigation-tracking fixture that produces a structured JSON timeline of every page visit, network request, and test result in your test suite.
3
+ A test analytics toolkit that generates structured JSON and HTML reports from your Playwright test runs — capturing navigation timelines, API call tracking, network statistics, failure diagnostics, and CI metadata. Supports browser E2E tests, API-only tests, and unified workflows that combine both.
4
4
 
5
5
  ## What It Does
6
6
 
7
- When you run your Playwright tests with this SDK, it generates a single JSON report that captures:
7
+ When you run your Playwright tests with the TestRelic reporter and fixture, you get a JSON + HTML report that captures:
8
8
 
9
- - **Navigation timeline** — Every URL visited during each test, in chronological order
10
- - **Network statistics** — Total requests, bytes transferred, and breakdowns by resource type (scripts, images, stylesheets, fonts, XHR, etc.)
11
- - **Test results** — Pass/fail status, duration, retry count, and tags for every test
12
- - **Failure diagnostics** — Error messages, stack traces, and source code snippets pointing to the exact line that failed
13
- - **CI metadata** — Automatic detection of GitHub Actions, GitLab CI, Jenkins, and CircleCI with build ID, commit SHA, and branch
14
- - **SPA detection** — Tracks `pushState`, `replaceState`, `popstate`, and `hashchange` navigations in single-page applications
15
- - **Sensitive data redaction** — Automatically scrubs AWS keys, Bearer tokens, private keys, and credential URLs from the report
9
+ - **Navigation timeline** — Every URL visited during each test, in chronological order, with navigation type detection (goto, link click, back/forward, SPA route changes, hash changes)
10
+ - **API call tracking** — Captures HTTP method, URL, status code, request/response headers and bodies, response times, and assertions for every API call
11
+ - **Network statistics** — Total requests, failed requests, bytes transferred, and resource type breakdowns (scripts, images, stylesheets, fonts, XHR)
12
+ - **Test results** — Pass/fail/flaky status, duration, retry count, and tags for every test
13
+ - **Failure diagnostics** — Error messages, source code snippets pointing to the exact failure line, and optional stack traces
14
+ - **CI metadata** — Auto-detection of GitHub Actions, GitLab CI, Jenkins, and CircleCI with build ID, commit SHA, and branch
15
+ - **Sensitive data redaction** — Automatically scrubs AWS keys, Bearer tokens, private keys, credential URLs, and sensitive API headers/body fields
16
+ - **HTML report** — Self-contained interactive HTML report with test grid, filter bar, and expandable drawer showing navigation timeline, API call details, and artifacts
16
17
 
17
- ## Prerequisites
18
-
19
- - **Node.js** >= 18
20
- - **Playwright** >= 1.35.0
21
- - **Package manager**: npm, pnpm, or yarn
18
+ ## Quick Start
22
19
 
23
- ## Installation
20
+ ### 1. Install
24
21
 
25
22
  ```bash
26
23
  npm install @testrelic/playwright-analytics
27
24
  ```
28
25
 
29
- ```bash
30
- pnpm add @testrelic/playwright-analytics
31
- ```
32
-
33
- ```bash
34
- yarn add @testrelic/playwright-analytics
35
- ```
36
-
37
- ## Quick Start
38
-
39
- ### 1. Add the reporter to your Playwright config
26
+ ### 2. Add the reporter to your Playwright config
40
27
 
41
28
  ```typescript
42
29
  // playwright.config.ts
@@ -55,68 +42,61 @@ export default defineConfig({
55
42
  });
56
43
  ```
57
44
 
58
- ### 2. Use the fixture in your tests
45
+ ### 3. Use the fixture in your tests
46
+
47
+ TestRelic provides two fixture modes depending on your testing needs:
59
48
 
60
- Replace your Playwright `test` import with the TestRelic fixture to enable automatic navigation tracking:
49
+ **E2E tests (browser)** — uses `page` for navigation tracking:
61
50
 
62
51
  ```typescript
63
- // my-test.spec.ts
64
52
  import { test, expect } from '@testrelic/playwright-analytics/fixture';
65
53
 
66
- test('homepage loads correctly', async ({ page }) => {
54
+ test('homepage loads correctly', { tag: ['@e2e'] }, async ({ page }) => {
67
55
  await page.goto('https://example.com');
68
56
  await expect(page.locator('h1')).toBeVisible();
69
57
  });
70
58
  ```
71
59
 
72
- That's it. Run your tests as usual:
60
+ **API tests** uses `request` for API call tracking:
73
61
 
74
- ```bash
75
- npx playwright test
62
+ ```typescript
63
+ import { test as base } from '@playwright/test';
64
+ import { testRelicApiFixture } from '@testrelic/playwright-analytics/api-fixture';
65
+ import { expect } from '@testrelic/playwright-analytics/fixture';
66
+
67
+ const test = base.extend(testRelicApiFixture);
68
+
69
+ test('fetch posts', { tag: ['@api'] }, async ({ request }) => {
70
+ const response = await request.get('https://api.example.com/posts');
71
+ expect(response.status()).toBe(200);
72
+ });
76
73
  ```
77
74
 
78
- The JSON report will be written to `./test-results/analytics-timeline.json` (or wherever you set `outputPath`).
75
+ **Unified tests (browser + API)** uses both `page` and `request` together:
79
76
 
80
- ## Configuration Options
77
+ ```typescript
78
+ import { test, expect } from '@testrelic/playwright-analytics/fixture';
81
79
 
82
- All options are passed as the second element of the reporter tuple in your Playwright config:
80
+ test('API data matches UI', { tag: ['@e2e', '@api'] }, async ({ page, request }) => {
81
+ // API call
82
+ const apiResponse = await request.get('https://api.example.com/user/1');
83
+ const user = await apiResponse.json();
83
84
 
84
- | Option | Type | Default | Description |
85
- |---|---|---|---|
86
- | `outputPath` | `string` | `./test-results/analytics-timeline.json` | Where to write the JSON report |
87
- | `includeStackTrace` | `boolean` | `false` | Include full stack traces in failure diagnostics |
88
- | `includeCodeSnippets` | `boolean` | `true` | Include source code snippets around the failure line |
89
- | `codeContextLines` | `number` | `3` | Number of lines above/below the failure line to include |
90
- | `includeNetworkStats` | `boolean` | `true` | Track network requests and byte sizes per navigation |
91
- | `navigationTypes` | `NavigationType[] \| null` | `null` (all) | Filter timeline to specific navigation types only |
92
- | `redactPatterns` | `(string \| RegExp)[]` | Built-in patterns | Additional patterns to redact from error messages and stacks |
93
- | `testRunId` | `string \| null` | `null` (auto UUID) | Override the test run ID |
94
- | `metadata` | `Record<string, unknown> \| null` | `null` | Attach custom metadata to the report |
85
+ // Browser navigation
86
+ await page.goto('https://example.com/profile');
87
+ await expect(page.locator('.user-name')).toHaveText(user.name);
88
+ });
89
+ ```
95
90
 
96
- ### Configuration Example
91
+ ### 4. Run your tests
97
92
 
98
- ```typescript
99
- ['@testrelic/playwright-analytics', {
100
- outputPath: './reports/timeline.json',
101
- includeStackTrace: true,
102
- includeCodeSnippets: true,
103
- codeContextLines: 5,
104
- includeNetworkStats: true,
105
- navigationTypes: ['goto', 'navigation', 'back', 'forward'],
106
- metadata: {
107
- team: 'frontend',
108
- environment: 'staging',
109
- },
110
- redactPatterns: [
111
- /my-secret-pattern/g,
112
- 'literal-string-to-redact',
113
- ],
114
- }]
93
+ ```bash
94
+ npx playwright test
115
95
  ```
116
96
 
117
- ## Output Format
97
+ The JSON report will be written to `./test-results/analytics-timeline.json` and the HTML report to `./test-results/analytics-timeline.html`.
118
98
 
119
- The report is a single JSON file with this structure:
99
+ ## Output Example
120
100
 
121
101
  ```jsonc
122
102
  {
@@ -132,17 +112,20 @@ The report is a single JSON file with this structure:
132
112
  "flaky": 0,
133
113
  "skipped": 0
134
114
  },
135
- "ci": null, // Auto-populated in CI environments
136
- "metadata": null, // Custom metadata from config
115
+ "ci": {
116
+ "provider": "github-actions",
117
+ "buildId": "12345678",
118
+ "commitSha": "abc123def456",
119
+ "branch": "main"
120
+ },
137
121
  "timeline": [
138
122
  {
139
123
  "url": "https://en.wikipedia.org/wiki/Main_Page",
140
124
  "navigationType": "goto",
141
125
  "visitedAt": "2026-02-07T10:41:29.844Z",
142
126
  "duration": 216,
143
- "specFile": "sdk-validation.spec.ts",
127
+ "specFile": "tests/homepage.spec.ts",
144
128
  "domContentLoadedAt": "2026-02-07T10:41:30.200Z",
145
- "networkIdleAt": null,
146
129
  "networkStats": {
147
130
  "totalRequests": 40,
148
131
  "failedRequests": 0,
@@ -159,103 +142,120 @@ The report is a single JSON file with this structure:
159
142
  },
160
143
  "tests": [
161
144
  {
162
- "title": "sdk-validation.spec.ts > SDK E2E Validation > homepage visit",
145
+ "title": "homepage.spec.ts > Homepage > loads correctly",
163
146
  "status": "passed",
164
147
  "duration": 1028,
165
- "startedAt": "2026-02-07T10:41:29.133Z",
166
- "completedAt": "2026-02-07T10:41:30.161Z",
167
- "retryCount": 0,
168
- "tags": [],
169
148
  "failure": null
170
149
  }
171
150
  ]
172
151
  }
173
- // ... more timeline entries
174
- ],
175
- "shardRunIds": null // Populated when merging shard reports
152
+ ]
176
153
  }
177
154
  ```
178
155
 
179
- ### Timeline Entry Fields
180
-
181
- | Field | Type | Description |
182
- |---|---|---|
183
- | `url` | `string` | The URL that was navigated to |
184
- | `navigationType` | `string` | How the navigation happened (see navigation types below) |
185
- | `visitedAt` | `string` | ISO-8601 timestamp of the navigation |
186
- | `duration` | `number` | Milliseconds until the next navigation or test end |
187
- | `specFile` | `string` | Relative path to the spec file |
188
- | `domContentLoadedAt` | `string \| null` | When DOMContentLoaded fired |
189
- | `networkIdleAt` | `string \| null` | When network became idle |
190
- | `networkStats` | `object \| null` | Network request statistics for this navigation |
191
- | `tests` | `array` | Test results associated with this navigation |
192
-
193
- ### Navigation Types
194
-
195
- | Type | Description |
196
- |---|---|
197
- | `goto` | `page.goto()` call |
198
- | `navigation` | Browser frame navigation (link click, form submit) |
199
- | `back` | `page.goBack()` call |
200
- | `forward` | `page.goForward()` call |
201
- | `refresh` | `page.reload()` call |
202
- | `spa_route` | `history.pushState()` detected |
203
- | `spa_replace` | `history.replaceState()` detected |
204
- | `hash_change` | URL hash change |
205
- | `popstate` | Browser back/forward via popstate event |
206
-
207
- ### Network Stats
208
-
209
- When `includeNetworkStats` is enabled, each timeline entry includes:
210
-
211
- ```json
212
- {
213
- "totalRequests": 40,
214
- "failedRequests": 0,
215
- "totalBytes": 1289736,
216
- "byType": {
217
- "xhr": 0,
218
- "document": 1,
219
- "script": 9,
220
- "stylesheet": 2,
221
- "image": 27,
222
- "font": 2,
223
- "other": 0
224
- }
225
- }
226
- ```
156
+ ## Configuration
227
157
 
228
- ### Failure Diagnostics
158
+ All options are passed as the second element of the reporter tuple:
229
159
 
230
- When a test fails, the report includes diagnostic details:
160
+ ### General Options
231
161
 
232
- ```json
233
- {
234
- "message": "expect(received).toBe(expected) // Object.is equality\n\nExpected: 3\nReceived: 2",
235
- "line": 70,
236
- "code": " 67 | test('deliberate failure', async ({ page }) => {\n 68 | await page.goto('https://example.com');\n 69 | // This assertion will fail\n> 70 | expect(1 + 1).toBe(3);\n 71 | });",
237
- "stack": "Error: expect(received).toBe(expected)\n at /path/to/spec.ts:70:19"
238
- }
162
+ | Option | Type | Default | Description |
163
+ |---|---|---|---|
164
+ | `outputPath` | `string` | `./test-results/analytics-timeline.json` | Where to write the JSON report |
165
+ | `includeStackTrace` | `boolean` | `false` | Include full stack traces in failure diagnostics |
166
+ | `includeCodeSnippets` | `boolean` | `true` | Include source code snippets around the failure line |
167
+ | `codeContextLines` | `number` | `3` | Lines of context above/below the failure line |
168
+ | `includeNetworkStats` | `boolean` | `true` | Track network requests and bytes per navigation |
169
+ | `includeArtifacts` | `boolean` | `true` | Include screenshots and video in the report |
170
+ | `navigationTypes` | `NavigationType[] \| null` | `null` (all) | Filter timeline to specific navigation types |
171
+ | `redactPatterns` | `(string \| RegExp)[]` | Built-in patterns | Additional patterns to redact from error output |
172
+ | `testRunId` | `string \| null` | `null` (auto UUID) | Override the test run ID |
173
+ | `metadata` | `Record<string, unknown> \| null` | `null` | Attach custom metadata to the report |
174
+ | `openReport` | `boolean` | `true` | Auto-open the HTML report after test run |
175
+ | `quiet` | `boolean` | `false` | Suppress TestRelic banner output |
176
+
177
+ ### API Tracking Options
178
+
179
+ | Option | Type | Default | Description |
180
+ |---|---|---|---|
181
+ | `trackApiCalls` | `boolean` | `true` | Enable/disable API call tracking entirely |
182
+ | `captureRequestHeaders` | `boolean` | `true` | Capture request headers for each API call |
183
+ | `captureResponseHeaders` | `boolean` | `true` | Capture response headers for each API call |
184
+ | `captureRequestBody` | `boolean` | `true` | Capture request body/payload for each API call |
185
+ | `captureResponseBody` | `boolean` | `true` | Capture response body for each API call |
186
+ | `captureAssertions` | `boolean` | `true` | Track assertion results (pass/fail with expected/actual values) |
187
+ | `redactHeaders` | `string[]` | `['authorization', 'cookie', 'set-cookie', 'x-api-key']` | Header names to redact (case-insensitive) |
188
+ | `redactBodyFields` | `string[]` | `['password', 'secret', 'token', 'apiKey', 'api_key']` | Body field names whose values are replaced with `[REDACTED]` |
189
+ | `apiIncludeUrls` | `(string \| RegExp)[]` | `[]` (all URLs) | Only track API calls matching these patterns |
190
+ | `apiExcludeUrls` | `(string \| RegExp)[]` | `[]` (none excluded) | Exclude API calls matching these patterns |
191
+
192
+ ### Configuration Examples
193
+
194
+ **Default (zero config)** — captures everything with built-in redaction:
195
+
196
+ ```typescript
197
+ reporter: [
198
+ ['list'],
199
+ ['@testrelic/playwright-analytics', {
200
+ outputPath: './test-results/analytics-timeline.json',
201
+ }],
202
+ ]
239
203
  ```
240
204
 
241
- ### CI Metadata
205
+ **Minimal capture (no bodies)** — reduces report size, tracks only method/URL/status/timing:
242
206
 
243
- When running in a supported CI environment, the `ci` field is auto-populated:
207
+ ```typescript
208
+ reporter: [
209
+ ['list'],
210
+ ['@testrelic/playwright-analytics', {
211
+ outputPath: './test-results/analytics-timeline.json',
212
+ captureRequestBody: false,
213
+ captureResponseBody: false,
214
+ }],
215
+ ]
216
+ ```
244
217
 
245
- ```json
246
- {
247
- "provider": "github-actions",
248
- "buildId": "12345678",
249
- "commitSha": "abc123def456",
250
- "branch": "main"
251
- }
218
+ **URL filtering** — only track specific endpoints:
219
+
220
+ ```typescript
221
+ reporter: [
222
+ ['list'],
223
+ ['@testrelic/playwright-analytics', {
224
+ outputPath: './test-results/analytics-timeline.json',
225
+ apiIncludeUrls: ['**/api/**'],
226
+ apiExcludeUrls: ['**/health', '**/metrics'],
227
+ }],
228
+ ]
252
229
  ```
253
230
 
254
- Supported providers: **GitHub Actions**, **GitLab CI**, **Jenkins**, **CircleCI**.
231
+ **Custom redaction** add your own sensitive header/body field names:
232
+
233
+ ```typescript
234
+ reporter: [
235
+ ['list'],
236
+ ['@testrelic/playwright-analytics', {
237
+ outputPath: './test-results/analytics-timeline.json',
238
+ redactHeaders: ['authorization', 'cookie', 'set-cookie', 'x-api-key', 'x-custom-secret'],
239
+ redactBodyFields: ['password', 'secret', 'token', 'ssn', 'creditCard'],
240
+ }],
241
+ ]
242
+ ```
243
+
244
+ **Disable API tracking** — browser-only report with no API call data:
245
+
246
+ ```typescript
247
+ reporter: [
248
+ ['list'],
249
+ ['@testrelic/playwright-analytics', {
250
+ outputPath: './test-results/analytics-timeline.json',
251
+ trackApiCalls: false,
252
+ }],
253
+ ]
254
+ ```
255
255
 
256
256
  ## Merging Shard Reports
257
257
 
258
- When running Playwright with sharding, each shard produces its own report. Use the CLI to merge them:
258
+ When running Playwright with sharding, each shard produces its own report. Merge them with the CLI:
259
259
 
260
260
  ```bash
261
261
  npx testrelic merge shard-1.json shard-2.json shard-3.json -o merged-report.json
@@ -266,38 +266,75 @@ Or programmatically:
266
266
  ```typescript
267
267
  import { mergeReports } from '@testrelic/playwright-analytics/merge';
268
268
 
269
- const merged = await mergeReports(
269
+ await mergeReports(
270
270
  ['shard-1.json', 'shard-2.json'],
271
271
  { output: 'merged-report.json' }
272
272
  );
273
273
  ```
274
274
 
275
- The merged report combines all timelines chronologically, recalculates the summary, and records the original shard run IDs.
275
+ ## Testing Modes
276
+
277
+ TestRelic supports three testing modes, each with its own fixture:
278
+
279
+ ### E2E Testing (Browser)
276
280
 
277
- ## Security
281
+ Use the unified fixture which provides `page` with navigation tracking — page load timing, DOM content loaded, network idle detection, and network request statistics.
282
+
283
+ ```typescript
284
+ import { test, expect } from '@testrelic/playwright-analytics/fixture';
278
285
 
279
- The reporter automatically redacts sensitive data from error messages, stack traces, and code snippets before writing the report:
286
+ test('search works', { tag: ['@e2e'] }, async ({ page }) => {
287
+ await page.goto('https://example.com');
288
+ await page.fill('#search', 'query');
289
+ await page.click('button[type=submit]');
290
+ });
291
+ ```
280
292
 
281
- - AWS access key IDs (`AKIA...`)
282
- - Bearer tokens (`Bearer eyJ...`)
283
- - Private keys (`-----BEGIN PRIVATE KEY-----`)
284
- - Credential URLs (`//user:password@host`)
293
+ ### API Testing
285
294
 
286
- You can add custom redaction patterns via the `redactPatterns` config option.
295
+ Use the API-only fixture which provides `request` without any browser dependency — tracks HTTP method, URL, status code, headers, bodies, response times, and assertions.
287
296
 
288
- ## How It Works
297
+ ```typescript
298
+ import { test as base } from '@playwright/test';
299
+ import { testRelicApiFixture } from '@testrelic/playwright-analytics/api-fixture';
300
+ import { expect } from '@testrelic/playwright-analytics/fixture';
289
301
 
290
- The SDK has two components that work together:
302
+ const test = base.extend(testRelicApiFixture);
291
303
 
292
- 1. **Fixture** (`@testrelic/playwright-analytics/fixture`) — Wraps the Playwright `page` object with a `NavigationTracker` that intercepts `goto`, `goBack`, `goForward`, and `reload` calls, listens for `framenavigated` events, injects a script to detect SPA navigations, and optionally tracks network responses. All tracked data is written as test annotations.
304
+ test('CRUD operations', { tag: ['@api'] }, async ({ request }) => {
305
+ const response = await request.post('https://api.example.com/posts', {
306
+ data: { title: 'New Post', body: 'Content' },
307
+ });
308
+ expect(response.status()).toBe(201);
309
+ });
310
+ ```
293
311
 
294
- 2. **Reporter** (`@testrelic/playwright-analytics`) — A Playwright custom reporter that collects test results and navigation annotations in `onTestEnd`, then on `onEnd` builds the final JSON timeline, detects CI metadata, applies redaction, and writes the report atomically (write to temp file, then rename).
312
+ ### Unified Testing (Browser + API)
295
313
 
296
- The reporter never throws during test executionall hooks are wrapped in try/catch to ensure it never crashes your test run.
314
+ Use the unified fixture which provides **both** `page` and `request` the TestRelic report shows navigation timeline AND API call details for the same test. This is ideal for:
297
315
 
298
- ## Using Without the Fixture
316
+ - **Contract testing**: Verify API data matches what the browser renders
317
+ - **Setup/teardown via API**: Use API calls to set up test data, then verify in the browser
318
+ - **Full-stack workflows**: Test end-to-end flows that span both UI and API layers
299
319
 
300
- The reporter works without the fixture, but navigation tracking will not be available. Tests will still be captured with their pass/fail status, duration, and failure diagnostics. The timeline entries will show `about:blank` as the URL with `dummy` navigation type.
320
+ ```typescript
321
+ import { test, expect } from '@testrelic/playwright-analytics/fixture';
322
+
323
+ test('API data matches UI', { tag: ['@e2e', '@api'] }, async ({ page, request }) => {
324
+ // Fetch data via API
325
+ const apiResponse = await request.get('https://api.example.com/user/1');
326
+ const user = await apiResponse.json();
327
+
328
+ // Verify it renders correctly in the browser
329
+ await page.goto('https://example.com/profile');
330
+ await expect(page.locator('.user-name')).toHaveText(user.name);
331
+ });
332
+ ```
333
+
334
+ ## Prerequisites
335
+
336
+ - **Node.js** >= 18
337
+ - **Playwright** >= 1.35.0
301
338
 
302
339
  ## License
303
340
 
package/package.json CHANGED
@@ -1,7 +1,27 @@
1
1
  {
2
2
  "name": "@testrelic/playwright-analytics",
3
- "version": "2.0.0",
4
- "description": "Playwright custom reporter and navigation-tracking fixture for test analytics",
3
+ "version": "2.1.1",
4
+ "description": "Playwright test analytics reporter with E2E navigation tracking, API call capture, network stats, failure diagnostics, and interactive HTML reports",
5
+ "keywords": [
6
+ "playwright",
7
+ "test",
8
+ "analytics",
9
+ "reporter",
10
+ "api-testing",
11
+ "e2e-testing",
12
+ "navigation",
13
+ "network",
14
+ "html-report",
15
+ "test-results",
16
+ "api-tracking",
17
+ "assertions",
18
+ "redaction",
19
+ "ci",
20
+ "testing",
21
+ "test-automation",
22
+ "playwright-reporter"
23
+ ],
24
+ "author": "TestRelic AI <hello@testrelic.ai>",
5
25
  "type": "module",
6
26
  "main": "./dist/index.cjs",
7
27
  "module": "./dist/index.js",
@@ -54,7 +74,8 @@
54
74
  },
55
75
  "files": [
56
76
  "dist",
57
- "timeline-schema.json"
77
+ "timeline-schema.json",
78
+ "README.md"
58
79
  ],
59
80
  "scripts": {
60
81
  "build": "tsup",