@testrelic/playwright-analytics 2.9.0 → 2.10.0

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
@@ -2,7 +2,7 @@
2
2
  `),false}}moveFile(e,r){try{fs$1.renameSync(e,r);}catch{try{let{copyFileSync:n}=vn("fs");n(e,r);try{fs$1.unlinkSync(e);}catch{}}catch(n){process.stderr.write(`[testrelic] Failed to move file ${e} \u2192 ${r}: ${n instanceof Error?n.message:String(n)}
3
3
  `);}}}writeIndex(e){let r=path.join(this.reportDir,"index.json"),n=r+".tmp",s=JSON.stringify(e);fs$1.writeFileSync(n,s,"utf-8"),fs$1.renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeCompactIndex(e){let r=path.join(this.reportDir,"index-compact.json"),n=r+".tmp",s=e.map(({titlePath:o,project:i,...l})=>l),a=JSON.stringify(s);fs$1.writeFileSync(n,a,"utf-8"),fs$1.renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(a,"utf-8");}writeSummary(e){let r=path.join(this.reportDir,"summary.json"),n=r+".tmp",s=JSON.stringify(e);fs$1.writeFileSync(n,s,"utf-8"),fs$1.renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeManifest(e){let r=path.join(this.reportDir,"manifest.json"),n=r+".tmp",s=JSON.stringify(e);fs$1.writeFileSync(n,s,"utf-8"),fs$1.renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var Bt=".testrelic",An="testrelic-config.json",_n=".testrelic",In=5,Ln=new Set(["__proto__","constructor","prototype"]),Ft=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${Bt}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),Pn={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function Ot(t){let e=path.resolve(t);for(let r=0;r<=In;r++){let n=path.join(e,Bt,An);if(fs$1.existsSync(n))try{if(fs$1.statSync(n).isFile())return n}catch{}let s=path.join(e,_n);if(fs$1.existsSync(s))try{if(fs$1.statSync(s).isFile())return process.stderr.write(`[testrelic] Deprecation: config file ".testrelic" has moved to ".testrelic/testrelic-config.json". Please migrate your config file to the new location.
4
4
  `),s}catch{}let a=path.dirname(e);if(a===e)break;e=a;}return null}function qt(t){try{let e=fs$1.readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!Ht(r)?null:r}catch{return null}}function Ht(t){for(let e of Object.keys(t)){if(Ln.has(e))return false;let r=t[e];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!Ht(r))return false}return true}function Ut(t){let e=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(t);if(e)return process.env[e[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(t);return r?process.env[r[1]]??null:t}function Pe(t){let e=Object.create(null);for(let r of Object.keys(t)){let n=t[r];typeof n=="string"&&n.startsWith("$")?e[r]=Ut(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?e[r]=Pe(n):e[r]=n;}return e}function Dt(t){let e=/^(\d+)\s*([smhd])$/.exec(t.trim());if(!e)return null;let r=parseInt(e[1],10),n=e[2],s=Pn[n];return !s||r<=0?null:r*s}function zt(t,e){let r=Object.create(null);if(Object.assign(r,Ft),t){let l=t.cloud;l&&typeof l=="object"&&(typeof l.endpoint=="string"&&(r.endpoint=l.endpoint),typeof l.upload=="string"&&(r.uploadStrategy=l.upload),typeof l.timeout=="number"&&(r.timeout=l.timeout),typeof l.apiKey=="string"&&l.apiKey.length>0&&(r.apiKey=l.apiKey));let d=t["testrelic-repo"]??t.project;d&&typeof d=="object"&&typeof d.name=="string"&&(r.projectName=d.name),t.project&&!t["testrelic-repo"]&&process.stderr.write(`[testrelic] Deprecation: "project" key in config is deprecated. Rename it to "testrelic-repo".
5
- `);let u=t.queue;if(u&&typeof u=="object"){if(typeof u.maxAge=="string"){let p=Dt(u.maxAge);p!==null&&(r.queueMaxAge=p);}typeof u.directory=="string"&&(r.queueDirectory=u.directory);}}if(e){if(typeof e.apiKey=="string"&&e.apiKey.length>0){let l=e.apiKey.startsWith("$")?Ut(e.apiKey):e.apiKey;l&&(r.apiKey=l);}if(typeof e.endpoint=="string"&&(r.endpoint=e.endpoint),typeof e.upload=="string"&&(r.uploadStrategy=e.upload),typeof e.timeout=="number"&&(r.timeout=e.timeout),typeof e.projectName=="string"&&(r.projectName=e.projectName),typeof e.queueMaxAge=="string"){let l=Dt(e.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof e.queueDirectory=="string"&&(r.queueDirectory=e.queueDirectory),typeof e.uploadArtifacts=="boolean"&&(r.uploadArtifacts=e.uploadArtifacts),typeof e.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=e.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&core.isValidEndpointUrl(s)&&(r.endpoint=s);let a=process.env.TESTRELIC_UPLOAD_STRATEGY;a&&["batch","realtime","both"].includes(a)&&(r.uploadStrategy=a);let o=process.env.TESTRELIC_CLOUD_TIMEOUT;if(o){let l=parseInt(o,10);!isNaN(l)&&l>=1e3&&l<=12e4&&(r.timeout=l);}let i=Object.freeze(r);return core.isValidCloudConfig(i)?i:Ft}var Fn=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Dn=["authorization","cookie","set-cookie","x-api-key"],Bn=["password","secret","token","apiKey","api_key"];function jt(t){let e=Object.create(null);return e.trackApiCalls=t?.trackApiCalls??true,e.captureRequestHeaders=t?.captureRequestHeaders??true,e.captureResponseHeaders=t?.captureResponseHeaders??true,e.captureRequestBody=t?.captureRequestBody??true,e.captureResponseBody=t?.captureResponseBody??true,e.captureAssertions=t?.captureAssertions??true,e.redactHeaders=t?.redactHeaders??[...Dn],e.redactBodyFields=t?.redactBodyFields??[...Bn],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function $t(t){if(t!==void 0&&!core.isValidConfig(t))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let e=Object.create(null);e.outputPath=t?.outputPath??"./test-results/analytics-timeline.json",e.includeStackTrace=t?.includeStackTrace??false,e.includeCodeSnippets=t?.includeCodeSnippets??true,e.codeContextLines=t?.codeContextLines??3,e.includeNetworkStats=t?.includeNetworkStats??true,e.navigationTypes=t?.navigationTypes??null,e.redactPatterns=[...Fn,...t?.redactPatterns??[]],e.testRunId=t?.testRunId??null,e.metadata=t?.metadata??null;let r=e.outputPath;e.openReport=t?.openReport??true,e.htmlReportPath=t?.htmlReportPath??r.replace(/\.json$/,".html"),e.includeArtifacts=t?.includeArtifacts??true,e.trackApiCalls=t?.trackApiCalls??true,e.quiet=t?.quiet??false,e.includeActionSteps=t?.includeActionSteps??true,e.captureConsoleLogs=t?.captureConsoleLogs??true;let n=Ot(process.cwd()),s=n?qt(n):null,a=s?Pe(s):null,o=zt(a,t?.cloud);return e.cloud=o.apiKey?o:null,e.reportMode=t?.reportMode??"streaming",e.streamingThreshold=t?.streamingThreshold??0,Object.freeze(e)}var ie="1.3.0";function Vt(t,e,r){try{let s=fs$1.readFileSync(t,"utf-8").split(`
5
+ `);let u=t.queue;if(u&&typeof u=="object"){if(typeof u.maxAge=="string"){let p=Dt(u.maxAge);p!==null&&(r.queueMaxAge=p);}typeof u.directory=="string"&&(r.queueDirectory=u.directory);}}if(e){if(typeof e.apiKey=="string"&&e.apiKey.length>0){let l=e.apiKey.startsWith("$")?Ut(e.apiKey):e.apiKey;l&&(r.apiKey=l);}if(typeof e.endpoint=="string"&&(r.endpoint=e.endpoint),typeof e.upload=="string"&&(r.uploadStrategy=e.upload),typeof e.timeout=="number"&&(r.timeout=e.timeout),typeof e.projectName=="string"&&(r.projectName=e.projectName),typeof e.queueMaxAge=="string"){let l=Dt(e.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof e.queueDirectory=="string"&&(r.queueDirectory=e.queueDirectory),typeof e.uploadArtifacts=="boolean"&&(r.uploadArtifacts=e.uploadArtifacts),typeof e.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=e.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&core.isValidEndpointUrl(s)&&(r.endpoint=s);let a=process.env.TESTRELIC_UPLOAD_STRATEGY;a&&["batch","realtime","both"].includes(a)&&(r.uploadStrategy=a);let o=process.env.TESTRELIC_CLOUD_TIMEOUT;if(o){let l=parseInt(o,10);!isNaN(l)&&l>=1e3&&l<=12e4&&(r.timeout=l);}let i=Object.freeze(r);return core.isValidCloudConfig(i)?i:Ft}var Fn=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Dn=["authorization","cookie","set-cookie","x-api-key"],Bn=["password","secret","token","apiKey","api_key"];function jt(t){let e=Object.create(null);return e.trackApiCalls=t?.trackApiCalls??true,e.captureRequestHeaders=t?.captureRequestHeaders??true,e.captureResponseHeaders=t?.captureResponseHeaders??true,e.captureRequestBody=t?.captureRequestBody??true,e.captureResponseBody=t?.captureResponseBody??true,e.captureAssertions=t?.captureAssertions??true,e.redactHeaders=t?.redactHeaders??[...Dn],e.redactBodyFields=t?.redactBodyFields??[...Bn],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function $t(t){if(t!==void 0&&!core.isValidConfig(t))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let e=Object.create(null);e.outputPath=t?.outputPath??"./test-results/analytics-timeline.json",e.includeStackTrace=t?.includeStackTrace??false,e.includeCodeSnippets=t?.includeCodeSnippets??true,e.codeContextLines=t?.codeContextLines??3,e.includeNetworkStats=t?.includeNetworkStats??true,e.captureNavigation=t?.captureNavigation??true,e.navigationTypes=t?.navigationTypes??null,e.redactPatterns=[...Fn,...t?.redactPatterns??[]],e.testRunId=t?.testRunId??null,e.metadata=t?.metadata??null;let r=e.outputPath;e.openReport=t?.openReport??true,e.htmlReportPath=t?.htmlReportPath??r.replace(/\.json$/,".html"),e.includeArtifacts=t?.includeArtifacts??true,e.trackApiCalls=t?.trackApiCalls??true,e.quiet=t?.quiet??false,e.includeActionSteps=t?.includeActionSteps??true,e.captureConsoleLogs=t?.captureConsoleLogs??true;let n=Ot(process.cwd()),s=n?qt(n):null,a=s?Pe(s):null,o=zt(a,t?.cloud);return e.cloud=o.apiKey?o:null,e.reportMode=t?.reportMode??"streaming",e.streamingThreshold=t?.streamingThreshold??0,Object.freeze(e)}var ie="1.3.0";function Vt(t,e,r){try{let s=fs$1.readFileSync(t,"utf-8").split(`
6
6
  `);if(e<1||e>s.length)return null;let a=Math.max(1,e-r),o=Math.min(s.length,e+r),i=[];for(let l=a;l<=o;l++){let d=l===e?">":" ",u=String(l).padStart(String(o).length," ");i.push(`${d} ${u} | ${s[l-1]}`);}return i.join(`
