@testrelic/playwright-analytics 2.4.7 → 2.4.8

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 CHANGED
@@ -2580,7 +2580,7 @@ ${s}
2580
2580
  `);}return c||(s=e.filter(h=>h.type==="lambdatest-navigation"&&h.description).map(h=>{try{return JSON.parse(h.description)}catch{return null}}).filter(h=>h!==null)),s.length===0&&i===0&&p===0&&!n&&!c&&process.stderr.write(`[testrelic] Warning: No data found for test "${r}". Make sure your tests import { test, expect } from '@testrelic/playwright-analytics/fixture' instead of '@playwright/test'. Without the TestRelic fixture, network logs, video sync, and timeline data cannot be captured.
2581
2581
  `),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:l,consoleLogsCount:d,apiCallsFile:u,apiCallsCount:p}}var ta=5,me=[1e3,3e3,9e3],U=3,ra={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip"},nt=0,st=[];async function na(){nt>=ta&&await new Promise(t=>st.push(t)),nt++;}function sa(){nt--,st.length>0&&st.shift()();}async function ve(t){return new Promise(e=>setTimeout(e,t))}function aa(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return ra[e]??"application/octet-stream"}function ia(t){try{return fs$1.statSync(t).size}catch{return 0}}async function oa(t,e,r,n,s){let a=`${t}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:path.basename(r.filePath),contentType:s,type:r.type,sizeBytes:n});for(let i=0;i<U;i++)try{let l=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:o});if(l.ok)return await l.json();if(l.status>=500&&i<U-1){await ve(me[i]);continue}return null}catch{if(i<U-1){await ve(me[i]);continue}return null}return null}async function la(t,e,r,n){for(let s=0;s<U;s++)try{let a=fs$1.createReadStream(e),o=stream.Readable.toWeb(a),i=await fetch(t,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(n)},body:o,duplex:"half"});if(i.ok)return !0;if(i.status>=500&&s<U-1){await ve(me[s]);continue}return !1}catch{if(s<U-1){await ve(me[s]);continue}return false}return false}async function da(t,e,r){let n=`${t}/artifacts/confirm`;try{return (await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function ca(t,e,r,n){let s=ia(r.filePath);if(s===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(s>n*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let a=aa(r.filePath);await na();try{let o=await oa(t,e,r,s,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await la(o.uploadUrl,r.filePath,a,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let l=await da(t,e,o.artifactId);return {success:l,storageKey:o.storageKey,artifactId:o.artifactId,error:l?null:"confirm_failed"}}finally{sa();}}async function Nr(t,e,r,n){let s=new Map,a=r.map(async o=>{let i=await ca(t,e,o,n);s.set(o.filePath,i);});return await Promise.allSettled(a),s}function at(t){let r=t.getGitMetadata()?.remoteUrl;return r?X(r):t.getConfig()?.projectName??ee(process.cwd())}async function Fr(t,e,r,n,s){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=N();return (await Ir(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:at(t),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:n,totalTests:null,ciProvider:i?.provider??null,ciRunUrl:i?.runUrl??null,environment:s??null}))?.runId??null}var ua=true,pa=50;async function fa(t,e,r,n){let s=new Map;if(!(e?.uploadArtifacts??ua)||!await t.ensureValidToken())return s;let i=[],l=new Map;for(let c of n){if(c.artifacts.screenshot){let f=path.join(c.outputDir,c.artifacts.screenshot);i.push({filePath:f,runId:r,testId:c.testId,type:"screenshot"}),l.set(f,{testId:c.testId,field:"screenshot"});}if(c.artifacts.video){let f=path.join(c.outputDir,c.artifacts.video);i.push({filePath:f,runId:r,testId:c.testId,type:"video"}),l.set(f,{testId:c.testId,field:"video"});}}if(i.length===0)return s;let d=e?.artifactMaxSizeMb??pa,u=await Nr(t.getEndpoint(),t.getAccessToken(),i,d),p=new Map;for(let[c,f]of u){if(!f.success||!f.storageKey)continue;let h=l.get(c);if(!h)continue;let m=p.get(h.testId)??{};h.field==="screenshot"&&(m.screenshotKey=f.storageKey),h.field==="video"&&(m.videoKey=f.storageKey),p.set(h.testId,m);}for(let c of n){let f=p.get(c.testId);s.set(c.testId,{...c.artifacts,...f?.screenshotKey?{screenshotKey:f.screenshotKey}:{},...f?.videoKey?{videoKey:f.videoKey}:{}});}let g=Array.from(u.values()).filter(c=>c.success).length;return g>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${g} artifact(s) to cloud storage.
2582
2582
  `),s}async function it(t,e,r,n,s,a,o,i,l,d,u){try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){let g=await t.ensureValidToken(),c=t.getGitMetadata(),f={finishedAt:o,duration:i,summary:l,...c?.commitMessage?{commitMessage:c.commitMessage}:{}};if(g){if(!await Mr(t.getEndpoint(),t.getAccessToken(),s,f)){let m=e?.queueDirectory??".testrelic/queue";te(m,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",f,{"Content-Type":"application/json"});}}else {let h=e?.queueDirectory??".testrelic/queue";te(h,n,"finalize",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",f,{"Content-Type":"application/json"});}}let p=new Map;if(t.isCloudMode()&&d&&d.length>0&&(p=await fa(t,e,n,d)),t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await t.ensureValidToken()){let c=t.getGitMetadata(),f=N(),h=at(t),m=ga(a,p),y=tt(m,h,c,f,u),C=await _r(t.getEndpoint(),t.getAccessToken(),y,async()=>await t.ensureValidToken()?t.getAccessToken():null);if(!C.success){let b=C,w=e?.queueDirectory??".testrelic/queue";te(w,n,"batch",b.reason,b.targetEndpoint,b.method,b.payload,{"Content-Type":"application/json"});}}else {let c=e?.queueDirectory??".testrelic/queue",f=t.getGitMetadata(),h=N(),m=at(t),y=tt(a,m,f,h);te(c,n,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",y,{"Content-Type":"application/json"});}await t.dispose();}catch{try{await t.dispose();}catch{}}}function ga(t,e){if(e.size===0)return t;let r=t.timeline.map(n=>{let s=n.testId;if(!s)return n;let a=e.get(s);return a?{...n,...a.screenshotKey?{screenshotKey:a.screenshotKey}:{},...a.videoKey?{videoKey:a.videoKey}:{}}:n});return {...t,timeline:r}}function ye(t){try{return fs$1.readFileSync(t,"utf-8").split(`
2583
- `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function lt(t){switch(t){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function xa(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function ka(t){return t.length<=3?"":t[t.length-2]}function Ca(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Ta(t){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":t?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[t.provider]??"CI":"Local"}function Sa(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function Ra(t){let e=t.parent?.project?.()?.use;if(!e)return;let{browserName:r,channel:n}=e;if(n){let a=n.toLowerCase();return a==="chrome"||a==="chrome-stable"?"Chrome":a.startsWith("chrome-beta")?"Chrome Beta":a.startsWith("chrome-dev")?"Chrome Dev":a.startsWith("chrome-canary")?"Chrome Canary":a==="msedge"||a==="msedge-stable"?"Microsoft Edge":a.startsWith("msedge-beta")?"Edge Beta":a.startsWith("msedge-dev")?"Edge Dev":a.startsWith("msedge-canary")?"Edge Canary":n}if(!r)return;let s=r.toLowerCase();return s==="chromium"?"Chromium":s==="firefox"?"Firefox":s==="webkit"?"WebKit":r}function Aa(t,e,r){let n=r.parent?.project?.(),s="unknown";n!==void 0&&(n.use.isMobile===true?s="mobile":s="e2e");let a=["e2e","api","unit","mobile"];for(let l of a)if(t.some(d=>d===`@${l}`||d===l))return l;let o=e.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let l of i)if(o.includes(`/${l}/`))return l;return s}var _a="__testrelic_api_config";function Ia(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var be=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.testCount=0;this.cloudClient=null;this.cloudRunId=null;this.runTimestamp="";this.pendingArtifactEntries=[];this.detectedOs="";this.detectedSource="";this.cloudTestsBuffer=[];this.activeReportMode="embedded";this.streamingWriter=null;this.testIndex=[];this.summaryCounters={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0,interrupted:0,totalApiCalls:0,totalAssertions:0,totalNavigations:0,totalNetworkRequests:0,totalConsoleLogs:0,totalActionSteps:0};this.config=Rt(e),this.apiConfig=St(e);}async onBegin(e,r){try{if(this.rootDir=e.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??crypto.randomUUID(),this.config.reportMode==="auto"){let a=r.allTests().length;this.activeReportMode=a>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let n=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${n} tests)
2583
+ `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function lt(t){switch(t){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function xa(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function ka(t){return t.length<=3?"":t[t.length-2]}function Ca(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Ta(t){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":t?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[t.provider]??"CI":"Local"}function Sa(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function Ra(t){let e=t.parent?.project?.()?.use;if(!e)return;let{browserName:r,channel:n}=e;if(n){let a=n.toLowerCase();return a==="chrome"||a==="chrome-stable"?"Chrome":a.startsWith("chrome-beta")?"Chrome Beta":a.startsWith("chrome-dev")?"Chrome Dev":a.startsWith("chrome-canary")?"Chrome Canary":a==="msedge"||a==="msedge-stable"?"Microsoft Edge":a.startsWith("msedge-beta")?"Edge Beta":a.startsWith("msedge-dev")?"Edge Dev":a.startsWith("msedge-canary")?"Edge Canary":n}if(r){let a=r.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":r}let s=e.defaultBrowserType;if(s){let a=s.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":s}}function Aa(t,e,r){let n=r.parent?.project?.(),s="unknown";n!==void 0&&(n.use.isMobile===true?s="mobile":s="e2e");let a=["e2e","api","unit","mobile"];for(let l of a)if(t.some(d=>d===`@${l}`||d===l))return l;let o=e.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let l of i)if(o.includes(`/${l}/`))return l;return s}var _a="__testrelic_api_config";function Ia(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var be=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.testCount=0;this.cloudClient=null;this.cloudRunId=null;this.runTimestamp="";this.pendingArtifactEntries=[];this.detectedOs="";this.detectedSource="";this.cloudTestsBuffer=[];this.activeReportMode="embedded";this.streamingWriter=null;this.testIndex=[];this.summaryCounters={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0,interrupted:0,totalApiCalls:0,totalAssertions:0,totalNavigations:0,totalNetworkRequests:0,totalConsoleLogs:0,totalActionSteps:0};this.config=Rt(e),this.apiConfig=St(e);}async onBegin(e,r){try{if(this.rootDir=e.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??crypto.randomUUID(),this.config.reportMode==="auto"){let a=r.allTests().length;this.activeReportMode=a>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let n=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${n} tests)
2584
2584
  `),this.activeReportMode==="streaming"){let a=path.dirname(this.config.outputPath);this.streamingWriter=new J(a);let o=()=>{if(this.streamingWriter){try{this.streamingWriter.writeIndex(this.testIndex);let i={testRunId:this.testRunId??"",startedAt:this.startedAt,completedAt:new Date().toISOString(),totalDuration:Date.now()-new Date(this.startedAt).getTime(),...this.summaryCounters,metadata:null,reportMode:"streaming",files:[],enrichedSummary:null,validation:null,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(i);}catch{}this.streamingWriter.dispose();}try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let i=this.cloudClient.getAccessToken();i&&rt(this.cloudClient.getEndpoint(),i,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",o),process.on("SIGINT",o);}if(this.config.includeArtifacts){let a=path.dirname(this.config.outputPath);this.runTimestamp=nr(path.join(a,"artifacts"));try{lr(path.join(a,"artifacts"));}catch{}}let s=N();this.detectedOs=Sa(),this.detectedSource=Ta(s);try{this.cloudClient=new pe(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await Fr(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource);}catch{this.cloudClient?.switchToLocalMode("init_error");}if(this.activeReportMode!=="streaming"){let a=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let o=this.cloudClient.getAccessToken();o&&rt(this.cloudClient.getEndpoint(),o,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",a),process.on("SIGINT",a);}}catch{}}onTestBegin(e,r){try{e.annotations.push({type:_a,description:Ia(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=lt(n.status);let o=n.startTime.toISOString(),i=new Date(n.startTime.getTime()+n.duration).toISOString(),l=e.tags?[...e.tags]:e.annotations.filter(A=>A.type==="tag").map(A=>A.description??""),d=Pr(n.attachments,e.annotations,e.title,a==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0);let u=null;if(a==="failed"||a==="flaky"){let S=(a==="flaky"?e.results.find(B=>B.status!=="passed")?.errors??[]:n.errors)[0];if(S){let B=_t(this.config.redactPatterns),V=S.location?.line??null,W=null;this.config.includeCodeSnippets&&V!==null&&S.location?.file&&(W=At(S.location.file,V,this.config.codeContextLines),W&&(W=B(W))),u={message:B(S.message??"Unknown error"),line:V,code:W,stack:this.config.includeStackTrace&&S.stack?B(S.stack):null};}}let p=e.titlePath().filter(Boolean),g=path.relative(this.rootDir||".",e.location.file),c=ka(p),f=p.join(" > "),h=g,m=xa(h,c,f),y=Aa(l,h,e),C=s==="flaky",b=Ca(e.results),w=lt(e.expectedStatus),T=lt(n.status),v=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let A=path.dirname(this.config.outputPath),S=p[p.length-1]??e.title;v=sr(n.attachments,S,n.retry,A,this.runTimestamp||void 0);}let k=this.config.includeActionSteps&&n.steps?fr(n.steps,n.startTime):null,q=Ra(e),R={titlePath:p,title:f,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:l,failure:u,specFile:g,navigations:d.navigations,testId:m,filePath:h,suiteName:c,testType:y,isFlaky:C,retryStatus:b,expectedStatus:w,actualStatus:T,artifacts:v,apiAssertions:d.apiAssertions,actions:k,networkRequestsFile:d.networkRequestsFile,networkRequestsCount:d.networkRequestsCount,consoleLogsFile:d.consoleLogsFile,consoleLogsCount:d.consoleLogsCount,apiCallsFile:d.apiCallsFile,apiCallsCount:d.apiCallsCount,browser:q,os:this.detectedOs||void 0,source:this.detectedSource||void 0};this.cloudTestsBuffer.push({testId:m,title:f,status:a,duration:n.duration,suiteName:c,filePath:h,testType:y,isFlaky:C,startedAt:o,completedAt:i,tags:l,failure:u,browser:q,os:this.detectedOs||void 0,source:this.detectedSource||void 0});try{let A=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(A==="realtime"||A==="both")){let S=this.cloudClient.getAccessToken();S&&Lr(this.cloudClient.getEndpoint(),S,this.cloudRunId,this.buildCloudTestPayload(R));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let A=Ce(h,p,e.id??"",n.retry),S=n.retry===e.results.length-1,B={id:A,navigations:d.navigations,apiAssertions:d.apiAssertions,actions:k??[],artifacts:v,failureDiagnostic:u,hasNetworkFile:d.networkRequestsFile!==null,networkRequestsCount:d.networkRequestsCount,hasConsoleFile:d.consoleLogsFile!==null,consoleLogsCount:d.consoleLogsCount,hasApiCallsFile:d.apiCallsFile!==null,apiCallsCount:d.apiCallsCount,startedAt:o};this.streamingWriter.writeTestDetail(A,B,{networkRequestsFile:d.networkRequestsFile,consoleLogsFile:d.consoleLogsFile,apiCallsFile:d.apiCallsFile});let V={id:A,title:p[p.length-1]??e.title,titlePath:p,filePath:h,status:a,duration:n.duration,project:p[1]??"",retryIndex:n.retry,tags:l,hasNetworkData:d.networkRequestsCount>0,hasConsoleData:d.consoleLogsCount>0,hasArtifacts:v!==null,hasActionSteps:(k?.length??0)>0,errorMessage:u?.message?.split(`
2585
2585
  `)[0]??null,networkCount:d.networkRequestsCount,consoleCount:d.consoleLogsCount,actionCount:k?.length??0,isRetry:!S};if(this.testIndex.push(V),S)switch(this.summaryCounters.total++,a){case "passed":this.summaryCounters.passed++;break;case "failed":this.summaryCounters.failed++;break;case "flaky":this.summaryCounters.flaky++;break;case "skipped":this.summaryCounters.skipped++;break;case "timedout":this.summaryCounters.timedOut++;break;default:this.summaryCounters.interrupted++;break}this.summaryCounters.totalApiCalls+=d.apiCallsCount,this.summaryCounters.totalAssertions+=d.apiAssertions.length,this.summaryCounters.totalNavigations+=d.navigations.length,this.summaryCounters.totalNetworkRequests+=d.networkRequestsCount,this.summaryCounters.totalConsoleLogs+=d.consoleLogsCount,this.summaryCounters.totalActionSteps+=k?.length??0,v&&this.pendingArtifactEntries.push({testId:m,artifacts:v,outputDir:path.dirname(this.config.outputPath)}),R.actions=null,R.apiAssertions=null,R.navigations=[],R.artifacts=null,R.failure=null,R.networkRequestsFile=null,R.consoleLogsFile=null,R.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(R),this.testCount++,this.checkMemoryPressure();}catch{}}async onEnd(e){try{let r=new Date().toISOString(),n=new Date(this.startedAt).getTime(),a=new Date(r).getTime()-n,o=this.activeReportMode==="streaming"?this.testIndex.some(l=>l.status!=="skipped"):this.collectedTests.some(l=>l.status!=="skipped");!this.fixtureDataReceived&&o&&process.stderr.write(`
2586
2586
  \u26A0 TestRelic: No fixture data received from any test.