@testrelic/playwright-analytics 2.2.1 → 2.2.2
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/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1533,7 +1533,8 @@ function _updateCard(cls,val){
|
|
|
1533
1533
|
`);}}function re(e){let t=e.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t.length>100&&(t=t.substring(0,100).replace(/-+$/,"")),t||"unnamed-test"}function ft(e,t,r,a){let n=e.find(p=>p.name==="screenshot"&&p.path),s=e.find(p=>p.name==="video"&&p.path);if(!n&&!s)return null;let o=re(t);r>0&&(o+=`--retry-${r}`);let i=path.join(a,"artifacts",o),d={};try{fs.mkdirSync(i,{recursive:!0});}catch{return null}if(n?.path)try{if(fs.existsSync(n.path)){let l=`screenshot${path.extname(n.path)||".png"}`;fs.copyFileSync(n.path,path.join(i,l)),d.screenshot=`artifacts/${o}/${l}`;}}catch{}if(s?.path)try{if(fs.existsSync(s.path)){let l=`video${path.extname(s.path)||".webm"}`;fs.copyFileSync(s.path,path.join(i,l)),d.video=`artifacts/${o}/${l}`;}}catch{}return !d.screenshot&&!d.video?null:d}function bt(e,t){let r=[];for(let a of e){let n=ae(a),s=ne(a),o=se(a,n,s,t),i=ie(a,n,s);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:a.startedAt,durationOnUrl:a.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:a.specFile,test:n,tests:[s],_testTitle:a.title});continue}r.push(...o,...i);}return r.sort(oe),le(r,e),r.map((a,n)=>a.type==="navigation"?{...{index:n,type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:a.durationOnUrl??0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:a.specFile,test:a.test},tests:a.tests}:{...{index:n,type:"api_call",callId:a.callId,method:a.method,url:a.url,timestamp:a.timestamp,responseTime:a.responseTime??null,request:a.request,response:a.response??null,...a.error?{error:a.error}:{},assertions:a.assertions??[],specFile:a.specFile,test:a.test},tests:a.tests})}function ae(e){return {title:e.title,fullTitle:e.titlePath,status:e.status,duration:e.duration,retries:e.retryCount,retry:e.retry,tags:e.tags,failure:e.failure}}function ne(e){return {title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:e.retryCount,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,retryStatus:e.retryStatus,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,networkRequests:e.networkRequests,apiCalls:e.apiCalls,apiAssertions:e.apiAssertions,actions:e.actions}}function se(e,t,r,a){let n=[];for(let s of e.navigations)a.navigationTypes!==null&&!a.navigationTypes.includes(s.navigationType)||n.push({type:"navigation",url:s.url,timestamp:s.timestamp,durationOnUrl:0,navigationType:s.navigationType,domContentLoadedAt:s.domContentLoadedAt??null,networkIdleAt:s.networkIdleAt??null,networkStats:s.networkStats??null,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title});return n}function ie(e,t,r){if(!e.apiCalls||e.apiCalls.length===0)return [];let a=e.apiAssertions??[];return e.apiCalls.map(n=>{let s=a.filter(i=>i.callId===n.id).map(i=>({type:i.type,expected:i.expected,actual:i.actual,status:i.status,location:i.location,...i.expression!==void 0?{expression:i.expression}:{}})),o=null;return n.responseStatusCode!==null&&n.responseStatusText!==null&&(o={statusCode:n.responseStatusCode,statusText:n.responseStatusText,headers:n.responseHeaders,body:mt(n.responseBody)}),{type:"api_call",callId:n.id,method:n.method,url:n.url,timestamp:n.timestamp,responseTime:n.error?null:n.responseTimeMs,request:{headers:n.requestHeaders,body:mt(n.requestBody)},response:o,...n.error?{error:n.error}:{},assertions:s,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title}})}function oe(e,t){let r=new Date(e.timestamp).getTime(),a=new Date(t.timestamp).getTime();if(r!==a)return r-a;let n={navigation:0,api_call:1},s=n[e.type],o=n[t.type];return s!==o?s-o:e.type==="api_call"&&t.type==="api_call"&&e.callId&&t.callId?ht(e.callId)-ht(t.callId):0}function ht(e){let t=e.match(/(\d+)$/);return t?parseInt(t[1],10):0}function le(e,t){for(let r=0;r<e.length;r++){let a=e[r];if(a.type!=="navigation")continue;let n=new Date(a.timestamp).getTime(),s=null;for(let o=r+1;o<e.length;o++)if(e[o]._testTitle===a._testTitle){s=new Date(e[o].timestamp).getTime();break}if(s!==null)a.durationOnUrl=Math.max(0,s-n);else {let o=t.find(i=>i.title===a._testTitle);if(o){let i=new Date(o.completedAt).getTime();a.durationOnUrl=Math.max(0,i-n);}}}}function mt(e){if(e==null)return null;try{return JSON.parse(e)}catch{return e}}function z(e,t){let r=e.length,a=Math.min(Math.ceil(t/100*r)-1,r-1);return e[Math.max(0,a)]}function de(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return e}}function ce(e){return e==null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function vt(e,t){let r=0,a=0,n=0,s=0,o=0;for(let g of e)switch(g.status){case "passed":r++;break;case "failed":a++;break;case "flaky":n++;break;case "skipped":s++;break;case "timedout":o++;break}let i=[];for(let g of e)g.apiCalls&&i.push(...g.apiCalls);let d=i.length,p=new Set,l={},f={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},u=[];for(let g of i)p.add(de(g.url)),l[g.method]=(l[g.method]??0)+1,f[ce(g.responseStatusCode)]+=1,u.push(g.responseTimeMs);let c=null;if(u.length>0){let g=[...u].sort((L,B)=>L-B),T=g.reduce((L,B)=>L+B,0);c={avg:Math.round(T/g.length),min:g[0],max:g[g.length-1],p50:z(g,50),p95:z(g,95),p99:z(g,99)};}let k=0,A=0,C=0;for(let g of e)if(g.apiAssertions)for(let T of g.apiAssertions)k++,T.status==="passed"?A++:C++;let m=0,v=new Set;for(let g of e){m+=g.navigations.length;for(let T of g.navigations)v.add(T.url);}let w=0,y={};function R(g){for(let T of g)w++,y[T.category]=(y[T.category]??0)+1,T.children.length>0&&R(T.children);}for(let g of e)g.actions&&R(g.actions);return {total:e.length,passed:r,failed:a,flaky:n,skipped:s,timedout:o,totalApiCalls:d,uniqueApiUrls:p.size,apiCallsByMethod:l,apiCallsByStatusRange:f,apiResponseTime:c,totalAssertions:k,passedAssertions:A,failedAssertions:C,totalNavigations:m,uniqueNavigationUrls:v.size,totalTimelineSteps:t,totalActionSteps:w,actionStepsByCategory:y}}function pe(e){let t=56-e.length;return t>0?e+" ".repeat(t):e}function S(e){return `\u2502 ${pe(e)} \u2502
|
|
1534
1534
|
`}function yt(e,t,r,a){if(a||e.total===0)return;let n=`\u250C${"\u2500".repeat(58)}\u2510
|
|
1535
1535
|
`,s=`\u2514${"\u2500".repeat(58)}\u2518
|
|
1536
|
-
`,o=S(""),i=n;i+=S("TestRelic
|
|
1536
|
+
`,o=S(""),i=n;i+=S("TestRelic AI - Playwright Test Report"),i+=o;let d=[];if(e.passed>0&&d.push(`${e.passed} \u2713`),e.failed>0&&d.push(`${e.failed} \u2717`),e.flaky>0&&d.push(`${e.flaky} \u26A0`),e.skipped>0&&d.push(`${e.skipped} skipped`),e.timedout>0&&d.push(`${e.timedout} timedout`),i+=S(`Tests: ${e.total} total (${d.join(" ")})`),e.totalNavigations>0&&(i+=S(`Navigations: ${e.totalNavigations} visits across ${e.uniqueNavigationUrls} unique URLs`)),e.totalApiCalls>0){i+=S(`API Calls: ${e.totalApiCalls} calls across ${e.uniqueApiUrls} unique endpoints`);let p=Object.entries(e.apiCallsByMethod).filter(([,f])=>f>0).map(([f,u])=>`${f}: ${u}`);p.length>0&&(i+=S(` ${p.join(" ")}`));let l=Object.entries(e.apiCallsByStatusRange).filter(([,f])=>f>0).map(([f,u])=>`${f}: ${u}`);l.length>0&&(i+=S(` ${l.join(" ")}`)),e.apiResponseTime&&(i+=S(` Avg response: ${e.apiResponseTime.avg}ms P95: ${e.apiResponseTime.p95}ms`));}if(e.totalAssertions>0&&(i+=S(`Assertions: ${e.totalAssertions} total (${e.passedAssertions} \u2713 ${e.failedAssertions} \u2717)`)),e.totalActionSteps>0){let p=[],l=e.actionStepsByCategory;l.ui_action&&p.push(`${l.ui_action} UI`),l.assertion&&p.push(`${l.assertion} assertions`),l.custom_step&&p.push(`${l.custom_step} custom`);let f=p.length>0?` (${p.join(" ")})`:"";i+=S(`Actions: ${e.totalActionSteps} steps${f}`);}i+=S(`Report: ${r}`),i+=S(`Data: ${t}`),i+=s,i+=`For more information visit us at https://docs.testrelic.ai
|
|
1537
|
+
`,process.stderr.write(i);}var ue=new Set(["pw:api","expect","test.step"]);function ge(e){return e==="expect"?"assertion":e==="test.step"?"custom_step":"ui_action"}function U(e,t,r){if(ue.has(e.category)){let a=[];for(let s of e.steps)U(s,t,a);let n=e.startTime.getTime()-t.getTime();r.push({title:e.title,category:ge(e.category),timestamp:e.startTime.toISOString(),duration:e.duration,videoOffset:n>=0?n/1e3:null,status:e.error?"failed":"passed",error:e.error?.message??null,children:a});}else for(let a of e.steps)U(a,t,r);}function xt(e,t){let r=[];for(let a of e)U(a,t,r);return r}function j(e){switch(e){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function ke(e,t,r){let a=`${e}::${t}::${r}`;return crypto.createHash("sha256").update(a).digest("hex").substring(0,16)}function Ce(e){return e.length<=4?"":e[e.length-2]}function Te(e){let t=e.findIndex(r=>r.status==="passed");return t>0?`passed on retry ${t}`:null}function Se(e,t){let r=["e2e","api","unit"];for(let a of r)if(e.some(n=>n===`@${a}`||n===a))return a;for(let a of r)if(t.includes(`/${a}/`))return a;return "unknown"}var Ae="__testrelic_api_config";function Re(e){return JSON.stringify(e,(t,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var M=class{constructor(t){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.config=Z(t),this.apiConfig=W(t);}onBegin(t,r){try{this.rootDir=t.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??crypto.randomUUID();}catch{}}onTestBegin(t,r){try{t.annotations.push({type:Ae,description:Re(this.apiConfig)});}catch{}}onTestEnd(t,r){try{let a=r,n=t.outcome(),s;n==="flaky"?s="flaky":n==="skipped"?s="skipped":s=j(a.status);let o=a.startTime.toISOString(),i=new Date(a.startTime.getTime()+a.duration).toISOString(),d=t.tags?[...t.tags]:t.annotations.filter(x=>x.type==="tag").map(x=>x.description??""),p=[],l=null,f=null,u=null,c=a.attachments.filter(x=>x.name===core.ATTACHMENT_NAME&&x.body),k=!1;if(c.length>0)for(let x of c)try{let h=JSON.parse(x.body.toString());core.isTestRelicDataPayload(h)&&(p=p.concat(h.navigations),h.networkRequests.length>0&&(l=(l??[]).concat(h.networkRequests)),h.apiCalls.length>0&&(f=(f??[]).concat(h.apiCalls)),h.apiAssertions.length>0&&(u=(u??[]).concat(h.apiAssertions)),k=!0);}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${t.title}", falling back to annotations
|
|
1537
1538
|
`);}if(!k){p=t.annotations.filter(b=>b.type==="lambdatest-navigation"&&b.description).map(b=>{try{return JSON.parse(b.description)}catch{return null}}).filter(b=>b!==null);let x=t.annotations.find(b=>b.type==="__testrelic_network_requests"&&b.description);if(x)try{l=JSON.parse(x.description);}catch{}let h=t.annotations.find(b=>b.type==="__testrelic_api_calls"&&b.description);if(h)try{f=JSON.parse(h.description);}catch{}let N=t.annotations.find(b=>b.type==="__testrelic_api_assertions"&&b.description);if(N)try{u=JSON.parse(N.description);}catch{}}p.length===0&&!l&&!f&&!u&&s!=="skipped"&&process.stderr.write(`[testrelic] Warning: No data found for test "${t.title}", data may be incomplete due to worker crash
|
|
1538
1539
|
`);let C=null;if(s==="failed"||s==="flaky"){let h=(s==="flaky"?t.results.find(N=>N.status!=="passed")?.errors??[]:a.errors)[0];if(h){let N=X(this.config.redactPatterns),b=h.location?.line??null,E=null;this.config.includeCodeSnippets&&b!==null&&h.location?.file&&(E=K(h.location.file,b,this.config.codeContextLines),E&&(E=N(E))),C={message:N(h.message??"Unknown error"),line:b,code:E,stack:this.config.includeStackTrace&&h.stack?N(h.stack):null};}}let m=t.titlePath().filter(Boolean),v=path.relative(this.rootDir||".",t.location.file),w=Ce(m),y=m.join(" > "),R=v,g=ke(R,w,y),T=Se(d,R),L=n==="flaky",B=Te(t.results),Lt=j(t.expectedStatus),Bt=j(a.status),Y=null;if(this.config.includeArtifacts&&s!=="skipped"&&a.attachments){let x=path.dirname(this.config.outputPath),h=m[m.length-1]??t.title;Y=ft(a.attachments,h,a.retry,x);}let Et=this.config.includeActionSteps&&a.steps?xt(a.steps,a.startTime):null;this.collectedTests.push({titlePath:m,title:y,status:s,duration:a.duration,startedAt:o,completedAt:i,retryCount:t.results.length-1,retry:a.retry,tags:d,failure:C,specFile:v,navigations:p,testId:g,filePath:R,suiteName:w,testType:T,isFlaky:L,retryStatus:B,expectedStatus:Lt,actualStatus:Bt,artifacts:Y,networkRequests:l,apiCalls:f,apiAssertions:u,actions:Et});}catch{}}onEnd(t){try{let r=new Date().toISOString(),a=new Date(this.startedAt).getTime(),s=new Date(r).getTime()-a,o=this.buildTimeline(),i=vt(this.collectedTests,o.length),d={schemaVersion:O,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:s,summary:i,ci:Q(),metadata:this.config.metadata,timeline:o,shardRunIds:null};this.writeReport(d),ct(d,this.config),yt(i,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);}catch{}}printsToStdio(){return false}buildTimeline(){let t=this.collectedTests.map(r=>({titlePath:r.titlePath,title:r.title,status:r.status,duration:r.duration,startedAt:r.startedAt,completedAt:r.completedAt,retryCount:r.retryCount,retry:r.retry,tags:r.tags,failure:r.failure,specFile:r.specFile,navigations:r.navigations,apiCalls:r.apiCalls,apiAssertions:r.apiAssertions,testId:r.testId,filePath:r.filePath,suiteName:r.suiteName,testType:r.testType,isFlaky:r.isFlaky,retryStatus:r.retryStatus,expectedStatus:r.expectedStatus,actualStatus:r.actualStatus,artifacts:r.artifacts,networkRequests:r.networkRequests,actions:r.actions}));return bt(t,{navigationTypes:this.config.navigationTypes})}toTestResult(t){return {title:t.title,status:t.status,duration:t.duration,startedAt:t.startedAt,completedAt:t.completedAt,retryCount:t.retryCount,tags:t.tags,failure:t.failure,testId:t.testId,filePath:t.filePath,suiteName:t.suiteName,testType:t.testType,isFlaky:t.isFlaky,retryStatus:t.retryStatus,expectedStatus:t.expectedStatus,actualStatus:t.actualStatus,artifacts:t.artifacts,networkRequests:t.networkRequests,apiCalls:t.apiCalls,apiAssertions:t.apiAssertions,actions:t.actions??null}}writeReport(t){try{let r=JSON.stringify(t,null,2),a=this.config.outputPath,n=path.dirname(a);fs.mkdirSync(n,{recursive:!0});let s=a+".tmp";fs.writeFileSync(s,r,"utf-8"),fs.renameSync(s,a);}catch(r){process.stderr.write(`[testrelic] Failed to write report: ${r instanceof Error?r.message:String(r)}
|
|
1539
1540
|
`);}}};var Le=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function Be(e){let t=e.toLowerCase();return Le.some(r=>t.includes(r))}function kt(e,t){let r=new TextEncoder().encode(e);return r.length<=t?{text:e,truncated:false}:{text:new TextDecoder().decode(r.slice(0,t)),truncated:true}}var F=class{constructor(t,r){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=r?.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,r]of this.pendingRequests)this.capturedRequests.push({url:r.url,method:r.method,resourceType:r.resourceType,statusCode:0,responseTimeMs:Date.now()-r.startTimeMs,startedAt:r.startedAt,requestHeaders:r.headers,requestBody:r.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:r.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.pendingRequests.delete(t);return [...this.capturedRequests].sort((t,r)=>t.startedAt.localeCompare(r.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(a=>({url:a.url,navigationType:a.navigationType,timestamp:a.timestamp,domContentLoadedAt:a.domContentLoadedAt,networkIdleAt:a.networkIdleAt,networkStats:a.networkStats})),r=this.includeNetworkStats?await this.getCapturedRequests():[];return {navigations:t,networkRequests:r}}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 r of this.records){let a={url:r.url,navigationType:r.navigationType,timestamp:r.timestamp,domContentLoadedAt:r.domContentLoadedAt,networkIdleAt:r.networkIdleAt,networkStats:r.networkStats};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(a)});}if(this.includeNetworkStats){let r=await this.getCapturedRequests();r.length>0&&t.annotations.push({type:"__testrelic_network_requests",description:JSON.stringify(r)});}}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:r}of this.listeners)this.page.off(t,r);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.capturedRequests=[],this.pendingBodyReads=[],this.requestCaptureCount=0;}getRecords(){return this.records}interceptMethods(){let t=this,r=this.page;r.goto=async function(a,n){return t.recordNavigation(a,"goto"),t.origGoto(a,n)},r.goBack=async function(a){let n=await t.origGoBack(a);return t.recordNavigation(r.url(),"back"),n},r.goForward=async function(a){let n=await t.origGoForward(a);return t.recordNavigation(r.url(),"forward"),n},r.reload=async function(a){return t.recordNavigation(r.url(),"refresh"),t.origReload(a)};}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 r=n=>{try{let s=n;if(typeof s.parentFrame=="function"&&s.parentFrame()!==null)return;let o=s.url(),i=this.records[this.records.length-1];if(i&&Date.now()-new Date(i.timestamp).getTime()<50&&i.url===o)return;this.recordNavigation(o,"navigation");}catch{}};this.page.on("framenavigated",r),this.listeners.push({event:"framenavigated",handler:r});let a=n=>{try{let s=n;if(s.type()!=="debug")return;let o=s.text();if(!o.startsWith("__testrelic_nav:"))return;let i=JSON.parse(o.slice(16));i.type&&i.url&&this.recordNavigation(i.url,i.type);}catch{}};if(this.page.on("console",a),this.listeners.push({event:"console",handler:a}),this.includeNetworkStats){let n=i=>{if(this.currentNetworkCounter&&this.currentNetworkCounter.totalRequests++,!(this.requestCaptureCount>=500)){this.requestCaptureCount++;try{let d=i,p=String(this.requestIdCounter++),l=d.postData()??null,f=!1;if(l!==null){let c=kt(l,10240);l=c.text,f=c.truncated;}let u={url:d.url(),method:d.method(),resourceType:this.mapResourceType(d.resourceType()),headers:d.headers(),postData:l,postDataTruncated:f,startedAt:new Date().toISOString(),startTimeMs:Date.now()};this.pendingRequests.set(p,u),i.__testrelic_id=p;}catch{}}};this.page.on("request",n),this.listeners.push({event:"request",handler:n});let s=i=>{try{let d=i;if(this.currentNetworkCounter){let m=d.status();m>=400&&(this.currentNetworkCounter.failedRequests++,this.currentNetworkCounter.failedRequestUrls.push(m+" "+d.url()));let v=d.headers()["content-length"];v&&(this.currentNetworkCounter.totalBytes+=parseInt(v,10)||0);let w=d.request().resourceType(),y=this.mapResourceType(w);this.currentNetworkCounter.byType[y]++;}let p=d.request().__testrelic_id;if(!p)return;let l=this.pendingRequests.get(p);if(!l)return;this.pendingRequests.delete(p);let f=Date.now()-l.startTimeMs,u=d.headers(),c=u["content-type"]??null,k=parseInt(u["content-length"]??"0",10)||0,A=c?!Be(c):!1,C=(async()=>{let m=null,v=!1;if(!A)try{let R=(await d.body()).toString("utf-8"),g=kt(R,10240);m=g.text,v=g.truncated;}catch{}let w={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:d.status(),responseTimeMs:f,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:m,responseHeaders:u,contentType:c,responseSize:k,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:v,isBinary:A,error:null};this.capturedRequests.push(w);})();this.pendingBodyReads.push(C);}catch{}};this.page.on("response",s),this.listeners.push({event:"response",handler:s});let o=i=>{if(this.currentNetworkCounter){this.currentNetworkCounter.failedRequests++;try{let d=i;this.currentNetworkCounter.failedRequestUrls.push("ERR "+d.url());}catch{}}try{let d=i,p=d.__testrelic_id;if(!p)return;let l=this.pendingRequests.get(p);if(!l)return;this.pendingRequests.delete(p);let f={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:0,responseTimeMs:Date.now()-l.startTimeMs,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:d.failure()?.errorText??"Unknown error"};this.capturedRequests.push(f);}catch{}};this.page.on("requestfailed",o),this.listeners.push({event:"requestfailed",handler:o});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let t=history.pushState.bind(history),r=history.replaceState.bind(history);history.pushState=function(...a){t(...a),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...a){r(...a),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,r){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:r,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 Ct=Symbol.for("__testrelic_call_id"),Ee="__testrelic_api_assertions",I=new WeakMap,_=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:Ee,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}};var Tt="[REDACTED]";function V(e,t){if(e===null||t.length===0)return e;let r=new Set(t.map(n=>n.toLowerCase())),a={};for(let n of Object.keys(e))Object.hasOwn(e,n)&&(a[n]=r.has(n.toLowerCase())?Tt:e[n]);return a}function D(e,t){if(e===null||t.length===0)return e;let r;try{r=JSON.parse(e);}catch{return e}if(typeof r!="object"||r===null)return e;let a=new Set(t),n=$(r,a);return JSON.stringify(n)}function $(e,t){if(Array.isArray(e))return e.map(r=>$(r,t));if(typeof e=="object"&&e!==null){let r={};for(let a of Object.keys(e)){if(!Object.hasOwn(e,a))continue;let n=e[a];t.has(a)?r[a]=Tt:r[a]=$(n,t);}return r}return e}function At(e,t,r){if(r.length>0){for(let a of r)if(St(e,a))return false}if(t.length>0){for(let a of t)if(St(e,a))return true;return false}return true}function St(e,t){try{return t instanceof RegExp?t.test(e):Me(t).test(e)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(t)}`),false}}function Me(e){let t="",r=0;for(;r<e.length;){let a=e[r];a==="*"&&e[r+1]==="*"?(t+=".*",r+=2,e[r]==="/"&&r++):a==="*"?(t+="[^/]*",r++):a==="?"?(t+="[^/]",r++):".+^${}()|[]\\".includes(a)?(t+="\\"+a,r++):(t+=a,r++);}return new RegExp(t)}var Fe=["get","post","put","patch","delete","head","fetch"],De=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"],Pe="__testrelic_api_calls";function Oe(e){let t=e.toLowerCase();return De.some(r=>t.includes(r))}function He(e){if(!e)return null;if(e.data!==void 0&&e.data!==null){let t=e.data;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("base64"):JSON.stringify(t)}if(e.form!==void 0&&e.form!==null)return JSON.stringify(e.form);if(e.multipart!==void 0&&e.multipart!==null){let t=e.multipart,r={};for(let[a,n]of Object.entries(t))typeof n=="string"||typeof n=="number"||typeof n=="boolean"?r[a]=String(n):n&&typeof n=="object"&&"name"in n?r[a]=`[file: ${n.name}]`:r[a]="[binary]";return JSON.stringify(r)}return null}var P=class P{constructor(t,r,a){this.originals=new Map;this.capturedCalls=[];this.callCounter=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=t,this.assertionTracker=r??null,this.apiConfig=a??P.DEFAULT_API_CONFIG;}get lastCallId(){return this._lastCallId}getCallIdForValue(t){return t!=null&&typeof t=="object"?I.get(t)??null:this.primitiveCallIds.get(t)??null}intercept(){for(let r of Fe){let a=this.context[r].bind(this.context);this.originals.set(r,a),this.context[r]=this.createWrapper(r,a);}let t=this.context.dispose.bind(this.context);this.originals.set("dispose",t),this.context.dispose=async r=>(this.disposed=true,t(r));}getData(){return [...this.capturedCalls]}flushLegacyAnnotations(t){this.capturedCalls.length!==0&&t.annotations.push({type:Pe,description:JSON.stringify(this.capturedCalls)});}dispose(){for(let[t,r]of this.originals)this.context[t]=r;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,r){let a=this,n=t.headers.bind(t);t.headers=function(){let c=n();return I.set(c,r),c};let s=t.headersArray.bind(t);t.headersArray=function(){let c=s();return I.set(c,r),c};let o=t.json.bind(t);t.json=async function(){let c=await o();return c!=null&&typeof c=="object"&&I.set(c,r),c};let i=t.status.bind(t);t.status=function(){let c=i();return a.primitiveCallIds.set(c,r),c};let d=t.statusText.bind(t);t.statusText=function(){let c=d();return a.primitiveCallIds.set(c,r),c};let p=t.ok.bind(t);t.ok=function(){let c=p();return a.primitiveCallIds.set(c,r),c};let l=t.text.bind(t);t.text=async function(){let c=await l();return a.primitiveCallIds.set(c,r),c};let f=t.body.bind(t);t.body=async function(){let c=await f();return I.set(c,r),c};}createWrapper(t,r){let a=this;return async function(s,o){if(!At(s,a.apiConfig.apiIncludeUrls,a.apiConfig.apiExcludeUrls))return r(s,o);let i=`api-call-${a.callCounter++}`,d=new Date().toISOString(),p=t==="fetch"?(o?.method??"GET").toUpperCase():t.toUpperCase(),l=He(o),f=perf_hooks.performance.now();a._lastCallId=i,a.assertionTracker&&a.assertionTracker.setCurrentCallId(i);let u;try{u=await r(s,o);}catch(c){let k=perf_hooks.performance.now();try{let A=a.apiConfig.captureRequestBody?D(l,a.apiConfig.redactBodyFields):null,C={id:i,timestamp:d,method:p,url:s,requestHeaders:null,requestBody:A,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((k-f)*100)/100,isBinary:!1,error:c instanceof Error?c.message:String(c)};a.capturedCalls.push(C);}catch{}throw c}try{let c=perf_hooks.performance.now(),k=u.headers(),A=k["content-type"]??null,C=A?!Oe(A):!1,m=null;a.apiConfig.captureRequestHeaders&&o?.headers&&(m=o.headers);let v=null;a.apiConfig.captureResponseHeaders&&(v=k);let w=a.apiConfig.captureRequestBody?l:null,y=null;if(a.apiConfig.captureResponseBody)try{C?y=(await u.body()).toString("base64"):y=await u.text();}catch{}m=V(m,a.apiConfig.redactHeaders),v=V(v,a.apiConfig.redactHeaders),w=D(w,a.apiConfig.redactBodyFields),y=D(y,a.apiConfig.redactBodyFields);let R={id:i,timestamp:d,method:p,url:u.url(),requestHeaders:m,requestBody:w,responseStatusCode:u.status(),responseStatusText:u.statusText(),responseHeaders:v,responseBody:y,responseTimeMs:Math.round((c-f)*100)/100,isBinary:C,error:null};a.capturedCalls.push(R);}catch{}try{u[Ct]=i,a.tagResponseMethods(u,i);}catch{}return u}}};P.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 q=P;var Ue="__testrelic_api_config",je="__testrelic_config_trackApiCalls";function J(e){let t=e.annotations.find(a=>a.type===Ue&&a.description!==void 0);if(t)try{return JSON.parse(t.description,$e)}catch{}let r=e.annotations.find(a=>a.type===je&&a.description!==void 0);return r?{trackApiCalls:r.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 $e(e,t){if(typeof t=="object"&&t!==null&&t.__regexp===true&&typeof t.source=="string"){let{source:r,flags:a}=t;return new RegExp(r,a)}return t}var It={page:async({page:e},t,r)=>{let a=new F(e);try{await a.init();}catch{}await t(e);try{let{navigations:n,networkRequests:s}=await a.getData(),o={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:n,networkRequests:s,apiCalls:[],apiAssertions:[]};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(o)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{await a.flushLegacyAnnotations(r);}catch{}a.dispose();},request:async({request:e},t,r)=>{let a=J(r);if(!a.trackApiCalls){await t(e);return}let n=new _,s=new q(e,n,a);s.intercept(),await t(e);try{let o=s.getData(),i=a.captureAssertions?n.getData():[],d={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:o,apiAssertions:i};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(d)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};test.test.extend(It);var Ye={request:async({request:e},t,r)=>{let a=J(r);if(!a.trackApiCalls){await t(e);return}let n=new _,s=new q(e,n,a);s.intercept(),await t(e);try{let o=s.getData(),i=a.captureAssertions?n.getData():[],d={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:o,apiAssertions:i};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(d)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};var qt=false;function xa(e,t,r="manual_record"){if(!e||!e.annotations){qt||(qt=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
|