7
7
  `)}catch{return null}}function Wt(t){return e=>{let r=e;for(let n of t)if(typeof n=="string"){let s=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(s,"g"),"[REDACTED]");}else {let s=n.flags.includes("g")?n.flags:n.flags+"g",a=new RegExp(n.source,s);r=r.replace(a,"[REDACTED]");}return r}}function qn(t){return t.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:t.GITHUB_RUN_ID??null,commitSha:t.GITHUB_SHA??null,branch:t.GITHUB_REF_NAME??null,runUrl:t.GITHUB_SERVER_URL&&t.GITHUB_REPOSITORY&&t.GITHUB_RUN_ID?`${t.GITHUB_SERVER_URL}/${t.GITHUB_REPOSITORY}/actions/runs/${t.GITHUB_RUN_ID}`:null}}function Hn(t){return t.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:t.CI_PIPELINE_ID??null,commitSha:t.CI_COMMIT_SHA??null,branch:t.CI_COMMIT_BRANCH??t.CI_COMMIT_REF_NAME??null,runUrl:t.CI_PIPELINE_URL??null}}function Un(t){if(!t.JENKINS_URL)return null;let e=t.GIT_BRANCH??null;return e?.startsWith("origin/")&&(e=e.slice(7)),{provider:"jenkins",buildId:t.BUILD_ID??null,commitSha:t.GIT_COMMIT??null,branch:e,runUrl:t.BUILD_URL??null}}function zn(t){return t.CIRCLECI!=="true"?null:{provider:"circleci",buildId:t.CIRCLE_BUILD_NUM??null,commitSha:t.CIRCLE_SHA1??null,branch:t.CIRCLE_BRANCH??null,runUrl:t.CIRCLE_BUILD_URL??null}}function jn(t){if(!t.BITBUCKET_PIPELINE_UUID)return null;let e=t.BITBUCKET_WORKSPACE&&t.BITBUCKET_REPO_SLUG&&t.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${t.BITBUCKET_WORKSPACE}/${t.BITBUCKET_REPO_SLUG}/pipelines/results/${t.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:t.BITBUCKET_BUILD_NUMBER??null,commitSha:t.BITBUCKET_COMMIT??null,branch:t.BITBUCKET_BRANCH??null,runUrl:e}}var $n=[qn,Hn,Un,zn,jn];function F(t){let e=process.env;for(let r of $n){let n=r(e);if(n)return n}return null}var Ee=`
8
8
  /* Theme Variables */
