@testrelic/playwright-analytics 2.2.4 → 2.2.6

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.
package/README.md CHANGED
@@ -13,8 +13,10 @@ When you run your Playwright tests with the TestRelic reporter and fixture, you
13
13
  - **Failure diagnostics** — Error messages, source code snippets pointing to the exact failure line, and optional stack traces
14
14
  - **CI metadata** — Auto-detection of GitHub Actions, GitLab CI, Jenkins, and CircleCI with build ID, commit SHA, and branch
15
15
  - **Sensitive data redaction** — Automatically scrubs AWS keys, Bearer tokens, private keys, credential URLs, and sensitive API headers/body fields
16
- - **Action steps** — Captures Playwright test steps (UI actions, assertions, custom test.step blocks) with timing, category badges, and video offset synchronization
17
- - **HTML report** — Self-contained interactive HTML report with test grid, filter bar, and expandable drawer showing navigation timeline, action steps with video sync, API call details, and artifacts
16
+ - **Action steps** — Captures Playwright test steps (actions, assertions, custom steps) with video timestamp sync
17
+ - **Console log capture** — Collects browser console messages (log, warn, error) per test
18
+ - **Screenshots & videos** — Automatically captures screenshots and video recordings, organized per test in an `artifacts/` folder alongside the report
19
+ - **HTML report** — Self-contained interactive HTML report with test grid, filter bar, and expandable drawer showing navigation timeline, API call details, and artifacts
18
20
 
19
21
  ## Quick Start
20
22
 
@@ -26,6 +28,30 @@ npm install @testrelic/playwright-analytics
26
28
 
27
29
  ### 2. Add the reporter to your Playwright config
28
30
 
31
+ **Option A: Use `defineConfig` (recommended)** — automatically enables video, screenshots, trace capture, and the TestRelic reporter:
32
+
33
+ ```typescript
34
+ // playwright.config.ts
35
+ import { defineConfig } from '@testrelic/playwright-analytics';
36
+
37
+ export default defineConfig({
38
+ testDir: './tests',
39
+ // video: 'on', screenshot: 'on', trace: 'on', and the TestRelic reporter
40
+ // are all configured automatically. Override any of these in `use:` if needed.
41
+ });
42
+ ```
43
+
44
+ You can pass reporter-specific options as a second argument:
45
+
46
+ ```typescript
47
+ export default defineConfig(
48
+ { testDir: './tests' },
49
+ { includeStackTrace: true, includeCodeSnippets: true },
50
+ );
51
+ ```
52
+
53
+ **Option B: Manual setup** — configure Playwright and the reporter separately:
54
+
29
55
  ```typescript
30
56
  // playwright.config.ts
31
57
  import { defineConfig } from '@playwright/test';
@@ -43,6 +69,8 @@ export default defineConfig({
43
69
  });
44
70
  ```
45
71
 
72
+ > **Note:** When using `defineConfig` from `@testrelic/playwright-analytics`, Playwright's default `list` reporter is preserved automatically so CLI commands like `npx playwright test --list` continue to work.
73
+
46
74
  ### 3. Use the fixture in your tests
47
75
 
48
76
  TestRelic provides two fixture modes depending on your testing needs:
@@ -168,12 +196,13 @@ All options are passed as the second element of the reporter tuple:
168
196
  | `codeContextLines` | `number` | `3` | Lines of context above/below the failure line |
169
197
  | `includeNetworkStats` | `boolean` | `true` | Track network requests and bytes per navigation |
170
198
  | `includeArtifacts` | `boolean` | `true` | Include screenshots and video in the report |
199
+ | `includeActionSteps` | `boolean` | `true` | Capture Playwright test steps (actions, assertions, custom steps) with video sync |
200
+ | `captureConsoleLogs` | `boolean` | `true` | Capture browser console messages (log, warn, error) per test |
171
201
  | `navigationTypes` | `NavigationType[] \| null` | `null` (all) | Filter timeline to specific navigation types |
172
202
  | `redactPatterns` | `(string \| RegExp)[]` | Built-in patterns | Additional patterns to redact from error output |
173
203
  | `testRunId` | `string \| null` | `null` (auto UUID) | Override the test run ID |
174
204
  | `metadata` | `Record<string, unknown> \| null` | `null` | Attach custom metadata to the report |
175
205
  | `openReport` | `boolean` | `true` | Auto-open the HTML report after test run |
176
- | `includeActionSteps` | `boolean` | `true` | Capture Playwright test steps (actions, assertions, custom steps) with video sync |
177
206
  | `quiet` | `boolean` | `false` | Suppress TestRelic banner output |
178
207
 
179
208
  ### API Tracking Options
@@ -255,6 +284,81 @@ reporter: [
255
284
  ]
