@testrelic/playwright-analytics 2.4.2 → 2.4.3
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 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2580,8 +2580,8 @@ ${s}
|
|
|
2580
2580
|
`);}return u||(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&&!u&&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:c,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 Er(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=E();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}async function ua(t,e,r,n){let s=new Map;if(!e.uploadArtifacts||!await t.ensureValidToken())return s;let o=[],i=new Map;for(let p of n){if(p.artifacts.screenshot){let f=path.join(p.outputDir,p.artifacts.screenshot);o.push({filePath:f,runId:r,testId:p.testId,type:"screenshot"}),i.set(f,{testId:p.testId,field:"screenshot"});}if(p.artifacts.video){let f=path.join(p.outputDir,p.artifacts.video);o.push({filePath:f,runId:r,testId:p.testId,type:"video"}),i.set(f,{testId:p.testId,field:"video"});}}if(o.length===0)return s;let l=await Er(t.getEndpoint(),t.getAccessToken(),o,e.artifactMaxSizeMb),d=new Map;for(let[p,f]of l){if(!f.success||!f.storageKey)continue;let u=i.get(p);if(!u)continue;let g=d.get(u.testId)??{};u.field==="screenshot"&&(g.screenshotKey=f.storageKey),u.field==="video"&&(g.videoKey=f.storageKey),d.set(u.testId,g);}for(let p of n){let f=d.get(p.testId);s.set(p.testId,{...p.artifacts,...f?.screenshotKey?{screenshotKey:f.screenshotKey}:{},...f?.videoKey?{videoKey:f.videoKey}:{}});}let c=Array.from(l.values()).filter(p=>p.success).length;return c>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${c} artifact(s) to cloud storage.
|
|
2582
2582
|
`),s}async function it(t,e,r,n,s,a,o,i,l,d,c){try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){let f=await t.ensureValidToken(),u=t.getGitMetadata(),g={finishedAt:o,duration:i,summary:l,...u?.commitMessage?{commitMessage:u.commitMessage}:{}};if(f){if(!await Mr(t.getEndpoint(),t.getAccessToken(),s,g)){let m=e?.queueDirectory??".testrelic/queue";te(m,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",g,{"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",g,{"Content-Type":"application/json"});}}let p=new Map;if(t.isCloudMode()&&e&&d&&d.length>0&&(p=await ua(t,e,n,d)),t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await t.ensureValidToken()){let u=t.getGitMetadata(),g=E(),h=at(t),m=pa(a,p),y=tt(m,h,u,g,c),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 u=e?.queueDirectory??".testrelic/queue",g=t.getGitMetadata(),h=E(),m=at(t),y=tt(a,m,g,h);te(u,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 pa(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 ba(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function wa(t){return t.length<=
|
|
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=E();this.detectedOs=Ca(),this.detectedSource=ka(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:Ra,description:Aa(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=Nr(n.attachments,e.annotations,e.title,a==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0);let c=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,G=null;this.config.includeCodeSnippets&&V!==null&&S.location?.file&&(G=At(S.location.file,V,this.config.codeContextLines),G&&(G=B(G))),c={message:B(S.message??"Unknown error"),line:V,code:G,stack:this.config.includeStackTrace&&S.stack?B(S.stack):null};}}let p=e.titlePath().filter(Boolean),f=path.relative(this.rootDir||".",e.location.file),u=wa(p),g=p.join(" > "),h=f,m=ba(h,u,g),y=Sa(l,h),C=s==="flaky",b=xa(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=Ta(p[
|
|
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 ba(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function wa(t){return t.length<=3?"":t[t.length-2]}function xa(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function ka(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 Ca(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function Ta(t){let e=t.toLowerCase();return e.includes("chrom")?"Chrome":e.includes("firefox")?"Firefox":e.includes("webkit")||e.includes("safari")?"WebKit":t||void 0}function Sa(t,e){let r=["e2e","api","unit"];for(let s of r)if(t.some(a=>a===`@${s}`||a===s))return s;let n=e.replace(/\\/g,"/");for(let s of r)if(n.includes(`/${s}/`))return s;return "unknown"}var Ra="__testrelic_api_config";function Aa(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
|
+
`),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=E();this.detectedOs=Ca(),this.detectedSource=ka(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:Ra,description:Aa(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=Nr(n.attachments,e.annotations,e.title,a==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0);let c=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,G=null;this.config.includeCodeSnippets&&V!==null&&S.location?.file&&(G=At(S.location.file,V,this.config.codeContextLines),G&&(G=B(G))),c={message:B(S.message??"Unknown error"),line:V,code:G,stack:this.config.includeStackTrace&&S.stack?B(S.stack):null};}}let p=e.titlePath().filter(Boolean),f=path.relative(this.rootDir||".",e.location.file),u=wa(p),g=p.join(" > "),h=f,m=ba(h,u,g),y=Sa(l,h),C=s==="flaky",b=xa(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=Ta(p[0]??""),R={titlePath:p,title:g,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:l,failure:c,specFile:f,navigations:d.navigations,testId:m,filePath:h,suiteName:u,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:g,status:a,duration:n.duration,suiteName:u,filePath:h,testType:y,isFlaky:C,startedAt:o,completedAt:i,tags:l,failure:c,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:c,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:c?.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.
|
|
2587
2587
|
To enable network logs, video sync, and timeline tracking, import the TestRelic fixture:
|