@@ -2400,7 +2400,7 @@ ${s?`<script id="artifact-manifest-data" type="application/json">${s}</script>`:
2400
2400
  "totalDuration":${Number(i.totalDuration)||0},
2401
2401
  "ci":${i.ci?JSON.stringify(i.ci).replace(/<\//g,"<\\/"):"null"},
2402
2402
  "metadata":${i.metadata?JSON.stringify(i.metadata).replace(/<\//g,"<\\/"):"null"},
2403
- "shardRunIds":null
2403
+ "shardRunIds":${i.shardRunIds?JSON.stringify(i.shardRunIds).replace(/<\//g,"<\\/"):"null"}
2404
2404
  }`,d=`
2405
2405
  (function(){
2406
2406
  var data=JSON.parse(document.getElementById('report-data').textContent);
@@ -2545,7 +2545,7 @@ ${o?`<script id="artifact-manifest-data" type="application/json">${o}</script>`:
2545
2545
  </body>
2546
2546
  </html>`}function je(t){try{let e=process.platform,r;e==="darwin"?r=`open "${t}"`:e==="win32"?r=`start "" "${t}"`:r=`xdg-open "${t}"`,child_process.exec(r,n=>{n&&process.stderr.write(`[testrelic] Failed to open browser: ${n.message}
2547
2547
  `);});}catch{}}var Jt=path.join(os$1.tmpdir(),"testrelic-data"),M=class{constructor(e){this.count=0;this.closed=false;fs$1.mkdirSync(Jt,{recursive:true}),this.filePath=path.join(Jt,`${e}-${crypto.randomUUID().substring(0,8)}.jsonl`),this.fd=fs$1.openSync(this.filePath,"w");}append(e){if(this.closed)return;let r=JSON.stringify(e)+`
2548
- `;fs$1.writeSync(this.fd,r),this.count++;}getPath(){return this.filePath}getCount(){return this.count}close(){if(!this.closed){this.closed=true;try{fs$1.closeSync(this.fd);}catch{}}}cleanup(){try{fs$1.unlinkSync(this.filePath);}catch{}}};async function Yt(t,e,r,n){let s=(e-1)*r,a=[],o=0,i=readline.createInterface({input:fs$1.createReadStream(t,{encoding:"utf-8"}),crlfDelay:1/0});for await(let u of i)if(u.length!==0){if(o>=s&&a.length<r)try{a.push(JSON.parse(u));}catch{}if(o++,a.length>=r&&n!==void 0)break}let l=n??o,d=Math.max(1,Math.ceil(l/r));return {items:a,total:l,page:e,pageSize:r,totalPages:d}}var Qt=/^[a-f0-9]{12}$/,$e=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,er=500;function x(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function tr(t){t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type");}function de(t){try{return fs$1.existsSync(t)?JSON.parse(fs$1.readFileSync(t,"utf-8")):null}catch{return null}}function ce(t){let e=0;try{let r=fs$1.readdirSync(t,{withFileTypes:!0});for(let n of r){let s=path.join(t,n.name);n.isFile()?e+=fs$1.statSync(s).size:n.isDirectory()&&(e+=ce(s));}}catch{}return e}function rr(t,e,r,n){let s=de(path.join(r,"index.json"));x(e,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-n)/1e3)});}function nr(t,e,r){let n=de(path.join(r,"summary.json"));if(!n){x(e,404,{error:"Summary not found"});return}x(e,200,n);}function sr(t,e,r){let n=de(path.join(r,"index.json"));if(!n){x(e,404,{error:"Test index not found"});return}let a=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,o=Math.max(1,parseInt(a.get("page")??"1",10)||1),i=Math.min(er,Math.max(1,parseInt(a.get("pageSize")??"100",10)||100)),l=a.get("status")?.split(",").filter(Boolean)??null,d=a.get("file")??null,u=a.get("search")?.toLowerCase()??null,p=a.get("tag")?.split(",").filter(Boolean)??null,f=a.get("sort")??"file",c=a.get("order")==="desc"?-1:1,g=n;l&&l.length>0&&(g=g.filter(y=>l.includes(y.status))),d&&(g=g.filter(y=>y.filePath===d||y.filePath.startsWith(d+"/"))),u&&(g=g.filter(y=>y.title.toLowerCase().includes(u)||y.filePath.toLowerCase().includes(u))),p&&p.length>0&&(g=g.filter(y=>p.some(b=>y.tags.includes(b)))),g=[...g].sort((y,b)=>{let C=0;switch(f){case "duration":C=y.duration-b.duration;break;case "status":C=y.status.localeCompare(b.status);break;case "title":C=y.title.localeCompare(b.title);break;default:C=y.filePath.localeCompare(b.filePath);break}return C*c});let h=g.length,m=Math.max(1,Math.ceil(h/i)),w=(o-1)*i,T=g.slice(w,w+i);x(e,200,{tests:T,pagination:{page:o,pageSize:i,totalItems:h,totalPages:m},filters:{status:l,file:d,search:u,tag:p}});}function ar(t,e,r,n){if(!Qt.test(n)){x(e,400,{error:"Invalid test ID format"});return}let s=path.join(r,"tests",n,"meta.json"),a=path.join(r,"tests",`${n}.json`),o=fs$1.existsSync(s)?s:fs$1.existsSync(a)?a:null;if(!o){x(e,404,{error:`Test not found: ${n}`});return}try{let i=fs$1.readFileSync(o,"utf-8");e.writeHead(200,{"Content-Type":"application/json"}),e.end(i);}catch(i){x(e,500,{error:i instanceof Error?i.message:String(i)});}}async function ir(t,e,r,n,s){if(!Qt.test(n)){x(e,400,{error:"Invalid test ID format"});return}let o=path.join(r,"tests",n,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!fs$1.existsSync(o)){x(e,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let l=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,d=Math.max(1,parseInt(l.get("page")??"1",10)||1),u=Math.min(er,Math.max(1,parseInt(l.get("pageSize")??"50",10)||50)),p,f=path.join(r,"tests",n,"meta.json");if(fs$1.existsSync(f))try{let g=JSON.parse(fs$1.readFileSync(f,"utf-8"));switch(s){case "network":p=g.networkRequestsCount;break;case "console":p=g.consoleLogsCount;break;case "api-calls":p=g.apiCallsCount;break}}catch{}let c=await Yt(o,d,u,p);x(e,200,c);}catch(i){x(e,500,{error:i instanceof Error?i.message:String(i)});}}function or(t,e,r){let n=de(path.join(r,"index.json"));if(!n){x(e,404,{error:"Test index not found"});return}let s=new Map;for(let o of n){if(o.isRetry)continue;let i=s.get(o.filePath);switch(i||(i={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},s.set(o.filePath,i)),i.total++,o.status){case "passed":i.passed++;break;case "failed":i.failed++;break;case "flaky":i.flaky++;break;case "skipped":i.skipped++;break;case "timedout":i.timedOut++;break}}let a=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));x(e,200,{files:a});}function lr(t,e,r){if(!fs$1.existsSync(r)){x(e,200,{runs:[],totalSizeBytes:0});return}try{let n=[],s=0,a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!$e.test(o.name))continue;let i=path.join(r,o.name),l=ce(i),d=fs$1.readdirSync(i,{withFileTypes:!0}).filter(u=>u.isDirectory());n.push({folderName:o.name,totalSizeBytes:l,testCount:d.length}),s+=l;}n.sort((o,i)=>i.folderName.localeCompare(o.folderName)),x(e,200,{runs:n,totalSizeBytes:s});}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}function dr(t,e,r){try{let n=0,s=0;if(fs$1.existsSync(r)){let a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!$e.test(o.name))continue;let i=path.join(r,o.name),l=ce(i);fs$1.rmSync(i,{recursive:!0,force:!0}),s+=l,n++;}}x(e,200,{deletedCount:n,freedBytes:s});}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}function cr(t,e,r,n){if(!$e.test(n)){x(e,400,{error:"Invalid folder name"});return}let s=path.join(r,n);try{if(!fs$1.statSync(s).isDirectory()){x(e,404,{error:"Not found"});return}}catch{x(e,404,{error:"Not found"});return}try{let a=ce(s);fs$1.rmSync(s,{recursive:!0,force:!0}),x(e,200,{deleted:n,freedBytes:a});}catch(a){x(e,500,{error:a instanceof Error?a.message:String(a)});}}function ur(t,e,r){x(e,200,{status:"shutting_down"}),r.close();}function Ve(t,e,r){if(!fs$1.existsSync(r)){x(e,404,{error:"File not found"});return}try{let n=fs$1.readFileSync(r),s=path.extname(r).toLowerCase(),a=ns[s]??"application/octet-stream";e.writeHead(200,{"Content-Type":a}),e.end(n);}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}var ns={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".json":"application/json",".html":"text/html",".css":"text/css",".js":"text/javascript",".svg":"image/svg+xml"};var os=9323,ls=10,ds=1800*1e3;function X(t,e){return new Promise((r,n)=>{let s=e?.port??os,a=Date.now(),o,i=0,l=fs$1.existsSync(path.join(t,"artifacts"))?path.join(t,"artifacts"):fs$1.existsSync(path.join(t,"..","artifacts"))?path.join(t,"..","artifacts"):path.join(t,"artifacts");function d(){clearTimeout(o),o=setTimeout(()=>{p.close();},ds);}let u=e?.htmlPath??null;if(!u){let c=path.dirname(t);try{let g=fs$1.readdirSync(c).find(h=>h.endsWith(".html"));g&&(u=path.join(c,g));}catch{}}let p=http.createServer((c,g)=>{if(d(),tr(g),c.method==="OPTIONS"){g.writeHead(204),g.end();return}let h;try{h=new URL(c.url??"/",`http://${c.headers.host??"localhost"}`).pathname;}catch{x(g,400,{error:"Invalid URL"});return}if(c.method==="GET"&&(h==="/"||h==="/index.html")){if(u&&fs$1.existsSync(u)){Ve(c,g,u);return}x(g,404,{error:"HTML report not found"});return}if(c.method==="GET"&&h==="/api/health"){rr(c,g,t,a);return}if(c.method==="GET"&&h==="/api/summary"){nr(c,g,t);return}if(c.method==="GET"&&h==="/api/tests"){sr(c,g,t);return}if(c.method==="GET"&&h==="/api/files"){or(c,g,t);return}let m=h.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(c.method==="GET"&&m){ir(c,g,t,m[1],m[2]);return}let w=h.match(/^\/api\/tests\/([a-f0-9]+)$/);if(c.method==="GET"&&w){ar(c,g,t,w[1]);return}if(c.method==="GET"&&h==="/api/artifacts"){lr(c,g,l);return}if(c.method==="DELETE"&&h==="/api/artifacts"){dr(c,g,l);return}let T=h.match(/^\/api\/artifacts\/(.+)$/);if(c.method==="DELETE"&&T){cr(c,g,l,decodeURIComponent(T[1]));return}if(c.method==="GET"&&h.startsWith("/artifacts/")){let y=decodeURIComponent(h.slice(11));if(y.includes("..")||y.includes("\0")){x(g,400,{error:"Invalid path"});return}Ve(c,g,path.join(l,y));return}if(c.method==="POST"&&h==="/api/shutdown"){ur(c,g,p);return}x(g,404,{error:"Not found"});});function f(c){let g=h=>{h.code==="EADDRINUSE"&&i<ls?(i++,f(c+1)):n(h);};p.once("error",g),p.listen(c,"127.0.0.1",()=>{p.removeListener("error",g);let h=p.address();if(!h||typeof h=="string"){n(new Error("Failed to get server address"));return}d(),r({port:h.port,dispose:()=>new Promise(m=>{clearTimeout(o),p.close(()=>m());})});});}f(s);})}async function pr(t){let e=await X(t);return {port:e.port,dispose:e.dispose}}function ps(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return Gt(n,e,s)}async function Ge(t,e,r){try{let n=null,s=null,a=e.reportMode==="streaming"||e.reportMode==="auto"&&t.timeline.length===0&&t.summary.total>=e.streamingThreshold,o,i=e.htmlReportPath,l=path.dirname(i);fs$1.mkdirSync(l,{recursive:!0});let d="",u="[]",p=null;if(a){d=JSON.stringify(t.summary);let c=path.dirname(e.outputPath),g=path.join(c,".testrelic-report");try{let h=path.join(g,"index-compact.json"),m=path.join(g,"index.json");fs$1.existsSync(h)?u=fs$1.readFileSync(h,"utf-8"):fs$1.existsSync(m)&&(u=fs$1.readFileSync(m,"utf-8"));}catch{}p=r?JSON.stringify(r):null,o=ze(d,u,null,p);}else o=ps(t,null,r);let f=i+".tmp";if(fs$1.writeFileSync(f,o,"utf-8"),fs$1.renameSync(f,i),a){if(t.ci===null){let c=path.dirname(e.outputPath),g=path.join(c,".testrelic-report"),h=path.resolve(i);try{if(await gs(),n=await hs(g),!n){s=await X(g,{htmlPath:h}),n=s.port;let m=setInterval(()=>{},6e4),w=()=>{clearInterval(m),s?.dispose();};process.on("SIGINT",w),process.on("SIGTERM",w),setTimeout(w,1800*1e3).unref();}if(n){process.stderr.write(`
2548
+ `;fs$1.writeSync(this.fd,r),this.count++;}getPath(){return this.filePath}getCount(){return this.count}close(){if(!this.closed){this.closed=true;try{fs$1.closeSync(this.fd);}catch{}}}cleanup(){try{fs$1.unlinkSync(this.filePath);}catch{}}};async function Yt(t,e,r,n){let s=(e-1)*r,a=[],o=0,i=readline.createInterface({input:fs$1.createReadStream(t,{encoding:"utf-8"}),crlfDelay:1/0});for await(let u of i)if(u.length!==0){if(o>=s&&a.length<r)try{a.push(JSON.parse(u));}catch{}if(o++,a.length>=r&&n!==void 0)break}let l=n??o,d=Math.max(1,Math.ceil(l/r));return {items:a,total:l,page:e,pageSize:r,totalPages:d}}var Qt=/^[a-f0-9]{12}$/,$e=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,er=500;function x(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function tr(t){t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type");}function de(t){try{return fs$1.existsSync(t)?JSON.parse(fs$1.readFileSync(t,"utf-8")):null}catch{return null}}function ce(t){let e=0;try{let r=fs$1.readdirSync(t,{withFileTypes:!0});for(let n of r){let s=path.join(t,n.name);n.isFile()?e+=fs$1.statSync(s).size:n.isDirectory()&&(e+=ce(s));}}catch{}return e}function rr(t,e,r,n){let s=de(path.join(r,"index.json"));x(e,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-n)/1e3)});}function nr(t,e,r){let n=de(path.join(r,"summary.json"));if(!n){x(e,404,{error:"Summary not found"});return}x(e,200,n);}function sr(t,e,r){let n=de(path.join(r,"index.json"));if(!n){x(e,404,{error:"Test index not found"});return}let a=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,o=Math.max(1,parseInt(a.get("page")??"1",10)||1),i=Math.min(er,Math.max(1,parseInt(a.get("pageSize")??"100",10)||100)),l=a.get("status")?.split(",").filter(Boolean)??null,d=a.get("file")??null,u=a.get("search")?.toLowerCase()??null,p=a.get("tag")?.split(",").filter(Boolean)??null,f=a.get("sort")??"file",c=a.get("order")==="desc"?-1:1,g=n;l&&l.length>0&&(g=g.filter(y=>l.includes(y.status))),d&&(g=g.filter(y=>y.filePath===d||y.filePath.startsWith(d+"/"))),u&&(g=g.filter(y=>y.title.toLowerCase().includes(u)||y.filePath.toLowerCase().includes(u))),p&&p.length>0&&(g=g.filter(y=>p.some(b=>y.tags.includes(b)))),g=[...g].sort((y,b)=>{let C=0;switch(f){case "duration":C=y.duration-b.duration;break;case "status":C=y.status.localeCompare(b.status);break;case "title":C=y.title.localeCompare(b.title);break;default:C=y.filePath.localeCompare(b.filePath);break}return C*c});let h=g.length,m=Math.max(1,Math.ceil(h/i)),w=(o-1)*i,T=g.slice(w,w+i);x(e,200,{tests:T,pagination:{page:o,pageSize:i,totalItems:h,totalPages:m},filters:{status:l,file:d,search:u,tag:p}});}function ar(t,e,r,n){if(!Qt.test(n)){x(e,400,{error:"Invalid test ID format"});return}let s=path.join(r,"tests",n,"meta.json"),a=path.join(r,"tests",`${n}.json`),o=fs$1.existsSync(s)?s:fs$1.existsSync(a)?a:null;if(!o){x(e,404,{error:`Test not found: ${n}`});return}try{let i=fs$1.readFileSync(o,"utf-8");e.writeHead(200,{"Content-Type":"application/json"}),e.end(i);}catch(i){x(e,500,{error:i instanceof Error?i.message:String(i)});}}async function ir(t,e,r,n,s){if(!Qt.test(n)){x(e,400,{error:"Invalid test ID format"});return}let o=path.join(r,"tests",n,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!fs$1.existsSync(o)){x(e,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let l=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,d=Math.max(1,parseInt(l.get("page")??"1",10)||1),u=Math.min(er,Math.max(1,parseInt(l.get("pageSize")??"50",10)||50)),p,f=path.join(r,"tests",n,"meta.json");if(fs$1.existsSync(f))try{let g=JSON.parse(fs$1.readFileSync(f,"utf-8"));switch(s){case "network":p=g.networkRequestsCount;break;case "console":p=g.consoleLogsCount;break;case "api-calls":p=g.apiCallsCount;break}}catch{}let c=await Yt(o,d,u,p);x(e,200,c);}catch(i){x(e,500,{error:i instanceof Error?i.message:String(i)});}}function or(t,e,r){let n=de(path.join(r,"index.json"));if(!n){x(e,404,{error:"Test index not found"});return}let s=new Map;for(let o of n){if(o.isRetry)continue;let i=s.get(o.filePath);switch(i||(i={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},s.set(o.filePath,i)),i.total++,o.status){case "passed":i.passed++;break;case "failed":i.failed++;break;case "flaky":i.flaky++;break;case "skipped":i.skipped++;break;case "timedout":i.timedOut++;break}}let a=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));x(e,200,{files:a});}function lr(t,e,r){if(!fs$1.existsSync(r)){x(e,200,{runs:[],totalSizeBytes:0});return}try{let n=[],s=0,a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!$e.test(o.name))continue;let i=path.join(r,o.name),l=ce(i),d=fs$1.readdirSync(i,{withFileTypes:!0}).filter(u=>u.isDirectory());n.push({folderName:o.name,totalSizeBytes:l,testCount:d.length}),s+=l;}n.sort((o,i)=>i.folderName.localeCompare(o.folderName)),x(e,200,{runs:n,totalSizeBytes:s});}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}function dr(t,e,r){try{let n=0,s=0;if(fs$1.existsSync(r)){let a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!$e.test(o.name))continue;let i=path.join(r,o.name),l=ce(i);fs$1.rmSync(i,{recursive:!0,force:!0}),s+=l,n++;}}x(e,200,{deletedCount:n,freedBytes:s});}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}function cr(t,e,r,n){if(!$e.test(n)){x(e,400,{error:"Invalid folder name"});return}let s=path.join(r,n);try{if(!fs$1.statSync(s).isDirectory()){x(e,404,{error:"Not found"});return}}catch{x(e,404,{error:"Not found"});return}try{let a=ce(s);fs$1.rmSync(s,{recursive:!0,force:!0}),x(e,200,{deleted:n,freedBytes:a});}catch(a){x(e,500,{error:a instanceof Error?a.message:String(a)});}}function ur(t,e,r){x(e,200,{status:"shutting_down"}),r.close();}function Ve(t,e,r){if(!fs$1.existsSync(r)){x(e,404,{error:"File not found"});return}try{let n=fs$1.readFileSync(r),s=path.extname(r).toLowerCase(),a=ns[s]??"application/octet-stream";e.writeHead(200,{"Content-Type":a}),e.end(n);}catch(n){x(e,500,{error:n instanceof Error?n.message:String(n)});}}var ns={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".json":"application/json",".html":"text/html",".css":"text/css",".js":"text/javascript",".svg":"image/svg+xml"};var os=9323,ls=10,ds=1800*1e3;function X(t,e){return new Promise((r,n)=>{let s=e?.port??os,a=Date.now(),o,i=0,l=fs$1.existsSync(path.join(t,"artifacts"))?path.join(t,"artifacts"):fs$1.existsSync(path.join(t,"..","artifacts"))?path.join(t,"..","artifacts"):path.join(t,"artifacts");function d(){clearTimeout(o),o=setTimeout(()=>{p.close();},ds);}let u=e?.htmlPath??null;if(!u){let c=path.dirname(t);try{let g=fs$1.readdirSync(c).find(h=>h.endsWith(".html"));g&&(u=path.join(c,g));}catch{}}let p=http.createServer((c,g)=>{if(d(),tr(g),c.method==="OPTIONS"){g.writeHead(204),g.end();return}let h;try{h=new URL(c.url??"/",`http://${c.headers.host??"localhost"}`).pathname;}catch{x(g,400,{error:"Invalid URL"});return}if(c.method==="GET"&&(h==="/"||h==="/index.html")){if(u&&fs$1.existsSync(u)){Ve(c,g,u);return}x(g,404,{error:"HTML report not found"});return}if(c.method==="GET"&&h==="/api/health"){rr(c,g,t,a);return}if(c.method==="GET"&&h==="/api/summary"){nr(c,g,t);return}if(c.method==="GET"&&h==="/api/tests"){sr(c,g,t);return}if(c.method==="GET"&&h==="/api/files"){or(c,g,t);return}let m=h.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(c.method==="GET"&&m){ir(c,g,t,m[1],m[2]);return}let w=h.match(/^\/api\/tests\/([a-f0-9]+)$/);if(c.method==="GET"&&w){ar(c,g,t,w[1]);return}if(c.method==="GET"&&h==="/api/artifacts"){lr(c,g,l);return}if(c.method==="DELETE"&&h==="/api/artifacts"){dr(c,g,l);return}let T=h.match(/^\/api\/artifacts\/(.+)$/);if(c.method==="DELETE"&&T){cr(c,g,l,decodeURIComponent(T[1]));return}if(c.method==="GET"&&h.startsWith("/artifacts/")){let y=decodeURIComponent(h.slice(11));if(y.includes("..")||y.includes("\0")){x(g,400,{error:"Invalid path"});return}Ve(c,g,path.join(l,y));return}if(c.method==="POST"&&h==="/api/shutdown"){ur(c,g,p);return}x(g,404,{error:"Not found"});});function f(c){let g=h=>{h.code==="EADDRINUSE"&&i<ls?(i++,f(c+1)):n(h);};p.once("error",g),p.listen(c,"127.0.0.1",()=>{p.removeListener("error",g);let h=p.address();if(!h||typeof h=="string"){n(new Error("Failed to get server address"));return}d(),r({port:h.port,dispose:()=>new Promise(m=>{clearTimeout(o),p.close(()=>m());})});});}f(s);})}async function pr(t){let e=await X(t);return {port:e.port,dispose:e.dispose}}function ps(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return Gt(n,e,s)}async function Ge(t,e,r){try{let n=null,s=null,a=e.reportMode==="streaming"||e.reportMode==="auto"&&t.timeline.length===0&&t.summary.total>=e.streamingThreshold,o,i=e.htmlReportPath,l=path.dirname(i);fs$1.mkdirSync(l,{recursive:!0});let d="",u="[]",p=null;if(a){d=JSON.stringify({...t.summary,testRunId:t.testRunId,startedAt:t.startedAt,completedAt:t.completedAt,totalDuration:t.totalDuration,ci:t.ci,metadata:t.metadata,shardRunIds:t.shardRunIds});let c=path.dirname(e.outputPath),g=path.join(c,".testrelic-report");try{let h=path.join(g,"index-compact.json"),m=path.join(g,"index.json");fs$1.existsSync(h)?u=fs$1.readFileSync(h,"utf-8"):fs$1.existsSync(m)&&(u=fs$1.readFileSync(m,"utf-8"));}catch{}p=r?JSON.stringify(r):null,o=ze(d,u,null,p);}else o=ps(t,null,r);let f=i+".tmp";if(fs$1.writeFileSync(f,o,"utf-8"),fs$1.renameSync(f,i),a){if(t.ci===null){let c=path.dirname(e.outputPath),g=path.join(c,".testrelic-report"),h=path.resolve(i);try{if(await gs(),n=await hs(g),!n){s=await X(g,{htmlPath:h}),n=s.port;let m=setInterval(()=>{},6e4),w=()=>{clearInterval(m),s?.dispose();};process.on("SIGINT",w),process.on("SIGTERM",w),setTimeout(w,1800*1e3).unref();}if(n){process.stderr.write(`
2549
2549
  Report server: http://127.0.0.1:${n}
2550
2550
  `);try{let m=ze(d,u,n,p),w=i+".tmp";fs$1.writeFileSync(w,m,"utf-8"),fs$1.renameSync(w,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let c=path.dirname(e.outputPath),g=path.join(c,"artifacts");if(fs$1.existsSync(g))try{let h=await pr(g);n=h.port,process.on("exit",()=>{h.dispose();});}catch{}}if(e.openReport&&t.ci===null)if(a&&n)je(`http://127.0.0.1:${n}`);else {let c=path.resolve(i);je(c);}}catch(n){process.stderr.write(`[testrelic] Failed to write HTML report: ${n instanceof Error?n.message:String(n)}
2551
2551
  `);}}var fe=9323,yr=10;async function fs(){for(let t=fe;t<fe+yr;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),500),n=await fetch(`http://127.0.0.1:${t}/api/health`,{signal:e.signal});if(clearTimeout(r),n.ok)return t}catch{}return null}async function gs(){for(let t=fe;t<fe+yr;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),1e3);await fetch(`http://127.0.0.1:${t}/api/shutdown`,{method:"POST",signal:e.signal}),clearTimeout(r);}catch{}await new Promise(t=>setTimeout(t,300));}async function hs(t){let r=[path.join(__dirname,"cli.cjs"),path.join(__dirname,"cli.js"),path.join(__dirname,"..","dist","cli.cjs"),path.join(__dirname,"..","dist","cli.js")].find(n=>fs$1.existsSync(n));if(!r){let n=await X(t);return process.on("exit",()=>{n?.dispose();}),n.port}return new Promise(n=>{let s=child_process.spawn(process.execPath,[r,"serve",t],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),a="",o=false,i=setTimeout(()=>{o||(o=true,s.stderr?.removeAllListeners(),fs().then(n));},5e3);s.stderr?.on("data",l=>{a+=l.toString();let d=a.match(/127\.0\.0\.1:(\d+)/);d&&!o&&(o=true,clearTimeout(i),s.stderr?.removeAllListeners(),s.unref(),n(Number(d[1])));}),s.on("error",()=>{o||(o=true,clearTimeout(i),n(null));}),s.on("exit",()=>{o||(o=true,clearTimeout(i),n(null));}),s.unref();})}var vs=20,Je=0,Ke=[];async function br(t,e){Je>=vs&&await new Promise(r=>Ke.push(r)),Je++;try{return await promises.copyFile(t,e),!0}catch{return false}finally{Je--,Ke.length>0&&Ke.shift()();}}var ee=[];async function wr(){ee.length!==0&&(await Promise.allSettled(ee),ee.length=0);}function xr(t){let e=new Date,r=a=>String(a).padStart(2,"0"),n=`${e.getFullYear()}-${r(e.getMonth()+1)}-${r(e.getDate())}T${r(e.getHours())}-${r(e.getMinutes())}-${r(e.getSeconds())}`;if(!fs$1.existsSync(path.join(t,n)))return n;let s=1;for(;fs$1.existsSync(path.join(t,`${n}-${s}`));)s++;return `${n}-${s}`}function bs(t){let e=t.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return e.length>100&&(e=e.substring(0,100).replace(/-+$/,"")),e||"unnamed-test"}function kr(t,e,r,n,s){let a=t.find(f=>f.name==="screenshot"&&f.path),o=t.find(f=>f.name==="video"&&f.path);if(!a&&!o)return null;let i=bs(e);r>0&&(i+=`--retry-${r}`);let l=s?["artifacts",s,i]:["artifacts",i],d=path.join(n,...l),u=l,p={};try{fs$1.mkdirSync(d,{recursive:!0});}catch{return null}if(a?.path&&fs$1.existsSync(a.path)){let c=`screenshot${path.extname(a.path)||".png"}`,g=path.join(d,c);ee.push(br(a.path,g).then(()=>{})),p.screenshot=`${u.join("/")}/${c}`;}if(o?.path&&fs$1.existsSync(o.path)){let c=`video${path.extname(o.path)||".webm"}`,g=path.join(d,c);ee.push(br(o.path,g).then(()=>{})),p.video=`${u.join("/")}/${c}`;}return !p.screenshot&&!p.video?null:p}var ks=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Ts="1.0";function Cs(t){let e=path.extname(t).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(e)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(e)?"video":"other"}function Tr(t,e,r){let n=[];try{let s=fs$1.readdirSync(t,{withFileTypes:!0});for(let a of s){if(!a.isFile())continue;let o=path.join(t,a.name),i=fs$1.statSync(o);n.push({name:a.name,type:Cs(a.name),relativePath:`artifacts/${e}/${r}/${a.name}`,sizeBytes:i.size});}}catch{}return {testName:r,files:n}}function Ss(t,e){let r=path.join(t,e),n=[],s=0;try{let o=fs$1.readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let l=Tr(path.join(r,i.name),e,i.name);n.push(l);for(let d of l.files)s+=d.sizeBytes;}}catch{}let a=e.replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/,"$1T$2:$3:$4").replace(/-\d+$/,"");return n.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:e,timestamp:a,totalSizeBytes:s,testCount:n.length,tests:n,isCurrentRun:false}}function Cr(t,e){let r=path.join(t,"artifacts"),n=[],s=[],a=0;try{let i=fs$1.readdirSync(r,{withFileTypes:!0});for(let l of i)if(l.isDirectory())if(ks.test(l.name)){let d=Ss(r,l.name);n.push({...d,isCurrentRun:l.name===e});}else {let d=Tr(path.join(r,l.name),l.name,l.name);s.push(d);for(let u of d.files)a+=u.sizeBytes;}}catch{}n.sort((i,l)=>l.timestamp.localeCompare(i.timestamp)),s.length>0&&(s.sort((i,l)=>i.testName.localeCompare(l.testName)),n.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:a,testCount:s.length,tests:s,isCurrentRun:false}));let o=n.reduce((i,l)=>i+l.totalSizeBytes,0);return {schemaVersion:Ts,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:n,serverPort:null}}function Ls(t){let e=t,{root:r}=path.parse(e);for(;e!==r;){if(fs$1.existsSync(path.join(e,".git")))return e;e=path.join(e,"..");}return null}function Rr(t){try{let e=Ls(t);if(!e)return;let r=path.join(e,".gitignore"),n=path.relative(e,t).replace(/\\/g,"/"),s=n.endsWith("/")?n:`${n}/`;if(fs$1.existsSync(r)&&fs$1.readFileSync(r,"utf-8").split(`
@@ -2576,19 +2576,21 @@ ${s}
2576
2576
  `);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
2577
2577
  `);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?re(this.gitMetadata.remoteUrl):null,r=e?Or(e):this.config.projectName??ne(process.cwd()),n=e??this.config.projectName??ne(process.cwd()),s=this.readRepoCache(n);if(s){this.repoId=s.repoId;return}try{let a=await Dr(this.config.endpoint,this.authState.accessToken,n,r,this.config.timeout,this.gitMetadata?.branch);a&&(this.repoId=a.repoId,this.writeRepoCache(n,a.repoId,a.displayName));}catch{}!e&&!this.config.projectName&&!st(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
2578
2578
  `);}readRepoCache(e){if(!this.config)return null;let r=path.join(this.config.queueDirectory,"..","cache","repo.json");try{if(!fs$1.existsSync(r))return null;let n=fs$1.readFileSync(r,"utf-8"),s=JSON.parse(n);if(s.gitId!==e||Date.now()-s.resolvedAt>fa)return null;let a=this.hashApiKey();return a&&s.apiKeyHash!==a?null:s}catch{return null}}writeRepoCache(e,r,n){if(!this.config)return;let s=path.join(this.config.queueDirectory,"..","cache"),a=path.join(s,"repo.json");try{fs$1.mkdirSync(s,{recursive:!0});let o={repoId:r,gitId:e,displayName:n,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},i=a+".tmp";fs$1.writeFileSync(i,JSON.stringify(o,null,2),"utf-8"),fs$1.renameSync(i,a);}catch{}}hashApiKey(){return this.config?.apiKey?crypto.createHash("sha256").update(this.config.apiKey).digest("hex").substring(0,16):null}startBackgroundFlush(){if(!this.config||!this.authState.accessToken)return;let e=this.authState.accessToken,r=this.config.queueDirectory,n=this.config.endpoint;this.flushPromise=Promise.race([zr(r,n,e),new Promise(s=>setTimeout(s,$r))]).catch(()=>{});}startHealthCheck(){if(!this.config)return;let e=this.config.endpoint;this.healthCheckTimer=setInterval(async()=>{if(!this.isCloudMode()&&!(!this.failureReason||!["cloud_unreachable","auth_timeout","network_error"].includes(this.failureReason)))try{if(!await tt(e))return;if(this.config?.apiKey){let n=await rt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!nt(n)){let s=n;this.authState={mode:"cloud",accessToken:s.accessToken,refreshToken:s.refreshToken,expiresAt:Date.now()+s.expiresIn*1e3,orgId:s.orgId,orgName:s.orgName,userId:s.userId,userName:s.userName},this.failureReason=null,process.stderr.write(`\u2713 TestRelic: Cloud connectivity restored.
2579
- `),this.startBackgroundFlush();}}}catch{}},ga);}};var ha=new Set(["smoke","regression","nightly","ci"]);function ye(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&ha.has(t))return t}var ya=1048576,ve=[1e3,3e3,9e3],be=3,va=40*1048576,ba=new Set(["e2e","mobile","unit"]);function dt(t){if(t&&t.length>0&&t.every(s=>s.testType==="api")){let s=new Map;for(let i of t){let l=i.apiProtocol??"rest";s.set(l,(s.get(l)??0)+1);}let a="rest",o=0;for(let[i,l]of s)l>o&&(o=l,a=i);return {testType:"api",apiProtocol:a,metadata:{testType:"api",primaryProtocol:a}}}let e=new Map;for(let s of t??[])ba.has(s.testType)&&e.set(s.testType,(e.get(s.testType)??0)+1);let r=null,n=0;for(let[s,a]of e)a>n&&(n=a,r=s);return {testType:r??"e2e"}}function ct(t,e,r,n,s,a){let o=a?.cloudPlatform?a.cloudPlatform:n?.provider&&n.provider!=="unknown"?n.provider:"local",i=ye(),l=dt(s),d=l.testType==="api"?l:null,u=d&&s?s.map(f=>f.apiProtocol?f:{...f,apiProtocol:d.apiProtocol}):s,p={runId:t.testRunId,repoGitId:e,startedAt:t.startedAt,summary:t.summary,timeline:t.timeline,environment:o,...i?{runType:i}:{},...d?{testType:d.testType,apiProtocol:d.apiProtocol,metadata:d.metadata}:{testType:l.testType},...u&&u.length>0?{tests:u}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...t.completedAt?{finishedAt:t.completedAt}:{},...t.totalDuration?{duration:t.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{},...a?.cloudPlatform?{cloudPlatform:a.cloudPlatform}:{},...a?.cloudBuildId?{cloudBuildId:a.cloudBuildId}:{},...a?.cloudSessionId?{cloudSessionId:a.cloudSessionId}:{}};if(p.tests&&p.tests.length>0){let f=JSON.stringify(p);if(Buffer.byteLength(f,"utf-8")>va){let c=p.tests.map(({consoleLogs:g,networkRequests:h,apiCalls:m,...w})=>w);return {...p,tests:c}}}return p}function lt(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function ut(t){return Array.isArray(t)?t.map(e=>{let r=e.statusCode??e.responseStatusCode??null;return {...e.protocol!=null?{protocol:e.protocol}:{},method:e.method??null,url:e.url??null,statusCode:r,statusText:e.statusText??e.responseStatusText??null,ok:typeof r=="number"?r<400:e.ok??null,durationMs:e.durationMs??e.responseTimeMs??null,bytesIn:typeof e.bytesIn=="number"?e.bytesIn:lt(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:lt(e.requestBody),requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,requestCookies:e.requestCookies??null,responseCookies:e.responseCookies??null}}):[]}function pt(t){return Array.isArray(t)?t.map(e=>{let r=e.responseStatusCode??e.statusCode??0,n=e.timestamp??null;return {method:e.method??"GET",url:e.url??"",status:r,statusCode:r,type:"xhr",size:lt(e.responseBody),duration:e.responseTimeMs??e.durationMs??0,responseTimeMs:e.responseTimeMs??e.durationMs??0,requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,timestamp:n,startedAt:n}}):[]}function ft(t){if(!Array.isArray(t))return [];let e=r=>{if(r==null)return String(r);if(typeof r=="string")return r;try{return JSON.stringify(r)}catch{return String(r)}};return t.map(r=>{let n=r.status==="failed"?"failed":"passed",s=typeof r.expression=="string"&&r.expression.trim()?r.expression.trim():null,a=r.kind??r.type??"assertion",o=n==="failed"?`expected ${e(r.expected)}, received ${e(r.actual)}`:r.expected!==void 0?`expected ${e(r.expected)}`:null;return {kind:a,description:s??r.description??`${a} assertion`,status:n,detail:o}})}async function we(t){return new Promise(e=>setTimeout(e,t))}function wa(t){let e={};for(let[r,n]of Object.entries(t))n!=null&&(e[r]=n);return e}async function Vr(t,e,r){for(let n=0;n<be;n++)try{let s=await fetch(t,e);if(s.ok)return s;if(s.status===401&&r&&n===0){let a=await r();if(a){let o={...e,headers:{...e.headers,Authorization:`Bearer ${a}`}},i=await fetch(t,o);if(i.ok)return i}return null}if(s.status===429&&n<be-1){let a=s.headers.get("Retry-After"),o=a?parseInt(a,10)*1e3:ve[n];!isNaN(o)&&o>0?await we(o):await we(ve[n]);continue}if(s.status>=500&&n<be-1){await we(ve[n]);continue}return s}catch{if(n<be-1){await we(ve[n]);continue}return null}return null}function xa(t){let e=JSON.stringify(t),r={"Content-Type":"application/json"};if(Buffer.byteLength(e,"utf-8")>ya){let n=zlib.gzipSync(Buffer.from(e,"utf-8"));return r["Content-Encoding"]="gzip",{body:n,headers:r}}return {body:e,headers:r}}async function Wr(t,e,r,n){let s=`${t}/runs`,{body:a,headers:o}=xa(r);o.Authorization=`Bearer ${e}`;let i=await Vr(s,{method:"POST",headers:o,body:a},n);return i?.ok?{success:true,statusCode:i.status,error:null}:i?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:i?`Upload failed with status ${i.status}`:"Upload failed after retries",statusCode:i?.status??null,payload:r,targetEndpoint:s,method:"POST"}}async function Gr(t,e,r){let n=`${t}/runs/init`;try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(wa(r))});return s.ok?{runId:(await s.json()).runId}:null}catch{return null}}function Jr(t,e,r,n){let s=`${t}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}).catch(()=>{});}async function Kr(t,e,r,n){let s=`${t}/runs/${r}/finalize`;return (await Vr(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}))?.ok??false}function gt(t,e,r,n){let s=`${t}/runs/${r}/finalize`,a=new Date,o={finishedAt:a.toISOString(),duration:a.getTime()-new Date(n).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)}).catch(()=>{});}function Yr(t,e,r,n){let s=[],a=[],o=null,i=0,l=null,d=0,u=null,p=0,f=t.filter(h=>h.name===core.ATTACHMENT_NAME&&h.body),c=false;if(f.length>0)for(let h of f)try{let m=JSON.parse(h.body.toString());if(core.isTestRelicFilePayload(m)){s=s.concat(m.navigations),a=a.concat(m.apiAssertions),m.networkRequestsFile&&(o=m.networkRequestsFile,i+=m.networkRequestsCount),m.consoleLogsFile&&(l=m.consoleLogsFile,d+=m.consoleLogsCount),m.apiCallsFile&&(u=m.apiCallsFile,p+=m.apiCallsCount),c=!0;continue}if(core.isTestRelicDataPayload(m)){s=s.concat(m.navigations),Array.isArray(m.apiAssertions)&&(a=a.concat(m.apiAssertions)),i+=m.networkRequests?.length??0,p+=m.apiCalls?.length??0;let w=m.consoleLogs;Array.isArray(w)&&(d+=w.length),c=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
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.
2579
+ `),this.startBackgroundFlush();}}}catch{}},ga);}};var ha=new Set(["smoke","regression","nightly","ci"]);function ye(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&ha.has(t))return t}var ya=1048576,ve=[1e3,3e3,9e3],be=3,va=40*1048576,ba=new Set(["e2e","mobile","unit"]);function dt(t){if(t&&t.length>0&&t.every(s=>s.testType==="api")){let s=new Map;for(let i of t){let l=i.apiProtocol??"rest";s.set(l,(s.get(l)??0)+1);}let a="rest",o=0;for(let[i,l]of s)l>o&&(o=l,a=i);return {testType:"api",apiProtocol:a,metadata:{testType:"api",primaryProtocol:a}}}let e=new Map;for(let s of t??[])ba.has(s.testType)&&e.set(s.testType,(e.get(s.testType)??0)+1);let r=null,n=0;for(let[s,a]of e)a>n&&(n=a,r=s);return {testType:r??"e2e"}}function ct(t,e,r,n,s,a){let o=a?.cloudPlatform?a.cloudPlatform:n?.provider&&n.provider!=="unknown"?n.provider:"local",i=ye(),l=dt(s),d=l.testType==="api"?l:null,u=d&&s?s.map(f=>f.apiProtocol?f:{...f,apiProtocol:d.apiProtocol}):s,p={runId:t.testRunId,repoGitId:e,startedAt:t.startedAt,summary:t.summary,timeline:t.timeline,environment:o,...i?{runType:i}:{},...d?{testType:d.testType,apiProtocol:d.apiProtocol,metadata:d.metadata}:{testType:l.testType},...u&&u.length>0?{tests:u}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...t.completedAt?{finishedAt:t.completedAt}:{},...t.totalDuration?{duration:t.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{},...a?.cloudPlatform?{cloudPlatform:a.cloudPlatform}:{},...a?.cloudBuildId?{cloudBuildId:a.cloudBuildId}:{},...a?.cloudSessionId?{cloudSessionId:a.cloudSessionId}:{}};if(p.tests&&p.tests.length>0){let f=JSON.stringify(p);if(Buffer.byteLength(f,"utf-8")>va){let c=p.tests.map(({consoleLogs:g,networkRequests:h,apiCalls:m,...w})=>w);return {...p,tests:c}}}return p}function lt(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function ut(t){return Array.isArray(t)?t.map(e=>{let r=e.statusCode??e.responseStatusCode??null;return {...e.id!=null?{id:e.id}:{},...e.protocol!=null?{protocol:e.protocol}:{},method:e.method??null,url:e.url??null,statusCode:r,statusText:e.statusText??e.responseStatusText??null,ok:typeof r=="number"?r<400:e.ok??null,durationMs:e.durationMs??e.responseTimeMs??null,bytesIn:typeof e.bytesIn=="number"?e.bytesIn:lt(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:lt(e.requestBody),requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,requestCookies:e.requestCookies??null,responseCookies:e.responseCookies??null}}):[]}function pt(t){return Array.isArray(t)?t.map(e=>{let r=e.responseStatusCode??e.statusCode??0,n=e.timestamp??null;return {method:e.method??"GET",url:e.url??"",status:r,statusCode:r,type:"xhr",size:lt(e.responseBody),duration:e.responseTimeMs??e.durationMs??0,responseTimeMs:e.responseTimeMs??e.durationMs??0,requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,timestamp:n,startedAt:n}}):[]}function ft(t){if(!Array.isArray(t))return [];let e=r=>{if(r==null)return String(r);if(typeof r=="string")return r;try{return JSON.stringify(r)}catch{return String(r)}};return t.map(r=>{let n=r.status==="failed"?"failed":"passed",s=typeof r.expression=="string"&&r.expression.trim()?r.expression.trim():null,a=r.kind??r.type??"assertion",o=n==="failed"?`expected ${e(r.expected)}, received ${e(r.actual)}`:r.expected!==void 0?`expected ${e(r.expected)}`:null;return {...r.callId!=null?{callId:r.callId}:{},kind:a,description:s??r.description??`${a} assertion`,status:n,detail:o}})}async function we(t){return new Promise(e=>setTimeout(e,t))}function wa(t){let e={};for(let[r,n]of Object.entries(t))n!=null&&(e[r]=n);return e}async function Vr(t,e,r){for(let n=0;n<be;n++)try{let s=await fetch(t,e);if(s.ok)return s;if(s.status===401&&r&&n===0){let a=await r();if(a){let o={...e,headers:{...e.headers,Authorization:`Bearer ${a}`}},i=await fetch(t,o);if(i.ok)return i}return null}if(s.status===429&&n<be-1){let a=s.headers.get("Retry-After"),o=a?parseInt(a,10)*1e3:ve[n];!isNaN(o)&&o>0?await we(o):await we(ve[n]);continue}if(s.status>=500&&n<be-1){await we(ve[n]);continue}return s}catch{if(n<be-1){await we(ve[n]);continue}return null}return null}function xa(t){let e=JSON.stringify(t),r={"Content-Type":"application/json"};if(Buffer.byteLength(e,"utf-8")>ya){let n=zlib.gzipSync(Buffer.from(e,"utf-8"));return r["Content-Encoding"]="gzip",{body:n,headers:r}}return {body:e,headers:r}}async function Wr(t,e,r,n){let s=`${t}/runs`,{body:a,headers:o}=xa(r);o.Authorization=`Bearer ${e}`;let i=await Vr(s,{method:"POST",headers:o,body:a},n);return i?.ok?{success:true,statusCode:i.status,error:null}:i?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:i?`Upload failed with status ${i.status}`:"Upload failed after retries",statusCode:i?.status??null,payload:r,targetEndpoint:s,method:"POST"}}async function Gr(t,e,r){let n=`${t}/runs/init`;try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(wa(r))});return s.ok?{runId:(await s.json()).runId}:null}catch{return null}}function Jr(t,e,r,n){let s=`${t}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}).catch(()=>{});}async function Kr(t,e,r,n){let s=`${t}/runs/${r}/finalize`;return (await Vr(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}))?.ok??false}function gt(t,e,r,n){let s=`${t}/runs/${r}/finalize`,a=new Date,o={finishedAt:a.toISOString(),duration:a.getTime()-new Date(n).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)}).catch(()=>{});}function Yr(t,e,r,n){let s=[],a=[],o=null,i=0,l=null,d=0,u=null,p=0,f=t.filter(h=>h.name===core.ATTACHMENT_NAME&&h.body),c=false;if(f.length>0)for(let h of f)try{let m=JSON.parse(h.body.toString());if(core.isTestRelicFilePayload(m)){s=s.concat(m.navigations),a=a.concat(m.apiAssertions),m.networkRequestsFile&&(o=m.networkRequestsFile,i+=m.networkRequestsCount),m.consoleLogsFile&&(l=m.consoleLogsFile,d+=m.consoleLogsCount),m.apiCallsFile&&(u=m.apiCallsFile,p+=m.apiCallsCount),c=!0;continue}if(core.isTestRelicDataPayload(m)){s=s.concat(m.navigations),Array.isArray(m.apiAssertions)&&(a=a.concat(m.apiAssertions)),i+=m.networkRequests?.length??0,p+=m.apiCalls?.length??0;let w=m.consoleLogs;Array.isArray(w)&&(d+=w.length),c=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
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 Test Navigation data cannot be captured.
2581
2581
  `),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:l,consoleLogsCount:d,apiCallsFile:u,apiCallsCount:p}}function xe(t=process.env){let e=Sa(t.TESTRELIC_CLOUD_PLATFORM);if(e)return {cloudPlatform:e,cloudBuildId:t.TESTRELIC_CLOUD_BUILD_ID||void 0,cloudSessionId:t.TESTRELIC_CLOUD_SESSION_ID||void 0};if(t.BROWSERSTACK_USERNAME||t.BROWSERSTACK_ACCESS_KEY)return {cloudPlatform:"browserstack",cloudBuildId:t.BROWSERSTACK_BUILD_NAME||t.BROWSERSTACK_BUILD_ID||void 0,cloudSessionId:t.BROWSERSTACK_SESSION_ID||void 0};if(t.LT_USERNAME||t.LAMBDATEST_USERNAME||t.LT_ACCESS_KEY||t.LAMBDATEST_ACCESS_KEY)return {cloudPlatform:"lambdatest",cloudBuildId:t.LT_BUILD||t.LAMBDATEST_BUILD||void 0,cloudSessionId:t.LT_SESSION_ID||t.LAMBDATEST_SESSION_ID||void 0};let r=t.PLAYWRIGHT_WS_ENDPOINT;if(r){if(/cdp\.lambdatest\.com/i.test(r))return {cloudPlatform:"lambdatest"};if(/cdp\.browserstack\.com/i.test(r))return {cloudPlatform:"browserstack"}}return {}}function Sa(t){if(!t)return;let e=t.toLowerCase().trim();if(e==="browserstack"||e==="bs")return "browserstack";if(e==="lambdatest"||e==="lt")return "lambdatest"}var La=5,ke=[1e3,3e3,9e3],$=3,Pa={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip"},ht=0,mt=[];async function Ea(){ht>=La&&await new Promise(t=>mt.push(t)),ht++;}function Ma(){ht--,mt.length>0&&mt.shift()();}async function Te(t){return new Promise(e=>setTimeout(e,t))}function Na(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return Pa[e]??"application/octet-stream"}function Fa(t){try{return fs$1.statSync(t).size}catch{return 0}}async function Da(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<$;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<$-1){await Te(ke[i]);continue}return null}catch{if(i<$-1){await Te(ke[i]);continue}return null}return null}async function Ba(t,e,r,n){for(let s=0;s<$;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<$-1){await Te(ke[s]);continue}return !1}catch{if(s<$-1){await Te(ke[s]);continue}return false}return false}async function Oa(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 qa(t,e,r,n){let s=Fa(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=Na(r.filePath);await Ea();try{let o=await Da(t,e,r,s,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Ba(o.uploadUrl,r.filePath,a,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let l=await Oa(t,e,o.artifactId);return {success:l,storageKey:o.storageKey,artifactId:o.artifactId,error:l?null:"confirm_failed"}}finally{Ma();}}async function Zr(t,e,r,n){let s=new Map,a=r.map(async o=>{let i=await qa(t,e,o,n);s.set(o.filePath,i);});return await Promise.allSettled(a),s}function yt(t){let r=t.getGitMetadata()?.remoteUrl;return r?re(r):t.getConfig()?.projectName??ne(process.cwd())}async function Qr(t,e,r,n,s){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=F(),l=xe(),d=ye();return (await Gr(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:yt(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??l.cloudPlatform??null,cloudPlatform:l.cloudPlatform??null,cloudBuildId:l.cloudBuildId??null,cloudSessionId:l.cloudSessionId??null,...d?{runType:d}:{},testType:"e2e"}))?.runId??null}var Ha=true,Ua=50;async function za(t,e,r,n){let s=new Map;if(!(e?.uploadArtifacts??Ha)||!await t.ensureValidToken())return s;let i=[],l=new Map;for(let c of n){if(c.artifacts.screenshot){let g=path.join(c.outputDir,c.artifacts.screenshot);i.push({filePath:g,runId:r,testId:c.testId,type:"screenshot"}),l.set(g,{testId:c.testId,field:"screenshot"});}if(c.artifacts.video){let g=path.join(c.outputDir,c.artifacts.video);i.push({filePath:g,runId:r,testId:c.testId,type:"video"}),l.set(g,{testId:c.testId,field:"video"});}}if(i.length===0)return s;let d=e?.artifactMaxSizeMb??Ua,u=await Zr(t.getEndpoint(),t.getAccessToken(),i,d),p=new Map;for(let[c,g]of u){if(!g.success||!g.storageKey)continue;let h=l.get(c);if(!h)continue;let m=p.get(h.testId)??{};h.field==="screenshot"&&(m.screenshotKey=g.storageKey),h.field==="video"&&(m.videoKey=g.storageKey),p.set(h.testId,m);}for(let c of n){let g=p.get(c.testId);s.set(c.testId,{...c.artifacts,...g?.screenshotKey?{screenshotKey:g.screenshotKey}:{},...g?.videoKey?{videoKey:g.videoKey}:{}});}let f=Array.from(u.values()).filter(c=>c.success).length;return f>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${f} artifact(s) to cloud storage.
2582
2582
  `),s}async function vt(t,e,r,n,s,a,o,i,l,d,u){try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){let f=await t.ensureValidToken(),c=t.getGitMetadata(),g=dt(u),h={finishedAt:o,duration:i,summary:l,...c?.commitMessage?{commitMessage:c.commitMessage}:{},testType:g.testType,...g.testType==="api"?{apiProtocol:g.apiProtocol,metadata:g.metadata}:{}};if(f){if(!await Kr(t.getEndpoint(),t.getAccessToken(),s,h)){let w=e?.queueDirectory??".testrelic/queue";se(w,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",h,{"Content-Type":"application/json"});}}else {let m=e?.queueDirectory??".testrelic/queue";se(m,n,"finalize",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",h,{"Content-Type":"application/json"});}}let p=new Map;if(t.isCloudMode()&&d&&d.length>0&&(p=await za(t,e,n,d)),t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await t.ensureValidToken()){let c=t.getGitMetadata(),g=F(),h=yt(t),m=ja(a,p),w=ct(m,h,c,g,u,xe()),T=await Wr(t.getEndpoint(),t.getAccessToken(),w,async()=>await t.ensureValidToken()?t.getAccessToken():null);if(!T.success){let y=T,b=e?.queueDirectory??".testrelic/queue";se(b,n,"batch",y.reason,y.targetEndpoint,y.method,y.payload,{"Content-Type":"application/json"});}}else {let c=e?.queueDirectory??".testrelic/queue",g=t.getGitMetadata(),h=F(),m=yt(t),w=ct(a,m,g,h,void 0,xe());se(c,n,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",w,{"Content-Type":"application/json"});}await t.dispose();}catch{try{await t.dispose();}catch{}}}function ja(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 U(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 wt(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 Ya(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function Za(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 Qa(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 ei(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function ti(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 ri(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 ni="__testrelic_api_config";function si(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var Ce=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=$t(e),this.apiConfig=jt(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 Z(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&&gt(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=xr(path.join(a,"artifacts"));try{Rr(path.join(a,"artifacts"));}catch{}}let s=F();this.detectedOs=ei(),this.detectedSource=Qa(s);try{this.cloudClient=new me(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await Qr(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&&gt(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:ni,description:si(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=wt(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=Yr(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 R=(a==="flaky"?e.results.find(q=>q.status!=="passed")?.errors??[]:n.errors)[0];if(R){let q=Wt(this.config.redactPatterns),J=R.location?.line??null,K=null;this.config.includeCodeSnippets&&J!==null&&R.location?.file&&(K=Vt(R.location.file,J,this.config.codeContextLines),K&&(K=q(K))),u={message:q(R.message??"Unknown error"),line:J,code:K,stack:this.config.includeStackTrace&&R.stack?q(R.stack):null};}}let p=e.titlePath().filter(Boolean),f=path.relative(this.rootDir||".",e.location.file),c=Za(p),g=p.join(" > "),h=f,m=Ya(h,c,g),w=ri(l,h,e),T=w!=="mobile"&&d.apiCallsCount>0?"api":w,y=s==="flaky",b=Xa(e.results),C=wt(e.expectedStatus),v=wt(n.status),k=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let A=path.dirname(this.config.outputPath),R=p[p.length-1]??e.title;k=kr(n.attachments,R,n.retry,A,this.runTimestamp||void 0);}let S=this.config.includeActionSteps&&n.steps?Pr(n.steps,n.startTime):null,P=ti(e),E={titlePath:p,title:g,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:l,failure:u,specFile:f,navigations:d.navigations,testId:m,filePath:h,suiteName:c,testType:T,isFlaky:y,retryStatus:b,expectedStatus:C,actualStatus:v,artifacts:k,apiAssertions:d.apiAssertions,actions:S,networkRequestsFile:d.networkRequestsFile,networkRequestsCount:d.networkRequestsCount,consoleLogsFile:d.consoleLogsFile,consoleLogsCount:d.consoleLogsCount,apiCallsFile:d.apiCallsFile,apiCallsCount:d.apiCallsCount,browser:P,os:this.detectedOs||void 0,source:this.detectedSource||void 0},At=d.consoleLogsFile&&d.consoleLogsCount>0?U(d.consoleLogsFile):void 0,Ie=d.networkRequestsFile&&d.networkRequestsCount>0?U(d.networkRequestsFile):void 0,ae=d.apiCallsFile&&d.apiCallsCount>0?U(d.apiCallsFile):void 0,_t=ae?ut(ae):void 0,It=!Ie&&ae?pt(ae):void 0,Lt=d.apiAssertions&&d.apiAssertions.length>0?ft(d.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:m,title:g,status:a,duration:n.duration,suiteName:c,filePath:h,testType:T,isFlaky:y,startedAt:o,completedAt:i,tags:l,failure:u,retry:n.retry,retryCount:e.results.length-1,retryStatus:b,browser:P,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...S&&S.length>0?{actions:S}:{},...At?{consoleLogs:At}:{},...Ie?{networkRequests:Ie}:It?{networkRequests:It}:{},..._t?{apiCalls:_t}:{},...Lt?{protocolAssertions:Lt}:{}});try{let A=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(A==="realtime"||A==="both")){let R=this.cloudClient.getAccessToken();R&&Jr(this.cloudClient.getEndpoint(),R,this.cloudRunId,this.buildCloudTestPayload(E));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let A=Le(h,p,e.id??"",n.retry),R=n.retry===e.results.length-1,q={id:A,navigations:d.navigations,apiAssertions:d.apiAssertions,actions:S??[],artifacts:k,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,q,{networkRequestsFile:d.networkRequestsFile,consoleLogsFile:d.consoleLogsFile,apiCallsFile:d.apiCallsFile});let J={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:k!==null,hasActionSteps:(S?.length??0)>0,errorMessage:u?.message?.split(`
2583
+ `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function wt(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 Ya(t,e,r){let n=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,16)}function Za(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 Qa(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 ei(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function ti(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 ri(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 ni="__testrelic_api_config";function si(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var Ce=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.navigationsCaptured=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=$t(e),this.apiConfig=jt(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 Z(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&&gt(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=xr(path.join(a,"artifacts"));try{Rr(path.join(a,"artifacts"));}catch{}}let s=F();this.detectedOs=ei(),this.detectedSource=Qa(s);try{this.cloudClient=new me(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await Qr(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&&gt(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:ni,description:si(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=wt(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=Yr(n.attachments,e.annotations,e.title,a==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0),d.navigations.length>0&&(this.navigationsCaptured=!0),!this.config.captureNavigation&&d.navigations.length>0&&(d={...d,navigations:[]});let u=null;if(a==="failed"||a==="flaky"){let R=(a==="flaky"?e.results.find(q=>q.status!=="passed")?.errors??[]:n.errors)[0];if(R){let q=Wt(this.config.redactPatterns),J=R.location?.line??null,K=null;this.config.includeCodeSnippets&&J!==null&&R.location?.file&&(K=Vt(R.location.file,J,this.config.codeContextLines),K&&(K=q(K))),u={message:q(R.message??"Unknown error"),line:J,code:K,stack:this.config.includeStackTrace&&R.stack?q(R.stack):null};}}let p=e.titlePath().filter(Boolean),f=path.relative(this.rootDir||".",e.location.file),c=Za(p),g=p.join(" > "),h=f,m=Ya(h,c,g),w=ri(l,h,e),T=w!=="mobile"&&d.apiCallsCount>0?"api":w,y=s==="flaky",b=Xa(e.results),C=wt(e.expectedStatus),v=wt(n.status),k=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let A=path.dirname(this.config.outputPath),R=p[p.length-1]??e.title;k=kr(n.attachments,R,n.retry,A,this.runTimestamp||void 0);}let S=this.config.includeActionSteps&&n.steps?Pr(n.steps,n.startTime):null,P=ti(e),E={titlePath:p,title:g,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:l,failure:u,specFile:f,navigations:d.navigations,testId:m,filePath:h,suiteName:c,testType:T,isFlaky:y,retryStatus:b,expectedStatus:C,actualStatus:v,artifacts:k,apiAssertions:d.apiAssertions,actions:S,networkRequestsFile:d.networkRequestsFile,networkRequestsCount:d.networkRequestsCount,consoleLogsFile:d.consoleLogsFile,consoleLogsCount:d.consoleLogsCount,apiCallsFile:d.apiCallsFile,apiCallsCount:d.apiCallsCount,browser:P,os:this.detectedOs||void 0,source:this.detectedSource||void 0},At=d.consoleLogsFile&&d.consoleLogsCount>0?U(d.consoleLogsFile):void 0,Ie=d.networkRequestsFile&&d.networkRequestsCount>0?U(d.networkRequestsFile):void 0,ae=d.apiCallsFile&&d.apiCallsCount>0?U(d.apiCallsFile):void 0,_t=ae?ut(ae):void 0,It=!Ie&&ae?pt(ae):void 0,Lt=d.apiAssertions&&d.apiAssertions.length>0?ft(d.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:m,title:g,status:a,duration:n.duration,suiteName:c,filePath:h,testType:T,isFlaky:y,startedAt:o,completedAt:i,tags:l,failure:u,retry:n.retry,retryCount:e.results.length-1,retryStatus:b,browser:P,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...S&&S.length>0?{actions:S}:{},...d.navigations&&d.navigations.length>0?{navigations:d.navigations}:{},...At?{consoleLogs:At}:{},...Ie?{networkRequests:Ie}:It?{networkRequests:It}:{},..._t?{apiCalls:_t}:{},...Lt?{protocolAssertions:Lt}:{}});try{let A=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(A==="realtime"||A==="both")){let R=this.cloudClient.getAccessToken();R&&Jr(this.cloudClient.getEndpoint(),R,this.cloudRunId,this.buildCloudTestPayload(E));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let A=Le(h,p,e.id??"",n.retry),R=n.retry===e.results.length-1,q={id:A,navigations:d.navigations,apiAssertions:d.apiAssertions,actions:S??[],artifacts:k,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,q,{networkRequestsFile:d.networkRequestsFile,consoleLogsFile:d.consoleLogsFile,apiCallsFile:d.apiCallsFile});let J={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:k!==null,hasActionSteps:(S?.length??0)>0,errorMessage:u?.message?.split(`
2585
2585
  `)[0]??null,networkCount:d.networkRequestsCount,consoleCount:d.consoleLogsCount,actionCount:S?.length??0,isRetry:!R};if(this.testIndex.push(J),R)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+=S?.length??0,k&&this.pendingArtifactEntries.push({testId:m,artifacts:k,outputDir:path.dirname(this.config.outputPath)}),E.actions=null,E.apiAssertions=null,E.navigations=[],E.artifacts=null,E.failure=null,E.networkRequestsFile=null,E.consoleLogsFile=null,E.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(E),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
- To enable network logs, video sync, and timeline tracking, import the TestRelic fixture:
2587
+ To enable network logs, video sync, and Test Navigation tracking, import the TestRelic fixture:
2588
2588
  import { test, expect } from '@testrelic/playwright-analytics/fixture';
2589
2589
  instead of:
2590
2590
  import { test, expect } from '@playwright/test';
2591
2591
 
2592
+ `),this.config.captureNavigation?this.fixtureDataReceived&&!this.navigationsCaptured&&o&&process.stderr.write(`[testrelic] Test Navigation: 0 navigation events captured this run. Navigation is recorded automatically on page.goto()/clicks; if you expected a navigation graph, ensure your tests drive page navigations (and use the '@testrelic/playwright-analytics/fixture' import).
2593
+ `):process.stderr.write(`[testrelic] Test Navigation capture is disabled (captureNavigation: false). Remove the option or set it to true to capture the navigation graph.
2592
2594
  `),await wr();let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let l=path.dirname(this.config.outputPath);i=Cr(l,this.runTimestamp);let d=path.join(l,"artifact-manifest.json"),u=JSON.stringify(i),p=d+".tmp";fs$1.writeFileSync(p,u,"utf-8"),fs$1.renameSync(p,d);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await this.finalizeStreamingReport(r,a,e,i);else {let l=this.buildTimeline(),d=new Map;for(let c of this.collectedTests){let g=d.get(c.testId);(!g||c.retry>g.retry)&&d.set(c.testId,c);}let u=Array.from(d.values()),p=Lr(u,l.length),f={schemaVersion:ie,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:a,summary:p,ci:F(),metadata:this.config.metadata,timeline:l,shardRunIds:null};if(this.writeReport(f),await Ge(f,this.config,i),Qe(p,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let c=this.collectArtifactEntries(),g=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await vt(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,f,r,a,p,c,g);}}}catch{}}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let e=path.dirname(this.config.outputPath),r=[];for(let n of this.collectedTests)n.artifacts&&r.push({testId:n.testId,artifacts:n.artifacts,outputDir:e});return r}async finalizeStreamingReport(e,r,n,s){if(!this.streamingWriter)return;let{totalApiCalls:a,totalAssertions:o,totalNavigations:i,totalNetworkRequests:l,totalConsoleLogs:d,totalActionSteps:u}=this.summaryCounters;this.summaryCounters={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0,interrupted:0,totalApiCalls:a,totalAssertions:o,totalNavigations:i,totalNetworkRequests:l,totalConsoleLogs:d,totalActionSteps:u};let p=new Map,f=new Map;for(let b of this.testIndex){let C=`${b.filePath}::${b.titlePath.join(" > ")}`,v=p.get(C);(v===void 0||b.retryIndex>v)&&p.set(C,b.retryIndex);}let c=0;for(let b of this.testIndex){let C=`${b.filePath}::${b.titlePath.join(" > ")}`,v=p.get(C);if(b.isRetry=b.retryIndex<v,b.isRetry)continue;switch(c++,this.summaryCounters.total++,b.status){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}let k=f.get(b.filePath);switch(k||(k={filePath:b.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},f.set(b.filePath,k)),k.total++,b.status){case "passed":k.passed++;break;case "failed":k.failed++;break;case "flaky":k.flaky++;break;case "skipped":k.skipped++;break;case "timedout":k.timedOut++;break}}let g=Array.from(f.values());this.streamingWriter.writeIndex(this.testIndex),this.streamingWriter.writeCompactIndex(this.testIndex);let h={reporterTotal:this.summaryCounters.total,indexTotal:c,playwrightStatus:n.status,isValid:this.summaryCounters.total===c};h.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${h.reporterTotal}, index: ${h.indexTotal}
2593
2595
  `);let m={total:this.summaryCounters.total,passed:this.summaryCounters.passed,failed:this.summaryCounters.failed,flaky:this.summaryCounters.flaky,skipped:this.summaryCounters.skipped,timedout:this.summaryCounters.timedOut,totalApiCalls:this.summaryCounters.totalApiCalls,uniqueApiUrls:0,apiCallsByMethod:{},apiCallsByStatusRange:{"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},apiResponseTime:null,totalAssertions:this.summaryCounters.totalAssertions,passedAssertions:0,failedAssertions:0,totalNavigations:this.summaryCounters.totalNavigations,uniqueNavigationUrls:0,totalTimelineSteps:this.testIndex.length,totalActionSteps:this.summaryCounters.totalActionSteps,actionStepsByCategory:{}},w={testRunId:this.testRunId,startedAt:this.startedAt,completedAt:e,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:g,enrichedSummary:m,validation:h,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(w);let T={schemaVersion:"2.0",generatedAt:new Date().toISOString(),reportMode:"streaming",summaryFile:"summary.json",indexFile:"index.json",testsDir:"tests",artifactsDir:"artifacts",testCount:this.testIndex.length,totalSizeBytes:this.streamingWriter.computeTotalSize()};this.streamingWriter.writeManifest(T),await Ge(this.buildStreamingReport(w,m,e,r),this.config,s),Qe(m,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let y=this.streamingWriter.getReportDir();if(process.stderr.write(`[testrelic] Streaming report written to ${y}
2594
2596
  [testrelic] ${this.testIndex.length} test detail files on disk