256
285
  ```
257
286
 
287
+ ## Screenshots & Videos
288
+
289
+ When using `defineConfig` from `@testrelic/playwright-analytics`, video recording and screenshot capture are enabled by default (`video: 'on'`, `screenshot: 'on'`). If using manual config, enable them in Playwright's `use` section:
290
+
291
+ ```typescript
292
+ export default defineConfig({
293
+ use: {
294
+ video: 'on',
295
+ screenshot: 'on',
296
+ },
297
+ reporter: [['list'], ['@testrelic/playwright-analytics']],
298
+ });
299
+ ```
300
+
301
+ Artifacts are automatically copied to an `artifacts/` folder next to your report:
302
+
303
+ ```
304
+ test-results/
305
+ ├── analytics-timeline.json
306
+ ├── analytics-timeline.html
307
+ └── artifacts/
308
+ ├── homepage-loads-correctly/
309
+ │ ├── screenshot.png
310
+ │ └── video.webm
311
+ └── search-works--retry-1/
312
+ ├── screenshot.png
313
+ └── video.webm
314
+ ```
315
+
316
+ - Screenshots are captured at the end of each test (`.png`)
317
+ - Videos record the full browser session (`.webm`)
318
+ - Retried tests get separate folders with a `--retry-N` suffix
319
+ - The HTML report embeds links to these artifacts with inline image/video viewers
320
+ - Disable artifact collection with `includeArtifacts: false`
321
+
322
+ ## Action Steps
323
+
324
+ TestRelic captures Playwright test steps — actions (`click`, `fill`, `goto`), assertions (`expect`), and custom steps (`test.step()`). Steps are timestamped and synced with the video timeline so you can jump to the exact moment in the recording.
325
+
326
+ Enable/disable with the `includeActionSteps` option (default: `true`):
327
+
328
+ ```typescript
329
+ ['@testrelic/playwright-analytics', {
330
+ includeActionSteps: true,
331
+ }]
332
+ ```
333
+
334
+ In the HTML report, action steps appear in the test drawer alongside the navigation timeline, showing:
335
+ - Step category (action, assertion, or custom)
336
+ - Step title and duration
337
+ - Video timestamp for playback sync
338
+
339
+ ## Console Log Capture
340
+
341
+ TestRelic captures browser console messages (`log`, `warn`, `error`) per test. Useful for debugging test failures without re-running.
342
+
343
+ Enable/disable with the `captureConsoleLogs` option (default: `true`):
344
+
345
+ ```typescript
346
+ ['@testrelic/playwright-analytics', {
347
+ captureConsoleLogs: true,
348
+ }]
349
+ ```
350
+
351
+ ## Network Statistics
352
+
353
+ Each navigation in the timeline includes detailed network statistics:
354
+
355
+ - **Total requests** — number of network requests during the navigation
356
+ - **Failed requests** — count and URLs of failed requests (useful for spotting broken assets)
357
+ - **Bytes transferred** — total bytes received
358
+ - **Resource breakdown** — requests grouped by type: `xhr`, `document`, `script`, `stylesheet`, `image`, `font`, `other`
359
+
360
+ Disable with `includeNetworkStats: false`.
361
+
258
362
  ## Merging Shard Reports
259
363
 
260
364
  When running Playwright with sharding, each shard produces its own report. Merge them with the CLI:
@@ -1,2 +1,2 @@
1
- 'use strict';var perf_hooks=require('perf_hooks');require('fs');var core=require('@testrelic/core'),test=require('@playwright/test');var I=Symbol.for("__testrelic_call_id"),F="__testrelic_api_assertions",T=new WeakMap,C=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(t){this.assertions.push(t);}getAssertions(){return this.assertions}setCurrentCallId(t){this.currentCallId=t;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(t){this.assertions.length!==0&&t.annotations.push({type:F,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}};var O="[REDACTED]";function x(r,t){if(r===null||t.length===0)return r;let e=new Set(t.map(s=>s.toLowerCase())),n={};for(let s of Object.keys(r))Object.hasOwn(r,s)&&(n[s]=e.has(s.toLowerCase())?O:r[s]);return n}function N(r,t){if(r===null||t.length===0)return r;let e;try{e=JSON.parse(r);}catch{return r}if(typeof e!="object"||e===null)return r;let n=new Set(t),s=S(e,n);return JSON.stringify(s)}function S(r,t){if(Array.isArray(r))return r.map(e=>S(e,t));if(typeof r=="object"&&r!==null){let e={};for(let n of Object.keys(r)){if(!Object.hasOwn(r,n))continue;let s=r[n];t.has(n)?e[n]=O:e[n]=S(s,t);}return e}return r}function E(r,t,e){if(e.length>0){for(let n of e)if(D(r,n))return false}if(t.length>0){for(let n of t)if(D(r,n))return true;return false}return true}function D(r,t){try{return t instanceof RegExp?t.test(r):U(t).test(r)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(t)}`),false}}function U(r){let t="",e=0;for(;e<r.length;){let n=r[e];n==="*"&&r[e+1]==="*"?(t+=".*",e+=2,r[e]==="/"&&e++):n==="*"?(t+="[^/]*",e++):n==="?"?(t+="[^/]",e++):".+^${}()|[]\\".includes(n)?(t+="\\"+n,e++):(t+=n,e++);}return new RegExp(t)}var J=["get","post","put","patch","delete","head","fetch"],G=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"],Y="__testrelic_api_calls";function z(r){let t=r.toLowerCase();return G.some(e=>t.includes(e))}function X(r){if(!r)return null;if(r.data!==void 0&&r.data!==null){let t=r.data;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("base64"):JSON.stringify(t)}if(r.form!==void 0&&r.form!==null)return JSON.stringify(r.form);if(r.multipart!==void 0&&r.multipart!==null){let t=r.multipart,e={};for(let[n,s]of Object.entries(t))typeof s=="string"||typeof s=="number"||typeof s=="boolean"?e[n]=String(s):s&&typeof s=="object"&&"name"in s?e[n]=`[file: ${s.name}]`:e[n]="[binary]";return JSON.stringify(e)}return null}var q=class q{constructor(t,e,n){this.originals=new Map;this.capturedCalls=[];this.callCounter=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=t,this.assertionTracker=e??null,this.apiConfig=n??q.DEFAULT_API_CONFIG;}get lastCallId(){return this._lastCallId}getCallIdForValue(t){return t!=null&&typeof t=="object"?T.get(t)??null:this.primitiveCallIds.get(t)??null}intercept(){for(let e of J){let n=this.context[e].bind(this.context);this.originals.set(e,n),this.context[e]=this.createWrapper(e,n);}let t=this.context.dispose.bind(this.context);this.originals.set("dispose",t),this.context.dispose=async e=>(this.disposed=true,t(e));}getData(){return [...this.capturedCalls]}flushLegacyAnnotations(t){this.capturedCalls.length!==0&&t.annotations.push({type:Y,description:JSON.stringify(this.capturedCalls)});}dispose(){for(let[t,e]of this.originals)this.context[t]=e;this.originals.clear(),this.capturedCalls=[],this.callCounter=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCalls(){return this.capturedCalls}tagResponseMethods(t,e){let n=this,s=t.headers.bind(t);t.headers=function(){let o=s();return T.set(o,e),o};let c=t.headersArray.bind(t);t.headersArray=function(){let o=c();return T.set(o,e),o};let d=t.json.bind(t);t.json=async function(){let o=await d();return o!=null&&typeof o=="object"&&T.set(o,e),o};let i=t.status.bind(t);t.status=function(){let o=i();return n.primitiveCallIds.set(o,e),o};let a=t.statusText.bind(t);t.statusText=function(){let o=a();return n.primitiveCallIds.set(o,e),o};let p=t.ok.bind(t);t.ok=function(){let o=p();return n.primitiveCallIds.set(o,e),o};let u=t.text.bind(t);t.text=async function(){let o=await u();return n.primitiveCallIds.set(o,e),o};let g=t.body.bind(t);t.body=async function(){let o=await g();return T.set(o,e),o};}createWrapper(t,e){let n=this;return async function(c,d){if(!E(c,n.apiConfig.apiIncludeUrls,n.apiConfig.apiExcludeUrls))return e(c,d);let i=`api-call-${n.callCounter++}`,a=new Date().toISOString(),p=t==="fetch"?(d?.method??"GET").toUpperCase():t.toUpperCase(),u=X(d),g=perf_hooks.performance.now();n._lastCallId=i,n.assertionTracker&&n.assertionTracker.setCurrentCallId(i);let l;try{l=await e(c,d);}catch(o){let m=perf_hooks.performance.now();try{let w=n.apiConfig.captureRequestBody?N(u,n.apiConfig.redactBodyFields):null,R={id:i,timestamp:a,method:p,url:c,requestHeaders:null,requestBody:w,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((m-g)*100)/100,isBinary:!1,error:o instanceof Error?o.message:String(o)};n.capturedCalls.push(R);}catch{}throw o}try{let o=perf_hooks.performance.now(),m=l.headers(),w=m["content-type"]??null,R=w?!z(w):!1,f=null;n.apiConfig.captureRequestHeaders&&d?.headers&&(f=d.headers);let h=null;n.apiConfig.captureResponseHeaders&&(h=m);let k=n.apiConfig.captureRequestBody?u:null,y=null;if(n.apiConfig.captureResponseBody)try{R?y=(await l.body()).toString("base64"):y=await l.text();}catch{}f=x(f,n.apiConfig.redactHeaders),h=x(h,n.apiConfig.redactHeaders),k=N(k,n.apiConfig.redactBodyFields),y=N(y,n.apiConfig.redactBodyFields);let _={id:i,timestamp:a,method:p,url:l.url(),requestHeaders:f,requestBody:k,responseStatusCode:l.status(),responseStatusText:l.statusText(),responseHeaders:h,responseBody:y,responseTimeMs:Math.round((o-g)*100)/100,isBinary:R,error:null};n.capturedCalls.push(_);}catch{}try{l[I]=i,n.tagResponseMethods(l,i);}catch{}return l}}};q.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var A=q;var W=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function K(r){let t=r.toLowerCase();return W.some(e=>t.includes(e))}function L(r,t){let e=new TextEncoder().encode(r);return e.length<=t?{text:r,truncated:false}:{text:new TextDecoder().decode(e.slice(0,t)),truncated:true}}var v=class{constructor(t,e){this.page=t;this.records=[];this.listeners=[];this.currentNetworkCounter=null;this.pendingRequests=new Map;this.capturedRequests=[];this.pendingBodyReads=[];this.requestIdCounter=0;this.requestCaptureCount=0;this.includeNetworkStats=e?.includeNetworkStats??true,this.origGoto=t.goto.bind(t),this.origGoBack=t.goBack.bind(t),this.origGoForward=t.goForward.bind(t),this.origReload=t.reload.bind(t),this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async getCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[t,e]of this.pendingRequests)this.capturedRequests.push({url:e.url,method:e.method,resourceType:e.resourceType,statusCode:0,responseTimeMs:Date.now()-e.startTimeMs,startedAt:e.startedAt,requestHeaders:e.headers,requestBody:e.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:e.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.pendingRequests.delete(t);return [...this.capturedRequests].sort((t,e)=>t.startedAt.localeCompare(e.startedAt))}async getData(){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});let t=this.records.map(n=>({url:n.url,navigationType:n.navigationType,timestamp:n.timestamp,domContentLoadedAt:n.domContentLoadedAt,networkIdleAt:n.networkIdleAt,networkStats:n.networkStats})),e=this.includeNetworkStats?await this.getCapturedRequests():[];return {navigations:t,networkRequests:e}}async flushLegacyAnnotations(t){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});for(let e of this.records){let n={url:e.url,navigationType:e.navigationType,timestamp:e.timestamp,domContentLoadedAt:e.domContentLoadedAt,networkIdleAt:e.networkIdleAt,networkStats:e.networkStats};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(n)});}if(this.includeNetworkStats){let e=await this.getCapturedRequests();e.length>0&&t.annotations.push({type:"__testrelic_network_requests",description:JSON.stringify(e)});}}dispose(){this.page.goto=this.origGoto,this.page.goBack=this.origGoBack,this.page.goForward=this.origGoForward,this.page.reload=this.origReload;for(let{event:t,handler:e}of this.listeners)this.page.off(t,e);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.capturedRequests=[],this.pendingBodyReads=[],this.requestCaptureCount=0;}getRecords(){return this.records}interceptMethods(){let t=this,e=this.page;e.goto=async function(n,s){return t.recordNavigation(n,"goto"),t.origGoto(n,s)},e.goBack=async function(n){let s=await t.origGoBack(n);return t.recordNavigation(e.url(),"back"),s},e.goForward=async function(n){let s=await t.origGoForward(n);return t.recordNavigation(e.url(),"forward"),s},e.reload=async function(n){return t.recordNavigation(e.url(),"refresh"),t.origReload(n)};}attachListeners(){let t=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",t),this.listeners.push({event:"domcontentloaded",handler:t});let e=s=>{try{let c=s;if(typeof c.parentFrame=="function"&&c.parentFrame()!==null)return;let d=c.url(),i=this.records[this.records.length-1];if(i&&Date.now()-new Date(i.timestamp).getTime()<50&&i.url===d)return;this.recordNavigation(d,"navigation");}catch{}};this.page.on("framenavigated",e),this.listeners.push({event:"framenavigated",handler:e});let n=s=>{try{let c=s;if(c.type()!=="debug")return;let d=c.text();if(!d.startsWith("__testrelic_nav:"))return;let i=JSON.parse(d.slice(16));i.type&&i.url&&this.recordNavigation(i.url,i.type);}catch{}};if(this.page.on("console",n),this.listeners.push({event:"console",handler:n}),this.includeNetworkStats){let s=i=>{if(this.currentNetworkCounter&&this.currentNetworkCounter.totalRequests++,!(this.requestCaptureCount>=500)){this.requestCaptureCount++;try{let a=i,p=String(this.requestIdCounter++),u=a.postData()??null,g=!1;if(u!==null){let o=L(u,10240);u=o.text,g=o.truncated;}let l={url:a.url(),method:a.method(),resourceType:this.mapResourceType(a.resourceType()),headers:a.headers(),postData:u,postDataTruncated:g,startedAt:new Date().toISOString(),startTimeMs:Date.now()};this.pendingRequests.set(p,l),i.__testrelic_id=p;}catch{}}};this.page.on("request",s),this.listeners.push({event:"request",handler:s});let c=i=>{try{let a=i;if(this.currentNetworkCounter){let f=a.status();f>=400&&(this.currentNetworkCounter.failedRequests++,this.currentNetworkCounter.failedRequestUrls.push(f+" "+a.url()));let h=a.headers()["content-length"];h&&(this.currentNetworkCounter.totalBytes+=parseInt(h,10)||0);let k=a.request().resourceType(),y=this.mapResourceType(k);this.currentNetworkCounter.byType[y]++;}let p=a.request().__testrelic_id;if(!p)return;let u=this.pendingRequests.get(p);if(!u)return;this.pendingRequests.delete(p);let g=Date.now()-u.startTimeMs,l=a.headers(),o=l["content-type"]??null,m=parseInt(l["content-length"]??"0",10)||0,w=o?!K(o):!1,R=(async()=>{let f=null,h=!1;if(!w)try{let _=(await a.body()).toString("utf-8"),b=L(_,10240);f=b.text,h=b.truncated;}catch{}let k={url:u.url,method:u.method,resourceType:u.resourceType,statusCode:a.status(),responseTimeMs:g,startedAt:u.startedAt,requestHeaders:u.headers,requestBody:u.postData,responseBody:f,responseHeaders:l,contentType:o,responseSize:m,requestBodyTruncated:u.postDataTruncated,responseBodyTruncated:h,isBinary:w,error:null};this.capturedRequests.push(k);})();this.pendingBodyReads.push(R);}catch{}};this.page.on("response",c),this.listeners.push({event:"response",handler:c});let d=i=>{if(this.currentNetworkCounter){this.currentNetworkCounter.failedRequests++;try{let a=i;this.currentNetworkCounter.failedRequestUrls.push("ERR "+a.url());}catch{}}try{let a=i,p=a.__testrelic_id;if(!p)return;let u=this.pendingRequests.get(p);if(!u)return;this.pendingRequests.delete(p);let g={url:u.url,method:u.method,resourceType:u.resourceType,statusCode:0,responseTimeMs:Date.now()-u.startTimeMs,startedAt:u.startedAt,requestHeaders:u.headers,requestBody:u.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:u.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:a.failure()?.errorText??"Unknown error"};this.capturedRequests.push(g);}catch{}};this.page.on("requestfailed",d),this.listeners.push({event:"requestfailed",handler:d});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let t=history.pushState.bind(history),e=history.replaceState.bind(history);history.pushState=function(...n){t(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...n){e(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(t,e){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}}),this.records.push({url:t,navigationType:e,timestamp:new Date().toISOString()}),this.includeNetworkStats&&(this.currentNetworkCounter=this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}mapResourceType(t){switch(t){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var $="__testrelic_api_config",Z="__testrelic_config_trackApiCalls";function P(r){let t=r.annotations.find(n=>n.type===$&&n.description!==void 0);if(t)try{return JSON.parse(t.description,Q)}catch{}let e=r.annotations.find(n=>n.type===Z&&n.description!==void 0);return e?{trackApiCalls:e.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Q(r,t){if(typeof t=="object"&&t!==null&&t.__regexp===true&&typeof t.source=="string"){let{source:e,flags:n}=t;return new RegExp(e,n)}return t}var tt={page:async({page:r},t,e)=>{let n=new v(r);try{await n.init();}catch{}await t(r);try{let{navigations:s,networkRequests:c}=await n.getData(),d={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:s,networkRequests:c,apiCalls:[],apiAssertions:[]};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(d)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{await n.flushLegacyAnnotations(e);}catch{}n.dispose();},request:async({request:r},t,e)=>{let n=P(e);if(!n.trackApiCalls){await t(r);return}let s=new C,c=new A(r,s,n);c.intercept(),await t(r);try{let d=c.getData(),i=n.captureAssertions?s.getData():[],a={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:d,apiAssertions:i};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(a)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{c.flushLegacyAnnotations(e);}catch{}try{s.flushLegacyAnnotations(e);}catch{}c.dispose(),s.dispose();}};test.test.extend(tt);var bt={request:async({request:r},t,e)=>{let n=P(e);if(!n.trackApiCalls){await t(r);return}let s=new C,c=new A(r,s,n);c.intercept(),await t(r);try{let d=c.getData(),i=n.captureAssertions?s.getData():[],a={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:d,apiAssertions:i};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(a)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{c.flushLegacyAnnotations(e);}catch{}try{s.flushLegacyAnnotations(e);}catch{}c.dispose(),s.dispose();}};exports.testRelicApiFixture=bt;//# sourceMappingURL=api-fixture.cjs.map
1
+ 'use strict';var perf_hooks=require('perf_hooks');require('fs');var core=require('@testrelic/core'),test=require('@playwright/test');var P=Symbol.for("__testrelic_call_id"),F="__testrelic_api_assertions",T=new WeakMap,C=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(t){this.assertions.push(t);}getAssertions(){return this.assertions}setCurrentCallId(t){this.currentCallId=t;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(t){this.assertions.length!==0&&t.annotations.push({type:F,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}};var L="[REDACTED]";function x(r,t){if(r===null||t.length===0)return r;let e=new Set(t.map(s=>s.toLowerCase())),n={};for(let s of Object.keys(r))Object.hasOwn(r,s)&&(n[s]=e.has(s.toLowerCase())?L:r[s]);return n}function v(r,t){if(r===null||t.length===0)return r;let e;try{e=JSON.parse(r);}catch{return r}if(typeof e!="object"||e===null)return r;let n=new Set(t),s=_(e,n);return JSON.stringify(s)}function _(r,t){if(Array.isArray(r))return r.map(e=>_(e,t));if(typeof r=="object"&&r!==null){let e={};for(let n of Object.keys(r)){if(!Object.hasOwn(r,n))continue;let s=r[n];t.has(n)?e[n]=L:e[n]=_(s,t);}return e}return r}function O(r,t,e){if(e.length>0){for(let n of e)if(E(r,n))return false}if(t.length>0){for(let n of t)if(E(r,n))return true;return false}return true}function E(r,t){try{return t instanceof RegExp?t.test(r):U(t).test(r)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(t)}`),false}}function U(r){let t="",e=0;for(;e<r.length;){let n=r[e];n==="*"&&r[e+1]==="*"?(t+=".*",e+=2,r[e]==="/"&&e++):n==="*"?(t+="[^/]*",e++):n==="?"?(t+="[^/]",e++):".+^${}()|[]\\".includes(n)?(t+="\\"+n,e++):(t+=n,e++);}return new RegExp(t)}var J=["get","post","put","patch","delete","head","fetch"],G=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"],W="__testrelic_api_calls";function Y(r){let t=r.toLowerCase();return G.some(e=>t.includes(e))}function $(r){if(!r)return null;if(r.data!==void 0&&r.data!==null){let t=r.data;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("base64"):JSON.stringify(t)}if(r.form!==void 0&&r.form!==null)return JSON.stringify(r.form);if(r.multipart!==void 0&&r.multipart!==null){let t=r.multipart,e={};for(let[n,s]of Object.entries(t))typeof s=="string"||typeof s=="number"||typeof s=="boolean"?e[n]=String(s):s&&typeof s=="object"&&"name"in s?e[n]=`[file: ${s.name}]`:e[n]="[binary]";return JSON.stringify(e)}return null}var N=class N{constructor(t,e,n){this.originals=new Map;this.capturedCalls=[];this.callCounter=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=t,this.assertionTracker=e??null,this.apiConfig=n??N.DEFAULT_API_CONFIG;}get lastCallId(){return this._lastCallId}getCallIdForValue(t){return t!=null&&typeof t=="object"?T.get(t)??null:this.primitiveCallIds.get(t)??null}intercept(){for(let e of J){let n=this.context[e].bind(this.context);this.originals.set(e,n),this.context[e]=this.createWrapper(e,n);}let t=this.context.dispose.bind(this.context);this.originals.set("dispose",t),this.context.dispose=async e=>(this.disposed=true,t(e));}getData(){return [...this.capturedCalls]}flushLegacyAnnotations(t){this.capturedCalls.length!==0&&t.annotations.push({type:W,description:JSON.stringify(this.capturedCalls)});}dispose(){for(let[t,e]of this.originals)this.context[t]=e;this.originals.clear(),this.capturedCalls=[],this.callCounter=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCalls(){return this.capturedCalls}tagResponseMethods(t,e){let n=this,s=t.headers.bind(t);t.headers=function(){let i=s();return T.set(i,e),i};let l=t.headersArray.bind(t);t.headersArray=function(){let i=l();return T.set(i,e),i};let d=t.json.bind(t);t.json=async function(){let i=await d();return i!=null&&typeof i=="object"&&T.set(i,e),i};let c=t.status.bind(t);t.status=function(){let i=c();return n.primitiveCallIds.set(i,e),i};let a=t.statusText.bind(t);t.statusText=function(){let i=a();return n.primitiveCallIds.set(i,e),i};let u=t.ok.bind(t);t.ok=function(){let i=u();return n.primitiveCallIds.set(i,e),i};let o=t.text.bind(t);t.text=async function(){let i=await o();return n.primitiveCallIds.set(i,e),i};let g=t.body.bind(t);t.body=async function(){let i=await g();return T.set(i,e),i};}createWrapper(t,e){let n=this;return async function(l,d){if(!O(l,n.apiConfig.apiIncludeUrls,n.apiConfig.apiExcludeUrls))return e(l,d);let c=`api-call-${n.callCounter++}`,a=new Date().toISOString(),u=t==="fetch"?(d?.method??"GET").toUpperCase():t.toUpperCase(),o=$(d),g=perf_hooks.performance.now();n._lastCallId=c,n.assertionTracker&&n.assertionTracker.setCurrentCallId(c);let p;try{p=await e(l,d);}catch(i){let m=perf_hooks.performance.now();try{let w=n.apiConfig.captureRequestBody?v(o,n.apiConfig.redactBodyFields):null,R={id:c,timestamp:a,method:u,url:l,requestHeaders:null,requestBody:w,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((m-g)*100)/100,isBinary:!1,error:i instanceof Error?i.message:String(i)};n.capturedCalls.push(R);}catch{}throw i}try{let i=perf_hooks.performance.now(),m=p.headers(),w=m["content-type"]??null,R=w?!Y(w):!1,f=null;n.apiConfig.captureRequestHeaders&&d?.headers&&(f=d.headers);let h=null;n.apiConfig.captureResponseHeaders&&(h=m);let k=n.apiConfig.captureRequestBody?o:null,y=null;if(n.apiConfig.captureResponseBody)try{R?y=(await p.body()).toString("base64"):y=await p.text();}catch{}f=x(f,n.apiConfig.redactHeaders),h=x(h,n.apiConfig.redactHeaders),k=v(k,n.apiConfig.redactBodyFields),y=v(y,n.apiConfig.redactBodyFields);let b={id:c,timestamp:a,method:u,url:p.url(),requestHeaders:f,requestBody:k,responseStatusCode:p.status(),responseStatusText:p.statusText(),responseHeaders:h,responseBody:y,responseTimeMs:Math.round((i-g)*100)/100,isBinary:R,error:null};n.capturedCalls.push(b);}catch{}try{p[P]=c,n.tagResponseMethods(p,c);}catch{}return p}}};N.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var A=N;var z=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function X(r){let t=r.toLowerCase();return z.some(e=>t.includes(e))}function D(r,t){let e=new TextEncoder().encode(r);return e.length<=t?{text:r,truncated:false}:{text:new TextDecoder().decode(e.slice(0,t)),truncated:true}}var q=class r{constructor(t,e){this.page=t;this.records=[];this.listeners=[];this.currentNetworkCounter=null;this.pendingRequests=new Map;this.capturedRequests=[];this.pendingBodyReads=[];this.requestIdCounter=0;this.requestCaptureCount=0;this.consoleLogs=[];this.includeNetworkStats=e?.includeNetworkStats??true,this.origGoto=t.goto.bind(t),this.origGoBack=t.goBack.bind(t),this.origGoForward=t.goForward.bind(t),this.origReload=t.reload.bind(t),this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async getCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[t,e]of this.pendingRequests)this.capturedRequests.push({url:e.url,method:e.method,resourceType:e.resourceType,statusCode:0,responseTimeMs:Date.now()-e.startTimeMs,startedAt:e.startedAt,requestHeaders:e.headers,requestBody:e.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:e.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.pendingRequests.delete(t);return [...this.capturedRequests].sort((t,e)=>t.startedAt.localeCompare(e.startedAt))}static mapConsoleType(t){switch(t){case "log":return "log";case "warning":return "warn";case "error":return "error";case "info":return "info";case "debug":return "debug";default:return "log"}}async getData(){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});let t=this.records.map(n=>({url:n.url,navigationType:n.navigationType,timestamp:n.timestamp,domContentLoadedAt:n.domContentLoadedAt,networkIdleAt:n.networkIdleAt,networkStats:n.networkStats})),e=this.includeNetworkStats?await this.getCapturedRequests():[];return {navigations:t,networkRequests:e,consoleLogs:[...this.consoleLogs]}}async flushLegacyAnnotations(t){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});for(let e of this.records){let n={url:e.url,navigationType:e.navigationType,timestamp:e.timestamp,domContentLoadedAt:e.domContentLoadedAt,networkIdleAt:e.networkIdleAt,networkStats:e.networkStats};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(n)});}if(this.includeNetworkStats){let e=await this.getCapturedRequests();e.length>0&&t.annotations.push({type:"__testrelic_network_requests",description:JSON.stringify(e)});}}dispose(){this.page.goto=this.origGoto,this.page.goBack=this.origGoBack,this.page.goForward=this.origGoForward,this.page.reload=this.origReload;for(let{event:t,handler:e}of this.listeners)this.page.off(t,e);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.capturedRequests=[],this.pendingBodyReads=[],this.requestCaptureCount=0;}getRecords(){return this.records}interceptMethods(){let t=this,e=this.page;e.goto=async function(n,s){return t.recordNavigation(n,"goto"),t.origGoto(n,s)},e.goBack=async function(n){let s=await t.origGoBack(n);return t.recordNavigation(e.url(),"back"),s},e.goForward=async function(n){let s=await t.origGoForward(n);return t.recordNavigation(e.url(),"forward"),s},e.reload=async function(n){return t.recordNavigation(e.url(),"refresh"),t.origReload(n)};}attachListeners(){let t=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",t),this.listeners.push({event:"domcontentloaded",handler:t});let e=s=>{try{let l=s;if(typeof l.parentFrame=="function"&&l.parentFrame()!==null)return;let d=l.url(),c=this.records[this.records.length-1];if(c&&Date.now()-new Date(c.timestamp).getTime()<50&&c.url===d)return;this.recordNavigation(d,"navigation");}catch{}};this.page.on("framenavigated",e),this.listeners.push({event:"framenavigated",handler:e});let n=s=>{try{let l=s,d=l.type(),c=l.text();if(d==="debug"&&c.startsWith("__testrelic_nav:")){try{let a=JSON.parse(c.slice(16));a.type&&a.url&&this.recordNavigation(a.url,a.type);}catch{}return}{let a=null;try{let o=l.location();o&&o.url&&(a=`${o.url}:${o.lineNumber}:${o.columnNumber}`);}catch{}let u=r.mapConsoleType(d);this.consoleLogs.push({level:u,text:c,timestamp:new Date().toISOString(),location:a});}}catch{}};if(this.page.on("console",n),this.listeners.push({event:"console",handler:n}),this.includeNetworkStats){let s=c=>{if(this.currentNetworkCounter&&this.currentNetworkCounter.totalRequests++,!(this.requestCaptureCount>=500)){this.requestCaptureCount++;try{let a=c,u=String(this.requestIdCounter++),o=a.postData()??null,g=!1;if(o!==null){let i=D(o,10240);o=i.text,g=i.truncated;}let p={url:a.url(),method:a.method(),resourceType:this.mapResourceType(a.resourceType()),headers:a.headers(),postData:o,postDataTruncated:g,startedAt:new Date().toISOString(),startTimeMs:Date.now()};this.pendingRequests.set(u,p),c.__testrelic_id=u;}catch{}}};this.page.on("request",s),this.listeners.push({event:"request",handler:s});let l=c=>{try{let a=c;if(this.currentNetworkCounter){let f=a.status();f>=400&&(this.currentNetworkCounter.failedRequests++,this.currentNetworkCounter.failedRequestUrls.push(f+" "+a.url()));let h=a.headers()["content-length"];h&&(this.currentNetworkCounter.totalBytes+=parseInt(h,10)||0);let k=a.request().resourceType(),y=this.mapResourceType(k);this.currentNetworkCounter.byType[y]++;}let u=a.request().__testrelic_id;if(!u)return;let o=this.pendingRequests.get(u);if(!o)return;this.pendingRequests.delete(u);let g=Date.now()-o.startTimeMs,p=a.headers(),i=p["content-type"]??null,m=parseInt(p["content-length"]??"0",10)||0,w=i?!X(i):!1,R=(async()=>{let f=null,h=!1;if(!w)try{let b=(await a.body()).toString("utf-8"),S=D(b,10240);f=S.text,h=S.truncated;}catch{}let k={url:o.url,method:o.method,resourceType:o.resourceType,statusCode:a.status(),responseTimeMs:g,startedAt:o.startedAt,requestHeaders:o.headers,requestBody:o.postData,responseBody:f,responseHeaders:p,contentType:i,responseSize:m,requestBodyTruncated:o.postDataTruncated,responseBodyTruncated:h,isBinary:w,error:null};this.capturedRequests.push(k);})();this.pendingBodyReads.push(R);}catch{}};this.page.on("response",l),this.listeners.push({event:"response",handler:l});let d=c=>{if(this.currentNetworkCounter){this.currentNetworkCounter.failedRequests++;try{let a=c;this.currentNetworkCounter.failedRequestUrls.push("ERR "+a.url());}catch{}}try{let a=c,u=a.__testrelic_id;if(!u)return;let o=this.pendingRequests.get(u);if(!o)return;this.pendingRequests.delete(u);let g={url:o.url,method:o.method,resourceType:o.resourceType,statusCode:0,responseTimeMs:Date.now()-o.startTimeMs,startedAt:o.startedAt,requestHeaders:o.headers,requestBody:o.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:o.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:a.failure()?.errorText??"Unknown error"};this.capturedRequests.push(g);}catch{}};this.page.on("requestfailed",d),this.listeners.push({event:"requestfailed",handler:d});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let t=history.pushState.bind(history),e=history.replaceState.bind(history);history.pushState=function(...n){t(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...n){e(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(t,e){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}}),this.records.push({url:t,navigationType:e,timestamp:new Date().toISOString()}),this.includeNetworkStats&&(this.currentNetworkCounter=this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}mapResourceType(t){switch(t){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var V="__testrelic_api_config",Z="__testrelic_config_trackApiCalls";function I(r){let t=r.annotations.find(n=>n.type===V&&n.description!==void 0);if(t)try{return JSON.parse(t.description,Q)}catch{}let e=r.annotations.find(n=>n.type===Z&&n.description!==void 0);return e?{trackApiCalls:e.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Q(r,t){if(typeof t=="object"&&t!==null&&t.__regexp===true&&typeof t.source=="string"){let{source:e,flags:n}=t;return new RegExp(e,n)}return t}var tt={page:async({page:r},t,e)=>{let n=new q(r);try{await n.init();}catch{}await t(r);try{let{navigations:s,networkRequests:l,consoleLogs:d}=await n.getData(),c={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:s,networkRequests:l,apiCalls:[],apiAssertions:[],consoleLogs:d};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(c)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{await n.flushLegacyAnnotations(e);}catch{}n.dispose();},request:async({request:r},t,e)=>{let n=I(e);if(!n.trackApiCalls){await t(r);return}let s=new C,l=new A(r,s,n);l.intercept(),await t(r);try{let d=l.getData(),c=n.captureAssertions?s.getData():[],a={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:d,apiAssertions:c,consoleLogs:[]};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(a)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{l.flushLegacyAnnotations(e);}catch{}try{s.flushLegacyAnnotations(e);}catch{}l.dispose(),s.dispose();}};test.test.extend(tt);var St={request:async({request:r},t,e)=>{let n=I(e);if(!n.trackApiCalls){await t(r);return}let s=new C,l=new A(r,s,n);l.intercept();let d=[],c=process.stdout.write,a=process.stderr.write;process.stdout.write=function(u,...o){try{let g=typeof u=="string"?u:Buffer.isBuffer(u)?u.toString("utf-8"):String(u);!g.startsWith("[testrelic]")&&!g.startsWith("\u2139 TestRelic")&&!g.startsWith("\u2713 TestRelic")&&!g.startsWith("\u26A0 TestRelic")&&d.push({level:"stdout",text:g.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null});}catch{}return c.apply(process.stdout,[u,...o])},process.stderr.write=function(u,...o){try{let g=typeof u=="string"?u:Buffer.isBuffer(u)?u.toString("utf-8"):String(u);!g.startsWith("[testrelic]")&&!g.startsWith("\u26A0 TestRelic")&&d.push({level:"stderr",text:g.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null});}catch{}return a.apply(process.stderr,[u,...o])};try{await t(r);}finally{process.stdout.write=c,process.stderr.write=a;}try{let u=l.getData(),o=n.captureAssertions?s.getData():[],g={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:u,apiAssertions:o,consoleLogs:d};await e.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(g)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{l.flushLegacyAnnotations(e);}catch{}try{s.flushLegacyAnnotations(e);}catch{}l.dispose(),s.dispose();}};exports.testRelicApiFixture=St;//# sourceMappingURL=api-fixture.cjs.map
2
2
  //# sourceMappingURL=api-fixture.cjs.map