@testrelic/playwright-analytics 2.7.0-next.60 → 2.7.0-next.61

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.
@@ -1,9 +1,9 @@
1
1
  import {randomUUID,createHash}from'crypto';import {writeFileSync,renameSync,mkdirSync,unlinkSync,existsSync,readFileSync,appendFileSync,readdirSync,statSync,rmSync,createReadStream}from'fs';import {join,dirname,relative,extname,resolve,parse,basename}from'path';import {tmpdir,platform}from'os';import {isValidConfig,createError,ErrorCode,ATTACHMENT_NAME,isTestRelicFilePayload,isTestRelicDataPayload,isValidEndpointUrl,isValidCloudConfig,isValidQueueEntry}from'@testrelic/core';import {spawn,exec,execSync}from'child_process';import {createServer}from'http';import {createInterface}from'readline';import {copyFile}from'fs/promises';import {gzipSync}from'zlib';import {Readable}from'stream';var Mr=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var Fr=".testrelic-report";function ye(e,t,r,a){let s=`${e}|${t.join("|")}|${r}|${a}`;return createHash("sha256").update(s).digest("hex").substring(0,12)}var G=class{constructor(t){this.writeErrors=[];this.totalBytesWritten=0;this.reportDir=join(t,Fr),this.testsDir=join(this.reportDir,"tests"),mkdirSync(this.testsDir,{recursive:true});}getReportDir(){return this.reportDir}getWriteErrors(){return this.writeErrors}writeTestDetail(t,r,a){try{let s=join(this.testsDir,t);mkdirSync(s,{recursive:!0});let n=join(s,"meta.json"),o=n+".tmp",i=JSON.stringify(r);return writeFileSync(o,i,"utf-8"),renameSync(o,n),this.totalBytesWritten+=Buffer.byteLength(i,"utf-8"),a?.networkRequestsFile&&this.moveFile(a.networkRequestsFile,join(s,"network.jsonl")),a?.consoleLogsFile&&this.moveFile(a.consoleLogsFile,join(s,"console.jsonl")),a?.apiCallsFile&&this.moveFile(a.apiCallsFile,join(s,"api-calls.jsonl")),!0}catch(s){let n=s instanceof Error?s.message:String(s);return this.writeErrors.push({testId:t,error:n,timestamp:new Date().toISOString()}),process.stderr.write(`[testrelic] Failed to write test detail for ${t}: ${n}
2
2
  `),false}}moveFile(t,r){try{renameSync(t,r);}catch{try{let{copyFileSync:a}=Mr("fs");a(t,r);try{unlinkSync(t);}catch{}}catch(a){process.stderr.write(`[testrelic] Failed to move file ${t} \u2192 ${r}: ${a instanceof Error?a.message:String(a)}
3
- `);}}}writeIndex(t){let r=join(this.reportDir,"index.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeCompactIndex(t){let r=join(this.reportDir,"index-compact.json"),a=r+".tmp",s=t.map(({titlePath:o,project:i,...l})=>l),n=JSON.stringify(s);writeFileSync(a,n,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeSummary(t){let r=join(this.reportDir,"summary.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeManifest(t){let r=join(this.reportDir,"manifest.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var gt=".testrelic",Hr="testrelic-config.json",Ur=".testrelic",zr=5,$r=new Set(["__proto__","constructor","prototype"]),pt=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${gt}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),jr={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function ht(e){let t=resolve(e);for(let r=0;r<=zr;r++){let a=join(t,gt,Hr);if(existsSync(a))try{if(statSync(a).isFile())return a}catch{}let s=join(t,Ur);if(existsSync(s))try{if(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
- `),s}catch{}let n=dirname(t);if(n===t)break;t=n;}return null}function mt(e){try{let t=readFileSync(e,"utf-8"),r=JSON.parse(t);return typeof r!="object"||r===null||Array.isArray(r)||!vt(r)?null:r}catch{return null}}function vt(e){for(let t of Object.keys(e)){if($r.has(t))return false;let r=e[t];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!vt(r))return false}return true}function yt(e){let t=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(e);if(t)return process.env[t[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(e);return r?process.env[r[1]]??null:e}function be(e){let t=Object.create(null);for(let r of Object.keys(e)){let a=e[r];typeof a=="string"&&a.startsWith("$")?t[r]=yt(a):typeof a=="object"&&a!==null&&!Array.isArray(a)?t[r]=be(a):t[r]=a;}return t}function ft(e){let t=/^(\d+)\s*([smhd])$/.exec(e.trim());if(!t)return null;let r=parseInt(t[1],10),a=t[2],s=jr[a];return !s||r<=0?null:r*s}function bt(e,t){let r=Object.create(null);if(Object.assign(r,pt),e){let l=e.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=e["testrelic-repo"]??e.project;d&&typeof d=="object"&&typeof d.name=="string"&&(r.projectName=d.name),e.project&&!e["testrelic-repo"]&&process.stderr.write(`[testrelic] Deprecation: "project" key in config is deprecated. Rename it to "testrelic-repo".
5
- `);let p=e.queue;if(p&&typeof p=="object"){if(typeof p.maxAge=="string"){let f=ft(p.maxAge);f!==null&&(r.queueMaxAge=f);}typeof p.directory=="string"&&(r.queueDirectory=p.directory);}}if(t){if(typeof t.apiKey=="string"&&t.apiKey.length>0){let l=t.apiKey.startsWith("$")?yt(t.apiKey):t.apiKey;l&&(r.apiKey=l);}if(typeof t.endpoint=="string"&&(r.endpoint=t.endpoint),typeof t.upload=="string"&&(r.uploadStrategy=t.upload),typeof t.timeout=="number"&&(r.timeout=t.timeout),typeof t.projectName=="string"&&(r.projectName=t.projectName),typeof t.queueMaxAge=="string"){let l=ft(t.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof t.queueDirectory=="string"&&(r.queueDirectory=t.queueDirectory),typeof t.uploadArtifacts=="boolean"&&(r.uploadArtifacts=t.uploadArtifacts),typeof t.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=t.artifactMaxSizeMb);}let a=process.env.TESTRELIC_API_KEY;a&&a.length>0&&(r.apiKey=a);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&isValidEndpointUrl(s)&&(r.endpoint=s);let n=process.env.TESTRELIC_UPLOAD_STRATEGY;n&&["batch","realtime","both"].includes(n)&&(r.uploadStrategy=n);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 isValidCloudConfig(i)?i:pt}var Kr=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Jr=["authorization","cookie","set-cookie","x-api-key"],Yr=["password","secret","token","apiKey","api_key"];function xt(e){let t=Object.create(null);return t.trackApiCalls=e?.trackApiCalls??true,t.captureRequestHeaders=e?.captureRequestHeaders??true,t.captureResponseHeaders=e?.captureResponseHeaders??true,t.captureRequestBody=e?.captureRequestBody??true,t.captureResponseBody=e?.captureResponseBody??true,t.captureAssertions=e?.captureAssertions??true,t.redactHeaders=e?.redactHeaders??[...Jr],t.redactBodyFields=e?.redactBodyFields??[...Yr],t.apiIncludeUrls=e?.apiIncludeUrls??[],t.apiExcludeUrls=e?.apiExcludeUrls??[],Object.freeze(t)}function wt(e){if(e!==void 0&&!isValidConfig(e))throw createError(ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let t=Object.create(null);t.outputPath=e?.outputPath??"./test-results/analytics-timeline.json",t.includeStackTrace=e?.includeStackTrace??false,t.includeCodeSnippets=e?.includeCodeSnippets??true,t.codeContextLines=e?.codeContextLines??3,t.includeNetworkStats=e?.includeNetworkStats??true,t.navigationTypes=e?.navigationTypes??null,t.redactPatterns=[...Kr,...e?.redactPatterns??[]],t.testRunId=e?.testRunId??null,t.metadata=e?.metadata??null;let r=t.outputPath;t.openReport=e?.openReport??true,t.htmlReportPath=e?.htmlReportPath??r.replace(/\.json$/,".html"),t.includeArtifacts=e?.includeArtifacts??true,t.trackApiCalls=e?.trackApiCalls??true,t.quiet=e?.quiet??false,t.includeActionSteps=e?.includeActionSteps??true,t.captureConsoleLogs=e?.captureConsoleLogs??true;let a=ht(process.cwd()),s=a?mt(a):null,n=s?be(s):null,o=bt(n,e?.cloud);return t.cloud=o.apiKey?o:null,t.reportMode=e?.reportMode??"streaming",t.streamingThreshold=e?.streamingThreshold??0,Object.freeze(t)}var xe="1.3.0";function kt(e,t,r){try{let s=readFileSync(e,"utf-8").split(`
6
- `);if(t<1||t>s.length)return null;let n=Math.max(1,t-r),o=Math.min(s.length,t+r),i=[];for(let l=n;l<=o;l++){let d=l===t?">":" ",p=String(l).padStart(String(o).length," ");i.push(`${d} ${p} | ${s[l-1]}`);}return i.join(`
3
+ `);}}}writeIndex(t){let r=join(this.reportDir,"index.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeCompactIndex(t){let r=join(this.reportDir,"index-compact.json"),a=r+".tmp",s=t.map(({titlePath:o,project:i,...l})=>l),n=JSON.stringify(s);writeFileSync(a,n,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeSummary(t){let r=join(this.reportDir,"summary.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeManifest(t){let r=join(this.reportDir,"manifest.json"),a=r+".tmp",s=JSON.stringify(t);writeFileSync(a,s,"utf-8"),renameSync(a,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var gt=".testrelic",Hr="testrelic-config.json",Ur=".testrelic",zr=5,$r=new Set(["__proto__","constructor","prototype"]),ut=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${gt}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),jr={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function ht(e){let t=resolve(e);for(let r=0;r<=zr;r++){let a=join(t,gt,Hr);if(existsSync(a))try{if(statSync(a).isFile())return a}catch{}let s=join(t,Ur);if(existsSync(s))try{if(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
+ `),s}catch{}let n=dirname(t);if(n===t)break;t=n;}return null}function mt(e){try{let t=readFileSync(e,"utf-8"),r=JSON.parse(t);return typeof r!="object"||r===null||Array.isArray(r)||!vt(r)?null:r}catch{return null}}function vt(e){for(let t of Object.keys(e)){if($r.has(t))return false;let r=e[t];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!vt(r))return false}return true}function yt(e){let t=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(e);if(t)return process.env[t[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(e);return r?process.env[r[1]]??null:e}function be(e){let t=Object.create(null);for(let r of Object.keys(e)){let a=e[r];typeof a=="string"&&a.startsWith("$")?t[r]=yt(a):typeof a=="object"&&a!==null&&!Array.isArray(a)?t[r]=be(a):t[r]=a;}return t}function ft(e){let t=/^(\d+)\s*([smhd])$/.exec(e.trim());if(!t)return null;let r=parseInt(t[1],10),a=t[2],s=jr[a];return !s||r<=0?null:r*s}function bt(e,t){let r=Object.create(null);if(Object.assign(r,ut),e){let l=e.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=e["testrelic-repo"]??e.project;d&&typeof d=="object"&&typeof d.name=="string"&&(r.projectName=d.name),e.project&&!e["testrelic-repo"]&&process.stderr.write(`[testrelic] Deprecation: "project" key in config is deprecated. Rename it to "testrelic-repo".
5
+ `);let u=e.queue;if(u&&typeof u=="object"){if(typeof u.maxAge=="string"){let f=ft(u.maxAge);f!==null&&(r.queueMaxAge=f);}typeof u.directory=="string"&&(r.queueDirectory=u.directory);}}if(t){if(typeof t.apiKey=="string"&&t.apiKey.length>0){let l=t.apiKey.startsWith("$")?yt(t.apiKey):t.apiKey;l&&(r.apiKey=l);}if(typeof t.endpoint=="string"&&(r.endpoint=t.endpoint),typeof t.upload=="string"&&(r.uploadStrategy=t.upload),typeof t.timeout=="number"&&(r.timeout=t.timeout),typeof t.projectName=="string"&&(r.projectName=t.projectName),typeof t.queueMaxAge=="string"){let l=ft(t.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof t.queueDirectory=="string"&&(r.queueDirectory=t.queueDirectory),typeof t.uploadArtifacts=="boolean"&&(r.uploadArtifacts=t.uploadArtifacts),typeof t.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=t.artifactMaxSizeMb);}let a=process.env.TESTRELIC_API_KEY;a&&a.length>0&&(r.apiKey=a);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&isValidEndpointUrl(s)&&(r.endpoint=s);let n=process.env.TESTRELIC_UPLOAD_STRATEGY;n&&["batch","realtime","both"].includes(n)&&(r.uploadStrategy=n);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 isValidCloudConfig(i)?i:ut}var Kr=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Jr=["authorization","cookie","set-cookie","x-api-key"],Yr=["password","secret","token","apiKey","api_key"];function xt(e){let t=Object.create(null);return t.trackApiCalls=e?.trackApiCalls??true,t.captureRequestHeaders=e?.captureRequestHeaders??true,t.captureResponseHeaders=e?.captureResponseHeaders??true,t.captureRequestBody=e?.captureRequestBody??true,t.captureResponseBody=e?.captureResponseBody??true,t.captureAssertions=e?.captureAssertions??true,t.redactHeaders=e?.redactHeaders??[...Jr],t.redactBodyFields=e?.redactBodyFields??[...Yr],t.apiIncludeUrls=e?.apiIncludeUrls??[],t.apiExcludeUrls=e?.apiExcludeUrls??[],Object.freeze(t)}function wt(e){if(e!==void 0&&!isValidConfig(e))throw createError(ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let t=Object.create(null);t.outputPath=e?.outputPath??"./test-results/analytics-timeline.json",t.includeStackTrace=e?.includeStackTrace??false,t.includeCodeSnippets=e?.includeCodeSnippets??true,t.codeContextLines=e?.codeContextLines??3,t.includeNetworkStats=e?.includeNetworkStats??true,t.navigationTypes=e?.navigationTypes??null,t.redactPatterns=[...Kr,...e?.redactPatterns??[]],t.testRunId=e?.testRunId??null,t.metadata=e?.metadata??null;let r=t.outputPath;t.openReport=e?.openReport??true,t.htmlReportPath=e?.htmlReportPath??r.replace(/\.json$/,".html"),t.includeArtifacts=e?.includeArtifacts??true,t.trackApiCalls=e?.trackApiCalls??true,t.quiet=e?.quiet??false,t.includeActionSteps=e?.includeActionSteps??true,t.captureConsoleLogs=e?.captureConsoleLogs??true;let a=ht(process.cwd()),s=a?mt(a):null,n=s?be(s):null,o=bt(n,e?.cloud);return t.cloud=o.apiKey?o:null,t.reportMode=e?.reportMode??"streaming",t.streamingThreshold=e?.streamingThreshold??0,Object.freeze(t)}var xe="1.3.0";function kt(e,t,r){try{let s=readFileSync(e,"utf-8").split(`
6
+ `);if(t<1||t>s.length)return null;let n=Math.max(1,t-r),o=Math.min(s.length,t+r),i=[];for(let l=n;l<=o;l++){let d=l===t?">":" ",u=String(l).padStart(String(o).length," ");i.push(`${d} ${u} | ${s[l-1]}`);}return i.join(`
7
7
  `)}catch{return null}}function Tt(e){return t=>{let r=t;for(let a of e)if(typeof a=="string"){let s=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(s,"g"),"[REDACTED]");}else {let s=a.flags.includes("g")?a.flags:a.flags+"g",n=new RegExp(a.source,s);r=r.replace(n,"[REDACTED]");}return r}}function Qr(e){return e.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:e.GITHUB_RUN_ID??null,commitSha:e.GITHUB_SHA??null,branch:e.GITHUB_REF_NAME??null,runUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY&&e.GITHUB_RUN_ID?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`:null}}function Xr(e){return e.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:e.CI_PIPELINE_ID??null,commitSha:e.CI_COMMIT_SHA??null,branch:e.CI_COMMIT_BRANCH??e.CI_COMMIT_REF_NAME??null,runUrl:e.CI_PIPELINE_URL??null}}function ea(e){if(!e.JENKINS_URL)return null;let t=e.GIT_BRANCH??null;return t?.startsWith("origin/")&&(t=t.slice(7)),{provider:"jenkins",buildId:e.BUILD_ID??null,commitSha:e.GIT_COMMIT??null,branch:t,runUrl:e.BUILD_URL??null}}function ta(e){return e.CIRCLECI!=="true"?null:{provider:"circleci",buildId:e.CIRCLE_BUILD_NUM??null,commitSha:e.CIRCLE_SHA1??null,branch:e.CIRCLE_BRANCH??null,runUrl:e.CIRCLE_BUILD_URL??null}}function ra(e){if(!e.BITBUCKET_PIPELINE_UUID)return null;let t=e.BITBUCKET_WORKSPACE&&e.BITBUCKET_REPO_SLUG&&e.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${e.BITBUCKET_WORKSPACE}/${e.BITBUCKET_REPO_SLUG}/pipelines/results/${e.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:e.BITBUCKET_BUILD_NUMBER??null,commitSha:e.BITBUCKET_COMMIT??null,branch:e.BITBUCKET_BRANCH??null,runUrl:t}}var aa=[Qr,Xr,ea,ta,ra];function P(e){let t=process.env;for(let r of aa){let a=r(t);if(a)return a}return null}var we=`
8
8
  /* Theme Variables */
9
9
  :root,[data-theme="dark"]{
@@ -2544,23 +2544,23 @@ ${o?`<script id="artifact-manifest-data" type="application/json">${o}</script>`:
2544
2544
  <script>${d}</script>
2545
2545
  </body>
2546
2546
  </html>`}function Ee(e){try{let t=process.platform,r;t==="darwin"?r=`open "${e}"`:t==="win32"?r=`start "" "${e}"`:r=`xdg-open "${e}"`,exec(r,a=>{a&&process.stderr.write(`[testrelic] Failed to open browser: ${a.message}
2547
- `);});}catch{}}join(tmpdir(),"testrelic-data");async function Ct(e,t,r,a){let s=(t-1)*r,n=[],o=0,i=createInterface({input:createReadStream(e,{encoding:"utf-8"}),crlfDelay:1/0});for await(let p of i)if(p.length!==0){if(o>=s&&n.length<r)try{n.push(JSON.parse(p));}catch{}if(o++,n.length>=r&&a!==void 0)break}let l=a??o,d=Math.max(1,Math.ceil(l/r));return {items:n,total:l,page:t,pageSize:r,totalPages:d}}var _t=/^[a-f0-9]{12}$/,Pe=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,It=500;function x(e,t,r){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(r));}function Lt(e){e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type");}function re(e){try{return existsSync(e)?JSON.parse(readFileSync(e,"utf-8")):null}catch{return null}}function ae(e){let t=0;try{let r=readdirSync(e,{withFileTypes:!0});for(let a of r){let s=join(e,a.name);a.isFile()?t+=statSync(s).size:a.isDirectory()&&(t+=ae(s));}}catch{}return t}function Mt(e,t,r,a){let s=re(join(r,"index.json"));x(t,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-a)/1e3)});}function Et(e,t,r){let a=re(join(r,"summary.json"));if(!a){x(t,404,{error:"Summary not found"});return}x(t,200,a);}function Pt(e,t,r){let a=re(join(r,"index.json"));if(!a){x(t,404,{error:"Test index not found"});return}let n=new URL(e.url??"/",`http://${e.headers.host}`).searchParams,o=Math.max(1,parseInt(n.get("page")??"1",10)||1),i=Math.min(It,Math.max(1,parseInt(n.get("pageSize")??"100",10)||100)),l=n.get("status")?.split(",").filter(Boolean)??null,d=n.get("file")??null,p=n.get("search")?.toLowerCase()??null,f=n.get("tag")?.split(",").filter(Boolean)??null,m=n.get("sort")??"file",c=n.get("order")==="desc"?-1:1,u=a;l&&l.length>0&&(u=u.filter(y=>l.includes(y.status))),d&&(u=u.filter(y=>y.filePath===d||y.filePath.startsWith(d+"/"))),p&&(u=u.filter(y=>y.title.toLowerCase().includes(p)||y.filePath.toLowerCase().includes(p))),f&&f.length>0&&(u=u.filter(y=>f.some(b=>y.tags.includes(b)))),u=[...u].sort((y,b)=>{let T=0;switch(m){case "duration":T=y.duration-b.duration;break;case "status":T=y.status.localeCompare(b.status);break;case "title":T=y.title.localeCompare(b.title);break;default:T=y.filePath.localeCompare(b.filePath);break}return T*c});let g=u.length,h=Math.max(1,Math.ceil(g/i)),w=(o-1)*i,S=u.slice(w,w+i);x(t,200,{tests:S,pagination:{page:o,pageSize:i,totalItems:g,totalPages:h},filters:{status:l,file:d,search:p,tag:f}});}function Ft(e,t,r,a){if(!_t.test(a)){x(t,400,{error:"Invalid test ID format"});return}let s=join(r,"tests",a,"meta.json"),n=join(r,"tests",`${a}.json`),o=existsSync(s)?s:existsSync(n)?n:null;if(!o){x(t,404,{error:`Test not found: ${a}`});return}try{let i=readFileSync(o,"utf-8");t.writeHead(200,{"Content-Type":"application/json"}),t.end(i);}catch(i){x(t,500,{error:i instanceof Error?i.message:String(i)});}}async function Dt(e,t,r,a,s){if(!_t.test(a)){x(t,400,{error:"Invalid test ID format"});return}let o=join(r,"tests",a,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!existsSync(o)){x(t,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let l=new URL(e.url??"/",`http://${e.headers.host}`).searchParams,d=Math.max(1,parseInt(l.get("page")??"1",10)||1),p=Math.min(It,Math.max(1,parseInt(l.get("pageSize")??"50",10)||50)),f,m=join(r,"tests",a,"meta.json");if(existsSync(m))try{let u=JSON.parse(readFileSync(m,"utf-8"));switch(s){case "network":f=u.networkRequestsCount;break;case "console":f=u.consoleLogsCount;break;case "api-calls":f=u.apiCallsCount;break}}catch{}let c=await Ct(o,d,p,f);x(t,200,c);}catch(i){x(t,500,{error:i instanceof Error?i.message:String(i)});}}function Nt(e,t,r){let a=re(join(r,"index.json"));if(!a){x(t,404,{error:"Test index not found"});return}let s=new Map;for(let o of a){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 n=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));x(t,200,{files:n});}function Bt(e,t,r){if(!existsSync(r)){x(t,200,{runs:[],totalSizeBytes:0});return}try{let a=[],s=0,n=readdirSync(r,{withFileTypes:!0});for(let o of n){if(!o.isDirectory()||!Pe.test(o.name))continue;let i=join(r,o.name),l=ae(i),d=readdirSync(i,{withFileTypes:!0}).filter(p=>p.isDirectory());a.push({folderName:o.name,totalSizeBytes:l,testCount:d.length}),s+=l;}a.sort((o,i)=>i.folderName.localeCompare(o.folderName)),x(t,200,{runs:a,totalSizeBytes:s});}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}function Ot(e,t,r){try{let a=0,s=0;if(existsSync(r)){let n=readdirSync(r,{withFileTypes:!0});for(let o of n){if(!o.isDirectory()||!Pe.test(o.name))continue;let i=join(r,o.name),l=ae(i);rmSync(i,{recursive:!0,force:!0}),s+=l,a++;}}x(t,200,{deletedCount:a,freedBytes:s});}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}function qt(e,t,r,a){if(!Pe.test(a)){x(t,400,{error:"Invalid folder name"});return}let s=join(r,a);try{if(!statSync(s).isDirectory()){x(t,404,{error:"Not found"});return}}catch{x(t,404,{error:"Not found"});return}try{let n=ae(s);rmSync(s,{recursive:!0,force:!0}),x(t,200,{deleted:a,freedBytes:n});}catch(n){x(t,500,{error:n instanceof Error?n.message:String(n)});}}function Ht(e,t,r){x(t,200,{status:"shutting_down"}),r.close();}function Fe(e,t,r){if(!existsSync(r)){x(t,404,{error:"File not found"});return}try{let a=readFileSync(r),s=extname(r).toLowerCase(),n=ua[s]??"application/octet-stream";t.writeHead(200,{"Content-Type":n}),t.end(a);}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}var ua={".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 ha=9323,ma=10,va=1800*1e3;function W(e,t){return new Promise((r,a)=>{let s=t?.port??ha,n=Date.now(),o,i=0,l=existsSync(join(e,"artifacts"))?join(e,"artifacts"):existsSync(join(e,"..","artifacts"))?join(e,"..","artifacts"):join(e,"artifacts");function d(){clearTimeout(o),o=setTimeout(()=>{f.close();},va);}let p=t?.htmlPath??null;if(!p){let c=dirname(e);try{let u=readdirSync(c).find(g=>g.endsWith(".html"));u&&(p=join(c,u));}catch{}}let f=createServer((c,u)=>{if(d(),Lt(u),c.method==="OPTIONS"){u.writeHead(204),u.end();return}let g;try{g=new URL(c.url??"/",`http://${c.headers.host??"localhost"}`).pathname;}catch{x(u,400,{error:"Invalid URL"});return}if(c.method==="GET"&&(g==="/"||g==="/index.html")){if(p&&existsSync(p)){Fe(c,u,p);return}x(u,404,{error:"HTML report not found"});return}if(c.method==="GET"&&g==="/api/health"){Mt(c,u,e,n);return}if(c.method==="GET"&&g==="/api/summary"){Et(c,u,e);return}if(c.method==="GET"&&g==="/api/tests"){Pt(c,u,e);return}if(c.method==="GET"&&g==="/api/files"){Nt(c,u,e);return}let h=g.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(c.method==="GET"&&h){Dt(c,u,e,h[1],h[2]);return}let w=g.match(/^\/api\/tests\/([a-f0-9]+)$/);if(c.method==="GET"&&w){Ft(c,u,e,w[1]);return}if(c.method==="GET"&&g==="/api/artifacts"){Bt(c,u,l);return}if(c.method==="DELETE"&&g==="/api/artifacts"){Ot(c,u,l);return}let S=g.match(/^\/api\/artifacts\/(.+)$/);if(c.method==="DELETE"&&S){qt(c,u,l,decodeURIComponent(S[1]));return}if(c.method==="GET"&&g.startsWith("/artifacts/")){let y=decodeURIComponent(g.slice(11));if(y.includes("..")||y.includes("\0")){x(u,400,{error:"Invalid path"});return}Fe(c,u,join(l,y));return}if(c.method==="POST"&&g==="/api/shutdown"){Ht(c,u,f);return}x(u,404,{error:"Not found"});});function m(c){let u=g=>{g.code==="EADDRINUSE"&&i<ma?(i++,m(c+1)):a(g);};f.once("error",u),f.listen(c,"127.0.0.1",()=>{f.removeListener("error",u);let g=f.address();if(!g||typeof g=="string"){a(new Error("Failed to get server address"));return}d(),r({port:g.port,dispose:()=>new Promise(h=>{clearTimeout(o),f.close(()=>h());})});});}m(s);})}async function Ut(e){let t=await W(e);return {port:t.port,dispose:t.dispose}}function xa(e,t,r){let a=JSON.stringify(e),s=r?JSON.stringify(r):null;return St(a,t,s)}async function Ne(e,t,r){try{let a=null,s=null,n=t.reportMode==="streaming"||t.reportMode==="auto"&&e.timeline.length===0&&e.summary.total>=t.streamingThreshold,o,i=t.htmlReportPath,l=dirname(i);mkdirSync(l,{recursive:!0});let d="",p="[]",f=null;if(n){d=JSON.stringify(e.summary);let c=dirname(t.outputPath),u=join(c,".testrelic-report");try{let g=join(u,"index-compact.json"),h=join(u,"index.json");existsSync(g)?p=readFileSync(g,"utf-8"):existsSync(h)&&(p=readFileSync(h,"utf-8"));}catch{}f=r?JSON.stringify(r):null,o=Me(d,p,null,f);}else o=xa(e,null,r);let m=i+".tmp";if(writeFileSync(m,o,"utf-8"),renameSync(m,i),n){if(e.ci===null){let c=dirname(t.outputPath),u=join(c,".testrelic-report"),g=resolve(i);try{if(await ka(),a=await Ta(u),!a){s=await W(u,{htmlPath:g}),a=s.port;let h=setInterval(()=>{},6e4),w=()=>{clearInterval(h),s?.dispose();};process.on("SIGINT",w),process.on("SIGTERM",w),setTimeout(w,1800*1e3).unref();}if(a){process.stderr.write(`
2547
+ `);});}catch{}}join(tmpdir(),"testrelic-data");async function Ct(e,t,r,a){let s=(t-1)*r,n=[],o=0,i=createInterface({input:createReadStream(e,{encoding:"utf-8"}),crlfDelay:1/0});for await(let u of i)if(u.length!==0){if(o>=s&&n.length<r)try{n.push(JSON.parse(u));}catch{}if(o++,n.length>=r&&a!==void 0)break}let l=a??o,d=Math.max(1,Math.ceil(l/r));return {items:n,total:l,page:t,pageSize:r,totalPages:d}}var _t=/^[a-f0-9]{12}$/,Pe=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,It=500;function x(e,t,r){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(r));}function Lt(e){e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type");}function re(e){try{return existsSync(e)?JSON.parse(readFileSync(e,"utf-8")):null}catch{return null}}function ae(e){let t=0;try{let r=readdirSync(e,{withFileTypes:!0});for(let a of r){let s=join(e,a.name);a.isFile()?t+=statSync(s).size:a.isDirectory()&&(t+=ae(s));}}catch{}return t}function Mt(e,t,r,a){let s=re(join(r,"index.json"));x(t,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-a)/1e3)});}function Et(e,t,r){let a=re(join(r,"summary.json"));if(!a){x(t,404,{error:"Summary not found"});return}x(t,200,a);}function Pt(e,t,r){let a=re(join(r,"index.json"));if(!a){x(t,404,{error:"Test index not found"});return}let n=new URL(e.url??"/",`http://${e.headers.host}`).searchParams,o=Math.max(1,parseInt(n.get("page")??"1",10)||1),i=Math.min(It,Math.max(1,parseInt(n.get("pageSize")??"100",10)||100)),l=n.get("status")?.split(",").filter(Boolean)??null,d=n.get("file")??null,u=n.get("search")?.toLowerCase()??null,f=n.get("tag")?.split(",").filter(Boolean)??null,m=n.get("sort")??"file",c=n.get("order")==="desc"?-1:1,p=a;l&&l.length>0&&(p=p.filter(y=>l.includes(y.status))),d&&(p=p.filter(y=>y.filePath===d||y.filePath.startsWith(d+"/"))),u&&(p=p.filter(y=>y.title.toLowerCase().includes(u)||y.filePath.toLowerCase().includes(u))),f&&f.length>0&&(p=p.filter(y=>f.some(b=>y.tags.includes(b)))),p=[...p].sort((y,b)=>{let T=0;switch(m){case "duration":T=y.duration-b.duration;break;case "status":T=y.status.localeCompare(b.status);break;case "title":T=y.title.localeCompare(b.title);break;default:T=y.filePath.localeCompare(b.filePath);break}return T*c});let g=p.length,h=Math.max(1,Math.ceil(g/i)),w=(o-1)*i,S=p.slice(w,w+i);x(t,200,{tests:S,pagination:{page:o,pageSize:i,totalItems:g,totalPages:h},filters:{status:l,file:d,search:u,tag:f}});}function Ft(e,t,r,a){if(!_t.test(a)){x(t,400,{error:"Invalid test ID format"});return}let s=join(r,"tests",a,"meta.json"),n=join(r,"tests",`${a}.json`),o=existsSync(s)?s:existsSync(n)?n:null;if(!o){x(t,404,{error:`Test not found: ${a}`});return}try{let i=readFileSync(o,"utf-8");t.writeHead(200,{"Content-Type":"application/json"}),t.end(i);}catch(i){x(t,500,{error:i instanceof Error?i.message:String(i)});}}async function Dt(e,t,r,a,s){if(!_t.test(a)){x(t,400,{error:"Invalid test ID format"});return}let o=join(r,"tests",a,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!existsSync(o)){x(t,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let l=new URL(e.url??"/",`http://${e.headers.host}`).searchParams,d=Math.max(1,parseInt(l.get("page")??"1",10)||1),u=Math.min(It,Math.max(1,parseInt(l.get("pageSize")??"50",10)||50)),f,m=join(r,"tests",a,"meta.json");if(existsSync(m))try{let p=JSON.parse(readFileSync(m,"utf-8"));switch(s){case "network":f=p.networkRequestsCount;break;case "console":f=p.consoleLogsCount;break;case "api-calls":f=p.apiCallsCount;break}}catch{}let c=await Ct(o,d,u,f);x(t,200,c);}catch(i){x(t,500,{error:i instanceof Error?i.message:String(i)});}}function Nt(e,t,r){let a=re(join(r,"index.json"));if(!a){x(t,404,{error:"Test index not found"});return}let s=new Map;for(let o of a){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 n=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));x(t,200,{files:n});}function Bt(e,t,r){if(!existsSync(r)){x(t,200,{runs:[],totalSizeBytes:0});return}try{let a=[],s=0,n=readdirSync(r,{withFileTypes:!0});for(let o of n){if(!o.isDirectory()||!Pe.test(o.name))continue;let i=join(r,o.name),l=ae(i),d=readdirSync(i,{withFileTypes:!0}).filter(u=>u.isDirectory());a.push({folderName:o.name,totalSizeBytes:l,testCount:d.length}),s+=l;}a.sort((o,i)=>i.folderName.localeCompare(o.folderName)),x(t,200,{runs:a,totalSizeBytes:s});}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}function Ot(e,t,r){try{let a=0,s=0;if(existsSync(r)){let n=readdirSync(r,{withFileTypes:!0});for(let o of n){if(!o.isDirectory()||!Pe.test(o.name))continue;let i=join(r,o.name),l=ae(i);rmSync(i,{recursive:!0,force:!0}),s+=l,a++;}}x(t,200,{deletedCount:a,freedBytes:s});}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}function qt(e,t,r,a){if(!Pe.test(a)){x(t,400,{error:"Invalid folder name"});return}let s=join(r,a);try{if(!statSync(s).isDirectory()){x(t,404,{error:"Not found"});return}}catch{x(t,404,{error:"Not found"});return}try{let n=ae(s);rmSync(s,{recursive:!0,force:!0}),x(t,200,{deleted:a,freedBytes:n});}catch(n){x(t,500,{error:n instanceof Error?n.message:String(n)});}}function Ht(e,t,r){x(t,200,{status:"shutting_down"}),r.close();}function Fe(e,t,r){if(!existsSync(r)){x(t,404,{error:"File not found"});return}try{let a=readFileSync(r),s=extname(r).toLowerCase(),n=pa[s]??"application/octet-stream";t.writeHead(200,{"Content-Type":n}),t.end(a);}catch(a){x(t,500,{error:a instanceof Error?a.message:String(a)});}}var pa={".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 ha=9323,ma=10,va=1800*1e3;function W(e,t){return new Promise((r,a)=>{let s=t?.port??ha,n=Date.now(),o,i=0,l=existsSync(join(e,"artifacts"))?join(e,"artifacts"):existsSync(join(e,"..","artifacts"))?join(e,"..","artifacts"):join(e,"artifacts");function d(){clearTimeout(o),o=setTimeout(()=>{f.close();},va);}let u=t?.htmlPath??null;if(!u){let c=dirname(e);try{let p=readdirSync(c).find(g=>g.endsWith(".html"));p&&(u=join(c,p));}catch{}}let f=createServer((c,p)=>{if(d(),Lt(p),c.method==="OPTIONS"){p.writeHead(204),p.end();return}let g;try{g=new URL(c.url??"/",`http://${c.headers.host??"localhost"}`).pathname;}catch{x(p,400,{error:"Invalid URL"});return}if(c.method==="GET"&&(g==="/"||g==="/index.html")){if(u&&existsSync(u)){Fe(c,p,u);return}x(p,404,{error:"HTML report not found"});return}if(c.method==="GET"&&g==="/api/health"){Mt(c,p,e,n);return}if(c.method==="GET"&&g==="/api/summary"){Et(c,p,e);return}if(c.method==="GET"&&g==="/api/tests"){Pt(c,p,e);return}if(c.method==="GET"&&g==="/api/files"){Nt(c,p,e);return}let h=g.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(c.method==="GET"&&h){Dt(c,p,e,h[1],h[2]);return}let w=g.match(/^\/api\/tests\/([a-f0-9]+)$/);if(c.method==="GET"&&w){Ft(c,p,e,w[1]);return}if(c.method==="GET"&&g==="/api/artifacts"){Bt(c,p,l);return}if(c.method==="DELETE"&&g==="/api/artifacts"){Ot(c,p,l);return}let S=g.match(/^\/api\/artifacts\/(.+)$/);if(c.method==="DELETE"&&S){qt(c,p,l,decodeURIComponent(S[1]));return}if(c.method==="GET"&&g.startsWith("/artifacts/")){let y=decodeURIComponent(g.slice(11));if(y.includes("..")||y.includes("\0")){x(p,400,{error:"Invalid path"});return}Fe(c,p,join(l,y));return}if(c.method==="POST"&&g==="/api/shutdown"){Ht(c,p,f);return}x(p,404,{error:"Not found"});});function m(c){let p=g=>{g.code==="EADDRINUSE"&&i<ma?(i++,m(c+1)):a(g);};f.once("error",p),f.listen(c,"127.0.0.1",()=>{f.removeListener("error",p);let g=f.address();if(!g||typeof g=="string"){a(new Error("Failed to get server address"));return}d(),r({port:g.port,dispose:()=>new Promise(h=>{clearTimeout(o),f.close(()=>h());})});});}m(s);})}async function Ut(e){let t=await W(e);return {port:t.port,dispose:t.dispose}}function xa(e,t,r){let a=JSON.stringify(e),s=r?JSON.stringify(r):null;return St(a,t,s)}async function Ne(e,t,r){try{let a=null,s=null,n=t.reportMode==="streaming"||t.reportMode==="auto"&&e.timeline.length===0&&e.summary.total>=t.streamingThreshold,o,i=t.htmlReportPath,l=dirname(i);mkdirSync(l,{recursive:!0});let d="",u="[]",f=null;if(n){d=JSON.stringify(e.summary);let c=dirname(t.outputPath),p=join(c,".testrelic-report");try{let g=join(p,"index-compact.json"),h=join(p,"index.json");existsSync(g)?u=readFileSync(g,"utf-8"):existsSync(h)&&(u=readFileSync(h,"utf-8"));}catch{}f=r?JSON.stringify(r):null,o=Me(d,u,null,f);}else o=xa(e,null,r);let m=i+".tmp";if(writeFileSync(m,o,"utf-8"),renameSync(m,i),n){if(e.ci===null){let c=dirname(t.outputPath),p=join(c,".testrelic-report"),g=resolve(i);try{if(await ka(),a=await Ta(p),!a){s=await W(p,{htmlPath:g}),a=s.port;let h=setInterval(()=>{},6e4),w=()=>{clearInterval(h),s?.dispose();};process.on("SIGINT",w),process.on("SIGTERM",w),setTimeout(w,1800*1e3).unref();}if(a){process.stderr.write(`
2548
2548
  Report server: http://127.0.0.1:${a}
2549
- `);try{let h=Me(d,p,a,f),w=i+".tmp";writeFileSync(w,h,"utf-8"),renameSync(w,i);}catch{}}}catch{}}}else if(t.openReport&&e.ci===null&&t.includeArtifacts){let c=dirname(t.outputPath),u=join(c,"artifacts");if(existsSync(u))try{let g=await Ut(u);a=g.port,process.on("exit",()=>{g.dispose();});}catch{}}if(t.openReport&&e.ci===null)if(n&&a)Ee(`http://127.0.0.1:${a}`);else {let c=resolve(i);Ee(c);}}catch(a){process.stderr.write(`[testrelic] Failed to write HTML report: ${a instanceof Error?a.message:String(a)}
2550
- `);}}var ie=9323,Gt=10;async function wa(){for(let e=ie;e<ie+Gt;e++)try{let t=new AbortController,r=setTimeout(()=>t.abort(),500),a=await fetch(`http://127.0.0.1:${e}/api/health`,{signal:t.signal});if(clearTimeout(r),a.ok)return e}catch{}return null}async function ka(){for(let e=ie;e<ie+Gt;e++)try{let t=new AbortController,r=setTimeout(()=>t.abort(),1e3);await fetch(`http://127.0.0.1:${e}/api/shutdown`,{method:"POST",signal:t.signal}),clearTimeout(r);}catch{}await new Promise(e=>setTimeout(e,300));}async function Ta(e){let r=[join(__dirname,"cli.cjs"),join(__dirname,"cli.js"),join(__dirname,"..","dist","cli.cjs"),join(__dirname,"..","dist","cli.js")].find(a=>existsSync(a));if(!r){let a=await W(e);return process.on("exit",()=>{a?.dispose();}),a.port}return new Promise(a=>{let s=spawn(process.execPath,[r,"serve",e],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),n="",o=false,i=setTimeout(()=>{o||(o=true,s.stderr?.removeAllListeners(),wa().then(a));},5e3);s.stderr?.on("data",l=>{n+=l.toString();let d=n.match(/127\.0\.0\.1:(\d+)/);d&&!o&&(o=true,clearTimeout(i),s.stderr?.removeAllListeners(),s.unref(),a(Number(d[1])));}),s.on("error",()=>{o||(o=true,clearTimeout(i),a(null));}),s.on("exit",()=>{o||(o=true,clearTimeout(i),a(null));}),s.unref();})}var Ra=20,Be=0,Oe=[];async function Kt(e,t){Be>=Ra&&await new Promise(r=>Oe.push(r)),Be++;try{return await copyFile(e,t),!0}catch{return false}finally{Be--,Oe.length>0&&Oe.shift()();}}var J=[];async function Jt(){J.length!==0&&(await Promise.allSettled(J),J.length=0);}function Yt(e){let t=new Date,r=n=>String(n).padStart(2,"0"),a=`${t.getFullYear()}-${r(t.getMonth()+1)}-${r(t.getDate())}T${r(t.getHours())}-${r(t.getMinutes())}-${r(t.getSeconds())}`;if(!existsSync(join(e,a)))return a;let s=1;for(;existsSync(join(e,`${a}-${s}`));)s++;return `${a}-${s}`}function Aa(e){let t=e.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t.length>100&&(t=t.substring(0,100).replace(/-+$/,"")),t||"unnamed-test"}function Zt(e,t,r,a,s){let n=e.find(m=>m.name==="screenshot"&&m.path),o=e.find(m=>m.name==="video"&&m.path);if(!n&&!o)return null;let i=Aa(t);r>0&&(i+=`--retry-${r}`);let l=s?["artifacts",s,i]:["artifacts",i],d=join(a,...l),p=l,f={};try{mkdirSync(d,{recursive:!0});}catch{return null}if(n?.path&&existsSync(n.path)){let c=`screenshot${extname(n.path)||".png"}`,u=join(d,c);J.push(Kt(n.path,u).then(()=>{})),f.screenshot=`${p.join("/")}/${c}`;}if(o?.path&&existsSync(o.path)){let c=`video${extname(o.path)||".webm"}`,u=join(d,c);J.push(Kt(o.path,u).then(()=>{})),f.video=`${p.join("/")}/${c}`;}return !f.screenshot&&!f.video?null:f}var La=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Ma="1.0";function Ea(e){let t=extname(e).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(t)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(t)?"video":"other"}function Qt(e,t,r){let a=[];try{let s=readdirSync(e,{withFileTypes:!0});for(let n of s){if(!n.isFile())continue;let o=join(e,n.name),i=statSync(o);a.push({name:n.name,type:Ea(n.name),relativePath:`artifacts/${t}/${r}/${n.name}`,sizeBytes:i.size});}}catch{}return {testName:r,files:a}}function Pa(e,t){let r=join(e,t),a=[],s=0;try{let o=readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let l=Qt(join(r,i.name),t,i.name);a.push(l);for(let d of l.files)s+=d.sizeBytes;}}catch{}let n=t.replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/,"$1T$2:$3:$4").replace(/-\d+$/,"");return a.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:t,timestamp:n,totalSizeBytes:s,testCount:a.length,tests:a,isCurrentRun:false}}function Xt(e,t){let r=join(e,"artifacts"),a=[],s=[],n=0;try{let i=readdirSync(r,{withFileTypes:!0});for(let l of i)if(l.isDirectory())if(La.test(l.name)){let d=Pa(r,l.name);a.push({...d,isCurrentRun:l.name===t});}else {let d=Qt(join(r,l.name),l.name,l.name);s.push(d);for(let p of d.files)n+=p.sizeBytes;}}catch{}a.sort((i,l)=>l.timestamp.localeCompare(i.timestamp)),s.length>0&&(s.sort((i,l)=>i.testName.localeCompare(l.testName)),a.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:n,testCount:s.length,tests:s,isCurrentRun:false}));let o=a.reduce((i,l)=>i+l.totalSizeBytes,0);return {schemaVersion:Ma,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:a,serverPort:null}}function Oa(e){let t=e,{root:r}=parse(t);for(;t!==r;){if(existsSync(join(t,".git")))return t;t=join(t,"..");}return null}function tr(e){try{let t=Oa(e);if(!t)return;let r=join(t,".gitignore"),a=relative(t,e).replace(/\\/g,"/"),s=a.endsWith("/")?a:`${a}/`;if(existsSync(r)&&readFileSync(r,"utf-8").split(`
2549
+ `);try{let h=Me(d,u,a,f),w=i+".tmp";writeFileSync(w,h,"utf-8"),renameSync(w,i);}catch{}}}catch{}}}else if(t.openReport&&e.ci===null&&t.includeArtifacts){let c=dirname(t.outputPath),p=join(c,"artifacts");if(existsSync(p))try{let g=await Ut(p);a=g.port,process.on("exit",()=>{g.dispose();});}catch{}}if(t.openReport&&e.ci===null)if(n&&a)Ee(`http://127.0.0.1:${a}`);else {let c=resolve(i);Ee(c);}}catch(a){process.stderr.write(`[testrelic] Failed to write HTML report: ${a instanceof Error?a.message:String(a)}
2550
+ `);}}var ie=9323,Gt=10;async function wa(){for(let e=ie;e<ie+Gt;e++)try{let t=new AbortController,r=setTimeout(()=>t.abort(),500),a=await fetch(`http://127.0.0.1:${e}/api/health`,{signal:t.signal});if(clearTimeout(r),a.ok)return e}catch{}return null}async function ka(){for(let e=ie;e<ie+Gt;e++)try{let t=new AbortController,r=setTimeout(()=>t.abort(),1e3);await fetch(`http://127.0.0.1:${e}/api/shutdown`,{method:"POST",signal:t.signal}),clearTimeout(r);}catch{}await new Promise(e=>setTimeout(e,300));}async function Ta(e){let r=[join(__dirname,"cli.cjs"),join(__dirname,"cli.js"),join(__dirname,"..","dist","cli.cjs"),join(__dirname,"..","dist","cli.js")].find(a=>existsSync(a));if(!r){let a=await W(e);return process.on("exit",()=>{a?.dispose();}),a.port}return new Promise(a=>{let s=spawn(process.execPath,[r,"serve",e],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),n="",o=false,i=setTimeout(()=>{o||(o=true,s.stderr?.removeAllListeners(),wa().then(a));},5e3);s.stderr?.on("data",l=>{n+=l.toString();let d=n.match(/127\.0\.0\.1:(\d+)/);d&&!o&&(o=true,clearTimeout(i),s.stderr?.removeAllListeners(),s.unref(),a(Number(d[1])));}),s.on("error",()=>{o||(o=true,clearTimeout(i),a(null));}),s.on("exit",()=>{o||(o=true,clearTimeout(i),a(null));}),s.unref();})}var Ra=20,Be=0,Oe=[];async function Kt(e,t){Be>=Ra&&await new Promise(r=>Oe.push(r)),Be++;try{return await copyFile(e,t),!0}catch{return false}finally{Be--,Oe.length>0&&Oe.shift()();}}var J=[];async function Jt(){J.length!==0&&(await Promise.allSettled(J),J.length=0);}function Yt(e){let t=new Date,r=n=>String(n).padStart(2,"0"),a=`${t.getFullYear()}-${r(t.getMonth()+1)}-${r(t.getDate())}T${r(t.getHours())}-${r(t.getMinutes())}-${r(t.getSeconds())}`;if(!existsSync(join(e,a)))return a;let s=1;for(;existsSync(join(e,`${a}-${s}`));)s++;return `${a}-${s}`}function Aa(e){let t=e.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t.length>100&&(t=t.substring(0,100).replace(/-+$/,"")),t||"unnamed-test"}function Zt(e,t,r,a,s){let n=e.find(m=>m.name==="screenshot"&&m.path),o=e.find(m=>m.name==="video"&&m.path);if(!n&&!o)return null;let i=Aa(t);r>0&&(i+=`--retry-${r}`);let l=s?["artifacts",s,i]:["artifacts",i],d=join(a,...l),u=l,f={};try{mkdirSync(d,{recursive:!0});}catch{return null}if(n?.path&&existsSync(n.path)){let c=`screenshot${extname(n.path)||".png"}`,p=join(d,c);J.push(Kt(n.path,p).then(()=>{})),f.screenshot=`${u.join("/")}/${c}`;}if(o?.path&&existsSync(o.path)){let c=`video${extname(o.path)||".webm"}`,p=join(d,c);J.push(Kt(o.path,p).then(()=>{})),f.video=`${u.join("/")}/${c}`;}return !f.screenshot&&!f.video?null:f}var La=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Ma="1.0";function Ea(e){let t=extname(e).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(t)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(t)?"video":"other"}function Qt(e,t,r){let a=[];try{let s=readdirSync(e,{withFileTypes:!0});for(let n of s){if(!n.isFile())continue;let o=join(e,n.name),i=statSync(o);a.push({name:n.name,type:Ea(n.name),relativePath:`artifacts/${t}/${r}/${n.name}`,sizeBytes:i.size});}}catch{}return {testName:r,files:a}}function Pa(e,t){let r=join(e,t),a=[],s=0;try{let o=readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let l=Qt(join(r,i.name),t,i.name);a.push(l);for(let d of l.files)s+=d.sizeBytes;}}catch{}let n=t.replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/,"$1T$2:$3:$4").replace(/-\d+$/,"");return a.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:t,timestamp:n,totalSizeBytes:s,testCount:a.length,tests:a,isCurrentRun:false}}function Xt(e,t){let r=join(e,"artifacts"),a=[],s=[],n=0;try{let i=readdirSync(r,{withFileTypes:!0});for(let l of i)if(l.isDirectory())if(La.test(l.name)){let d=Pa(r,l.name);a.push({...d,isCurrentRun:l.name===t});}else {let d=Qt(join(r,l.name),l.name,l.name);s.push(d);for(let u of d.files)n+=u.sizeBytes;}}catch{}a.sort((i,l)=>l.timestamp.localeCompare(i.timestamp)),s.length>0&&(s.sort((i,l)=>i.testName.localeCompare(l.testName)),a.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:n,testCount:s.length,tests:s,isCurrentRun:false}));let o=a.reduce((i,l)=>i+l.totalSizeBytes,0);return {schemaVersion:Ma,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:a,serverPort:null}}function Oa(e){let t=e,{root:r}=parse(t);for(;t!==r;){if(existsSync(join(t,".git")))return t;t=join(t,"..");}return null}function tr(e){try{let t=Oa(e);if(!t)return;let r=join(t,".gitignore"),a=relative(t,e).replace(/\\/g,"/"),s=a.endsWith("/")?a:`${a}/`;if(existsSync(r)&&readFileSync(r,"utf-8").split(`
2551
2551
  `).map(l=>l.trim()).some(l=>l===s||l===a))return;let n=`
2552
2552
  # TestRelic test artifacts
2553
2553
  ${s}
2554
- `;appendFileSync(r,n,"utf-8");}catch{}}function sr(e,t){let r=[];for(let a of e){let s=qa(a),n=Ha(a),o=Ua(a,s,n,t),i=za(a,s,n);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:a.startedAt,durationOnUrl:a.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:a.specFile,test:s,tests:[n],_testTitle:a.title});continue}r.push(...o,...i);}return r.sort($a),ja(r,e),r.map((a,s)=>a.type==="navigation"?{...{index:s,type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:a.durationOnUrl??0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:a.specFile,test:a.test},tests:a.tests}:{...{index:s,type:"api_call",callId:a.callId,method:a.method,url:a.url,timestamp:a.timestamp,responseTime:a.responseTime??null,request:a.request,response:a.response??null,...a.error?{error:a.error}:{},assertions:a.assertions??[],specFile:a.specFile,test:a.test},tests:a.tests})}function qa(e){return {title:e.title,fullTitle:e.titlePath,status:e.status,duration:e.duration,retries:e.retryCount,retry:e.retry,tags:e.tags,failure:e.failure}}function Ha(e){return {title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:e.retryCount,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,retryStatus:e.retryStatus,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,networkRequests:e.networkRequests,apiCalls:e.apiCalls,apiAssertions:e.apiAssertions,actions:e.actions,consoleLogs:e.consoleLogs}}function Ua(e,t,r,a){let s=[];for(let n of e.navigations)a.navigationTypes!==null&&!a.navigationTypes.includes(n.navigationType)||s.push({type:"navigation",url:n.url,timestamp:n.timestamp,durationOnUrl:0,navigationType:n.navigationType,domContentLoadedAt:n.domContentLoadedAt??null,networkIdleAt:n.networkIdleAt??null,networkStats:n.networkStats??null,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title});return s}function za(e,t,r){if(!e.apiCalls||e.apiCalls.length===0)return [];let a=e.apiAssertions??[];return e.apiCalls.map(s=>{let n=a.filter(i=>i.callId===s.id).map(i=>({type:i.type,expected:i.expected,actual:i.actual,status:i.status,location:i.location,...i.expression!==void 0?{expression:i.expression}:{}})),o=null;return s.responseStatusCode!==null&&s.responseStatusText!==null&&(o={statusCode:s.responseStatusCode,statusText:s.responseStatusText,headers:s.responseHeaders,body:ar(s.responseBody)}),{type:"api_call",callId:s.id,method:s.method,url:s.url,timestamp:s.timestamp,responseTime:s.error?null:s.responseTimeMs,request:{headers:s.requestHeaders,body:ar(s.requestBody)},response:o,...s.error?{error:s.error}:{},assertions:n,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title}})}function $a(e,t){let r=new Date(e.timestamp).getTime(),a=new Date(t.timestamp).getTime();if(r!==a)return r-a;let s={navigation:0,api_call:1},n=s[e.type],o=s[t.type];return n!==o?n-o:e.type==="api_call"&&t.type==="api_call"&&e.callId&&t.callId?rr(e.callId)-rr(t.callId):0}function rr(e){let t=e.match(/(\d+)$/);return t?parseInt(t[1],10):0}function ja(e,t){for(let r=0;r<e.length;r++){let a=e[r];if(a.type!=="navigation")continue;let s=new Date(a.timestamp).getTime(),n=null;for(let o=r+1;o<e.length;o++)if(e[o]._testTitle===a._testTitle){n=new Date(e[o].timestamp).getTime();break}if(n!==null)a.durationOnUrl=Math.max(0,n-s);else {let o=t.find(i=>i.title===a._testTitle);if(o){let i=new Date(o.completedAt).getTime();a.durationOnUrl=Math.max(0,i-s);}}}}function ar(e){if(e==null)return null;try{return JSON.parse(e)}catch{return e}}function Ue(e,t){let r=e.length,a=Math.min(Math.ceil(t/100*r)-1,r-1);return e[Math.max(0,a)]}function Va(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return e}}function Ga(e){return e==null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function nr(e,t){let r=0,a=0,s=0,n=0,o=0;for(let v of e)switch(v.status){case "passed":r++;break;case "failed":a++;break;case "flaky":s++;break;case "skipped":n++;break;case "timedout":o++;break}let i=[];for(let v of e)v.apiCalls&&i.push(...v.apiCalls);let l=i.length,d=new Set,p={},f={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},m=[];for(let v of i)d.add(Va(v.url)),p[v.method]=(p[v.method]??0)+1,f[Ga(v.responseStatusCode)]+=1,m.push(v.responseTimeMs);let c=null;if(m.length>0){let v=[...m].sort((A,q)=>A-q),k=v.reduce((A,q)=>A+q,0);c={avg:Math.round(k/v.length),min:v[0],max:v[v.length-1],p50:Ue(v,50),p95:Ue(v,95),p99:Ue(v,99)};}let u=0,g=0,h=0;for(let v of e)if(v.apiAssertions)for(let k of v.apiAssertions)u++,k.status==="passed"?g++:h++;let w=0,S=new Set;for(let v of e){w+=v.navigations.length;for(let k of v.navigations)S.add(k.url);}let y=0,b={};function T(v){for(let k of v)y++,b[k.category]=(b[k.category]??0)+1,k.children.length>0&&T(k.children);}for(let v of e)v.actions&&T(v.actions);return {total:e.length,passed:r,failed:a,flaky:s,skipped:n,timedout:o,totalApiCalls:l,uniqueApiUrls:d.size,apiCallsByMethod:p,apiCallsByStatusRange:f,apiResponseTime:c,totalAssertions:u,passedAssertions:g,failedAssertions:h,totalNavigations:w,uniqueNavigationUrls:S.size,totalTimelineSteps:t,totalActionSteps:y,actionStepsByCategory:b}}function Wa(e){let t=56-e.length;return t>0?e+" ".repeat(t):e}function I(e){return `\u2502 ${Wa(e)} \u2502
2554
+ `;appendFileSync(r,n,"utf-8");}catch{}}function sr(e,t){let r=[];for(let a of e){let s=qa(a),n=Ha(a),o=Ua(a,s,n,t),i=za(a,s,n);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:a.startedAt,durationOnUrl:a.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:a.specFile,test:s,tests:[n],_testTitle:a.title});continue}r.push(...o,...i);}return r.sort($a),ja(r,e),r.map((a,s)=>a.type==="navigation"?{...{index:s,type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:a.durationOnUrl??0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:a.specFile,test:a.test},tests:a.tests}:{...{index:s,type:"api_call",callId:a.callId,method:a.method,url:a.url,timestamp:a.timestamp,responseTime:a.responseTime??null,request:a.request,response:a.response??null,...a.error?{error:a.error}:{},assertions:a.assertions??[],specFile:a.specFile,test:a.test},tests:a.tests})}function qa(e){return {title:e.title,fullTitle:e.titlePath,status:e.status,duration:e.duration,retries:e.retryCount,retry:e.retry,tags:e.tags,failure:e.failure}}function Ha(e){return {title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:e.retryCount,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,retryStatus:e.retryStatus,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,networkRequests:e.networkRequests,apiCalls:e.apiCalls,apiAssertions:e.apiAssertions,actions:e.actions,consoleLogs:e.consoleLogs}}function Ua(e,t,r,a){let s=[];for(let n of e.navigations)a.navigationTypes!==null&&!a.navigationTypes.includes(n.navigationType)||s.push({type:"navigation",url:n.url,timestamp:n.timestamp,durationOnUrl:0,navigationType:n.navigationType,domContentLoadedAt:n.domContentLoadedAt??null,networkIdleAt:n.networkIdleAt??null,networkStats:n.networkStats??null,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title});return s}function za(e,t,r){if(!e.apiCalls||e.apiCalls.length===0)return [];let a=e.apiAssertions??[];return e.apiCalls.map(s=>{let n=a.filter(i=>i.callId===s.id).map(i=>({type:i.type,expected:i.expected,actual:i.actual,status:i.status,location:i.location,...i.expression!==void 0?{expression:i.expression}:{}})),o=null;return s.responseStatusCode!==null&&s.responseStatusText!==null&&(o={statusCode:s.responseStatusCode,statusText:s.responseStatusText,headers:s.responseHeaders,body:ar(s.responseBody)}),{type:"api_call",callId:s.id,method:s.method,url:s.url,timestamp:s.timestamp,responseTime:s.error?null:s.responseTimeMs,request:{headers:s.requestHeaders,body:ar(s.requestBody)},response:o,...s.error?{error:s.error}:{},assertions:n,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title}})}function $a(e,t){let r=new Date(e.timestamp).getTime(),a=new Date(t.timestamp).getTime();if(r!==a)return r-a;let s={navigation:0,api_call:1},n=s[e.type],o=s[t.type];return n!==o?n-o:e.type==="api_call"&&t.type==="api_call"&&e.callId&&t.callId?rr(e.callId)-rr(t.callId):0}function rr(e){let t=e.match(/(\d+)$/);return t?parseInt(t[1],10):0}function ja(e,t){for(let r=0;r<e.length;r++){let a=e[r];if(a.type!=="navigation")continue;let s=new Date(a.timestamp).getTime(),n=null;for(let o=r+1;o<e.length;o++)if(e[o]._testTitle===a._testTitle){n=new Date(e[o].timestamp).getTime();break}if(n!==null)a.durationOnUrl=Math.max(0,n-s);else {let o=t.find(i=>i.title===a._testTitle);if(o){let i=new Date(o.completedAt).getTime();a.durationOnUrl=Math.max(0,i-s);}}}}function ar(e){if(e==null)return null;try{return JSON.parse(e)}catch{return e}}function Ue(e,t){let r=e.length,a=Math.min(Math.ceil(t/100*r)-1,r-1);return e[Math.max(0,a)]}function Va(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return e}}function Ga(e){return e==null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function nr(e,t){let r=0,a=0,s=0,n=0,o=0;for(let v of e)switch(v.status){case "passed":r++;break;case "failed":a++;break;case "flaky":s++;break;case "skipped":n++;break;case "timedout":o++;break}let i=[];for(let v of e)v.apiCalls&&i.push(...v.apiCalls);let l=i.length,d=new Set,u={},f={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},m=[];for(let v of i)d.add(Va(v.url)),u[v.method]=(u[v.method]??0)+1,f[Ga(v.responseStatusCode)]+=1,m.push(v.responseTimeMs);let c=null;if(m.length>0){let v=[...m].sort((A,q)=>A-q),k=v.reduce((A,q)=>A+q,0);c={avg:Math.round(k/v.length),min:v[0],max:v[v.length-1],p50:Ue(v,50),p95:Ue(v,95),p99:Ue(v,99)};}let p=0,g=0,h=0;for(let v of e)if(v.apiAssertions)for(let k of v.apiAssertions)p++,k.status==="passed"?g++:h++;let w=0,S=new Set;for(let v of e){w+=v.navigations.length;for(let k of v.navigations)S.add(k.url);}let y=0,b={};function T(v){for(let k of v)y++,b[k.category]=(b[k.category]??0)+1,k.children.length>0&&T(k.children);}for(let v of e)v.actions&&T(v.actions);return {total:e.length,passed:r,failed:a,flaky:s,skipped:n,timedout:o,totalApiCalls:l,uniqueApiUrls:d.size,apiCallsByMethod:u,apiCallsByStatusRange:f,apiResponseTime:c,totalAssertions:p,passedAssertions:g,failedAssertions:h,totalNavigations:w,uniqueNavigationUrls:S.size,totalTimelineSteps:t,totalActionSteps:y,actionStepsByCategory:b}}function Wa(e){let t=56-e.length;return t>0?e+" ".repeat(t):e}function I(e){return `\u2502 ${Wa(e)} \u2502
2555
2555
  `}function ze(e,t,r,a){if(a||e.total===0)return;let s=`\u250C${"\u2500".repeat(58)}\u2510
2556
2556
  `,n=`\u2514${"\u2500".repeat(58)}\u2518
2557
- `,o=I(""),i=s;i+=I("TestRelic AI - Playwright Test Report"),i+=o;let l=[];if(e.passed>0&&l.push(`${e.passed} \u2713`),e.failed>0&&l.push(`${e.failed} \u2717`),e.flaky>0&&l.push(`${e.flaky} \u26A0`),e.skipped>0&&l.push(`${e.skipped} skipped`),e.timedout>0&&l.push(`${e.timedout} timedout`),i+=I(`Tests: ${e.total} total (${l.join(" ")})`),e.totalNavigations>0&&(i+=I(`Navigations: ${e.totalNavigations} visits across ${e.uniqueNavigationUrls} unique URLs`)),e.totalApiCalls>0){i+=I(`API Calls: ${e.totalApiCalls} calls across ${e.uniqueApiUrls} unique endpoints`);let d=Object.entries(e.apiCallsByMethod).filter(([,f])=>f>0).map(([f,m])=>`${f}: ${m}`);d.length>0&&(i+=I(` ${d.join(" ")}`));let p=Object.entries(e.apiCallsByStatusRange).filter(([,f])=>f>0).map(([f,m])=>`${f}: ${m}`);p.length>0&&(i+=I(` ${p.join(" ")}`)),e.apiResponseTime&&(i+=I(` Avg response: ${e.apiResponseTime.avg}ms P95: ${e.apiResponseTime.p95}ms`));}if(e.totalAssertions>0&&(i+=I(`Assertions: ${e.totalAssertions} total (${e.passedAssertions} \u2713 ${e.failedAssertions} \u2717)`)),e.totalActionSteps>0){let d=[],p=e.actionStepsByCategory;p.ui_action&&d.push(`${p.ui_action} UI`),p.assertion&&d.push(`${p.assertion} assertions`),p.custom_step&&d.push(`${p.custom_step} custom`);let f=d.length>0?` (${d.join(" ")})`:"";i+=I(`Actions: ${e.totalActionSteps} steps${f}`);}i+=I(`Report: ${r}`),i+=I(`Data: ${t}`),i+=n,i+=`For more information visit us at https://docs.testrelic.ai
2558
- `,process.stderr.write(i);}var Ka=new Set(["pw:api","expect","test.step"]);function Ja(e){return e==="expect"?"assertion":e==="test.step"?"custom_step":"ui_action"}function $e(e,t,r){if(Ka.has(e.category)){let a=[];for(let n of e.steps)$e(n,t,a);let s=e.startTime.getTime()-t.getTime();r.push({title:e.title,category:Ja(e.category),timestamp:e.startTime.toISOString(),duration:e.duration,videoOffset:s>=0?s/1e3:null,status:e.error?"failed":"passed",error:e.error?.message??null,children:a});}else for(let a of e.steps)$e(a,t,r);}function ir(e,t){let r=[];for(let a of e)$e(a,t,r);return r}var Qa=new Set(["localhost","127.0.0.1","0.0.0.0"]);function lr(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Qa.has(t.hostname)))throw createError(ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Xa=3e3;async function je(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Xa);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function dr(e){return new Promise(t=>setTimeout(t,e))}async function or(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string"){let a=r.details;if(Array.isArray(a)&&a.length>0){let s=a.map(n=>`${n.field}: ${n.message}`).join(", ");return `${r.message} (${s})`}return r.message}}catch{}return `HTTP ${e.status}`}async function Ve(e,t,r){let a=new AbortController,s=setTimeout(()=>a.abort(),r);try{let n=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:a.signal});if(n.ok){let i=await n.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,orgId:i.orgId,orgName:i.orgName,userId:i.userId,userName:i.userName}}if(n.status===429){let i=n.headers.get("Retry-After"),l=i?parseInt(i,10)*1e3:5e3;if(!isNaN(l)&&l>0){await dr(l);let d=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:a.signal});if(d.ok){let p=await d.json();return {accessToken:p.accessToken,refreshToken:p.refreshToken,expiresIn:p.expiresIn,orgId:p.orgId,orgName:p.orgName,userId:p.userId,userName:p.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return n.status===400?{code:"validation_error",message:await or(n),statusCode:400}:n.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:n.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await or(n),statusCode:n.status}}catch(n){return n instanceof DOMException&&n.name==="AbortError"?{code:"timeout",message:"Token exchange timed out.",statusCode:null}:{code:"network_error",message:"Failed to reach cloud for token exchange.",statusCode:null}}finally{clearTimeout(s);}}function Ge(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function cr(e,t,r){let a=new AbortController,s=setTimeout(()=>a.abort(),r);try{let n=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:a.signal});if(n.status===429){let i=n.headers.get("Retry-After"),l=i?parseInt(i,10)*1e3:5e3;!isNaN(l)&&l>0&&(await dr(l),n=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:a.signal}));}if(!n.ok)return null;let o=await n.json();return {accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn}}catch{return null}finally{clearTimeout(s);}}async function ur(e,t,r,a,s,n){let o=new AbortController,i=setTimeout(()=>o.abort(),s);try{let l={gitId:r,displayName:a};n&&(l.branch=n);let d=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:o.signal});if(!d.ok)return null;let p=await d.json();return {repoId:p.repoId,displayName:p.displayName}}catch{return null}finally{clearTimeout(i);}}var ss=5e3;function D(e,t){try{return execSync(e,{cwd:t,timeout:ss,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function pr(e){let t=D("git rev-parse --abbrev-ref HEAD",e),r=D("git rev-parse --short HEAD",e),a=D("git log -1 --pretty=%s",e),s=D("git log -1 --format=%an",e)??D("git config user.name",e),n=ns(e),o=n?Z(n):null;return {branch:t,commitSha:r,commitMessage:a,commitAuthor:s,remoteUrl:o}}function ns(e){let t=D("git remote get-url origin",e);if(t)return t;let r=D("git remote",e);if(!r)return null;let a=r.split(`
2559
- `)[0]?.trim();return a?D(`git remote get-url ${a}`,e):null}function Z(e){let t=e.trim();return t=t.replace(/^[a-z+]+:\/\//,""),t=t.replace(/^[^@]+@/,""),t=t.replace(/:(?!\d)/,"/"),t=t.replace(/\.git$/,""),t=t.replace(/\/+$/,""),t=t.replace(/^[^@/]+@/,""),t.toLowerCase()}function fr(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function We(e){try{let t=readFileSync(join(e,"package.json"),"utf-8"),r=JSON.parse(t);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function Q(e){let t=We(e);return t||`local/${basename(e)}`}var ps=1048576,fs="1.0.0",gr=10;function X(e,t,r,a,s,n,o,i){try{mkdirSync(e,{recursive:!0});let l=Date.now(),d=`${l}-${t}-${r}.json`,p=join(e,d),f={version:fs,queuedAt:new Date(l).toISOString(),reason:a,retryCount:0,targetEndpoint:s,method:n,payload:o,headers:i},m=p+".tmp";writeFileSync(m,JSON.stringify(f,null,2),"utf-8"),renameSync(m,p);}catch(l){l.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
2557
+ `,o=I(""),i=s;i+=I("TestRelic AI - Playwright Test Report"),i+=o;let l=[];if(e.passed>0&&l.push(`${e.passed} \u2713`),e.failed>0&&l.push(`${e.failed} \u2717`),e.flaky>0&&l.push(`${e.flaky} \u26A0`),e.skipped>0&&l.push(`${e.skipped} skipped`),e.timedout>0&&l.push(`${e.timedout} timedout`),i+=I(`Tests: ${e.total} total (${l.join(" ")})`),e.totalNavigations>0&&(i+=I(`Navigations: ${e.totalNavigations} visits across ${e.uniqueNavigationUrls} unique URLs`)),e.totalApiCalls>0){i+=I(`API Calls: ${e.totalApiCalls} calls across ${e.uniqueApiUrls} unique endpoints`);let d=Object.entries(e.apiCallsByMethod).filter(([,f])=>f>0).map(([f,m])=>`${f}: ${m}`);d.length>0&&(i+=I(` ${d.join(" ")}`));let u=Object.entries(e.apiCallsByStatusRange).filter(([,f])=>f>0).map(([f,m])=>`${f}: ${m}`);u.length>0&&(i+=I(` ${u.join(" ")}`)),e.apiResponseTime&&(i+=I(` Avg response: ${e.apiResponseTime.avg}ms P95: ${e.apiResponseTime.p95}ms`));}if(e.totalAssertions>0&&(i+=I(`Assertions: ${e.totalAssertions} total (${e.passedAssertions} \u2713 ${e.failedAssertions} \u2717)`)),e.totalActionSteps>0){let d=[],u=e.actionStepsByCategory;u.ui_action&&d.push(`${u.ui_action} UI`),u.assertion&&d.push(`${u.assertion} assertions`),u.custom_step&&d.push(`${u.custom_step} custom`);let f=d.length>0?` (${d.join(" ")})`:"";i+=I(`Actions: ${e.totalActionSteps} steps${f}`);}i+=I(`Report: ${r}`),i+=I(`Data: ${t}`),i+=n,i+=`For more information visit us at https://docs.testrelic.ai
2558
+ `,process.stderr.write(i);}var Ka=new Set(["pw:api","expect","test.step"]);function Ja(e){return e==="expect"?"assertion":e==="test.step"?"custom_step":"ui_action"}function $e(e,t,r){if(Ka.has(e.category)){let a=[];for(let n of e.steps)$e(n,t,a);let s=e.startTime.getTime()-t.getTime();r.push({title:e.title,category:Ja(e.category),timestamp:e.startTime.toISOString(),duration:e.duration,videoOffset:s>=0?s/1e3:null,status:e.error?"failed":"passed",error:e.error?.message??null,children:a});}else for(let a of e.steps)$e(a,t,r);}function ir(e,t){let r=[];for(let a of e)$e(a,t,r);return r}var Qa=new Set(["localhost","127.0.0.1","0.0.0.0"]);function lr(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Qa.has(t.hostname)))throw createError(ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Xa=3e3;async function je(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Xa);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function dr(e){return new Promise(t=>setTimeout(t,e))}async function or(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string"){let a=r.details;if(Array.isArray(a)&&a.length>0){let s=a.map(n=>`${n.field}: ${n.message}`).join(", ");return `${r.message} (${s})`}return r.message}}catch{}return `HTTP ${e.status}`}async function Ve(e,t,r){let a=new AbortController,s=setTimeout(()=>a.abort(),r);try{let n=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:a.signal});if(n.ok){let i=await n.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,orgId:i.orgId,orgName:i.orgName,userId:i.userId,userName:i.userName}}if(n.status===429){let i=n.headers.get("Retry-After"),l=i?parseInt(i,10)*1e3:5e3;if(!isNaN(l)&&l>0){await dr(l);let d=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:a.signal});if(d.ok){let u=await d.json();return {accessToken:u.accessToken,refreshToken:u.refreshToken,expiresIn:u.expiresIn,orgId:u.orgId,orgName:u.orgName,userId:u.userId,userName:u.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return n.status===400?{code:"validation_error",message:await or(n),statusCode:400}:n.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:n.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await or(n),statusCode:n.status}}catch(n){return n instanceof DOMException&&n.name==="AbortError"?{code:"timeout",message:"Token exchange timed out.",statusCode:null}:{code:"network_error",message:"Failed to reach cloud for token exchange.",statusCode:null}}finally{clearTimeout(s);}}function Ge(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function cr(e,t,r){let a=new AbortController,s=setTimeout(()=>a.abort(),r);try{let n=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:a.signal});if(n.status===429){let i=n.headers.get("Retry-After"),l=i?parseInt(i,10)*1e3:5e3;!isNaN(l)&&l>0&&(await dr(l),n=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:a.signal}));}if(!n.ok)return null;let o=await n.json();return {accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn}}catch{return null}finally{clearTimeout(s);}}async function pr(e,t,r,a,s,n){let o=new AbortController,i=setTimeout(()=>o.abort(),s);try{let l={gitId:r,displayName:a};n&&(l.branch=n);let d=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:o.signal});if(!d.ok)return null;let u=await d.json();return {repoId:u.repoId,displayName:u.displayName}}catch{return null}finally{clearTimeout(i);}}var ss=5e3;function D(e,t){try{return execSync(e,{cwd:t,timeout:ss,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function ur(e){let t=D("git rev-parse --abbrev-ref HEAD",e),r=D("git rev-parse --short HEAD",e),a=D("git log -1 --pretty=%s",e),s=D("git log -1 --format=%an",e)??D("git config user.name",e),n=ns(e),o=n?Z(n):null;return {branch:t,commitSha:r,commitMessage:a,commitAuthor:s,remoteUrl:o}}function ns(e){let t=D("git remote get-url origin",e);if(t)return t;let r=D("git remote",e);if(!r)return null;let a=r.split(`
2559
+ `)[0]?.trim();return a?D(`git remote get-url ${a}`,e):null}function Z(e){let t=e.trim();return t=t.replace(/^[a-z+]+:\/\//,""),t=t.replace(/^[^@]+@/,""),t=t.replace(/:(?!\d)/,"/"),t=t.replace(/\.git$/,""),t=t.replace(/\/+$/,""),t=t.replace(/^[^@/]+@/,""),t.toLowerCase()}function fr(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function We(e){try{let t=readFileSync(join(e,"package.json"),"utf-8"),r=JSON.parse(t);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function Q(e){let t=We(e);return t||`local/${basename(e)}`}var us=1048576,fs="1.0.0",gr=10;function X(e,t,r,a,s,n,o,i){try{mkdirSync(e,{recursive:!0});let l=Date.now(),d=`${l}-${t}-${r}.json`,u=join(e,d),f={version:fs,queuedAt:new Date(l).toISOString(),reason:a,retryCount:0,targetEndpoint:s,method:n,payload:o,headers:i},m=u+".tmp";writeFileSync(m,JSON.stringify(f,null,2),"utf-8"),renameSync(m,u);}catch(l){l.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
2560
2560
  `):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
2561
- `);}}async function vr(e,t,r){let a;try{a=readdirSync(e).filter(n=>n.endsWith(".json")&&!n.endsWith(".tmp")).sort();}catch{return}if(a.length===0)return;let s=[];for(let n=0;n<a.length;n+=gr)s.push(a.slice(n,n+gr));for(let n of s)for(let o of n){let i=join(e,o);try{if(!statSync(i).isFile())continue;let d=readFileSync(i,"utf-8"),p=JSON.parse(d);if(!isValidQueueEntry(p)){process.stderr.write(`\u26A0 TestRelic: Corrupted queue file deleted: ${o}
2562
- `),unlinkSync(i);continue}let f=p,m=JSON.stringify(f.payload),c={...f.headers,Authorization:`Bearer ${r}`},u=m;if(Buffer.byteLength(m,"utf-8")>ps&&(u=gzipSync(Buffer.from(m,"utf-8")),c["Content-Encoding"]="gzip"),(await fetch(f.targetEndpoint,{method:f.method,headers:c,body:u})).ok)unlinkSync(i);else return}catch{return}}}function yr(e,t){try{let r=readdirSync(e).filter(s=>s.endsWith(".json")&&!s.endsWith(".tmp")),a=Date.now();for(let s of r){let n=join(e,s);try{let o=readFileSync(n,"utf-8"),l=JSON.parse(o).queuedAt;if(typeof l=="string"){let d=new Date(l).getTime();a-d>t&&unlinkSync(n);}}catch{try{unlinkSync(n);}catch{}}}}catch{}}var xs=3e5,ws=864e5,ks=6e4,br=3e4,Ye="https://platform.testrelic.ai/settings/api-keys",de=class{constructor(t){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=t,this.authState={mode:"pending",accessToken:null,refreshToken:null,expiresAt:null,orgId:null,orgName:null,userId:null,userName:null};}async initialize(){if(!this.config||!this.config.apiKey){this.setLocalMode("no_api_key"),process.stderr.write(`\u2139 TestRelic: No API key configured. Running in local mode.
2563
- `);return}try{if(lr(this.config.endpoint),this.gitMetadata=pr(),!await je(this.config.endpoint)){this.setLocalMode("cloud_unreachable"),process.stderr.write(`\u26A0 TestRelic: Cloud unreachable. Switching to local mode. Data will be queued for later upload.
2561
+ `);}}async function vr(e,t,r){let a;try{a=readdirSync(e).filter(n=>n.endsWith(".json")&&!n.endsWith(".tmp")).sort();}catch{return}if(a.length===0)return;let s=[];for(let n=0;n<a.length;n+=gr)s.push(a.slice(n,n+gr));for(let n of s)for(let o of n){let i=join(e,o);try{if(!statSync(i).isFile())continue;let d=readFileSync(i,"utf-8"),u=JSON.parse(d);if(!isValidQueueEntry(u)){process.stderr.write(`\u26A0 TestRelic: Corrupted queue file deleted: ${o}
2562
+ `),unlinkSync(i);continue}let f=u,m=JSON.stringify(f.payload),c={...f.headers,Authorization:`Bearer ${r}`},p=m;if(Buffer.byteLength(m,"utf-8")>us&&(p=gzipSync(Buffer.from(m,"utf-8")),c["Content-Encoding"]="gzip"),(await fetch(f.targetEndpoint,{method:f.method,headers:c,body:p})).ok)unlinkSync(i);else return}catch{return}}}function yr(e,t){try{let r=readdirSync(e).filter(s=>s.endsWith(".json")&&!s.endsWith(".tmp")),a=Date.now();for(let s of r){let n=join(e,s);try{let o=readFileSync(n,"utf-8"),l=JSON.parse(o).queuedAt;if(typeof l=="string"){let d=new Date(l).getTime();a-d>t&&unlinkSync(n);}}catch{try{unlinkSync(n);}catch{}}}}catch{}}var xs=3e5,ws=864e5,ks=6e4,br=3e4,Ye="https://platform.testrelic.ai/settings/api-keys",de=class{constructor(t){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=t,this.authState={mode:"pending",accessToken:null,refreshToken:null,expiresAt:null,orgId:null,orgName:null,userId:null,userName:null};}async initialize(){if(!this.config||!this.config.apiKey){this.setLocalMode("no_api_key"),process.stderr.write(`\u2139 TestRelic: No API key configured. Running in local mode.
2563
+ `);return}try{if(lr(this.config.endpoint),this.gitMetadata=ur(),!await je(this.config.endpoint)){this.setLocalMode("cloud_unreachable"),process.stderr.write(`\u26A0 TestRelic: Cloud unreachable. Switching to local mode. Data will be queued for later upload.
2564
2564
  `);return}let r=await Ve(this.config.endpoint,this.config.apiKey,this.config.timeout);if(Ge(r)){this.handleAuthError(r.code,r.statusCode);return}let a=r;this.authState={mode:"cloud",accessToken:a.accessToken,refreshToken:a.refreshToken,expiresAt:Date.now()+a.expiresIn*1e3,orgId:a.orgId,orgName:a.orgName,userId:a.userId,userName:a.userName},process.stderr.write(`\u2713 TestRelic: Connected to cloud (${a.orgName} / ${a.userName})
2565
2565
  `),await this.resolveRepoId(),this.config.queueDirectory&&(yr(this.config.queueDirectory,this.config.queueMaxAge),this.startBackgroundFlush()),this.startHealthCheck();}catch(t){this.setLocalMode("unexpected_error"),process.stderr.write(`\u26A0 TestRelic: Unexpected error during cloud initialization. Running in local mode. ${t instanceof Error?t.message:String(t)}
2566
2566
  `);}}getMode(){return this.authState.mode}isCloudMode(){return this.authState.mode==="cloud"}isLocalMode(){return this.authState.mode==="local"}getAccessToken(){return this.authState.accessToken}getRepoId(){return this.repoId}getGitMetadata(){return this.gitMetadata}getConfig(){return this.config}getFailureReason(){return this.failureReason}getEndpoint(){return this.config?.endpoint??"https://platform.testrelic.ai/api/v1"}async ensureValidToken(){if(!this.isCloudMode()||!this.authState.accessToken)return false;let t=this.authState.expiresAt??0;if(Date.now()+xs<t)return true;if(!this.config||!this.authState.refreshToken)return this.switchToLocalMode("token_expired_no_refresh"),false;try{let r=await cr(this.config.endpoint,this.authState.refreshToken,this.config.timeout);return r?(this.authState.accessToken=r.accessToken,this.authState.refreshToken=r.refreshToken,this.authState.expiresAt=Date.now()+r.expiresIn*1e3,!0):(this.switchToLocalMode("token_refresh_failed"),!1)}catch{return this.switchToLocalMode("token_refresh_error"),false}}switchToLocalMode(t){this.authState.mode!=="local"&&(this.authState.mode="local",this.failureReason=t,process.stderr.write(`\u26A0 TestRelic: Switched to local mode (${t}).
@@ -2573,14 +2573,14 @@ ${s}
2573
2573
  `);break;case "rate_limited":this.setLocalMode("rate_limited"),process.stderr.write(`\u26A0 TestRelic: Rate limited during authentication. Running in local mode.
2574
2574
  `);break;case "timeout":this.setLocalMode("auth_timeout"),process.stderr.write(`\u26A0 TestRelic: Authentication timed out. Running in local mode.
2575
2575
  `);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
2576
- `);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let t=this.gitMetadata?.remoteUrl?Z(this.gitMetadata.remoteUrl):null,r=t?fr(t):this.config.projectName??Q(process.cwd()),a=t??this.config.projectName??Q(process.cwd()),s=this.readRepoCache(a);if(s){this.repoId=s.repoId;return}try{let n=await ur(this.config.endpoint,this.authState.accessToken,a,r,this.config.timeout,this.gitMetadata?.branch);n&&(this.repoId=n.repoId,this.writeRepoCache(a,n.repoId,n.displayName));}catch{}!t&&!this.config.projectName&&!We(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
2576
+ `);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let t=this.gitMetadata?.remoteUrl?Z(this.gitMetadata.remoteUrl):null,r=t?fr(t):this.config.projectName??Q(process.cwd()),a=t??this.config.projectName??Q(process.cwd()),s=this.readRepoCache(a);if(s){this.repoId=s.repoId;return}try{let n=await pr(this.config.endpoint,this.authState.accessToken,a,r,this.config.timeout,this.gitMetadata?.branch);n&&(this.repoId=n.repoId,this.writeRepoCache(a,n.repoId,n.displayName));}catch{}!t&&!this.config.projectName&&!We(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
2577
2577
  `);}readRepoCache(t){if(!this.config)return null;let r=join(this.config.queueDirectory,"..","cache","repo.json");try{if(!existsSync(r))return null;let a=readFileSync(r,"utf-8"),s=JSON.parse(a);if(s.gitId!==t||Date.now()-s.resolvedAt>ws)return null;let n=this.hashApiKey();return n&&s.apiKeyHash!==n?null:s}catch{return null}}writeRepoCache(t,r,a){if(!this.config)return;let s=join(this.config.queueDirectory,"..","cache"),n=join(s,"repo.json");try{mkdirSync(s,{recursive:!0});let o={repoId:r,gitId:t,displayName:a,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},i=n+".tmp";writeFileSync(i,JSON.stringify(o,null,2),"utf-8"),renameSync(i,n);}catch{}}hashApiKey(){return this.config?.apiKey?createHash("sha256").update(this.config.apiKey).digest("hex").substring(0,16):null}startBackgroundFlush(){if(!this.config||!this.authState.accessToken)return;let t=this.authState.accessToken,r=this.config.queueDirectory,a=this.config.endpoint;this.flushPromise=Promise.race([vr(r,a,t),new Promise(s=>setTimeout(s,br))]).catch(()=>{});}startHealthCheck(){if(!this.config)return;let t=this.config.endpoint;this.healthCheckTimer=setInterval(async()=>{if(!this.isCloudMode()&&!(!this.failureReason||!["cloud_unreachable","auth_timeout","network_error"].includes(this.failureReason)))try{if(!await je(t))return;if(this.config?.apiKey){let a=await Ve(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!Ge(a)){let s=a;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.
2578
- `),this.startBackgroundFlush();}}}catch{}},ks);}};var Ts=new Set(["smoke","regression","nightly","ci"]);function ce(){let e=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(e&&Ts.has(e))return e}var Cs=1048576,ue=[1e3,3e3,9e3],pe=3,Rs=40*1048576;function Ze(e){if(!e||e.length===0||!e.every(s=>s.testType==="api"))return null;let t=new Map;for(let s of e){let n=s.apiProtocol??"rest";t.set(n,(t.get(n)??0)+1);}let r="rest",a=0;for(let[s,n]of t)n>a&&(a=n,r=s);return {testType:"api",apiProtocol:r,metadata:{testType:"api",primaryProtocol:r}}}function Qe(e,t,r,a,s,n){let o=n?.cloudPlatform?n.cloudPlatform:a?.provider&&a.provider!=="unknown"?a.provider:"local",i=ce(),l=Ze(s),d=l&&s?s.map(f=>f.apiProtocol?f:{...f,apiProtocol:l.apiProtocol}):s,p={runId:e.testRunId,repoGitId:t,startedAt:e.startedAt,summary:e.summary,timeline:e.timeline,environment:o,...i?{runType:i}:{},...l?{testType:l.testType,apiProtocol:l.apiProtocol,metadata:l.metadata}:{},...d&&d.length>0?{tests:d}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...e.completedAt?{finishedAt:e.completedAt}:{},...e.totalDuration?{duration:e.totalDuration}:{},...a?.provider?{ciProvider:a.provider}:{},...a?.runUrl?{ciRunUrl:a.runUrl}:{},...n?.cloudPlatform?{cloudPlatform:n.cloudPlatform}:{},...n?.cloudBuildId?{cloudBuildId:n.cloudBuildId}:{},...n?.cloudSessionId?{cloudSessionId:n.cloudSessionId}:{}};if(p.tests&&p.tests.length>0){let f=JSON.stringify(p);if(Buffer.byteLength(f,"utf-8")>Rs){let m=p.tests.map(({consoleLogs:c,networkRequests:u,...g})=>g);return {...p,tests:m}}}return p}async function fe(e){return new Promise(t=>setTimeout(t,e))}function As(e){let t={};for(let[r,a]of Object.entries(e))a!=null&&(t[r]=a);return t}async function xr(e,t,r){for(let a=0;a<pe;a++)try{let s=await fetch(e,t);if(s.ok)return s;if(s.status===401&&r&&a===0){let n=await r();if(n){let o={...t,headers:{...t.headers,Authorization:`Bearer ${n}`}},i=await fetch(e,o);if(i.ok)return i}return null}if(s.status===429&&a<pe-1){let n=s.headers.get("Retry-After"),o=n?parseInt(n,10)*1e3:ue[a];!isNaN(o)&&o>0?await fe(o):await fe(ue[a]);continue}if(s.status>=500&&a<pe-1){await fe(ue[a]);continue}return s}catch{if(a<pe-1){await fe(ue[a]);continue}return null}return null}function _s(e){let t=JSON.stringify(e),r={"Content-Type":"application/json"};if(Buffer.byteLength(t,"utf-8")>Cs){let a=gzipSync(Buffer.from(t,"utf-8"));return r["Content-Encoding"]="gzip",{body:a,headers:r}}return {body:t,headers:r}}async function wr(e,t,r,a){let s=`${e}/runs`,{body:n,headers:o}=_s(r);o.Authorization=`Bearer ${t}`;let i=await xr(s,{method:"POST",headers:o,body:n},a);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 kr(e,t,r){let a=`${e}/runs/init`;try{let s=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(As(r))});return s.ok?{runId:(await s.json()).runId}:null}catch{return null}}function Tr(e,t,r,a){let s=`${e}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(a)}).catch(()=>{});}async function Sr(e,t,r,a){let s=`${e}/runs/${r}/finalize`;return (await xr(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(a)}))?.ok??false}function Xe(e,t,r,a){let s=`${e}/runs/${r}/finalize`,n=new Date,o={finishedAt:n.toISOString(),duration:n.getTime()-new Date(a).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(o)}).catch(()=>{});}function Cr(e,t,r,a){let s=[],n=[],o=null,i=0,l=null,d=0,p=null,f=0,m=e.filter(g=>g.name===ATTACHMENT_NAME&&g.body),c=false;if(m.length>0)for(let g of m)try{let h=JSON.parse(g.body.toString());if(isTestRelicFilePayload(h)){s=s.concat(h.navigations),n=n.concat(h.apiAssertions),h.networkRequestsFile&&(o=h.networkRequestsFile,i+=h.networkRequestsCount),h.consoleLogsFile&&(l=h.consoleLogsFile,d+=h.consoleLogsCount),h.apiCallsFile&&(p=h.apiCallsFile,f+=h.apiCallsCount),c=!0;continue}if(isTestRelicDataPayload(h)){s=s.concat(h.navigations),Array.isArray(h.apiAssertions)&&(n=n.concat(h.apiAssertions)),i+=h.networkRequests?.length??0,f+=h.apiCalls?.length??0;let w=h.consoleLogs;Array.isArray(w)&&(d+=w.length),c=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
2578
+ `),this.startBackgroundFlush();}}}catch{}},ks);}};var Ts=new Set(["smoke","regression","nightly","ci"]);function ce(){let e=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(e&&Ts.has(e))return e}var Cs=1048576,pe=[1e3,3e3,9e3],ue=3,Rs=40*1048576,As=new Set(["e2e","mobile","unit"]);function Ze(e){if(e&&e.length>0&&e.every(s=>s.testType==="api")){let s=new Map;for(let i of e){let l=i.apiProtocol??"rest";s.set(l,(s.get(l)??0)+1);}let n="rest",o=0;for(let[i,l]of s)l>o&&(o=l,n=i);return {testType:"api",apiProtocol:n,metadata:{testType:"api",primaryProtocol:n}}}let t=new Map;for(let s of e??[])As.has(s.testType)&&t.set(s.testType,(t.get(s.testType)??0)+1);let r=null,a=0;for(let[s,n]of t)n>a&&(a=n,r=s);return {testType:r??"e2e"}}function Qe(e,t,r,a,s,n){let o=n?.cloudPlatform?n.cloudPlatform:a?.provider&&a.provider!=="unknown"?a.provider:"local",i=ce(),l=Ze(s),d=l.testType==="api"?l:null,u=d&&s?s.map(m=>m.apiProtocol?m:{...m,apiProtocol:d.apiProtocol}):s,f={runId:e.testRunId,repoGitId:t,startedAt:e.startedAt,summary:e.summary,timeline:e.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}:{},...e.completedAt?{finishedAt:e.completedAt}:{},...e.totalDuration?{duration:e.totalDuration}:{},...a?.provider?{ciProvider:a.provider}:{},...a?.runUrl?{ciRunUrl:a.runUrl}:{},...n?.cloudPlatform?{cloudPlatform:n.cloudPlatform}:{},...n?.cloudBuildId?{cloudBuildId:n.cloudBuildId}:{},...n?.cloudSessionId?{cloudSessionId:n.cloudSessionId}:{}};if(f.tests&&f.tests.length>0){let m=JSON.stringify(f);if(Buffer.byteLength(m,"utf-8")>Rs){let c=f.tests.map(({consoleLogs:p,networkRequests:g,...h})=>h);return {...f,tests:c}}}return f}async function fe(e){return new Promise(t=>setTimeout(t,e))}function _s(e){let t={};for(let[r,a]of Object.entries(e))a!=null&&(t[r]=a);return t}async function xr(e,t,r){for(let a=0;a<ue;a++)try{let s=await fetch(e,t);if(s.ok)return s;if(s.status===401&&r&&a===0){let n=await r();if(n){let o={...t,headers:{...t.headers,Authorization:`Bearer ${n}`}},i=await fetch(e,o);if(i.ok)return i}return null}if(s.status===429&&a<ue-1){let n=s.headers.get("Retry-After"),o=n?parseInt(n,10)*1e3:pe[a];!isNaN(o)&&o>0?await fe(o):await fe(pe[a]);continue}if(s.status>=500&&a<ue-1){await fe(pe[a]);continue}return s}catch{if(a<ue-1){await fe(pe[a]);continue}return null}return null}function Is(e){let t=JSON.stringify(e),r={"Content-Type":"application/json"};if(Buffer.byteLength(t,"utf-8")>Cs){let a=gzipSync(Buffer.from(t,"utf-8"));return r["Content-Encoding"]="gzip",{body:a,headers:r}}return {body:t,headers:r}}async function wr(e,t,r,a){let s=`${e}/runs`,{body:n,headers:o}=Is(r);o.Authorization=`Bearer ${t}`;let i=await xr(s,{method:"POST",headers:o,body:n},a);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 kr(e,t,r){let a=`${e}/runs/init`;try{let s=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(_s(r))});return s.ok?{runId:(await s.json()).runId}:null}catch{return null}}function Tr(e,t,r,a){let s=`${e}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(a)}).catch(()=>{});}async function Sr(e,t,r,a){let s=`${e}/runs/${r}/finalize`;return (await xr(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(a)}))?.ok??false}function Xe(e,t,r,a){let s=`${e}/runs/${r}/finalize`,n=new Date,o={finishedAt:n.toISOString(),duration:n.getTime()-new Date(a).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(o)}).catch(()=>{});}function Cr(e,t,r,a){let s=[],n=[],o=null,i=0,l=null,d=0,u=null,f=0,m=e.filter(g=>g.name===ATTACHMENT_NAME&&g.body),c=false;if(m.length>0)for(let g of m)try{let h=JSON.parse(g.body.toString());if(isTestRelicFilePayload(h)){s=s.concat(h.navigations),n=n.concat(h.apiAssertions),h.networkRequestsFile&&(o=h.networkRequestsFile,i+=h.networkRequestsCount),h.consoleLogsFile&&(l=h.consoleLogsFile,d+=h.consoleLogsCount),h.apiCallsFile&&(u=h.apiCallsFile,f+=h.apiCallsCount),c=!0;continue}if(isTestRelicDataPayload(h)){s=s.concat(h.navigations),Array.isArray(h.apiAssertions)&&(n=n.concat(h.apiAssertions)),i+=h.networkRequests?.length??0,f+=h.apiCalls?.length??0;let w=h.consoleLogs;Array.isArray(w)&&(d+=w.length),c=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
2579
2579
  `);}return c||(s=t.filter(g=>g.type==="lambdatest-navigation"&&g.description).map(g=>{try{return JSON.parse(g.description)}catch{return null}}).filter(g=>g!==null)),s.length===0&&i===0&&f===0&&!a&&!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.
2580
- `),{navigations:s,apiAssertions:n,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:l,consoleLogsCount:d,apiCallsFile:p,apiCallsCount:f}}function ge(e=process.env){let t=Es(e.TESTRELIC_CLOUD_PLATFORM);if(t)return {cloudPlatform:t,cloudBuildId:e.TESTRELIC_CLOUD_BUILD_ID||void 0,cloudSessionId:e.TESTRELIC_CLOUD_SESSION_ID||void 0};if(e.BROWSERSTACK_USERNAME||e.BROWSERSTACK_ACCESS_KEY)return {cloudPlatform:"browserstack",cloudBuildId:e.BROWSERSTACK_BUILD_NAME||e.BROWSERSTACK_BUILD_ID||void 0,cloudSessionId:e.BROWSERSTACK_SESSION_ID||void 0};if(e.LT_USERNAME||e.LAMBDATEST_USERNAME||e.LT_ACCESS_KEY||e.LAMBDATEST_ACCESS_KEY)return {cloudPlatform:"lambdatest",cloudBuildId:e.LT_BUILD||e.LAMBDATEST_BUILD||void 0,cloudSessionId:e.LT_SESSION_ID||e.LAMBDATEST_SESSION_ID||void 0};let r=e.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 Es(e){if(!e)return;let t=e.toLowerCase().trim();if(t==="browserstack"||t==="bs")return "browserstack";if(t==="lambdatest"||t==="lt")return "lambdatest"}var Bs=5,he=[1e3,3e3,9e3],U=3,Os={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip"},et=0,tt=[];async function qs(){et>=Bs&&await new Promise(e=>tt.push(e)),et++;}function Hs(){et--,tt.length>0&&tt.shift()();}async function me(e){return new Promise(t=>setTimeout(t,e))}function Us(e){let t=e.substring(e.lastIndexOf(".")).toLowerCase();return Os[t]??"application/octet-stream"}function zs(e){try{return statSync(e).size}catch{return 0}}async function $s(e,t,r,a,s){let n=`${e}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:basename(r.filePath),contentType:s,type:r.type,sizeBytes:a});for(let i=0;i<U;i++)try{let l=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:o});if(l.ok)return await l.json();if(l.status>=500&&i<U-1){await me(he[i]);continue}return null}catch{if(i<U-1){await me(he[i]);continue}return null}return null}async function js(e,t,r,a){for(let s=0;s<U;s++)try{let n=createReadStream(t),o=Readable.toWeb(n),i=await fetch(e,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(a)},body:o,duplex:"half"});if(i.ok)return !0;if(i.status>=500&&s<U-1){await me(he[s]);continue}return !1}catch{if(s<U-1){await me(he[s]);continue}return false}return false}async function Vs(e,t,r){let a=`${e}/artifacts/confirm`;try{return (await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function Gs(e,t,r,a){let s=zs(r.filePath);if(s===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(s>a*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let n=Us(r.filePath);await qs();try{let o=await $s(e,t,r,s,n);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await js(o.uploadUrl,r.filePath,n,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let l=await Vs(e,t,o.artifactId);return {success:l,storageKey:o.storageKey,artifactId:o.artifactId,error:l?null:"confirm_failed"}}finally{Hs();}}async function Rr(e,t,r,a){let s=new Map,n=r.map(async o=>{let i=await Gs(e,t,o,a);s.set(o.filePath,i);});return await Promise.allSettled(n),s}function rt(e){let r=e.getGitMetadata()?.remoteUrl;return r?Z(r):e.getConfig()?.projectName??Q(process.cwd())}async function _r(e,t,r,a,s){if(!e.isCloudMode()||t!=="realtime"&&t!=="both"||!await e.ensureValidToken())return null;let o=e.getGitMetadata(),i=P(),l=ge(),d=ce();return (await kr(e.getEndpoint(),e.getAccessToken(),{runId:r,repoGitId:rt(e),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:a,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}:{}}))?.runId??null}var Ws=true,Ks=50;async function Js(e,t,r,a){let s=new Map;if(!(t?.uploadArtifacts??Ws)||!await e.ensureValidToken())return s;let i=[],l=new Map;for(let c of a){if(c.artifacts.screenshot){let u=join(c.outputDir,c.artifacts.screenshot);i.push({filePath:u,runId:r,testId:c.testId,type:"screenshot"}),l.set(u,{testId:c.testId,field:"screenshot"});}if(c.artifacts.video){let u=join(c.outputDir,c.artifacts.video);i.push({filePath:u,runId:r,testId:c.testId,type:"video"}),l.set(u,{testId:c.testId,field:"video"});}}if(i.length===0)return s;let d=t?.artifactMaxSizeMb??Ks,p=await Rr(e.getEndpoint(),e.getAccessToken(),i,d),f=new Map;for(let[c,u]of p){if(!u.success||!u.storageKey)continue;let g=l.get(c);if(!g)continue;let h=f.get(g.testId)??{};g.field==="screenshot"&&(h.screenshotKey=u.storageKey),g.field==="video"&&(h.videoKey=u.storageKey),f.set(g.testId,h);}for(let c of a){let u=f.get(c.testId);s.set(c.testId,{...c.artifacts,...u?.screenshotKey?{screenshotKey:u.screenshotKey}:{},...u?.videoKey?{videoKey:u.videoKey}:{}});}let m=Array.from(p.values()).filter(c=>c.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
2581
- `),s}async function at(e,t,r,a,s,n,o,i,l,d,p){try{if(e.isCloudMode()&&s&&(r==="realtime"||r==="both")){let m=await e.ensureValidToken(),c=e.getGitMetadata(),u=Ze(p),g={finishedAt:o,duration:i,summary:l,...c?.commitMessage?{commitMessage:c.commitMessage}:{},...u?{testType:u.testType,apiProtocol:u.apiProtocol,metadata:u.metadata}:{}};if(m){if(!await Sr(e.getEndpoint(),e.getAccessToken(),s,g)){let w=t?.queueDirectory??".testrelic/queue";X(w,a,"finalize","finalize_failed_after_retries",`${e.getEndpoint()}/runs/${s}/finalize`,"POST",g,{"Content-Type":"application/json"});}}else {let h=t?.queueDirectory??".testrelic/queue";X(h,a,"finalize",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs/${s}/finalize`,"POST",g,{"Content-Type":"application/json"});}}let f=new Map;if(e.isCloudMode()&&d&&d.length>0&&(f=await Js(e,t,a,d)),e.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await e.ensureValidToken()){let c=e.getGitMetadata(),u=P(),g=rt(e),h=Ys(n,f),w=Qe(h,g,c,u,p,ge()),S=await wr(e.getEndpoint(),e.getAccessToken(),w,async()=>await e.ensureValidToken()?e.getAccessToken():null);if(!S.success){let y=S,b=t?.queueDirectory??".testrelic/queue";X(b,a,"batch",y.reason,y.targetEndpoint,y.method,y.payload,{"Content-Type":"application/json"});}}else {let c=t?.queueDirectory??".testrelic/queue",u=e.getGitMetadata(),g=P(),h=rt(e),w=Qe(n,h,u,g,void 0,ge());X(c,a,"batch",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs`,"POST",w,{"Content-Type":"application/json"});}await e.dispose();}catch{try{await e.dispose();}catch{}}}function Ys(e,t){if(t.size===0)return e;let r=e.timeline.map(a=>{let s=a.testId;if(!s)return a;let n=t.get(s);return n?{...a,...n.screenshotKey?{screenshotKey:n.screenshotKey}:{},...n.videoKey?{videoKey:n.videoKey}:{}}:a});return {...e,timeline:r}}function z(e){try{return readFileSync(e,"utf-8").split(`
2582
- `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function nt(e){switch(e){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function an(e,t,r){let a=`${e}::${t}::${r}`;return createHash("sha256").update(a).digest("hex").substring(0,16)}function sn(e){return e.length<=3?"":e[e.length-2]}function nn(e){let t=e.findIndex(r=>r.status==="passed");return t>0?`passed on retry ${t}`:null}function on(e){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":e?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[e.provider]??"CI":"Local"}function ln(){let e=platform();return e==="win32"?"Windows":e==="darwin"?"macOS":"Linux"}function dn(e){let t=e.parent?.project?.()?.use;if(!t)return;let{browserName:r,channel:a}=t;if(a){let n=a.toLowerCase();return n==="chrome"||n==="chrome-stable"?"Chrome":n.startsWith("chrome-beta")?"Chrome Beta":n.startsWith("chrome-dev")?"Chrome Dev":n.startsWith("chrome-canary")?"Chrome Canary":n==="msedge"||n==="msedge-stable"?"Microsoft Edge":n.startsWith("msedge-beta")?"Edge Beta":n.startsWith("msedge-dev")?"Edge Dev":n.startsWith("msedge-canary")?"Edge Canary":a}if(r){let n=r.toLowerCase();return n==="chromium"?"Chromium":n==="firefox"?"Firefox":n==="webkit"?"WebKit":r}let s=t.defaultBrowserType;if(s){let n=s.toLowerCase();return n==="chromium"?"Chromium":n==="firefox"?"Firefox":n==="webkit"?"WebKit":s}}function cn(e,t,r){let a=r.parent?.project?.(),s="unknown";a!==void 0&&(a.use.isMobile===true?s="mobile":s="e2e");let n=["e2e","api","unit","mobile"];for(let l of n)if(e.some(d=>d===`@${l}`||d===l))return l;let o=t.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let l of i)if(o.includes(`/${l}/`))return l;return s}var un="__testrelic_api_config";function pn(e){return JSON.stringify(e,(t,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var ve=class{constructor(t){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=wt(t),this.apiConfig=xt(t);}async onBegin(t,r){try{if(this.rootDir=t.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??randomUUID(),this.config.reportMode==="auto"){let n=r.allTests().length;this.activeReportMode=n>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let a=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${a} tests)
2583
- `),this.activeReportMode==="streaming"){let n=dirname(this.config.outputPath);this.streamingWriter=new G(n);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&&Xe(this.cloudClient.getEndpoint(),i,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",o),process.on("SIGINT",o);}if(this.config.includeArtifacts){let n=dirname(this.config.outputPath);this.runTimestamp=Yt(join(n,"artifacts"));try{tr(join(n,"artifacts"));}catch{}}let s=P();this.detectedOs=ln(),this.detectedSource=on(s);try{this.cloudClient=new de(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await _r(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource);}catch{this.cloudClient?.switchToLocalMode("init_error");}if(this.activeReportMode!=="streaming"){let n=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let o=this.cloudClient.getAccessToken();o&&Xe(this.cloudClient.getEndpoint(),o,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",n),process.on("SIGINT",n);}}catch{}}onTestBegin(t,r){try{t.annotations.push({type:un,description:pn(this.apiConfig)});}catch{}}onTestEnd(t,r){try{let a=r,s=t.outcome(),n;s==="flaky"?n="flaky":s==="skipped"?n="skipped":n=nt(a.status);let o=a.startTime.toISOString(),i=new Date(a.startTime.getTime()+a.duration).toISOString(),l=t.tags?[...t.tags]:t.annotations.filter(R=>R.type==="tag").map(R=>R.description??""),d=Cr(a.attachments,t.annotations,t.title,n==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0);let p=null;if(n==="failed"||n==="flaky"){let C=(n==="flaky"?t.results.find(B=>B.status!=="passed")?.errors??[]:a.errors)[0];if(C){let B=Tt(this.config.redactPatterns),$=C.location?.line??null,j=null;this.config.includeCodeSnippets&&$!==null&&C.location?.file&&(j=kt(C.location.file,$,this.config.codeContextLines),j&&(j=B(j))),p={message:B(C.message??"Unknown error"),line:$,code:j,stack:this.config.includeStackTrace&&C.stack?B(C.stack):null};}}let f=t.titlePath().filter(Boolean),m=relative(this.rootDir||".",t.location.file),c=sn(f),u=f.join(" > "),g=m,h=an(g,c,u),w=cn(l,g,t),S=w!=="mobile"&&d.apiCallsCount>0?"api":w,y=s==="flaky",b=nn(t.results),T=nt(t.expectedStatus),v=nt(a.status),k=null;if(this.config.includeArtifacts&&n!=="skipped"&&a.attachments){let R=dirname(this.config.outputPath),C=f[f.length-1]??t.title;k=Zt(a.attachments,C,a.retry,R,this.runTimestamp||void 0);}let A=this.config.includeActionSteps&&a.steps?ir(a.steps,a.startTime):null,q=dn(t),M={titlePath:f,title:u,status:n,duration:a.duration,startedAt:o,completedAt:i,retryCount:t.results.length-1,retry:a.retry,tags:l,failure:p,specFile:m,navigations:d.navigations,testId:h,filePath:g,suiteName:c,testType:S,isFlaky:y,retryStatus:b,expectedStatus:T,actualStatus:v,artifacts:k,apiAssertions:d.apiAssertions,actions:A,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},it=d.consoleLogsFile&&d.consoleLogsCount>0?z(d.consoleLogsFile):void 0,ot=d.networkRequestsFile&&d.networkRequestsCount>0?z(d.networkRequestsFile):void 0;this.cloudTestsBuffer.push({testId:h,title:u,status:n,duration:a.duration,suiteName:c,filePath:g,testType:S,isFlaky:y,startedAt:o,completedAt:i,tags:l,failure:p,retry:a.retry,retryCount:t.results.length-1,retryStatus:b,browser:q,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...A&&A.length>0?{actions:A}:{},...it?{consoleLogs:it}:{},...ot?{networkRequests:ot}:{}});try{let R=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(R==="realtime"||R==="both")){let C=this.cloudClient.getAccessToken();C&&Tr(this.cloudClient.getEndpoint(),C,this.cloudRunId,this.buildCloudTestPayload(M));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let R=ye(g,f,t.id??"",a.retry),C=a.retry===t.results.length-1,B={id:R,navigations:d.navigations,apiAssertions:d.apiAssertions,actions:A??[],artifacts:k,failureDiagnostic:p,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(R,B,{networkRequestsFile:d.networkRequestsFile,consoleLogsFile:d.consoleLogsFile,apiCallsFile:d.apiCallsFile});let $={id:R,title:f[f.length-1]??t.title,titlePath:f,filePath:g,status:n,duration:a.duration,project:f[1]??"",retryIndex:a.retry,tags:l,hasNetworkData:d.networkRequestsCount>0,hasConsoleData:d.consoleLogsCount>0,hasArtifacts:k!==null,hasActionSteps:(A?.length??0)>0,errorMessage:p?.message?.split(`
2580
+ `),{navigations:s,apiAssertions:n,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:l,consoleLogsCount:d,apiCallsFile:u,apiCallsCount:f}}function ge(e=process.env){let t=Ps(e.TESTRELIC_CLOUD_PLATFORM);if(t)return {cloudPlatform:t,cloudBuildId:e.TESTRELIC_CLOUD_BUILD_ID||void 0,cloudSessionId:e.TESTRELIC_CLOUD_SESSION_ID||void 0};if(e.BROWSERSTACK_USERNAME||e.BROWSERSTACK_ACCESS_KEY)return {cloudPlatform:"browserstack",cloudBuildId:e.BROWSERSTACK_BUILD_NAME||e.BROWSERSTACK_BUILD_ID||void 0,cloudSessionId:e.BROWSERSTACK_SESSION_ID||void 0};if(e.LT_USERNAME||e.LAMBDATEST_USERNAME||e.LT_ACCESS_KEY||e.LAMBDATEST_ACCESS_KEY)return {cloudPlatform:"lambdatest",cloudBuildId:e.LT_BUILD||e.LAMBDATEST_BUILD||void 0,cloudSessionId:e.LT_SESSION_ID||e.LAMBDATEST_SESSION_ID||void 0};let r=e.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 Ps(e){if(!e)return;let t=e.toLowerCase().trim();if(t==="browserstack"||t==="bs")return "browserstack";if(t==="lambdatest"||t==="lt")return "lambdatest"}var Os=5,he=[1e3,3e3,9e3],U=3,qs={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip"},et=0,tt=[];async function Hs(){et>=Os&&await new Promise(e=>tt.push(e)),et++;}function Us(){et--,tt.length>0&&tt.shift()();}async function me(e){return new Promise(t=>setTimeout(t,e))}function zs(e){let t=e.substring(e.lastIndexOf(".")).toLowerCase();return qs[t]??"application/octet-stream"}function $s(e){try{return statSync(e).size}catch{return 0}}async function js(e,t,r,a,s){let n=`${e}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:basename(r.filePath),contentType:s,type:r.type,sizeBytes:a});for(let i=0;i<U;i++)try{let l=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:o});if(l.ok)return await l.json();if(l.status>=500&&i<U-1){await me(he[i]);continue}return null}catch{if(i<U-1){await me(he[i]);continue}return null}return null}async function Vs(e,t,r,a){for(let s=0;s<U;s++)try{let n=createReadStream(t),o=Readable.toWeb(n),i=await fetch(e,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(a)},body:o,duplex:"half"});if(i.ok)return !0;if(i.status>=500&&s<U-1){await me(he[s]);continue}return !1}catch{if(s<U-1){await me(he[s]);continue}return false}return false}async function Gs(e,t,r){let a=`${e}/artifacts/confirm`;try{return (await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function Ws(e,t,r,a){let s=$s(r.filePath);if(s===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(s>a*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let n=zs(r.filePath);await Hs();try{let o=await js(e,t,r,s,n);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Vs(o.uploadUrl,r.filePath,n,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let l=await Gs(e,t,o.artifactId);return {success:l,storageKey:o.storageKey,artifactId:o.artifactId,error:l?null:"confirm_failed"}}finally{Us();}}async function Rr(e,t,r,a){let s=new Map,n=r.map(async o=>{let i=await Ws(e,t,o,a);s.set(o.filePath,i);});return await Promise.allSettled(n),s}function rt(e){let r=e.getGitMetadata()?.remoteUrl;return r?Z(r):e.getConfig()?.projectName??Q(process.cwd())}async function _r(e,t,r,a,s){if(!e.isCloudMode()||t!=="realtime"&&t!=="both"||!await e.ensureValidToken())return null;let o=e.getGitMetadata(),i=P(),l=ge(),d=ce();return (await kr(e.getEndpoint(),e.getAccessToken(),{runId:r,repoGitId:rt(e),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:a,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 Ks=true,Js=50;async function Ys(e,t,r,a){let s=new Map;if(!(t?.uploadArtifacts??Ks)||!await e.ensureValidToken())return s;let i=[],l=new Map;for(let c of a){if(c.artifacts.screenshot){let p=join(c.outputDir,c.artifacts.screenshot);i.push({filePath:p,runId:r,testId:c.testId,type:"screenshot"}),l.set(p,{testId:c.testId,field:"screenshot"});}if(c.artifacts.video){let p=join(c.outputDir,c.artifacts.video);i.push({filePath:p,runId:r,testId:c.testId,type:"video"}),l.set(p,{testId:c.testId,field:"video"});}}if(i.length===0)return s;let d=t?.artifactMaxSizeMb??Js,u=await Rr(e.getEndpoint(),e.getAccessToken(),i,d),f=new Map;for(let[c,p]of u){if(!p.success||!p.storageKey)continue;let g=l.get(c);if(!g)continue;let h=f.get(g.testId)??{};g.field==="screenshot"&&(h.screenshotKey=p.storageKey),g.field==="video"&&(h.videoKey=p.storageKey),f.set(g.testId,h);}for(let c of a){let p=f.get(c.testId);s.set(c.testId,{...c.artifacts,...p?.screenshotKey?{screenshotKey:p.screenshotKey}:{},...p?.videoKey?{videoKey:p.videoKey}:{}});}let m=Array.from(u.values()).filter(c=>c.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
2581
+ `),s}async function at(e,t,r,a,s,n,o,i,l,d,u){try{if(e.isCloudMode()&&s&&(r==="realtime"||r==="both")){let m=await e.ensureValidToken(),c=e.getGitMetadata(),p=Ze(u),g={finishedAt:o,duration:i,summary:l,...c?.commitMessage?{commitMessage:c.commitMessage}:{},testType:p.testType,...p.testType==="api"?{apiProtocol:p.apiProtocol,metadata:p.metadata}:{}};if(m){if(!await Sr(e.getEndpoint(),e.getAccessToken(),s,g)){let w=t?.queueDirectory??".testrelic/queue";X(w,a,"finalize","finalize_failed_after_retries",`${e.getEndpoint()}/runs/${s}/finalize`,"POST",g,{"Content-Type":"application/json"});}}else {let h=t?.queueDirectory??".testrelic/queue";X(h,a,"finalize",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs/${s}/finalize`,"POST",g,{"Content-Type":"application/json"});}}let f=new Map;if(e.isCloudMode()&&d&&d.length>0&&(f=await Ys(e,t,a,d)),e.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await e.ensureValidToken()){let c=e.getGitMetadata(),p=P(),g=rt(e),h=Zs(n,f),w=Qe(h,g,c,p,u,ge()),S=await wr(e.getEndpoint(),e.getAccessToken(),w,async()=>await e.ensureValidToken()?e.getAccessToken():null);if(!S.success){let y=S,b=t?.queueDirectory??".testrelic/queue";X(b,a,"batch",y.reason,y.targetEndpoint,y.method,y.payload,{"Content-Type":"application/json"});}}else {let c=t?.queueDirectory??".testrelic/queue",p=e.getGitMetadata(),g=P(),h=rt(e),w=Qe(n,h,p,g,void 0,ge());X(c,a,"batch",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs`,"POST",w,{"Content-Type":"application/json"});}await e.dispose();}catch{try{await e.dispose();}catch{}}}function Zs(e,t){if(t.size===0)return e;let r=e.timeline.map(a=>{let s=a.testId;if(!s)return a;let n=t.get(s);return n?{...a,...n.screenshotKey?{screenshotKey:n.screenshotKey}:{},...n.videoKey?{videoKey:n.videoKey}:{}}:a});return {...e,timeline:r}}function z(e){try{return readFileSync(e,"utf-8").split(`
2582
+ `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function nt(e){switch(e){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function sn(e,t,r){let a=`${e}::${t}::${r}`;return createHash("sha256").update(a).digest("hex").substring(0,16)}function nn(e){return e.length<=3?"":e[e.length-2]}function on(e){let t=e.findIndex(r=>r.status==="passed");return t>0?`passed on retry ${t}`:null}function ln(e){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":e?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[e.provider]??"CI":"Local"}function dn(){let e=platform();return e==="win32"?"Windows":e==="darwin"?"macOS":"Linux"}function cn(e){let t=e.parent?.project?.()?.use;if(!t)return;let{browserName:r,channel:a}=t;if(a){let n=a.toLowerCase();return n==="chrome"||n==="chrome-stable"?"Chrome":n.startsWith("chrome-beta")?"Chrome Beta":n.startsWith("chrome-dev")?"Chrome Dev":n.startsWith("chrome-canary")?"Chrome Canary":n==="msedge"||n==="msedge-stable"?"Microsoft Edge":n.startsWith("msedge-beta")?"Edge Beta":n.startsWith("msedge-dev")?"Edge Dev":n.startsWith("msedge-canary")?"Edge Canary":a}if(r){let n=r.toLowerCase();return n==="chromium"?"Chromium":n==="firefox"?"Firefox":n==="webkit"?"WebKit":r}let s=t.defaultBrowserType;if(s){let n=s.toLowerCase();return n==="chromium"?"Chromium":n==="firefox"?"Firefox":n==="webkit"?"WebKit":s}}function pn(e,t,r){let a=r.parent?.project?.(),s="unknown";a!==void 0&&(a.use.isMobile===true?s="mobile":s="e2e");let n=["e2e","api","unit","mobile"];for(let l of n)if(e.some(d=>d===`@${l}`||d===l))return l;let o=t.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let l of i)if(o.includes(`/${l}/`))return l;return s}var un="__testrelic_api_config";function fn(e){return JSON.stringify(e,(t,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var ve=class{constructor(t){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=wt(t),this.apiConfig=xt(t);}async onBegin(t,r){try{if(this.rootDir=t.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??randomUUID(),this.config.reportMode==="auto"){let n=r.allTests().length;this.activeReportMode=n>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let a=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${a} tests)
2583
+ `),this.activeReportMode==="streaming"){let n=dirname(this.config.outputPath);this.streamingWriter=new G(n);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&&Xe(this.cloudClient.getEndpoint(),i,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",o),process.on("SIGINT",o);}if(this.config.includeArtifacts){let n=dirname(this.config.outputPath);this.runTimestamp=Yt(join(n,"artifacts"));try{tr(join(n,"artifacts"));}catch{}}let s=P();this.detectedOs=dn(),this.detectedSource=ln(s);try{this.cloudClient=new de(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await _r(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource);}catch{this.cloudClient?.switchToLocalMode("init_error");}if(this.activeReportMode!=="streaming"){let n=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let o=this.cloudClient.getAccessToken();o&&Xe(this.cloudClient.getEndpoint(),o,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",n),process.on("SIGINT",n);}}catch{}}onTestBegin(t,r){try{t.annotations.push({type:un,description:fn(this.apiConfig)});}catch{}}onTestEnd(t,r){try{let a=r,s=t.outcome(),n;s==="flaky"?n="flaky":s==="skipped"?n="skipped":n=nt(a.status);let o=a.startTime.toISOString(),i=new Date(a.startTime.getTime()+a.duration).toISOString(),l=t.tags?[...t.tags]:t.annotations.filter(R=>R.type==="tag").map(R=>R.description??""),d=Cr(a.attachments,t.annotations,t.title,n==="skipped");(d.navigations.length>0||d.networkRequestsCount>0||d.apiCallsCount>0)&&(this.fixtureDataReceived=!0);let u=null;if(n==="failed"||n==="flaky"){let C=(n==="flaky"?t.results.find(B=>B.status!=="passed")?.errors??[]:a.errors)[0];if(C){let B=Tt(this.config.redactPatterns),$=C.location?.line??null,j=null;this.config.includeCodeSnippets&&$!==null&&C.location?.file&&(j=kt(C.location.file,$,this.config.codeContextLines),j&&(j=B(j))),u={message:B(C.message??"Unknown error"),line:$,code:j,stack:this.config.includeStackTrace&&C.stack?B(C.stack):null};}}let f=t.titlePath().filter(Boolean),m=relative(this.rootDir||".",t.location.file),c=nn(f),p=f.join(" > "),g=m,h=sn(g,c,p),w=pn(l,g,t),S=w!=="mobile"&&d.apiCallsCount>0?"api":w,y=s==="flaky",b=on(t.results),T=nt(t.expectedStatus),v=nt(a.status),k=null;if(this.config.includeArtifacts&&n!=="skipped"&&a.attachments){let R=dirname(this.config.outputPath),C=f[f.length-1]??t.title;k=Zt(a.attachments,C,a.retry,R,this.runTimestamp||void 0);}let A=this.config.includeActionSteps&&a.steps?ir(a.steps,a.startTime):null,q=cn(t),M={titlePath:f,title:p,status:n,duration:a.duration,startedAt:o,completedAt:i,retryCount:t.results.length-1,retry:a.retry,tags:l,failure:u,specFile:m,navigations:d.navigations,testId:h,filePath:g,suiteName:c,testType:S,isFlaky:y,retryStatus:b,expectedStatus:T,actualStatus:v,artifacts:k,apiAssertions:d.apiAssertions,actions:A,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},it=d.consoleLogsFile&&d.consoleLogsCount>0?z(d.consoleLogsFile):void 0,ot=d.networkRequestsFile&&d.networkRequestsCount>0?z(d.networkRequestsFile):void 0;this.cloudTestsBuffer.push({testId:h,title:p,status:n,duration:a.duration,suiteName:c,filePath:g,testType:S,isFlaky:y,startedAt:o,completedAt:i,tags:l,failure:u,retry:a.retry,retryCount:t.results.length-1,retryStatus:b,browser:q,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...A&&A.length>0?{actions:A}:{},...it?{consoleLogs:it}:{},...ot?{networkRequests:ot}:{}});try{let R=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(R==="realtime"||R==="both")){let C=this.cloudClient.getAccessToken();C&&Tr(this.cloudClient.getEndpoint(),C,this.cloudRunId,this.buildCloudTestPayload(M));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let R=ye(g,f,t.id??"",a.retry),C=a.retry===t.results.length-1,B={id:R,navigations:d.navigations,apiAssertions:d.apiAssertions,actions:A??[],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(R,B,{networkRequestsFile:d.networkRequestsFile,consoleLogsFile:d.consoleLogsFile,apiCallsFile:d.apiCallsFile});let $={id:R,title:f[f.length-1]??t.title,titlePath:f,filePath:g,status:n,duration:a.duration,project:f[1]??"",retryIndex:a.retry,tags:l,hasNetworkData:d.networkRequestsCount>0,hasConsoleData:d.consoleLogsCount>0,hasArtifacts:k!==null,hasActionSteps:(A?.length??0)>0,errorMessage:u?.message?.split(`
2584
2584
  `)[0]??null,networkCount:d.networkRequestsCount,consoleCount:d.consoleLogsCount,actionCount:A?.length??0,isRetry:!C};if(this.testIndex.push($),C)switch(this.summaryCounters.total++,n){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+=A?.length??0,k&&this.pendingArtifactEntries.push({testId:h,artifacts:k,outputDir:dirname(this.config.outputPath)}),M.actions=null,M.apiAssertions=null,M.navigations=[],M.artifacts=null,M.failure=null,M.networkRequestsFile=null,M.consoleLogsFile=null,M.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(M),this.testCount++,this.checkMemoryPressure();}catch{}}async onEnd(t){try{let r=new Date().toISOString(),a=new Date(this.startedAt).getTime(),n=new Date(r).getTime()-a,o=this.activeReportMode==="streaming"?this.testIndex.some(l=>l.status!=="skipped"):this.collectedTests.some(l=>l.status!=="skipped");!this.fixtureDataReceived&&o&&process.stderr.write(`
2585
2585
  \u26A0 TestRelic: No fixture data received from any test.
2586
2586
  To enable network logs, video sync, and timeline tracking, import the TestRelic fixture:
@@ -2588,8 +2588,8 @@ ${s}
2588
2588
  instead of:
2589
2589
  import { test, expect } from '@playwright/test';
2590
2590
 
2591
- `),await Jt();let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let l=dirname(this.config.outputPath);i=Xt(l,this.runTimestamp);let d=join(l,"artifact-manifest.json"),p=JSON.stringify(i),f=d+".tmp";writeFileSync(f,p,"utf-8"),renameSync(f,d);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await this.finalizeStreamingReport(r,n,t,i);else {let l=this.buildTimeline(),d=new Map;for(let c of this.collectedTests){let u=d.get(c.testId);(!u||c.retry>u.retry)&&d.set(c.testId,c);}let p=Array.from(d.values()),f=nr(p,l.length),m={schemaVersion:xe,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:n,summary:f,ci:P(),metadata:this.config.metadata,timeline:l,shardRunIds:null};if(this.writeReport(m),await Ne(m,this.config,i),ze(f,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let c=this.collectArtifactEntries(),u=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await at(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,m,r,n,f,c,u);}}}catch{}}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let t=dirname(this.config.outputPath),r=[];for(let a of this.collectedTests)a.artifacts&&r.push({testId:a.testId,artifacts:a.artifacts,outputDir:t});return r}async finalizeStreamingReport(t,r,a,s){if(!this.streamingWriter)return;let{totalApiCalls:n,totalAssertions:o,totalNavigations:i,totalNetworkRequests:l,totalConsoleLogs:d,totalActionSteps:p}=this.summaryCounters;this.summaryCounters={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0,interrupted:0,totalApiCalls:n,totalAssertions:o,totalNavigations:i,totalNetworkRequests:l,totalConsoleLogs:d,totalActionSteps:p};let f=new Map,m=new Map;for(let b of this.testIndex){let T=`${b.filePath}::${b.titlePath.join(" > ")}`,v=f.get(T);(v===void 0||b.retryIndex>v)&&f.set(T,b.retryIndex);}let c=0;for(let b of this.testIndex){let T=`${b.filePath}::${b.titlePath.join(" > ")}`,v=f.get(T);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=m.get(b.filePath);switch(k||(k={filePath:b.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},m.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 u=Array.from(m.values());this.streamingWriter.writeIndex(this.testIndex),this.streamingWriter.writeCompactIndex(this.testIndex);let g={reporterTotal:this.summaryCounters.total,indexTotal:c,playwrightStatus:a.status,isValid:this.summaryCounters.total===c};g.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${g.reporterTotal}, index: ${g.indexTotal}
2592
- `);let h={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:t,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:u,enrichedSummary:h,validation:g,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(w);let S={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(S),await Ne(this.buildStreamingReport(w,h,t,r),this.config,s),ze(h,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let y=this.streamingWriter.getReportDir();if(process.stderr.write(`[testrelic] Streaming report written to ${y}
2591
+ `),await Jt();let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let l=dirname(this.config.outputPath);i=Xt(l,this.runTimestamp);let d=join(l,"artifact-manifest.json"),u=JSON.stringify(i),f=d+".tmp";writeFileSync(f,u,"utf-8"),renameSync(f,d);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await this.finalizeStreamingReport(r,n,t,i);else {let l=this.buildTimeline(),d=new Map;for(let c of this.collectedTests){let p=d.get(c.testId);(!p||c.retry>p.retry)&&d.set(c.testId,c);}let u=Array.from(d.values()),f=nr(u,l.length),m={schemaVersion:xe,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:n,summary:f,ci:P(),metadata:this.config.metadata,timeline:l,shardRunIds:null};if(this.writeReport(m),await Ne(m,this.config,i),ze(f,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let c=this.collectArtifactEntries(),p=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await at(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,m,r,n,f,c,p);}}}catch{}}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let t=dirname(this.config.outputPath),r=[];for(let a of this.collectedTests)a.artifacts&&r.push({testId:a.testId,artifacts:a.artifacts,outputDir:t});return r}async finalizeStreamingReport(t,r,a,s){if(!this.streamingWriter)return;let{totalApiCalls:n,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:n,totalAssertions:o,totalNavigations:i,totalNetworkRequests:l,totalConsoleLogs:d,totalActionSteps:u};let f=new Map,m=new Map;for(let b of this.testIndex){let T=`${b.filePath}::${b.titlePath.join(" > ")}`,v=f.get(T);(v===void 0||b.retryIndex>v)&&f.set(T,b.retryIndex);}let c=0;for(let b of this.testIndex){let T=`${b.filePath}::${b.titlePath.join(" > ")}`,v=f.get(T);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=m.get(b.filePath);switch(k||(k={filePath:b.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},m.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 p=Array.from(m.values());this.streamingWriter.writeIndex(this.testIndex),this.streamingWriter.writeCompactIndex(this.testIndex);let g={reporterTotal:this.summaryCounters.total,indexTotal:c,playwrightStatus:a.status,isValid:this.summaryCounters.total===c};g.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${g.reporterTotal}, index: ${g.indexTotal}
2592
+ `);let h={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:t,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:p,enrichedSummary:h,validation:g,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(w);let S={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(S),await Ne(this.buildStreamingReport(w,h,t,r),this.config,s),ze(h,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let y=this.streamingWriter.getReportDir();if(process.stderr.write(`[testrelic] Streaming report written to ${y}
2593
2593
  [testrelic] ${this.testIndex.length} test detail files on disk
2594
2594
  [testrelic] View report: npx testrelic serve ${y}
2595
2595
  `),this.streamingWriter.getWriteErrors().length>0&&process.stderr.write(`[testrelic] WARNING: ${this.streamingWriter.getWriteErrors().length} write error(s) during streaming