@testrelic/playwright-analytics 2.16.1-next.132 → 2.16.1-next.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {randomUUID,createHash}from'crypto';import {writeFileSync,existsSync,mkdirSync,openSync,writeSync,closeSync,unlinkSync,readFileSync,renameSync,appendFileSync,readdirSync,statSync,readSync,createReadStream,rmSync}from'fs';import {join,extname,basename,dirname,resolve,relative}from'path';import {tmpdir,platform}from'os';import {PAYLOAD_VERSION,ATTACHMENT_NAME,ATTACHMENT_CONTENT_TYPE,isValidConfig,createError,ErrorCode,isTestRelicFilePayload,isTestRelicDataPayload,isValidEndpointUrl,isValidCloudConfig,isValidQueueEntry}from'@testrelic/core';export{ATTACHMENT_CONTENT_TYPE,ATTACHMENT_NAME,PAYLOAD_VERSION,isTestRelicDataPayload}from'@testrelic/core';import {spawn,execFile,execSync}from'child_process';import {createServer}from'http';import {createInterface}from'readline';import {copyFile}from'fs/promises';import {gzip}from'zlib';import {promisify}from'util';import {Readable}from'stream';import {expect,test,defineConfig}from'@playwright/test';import {performance}from'perf_hooks';import {fileURLToPath}from'url';var ia=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var la=".testrelic-report";function et(t,e,r,n){let s=`${t}|${e.join("|")}|${r}|${n}`;return createHash("sha256").update(s).digest("hex").substring(0,12)}function tt(t,e,r){let n=`${t}|${e.join("|")}|${r}`;return createHash("sha256").update(n).digest("hex").substring(0,12)}var he=class{constructor(e){this.writeErrors=[];this.totalBytesWritten=0;this.reportDir=join(e,la),this.testsDir=join(this.reportDir,"tests"),mkdirSync(this.testsDir,{recursive:true});}getReportDir(){return this.reportDir}getWriteErrors(){return this.writeErrors}writeTestDetail(e,r,n){try{let s=join(this.testsDir,e);mkdirSync(s,{recursive:!0});let a=join(s,"meta.json"),o=a+".tmp",i=JSON.stringify(r);return writeFileSync(o,i,"utf-8"),renameSync(o,a),this.totalBytesWritten+=Buffer.byteLength(i,"utf-8"),n?.networkRequestsFile&&this.moveFile(n.networkRequestsFile,join(s,"network.jsonl")),n?.consoleLogsFile&&this.moveFile(n.consoleLogsFile,join(s,"console.jsonl")),n?.apiCallsFile&&this.moveFile(n.apiCallsFile,join(s,"api-calls.jsonl")),!0}catch(s){let a=s instanceof Error?s.message:String(s);return this.writeErrors.push({testId:e,error:a,timestamp:new Date().toISOString()}),process.stderr.write(`[testrelic] Failed to write test detail for ${e}: ${a}
2
2
  `),false}}moveFile(e,r){try{renameSync(e,r);}catch{try{let{copyFileSync:n}=ia("fs");n(e,r);try{unlinkSync(e);}catch{}}catch(n){process.stderr.write(`[testrelic] Failed to move file ${e} \u2192 ${r}: ${n instanceof Error?n.message:String(n)}
3
- `);}}}writeIndex(e){let r=join(this.reportDir,"index.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeCompactIndex(e){let r=join(this.reportDir,"index-compact.json"),n=r+".tmp",s=e.map(({titlePath:o,project:i,...d})=>d),a=JSON.stringify(s);writeFileSync(n,a,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(a,"utf-8");}writeSummary(e){let r=join(this.reportDir,"summary.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeManifest(e){let r=join(this.reportDir,"manifest.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var Lr=".testrelic",ga="testrelic-config.json",ha=".testrelic",ma=5,va=new Set(["__proto__","constructor","prototype"]),Er=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,uploadBudgetMs:12e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${Lr}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),ya={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function Nr(t){let e=resolve(t);for(let r=0;r<=ma;r++){let n=join(e,Lr,ga);if(existsSync(n))try{if(statSync(n).isFile())return n}catch{}let s=join(e,ha);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 a=dirname(e);if(a===e)break;e=a;}return null}function Dr(t){try{let e=readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!Fr(r)?null:r}catch{return null}}function Fr(t){for(let e of Object.keys(t)){if(va.has(e))return false;let r=t[e];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!Fr(r))return false}return true}function Br(t){let e=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(t);if(e)return process.env[e[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(t);return r?process.env[r[1]]??null:t}function rt(t){let e=Object.create(null);for(let r of Object.keys(t)){let n=t[r];typeof n=="string"&&n.startsWith("$")?e[r]=Br(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?e[r]=rt(n):e[r]=n;}return e}function Pr(t){let e=/^(\d+)\s*([smhd])$/.exec(t.trim());if(!e)return null;let r=parseInt(e[1],10),n=e[2],s=ya[n];return !s||r<=0?null:r*s}function Or(t,e){let r=Object.create(null);if(Object.assign(r,Er),t){let d=t.cloud;d&&typeof d=="object"&&(typeof d.endpoint=="string"&&(r.endpoint=d.endpoint),typeof d.upload=="string"&&(r.uploadStrategy=d.upload),typeof d.timeout=="number"&&(r.timeout=d.timeout),typeof d.uploadBudgetMs=="number"&&(r.uploadBudgetMs=d.uploadBudgetMs),typeof d.apiKey=="string"&&d.apiKey.length>0&&(r.apiKey=d.apiKey));let l=t["testrelic-repo"]??t.project;l&&typeof l=="object"&&typeof l.name=="string"&&(r.projectName=l.name),t.project&&!t["testrelic-repo"]&&process.stderr.write(`[testrelic] Deprecation: "project" key in config is deprecated. Rename it to "testrelic-repo".
5
- `);let c=t.queue;if(c&&typeof c=="object"){if(typeof c.maxAge=="string"){let u=Pr(c.maxAge);u!==null&&(r.queueMaxAge=u);}typeof c.directory=="string"&&(r.queueDirectory=c.directory);}}if(e){if(typeof e.apiKey=="string"&&e.apiKey.length>0){let d=e.apiKey.startsWith("$")?Br(e.apiKey):e.apiKey;d&&(r.apiKey=d);}if(typeof e.endpoint=="string"&&(r.endpoint=e.endpoint),typeof e.upload=="string"&&(r.uploadStrategy=e.upload),typeof e.timeout=="number"&&(r.timeout=e.timeout),typeof e.uploadBudgetMs=="number"&&(r.uploadBudgetMs=e.uploadBudgetMs),typeof e.projectName=="string"&&(r.projectName=e.projectName),typeof e.queueMaxAge=="string"){let d=Pr(e.queueMaxAge);d!==null&&(r.queueMaxAge=d);}typeof e.queueDirectory=="string"&&(r.queueDirectory=e.queueDirectory),typeof e.uploadArtifacts=="boolean"&&(r.uploadArtifacts=e.uploadArtifacts),typeof e.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=e.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&isValidEndpointUrl(s)&&(r.endpoint=s);let a=process.env.TESTRELIC_UPLOAD_STRATEGY;a&&["batch","realtime","both"].includes(a)&&(r.uploadStrategy=a);let o=process.env.TESTRELIC_CLOUD_TIMEOUT;if(o){let d=parseInt(o,10);!isNaN(d)&&d>=1e3&&d<=12e4&&(r.timeout=d);}let i=Object.freeze(r);return isValidCloudConfig(i)?i:Er}var ka=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Ca=["authorization","cookie","set-cookie","x-api-key"],Ta=["password","secret","token","apiKey","api_key"];function qr(t){let e=Object.create(null);return e.trackApiCalls=t?.trackApiCalls??true,e.captureRequestHeaders=t?.captureRequestHeaders??true,e.captureResponseHeaders=t?.captureResponseHeaders??true,e.captureRequestBody=t?.captureRequestBody??true,e.captureResponseBody=t?.captureResponseBody??true,e.captureAssertions=t?.captureAssertions??true,e.redactHeaders=t?.redactHeaders??[...Ca],e.redactBodyFields=t?.redactBodyFields??[...Ta],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function Ur(t){if(t!==void 0&&!isValidConfig(t))throw createError(ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let e=Object.create(null);e.outputPath=t?.outputPath??"./test-results/analytics-timeline.json",e.includeStackTrace=t?.includeStackTrace??false,e.includeCodeSnippets=t?.includeCodeSnippets??true,e.codeContextLines=t?.codeContextLines??3,e.includeNetworkStats=t?.includeNetworkStats??true,e.captureNavigation=t?.captureNavigation??true,e.navigationTypes=t?.navigationTypes??null,e.redactPatterns=[...ka,...t?.redactPatterns??[]],e.testRunId=t?.testRunId??null,e.metadata=t?.metadata??null;let r=e.outputPath;e.openReport=t?.openReport??true,e.htmlReportPath=t?.htmlReportPath??r.replace(/\.json$/,".html"),e.includeArtifacts=t?.includeArtifacts??true,e.trackApiCalls=t?.trackApiCalls??true,e.quiet=t?.quiet??false,e.includeActionSteps=t?.includeActionSteps??true,e.captureConsoleLogs=t?.captureConsoleLogs??true;let n=Nr(process.cwd()),s=n?Dr(n):null,a=s?rt(s):null,o=Or(a,t?.cloud);return e.cloud=o.apiKey?o:null,e.reportMode=t?.reportMode??"streaming",e.streamingThreshold=t?.streamingThreshold??0,Object.freeze(e)}var Ce="1.6.0";function Hr(t,e,r){try{let s=readFileSync(t,"utf-8").split(`
3
+ `);}}}writeIndex(e){let r=join(this.reportDir,"index.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeCompactIndex(e){let r=join(this.reportDir,"index-compact.json"),n=r+".tmp",s=e.map(({titlePath:o,project:i,...d})=>d),a=JSON.stringify(s);writeFileSync(n,a,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(a,"utf-8");}writeSummary(e){let r=join(this.reportDir,"summary.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}writeManifest(e){let r=join(this.reportDir,"manifest.json"),n=r+".tmp",s=JSON.stringify(e);writeFileSync(n,s,"utf-8"),renameSync(n,r),this.totalBytesWritten+=Buffer.byteLength(s,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var Lr=".testrelic",ga="testrelic-config.json",ha=".testrelic",ma=5,va=new Set(["__proto__","constructor","prototype"]),Pr=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,uploadBudgetMs:12e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${Lr}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),ya={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function Nr(t){let e=resolve(t);for(let r=0;r<=ma;r++){let n=join(e,Lr,ga);if(existsSync(n))try{if(statSync(n).isFile())return n}catch{}let s=join(e,ha);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 a=dirname(e);if(a===e)break;e=a;}return null}function Dr(t){try{let e=readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!Fr(r)?null:r}catch{return null}}function Fr(t){for(let e of Object.keys(t)){if(va.has(e))return false;let r=t[e];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!Fr(r))return false}return true}function Br(t){let e=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(t);if(e)return process.env[e[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(t);return r?process.env[r[1]]??null:t}function rt(t){let e=Object.create(null);for(let r of Object.keys(t)){let n=t[r];typeof n=="string"&&n.startsWith("$")?e[r]=Br(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?e[r]=rt(n):e[r]=n;}return e}function Er(t){let e=/^(\d+)\s*([smhd])$/.exec(t.trim());if(!e)return null;let r=parseInt(e[1],10),n=e[2],s=ya[n];return !s||r<=0?null:r*s}function Or(t,e){let r=Object.create(null);if(Object.assign(r,Pr),t){let d=t.cloud;d&&typeof d=="object"&&(typeof d.endpoint=="string"&&(r.endpoint=d.endpoint),typeof d.upload=="string"&&(r.uploadStrategy=d.upload),typeof d.timeout=="number"&&(r.timeout=d.timeout),typeof d.uploadBudgetMs=="number"&&(r.uploadBudgetMs=d.uploadBudgetMs),typeof d.apiKey=="string"&&d.apiKey.length>0&&(r.apiKey=d.apiKey));let l=t["testrelic-repo"]??t.project;l&&typeof l=="object"&&typeof l.name=="string"&&(r.projectName=l.name),t.project&&!t["testrelic-repo"]&&process.stderr.write(`[testrelic] Deprecation: "project" key in config is deprecated. Rename it to "testrelic-repo".
5
+ `);let c=t.queue;if(c&&typeof c=="object"){if(typeof c.maxAge=="string"){let u=Er(c.maxAge);u!==null&&(r.queueMaxAge=u);}typeof c.directory=="string"&&(r.queueDirectory=c.directory);}}if(e){if(typeof e.apiKey=="string"&&e.apiKey.length>0){let d=e.apiKey.startsWith("$")?Br(e.apiKey):e.apiKey;d&&(r.apiKey=d);}if(typeof e.endpoint=="string"&&(r.endpoint=e.endpoint),typeof e.upload=="string"&&(r.uploadStrategy=e.upload),typeof e.timeout=="number"&&(r.timeout=e.timeout),typeof e.uploadBudgetMs=="number"&&(r.uploadBudgetMs=e.uploadBudgetMs),typeof e.projectName=="string"&&(r.projectName=e.projectName),typeof e.queueMaxAge=="string"){let d=Er(e.queueMaxAge);d!==null&&(r.queueMaxAge=d);}typeof e.queueDirectory=="string"&&(r.queueDirectory=e.queueDirectory),typeof e.uploadArtifacts=="boolean"&&(r.uploadArtifacts=e.uploadArtifacts),typeof e.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=e.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let s=process.env.TESTRELIC_CLOUD_ENDPOINT;s&&isValidEndpointUrl(s)&&(r.endpoint=s);let a=process.env.TESTRELIC_UPLOAD_STRATEGY;a&&["batch","realtime","both"].includes(a)&&(r.uploadStrategy=a);let o=process.env.TESTRELIC_CLOUD_TIMEOUT;if(o){let d=parseInt(o,10);!isNaN(d)&&d>=1e3&&d<=12e4&&(r.timeout=d);}let i=Object.freeze(r);return isValidCloudConfig(i)?i:Pr}var ka=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Ca=["authorization","cookie","set-cookie","x-api-key"],Ta=["password","secret","token","apiKey","api_key"];function qr(t){let e=Object.create(null);return e.trackApiCalls=t?.trackApiCalls??true,e.captureRequestHeaders=t?.captureRequestHeaders??true,e.captureResponseHeaders=t?.captureResponseHeaders??true,e.captureRequestBody=t?.captureRequestBody??true,e.captureResponseBody=t?.captureResponseBody??true,e.captureAssertions=t?.captureAssertions??true,e.redactHeaders=t?.redactHeaders??[...Ca],e.redactBodyFields=t?.redactBodyFields??[...Ta],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function Hr(t){if(t!==void 0&&!isValidConfig(t))throw createError(ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let e=Object.create(null);e.outputPath=t?.outputPath??"./test-results/analytics-timeline.json",e.includeStackTrace=t?.includeStackTrace??false,e.includeCodeSnippets=t?.includeCodeSnippets??true,e.codeContextLines=t?.codeContextLines??3,e.includeNetworkStats=t?.includeNetworkStats??true,e.captureNavigation=t?.captureNavigation??true,e.navigationTypes=t?.navigationTypes??null,e.redactPatterns=[...ka,...t?.redactPatterns??[]],e.testRunId=t?.testRunId??null,e.metadata=t?.metadata??null;let r=e.outputPath;e.openReport=t?.openReport??true,e.htmlReportPath=t?.htmlReportPath??r.replace(/\.json$/,".html"),e.includeArtifacts=t?.includeArtifacts??true,e.trackApiCalls=t?.trackApiCalls??true,e.quiet=t?.quiet??false,e.includeActionSteps=t?.includeActionSteps??true,e.captureConsoleLogs=t?.captureConsoleLogs??true;let n=Nr(process.cwd()),s=n?Dr(n):null,a=s?rt(s):null,o=Or(a,t?.cloud);return e.cloud=o.apiKey?o:null,e.reportMode=t?.reportMode??"streaming",e.streamingThreshold=t?.streamingThreshold??0,Object.freeze(e)}var Ce="1.7.0";function Ur(t,e,r){try{let s=readFileSync(t,"utf-8").split(`
6
6
  `);if(e<1||e>s.length)return null;let a=Math.max(1,e-r),o=Math.min(s.length,e+r),i=[];for(let d=a;d<=o;d++){let l=d===e?">":" ",c=String(d).padStart(String(o).length," ");i.push(`${l} ${c} | ${s[d-1]}`);}return i.join(`
7
- `)}catch{return null}}function zr(t){return e=>{let r=e;for(let n of t)if(typeof n=="string"){let s=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(s,"g"),"[REDACTED]");}else {let s=n.flags.includes("g")?n.flags:n.flags+"g",a=new RegExp(n.source,s);r=r.replace(a,"[REDACTED]");}return r}}function Ra(t){return t.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:t.GITHUB_RUN_ID??null,commitSha:t.GITHUB_SHA??null,branch:t.GITHUB_REF_NAME??null,runUrl:t.GITHUB_SERVER_URL&&t.GITHUB_REPOSITORY&&t.GITHUB_RUN_ID?`${t.GITHUB_SERVER_URL}/${t.GITHUB_REPOSITORY}/actions/runs/${t.GITHUB_RUN_ID}`:null}}function Aa(t){return t.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:t.CI_PIPELINE_ID??null,commitSha:t.CI_COMMIT_SHA??null,branch:t.CI_COMMIT_BRANCH??t.CI_COMMIT_REF_NAME??null,runUrl:t.CI_PIPELINE_URL??null}}function _a(t){if(!t.JENKINS_URL)return null;let e=t.GIT_BRANCH??null;return e?.startsWith("origin/")&&(e=e.slice(7)),{provider:"jenkins",buildId:t.BUILD_ID??null,commitSha:t.GIT_COMMIT??null,branch:e,runUrl:t.BUILD_URL??null}}function Ia(t){return t.CIRCLECI!=="true"?null:{provider:"circleci",buildId:t.CIRCLE_BUILD_NUM??null,commitSha:t.CIRCLE_SHA1??null,branch:t.CIRCLE_BRANCH??null,runUrl:t.CIRCLE_BUILD_URL??null}}function Ma(t){if(!t.BITBUCKET_PIPELINE_UUID)return null;let e=t.BITBUCKET_WORKSPACE&&t.BITBUCKET_REPO_SLUG&&t.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${t.BITBUCKET_WORKSPACE}/${t.BITBUCKET_REPO_SLUG}/pipelines/results/${t.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:t.BITBUCKET_BUILD_NUMBER??null,commitSha:t.BITBUCKET_COMMIT??null,branch:t.BITBUCKET_BRANCH??null,runUrl:e}}var Ea=[Ra,Aa,_a,Ia,Ma];function V(t){let e=process.env;for(let r of Ea){let n=r(e);if(n)return n}return null}var nt=`
7
+ `)}catch{return null}}function zr(t){return e=>{let r=e;for(let n of t)if(typeof n=="string"){let s=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(s,"g"),"[REDACTED]");}else {let s=n.flags.includes("g")?n.flags:n.flags+"g",a=new RegExp(n.source,s);r=r.replace(a,"[REDACTED]");}return r}}function Ra(t){return t.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:t.GITHUB_RUN_ID??null,commitSha:t.GITHUB_SHA??null,branch:t.GITHUB_REF_NAME??null,runUrl:t.GITHUB_SERVER_URL&&t.GITHUB_REPOSITORY&&t.GITHUB_RUN_ID?`${t.GITHUB_SERVER_URL}/${t.GITHUB_REPOSITORY}/actions/runs/${t.GITHUB_RUN_ID}`:null}}function Aa(t){return t.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:t.CI_PIPELINE_ID??null,commitSha:t.CI_COMMIT_SHA??null,branch:t.CI_COMMIT_BRANCH??t.CI_COMMIT_REF_NAME??null,runUrl:t.CI_PIPELINE_URL??null}}function _a(t){if(!t.JENKINS_URL)return null;let e=t.GIT_BRANCH??null;return e?.startsWith("origin/")&&(e=e.slice(7)),{provider:"jenkins",buildId:t.BUILD_ID??null,commitSha:t.GIT_COMMIT??null,branch:e,runUrl:t.BUILD_URL??null}}function Ia(t){return t.CIRCLECI!=="true"?null:{provider:"circleci",buildId:t.CIRCLE_BUILD_NUM??null,commitSha:t.CIRCLE_SHA1??null,branch:t.CIRCLE_BRANCH??null,runUrl:t.CIRCLE_BUILD_URL??null}}function Ma(t){if(!t.BITBUCKET_PIPELINE_UUID)return null;let e=t.BITBUCKET_WORKSPACE&&t.BITBUCKET_REPO_SLUG&&t.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${t.BITBUCKET_WORKSPACE}/${t.BITBUCKET_REPO_SLUG}/pipelines/results/${t.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:t.BITBUCKET_BUILD_NUMBER??null,commitSha:t.BITBUCKET_COMMIT??null,branch:t.BITBUCKET_BRANCH??null,runUrl:e}}var Pa=[Ra,Aa,_a,Ia,Ma];function V(t){let e=process.env;for(let r of Pa){let n=r(e);if(n)return n}return null}var nt=`
8
8
  /* Theme Variables */
9
9
  :root,[data-theme="dark"]{
10
10
  --bg:#0f1117;--bg-1:#161b22;--bg-2:#1c2128;--bg-3:#21262d;--bg-code:#13111c;
@@ -2752,7 +2752,7 @@ function _updateCard(cls,val){
2752
2752
  function visSideBySide(v){
2753
2753
  var h='<div class="vis-pair">';
2754
2754
  if(v.baseline)h+='<div><div class="vis-pane-label">Baseline</div>'+visImg(v.baseline,'Baseline')+'</div>';
2755
- if(v.actual)h+='<div><div class="vis-pane-label">Actual</div>'+visImg(v.actual,'Actual')+'</div>';
2755
+ if(v.actual)h+='<div><div class="vis-pane-label">This run</div>'+visImg(v.actual,'This run')+'</div>';
2756
2756
  if(v.previous)h+='<div><div class="vis-pane-label">Previous attempt</div>'+visImg(v.previous,'Previous attempt')+'</div>';
2757
2757
  return h+'</div>';
2758
2758
  }
@@ -2760,19 +2760,19 @@ function _updateCard(cls,val){
2760
2760
  function visSlider(v,id){
2761
2761
  var h='<div class="vis-stack" data-vis-stack="'+id+'">';
2762
2762
  h+='<img src="'+esc(v.baseline)+'" alt="Baseline">';
2763
- h+='<img class="vis-top" data-vis-wipe="'+id+'" src="'+esc(v.actual)+'" alt="Actual" style="clip-path:inset(0 0 0 50%)">';
2763
+ h+='<img class="vis-top" data-vis-wipe="'+id+'" src="'+esc(v.actual)+'" alt="This run" style="clip-path:inset(0 0 0 50%)">';
2764
2764
  h+='<div class="vis-handle" data-vis-handle="'+id+'" style="left:50%"></div>';
2765
2765
  h+='</div>';
2766
- h+='<div class="vis-range-row"><span>Baseline</span><input type="range" class="vis-range" min="0" max="100" value="50" data-vis-slider="'+id+'" aria-label="Wipe between baseline and actual"><span>Actual</span></div>';
2766
+ h+='<div class="vis-range-row"><span>Baseline</span><input type="range" class="vis-range" min="0" max="100" value="50" data-vis-slider="'+id+'" aria-label="Wipe between baseline and this run"><span>This run</span></div>';
2767
2767
  return h;
2768
2768
  }
2769
2769
 
2770
2770
  function visOnion(v,id){
2771
2771
  var h='<div class="vis-stack">';
2772
2772
  h+='<img src="'+esc(v.baseline)+'" alt="Baseline">';
2773
- h+='<img class="vis-top" data-vis-fade="'+id+'" src="'+esc(v.actual)+'" alt="Actual" style="opacity:0.5">';
2773
+ h+='<img class="vis-top" data-vis-fade="'+id+'" src="'+esc(v.actual)+'" alt="This run" style="opacity:0.5">';
2774
2774
  h+='</div>';
2775
- h+='<div class="vis-range-row"><span>Baseline</span><input type="range" class="vis-range" min="0" max="100" value="50" data-vis-onion="'+id+'" aria-label="Blend between baseline and actual"><span>Actual</span></div>';
2775
+ h+='<div class="vis-range-row"><span>Baseline</span><input type="range" class="vis-range" min="0" max="100" value="50" data-vis-onion="'+id+'" aria-label="Blend between baseline and this run"><span>This run</span></div>';
2776
2776
  return h;
2777
2777
  }
2778
2778
 
@@ -2780,12 +2780,12 @@ function _updateCard(cls,val){
2780
2780
  var modes=[];
2781
2781
  if(v.baseline&&v.actual){
2782
2782
  modes.push({key:'side',label:'Side by side'});
2783
- modes.push({key:'wipe',label:'Slider'});
2783
+ modes.push({key:'wipe',label:'Wipe'});
2784
2784
  modes.push({key:'onion',label:'Onion skin'});
2785
2785
  }else if(v.baseline||v.actual){
2786
2786
  modes.push({key:'side',label:'Image'});
2787
2787
  }
2788
- if(v.diff)modes.push({key:'diff',label:'Diff'});
2788
+ if(v.diff)modes.push({key:'diff',label:'Pixel diff'});
2789
2789
  /* Only when a DOM baseline existed to compare against \u2014 an assertion
2790
2790
  written with Playwright's own expect compares pixels only. */
2791
2791
  if(v.domChangeCount!==undefined)modes.push({key:'dom',label:'Elements'});
@@ -3999,7 +3999,7 @@ function _updateCard(cls,val){
3999
3999
  @media (max-width:1100px){
4000
4000
  .tband-3,.tband-2{grid-template-columns:1fr}
4001
4001
  }
4002
- `;var Pa=`
4002
+ `;var Ea=`
4003
4003
  (function(){
4004
4004
  var data=JSON.parse(document.getElementById('report-data').textContent);
4005
4005
  ${it}
@@ -4078,7 +4078,7 @@ ${""}
4078
4078
  </aside>
4079
4079
  <script id="report-data" type="application/json">${n}</script>
4080
4080
  ${s?`<script id="artifact-manifest-data" type="application/json">${s}</script>`:""}
4081
- <script>${Pa}</script>
4081
+ <script>${Ea}</script>
4082
4082
  </body>
4083
4083
  </html>`}function Ct(t,e,r,n){let s=t.replace(/<\//g,"<\\/"),a=e.replace(/<\//g,"<\\/"),o=n?n.replace(/<\//g,"<\\/"):null,i={};try{i=JSON.parse(t);}catch{}let d=`{
4084
4084
  "schemaVersion":"2.0",
@@ -4248,37 +4248,37 @@ ${o?`<script id="artifact-manifest-data" type="application/json">${o}</script>`:
4248
4248
  </body>
4249
4249
  </html>`}function Tt(t){try{let e=process.platform,r,n;e==="darwin"?(r="open",n=[t]):e==="win32"?(r="cmd",n=["/c","start","",t]):(r="xdg-open",n=[t]),execFile(r,n,s=>{s&&process.stderr.write(`[testrelic] Failed to open browser: ${s.message}
4250
4250
  `);});}catch{}}var Vr=join(tmpdir(),"testrelic-data"),q=class{constructor(e){this.count=0;this.closed=false;mkdirSync(Vr,{recursive:true}),this.filePath=join(Vr,`${e}-${randomUUID().substring(0,8)}.jsonl`),this.fd=openSync(this.filePath,"w");}append(e){if(this.closed)return;let r=JSON.stringify(e)+`
4251
- `;writeSync(this.fd,r),this.count++;}getPath(){return this.filePath}getCount(){return this.count}close(){if(!this.closed){this.closed=true;try{closeSync(this.fd);}catch{}}}cleanup(){try{unlinkSync(this.filePath);}catch{}}};async function Wr(t,e,r,n){let s=(e-1)*r,a=[],o=0,i=createInterface({input:createReadStream(t,{encoding:"utf-8"}),crlfDelay:1/0});for await(let c of i)if(c.length!==0){if(o>=s&&a.length<r)try{a.push(JSON.parse(c));}catch{}if(o++,a.length>=r&&n!==void 0)break}let d=n??o,l=Math.max(1,Math.ceil(d/r));return {items:a,total:d,page:e,pageSize:r,totalPages:l}}var Yr=/^[a-f0-9]{12}$/,At=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Xr=500;function R(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function Zr(t){t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type");}function Se(t){try{return existsSync(t)?JSON.parse(readFileSync(t,"utf-8")):null}catch{return null}}function Re(t){let e=0;try{let r=readdirSync(t,{withFileTypes:!0});for(let n of r){let s=join(t,n.name);n.isFile()?e+=statSync(s).size:n.isDirectory()&&(e+=Re(s));}}catch{}return e}function Qr(t,e,r,n){let s=Se(join(r,"index.json"));R(e,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-n)/1e3)});}function en(t,e,r){let n=Se(join(r,"summary.json"));if(!n){R(e,404,{error:"Summary not found"});return}R(e,200,n);}function tn(t,e,r){let n=Se(join(r,"index.json"));if(!n){R(e,404,{error:"Test index not found"});return}let a=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,o=Math.max(1,parseInt(a.get("page")??"1",10)||1),i=Math.min(Xr,Math.max(1,parseInt(a.get("pageSize")??"100",10)||100)),d=a.get("status")?.split(",").filter(Boolean)??null,l=a.get("file")??null,c=a.get("search")?.toLowerCase()??null,u=a.get("tag")?.split(",").filter(Boolean)??null,f=a.get("sort")??"file",p=a.get("order")==="desc"?-1:1,g=n;d&&d.length>0&&(g=g.filter(b=>d.includes(b.status))),l&&(g=g.filter(b=>b.filePath===l||b.filePath.startsWith(l+"/"))),c&&(g=g.filter(b=>b.title.toLowerCase().includes(c)||b.filePath.toLowerCase().includes(c))),u&&u.length>0&&(g=g.filter(b=>u.some(k=>b.tags.includes(k)))),g=[...g].sort((b,k)=>{let A=0;switch(f){case "duration":A=b.duration-k.duration;break;case "status":A=b.status.localeCompare(k.status);break;case "title":A=b.title.localeCompare(k.title);break;default:A=b.filePath.localeCompare(k.filePath);break}return A*p});let m=g.length,h=Math.max(1,Math.ceil(m/i)),v=(o-1)*i,y=g.slice(v,v+i);R(e,200,{tests:y,pagination:{page:o,pageSize:i,totalItems:m,totalPages:h},filters:{status:d,file:l,search:c,tag:u}});}function rn(t,e,r,n){if(!Yr.test(n)){R(e,400,{error:"Invalid test ID format"});return}let s=join(r,"tests",n,"meta.json"),a=join(r,"tests",`${n}.json`),o=existsSync(s)?s:existsSync(a)?a:null;if(!o){R(e,404,{error:`Test not found: ${n}`});return}try{let i=readFileSync(o,"utf-8");e.writeHead(200,{"Content-Type":"application/json"}),e.end(i);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}async function nn(t,e,r,n,s){if(!Yr.test(n)){R(e,400,{error:"Invalid test ID format"});return}let o=join(r,"tests",n,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!existsSync(o)){R(e,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let d=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,l=Math.max(1,parseInt(d.get("page")??"1",10)||1),c=Math.min(Xr,Math.max(1,parseInt(d.get("pageSize")??"50",10)||50)),u,f=join(r,"tests",n,"meta.json");if(existsSync(f))try{let g=JSON.parse(readFileSync(f,"utf-8"));switch(s){case "network":u=g.networkRequestsCount;break;case "console":u=g.consoleLogsCount;break;case "api-calls":u=g.apiCallsCount;break}}catch{}let p=await Wr(o,l,c,u);R(e,200,p);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}function sn(t,e,r){let n=Se(join(r,"index.json"));if(!n){R(e,404,{error:"Test index not found"});return}let s=new Map;for(let o of n){if(o.isRetry)continue;let i=s.get(o.filePath);switch(i||(i={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},s.set(o.filePath,i)),i.total++,o.status){case "passed":i.passed++;break;case "failed":i.failed++;break;case "flaky":i.flaky++;break;case "skipped":i.skipped++;break;case "timedout":i.timedOut++;break}}let a=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));R(e,200,{files:a});}function an(t,e,r){if(!existsSync(r)){R(e,200,{runs:[],totalSizeBytes:0});return}try{let n=[],s=0,a=readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!At.test(o.name))continue;let i=join(r,o.name),d=Re(i),l=readdirSync(i,{withFileTypes:!0}).filter(c=>c.isDirectory());n.push({folderName:o.name,totalSizeBytes:d,testCount:l.length}),s+=d;}n.sort((o,i)=>i.folderName.localeCompare(o.folderName)),R(e,200,{runs:n,totalSizeBytes:s});}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function on(t,e,r){try{let n=0,s=0;if(existsSync(r)){let a=readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!At.test(o.name))continue;let i=join(r,o.name),d=Re(i);rmSync(i,{recursive:!0,force:!0}),s+=d,n++;}}R(e,200,{deletedCount:n,freedBytes:s});}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function ln(t,e,r,n){if(!At.test(n)){R(e,400,{error:"Invalid folder name"});return}let s=join(r,n);try{if(!statSync(s).isDirectory()){R(e,404,{error:"Not found"});return}}catch{R(e,404,{error:"Not found"});return}try{let a=Re(s);rmSync(s,{recursive:!0,force:!0}),R(e,200,{deleted:n,freedBytes:a});}catch(a){R(e,500,{error:a instanceof Error?a.message:String(a)});}}function dn(t,e,r){R(e,200,{status:"shutting_down"}),r.close();}function _t(t,e,r){if(!existsSync(r)){R(e,404,{error:"File not found"});return}try{let n=statSync(r).size,s=extname(r).toLowerCase(),a=$a[s]??"application/octet-stream",o=Va(t.headers.range,n);if(o==="unsatisfiable"){e.writeHead(416,{"Content-Range":`bytes */${n}`,"Accept-Ranges":"bytes"}),e.end();return}if(o){e.writeHead(206,{"Content-Type":a,"Content-Length":o.end-o.start+1,"Content-Range":`bytes ${o.start}-${o.end}/${n}`,"Accept-Ranges":"bytes"}),Kr(createReadStream(r,{start:o.start,end:o.end}),e);return}e.writeHead(200,{"Content-Type":a,"Content-Length":n,"Accept-Ranges":"bytes"}),Kr(createReadStream(r),e);}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function Kr(t,e){t.on("error",()=>{t.destroy(),e.destroy();}),e.on("close",()=>{t.destroy();}),t.pipe(e);}function Va(t,e){if(!t)return null;let r=/^bytes=(\d*)-(\d*)$/.exec(t.trim());if(!r)return null;let[,n,s]=r;if(n===""&&s==="")return null;let a,o;if(n===""){let i=Number(s);if(i<=0)return "unsatisfiable";a=Math.max(0,e-i),o=e-1;}else a=Number(n),o=s===""?e-1:Math.min(Number(s),e-1);return !Number.isFinite(a)||!Number.isFinite(o)?null:e===0||a>=e||a>o?"unsatisfiable":{start:a,end:o}}var $a={".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 Ja=9323,Ya=10,Xa=1800*1e3;function me(t,e){return new Promise((r,n)=>{let s=e?.port??Ja,a=Date.now(),o,i=0,d=existsSync(join(t,"artifacts"))?join(t,"artifacts"):existsSync(join(t,"..","artifacts"))?join(t,"..","artifacts"):join(t,"artifacts");function l(){clearTimeout(o),o=setTimeout(()=>{u.close();},Xa);}let c=e?.htmlPath??null;if(!c){let p=dirname(t);try{let g=readdirSync(p).find(m=>m.endsWith(".html"));g&&(c=join(p,g));}catch{}}let u=createServer((p,g)=>{if(l(),Zr(g),p.method==="OPTIONS"){g.writeHead(204),g.end();return}let m;try{m=new URL(p.url??"/",`http://${p.headers.host??"localhost"}`).pathname;}catch{R(g,400,{error:"Invalid URL"});return}if(p.method==="GET"&&(m==="/"||m==="/index.html")){if(c&&existsSync(c)){_t(p,g,c);return}R(g,404,{error:"HTML report not found"});return}if(p.method==="GET"&&m==="/api/health"){Qr(p,g,t,a);return}if(p.method==="GET"&&m==="/api/summary"){en(p,g,t);return}if(p.method==="GET"&&m==="/api/tests"){tn(p,g,t);return}if(p.method==="GET"&&m==="/api/files"){sn(p,g,t);return}let h=m.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(p.method==="GET"&&h){nn(p,g,t,h[1],h[2]);return}let v=m.match(/^\/api\/tests\/([a-f0-9]+)$/);if(p.method==="GET"&&v){rn(p,g,t,v[1]);return}if(p.method==="GET"&&m==="/api/artifacts"){an(p,g,d);return}if(p.method==="DELETE"&&m==="/api/artifacts"){on(p,g,d);return}let y=m.match(/^\/api\/artifacts\/(.+)$/);if(p.method==="DELETE"&&y){ln(p,g,d,decodeURIComponent(y[1]));return}if(p.method==="GET"&&m.startsWith("/artifacts/")){let b=decodeURIComponent(m.slice(11));if(b.includes("..")||b.includes("\0")){R(g,400,{error:"Invalid path"});return}_t(p,g,join(d,b));return}if(p.method==="POST"&&m==="/api/shutdown"){dn(p,g,u);return}R(g,404,{error:"Not found"});});function f(p){let g=m=>{m.code==="EADDRINUSE"&&i<Ya?(i++,f(p+1)):n(m);};u.once("error",g),u.listen(p,"127.0.0.1",()=>{u.removeListener("error",g);let m=u.address();if(!m||typeof m=="string"){n(new Error("Failed to get server address"));return}l(),r({port:m.port,dispose:()=>new Promise(h=>{clearTimeout(o),u.close(()=>h());})});});}f(s);})}async function cn(t){let e=await me(t);return {port:e.port,dispose:e.dispose}}function ei(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return jr(n,e,s)}async function Mt(t,e,r){try{let n=null,s=null,a=e.reportMode==="streaming"||e.reportMode==="auto"&&t.timeline.length===0&&t.summary.total>=e.streamingThreshold,o,i=e.htmlReportPath,d=dirname(i);mkdirSync(d,{recursive:!0});let l="",c="[]",u=null;if(a){l=JSON.stringify({...t.summary,testRunId:t.testRunId,startedAt:t.startedAt,completedAt:t.completedAt,totalDuration:t.totalDuration,ci:t.ci,metadata:t.metadata,shardRunIds:t.shardRunIds});let p=dirname(e.outputPath),g=join(p,".testrelic-report");try{let m=join(g,"index-compact.json"),h=join(g,"index.json");existsSync(m)?c=readFileSync(m,"utf-8"):existsSync(h)&&(c=readFileSync(h,"utf-8"));}catch{}u=r?JSON.stringify(r):null,o=Ct(l,c,null,u);}else o=ei(t,null,r);let f=i+".tmp";if(writeFileSync(f,o,"utf-8"),renameSync(f,i),a){if(t.ci===null){let p=dirname(e.outputPath),g=join(p,".testrelic-report"),m=resolve(i);try{if(await ri(),n=await ni(g),!n){s=await me(g,{htmlPath:m}),n=s.port;let h=setInterval(()=>{},6e4),v=()=>{clearInterval(h),s?.dispose();};process.on("SIGINT",v),process.on("SIGTERM",v),setTimeout(v,1800*1e3).unref();}if(n){process.stderr.write(`
4251
+ `;writeSync(this.fd,r),this.count++;}getPath(){return this.filePath}getCount(){return this.count}close(){if(!this.closed){this.closed=true;try{closeSync(this.fd);}catch{}}}cleanup(){try{unlinkSync(this.filePath);}catch{}}};async function Wr(t,e,r,n){let s=(e-1)*r,a=[],o=0,i=createInterface({input:createReadStream(t,{encoding:"utf-8"}),crlfDelay:1/0});for await(let c of i)if(c.length!==0){if(o>=s&&a.length<r)try{a.push(JSON.parse(c));}catch{}if(o++,a.length>=r&&n!==void 0)break}let d=n??o,l=Math.max(1,Math.ceil(d/r));return {items:a,total:d,page:e,pageSize:r,totalPages:l}}var Yr=/^[a-f0-9]{12}$/,At=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Xr=500;function R(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function Zr(t){t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type");}function Se(t){try{return existsSync(t)?JSON.parse(readFileSync(t,"utf-8")):null}catch{return null}}function Re(t){let e=0;try{let r=readdirSync(t,{withFileTypes:!0});for(let n of r){let s=join(t,n.name);n.isFile()?e+=statSync(s).size:n.isDirectory()&&(e+=Re(s));}}catch{}return e}function Qr(t,e,r,n){let s=Se(join(r,"index.json"));R(e,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-n)/1e3)});}function en(t,e,r){let n=Se(join(r,"summary.json"));if(!n){R(e,404,{error:"Summary not found"});return}R(e,200,n);}function tn(t,e,r){let n=Se(join(r,"index.json"));if(!n){R(e,404,{error:"Test index not found"});return}let a=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,o=Math.max(1,parseInt(a.get("page")??"1",10)||1),i=Math.min(Xr,Math.max(1,parseInt(a.get("pageSize")??"100",10)||100)),d=a.get("status")?.split(",").filter(Boolean)??null,l=a.get("file")??null,c=a.get("search")?.toLowerCase()??null,u=a.get("tag")?.split(",").filter(Boolean)??null,p=a.get("sort")??"file",g=a.get("order")==="desc"?-1:1,f=n;d&&d.length>0&&(f=f.filter(b=>d.includes(b.status))),l&&(f=f.filter(b=>b.filePath===l||b.filePath.startsWith(l+"/"))),c&&(f=f.filter(b=>b.title.toLowerCase().includes(c)||b.filePath.toLowerCase().includes(c))),u&&u.length>0&&(f=f.filter(b=>u.some(k=>b.tags.includes(k)))),f=[...f].sort((b,k)=>{let A=0;switch(p){case "duration":A=b.duration-k.duration;break;case "status":A=b.status.localeCompare(k.status);break;case "title":A=b.title.localeCompare(k.title);break;default:A=b.filePath.localeCompare(k.filePath);break}return A*g});let m=f.length,h=Math.max(1,Math.ceil(m/i)),v=(o-1)*i,y=f.slice(v,v+i);R(e,200,{tests:y,pagination:{page:o,pageSize:i,totalItems:m,totalPages:h},filters:{status:d,file:l,search:c,tag:u}});}function rn(t,e,r,n){if(!Yr.test(n)){R(e,400,{error:"Invalid test ID format"});return}let s=join(r,"tests",n,"meta.json"),a=join(r,"tests",`${n}.json`),o=existsSync(s)?s:existsSync(a)?a:null;if(!o){R(e,404,{error:`Test not found: ${n}`});return}try{let i=readFileSync(o,"utf-8");e.writeHead(200,{"Content-Type":"application/json"}),e.end(i);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}async function nn(t,e,r,n,s){if(!Yr.test(n)){R(e,400,{error:"Invalid test ID format"});return}let o=join(r,"tests",n,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[s]);if(!existsSync(o)){R(e,200,{items:[],total:0,page:1,pageSize:50,totalPages:0});return}try{let d=new URL(t.url??"/",`http://${t.headers.host}`).searchParams,l=Math.max(1,parseInt(d.get("page")??"1",10)||1),c=Math.min(Xr,Math.max(1,parseInt(d.get("pageSize")??"50",10)||50)),u,p=join(r,"tests",n,"meta.json");if(existsSync(p))try{let f=JSON.parse(readFileSync(p,"utf-8"));switch(s){case "network":u=f.networkRequestsCount;break;case "console":u=f.consoleLogsCount;break;case "api-calls":u=f.apiCallsCount;break}}catch{}let g=await Wr(o,l,c,u);R(e,200,g);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}function sn(t,e,r){let n=Se(join(r,"index.json"));if(!n){R(e,404,{error:"Test index not found"});return}let s=new Map;for(let o of n){if(o.isRetry)continue;let i=s.get(o.filePath);switch(i||(i={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},s.set(o.filePath,i)),i.total++,o.status){case "passed":i.passed++;break;case "failed":i.failed++;break;case "flaky":i.flaky++;break;case "skipped":i.skipped++;break;case "timedout":i.timedOut++;break}}let a=Array.from(s.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));R(e,200,{files:a});}function an(t,e,r){if(!existsSync(r)){R(e,200,{runs:[],totalSizeBytes:0});return}try{let n=[],s=0,a=readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!At.test(o.name))continue;let i=join(r,o.name),d=Re(i),l=readdirSync(i,{withFileTypes:!0}).filter(c=>c.isDirectory());n.push({folderName:o.name,totalSizeBytes:d,testCount:l.length}),s+=d;}n.sort((o,i)=>i.folderName.localeCompare(o.folderName)),R(e,200,{runs:n,totalSizeBytes:s});}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function on(t,e,r){try{let n=0,s=0;if(existsSync(r)){let a=readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!At.test(o.name))continue;let i=join(r,o.name),d=Re(i);rmSync(i,{recursive:!0,force:!0}),s+=d,n++;}}R(e,200,{deletedCount:n,freedBytes:s});}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function ln(t,e,r,n){if(!At.test(n)){R(e,400,{error:"Invalid folder name"});return}let s=join(r,n);try{if(!statSync(s).isDirectory()){R(e,404,{error:"Not found"});return}}catch{R(e,404,{error:"Not found"});return}try{let a=Re(s);rmSync(s,{recursive:!0,force:!0}),R(e,200,{deleted:n,freedBytes:a});}catch(a){R(e,500,{error:a instanceof Error?a.message:String(a)});}}function dn(t,e,r){R(e,200,{status:"shutting_down"}),r.close();}function _t(t,e,r){if(!existsSync(r)){R(e,404,{error:"File not found"});return}try{let n=statSync(r).size,s=extname(r).toLowerCase(),a=$a[s]??"application/octet-stream",o=Va(t.headers.range,n);if(o==="unsatisfiable"){e.writeHead(416,{"Content-Range":`bytes */${n}`,"Accept-Ranges":"bytes"}),e.end();return}if(o){e.writeHead(206,{"Content-Type":a,"Content-Length":o.end-o.start+1,"Content-Range":`bytes ${o.start}-${o.end}/${n}`,"Accept-Ranges":"bytes"}),Kr(createReadStream(r,{start:o.start,end:o.end}),e);return}e.writeHead(200,{"Content-Type":a,"Content-Length":n,"Accept-Ranges":"bytes"}),Kr(createReadStream(r),e);}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function Kr(t,e){t.on("error",()=>{t.destroy(),e.destroy();}),e.on("close",()=>{t.destroy();}),t.pipe(e);}function Va(t,e){if(!t)return null;let r=/^bytes=(\d*)-(\d*)$/.exec(t.trim());if(!r)return null;let[,n,s]=r;if(n===""&&s==="")return null;let a,o;if(n===""){let i=Number(s);if(i<=0)return "unsatisfiable";a=Math.max(0,e-i),o=e-1;}else a=Number(n),o=s===""?e-1:Math.min(Number(s),e-1);return !Number.isFinite(a)||!Number.isFinite(o)?null:e===0||a>=e||a>o?"unsatisfiable":{start:a,end:o}}var $a={".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 Ja=9323,Ya=10,Xa=1800*1e3;function me(t,e){return new Promise((r,n)=>{let s=e?.port??Ja,a=Date.now(),o,i=0,d=existsSync(join(t,"artifacts"))?join(t,"artifacts"):existsSync(join(t,"..","artifacts"))?join(t,"..","artifacts"):join(t,"artifacts");function l(){clearTimeout(o),o=setTimeout(()=>{u.close();},Xa);}let c=e?.htmlPath??null;if(!c){let g=dirname(t);try{let f=readdirSync(g).find(m=>m.endsWith(".html"));f&&(c=join(g,f));}catch{}}let u=createServer((g,f)=>{if(l(),Zr(f),g.method==="OPTIONS"){f.writeHead(204),f.end();return}let m;try{m=new URL(g.url??"/",`http://${g.headers.host??"localhost"}`).pathname;}catch{R(f,400,{error:"Invalid URL"});return}if(g.method==="GET"&&(m==="/"||m==="/index.html")){if(c&&existsSync(c)){_t(g,f,c);return}R(f,404,{error:"HTML report not found"});return}if(g.method==="GET"&&m==="/api/health"){Qr(g,f,t,a);return}if(g.method==="GET"&&m==="/api/summary"){en(g,f,t);return}if(g.method==="GET"&&m==="/api/tests"){tn(g,f,t);return}if(g.method==="GET"&&m==="/api/files"){sn(g,f,t);return}let h=m.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(g.method==="GET"&&h){nn(g,f,t,h[1],h[2]);return}let v=m.match(/^\/api\/tests\/([a-f0-9]+)$/);if(g.method==="GET"&&v){rn(g,f,t,v[1]);return}if(g.method==="GET"&&m==="/api/artifacts"){an(g,f,d);return}if(g.method==="DELETE"&&m==="/api/artifacts"){on(g,f,d);return}let y=m.match(/^\/api\/artifacts\/(.+)$/);if(g.method==="DELETE"&&y){ln(g,f,d,decodeURIComponent(y[1]));return}if(g.method==="GET"&&m.startsWith("/artifacts/")){let b=decodeURIComponent(m.slice(11));if(b.includes("..")||b.includes("\0")){R(f,400,{error:"Invalid path"});return}_t(g,f,join(d,b));return}if(g.method==="POST"&&m==="/api/shutdown"){dn(g,f,u);return}R(f,404,{error:"Not found"});});function p(g){let f=m=>{m.code==="EADDRINUSE"&&i<Ya?(i++,p(g+1)):n(m);};u.once("error",f),u.listen(g,"127.0.0.1",()=>{u.removeListener("error",f);let m=u.address();if(!m||typeof m=="string"){n(new Error("Failed to get server address"));return}l(),r({port:m.port,dispose:()=>new Promise(h=>{clearTimeout(o),u.close(()=>h());})});});}p(s);})}async function cn(t){let e=await me(t);return {port:e.port,dispose:e.dispose}}function ei(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return jr(n,e,s)}async function Mt(t,e,r){try{let n=null,s=null,a=e.reportMode==="streaming"||e.reportMode==="auto"&&t.timeline.length===0&&t.summary.total>=e.streamingThreshold,o,i=e.htmlReportPath,d=dirname(i);mkdirSync(d,{recursive:!0});let l="",c="[]",u=null;if(a){l=JSON.stringify({...t.summary,testRunId:t.testRunId,startedAt:t.startedAt,completedAt:t.completedAt,totalDuration:t.totalDuration,ci:t.ci,metadata:t.metadata,shardRunIds:t.shardRunIds});let g=dirname(e.outputPath),f=join(g,".testrelic-report");try{let m=join(f,"index-compact.json"),h=join(f,"index.json");existsSync(m)?c=readFileSync(m,"utf-8"):existsSync(h)&&(c=readFileSync(h,"utf-8"));}catch{}u=r?JSON.stringify(r):null,o=Ct(l,c,null,u);}else o=ei(t,null,r);let p=i+".tmp";if(writeFileSync(p,o,"utf-8"),renameSync(p,i),a){if(t.ci===null){let g=dirname(e.outputPath),f=join(g,".testrelic-report"),m=resolve(i);try{if(await ri(),n=await ni(f),!n){s=await me(f,{htmlPath:m}),n=s.port;let h=setInterval(()=>{},6e4),v=()=>{clearInterval(h),s?.dispose();};process.on("SIGINT",v),process.on("SIGTERM",v),setTimeout(v,1800*1e3).unref();}if(n){process.stderr.write(`
4252
4252
  Report server: http://127.0.0.1:${n}
4253
- `);try{let h=Ct(l,c,n,u),v=i+".tmp";writeFileSync(v,h,"utf-8"),renameSync(v,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let p=dirname(e.outputPath),g=join(p,"artifacts");if(existsSync(g))try{let m=await cn(g);n=m.port,process.on("exit",()=>{m.dispose();});}catch{}}if(e.openReport&&t.ci===null)if(a&&n)Tt(`http://127.0.0.1:${n}`);else {let p=resolve(i);Tt(p);}}catch(n){process.stderr.write(`[testrelic] Failed to write HTML report: ${n instanceof Error?n.message:String(n)}
4254
- `);}}var Ie=9323,hn=10;async function ti(){for(let t=Ie;t<Ie+hn;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),500),n=await fetch(`http://127.0.0.1:${t}/api/health`,{signal:e.signal});if(clearTimeout(r),n.ok)return t}catch{}return null}async function ri(){for(let t=Ie;t<Ie+hn;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),1e3);await fetch(`http://127.0.0.1:${t}/api/shutdown`,{method:"POST",signal:e.signal}),clearTimeout(r);}catch{}await new Promise(t=>setTimeout(t,300));}async function ni(t){let r=[join(__dirname,"cli.cjs"),join(__dirname,"cli.js"),join(__dirname,"..","dist","cli.cjs"),join(__dirname,"..","dist","cli.js")].find(n=>existsSync(n));if(!r){let n=await me(t);return process.on("exit",()=>{n?.dispose();}),n.port}return new Promise(n=>{let s=spawn(process.execPath,[r,"serve",t],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),a="",o=false,i=setTimeout(()=>{o||(o=true,s.stderr?.removeAllListeners(),ti().then(n));},5e3);s.stderr?.on("data",d=>{a+=d.toString();let l=a.match(/127\.0\.0\.1:(\d+)/);l&&!o&&(o=true,clearTimeout(i),s.stderr?.removeAllListeners(),s.unref(),n(Number(l[1])));}),s.on("error",()=>{o||(o=true,clearTimeout(i),n(null));}),s.on("exit",()=>{o||(o=true,clearTimeout(i),n(null));}),s.unref();})}var mn=Buffer.from([137,80,78,71,13,10,26,10]),si=16,ai=20,Me=24;function vn(t){if(t.length<Me||!t.subarray(0,mn.length).equals(mn))return null;let e=t.readUInt32BE(si),r=t.readUInt32BE(ai);return e===0||r===0?null:{width:e,height:r}}var ii=/(\d+) pixels \(ratio [\d.]+ of all image pixels\) are different/,yn=/Expected an image (\d+)px by (\d+)px, received (\d+)px by (\d+)px/;function Ee(t){return t?yn.test(t):false}var oi=/^\s*Snapshot:\s*(.+?)\s*$/m;function bn(t){if(!t)return {};let e={},r=ii.exec(t);if(r){let a=Number.parseInt(r[1],10);Number.isFinite(a)&&(e.diffPixels=a);}let n=yn.exec(t);if(n){let[,a,o,i,d]=n,l=[a,o,i,d].map(c=>Number.parseInt(c,10));l.every(c=>Number.isFinite(c))&&(e.expectedWidth=l[0],e.expectedHeight=l[1],e.actualWidth=l[2],e.actualHeight=l[3]);}let s=oi.exec(t);return s&&(e.snapshotName=s[1]),e}function xn(t,e){if(t===void 0||!e)return;let r=e.width*e.height;if(!(r<=0))return t/r}var fi=20,Et=0,Pt=[];async function ve(t,e){Et>=fi&&await new Promise(r=>Pt.push(r)),Et++;try{return await copyFile(t,e),!0}catch{return false}finally{Et--,Pt.length>0&&Pt.shift()();}}var W=[];async function kn(){W.length!==0&&(await Promise.allSettled(W),W.length=0);}function Cn(t){let e=new Date,r=a=>String(a).padStart(2,"0"),n=`${e.getFullYear()}-${r(e.getMonth()+1)}-${r(e.getDate())}T${r(e.getHours())}-${r(e.getMinutes())}-${r(e.getSeconds())}`;if(!existsSync(join(t,n)))return n;let s=1;for(;existsSync(join(t,`${n}-${s}`));)s++;return `${n}-${s}`}function Lt(t){let e=t.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return e.length>100&&(e=e.substring(0,100).replace(/-+$/,"")),e||"unnamed-test"}var gi=8;function Tn(t,e,r){let n=Lt(t),s=r?Lt(r).substring(0,gi):"";return s&&(n+=`--${s}`),e>0&&(n+=`--retry-${e}`),n}function Sn(t,e,r,n,s,a){let o=t.find(g=>g.name==="screenshot"&&g.path),i=t.find(g=>g.name==="video"&&g.path),d=t.find(g=>g.name==="trace"&&g.path);if(!o&&!i&&!d)return null;let l=Tn(e,r,a),c=s?["artifacts",s,l]:["artifacts",l],u=join(n,...c),f=c,p={};try{mkdirSync(u,{recursive:!0});}catch{return null}if(o?.path&&existsSync(o.path)){let m=`screenshot${extname(o.path)||".png"}`,h=join(u,m);W.push(ve(o.path,h).then(()=>{})),p.screenshot=`${f.join("/")}/${m}`;}if(i?.path&&existsSync(i.path)){let m=`video${extname(i.path)||".webm"}`,h=join(u,m);W.push(ve(i.path,h).then(()=>{})),p.video=`${f.join("/")}/${m}`;}if(d?.path&&existsSync(d.path)){let m=`trace${extname(d.path)||".zip"}`,h=join(u,m);W.push(ve(d.path,h).then(()=>{})),p.trace=`${f.join("/")}/${m}`;}return !p.screenshot&&!p.video&&!p.trace?null:p}var Nt="visual",hi=6;function mi(t){let e=createHash("sha256").update(t).digest("hex").substring(0,hi);return `${Lt(t)}--${e}`}function wn(t){let e=null;try{e=openSync(t,"r");let r=Buffer.alloc(Me),n=readSync(e,r,0,Me,0);return vn(r.subarray(0,n))}catch{return null}finally{if(e!==null)try{closeSync(e);}catch{}}}var vi=[{key:"expectedPath",dest:"baseline",field:"baseline"},{key:"actualPath",dest:"actual",field:"actual"},{key:"diffPath",dest:"diff",field:"diff"},{key:"previousPath",dest:"previous",field:"previous"}],yi=[{key:"baselineDomPath",dest:"baseline.dom.json",field:"baselineDom"},{key:"actualDomPath",dest:"actual.dom.json",field:"actualDom"}];function bi(t,e,r){let n=mi(t.name),s=join(e,n);try{mkdirSync(s,{recursive:!0});}catch{return null}let a={},o=false;for(let c of vi){let u=t[c.key];if(!u||!existsSync(u))continue;let f=extname(u)||".png",p=`${c.dest}${f}`;W.push(ve(u,join(s,p)).then(()=>{})),a[c.field]=`${r}/${Nt}/${n}/${p}`,o=true;}let i=t.dom;if(i)for(let c of yi){let u=i[c.key];!u||!existsSync(u)||(W.push(ve(u,join(s,c.dest)).then(()=>{})),a[c.field]=`${r}/${Nt}/${n}/${c.dest}`);}if(!o)return null;let d=t.expectedPath?wn(t.expectedPath):t.actualPath?wn(t.actualPath):null,l=xn(t.diffPixels,d);return {name:t.name,status:t.status,source:t.source,...a,...d?{width:d.width,height:d.height}:{},...t.actualWidth!==void 0?{actualWidth:t.actualWidth}:{},...t.actualHeight!==void 0?{actualHeight:t.actualHeight}:{},...t.diffPixels!==void 0?{diffPixels:t.diffPixels}:{},...l!==void 0?{diffPixelRatio:l}:{},...i?{domChanges:i.changes,domChangeCount:i.total,domRootCauses:i.rootCauses,domTruncated:i.truncated,domCaptureBox:i.captureBox}:{}}}function Rn(t,e,r,n,s,a){if(t.length===0)return null;let o=Tn(e,r,a),i=s?["artifacts",s,o]:["artifacts",o],d=join(n,...i,Nt),l=i.join("/");try{mkdirSync(d,{recursive:!0});}catch{return null}let c=[];for(let u of t){let f=bi(u,d,l);f&&c.push(f);}return c.length>0?c:null}function An(t){let{styleProps:e,defaults:r,inherited:n,maxNodes:s,maxText:a,maskBoxes:o,viewportBox:i,fullPage:d}=t,l={};for(let T=0;T<n.length;T++)l[n[T]]=true;let c=window.scrollX||window.pageXOffset||0,u=window.scrollY||window.pageYOffset||0,f=[],p=0,g=[];for(let T=0;T<o.length;T++){let x=o[T];g.push([x[0]+c,x[1]+u,x[2],x[3]]);}function m(T,x,S,w){for(let C=0;C<g.length;C++){let _=g[C];if(T<_[0]+_[2]&&T+S>_[0]&&x<_[1]+_[3]&&x+w>_[1])return true}return false}function h(T){let x=T.parentElement;if(!x)return 0;let S=x.children,w=0;for(let C=0;C<S.length;C++){let _=S[C];if(_===T)break;_.tagName===T.tagName&&w++;}return w}function v(T){let x="",S=T.childNodes;for(let w=0;w<S.length;w++){let C=S[w];C.nodeType===3&&(x+=C.nodeValue??"");}return x=x.replace(/\s+/g," ").trim(),x.length>a?x.slice(0,a):x}function y(T,x){let S;for(let w=0;w<e.length;w++){let C=e[w],_=T.getPropertyValue(C);if(_){if(l[C]){if(x&&x.getPropertyValue(C)===_)continue}else if(r[C]===_)continue;S||(S={}),S[C]=_;}}return S}let b=[{el:document.body,parentPath:"",parentComputed:null}];for(;b.length>0;){let T=b.pop(),x=T.el,S=window.getComputedStyle(x);if(S.display==="none")continue;let w=x.tagName.toLowerCase(),C=x.id?"#"+x.id:T.parentPath?T.parentPath+">"+w+"["+h(x)+"]":w,_=x.children;for(let P=_.length-1;P>=0;P--)b.push({el:_[P],parentPath:C,parentComputed:S});if(S.visibility==="hidden")continue;let L=x.getBoundingClientRect();if(L.width<=0||L.height<=0)continue;if(f.length>=s){p++;continue}let z=Math.round(L.left+c),ce=Math.round(L.top+u),ue=Math.round(L.width),pe=Math.round(L.height),I={p:C,t:w,r:[z,ce,ue,pe]};x.id&&(I.i=x.id);let M=x.getAttribute("class");M&&(I.c=M.replace(/\s+/g," ").trim());let N=v(x);N&&(I.x=N);let j=y(S,T.parentComputed);j&&(I.s=j),m(z,ce,ue,pe)&&(I.m=1),f.push(I);}let k=Math.max(document.documentElement.scrollWidth,window.innerWidth),A=Math.max(document.documentElement.scrollHeight,window.innerHeight),E;return i?E=[Math.round(i[0]+c),Math.round(i[1]+u),Math.round(i[2]),Math.round(i[3])]:d?E=[0,0,k,A]:E=[Math.round(c),Math.round(u),window.innerWidth,window.innerHeight],{version:"1.0",url:location.href,viewport:{width:window.innerWidth,height:window.innerHeight},content:{width:k,height:A},captureBox:E,nodes:f,truncatedNodes:p}}var Si=["display","position","color","background-color","background-image","border-top-width","border-right-width","border-bottom-width","border-left-width","border-color","border-style","border-radius","box-shadow","opacity","transform","margin-top","margin-right","margin-bottom","margin-left","padding-top","padding-right","padding-bottom","padding-left","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-decoration-line","text-transform","flex-direction","justify-content","align-items","gap","z-index","overflow"],Ri={position:"static","background-color":"rgba(0, 0, 0, 0)","background-image":"none","border-top-width":"0px","border-right-width":"0px","border-bottom-width":"0px","border-left-width":"0px","border-style":"none","border-radius":"0px","box-shadow":"none",opacity:"1",transform:"none","margin-top":"0px","margin-right":"0px","margin-bottom":"0px","margin-left":"0px","padding-top":"0px","padding-right":"0px","padding-bottom":"0px","padding-left":"0px","text-decoration-line":"none","flex-direction":"row","justify-content":"normal","align-items":"normal",gap:"normal","z-index":"auto",overflow:"visible"},Ai=["color","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-transform"],_i=1024*1024,Ii=1500,Mi=200;async function Ei(t){let e=[];for(let r of t)try{let n=await r.boundingBox();n&&e.push([n.x,n.y,n.width,n.height]);}catch{}return e}async function _n(t){let e=t.config??{};try{let r=t.maskLocators?.length?await Ei(t.maskLocators):[],n=null;if(t.bounded){let a=await t.bounded.boundingBox();a&&(n=[a.x,a.y,a.width,a.height]);}let s={styleProps:Si,defaults:Ri,inherited:Ai,maxNodes:e.maxNodes??Ii,maxText:e.maxText??Mi,maskBoxes:r,viewportBox:n,fullPage:t.fullPage===!0};return await t.target.evaluate(An,s)}catch{return null}}function In(t,e=_i){let r=JSON.stringify(t);if(Buffer.byteLength(r,"utf-8")<=e)return {json:r,truncatedBytes:false};let n=t.nodes.slice(),s=0;for(;n.length>0&&Buffer.byteLength(r,"utf-8")>e;){let a=Math.max(1,Math.floor(n.length*.1));n.splice(-a,a),s+=a,r=JSON.stringify({...t,nodes:n,truncatedNodes:t.truncatedNodes+s});}return {json:r,truncatedBytes:true}}function Mn(t){return t.replace(/\.[A-Za-z0-9]+$/,"")+".dom.json"}function En(t){try{if(!existsSync(t))return null;let e=JSON.parse(readFileSync(t,"utf-8"));return Pi(e)?e:null}catch{return null}}function Pn(t,e){try{return mkdirSync(dirname(t),{recursive:!0}),writeFileSync(t,e,"utf-8"),!0}catch{return false}}function Pi(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.version=="string"&&Array.isArray(e.nodes)&&Array.isArray(e.captureBox)&&e.captureBox.length===4}var Li=new Set(["moved","resized"]);function Le(t){return t.some(e=>!Li.has(e))}function Ft(t){let e=t.t;if(t.i&&(e+="#"+t.i),t.c){let r=t.c.split(" ").filter(Boolean).slice(0,3);r.length>0&&(e+="."+r.join("."));}return e}function Ni(t,e){let r=[],n=Math.abs(t.r[0]-e.r[0]),s=Math.abs(t.r[1]-e.r[1]),a=Math.abs(t.r[2]-e.r[2]),o=Math.abs(t.r[3]-e.r[3]);return (n>1||s>1)&&r.push("moved"),(a>1||o>1)&&r.push("resized"),r}function Di(t,e){let r=t.s??{},n=e.s??{},s=new Set([...Object.keys(r),...Object.keys(n)]),a=[];for(let o of s){let i=r[o],d=n[o];i!==d&&a.push({prop:o,from:i??"(initial)",to:d??"(initial)"});}return a.sort((o,i)=>o.prop.localeCompare(i.prop)),a}function Ln(t){return t.i?"i:"+t.t+"#"+t.i:t.c?"c:"+t.t+"."+t.c:null}function Fi(t,e){let r=new Map;for(let u of t)r.set(u.p,u);let n=[],s=[],a=new Set;for(let u of e){let f=r.get(u.p);if(f&&f.t!==u.t){s.push(u);continue}f&&!a.has(f)?(a.add(f),n.push({before:f,after:u})):s.push(u);}let o=t.filter(u=>!a.has(u)),i=new Map;for(let u of o){let f=Ln(u);if(!f)continue;let p=i.get(f);p?p.push(u):i.set(f,[u]);}let d=[],l=new Set;for(let u of s){let f=Ln(u),g=(f?i.get(f):void 0)?.find(m=>!l.has(m));g?(l.add(g),n.push({before:g,after:u})):d.push(u);}let c=o.filter(u=>!l.has(u));return {pairs:n,removed:c,added:d}}function Bi(t,e){let r=[];return (t.i??"")!==(e.i??"")&&r.push({prop:"id",from:t.i??"(none)",to:e.i??"(none)"}),(t.c??"")!==(e.c??"")&&r.push({prop:"class",from:t.c??"(none)",to:e.c??"(none)"}),r}function Bt(t,e){let r=(e[2]??0)*(e[3]??0);return r<=0?0:Math.min(1,t.r[2]*t.r[3]/r)}function Nn(t,e,r={}){let n=r.maxChanges??50,s=r.includeText!==false,a=r.includeStyles!==false,o=t.nodes.filter(g=>g.m!==1),i=e.nodes.filter(g=>g.m!==1),{pairs:d,removed:l,added:c}=Fi(o,i),u=[];for(let{before:g,after:m}of d){let h=Ni(g,m),v=a?Di(g,m):[];v.length>0&&h.push("restyled");let y=Bi(g,m);y.length>0&&h.push("attrs");let b=s&&(g.x??"")!==(m.x??"");if(b&&h.push("text"),h.length===0)continue;let k=Bt(m,e.captureBox);u.push({score:k,change:{path:m.p,label:Ft(m),kinds:h,rect:m.r,baselineRect:g.r,areaPct:k,...y.length>0?{attrs:y}:{},...v.length>0?{styles:v}:{},...b?{text:{from:g.x??"",to:m.x??""}}:{}}});}for(let g of c){let m=Bt(g,e.captureBox);u.push({score:m,change:{path:g.p,label:Ft(g),kinds:["added"],rect:g.r,areaPct:m}});}for(let g of l){let m=Bt(g,t.captureBox);u.push({score:m,change:{path:g.p,label:Ft(g),kinds:["removed"],baselineRect:g.r,areaPct:m}});}let f=u.filter(g=>Le(g.change.kinds)).length;return u.sort((g,m)=>{if(f>0){let h=Le(g.change.kinds)?1:0,v=Le(m.change.kinds)?1:0;if(h!==v)return v-h}return m.score-g.score}),{changes:u.slice(0,n).map((g,m)=>({rank:m+1,...g.change,...f>0&&!Le(g.change.kinds)?{consequence:true}:{}})),total:u.length,rootCauses:f}}var Oi="__testrelic_snapshot_path_probe__.png",Dn=Symbol.for("testrelic.snapshotPathWarned");function qi(){let t=globalThis,e=t[Dn];return e||(e={warned:false},t[Dn]=e),e}function Ne(t){try{let e=t.snapshotPath(Oi,{kind:"screenshot"});return typeof e=="string"&&!e.includes("[object Object]")}catch{return false}}function De(t){let e=qi();e.warned||(e.warned=true,process.stderr.write(`[testrelic] ${t} needs Playwright >= 1.51 for testInfo.snapshotPath(name, { kind }); this project's Playwright resolves that call the older way. Everything else in the reporter is unaffected \u2014 upgrade Playwright to enable it.
4255
- `));}var Ot="testrelic-visual-dom",Vi=new Set(["toHaveScreenshot","toMatchVisualBaseline"]);function Fn(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.boundingBox=="function"&&typeof e.page=="function"}function $i(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.evaluate=="function"&&typeof e.screenshot=="function"}function Wi(t){let e=t[0];if(typeof e=="string")return e;if(Array.isArray(e))return e.join("/");if(typeof e=="object"&&e!==null){let r=e.name;if(typeof r=="string")return r}return null}function Gi(t){for(let e of t)if(typeof e=="object"&&e!==null&&!Array.isArray(e))return e;return {}}function Ki(t){let e=t.mask;return Array.isArray(e)?e.filter(r=>typeof r=="object"&&r!==null&&typeof r.boundingBox=="function"):[]}function Ji(t){return /\.(png|jpg|jpeg)$/i.test(t)?t:`${t}.png`}var Yi=/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/;function Xi(t,e,r){let n=t.attachments;for(let s=e;s<n.length;s++){let a=Yi.exec(n[s]?.name??"");if(a)return a[1]}return r}async function Zi(t){let e=Gi(t.args),r=Fn(t.received)?t.received:null,n=r?r.page():t.received;return _n({target:n,bounded:r,maskLocators:Ki(e),fullPage:e.fullPage===true})}function Qi(t){let e=t.config?.updateSnapshots;return e==="all"||e==="changed"}async function eo(t,e){let r=Wi(t.args);if(!r)return;if(!Ne(t.testInfo)){De("DOM comparison");return}let n=t.testInfo.snapshotPath(Ji(r),{kind:"screenshot"}),s=Mn(n),a=Xi(t.testInfo,t.attachedBefore,basename(n,extname(n))),o=In(e),d=Qi(t.testInfo)?null:En(s);if(!d){Pn(s,o.json);return}let{changes:l,total:c,rootCauses:u}=Nn(d,e),f;try{f=t.testInfo.outputPath(`${a}.actual.dom.json`),writeFileSync(f,o.json,"utf-8");}catch{f=void 0;}let p={stem:a,changes:l,total:c,rootCauses:u,truncated:o.truncatedBytes||e.truncatedNodes>0,captureBox:e.captureBox,...existsSync(s)?{baselineDomPath:s}:{},...f?{actualDomPath:f}:{}};await t.testInfo.attach(Ot,{body:Buffer.from(JSON.stringify([p])),contentType:"application/json"});}function Bn(t,e){let r=function(o,...i){let d=t(o,...i);return !(Fn(o)||$i(o))||typeof d!="object"||d===null?d:new Proxy(d,{get(c,u,f){let p=Reflect.get(c,u,f);if(typeof u!="string"||!Vi.has(u)||typeof p!="function")return p;let g=p;return async function(...h){let v=e(),y=null,b=v?.attachments.length??0;if(v)try{y=await Zi({received:o,args:h,testInfo:v,attachedBefore:b});}catch{}try{return await g.apply(c,h)}finally{if(v&&y)try{await eo({received:o,args:h,testInfo:v,attachedBefore:b},y);}catch{}}}}})},n=t,s=r;for(let a of Object.keys(n))s[a]=n[a];return r}var qt="testrelic-visual",to=/^(.+)-(expected|actual|diff|previous)(\.[A-Za-z0-9]+)$/;function ro(t){let e=new Map;for(let r of t)if(!(r.name!==qt||!r.body))try{let n=JSON.parse(r.body.toString("utf-8"));if(!Array.isArray(n))continue;for(let s of n){let a=so(s);a&&e.set(a.stem,a);}}catch{}return e}var no=["passed","failed","new","updated"];function so(t){if(typeof t!="object"||t===null)return null;let e=t;return typeof e.stem!="string"||!e.stem||typeof e.name!="string"||!e.name||typeof e.status!="string"||!no.includes(e.status)?null:{stem:e.stem,name:e.name,status:e.status}}function ao(t){let e=new Map;for(let r of t)if(!(r.name!==Ot||!r.body))try{let n=JSON.parse(r.body.toString("utf-8"));if(!Array.isArray(n))continue;for(let s of n){if(typeof s!="object"||s===null)continue;let a=s;typeof a.stem!="string"||!Array.isArray(a.changes)||e.set(a.stem,s);}}catch{}return e}function io(t){let e=new Map;for(let r of t){if(!r.path)continue;let n=to.exec(r.name);if(!n)continue;let[,s,a]=n,o=e.get(s)??{};o[a]=r.path,e.set(s,o);}return e}function oo(t){return !!(t.actual&&(t.expected||t.diff))}function lo(t,e,r){return t.diff||Ee(r)?"failed":e?"updated":"new"}function co(t,e){if(t.length===0)return null;if(t.length===1)return t[0];if(!e)return null;let r=e.replace(/\.[A-Za-z0-9]+$/,""),n=t.filter(s=>s===r||s.endsWith(`/${r}`));return n.length===1?n[0]:null}function qn(t,e={}){if(t.length===0)return [];let r=ro(t),n=ao(t),s=io(t);if(s.size===0)return [];let a=e.updatingSnapshots===true,o=[];for(let[i,d]of s){let l=r.get(i);!l&&!oo(d)||o.push({name:l?.name??i,status:l?.status??lo(d,a,e.failureMessage),source:l?"toMatchVisualBaseline":"toHaveScreenshot",...d.expected?{expectedPath:d.expected}:{},...d.actual?{actualPath:d.actual}:{},...d.diff?{diffPath:d.diff}:{},...d.previous?{previousPath:d.previous}:{},...n.has(i)?{dom:n.get(i)}:{}});}return uo(o,s,e.failureMessage)}function uo(t,e,r){let n=bn(r);if(n.diffPixels===void 0&&n.actualWidth===void 0)return [...t];let s=t.filter(o=>o.status==="failed").map(o=>On(o,e)),a=co(s,n.snapshotName);return a===null?[...t]:t.map(o=>On(o,e)===a?{...o,...n.diffPixels!==void 0?{diffPixels:n.diffPixels}:{},...n.actualWidth!==void 0?{actualWidth:n.actualWidth}:{},...n.actualHeight!==void 0?{actualHeight:n.actualHeight}:{}}:o)}function On(t,e){if(e.has(t.name))return t.name;for(let[r,n]of e)if(n.actual===t.actualPath&&n.expected===t.expectedPath&&n.diff===t.diffPath)return r;return t.name}var po=new RegExp("[\x1B\x9B][[\\]()#;?]*(?:\\d{1,4}(?:;\\d{0,4})*)?[0-9A-PR-TZcf-nqry=><]","g");function se(t){return !t||t.indexOf("\x1B")===-1&&t.indexOf("\x9B")===-1?t:t.replace(po,"")}function Un(t){return t==null?null:se(t)}var fo=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,go="1.0",Ut="visual";function Vn(t){let e=extname(t).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(e)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(e)?"video":e===".zip"&&basename(t,e)==="trace"?"trace":"other"}function ho(t){if(t.endsWith(".dom.json"))return "dom";let e=basename(t,extname(t));return e==="baseline"?"baseline":e==="diff"?"diff":Vn(t)}function mo(t,e,r){let n=[];try{for(let s of readdirSync(t,{withFileTypes:!0})){if(!s.isFile())continue;let a=statSync(join(t,s.name));n.push({name:`${Ut}/${r}/${s.name}`,type:ho(s.name),relativePath:`${e}/${Ut}/${r}/${s.name}`,sizeBytes:a.size});}}catch{}return n}function $n(t,e,r){let n=[],s=`artifacts/${e}/${r}`;try{let a=readdirSync(t,{withFileTypes:!0});for(let o of a){if(o.isDirectory()&&o.name===Ut){let l=join(t,o.name);for(let c of readdirSync(l,{withFileTypes:!0}))c.isDirectory()&&n.push(...mo(join(l,c.name),s,c.name));continue}if(!o.isFile())continue;let i=join(t,o.name),d=statSync(i);n.push({name:o.name,type:Vn(o.name),relativePath:`${s}/${o.name}`,sizeBytes:d.size});}}catch{}return {testName:r,files:n}}function vo(t,e){let r=join(t,e),n=[],s=0;try{let o=readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let d=$n(join(r,i.name),e,i.name);n.push(d);for(let l of d.files)s+=l.sizeBytes;}}catch{}let a=e.replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/,"$1T$2:$3:$4").replace(/-\d+$/,"");return n.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:e,timestamp:a,totalSizeBytes:s,testCount:n.length,tests:n,isCurrentRun:false}}function Wn(t,e){let r=join(t,"artifacts"),n=[],s=[],a=0;try{let i=readdirSync(r,{withFileTypes:!0});for(let d of i)if(d.isDirectory())if(fo.test(d.name)){let l=vo(r,d.name);n.push({...l,isCurrentRun:d.name===e});}else {let l=$n(join(r,d.name),d.name,d.name);s.push(l);for(let c of l.files)a+=c.sizeBytes;}}catch{}n.sort((i,d)=>d.timestamp.localeCompare(i.timestamp)),s.length>0&&(s.sort((i,d)=>i.testName.localeCompare(d.testName)),n.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:a,testCount:s.length,tests:s,isCurrentRun:false}));let o=n.reduce((i,d)=>i+d.totalSizeBytes,0);return {schemaVersion:go,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:n,serverPort:null}}var Co=256;function To(t){let e=resolve(t);for(let r=0;r<Co;r++){if(existsSync(join(e,".git")))return e;let n=dirname(e);if(n===e)return null;e=n;}return null}function Jn(t){try{let e=To(t);if(!e)return;let r=join(e,".gitignore"),n=relative(e,t).replace(/\\/g,"/"),s=n.endsWith("/")?n:`${n}/`;if(existsSync(r)&&readFileSync(r,"utf-8").split(`
4253
+ `);try{let h=Ct(l,c,n,u),v=i+".tmp";writeFileSync(v,h,"utf-8"),renameSync(v,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let g=dirname(e.outputPath),f=join(g,"artifacts");if(existsSync(f))try{let m=await cn(f);n=m.port,process.on("exit",()=>{m.dispose();});}catch{}}if(e.openReport&&t.ci===null)if(a&&n)Tt(`http://127.0.0.1:${n}`);else {let g=resolve(i);Tt(g);}}catch(n){process.stderr.write(`[testrelic] Failed to write HTML report: ${n instanceof Error?n.message:String(n)}
4254
+ `);}}var Ie=9323,hn=10;async function ti(){for(let t=Ie;t<Ie+hn;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),500),n=await fetch(`http://127.0.0.1:${t}/api/health`,{signal:e.signal});if(clearTimeout(r),n.ok)return t}catch{}return null}async function ri(){for(let t=Ie;t<Ie+hn;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),1e3);await fetch(`http://127.0.0.1:${t}/api/shutdown`,{method:"POST",signal:e.signal}),clearTimeout(r);}catch{}await new Promise(t=>setTimeout(t,300));}async function ni(t){let r=[join(__dirname,"cli.cjs"),join(__dirname,"cli.js"),join(__dirname,"..","dist","cli.cjs"),join(__dirname,"..","dist","cli.js")].find(n=>existsSync(n));if(!r){let n=await me(t);return process.on("exit",()=>{n?.dispose();}),n.port}return new Promise(n=>{let s=spawn(process.execPath,[r,"serve",t],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),a="",o=false,i=setTimeout(()=>{o||(o=true,s.stderr?.removeAllListeners(),ti().then(n));},5e3);s.stderr?.on("data",d=>{a+=d.toString();let l=a.match(/127\.0\.0\.1:(\d+)/);l&&!o&&(o=true,clearTimeout(i),s.stderr?.removeAllListeners(),s.unref(),n(Number(l[1])));}),s.on("error",()=>{o||(o=true,clearTimeout(i),n(null));}),s.on("exit",()=>{o||(o=true,clearTimeout(i),n(null));}),s.unref();})}var mn=Buffer.from([137,80,78,71,13,10,26,10]),si=16,ai=20,Me=24;function vn(t){if(t.length<Me||!t.subarray(0,mn.length).equals(mn))return null;let e=t.readUInt32BE(si),r=t.readUInt32BE(ai);return e===0||r===0?null:{width:e,height:r}}var ii=/(\d+) pixels \(ratio [\d.]+ of all image pixels\) are different/,yn=/Expected an image (\d+)px by (\d+)px, received (\d+)px by (\d+)px/;function Pe(t){return t?yn.test(t):false}var oi=/^\s*Snapshot:\s*(.+?)\s*$/m;function bn(t){if(!t)return {};let e={},r=ii.exec(t);if(r){let a=Number.parseInt(r[1],10);Number.isFinite(a)&&(e.diffPixels=a);}let n=yn.exec(t);if(n){let[,a,o,i,d]=n,l=[a,o,i,d].map(c=>Number.parseInt(c,10));l.every(c=>Number.isFinite(c))&&(e.expectedWidth=l[0],e.expectedHeight=l[1],e.actualWidth=l[2],e.actualHeight=l[3]);}let s=oi.exec(t);return s&&(e.snapshotName=s[1]),e}function xn(t,e){if(t===void 0||!e)return;let r=e.width*e.height;if(!(r<=0))return t/r}var gi=20,Pt=0,Et=[];async function ve(t,e){Pt>=gi&&await new Promise(r=>Et.push(r)),Pt++;try{return await copyFile(t,e),!0}catch{return false}finally{Pt--,Et.length>0&&Et.shift()();}}var W=[];async function kn(){W.length!==0&&(await Promise.allSettled(W),W.length=0);}function Cn(t){let e=new Date,r=a=>String(a).padStart(2,"0"),n=`${e.getFullYear()}-${r(e.getMonth()+1)}-${r(e.getDate())}T${r(e.getHours())}-${r(e.getMinutes())}-${r(e.getSeconds())}`;if(!existsSync(join(t,n)))return n;let s=1;for(;existsSync(join(t,`${n}-${s}`));)s++;return `${n}-${s}`}function Lt(t){let e=t.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return e.length>100&&(e=e.substring(0,100).replace(/-+$/,"")),e||"unnamed-test"}var hi=8;function Tn(t,e,r){let n=Lt(t),s=r?Lt(r).substring(0,hi):"";return s&&(n+=`--${s}`),e>0&&(n+=`--retry-${e}`),n}function Sn(t,e,r,n,s,a){let o=t.find(f=>f.name==="screenshot"&&f.path),i=t.find(f=>f.name==="video"&&f.path),d=t.find(f=>f.name==="trace"&&f.path);if(!o&&!i&&!d)return null;let l=Tn(e,r,a),c=s?["artifacts",s,l]:["artifacts",l],u=join(n,...c),p=c,g={};try{mkdirSync(u,{recursive:!0});}catch{return null}if(o?.path&&existsSync(o.path)){let m=`screenshot${extname(o.path)||".png"}`,h=join(u,m);W.push(ve(o.path,h).then(()=>{})),g.screenshot=`${p.join("/")}/${m}`;}if(i?.path&&existsSync(i.path)){let m=`video${extname(i.path)||".webm"}`,h=join(u,m);W.push(ve(i.path,h).then(()=>{})),g.video=`${p.join("/")}/${m}`;}if(d?.path&&existsSync(d.path)){let m=`trace${extname(d.path)||".zip"}`,h=join(u,m);W.push(ve(d.path,h).then(()=>{})),g.trace=`${p.join("/")}/${m}`;}return !g.screenshot&&!g.video&&!g.trace?null:g}var Nt="visual",mi=6;function vi(t){let e=createHash("sha256").update(t).digest("hex").substring(0,mi);return `${Lt(t)}--${e}`}function wn(t){let e=null;try{e=openSync(t,"r");let r=Buffer.alloc(Me),n=readSync(e,r,0,Me,0);return vn(r.subarray(0,n))}catch{return null}finally{if(e!==null)try{closeSync(e);}catch{}}}var yi=[{key:"expectedPath",dest:"baseline",field:"baseline"},{key:"actualPath",dest:"actual",field:"actual"},{key:"diffPath",dest:"diff",field:"diff"},{key:"previousPath",dest:"previous",field:"previous"}],bi=[{key:"baselineDomPath",dest:"baseline.dom.json",field:"baselineDom"},{key:"actualDomPath",dest:"actual.dom.json",field:"actualDom"}];function xi(t,e,r){let n=vi(t.name),s=join(e,n);try{mkdirSync(s,{recursive:!0});}catch{return null}let a={},o=false;for(let u of yi){let p=t[u.key];if(!p||!existsSync(p))continue;let g=extname(p)||".png",f=`${u.dest}${g}`;W.push(ve(p,join(s,f)).then(()=>{})),a[u.field]=`${r}/${Nt}/${n}/${f}`,o=true;}let i=t.dom;if(i)for(let u of bi){let p=i[u.key];!p||!existsSync(p)||(W.push(ve(p,join(s,u.dest)).then(()=>{})),a[u.field]=`${r}/${Nt}/${n}/${u.dest}`);}if(!o)return null;let d=t.expectedPath?wn(t.expectedPath):t.actualPath?wn(t.actualPath):null,l=xn(t.diffPixels,d),c=t.expectedPath?relative(process.cwd(),t.expectedPath).replace(/\\/g,"/"):void 0;return {name:t.name,status:t.status,source:t.source,...a,...c?{baselinePath:c}:{},...d?{width:d.width,height:d.height}:{},...t.actualWidth!==void 0?{actualWidth:t.actualWidth}:{},...t.actualHeight!==void 0?{actualHeight:t.actualHeight}:{},...t.diffPixels!==void 0?{diffPixels:t.diffPixels}:{},...l!==void 0?{diffPixelRatio:l}:{},...i?{domChanges:i.changes,domChangeCount:i.total,domRootCauses:i.rootCauses,domTruncated:i.truncated,domCaptureBox:i.captureBox}:{}}}function Rn(t,e,r,n,s,a){if(t.length===0)return null;let o=Tn(e,r,a),i=s?["artifacts",s,o]:["artifacts",o],d=join(n,...i,Nt),l=i.join("/");try{mkdirSync(d,{recursive:!0});}catch{return null}let c=[];for(let u of t){let p=xi(u,d,l);p&&c.push(p);}return c.length>0?c:null}function An(t){let{styleProps:e,defaults:r,inherited:n,maxNodes:s,maxText:a,maskBoxes:o,viewportBox:i,fullPage:d}=t,l={};for(let T=0;T<n.length;T++)l[n[T]]=true;let c=window.scrollX||window.pageXOffset||0,u=window.scrollY||window.pageYOffset||0,p=[],g=0,f=[];for(let T=0;T<o.length;T++){let x=o[T];f.push([x[0]+c,x[1]+u,x[2],x[3]]);}function m(T,x,S,w){for(let C=0;C<f.length;C++){let _=f[C];if(T<_[0]+_[2]&&T+S>_[0]&&x<_[1]+_[3]&&x+w>_[1])return true}return false}function h(T){let x=T.parentElement;if(!x)return 0;let S=x.children,w=0;for(let C=0;C<S.length;C++){let _=S[C];if(_===T)break;_.tagName===T.tagName&&w++;}return w}function v(T){let x="",S=T.childNodes;for(let w=0;w<S.length;w++){let C=S[w];C.nodeType===3&&(x+=C.nodeValue??"");}return x=x.replace(/\s+/g," ").trim(),x.length>a?x.slice(0,a):x}function y(T,x){let S;for(let w=0;w<e.length;w++){let C=e[w],_=T.getPropertyValue(C);if(_){if(l[C]){if(x&&x.getPropertyValue(C)===_)continue}else if(r[C]===_)continue;S||(S={}),S[C]=_;}}return S}let b=[{el:document.body,parentPath:"",parentComputed:null}];for(;b.length>0;){let T=b.pop(),x=T.el,S=window.getComputedStyle(x);if(S.display==="none")continue;let w=x.tagName.toLowerCase(),C=x.id?"#"+x.id:T.parentPath?T.parentPath+">"+w+"["+h(x)+"]":w,_=x.children;for(let E=_.length-1;E>=0;E--)b.push({el:_[E],parentPath:C,parentComputed:S});if(S.visibility==="hidden")continue;let L=x.getBoundingClientRect();if(L.width<=0||L.height<=0)continue;if(p.length>=s){g++;continue}let z=Math.round(L.left+c),ce=Math.round(L.top+u),ue=Math.round(L.width),pe=Math.round(L.height),I={p:C,t:w,r:[z,ce,ue,pe]};x.id&&(I.i=x.id);let M=x.getAttribute("class");M&&(I.c=M.replace(/\s+/g," ").trim());let N=v(x);N&&(I.x=N);let j=y(S,T.parentComputed);j&&(I.s=j),m(z,ce,ue,pe)&&(I.m=1),p.push(I);}let k=Math.max(document.documentElement.scrollWidth,window.innerWidth),A=Math.max(document.documentElement.scrollHeight,window.innerHeight),P;return i?P=[Math.round(i[0]+c),Math.round(i[1]+u),Math.round(i[2]),Math.round(i[3])]:d?P=[0,0,k,A]:P=[Math.round(c),Math.round(u),window.innerWidth,window.innerHeight],{version:"1.0",url:location.href,viewport:{width:window.innerWidth,height:window.innerHeight},content:{width:k,height:A},captureBox:P,nodes:p,truncatedNodes:g}}var Ri=["display","position","color","background-color","background-image","border-top-width","border-right-width","border-bottom-width","border-left-width","border-color","border-style","border-radius","box-shadow","opacity","transform","margin-top","margin-right","margin-bottom","margin-left","padding-top","padding-right","padding-bottom","padding-left","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-decoration-line","text-transform","flex-direction","justify-content","align-items","gap","z-index","overflow"],Ai={position:"static","background-color":"rgba(0, 0, 0, 0)","background-image":"none","border-top-width":"0px","border-right-width":"0px","border-bottom-width":"0px","border-left-width":"0px","border-style":"none","border-radius":"0px","box-shadow":"none",opacity:"1",transform:"none","margin-top":"0px","margin-right":"0px","margin-bottom":"0px","margin-left":"0px","padding-top":"0px","padding-right":"0px","padding-bottom":"0px","padding-left":"0px","text-decoration-line":"none","flex-direction":"row","justify-content":"normal","align-items":"normal",gap:"normal","z-index":"auto",overflow:"visible"},_i=["color","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-transform"],Ii=1024*1024,Mi=1500,Pi=200;async function Ei(t){let e=[];for(let r of t)try{let n=await r.boundingBox();n&&e.push([n.x,n.y,n.width,n.height]);}catch{}return e}async function _n(t){let e=t.config??{};try{let r=t.maskLocators?.length?await Ei(t.maskLocators):[],n=null;if(t.bounded){let a=await t.bounded.boundingBox();a&&(n=[a.x,a.y,a.width,a.height]);}let s={styleProps:Ri,defaults:Ai,inherited:_i,maxNodes:e.maxNodes??Mi,maxText:e.maxText??Pi,maskBoxes:r,viewportBox:n,fullPage:t.fullPage===!0};return await t.target.evaluate(An,s)}catch{return null}}function In(t,e=Ii){let r=JSON.stringify(t);if(Buffer.byteLength(r,"utf-8")<=e)return {json:r,truncatedBytes:false};let n=t.nodes.slice(),s=0;for(;n.length>0&&Buffer.byteLength(r,"utf-8")>e;){let a=Math.max(1,Math.floor(n.length*.1));n.splice(-a,a),s+=a,r=JSON.stringify({...t,nodes:n,truncatedNodes:t.truncatedNodes+s});}return {json:r,truncatedBytes:true}}function Mn(t){return t.replace(/\.[A-Za-z0-9]+$/,"")+".dom.json"}function Pn(t){try{if(!existsSync(t))return null;let e=JSON.parse(readFileSync(t,"utf-8"));return Li(e)?e:null}catch{return null}}function En(t,e){try{return mkdirSync(dirname(t),{recursive:!0}),writeFileSync(t,e,"utf-8"),!0}catch{return false}}function Li(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.version=="string"&&Array.isArray(e.nodes)&&Array.isArray(e.captureBox)&&e.captureBox.length===4}var Ni=new Set(["moved","resized"]);function Le(t){return t.some(e=>!Ni.has(e))}function Ft(t){let e=t.t;if(t.i&&(e+="#"+t.i),t.c){let r=t.c.split(" ").filter(Boolean).slice(0,3);r.length>0&&(e+="."+r.join("."));}return e}function Di(t,e){let r=[],n=Math.abs(t.r[0]-e.r[0]),s=Math.abs(t.r[1]-e.r[1]),a=Math.abs(t.r[2]-e.r[2]),o=Math.abs(t.r[3]-e.r[3]);return (n>1||s>1)&&r.push("moved"),(a>1||o>1)&&r.push("resized"),r}function Fi(t,e){let r=t.s??{},n=e.s??{},s=new Set([...Object.keys(r),...Object.keys(n)]),a=[];for(let o of s){let i=r[o],d=n[o];i!==d&&a.push({prop:o,from:i??"(initial)",to:d??"(initial)"});}return a.sort((o,i)=>o.prop.localeCompare(i.prop)),a}function Ln(t){return t.i?"i:"+t.t+"#"+t.i:t.c?"c:"+t.t+"."+t.c:null}function Bi(t,e){let r=new Map;for(let u of t)r.set(u.p,u);let n=[],s=[],a=new Set;for(let u of e){let p=r.get(u.p);if(p&&p.t!==u.t){s.push(u);continue}p&&!a.has(p)?(a.add(p),n.push({before:p,after:u})):s.push(u);}let o=t.filter(u=>!a.has(u)),i=new Map;for(let u of o){let p=Ln(u);if(!p)continue;let g=i.get(p);g?g.push(u):i.set(p,[u]);}let d=[],l=new Set;for(let u of s){let p=Ln(u),f=(p?i.get(p):void 0)?.find(m=>!l.has(m));f?(l.add(f),n.push({before:f,after:u})):d.push(u);}let c=o.filter(u=>!l.has(u));return {pairs:n,removed:c,added:d}}function Oi(t,e){let r=[];return (t.i??"")!==(e.i??"")&&r.push({prop:"id",from:t.i??"(none)",to:e.i??"(none)"}),(t.c??"")!==(e.c??"")&&r.push({prop:"class",from:t.c??"(none)",to:e.c??"(none)"}),r}function Bt(t,e){let r=(e[2]??0)*(e[3]??0);return r<=0?0:Math.min(1,t.r[2]*t.r[3]/r)}function Nn(t,e,r={}){let n=r.maxChanges??50,s=r.includeText!==false,a=r.includeStyles!==false,o=t.nodes.filter(f=>f.m!==1),i=e.nodes.filter(f=>f.m!==1),{pairs:d,removed:l,added:c}=Bi(o,i),u=[];for(let{before:f,after:m}of d){let h=Di(f,m),v=a?Fi(f,m):[];v.length>0&&h.push("restyled");let y=Oi(f,m);y.length>0&&h.push("attrs");let b=s&&(f.x??"")!==(m.x??"");if(b&&h.push("text"),h.length===0)continue;let k=Bt(m,e.captureBox);u.push({score:k,change:{path:m.p,label:Ft(m),kinds:h,rect:m.r,baselineRect:f.r,areaPct:k,...y.length>0?{attrs:y}:{},...v.length>0?{styles:v}:{},...b?{text:{from:f.x??"",to:m.x??""}}:{}}});}for(let f of c){let m=Bt(f,e.captureBox);u.push({score:m,change:{path:f.p,label:Ft(f),kinds:["added"],rect:f.r,areaPct:m}});}for(let f of l){let m=Bt(f,t.captureBox);u.push({score:m,change:{path:f.p,label:Ft(f),kinds:["removed"],baselineRect:f.r,areaPct:m}});}let p=u.filter(f=>Le(f.change.kinds)).length;return u.sort((f,m)=>{if(p>0){let h=Le(f.change.kinds)?1:0,v=Le(m.change.kinds)?1:0;if(h!==v)return v-h}return m.score-f.score}),{changes:u.slice(0,n).map((f,m)=>({rank:m+1,...f.change,...p>0&&!Le(f.change.kinds)?{consequence:true}:{}})),total:u.length,rootCauses:p}}var qi="__testrelic_snapshot_path_probe__.png",Dn=Symbol.for("testrelic.snapshotPathWarned");function Hi(){let t=globalThis,e=t[Dn];return e||(e={warned:false},t[Dn]=e),e}function Ne(t){try{let e=t.snapshotPath(qi,{kind:"screenshot"});return typeof e=="string"&&!e.includes("[object Object]")}catch{return false}}function De(t){let e=Hi();e.warned||(e.warned=true,process.stderr.write(`[testrelic] ${t} needs Playwright >= 1.51 for testInfo.snapshotPath(name, { kind }); this project's Playwright resolves that call the older way. Everything else in the reporter is unaffected \u2014 upgrade Playwright to enable it.
4255
+ `));}var Ot="testrelic-visual-dom",$i=new Set(["toHaveScreenshot","toMatchVisualBaseline"]);function Fn(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.boundingBox=="function"&&typeof e.page=="function"}function Wi(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.evaluate=="function"&&typeof e.screenshot=="function"}function Gi(t){let e=t[0];if(typeof e=="string")return e;if(Array.isArray(e))return e.join("/");if(typeof e=="object"&&e!==null){let r=e.name;if(typeof r=="string")return r}return null}function Ki(t){for(let e of t)if(typeof e=="object"&&e!==null&&!Array.isArray(e))return e;return {}}function Ji(t){let e=t.mask;return Array.isArray(e)?e.filter(r=>typeof r=="object"&&r!==null&&typeof r.boundingBox=="function"):[]}function Yi(t){return /\.(png|jpg|jpeg)$/i.test(t)?t:`${t}.png`}var Xi=/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/;function Zi(t,e,r){let n=t.attachments;for(let s=e;s<n.length;s++){let a=Xi.exec(n[s]?.name??"");if(a)return a[1]}return r}async function Qi(t){let e=Ki(t.args),r=Fn(t.received)?t.received:null,n=r?r.page():t.received;return _n({target:n,bounded:r,maskLocators:Ji(e),fullPage:e.fullPage===true})}function eo(t){let e=t.config?.updateSnapshots;return e==="all"||e==="changed"}async function to(t,e){let r=Gi(t.args);if(!r)return;if(!Ne(t.testInfo)){De("DOM comparison");return}let n=t.testInfo.snapshotPath(Yi(r),{kind:"screenshot"}),s=Mn(n),a=Zi(t.testInfo,t.attachedBefore,basename(n,extname(n))),o=In(e),d=eo(t.testInfo)?null:Pn(s);if(!d){En(s,o.json);return}let{changes:l,total:c,rootCauses:u}=Nn(d,e),p;try{p=t.testInfo.outputPath(`${a}.actual.dom.json`),writeFileSync(p,o.json,"utf-8");}catch{p=void 0;}let g={stem:a,changes:l,total:c,rootCauses:u,truncated:o.truncatedBytes||e.truncatedNodes>0,captureBox:e.captureBox,...existsSync(s)?{baselineDomPath:s}:{},...p?{actualDomPath:p}:{}};await t.testInfo.attach(Ot,{body:Buffer.from(JSON.stringify([g])),contentType:"application/json"});}function Bn(t,e){let r=function(o,...i){let d=t(o,...i);return !(Fn(o)||Wi(o))||typeof d!="object"||d===null?d:new Proxy(d,{get(c,u,p){let g=Reflect.get(c,u,p);if(typeof u!="string"||!$i.has(u)||typeof g!="function")return g;let f=g;return async function(...h){let v=e(),y=null,b=v?.attachments.length??0;if(v)try{y=await Qi({received:o,args:h,testInfo:v,attachedBefore:b});}catch{}try{return await f.apply(c,h)}finally{if(v&&y)try{await to({received:o,args:h,testInfo:v,attachedBefore:b},y);}catch{}}}}})},n=t,s=r;for(let a of Object.keys(n))s[a]=n[a];return r}var qt="testrelic-visual",ro=/^(.+)-(expected|actual|diff|previous)(\.[A-Za-z0-9]+)$/;function no(t){let e=new Map;for(let r of t)if(!(r.name!==qt||!r.body))try{let n=JSON.parse(r.body.toString("utf-8"));if(!Array.isArray(n))continue;for(let s of n){let a=ao(s);a&&e.set(a.stem,a);}}catch{}return e}var so=["passed","failed","new","updated"];function ao(t){if(typeof t!="object"||t===null)return null;let e=t;return typeof e.stem!="string"||!e.stem||typeof e.name!="string"||!e.name||typeof e.status!="string"||!so.includes(e.status)?null:{stem:e.stem,name:e.name,status:e.status}}function io(t){let e=new Map;for(let r of t)if(!(r.name!==Ot||!r.body))try{let n=JSON.parse(r.body.toString("utf-8"));if(!Array.isArray(n))continue;for(let s of n){if(typeof s!="object"||s===null)continue;let a=s;typeof a.stem!="string"||!Array.isArray(a.changes)||e.set(a.stem,s);}}catch{}return e}function oo(t){let e=new Map;for(let r of t){if(!r.path)continue;let n=ro.exec(r.name);if(!n)continue;let[,s,a]=n,o=e.get(s)??{};o[a]=r.path,e.set(s,o);}return e}function lo(t){return !!(t.actual&&(t.expected||t.diff))}function co(t,e,r){return t.diff||Pe(r)?"failed":e?"updated":"new"}function uo(t,e){if(t.length===0)return null;if(t.length===1)return t[0];if(!e)return null;let r=e.replace(/\.[A-Za-z0-9]+$/,""),n=t.filter(s=>s===r||s.endsWith(`/${r}`));return n.length===1?n[0]:null}function qn(t,e={}){if(t.length===0)return [];let r=no(t),n=io(t),s=oo(t);if(s.size===0)return [];let a=e.updatingSnapshots===true,o=[];for(let[i,d]of s){let l=r.get(i);!l&&!lo(d)||o.push({name:l?.name??i,status:l?.status??co(d,a,e.failureMessage),source:l?"toMatchVisualBaseline":"toHaveScreenshot",...d.expected?{expectedPath:d.expected}:{},...d.actual?{actualPath:d.actual}:{},...d.diff?{diffPath:d.diff}:{},...d.previous?{previousPath:d.previous}:{},...n.has(i)?{dom:n.get(i)}:{}});}return fo(po(o),s,e.failureMessage)}function po(t){let e=new Map;for(let n of t)n.source==="toMatchVisualBaseline"&&e.set(n.name,n);if(e.size===0)return [...t];let r=[];for(let n of t){if(n.source==="toMatchVisualBaseline"){r.push(n);continue}let s=e.get(n.name);if(!s){r.push(n);continue}let a={...s,...s.expectedPath===void 0&&n.expectedPath?{expectedPath:n.expectedPath}:{},...s.actualPath===void 0&&n.actualPath?{actualPath:n.actualPath}:{},...s.diffPath===void 0&&n.diffPath?{diffPath:n.diffPath}:{},...s.previousPath===void 0&&n.previousPath?{previousPath:n.previousPath}:{},...s.dom===void 0&&n.dom?{dom:n.dom}:{}},o=r.indexOf(s);o>=0&&(r[o]=a),e.set(n.name,a);}return r}function fo(t,e,r){let n=bn(r);if(n.diffPixels===void 0&&n.actualWidth===void 0)return [...t];let s=t.filter(o=>o.status==="failed").map(o=>On(o,e)),a=uo(s,n.snapshotName);return a===null?[...t]:t.map(o=>On(o,e)===a?{...o,...n.diffPixels!==void 0?{diffPixels:n.diffPixels}:{},...n.actualWidth!==void 0?{actualWidth:n.actualWidth}:{},...n.actualHeight!==void 0?{actualHeight:n.actualHeight}:{}}:o)}function On(t,e){if(e.has(t.name))return t.name;for(let[r,n]of e)if(n.actual===t.actualPath&&n.expected===t.expectedPath&&n.diff===t.diffPath)return r;return t.name}var go=new RegExp("[\x1B\x9B][[\\]()#;?]*(?:\\d{1,4}(?:;\\d{0,4})*)?[0-9A-PR-TZcf-nqry=><]","g");function se(t){return !t||t.indexOf("\x1B")===-1&&t.indexOf("\x9B")===-1?t:t.replace(go,"")}function Hn(t){return t==null?null:se(t)}var ho=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,mo="1.0",Ht="visual";function Vn(t){let e=extname(t).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(e)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(e)?"video":e===".zip"&&basename(t,e)==="trace"?"trace":"other"}function vo(t){if(t.endsWith(".dom.json"))return "dom";let e=basename(t,extname(t));return e==="baseline"?"baseline":e==="diff"?"diff":Vn(t)}function yo(t,e,r){let n=[];try{for(let s of readdirSync(t,{withFileTypes:!0})){if(!s.isFile())continue;let a=statSync(join(t,s.name));n.push({name:`${Ht}/${r}/${s.name}`,type:vo(s.name),relativePath:`${e}/${Ht}/${r}/${s.name}`,sizeBytes:a.size});}}catch{}return n}function $n(t,e,r){let n=[],s=`artifacts/${e}/${r}`;try{let a=readdirSync(t,{withFileTypes:!0});for(let o of a){if(o.isDirectory()&&o.name===Ht){let l=join(t,o.name);for(let c of readdirSync(l,{withFileTypes:!0}))c.isDirectory()&&n.push(...yo(join(l,c.name),s,c.name));continue}if(!o.isFile())continue;let i=join(t,o.name),d=statSync(i);n.push({name:o.name,type:Vn(o.name),relativePath:`${s}/${o.name}`,sizeBytes:d.size});}}catch{}return {testName:r,files:n}}function bo(t,e){let r=join(t,e),n=[],s=0;try{let o=readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let d=$n(join(r,i.name),e,i.name);n.push(d);for(let l of d.files)s+=l.sizeBytes;}}catch{}let a=e.replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/,"$1T$2:$3:$4").replace(/-\d+$/,"");return n.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:e,timestamp:a,totalSizeBytes:s,testCount:n.length,tests:n,isCurrentRun:false}}function Wn(t,e){let r=join(t,"artifacts"),n=[],s=[],a=0;try{let i=readdirSync(r,{withFileTypes:!0});for(let d of i)if(d.isDirectory())if(ho.test(d.name)){let l=bo(r,d.name);n.push({...l,isCurrentRun:d.name===e});}else {let l=$n(join(r,d.name),d.name,d.name);s.push(l);for(let c of l.files)a+=c.sizeBytes;}}catch{}n.sort((i,d)=>d.timestamp.localeCompare(i.timestamp)),s.length>0&&(s.sort((i,d)=>i.testName.localeCompare(d.testName)),n.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:a,testCount:s.length,tests:s,isCurrentRun:false}));let o=n.reduce((i,d)=>i+d.totalSizeBytes,0);return {schemaVersion:mo,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:n,serverPort:null}}var So=256;function Ro(t){let e=resolve(t);for(let r=0;r<So;r++){if(existsSync(join(e,".git")))return e;let n=dirname(e);if(n===e)return null;e=n;}return null}function Jn(t){try{let e=Ro(t);if(!e)return;let r=join(e,".gitignore"),n=relative(e,t).replace(/\\/g,"/"),s=n.endsWith("/")?n:`${n}/`;if(existsSync(r)&&readFileSync(r,"utf-8").split(`
4256
4256
  `).map(d=>d.trim()).some(d=>d===s||d===n))return;let a=`
4257
4257
  # TestRelic test artifacts
4258
4258
  ${s}
4259
- `;appendFileSync(r,a,"utf-8");}catch{}}var Yn=Symbol("testrelic.timeout"),Xn=3e4,Ht=12e4,zt=6e4,Zn=15e3;async function Q(t,e,r){let n,s=new Promise(a=>{n=setTimeout(()=>a(Yn),e),typeof n?.unref=="function"&&n.unref();});try{let a=await Promise.race([t(),s]);if(a===Yn){process.stderr.write(`[testrelic] ${r} timed out after ${Math.round(e/1e3)}s \u2014 continuing without it. Your tests are unaffected.
4259
+ `;appendFileSync(r,a,"utf-8");}catch{}}var Yn=Symbol("testrelic.timeout"),Xn=3e4,Ut=12e4,zt=6e4,Zn=15e3;async function Q(t,e,r){let n,s=new Promise(a=>{n=setTimeout(()=>a(Yn),e),typeof n?.unref=="function"&&n.unref();});try{let a=await Promise.race([t(),s]);if(a===Yn){process.stderr.write(`[testrelic] ${r} timed out after ${Math.round(e/1e3)}s \u2014 continuing without it. Your tests are unaffected.
4260
4260
  `);return}return a}catch(a){process.stderr.write(`[testrelic] ${r} failed \u2014 continuing without it. Your tests are unaffected. (${a instanceof Error?a.message:String(a)})
4261
- `);return}finally{n&&clearTimeout(n);}}function ts(t,e){let r=[];for(let n of t){let s=So(n),a=Ro(n),o=Ao(n,s,a,e),i=_o(n,s,a);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:n.startedAt,durationOnUrl:n.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:n.specFile,test:s,tests:[a],_testTitle:n.title});continue}r.push(...o,...i);}return r.sort(Io),Mo(r,t),r.map((n,s)=>n.type==="navigation"?{...{index:s,type:"navigation",url:n.url,timestamp:n.timestamp,durationOnUrl:n.durationOnUrl??0,navigationType:n.navigationType,domContentLoadedAt:n.domContentLoadedAt??null,networkIdleAt:n.networkIdleAt??null,networkStats:n.networkStats??null,specFile:n.specFile,test:n.test},tests:n.tests}:{...{index:s,type:"api_call",callId:n.callId,method:n.method,url:n.url,timestamp:n.timestamp,responseTime:n.responseTime??null,request:n.request,response:n.response??null,...n.error?{error:n.error}:{},assertions:n.assertions??[],specFile:n.specFile,test:n.test},tests:n.tests})}function So(t){return {title:t.title,fullTitle:t.titlePath,status:t.status,duration:t.duration,retries:t.retryCount,retry:t.retry,tags:t.tags,failure:t.failure}}function Ro(t){return {title:t.title,status:t.status,duration:t.duration,startedAt:t.startedAt,completedAt:t.completedAt,retryCount:t.retryCount,tags:t.tags,failure:t.failure,testId:t.testId,filePath:t.filePath,suiteName:t.suiteName,testType:t.testType,isFlaky:t.isFlaky,retryStatus:t.retryStatus,expectedStatus:t.expectedStatus,actualStatus:t.actualStatus,artifacts:t.artifacts,networkRequests:t.networkRequests,apiCalls:t.apiCalls,apiAssertions:t.apiAssertions,actions:t.actions,consoleLogs:t.consoleLogs}}function Ao(t,e,r,n){let s=[];for(let a of t.navigations)n.navigationTypes!==null&&!n.navigationTypes.includes(a.navigationType)||s.push({type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title});return s}function _o(t,e,r){if(!t.apiCalls||t.apiCalls.length===0)return [];let n=t.apiAssertions??[];return t.apiCalls.map(s=>{let a=n.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:es(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:es(s.requestBody)},response:o,...s.error?{error:s.error}:{},assertions:a,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title}})}function Io(t,e){let r=new Date(t.timestamp).getTime(),n=new Date(e.timestamp).getTime();if(r!==n)return r-n;let s={navigation:0,api_call:1},a=s[t.type],o=s[e.type];return a!==o?a-o:t.type==="api_call"&&e.type==="api_call"&&t.callId&&e.callId?Qn(t.callId)-Qn(e.callId):0}function Qn(t){let e=t.match(/(\d+)$/);return e?parseInt(e[1],10):0}function Mo(t,e){for(let r=0;r<t.length;r++){let n=t[r];if(n.type!=="navigation")continue;let s=new Date(n.timestamp).getTime(),a=null;for(let o=r+1;o<t.length;o++)if(t[o]._testTitle===n._testTitle){a=new Date(t[o].timestamp).getTime();break}if(a!==null)n.durationOnUrl=Math.max(0,a-s);else {let o=e.find(i=>i.title===n._testTitle);if(o){let i=new Date(o.completedAt).getTime();n.durationOnUrl=Math.max(0,i-s);}}}}function es(t){if(t==null)return null;try{return JSON.parse(t)}catch{return t}}function ee(t,e){let r=t.length,n=Math.min(Math.ceil(e/100*r)-1,r-1);return t[Math.max(0,n)]}function jt(t){try{let e=new URL(t);return e.origin+e.pathname}catch{return t}}function Eo(t){return t==null?"error":t>=200&&t<300?"2xx":t>=300&&t<400?"3xx":t>=400&&t<500?"4xx":t>=500&&t<600?"5xx":"error"}function rs(t,e){let r=0,n=0,s=0,a=0,o=0;for(let w of t)switch(w.status){case "passed":r++;break;case "failed":n++;break;case "flaky":s++;break;case "skipped":a++;break;case "timedout":o++;break}let i=[];for(let w of t)w.apiCalls&&i.push(...w.apiCalls);let d=i.length,l=new Set,c={},u={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},f=[];for(let w of i)l.add(jt(w.url)),c[w.method]=(c[w.method]??0)+1,u[Eo(w.responseStatusCode)]+=1,f.push(w.responseTimeMs);let p=null;if(f.length>0){let w=[...f].sort((_,L)=>_-L),C=w.reduce((_,L)=>_+L,0);p={avg:Math.round(C/w.length),min:w[0],max:w[w.length-1],p50:ee(w,50),p95:ee(w,95),p99:ee(w,99)};}let g=0,m=0,h=0;for(let w of t)if(w.apiAssertions)for(let C of w.apiAssertions)g++,C.status==="passed"?m++:h++;let v=0,y=new Set;for(let w of t){v+=w.navigations.length;for(let C of w.navigations)y.add(C.url);}let b=0,k={};function A(w){for(let C of w)b++,k[C.category]=(k[C.category]??0)+1,C.children.length>0&&A(C.children);}for(let w of t)w.actions&&A(w.actions);let E=0,T=0,x=0,S=0;for(let w of t)if(w.visual)for(let C of w.visual)E++,C.status==="failed"?T++:(C.status==="new"||C.status==="updated")&&x++,S+=C.domChangeCount??0;return {total:t.length,passed:r,failed:n,flaky:s,skipped:a,timedout:o,totalApiCalls:d,uniqueApiUrls:l.size,apiCallsByMethod:c,apiCallsByStatusRange:u,apiResponseTime:p,totalAssertions:g,passedAssertions:m,failedAssertions:h,totalNavigations:v,uniqueNavigationUrls:y.size,totalTimelineSteps:e,totalActionSteps:b,actionStepsByCategory:k,visualChecks:E,visualFailures:T,visualNew:x,visualDomChanges:S}}function Po(t){let e=56-t.length;return e>0?t+" ".repeat(e):t}function F(t){return `\u2502 ${Po(t)} \u2502
4261
+ `);return}finally{n&&clearTimeout(n);}}function ts(t,e){let r=[];for(let n of t){let s=Ao(n),a=_o(n),o=Io(n,s,a,e),i=Mo(n,s,a);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:n.startedAt,durationOnUrl:n.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:n.specFile,test:s,tests:[a],_testTitle:n.title});continue}r.push(...o,...i);}return r.sort(Po),Eo(r,t),r.map((n,s)=>n.type==="navigation"?{...{index:s,type:"navigation",url:n.url,timestamp:n.timestamp,durationOnUrl:n.durationOnUrl??0,navigationType:n.navigationType,domContentLoadedAt:n.domContentLoadedAt??null,networkIdleAt:n.networkIdleAt??null,networkStats:n.networkStats??null,specFile:n.specFile,test:n.test},tests:n.tests}:{...{index:s,type:"api_call",callId:n.callId,method:n.method,url:n.url,timestamp:n.timestamp,responseTime:n.responseTime??null,request:n.request,response:n.response??null,...n.error?{error:n.error}:{},assertions:n.assertions??[],specFile:n.specFile,test:n.test},tests:n.tests})}function Ao(t){return {title:t.title,fullTitle:t.titlePath,status:t.status,duration:t.duration,retries:t.retryCount,retry:t.retry,tags:t.tags,failure:t.failure}}function _o(t){return {title:t.title,status:t.status,duration:t.duration,startedAt:t.startedAt,completedAt:t.completedAt,retryCount:t.retryCount,tags:t.tags,failure:t.failure,testId:t.testId,filePath:t.filePath,suiteName:t.suiteName,testType:t.testType,isFlaky:t.isFlaky,retryStatus:t.retryStatus,expectedStatus:t.expectedStatus,actualStatus:t.actualStatus,artifacts:t.artifacts,networkRequests:t.networkRequests,apiCalls:t.apiCalls,apiAssertions:t.apiAssertions,actions:t.actions,consoleLogs:t.consoleLogs}}function Io(t,e,r,n){let s=[];for(let a of t.navigations)n.navigationTypes!==null&&!n.navigationTypes.includes(a.navigationType)||s.push({type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title});return s}function Mo(t,e,r){if(!t.apiCalls||t.apiCalls.length===0)return [];let n=t.apiAssertions??[];return t.apiCalls.map(s=>{let a=n.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:es(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:es(s.requestBody)},response:o,...s.error?{error:s.error}:{},assertions:a,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title}})}function Po(t,e){let r=new Date(t.timestamp).getTime(),n=new Date(e.timestamp).getTime();if(r!==n)return r-n;let s={navigation:0,api_call:1},a=s[t.type],o=s[e.type];return a!==o?a-o:t.type==="api_call"&&e.type==="api_call"&&t.callId&&e.callId?Qn(t.callId)-Qn(e.callId):0}function Qn(t){let e=t.match(/(\d+)$/);return e?parseInt(e[1],10):0}function Eo(t,e){for(let r=0;r<t.length;r++){let n=t[r];if(n.type!=="navigation")continue;let s=new Date(n.timestamp).getTime(),a=null;for(let o=r+1;o<t.length;o++)if(t[o]._testTitle===n._testTitle){a=new Date(t[o].timestamp).getTime();break}if(a!==null)n.durationOnUrl=Math.max(0,a-s);else {let o=e.find(i=>i.title===n._testTitle);if(o){let i=new Date(o.completedAt).getTime();n.durationOnUrl=Math.max(0,i-s);}}}}function es(t){if(t==null)return null;try{return JSON.parse(t)}catch{return t}}function ee(t,e){let r=t.length,n=Math.min(Math.ceil(e/100*r)-1,r-1);return t[Math.max(0,n)]}function jt(t){try{let e=new URL(t);return e.origin+e.pathname}catch{return t}}function Lo(t){return t==null?"error":t>=200&&t<300?"2xx":t>=300&&t<400?"3xx":t>=400&&t<500?"4xx":t>=500&&t<600?"5xx":"error"}function rs(t,e){let r=0,n=0,s=0,a=0,o=0;for(let w of t)switch(w.status){case "passed":r++;break;case "failed":n++;break;case "flaky":s++;break;case "skipped":a++;break;case "timedout":o++;break}let i=[];for(let w of t)w.apiCalls&&i.push(...w.apiCalls);let d=i.length,l=new Set,c={},u={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},p=[];for(let w of i)l.add(jt(w.url)),c[w.method]=(c[w.method]??0)+1,u[Lo(w.responseStatusCode)]+=1,p.push(w.responseTimeMs);let g=null;if(p.length>0){let w=[...p].sort((_,L)=>_-L),C=w.reduce((_,L)=>_+L,0);g={avg:Math.round(C/w.length),min:w[0],max:w[w.length-1],p50:ee(w,50),p95:ee(w,95),p99:ee(w,99)};}let f=0,m=0,h=0;for(let w of t)if(w.apiAssertions)for(let C of w.apiAssertions)f++,C.status==="passed"?m++:h++;let v=0,y=new Set;for(let w of t){v+=w.navigations.length;for(let C of w.navigations)y.add(C.url);}let b=0,k={};function A(w){for(let C of w)b++,k[C.category]=(k[C.category]??0)+1,C.children.length>0&&A(C.children);}for(let w of t)w.actions&&A(w.actions);let P=0,T=0,x=0,S=0;for(let w of t)if(w.visual)for(let C of w.visual)P++,C.status==="failed"?T++:(C.status==="new"||C.status==="updated")&&x++,S+=C.domChangeCount??0;return {total:t.length,passed:r,failed:n,flaky:s,skipped:a,timedout:o,totalApiCalls:d,uniqueApiUrls:l.size,apiCallsByMethod:c,apiCallsByStatusRange:u,apiResponseTime:g,totalAssertions:f,passedAssertions:m,failedAssertions:h,totalNavigations:v,uniqueNavigationUrls:y.size,totalTimelineSteps:e,totalActionSteps:b,actionStepsByCategory:k,visualChecks:P,visualFailures:T,visualNew:x,visualDomChanges:S}}function No(t){let e=56-t.length;return e>0?t+" ".repeat(e):t}function F(t){return `\u2502 ${No(t)} \u2502
4262
4262
  `}function Vt(t,e,r,n){if(n||t.total===0)return;let s=`\u250C${"\u2500".repeat(58)}\u2510
4263
4263
  `,a=`\u2514${"\u2500".repeat(58)}\u2518
4264
- `,o=F(""),i=s;i+=F("TestRelic AI - Playwright Test Report"),i+=o;let d=[];if(t.passed>0&&d.push(`${t.passed} \u2713`),t.failed>0&&d.push(`${t.failed} \u2717`),t.flaky>0&&d.push(`${t.flaky} \u26A0`),t.skipped>0&&d.push(`${t.skipped} skipped`),t.timedout>0&&d.push(`${t.timedout} timedout`),i+=F(`Tests: ${t.total} total (${d.join(" ")})`),t.totalNavigations>0&&(i+=F(`Navigations: ${t.totalNavigations} visits across ${t.uniqueNavigationUrls} unique URLs`)),t.totalApiCalls>0){i+=F(`API Calls: ${t.totalApiCalls} calls across ${t.uniqueApiUrls} unique endpoints`);let l=Object.entries(t.apiCallsByMethod).filter(([,u])=>u>0).map(([u,f])=>`${u}: ${f}`);l.length>0&&(i+=F(` ${l.join(" ")}`));let c=Object.entries(t.apiCallsByStatusRange).filter(([,u])=>u>0).map(([u,f])=>`${u}: ${f}`);c.length>0&&(i+=F(` ${c.join(" ")}`)),t.apiResponseTime&&(i+=F(` Avg response: ${t.apiResponseTime.avg}ms P95: ${t.apiResponseTime.p95}ms`));}if(t.totalAssertions>0&&(i+=F(`Assertions: ${t.totalAssertions} total (${t.passedAssertions} \u2713 ${t.failedAssertions} \u2717)`)),t.totalActionSteps>0){let l=[],c=t.actionStepsByCategory;c.ui_action&&l.push(`${c.ui_action} UI`),c.assertion&&l.push(`${c.assertion} assertions`),c.custom_step&&l.push(`${c.custom_step} custom`);let u=l.length>0?` (${l.join(" ")})`:"";i+=F(`Actions: ${t.totalActionSteps} steps${u}`);}i+=F(`Report: ${r}`),i+=F(`Data: ${e}`),i+=a,i+=`For more information visit us at https://docs.testrelic.ai
4265
- `,process.stderr.write(i);}var Lo=new Set(["pw:api","expect","test.step"]);function No(t){return t==="expect"?"assertion":t==="test.step"?"custom_step":"ui_action"}function $t(t,e,r){if(Lo.has(t.category)){let n=[];for(let a of t.steps)$t(a,e,n);let s=t.startTime.getTime()-e.getTime();r.push({title:t.title,category:No(t.category),timestamp:t.startTime.toISOString(),duration:t.duration,videoOffset:s>=0?s/1e3:null,status:t.error?"failed":"passed",error:Un(t.error?.message),children:n});}else for(let n of t.steps)$t(n,e,r);}function ns(t,e){let r=[];for(let n of t)$t(n,e,r);return r}var Bo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function as(t){let e=new URL(t);if(e.protocol!=="https:"&&!(e.protocol==="http:"&&Bo.has(e.hostname)))throw createError(ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${e.protocol}//${e.hostname}`)}var Oo=3e3;async function Wt(t){let e=new AbortController,r=setTimeout(()=>e.abort(),Oo);try{return (await fetch(`${t}/health`,{method:"GET",signal:e.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function is(t){return new Promise(e=>setTimeout(e,t))}async function ss(t){try{let r=(await t.json()).error;if(r&&typeof r.message=="string"){let n=r.details;if(Array.isArray(n)&&n.length>0){let s=n.map(a=>`${a.field}: ${a.message}`).join(", ");return `${r.message} (${s})`}return r.message}}catch{}return `HTTP ${t.status}`}async function Gt(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),r);try{let a=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:n.signal});if(a.ok){let i=await a.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,orgId:i.orgId,orgName:i.orgName,userId:i.userId,userName:i.userName}}if(a.status===429){let i=a.headers.get("Retry-After"),d=i?parseInt(i,10)*1e3:5e3;if(!isNaN(d)&&d>0){await is(d);let l=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:n.signal});if(l.ok){let c=await l.json();return {accessToken:c.accessToken,refreshToken:c.refreshToken,expiresIn:c.expiresIn,orgId:c.orgId,orgName:c.orgName,userId:c.userId,userName:c.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return a.status===400?{code:"validation_error",message:await ss(a),statusCode:400}:a.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:a.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await ss(a),statusCode:a.status}}catch(a){return a instanceof DOMException&&a.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 Kt(t){return "code"in t&&typeof t.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(t.code)}async function os(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),r);try{let a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:n.signal});if(a.status===429){let i=a.headers.get("Retry-After"),d=i?parseInt(i,10)*1e3:5e3;!isNaN(d)&&d>0&&(await is(d),a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:n.signal}));}if(!a.ok)return null;let o=await a.json();return {accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn}}catch{return null}finally{clearTimeout(s);}}async function ls(t,e,r,n,s,a){let o=new AbortController,i=setTimeout(()=>o.abort(),s);try{let d={gitId:r,displayName:n};a&&(d.branch=a);let l=await fetch(`${t}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(d),signal:o.signal});if(!l.ok)return null;let c=await l.json();return {repoId:c.repoId,displayName:c.displayName}}catch{return null}finally{clearTimeout(i);}}var jo=5e3;function K(t,e){try{return execSync(t,{cwd:e,timeout:jo,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function ds(t){let e=K("git rev-parse --abbrev-ref HEAD",t),r=K("git rev-parse --short HEAD",t),n=K("git log -1 --pretty=%s",t),s=K("git log -1 --format=%an",t)??K("git config user.name",t),a=Vo(t),o=a?be(a):null;return {branch:e,commitSha:r,commitMessage:n,commitAuthor:s,remoteUrl:o}}function Vo(t){let e=K("git remote get-url origin",t);if(e)return e;let r=K("git remote",t);if(!r)return null;let n=r.split(`
4266
- `)[0]?.trim();return n?K(`git remote get-url ${n}`,t):null}function be(t){let e=t.trim();return e=e.replace(/^[a-z+]+:\/\//,""),e=e.replace(/^[^@]+@/,""),e=e.replace(/:(?!\d)/,"/"),e=e.replace(/\.git$/,""),e=e.replace(/\/+$/,""),e=e.replace(/^[^@/]+@/,""),e.toLowerCase()}function cs(t){let e=t.split("/").filter(Boolean);return e[e.length-1]??t}function Jt(t){try{let e=readFileSync(join(t,"package.json"),"utf-8"),r=JSON.parse(e);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function xe(t){let e=Jt(t);return e||`local/${basename(t)}`}var $o=new Set(["smoke","regression","nightly","ci"]);function Fe(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&$o.has(t))return t}async function J(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),Math.max(1,r));try{return await fetch(t,{...e,signal:n.signal})}finally{clearTimeout(s);}}function us(t,e){let r=e+Math.ceil(Math.max(0,t)/1e3);return Math.min(6e5,Math.max(3e4,r))}var Be=class{constructor(e=12e4,r=Date.now()){this.deadline=r+Math.max(0,e);}remaining(e=Date.now()){return Math.max(0,this.deadline-e)}expired(e=Date.now()){return this.remaining(e)===0}slice(e,r=Date.now()){return Math.min(e,this.remaining(r))}};var Ko=1048576,Oe=[1e3,3e3,9e3],qe=3,fs=3e4,Jo=90*1048576,Yo=new Set(["e2e","mobile","unit"]);function Xt(t){if(t&&t.length>0&&t.every(s=>s.testType==="api")){let s=new Map;for(let i of t){let d=i.apiProtocol??"rest";s.set(d,(s.get(d)??0)+1);}let a="rest",o=0;for(let[i,d]of s)d>o&&(o=d,a=i);return {testType:"api",apiProtocol:a,metadata:{testType:"api",primaryProtocol:a}}}let e=new Map;for(let s of t??[])Yo.has(s.testType)&&e.set(s.testType,(e.get(s.testType)??0)+1);let r=null,n=0;for(let[s,a]of e)a>n&&(n=a,r=s);return {testType:r??"e2e"}}function Zt(t,e,r,n,s,a){let o=a?.cloudPlatform?a.cloudPlatform:n?.provider&&n.provider!=="unknown"?n.provider:"local",i=Fe(),d=Xt(s),l=d.testType==="api"?d:null,c=l&&s?s.map(f=>f.apiProtocol?f:{...f,apiProtocol:l.apiProtocol}):s;return {runId:t.testRunId,repoGitId:e,startedAt:t.startedAt,summary:t.summary,timeline:t.timeline,environment:o,...i?{runType:i}:{},...l?{testType:l.testType,apiProtocol:l.apiProtocol,metadata:l.metadata}:{testType:d.testType},...c&&c.length>0?{tests:c}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...t.completedAt?{finishedAt:t.completedAt}:{},...t.totalDuration?{duration:t.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{},...a?.cloudPlatform?{cloudPlatform:a.cloudPlatform}:{},...a?.cloudBuildId?{cloudBuildId:a.cloudBuildId}:{},...a?.cloudSessionId?{cloudSessionId:a.cloudSessionId}:{}}}function Yt(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function Qt(t){return Array.isArray(t)?t.map(e=>{let r=e.statusCode??e.responseStatusCode??null;return {...e.id!=null?{id:e.id}:{},...e.protocol!=null?{protocol:e.protocol}:{},method:e.method??null,url:e.url??null,statusCode:r,statusText:e.statusText??e.responseStatusText??null,ok:typeof r=="number"?r<400:e.ok??null,durationMs:e.durationMs??e.responseTimeMs??null,bytesIn:typeof e.bytesIn=="number"?e.bytesIn:Yt(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:Yt(e.requestBody),requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,requestCookies:e.requestCookies??null,responseCookies:e.responseCookies??null}}):[]}function er(t){return Array.isArray(t)?t.map(e=>{let r=e.responseStatusCode??e.statusCode??0,n=e.timestamp??null;return {method:e.method??"GET",url:e.url??"",status:r,statusCode:r,type:"xhr",size:Yt(e.responseBody),duration:e.responseTimeMs??e.durationMs??0,responseTimeMs:e.responseTimeMs??e.durationMs??0,requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,timestamp:n,startedAt:n}}):[]}function tr(t){if(!Array.isArray(t))return [];let e=r=>{if(r==null)return String(r);if(typeof r=="string")return r;try{return JSON.stringify(r)}catch{return String(r)}};return t.map(r=>{let n=r.status==="failed"?"failed":"passed",s=typeof r.expression=="string"&&r.expression.trim()?r.expression.trim():null,a=r.kind??r.type??"assertion",o=n==="failed"?`expected ${e(r.expected)}, received ${e(r.actual)}`:r.expected!==void 0?`expected ${e(r.expected)}`:null;return {...r.callId!=null?{callId:r.callId}:{},kind:a,description:s??r.description??`${a} assertion`,status:n,detail:o}})}async function Ue(t){return new Promise(e=>setTimeout(e,t))}function Xo(t){let e={};for(let[r,n]of Object.entries(t))n!=null&&(e[r]=n);return e}async function gs(t,e,r,n=fs,s){for(let a=0;a<qe;a++){if(s?.expired())return null;let o=s?s.slice(n):n;if(o<=0)return null;try{let i=await J(t,e,o);if(i.ok)return i;if(i.status===401&&r&&a===0){let d=await r();if(d){let l={...e,headers:{...e.headers,Authorization:`Bearer ${d}`}},c=await J(t,l,o);if(c.ok)return c}return null}if(i.status===429&&a<qe-1){let d=i.headers.get("Retry-After"),l=d?parseInt(d,10)*1e3:Oe[a];!isNaN(l)&&l>0?await Ue(l):await Ue(Oe[a]);continue}if(i.status>=500&&a<qe-1){await Ue(Oe[a]);continue}return i}catch{if(a<qe-1){await Ue(Oe[a]);continue}return null}}return null}var Zo=promisify(gzip);function ps(t,e){if(!Array.isArray(t.tests))return t;let r=t.tests.map(n=>{let{consoleLogs:s,networkRequests:a,apiCalls:o,...i}=n;return e?i:{...i,...o!==void 0?{apiCalls:o}:{}}});return {...t,tests:r}}var Qo=["consoleLogs","networkRequests","apiCalls","actions","navigations","protocolAssertions","visual"];function el(t){if(!Array.isArray(t.tests))return t;let e=new Set(Qo),r=t.tests.map(n=>{let s={};for(let a in n)if(!e.has(a))if(a==="failure"&&n[a]&&typeof n[a]=="object"){let o=n[a];s.failure={message:o.message??null,line:o.line??null};}else s[a]=n[a];return s});return {...t,tests:r}}function tl(t){let e=new Set(["tests","timeline","unifiedTimeline","navigations"]),r={};for(let n in t)e.has(n)||(r[n]=t[n]);return r.tests=[],r}async function rr(t,e=Jo){let r={"Content-Type":"application/json"},n=JSON.stringify(t),s=t,a=Array.isArray(s?.tests)?s.tests.length:0,o=i=>Buffer.byteLength(i,"utf-8")>e;if(a>0&&o(n)){let i=Math.max(1,Math.round(e/1048576));process.stderr.write(`[testrelic] WARNING: batch payload exceeds ${i}MB \u2014 dropping consoleLogs/networkRequests from ${a} test(s) to avoid HTTP 413. Console/network detail will be missing in the cloud.
4264
+ `,o=F(""),i=s;i+=F("TestRelic AI - Playwright Test Report"),i+=o;let d=[];if(t.passed>0&&d.push(`${t.passed} \u2713`),t.failed>0&&d.push(`${t.failed} \u2717`),t.flaky>0&&d.push(`${t.flaky} \u26A0`),t.skipped>0&&d.push(`${t.skipped} skipped`),t.timedout>0&&d.push(`${t.timedout} timedout`),i+=F(`Tests: ${t.total} total (${d.join(" ")})`),t.totalNavigations>0&&(i+=F(`Navigations: ${t.totalNavigations} visits across ${t.uniqueNavigationUrls} unique URLs`)),t.totalApiCalls>0){i+=F(`API Calls: ${t.totalApiCalls} calls across ${t.uniqueApiUrls} unique endpoints`);let l=Object.entries(t.apiCallsByMethod).filter(([,u])=>u>0).map(([u,p])=>`${u}: ${p}`);l.length>0&&(i+=F(` ${l.join(" ")}`));let c=Object.entries(t.apiCallsByStatusRange).filter(([,u])=>u>0).map(([u,p])=>`${u}: ${p}`);c.length>0&&(i+=F(` ${c.join(" ")}`)),t.apiResponseTime&&(i+=F(` Avg response: ${t.apiResponseTime.avg}ms P95: ${t.apiResponseTime.p95}ms`));}if(t.totalAssertions>0&&(i+=F(`Assertions: ${t.totalAssertions} total (${t.passedAssertions} \u2713 ${t.failedAssertions} \u2717)`)),t.totalActionSteps>0){let l=[],c=t.actionStepsByCategory;c.ui_action&&l.push(`${c.ui_action} UI`),c.assertion&&l.push(`${c.assertion} assertions`),c.custom_step&&l.push(`${c.custom_step} custom`);let u=l.length>0?` (${l.join(" ")})`:"";i+=F(`Actions: ${t.totalActionSteps} steps${u}`);}i+=F(`Report: ${r}`),i+=F(`Data: ${e}`),i+=a,i+=`For more information visit us at https://docs.testrelic.ai
4265
+ `,process.stderr.write(i);}var Do=new Set(["pw:api","expect","test.step"]);function Fo(t){return t==="expect"?"assertion":t==="test.step"?"custom_step":"ui_action"}function $t(t,e,r){if(Do.has(t.category)){let n=[];for(let a of t.steps)$t(a,e,n);let s=t.startTime.getTime()-e.getTime();r.push({title:t.title,category:Fo(t.category),timestamp:t.startTime.toISOString(),duration:t.duration,videoOffset:s>=0?s/1e3:null,status:t.error?"failed":"passed",error:Hn(t.error?.message),children:n});}else for(let n of t.steps)$t(n,e,r);}function ns(t,e){let r=[];for(let n of t)$t(n,e,r);return r}var qo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function as(t){let e=new URL(t);if(e.protocol!=="https:"&&!(e.protocol==="http:"&&qo.has(e.hostname)))throw createError(ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${e.protocol}//${e.hostname}`)}var Ho=3e3;async function Wt(t){let e=new AbortController,r=setTimeout(()=>e.abort(),Ho);try{return (await fetch(`${t}/health`,{method:"GET",signal:e.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function is(t){return new Promise(e=>setTimeout(e,t))}async function ss(t){try{let r=(await t.json()).error;if(r&&typeof r.message=="string"){let n=r.details;if(Array.isArray(n)&&n.length>0){let s=n.map(a=>`${a.field}: ${a.message}`).join(", ");return `${r.message} (${s})`}return r.message}}catch{}return `HTTP ${t.status}`}async function Gt(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),r);try{let a=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:n.signal});if(a.ok){let i=await a.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn,orgId:i.orgId,orgName:i.orgName,userId:i.userId,userName:i.userName}}if(a.status===429){let i=a.headers.get("Retry-After"),d=i?parseInt(i,10)*1e3:5e3;if(!isNaN(d)&&d>0){await is(d);let l=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:n.signal});if(l.ok){let c=await l.json();return {accessToken:c.accessToken,refreshToken:c.refreshToken,expiresIn:c.expiresIn,orgId:c.orgId,orgName:c.orgName,userId:c.userId,userName:c.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return a.status===400?{code:"validation_error",message:await ss(a),statusCode:400}:a.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:a.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await ss(a),statusCode:a.status}}catch(a){return a instanceof DOMException&&a.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 Kt(t){return "code"in t&&typeof t.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(t.code)}async function os(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),r);try{let a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:n.signal});if(a.status===429){let i=a.headers.get("Retry-After"),d=i?parseInt(i,10)*1e3:5e3;!isNaN(d)&&d>0&&(await is(d),a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:n.signal}));}if(!a.ok)return null;let o=await a.json();return {accessToken:o.accessToken,refreshToken:o.refreshToken,expiresIn:o.expiresIn}}catch{return null}finally{clearTimeout(s);}}async function ls(t,e,r,n,s,a){let o=new AbortController,i=setTimeout(()=>o.abort(),s);try{let d={gitId:r,displayName:n};a&&(d.branch=a);let l=await fetch(`${t}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(d),signal:o.signal});if(!l.ok)return null;let c=await l.json();return {repoId:c.repoId,displayName:c.displayName}}catch{return null}finally{clearTimeout(i);}}var $o=5e3;function K(t,e){try{return execSync(t,{cwd:e,timeout:$o,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function ds(t){let e=K("git rev-parse --abbrev-ref HEAD",t),r=K("git rev-parse --short HEAD",t),n=K("git log -1 --pretty=%s",t),s=K("git log -1 --format=%an",t)??K("git config user.name",t),a=Wo(t),o=a?be(a):null;return {branch:e,commitSha:r,commitMessage:n,commitAuthor:s,remoteUrl:o}}function Wo(t){let e=K("git remote get-url origin",t);if(e)return e;let r=K("git remote",t);if(!r)return null;let n=r.split(`
4266
+ `)[0]?.trim();return n?K(`git remote get-url ${n}`,t):null}function be(t){let e=t.trim();return e=e.replace(/^[a-z+]+:\/\//,""),e=e.replace(/^[^@]+@/,""),e=e.replace(/:(?!\d)/,"/"),e=e.replace(/\.git$/,""),e=e.replace(/\/+$/,""),e=e.replace(/^[^@/]+@/,""),e.toLowerCase()}function cs(t){let e=t.split("/").filter(Boolean);return e[e.length-1]??t}function Jt(t){try{let e=readFileSync(join(t,"package.json"),"utf-8"),r=JSON.parse(e);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function xe(t){let e=Jt(t);return e||`local/${basename(t)}`}var Go=new Set(["smoke","regression","nightly","ci"]);function Fe(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&Go.has(t))return t}async function J(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),Math.max(1,r));try{return await fetch(t,{...e,signal:n.signal})}finally{clearTimeout(s);}}function us(t,e){let r=e+Math.ceil(Math.max(0,t)/1e3);return Math.min(6e5,Math.max(3e4,r))}var Be=class{constructor(e=12e4,r=Date.now()){this.deadline=r+Math.max(0,e);}remaining(e=Date.now()){return Math.max(0,this.deadline-e)}expired(e=Date.now()){return this.remaining(e)===0}slice(e,r=Date.now()){return Math.min(e,this.remaining(r))}};var Yo=1048576,Oe=[1e3,3e3,9e3],qe=3,fs=3e4,Xo=90*1048576,Zo=new Set(["e2e","mobile","unit"]);function Xt(t){if(t&&t.length>0&&t.every(s=>s.testType==="api")){let s=new Map;for(let i of t){let d=i.apiProtocol??"rest";s.set(d,(s.get(d)??0)+1);}let a="rest",o=0;for(let[i,d]of s)d>o&&(o=d,a=i);return {testType:"api",apiProtocol:a,metadata:{testType:"api",primaryProtocol:a}}}let e=new Map;for(let s of t??[])Zo.has(s.testType)&&e.set(s.testType,(e.get(s.testType)??0)+1);let r=null,n=0;for(let[s,a]of e)a>n&&(n=a,r=s);return {testType:r??"e2e"}}function Zt(t,e,r,n,s,a){let o=a?.cloudPlatform?a.cloudPlatform:n?.provider&&n.provider!=="unknown"?n.provider:"local",i=Fe(),d=Xt(s),l=d.testType==="api"?d:null,c=l&&s?s.map(p=>p.apiProtocol?p:{...p,apiProtocol:l.apiProtocol}):s;return {runId:t.testRunId,repoGitId:e,startedAt:t.startedAt,summary:t.summary,timeline:t.timeline,environment:o,...i?{runType:i}:{},...l?{testType:l.testType,apiProtocol:l.apiProtocol,metadata:l.metadata}:{testType:d.testType},...c&&c.length>0?{tests:c}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...t.completedAt?{finishedAt:t.completedAt}:{},...t.totalDuration?{duration:t.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{},...a?.cloudPlatform?{cloudPlatform:a.cloudPlatform}:{},...a?.cloudBuildId?{cloudBuildId:a.cloudBuildId}:{},...a?.cloudSessionId?{cloudSessionId:a.cloudSessionId}:{}}}function Yt(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function Qt(t){return Array.isArray(t)?t.map(e=>{let r=e.statusCode??e.responseStatusCode??null;return {...e.id!=null?{id:e.id}:{},...e.protocol!=null?{protocol:e.protocol}:{},method:e.method??null,url:e.url??null,statusCode:r,statusText:e.statusText??e.responseStatusText??null,ok:typeof r=="number"?r<400:e.ok??null,durationMs:e.durationMs??e.responseTimeMs??null,bytesIn:typeof e.bytesIn=="number"?e.bytesIn:Yt(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:Yt(e.requestBody),requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,requestCookies:e.requestCookies??null,responseCookies:e.responseCookies??null}}):[]}function er(t){return Array.isArray(t)?t.map(e=>{let r=e.responseStatusCode??e.statusCode??0,n=e.timestamp??null;return {method:e.method??"GET",url:e.url??"",status:r,statusCode:r,type:"xhr",size:Yt(e.responseBody),duration:e.responseTimeMs??e.durationMs??0,responseTimeMs:e.responseTimeMs??e.durationMs??0,requestHeaders:e.requestHeaders??null,responseHeaders:e.responseHeaders??null,requestBody:e.requestBody??null,responseBody:e.responseBody??null,timestamp:n,startedAt:n}}):[]}function tr(t){if(!Array.isArray(t))return [];let e=r=>{if(r==null)return String(r);if(typeof r=="string")return r;try{return JSON.stringify(r)}catch{return String(r)}};return t.map(r=>{let n=r.status==="failed"?"failed":"passed",s=typeof r.expression=="string"&&r.expression.trim()?r.expression.trim():null,a=r.kind??r.type??"assertion",o=n==="failed"?`expected ${e(r.expected)}, received ${e(r.actual)}`:r.expected!==void 0?`expected ${e(r.expected)}`:null;return {...r.callId!=null?{callId:r.callId}:{},kind:a,description:s??r.description??`${a} assertion`,status:n,detail:o}})}async function He(t){return new Promise(e=>setTimeout(e,t))}function Qo(t){let e={};for(let[r,n]of Object.entries(t))n!=null&&(e[r]=n);return e}async function gs(t,e,r,n=fs,s){for(let a=0;a<qe;a++){if(s?.expired())return null;let o=s?s.slice(n):n;if(o<=0)return null;try{let i=await J(t,e,o);if(i.ok)return i;if(i.status===401&&r&&a===0){let d=await r();if(d){let l={...e,headers:{...e.headers,Authorization:`Bearer ${d}`}},c=await J(t,l,o);if(c.ok)return c}return null}if(i.status===429&&a<qe-1){let d=i.headers.get("Retry-After"),l=d?parseInt(d,10)*1e3:Oe[a];!isNaN(l)&&l>0?await He(l):await He(Oe[a]);continue}if(i.status>=500&&a<qe-1){await He(Oe[a]);continue}return i}catch{if(a<qe-1){await He(Oe[a]);continue}return null}}return null}var el=promisify(gzip);function ps(t,e){if(!Array.isArray(t.tests))return t;let r=t.tests.map(n=>{let{consoleLogs:s,networkRequests:a,apiCalls:o,...i}=n;return e?i:{...i,...o!==void 0?{apiCalls:o}:{}}});return {...t,tests:r}}var tl=["consoleLogs","networkRequests","apiCalls","actions","navigations","protocolAssertions","visual"];function rl(t){if(!Array.isArray(t.tests))return t;let e=new Set(tl),r=t.tests.map(n=>{let s={};for(let a in n)if(!e.has(a))if(a==="failure"&&n[a]&&typeof n[a]=="object"){let o=n[a];s.failure={message:o.message??null,line:o.line??null};}else s[a]=n[a];return s});return {...t,tests:r}}function nl(t){let e=new Set(["tests","timeline","unifiedTimeline","navigations"]),r={};for(let n in t)e.has(n)||(r[n]=t[n]);return r.tests=[],r}async function rr(t,e=Xo){let r={"Content-Type":"application/json"},n=JSON.stringify(t),s=t,a=Array.isArray(s?.tests)?s.tests.length:0,o=i=>Buffer.byteLength(i,"utf-8")>e;if(a>0&&o(n)){let i=Math.max(1,Math.round(e/1048576));process.stderr.write(`[testrelic] WARNING: batch payload exceeds ${i}MB \u2014 dropping consoleLogs/networkRequests from ${a} test(s) to avoid HTTP 413. Console/network detail will be missing in the cloud.
4267
4267
  `),n=JSON.stringify(ps(s,false)),o(n)&&(process.stderr.write(`[testrelic] WARNING: batch still exceeds ${i}MB after dropping logs \u2014 also dropping apiCalls from ${a} test(s). API request/response detail will be missing in the cloud.
4268
4268
  `),n=JSON.stringify(ps(s,true))),o(n)&&(process.stderr.write(`[testrelic] WARNING: batch still exceeds ${i}MB \u2014 shedding remaining per-test detail (actions/navigations/assertions) from ${a} test(s). Only test results + summary will reach the cloud.
4269
- `),n=JSON.stringify(el(s))),o(n)&&(process.stderr.write(`[testrelic] ERROR: batch still exceeds ${i}MB after shedding all per-test detail \u2014 uploading run summary only (${a} per-test result(s) omitted) to avoid losing the run to HTTP 413.
4270
- `),n=JSON.stringify(tl(s)));}if(Buffer.byteLength(n,"utf-8")>Ko){r["Content-Encoding"]="gzip";let i=await Zo(Buffer.from(n,"utf-8")),d=i.buffer;return {body:new Uint8Array(d,i.byteOffset,i.byteLength),headers:r}}return {body:n,headers:r}}async function hs(t,e,r,n,s,a){let o=`${t}/runs`,{body:i,headers:d}=await rr(r);d.Authorization=`Bearer ${e}`;let l=await gs(o,{method:"POST",headers:d,body:i},n,s,a);return l?.ok?{success:true,statusCode:l.status,error:null}:l?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:l?`Upload failed with status ${l.status}`:"Upload failed after retries",statusCode:l?.status??null,payload:r,targetEndpoint:o,method:"POST"}}async function ms(t,e,r,n){let s=`${t}/runs/init`;try{let a=await J(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(Xo(r))},n??fs);return a.ok?{runId:(await a.json()).runId}:null}catch{return null}}function vs(t,e,r,n){let s=`${t}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}).catch(()=>{});}async function ys(t,e,r,n){let s=`${t}/runs/${r}/finalize`;return (await gs(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}))?.ok??false}function nr(t,e,r,n){let s=`${t}/runs/${r}/finalize`,a=new Date,o={finishedAt:a.toISOString(),duration:a.getTime()-new Date(n).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)}).catch(()=>{});}var il="1.0.0",bs=10;function xs(t){return t instanceof Error?t.message:String(t)}function ol(t){return t>=400&&t<500&&t!==408&&t!==429}function we(t,e,r,n,s,a,o,i){try{mkdirSync(t,{recursive:!0});let d=Date.now(),l=`${d}-${e}-${r}.json`,c=join(t,l),u={version:il,queuedAt:new Date(d).toISOString(),reason:n,retryCount:0,targetEndpoint:s,method:a,payload:o,headers:i},f=c+".tmp";writeFileSync(f,JSON.stringify(u,null,2),"utf-8"),renameSync(f,c);}catch(d){d.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
4269
+ `),n=JSON.stringify(rl(s))),o(n)&&(process.stderr.write(`[testrelic] ERROR: batch still exceeds ${i}MB after shedding all per-test detail \u2014 uploading run summary only (${a} per-test result(s) omitted) to avoid losing the run to HTTP 413.
4270
+ `),n=JSON.stringify(nl(s)));}if(Buffer.byteLength(n,"utf-8")>Yo){r["Content-Encoding"]="gzip";let i=await el(Buffer.from(n,"utf-8")),d=i.buffer;return {body:new Uint8Array(d,i.byteOffset,i.byteLength),headers:r}}return {body:n,headers:r}}async function hs(t,e,r,n,s,a){let o=`${t}/runs`,{body:i,headers:d}=await rr(r);d.Authorization=`Bearer ${e}`;let l=await gs(o,{method:"POST",headers:d,body:i},n,s,a);return l?.ok?{success:true,statusCode:l.status,error:null}:l?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:l?`Upload failed with status ${l.status}`:"Upload failed after retries",statusCode:l?.status??null,payload:r,targetEndpoint:o,method:"POST"}}async function ms(t,e,r,n){let s=`${t}/runs/init`;try{let a=await J(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(Qo(r))},n??fs);return a.ok?{runId:(await a.json()).runId}:null}catch{return null}}function vs(t,e,r,n){let s=`${t}/runs/${r}/tests`;fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}).catch(()=>{});}async function ys(t,e,r,n){let s=`${t}/runs/${r}/finalize`;return (await gs(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}))?.ok??false}function nr(t,e,r,n){let s=`${t}/runs/${r}/finalize`,a=new Date,o={finishedAt:a.toISOString(),duration:a.getTime()-new Date(n).getTime(),summary:{}};fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)}).catch(()=>{});}var ll="1.0.0",bs=10;function xs(t){return t instanceof Error?t.message:String(t)}function dl(t){return t>=400&&t<500&&t!==408&&t!==429}function we(t,e,r,n,s,a,o,i){try{mkdirSync(t,{recursive:!0});let d=Date.now(),l=`${d}-${e}-${r}.json`,c=join(t,l),u={version:ll,queuedAt:new Date(d).toISOString(),reason:n,retryCount:0,targetEndpoint:s,method:a,payload:o,headers:i},p=c+".tmp";writeFileSync(p,JSON.stringify(u,null,2),"utf-8"),renameSync(p,c);}catch(d){d.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
4271
4271
  `):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
4272
4272
  `);}}async function Ts(t,e,r){let n;try{n=readdirSync(t).filter(a=>a.endsWith(".json")&&!a.endsWith(".tmp")).sort();}catch{return}if(n.length===0)return;let s=[];for(let a=0;a<n.length;a+=bs)s.push(n.slice(a,a+bs));for(let a of s)for(let o of a){let i=join(t,o),d;try{if(!statSync(i).isFile())continue;let c=JSON.parse(readFileSync(i,"utf-8"));if(!isValidQueueEntry(c)){process.stderr.write(`\u26A0 TestRelic: Corrupted queue file deleted: ${o}
4273
4273
  `),unlinkSync(i);continue}d=c;}catch(l){process.stderr.write(`\u26A0 TestRelic: Skipping unreadable queue file ${o}: ${xs(l)}
4274
- `);try{unlinkSync(i);}catch{}continue}try{let{body:l,headers:c}=await rr(d.payload),u={...d.headers,...c,Authorization:`Bearer ${r}`},f=await fetch(d.targetEndpoint,{method:d.method,headers:u,body:l});if(f.ok)unlinkSync(i);else if(ol(f.status)){process.stderr.write(`\u26A0 TestRelic: Queue entry ${o} rejected (HTTP ${f.status}) \u2014 moving aside; it will not be retried.
4275
- `);try{renameSync(i,`${i}.failed`);}catch{try{unlinkSync(i);}catch{}}}else {process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 server returned HTTP ${f.status} for ${o}; will retry later.
4274
+ `);try{unlinkSync(i);}catch{}continue}try{let{body:l,headers:c}=await rr(d.payload),u={...d.headers,...c,Authorization:`Bearer ${r}`},p=await fetch(d.targetEndpoint,{method:d.method,headers:u,body:l});if(p.ok)unlinkSync(i);else if(dl(p.status)){process.stderr.write(`\u26A0 TestRelic: Queue entry ${o} rejected (HTTP ${p.status}) \u2014 moving aside; it will not be retried.
4275
+ `);try{renameSync(i,`${i}.failed`);}catch{try{unlinkSync(i);}catch{}}}else {process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 server returned HTTP ${p.status} for ${o}; will retry later.
4276
4276
  `);return}}catch(l){process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 ${xs(l)}; will retry later.
4277
- `);return}}}function Ss(t,e){try{let r=readdirSync(t).filter(s=>(s.endsWith(".json")||s.endsWith(".failed"))&&!s.endsWith(".tmp")),n=Date.now();for(let s of r){let a=join(t,s);try{let o=readFileSync(a,"utf-8"),d=JSON.parse(o).queuedAt;if(typeof d=="string"){let l=new Date(d).getTime();n-l>e&&unlinkSync(a);}}catch{try{unlinkSync(a);}catch{}}}}catch{}}var gl=3e5,hl=864e5,ml=6e4,Rs=3e4,ir="https://platform.testrelic.ai/settings/api-keys";function As(t){return new Promise(e=>{let r=setTimeout(e,t);typeof r?.unref=="function"&&r.unref();})}var He=class{constructor(e){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=e,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.
4277
+ `);return}}}function Ss(t,e){try{let r=readdirSync(t).filter(s=>(s.endsWith(".json")||s.endsWith(".failed"))&&!s.endsWith(".tmp")),n=Date.now();for(let s of r){let a=join(t,s);try{let o=readFileSync(a,"utf-8"),d=JSON.parse(o).queuedAt;if(typeof d=="string"){let l=new Date(d).getTime();n-l>e&&unlinkSync(a);}}catch{try{unlinkSync(a);}catch{}}}}catch{}}var ml=3e5,vl=864e5,yl=6e4,Rs=3e4,ir="https://platform.testrelic.ai/settings/api-keys";function As(t){return new Promise(e=>{let r=setTimeout(e,t);typeof r?.unref=="function"&&r.unref();})}var Ue=class{constructor(e){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=e,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.
4278
4278
  `);return}try{if(as(this.config.endpoint),this.gitMetadata=ds(),!await Wt(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.
4279
4279
  `);return}let r=await Gt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(Kt(r)){this.handleAuthError(r.code,r.statusCode);return}let n=r;this.authState={mode:"cloud",accessToken:n.accessToken,refreshToken:n.refreshToken,expiresAt:Date.now()+n.expiresIn*1e3,orgId:n.orgId,orgName:n.orgName,userId:n.userId,userName:n.userName},process.stderr.write(`\u2713 TestRelic: Connected to cloud (${n.orgName} / ${n.userName})
4280
4280
  `),await this.resolveRepoId(),this.config.queueDirectory&&(Ss(this.config.queueDirectory,this.config.queueMaxAge),this.startBackgroundFlush()),this.startHealthCheck();}catch(e){this.setLocalMode("unexpected_error"),process.stderr.write(`\u26A0 TestRelic: Unexpected error during cloud initialization. Running in local mode. ${e instanceof Error?e.message:String(e)}
4281
- `);}}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 e=this.authState.expiresAt??0;if(Date.now()+gl<e)return true;if(!this.config||!this.authState.refreshToken)return this.switchToLocalMode("token_expired_no_refresh"),false;try{let r=await os(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(e){this.authState.mode!=="local"&&(this.authState.mode="local",this.failureReason=e,process.stderr.write(`\u26A0 TestRelic: Switched to local mode (${e}).
4281
+ `);}}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 e=this.authState.expiresAt??0;if(Date.now()+ml<e)return true;if(!this.config||!this.authState.refreshToken)return this.switchToLocalMode("token_expired_no_refresh"),false;try{let r=await os(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(e){this.authState.mode!=="local"&&(this.authState.mode="local",this.failureReason=e,process.stderr.write(`\u26A0 TestRelic: Switched to local mode (${e}).
4282
4282
  `));}async dispose(){if(this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=null),this.flushPromise){try{await Promise.race([this.flushPromise,As(Rs)]);}catch{}this.flushPromise=null;}this.authState={mode:"local",accessToken:null,refreshToken:null,expiresAt:null,orgId:null,orgName:null,userId:null,userName:null},this.repoId=null,this.gitMetadata=null;}setLocalMode(e){this.authState.mode="local",this.failureReason=e;}handleAuthError(e,r){switch(e){case "invalid_key":this.setLocalMode("invalid_api_key"),process.stderr.write(`\u26A0 TestRelic: API key is invalid or revoked. Running in local mode.
4283
4283
  \u2192 Manage keys: ${ir}
4284
4284
  `);break;case "expired_key":this.setLocalMode("expired_api_key"),process.stderr.write(`\u26A0 TestRelic: API key has expired. Running in local mode.
@@ -4289,15 +4289,15 @@ ${s}
4289
4289
  `);break;case "timeout":this.setLocalMode("auth_timeout"),process.stderr.write(`\u26A0 TestRelic: Authentication timed out. Running in local mode.
4290
4290
  `);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
4291
4291
  `);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?be(this.gitMetadata.remoteUrl):null,r=e?cs(e):this.config.projectName??xe(process.cwd()),n=e??this.config.projectName??xe(process.cwd()),s=this.readRepoCache(n);if(s){this.repoId=s.repoId;return}try{let a=await ls(this.config.endpoint,this.authState.accessToken,n,r,this.config.timeout,this.gitMetadata?.branch);a&&(this.repoId=a.repoId,this.writeRepoCache(n,a.repoId,a.displayName));}catch{}!e&&!this.config.projectName&&!Jt(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
4292
- `);}readRepoCache(e){if(!this.config)return null;let r=join(this.config.queueDirectory,"..","cache","repo.json");try{if(!existsSync(r))return null;let n=readFileSync(r,"utf-8"),s=JSON.parse(n);if(s.gitId!==e||Date.now()-s.resolvedAt>hl)return null;let a=this.hashApiKey();return a&&s.apiKeyHash!==a?null:s}catch{return null}}writeRepoCache(e,r,n){if(!this.config)return;let s=join(this.config.queueDirectory,"..","cache"),a=join(s,"repo.json");try{mkdirSync(s,{recursive:!0});let o={repoId:r,gitId:e,displayName:n,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},i=a+".tmp";writeFileSync(i,JSON.stringify(o,null,2),"utf-8"),renameSync(i,a);}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 e=this.authState.accessToken,r=this.config.queueDirectory,n=this.config.endpoint;this.flushPromise=Promise.race([Ts(r,n,e),As(Rs)]).catch(()=>{});}startHealthCheck(){if(!this.config)return;let e=this.config.endpoint;this.healthCheckTimer=setInterval(async()=>{if(!this.isCloudMode()&&!(!this.failureReason||!["cloud_unreachable","auth_timeout","network_error"].includes(this.failureReason)))try{if(!await Wt(e))return;if(this.config?.apiKey){let n=await Gt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!Kt(n)){let s=n;this.authState={mode:"cloud",accessToken:s.accessToken,refreshToken:s.refreshToken,expiresAt:Date.now()+s.expiresIn*1e3,orgId:s.orgId,orgName:s.orgName,userId:s.userId,userName:s.userName},this.failureReason=null,process.stderr.write(`\u2713 TestRelic: Cloud connectivity restored.
4293
- `),this.startBackgroundFlush();}}}catch{}},ml),typeof this.healthCheckTimer?.unref=="function"&&this.healthCheckTimer.unref();}};function xl(t,e){return e?t?{"2xx":t["2xx"]+e["2xx"],"3xx":t["3xx"]+e["3xx"],"4xx":t["4xx"]+e["4xx"],"5xx":t["5xx"]+e["5xx"],error:t.error+e.error}:{...e}:t}function _s(t,e,r,n){let s=[],a=[],o=null,i=0,d=null,l=0,c=null,u=0,f=null,p=t.filter(h=>h.name===ATTACHMENT_NAME&&h.body),g=false;if(p.length>0)for(let h of p)try{let v=JSON.parse(h.body.toString());if(isTestRelicFilePayload(v)){s=s.concat(v.navigations),a=a.concat(v.apiAssertions),v.networkRequestsFile&&(o=v.networkRequestsFile,i+=v.networkRequestsCount),v.consoleLogsFile&&(d=v.consoleLogsFile,l+=v.consoleLogsCount),v.apiCallsFile&&(c=v.apiCallsFile,u+=v.apiCallsCount),f=xl(f,v.apiStatusMix),g=!0;continue}if(isTestRelicDataPayload(v)){s=s.concat(v.navigations),Array.isArray(v.apiAssertions)&&(a=a.concat(v.apiAssertions)),i+=v.networkRequests?.length??0,u+=v.apiCalls?.length??0;let y=v.consoleLogs;Array.isArray(y)&&(l+=y.length),g=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
4294
- `);}return g||(s=e.filter(h=>h.type==="lambdatest-navigation"&&h.description).map(h=>{try{return JSON.parse(h.description)}catch{return null}}).filter(h=>h!==null)),s.length===0&&i===0&&u===0&&!n&&!g&&process.stderr.write(`[testrelic] Warning: No data found for test "${r}". Make sure your tests import { test, expect } from '@testrelic/playwright-analytics/fixture' instead of '@playwright/test'. Without the TestRelic fixture, network logs, video sync, and Test Navigation data cannot be captured.
4295
- `),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:c,apiCallsCount:u,apiStatusMix:f}}function ze(t=process.env){let e=wl(t.TESTRELIC_CLOUD_PLATFORM);if(e)return {cloudPlatform:e,cloudBuildId:t.TESTRELIC_CLOUD_BUILD_ID||void 0,cloudSessionId:t.TESTRELIC_CLOUD_SESSION_ID||void 0};if(t.BROWSERSTACK_USERNAME||t.BROWSERSTACK_ACCESS_KEY)return {cloudPlatform:"browserstack",cloudBuildId:t.BROWSERSTACK_BUILD_NAME||t.BROWSERSTACK_BUILD_ID||void 0,cloudSessionId:t.BROWSERSTACK_SESSION_ID||void 0};if(t.LT_USERNAME||t.LAMBDATEST_USERNAME||t.LT_ACCESS_KEY||t.LAMBDATEST_ACCESS_KEY)return {cloudPlatform:"lambdatest",cloudBuildId:t.LT_BUILD||t.LAMBDATEST_BUILD||void 0,cloudSessionId:t.LT_SESSION_ID||t.LAMBDATEST_SESSION_ID||void 0};let r=t.PLAYWRIGHT_WS_ENDPOINT;if(r){if(/cdp\.lambdatest\.com/i.test(r))return {cloudPlatform:"lambdatest"};if(/cdp\.browserstack\.com/i.test(r))return {cloudPlatform:"browserstack"}}return {}}function wl(t){if(!t)return;let e=t.toLowerCase().trim();if(e==="browserstack"||e==="bs")return "browserstack";if(e==="lambdatest"||e==="lt")return "lambdatest"}var Rl=5,je=[1e3,3e3,9e3],ie=3,dr=3e4,Al={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip",".json":"application/json"},or=0,lr=[];async function _l(){or>=Rl&&await new Promise(t=>lr.push(t)),or++;}function Il(){or--,lr.length>0&&lr.shift()();}async function Ve(t){return new Promise(e=>setTimeout(e,t))}function Ml(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return Al[e]??"application/octet-stream"}function El(t){try{return statSync(t).size}catch{return 0}}async function Pl(t,e,r,n,s){let a=`${t}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:basename(r.filePath),contentType:s,type:r.type,sizeBytes:n});for(let i=0;i<ie;i++)try{let d=await J(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:o},dr);if(d.ok)return await d.json();if(d.status>=500&&i<ie-1){await Ve(je[i]);continue}return null}catch{if(i<ie-1){await Ve(je[i]);continue}return null}return null}async function Ll(t,e,r,n){let s=us(n,dr);for(let a=0;a<ie;a++)try{let o=createReadStream(e),i=Readable.toWeb(o),d=await J(t,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(n)},body:i,duplex:"half"},s);if(d.ok)return !0;if(d.status>=500&&a<ie-1){await Ve(je[a]);continue}return !1}catch{if(a<ie-1){await Ve(je[a]);continue}return false}return false}async function Nl(t,e,r){let n=`${t}/artifacts/confirm`;try{return (await J(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({artifactId:r})},dr)).ok}catch{return false}}async function Dl(t,e,r,n){let s=El(r.filePath);if(s===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(s>n*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let a=Ml(r.filePath);await _l();try{let o=await Pl(t,e,r,s,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Ll(o.uploadUrl,r.filePath,a,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let d=await Nl(t,e,o.artifactId);return {success:d,storageKey:o.storageKey,artifactId:o.artifactId,error:d?null:"confirm_failed"}}finally{Il();}}async function Is(t,e,r,n,s){let a=new Map,o=r.map(async i=>{if(s?.expired()){a.set(i.filePath,{success:false,storageKey:null,artifactId:null,error:"upload_budget_exhausted"});return}let d=await Dl(t,e,i,n);a.set(i.filePath,d);});return await Promise.allSettled(o),a}function ur(t){let r=t.getGitMetadata()?.remoteUrl;return r?be(r):t.getConfig()?.projectName??xe(process.cwd())}async function Ms(t,e,r,n,s){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=V(),d=ze(),l=Fe();return (await ms(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:ur(t),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:n,totalTests:null,ciProvider:i?.provider??null,ciRunUrl:i?.runUrl??null,environment:s??d.cloudPlatform??null,cloudPlatform:d.cloudPlatform??null,cloudBuildId:d.cloudBuildId??null,cloudSessionId:d.cloudSessionId??null,...l?{runType:l}:{},testType:"e2e"}))?.runId??null}var Bl=[{field:"baseline",keyField:"baselineKey",type:"baseline"},{field:"actual",keyField:"actualKey",type:"screenshot"},{field:"diff",keyField:"diffKey",type:"diff"},{field:"baselineDom",keyField:"baselineDomKey",type:"dom"},{field:"actualDom",keyField:"actualDomKey",type:"dom"}],Ol=true,ql=50,cr={keyMap:new Map,visualKeyMap:new Map,total:0,uploaded:0};async function Ul(t,e,r,n,s){let a=new Map,o=new Map;if(!(e?.uploadArtifacts??Ol)||!await t.ensureValidToken())return cr;let l=[],c=new Map,u=new Map;for(let h of n){if(h.artifacts.screenshot){let y=join(h.outputDir,h.artifacts.screenshot);l.push({filePath:y,runId:r,testId:h.testId,type:"screenshot"}),c.set(y,{testId:h.testId,field:"screenshot"});}if(h.artifacts.video){let y=join(h.outputDir,h.artifacts.video);l.push({filePath:y,runId:r,testId:h.testId,type:"video"}),c.set(y,{testId:h.testId,field:"video"});}if(h.artifacts.trace){let y=join(h.outputDir,h.artifacts.trace);l.push({filePath:y,runId:r,testId:h.testId,type:"trace"}),c.set(y,{testId:h.testId,field:"trace"});}let v=h.visual??[];for(let y=0;y<v.length;y++){let b=v[y];if(b)for(let k of Bl){let A=b[k.field];if(!A)continue;let E=join(h.outputDir,A);l.push({filePath:E,runId:r,testId:h.testId,type:k.type}),c.set(E,{testId:h.testId,field:"visual",visualIndex:y,visualKey:k.keyField});}}}if(l.length===0)return cr;let f=e?.artifactMaxSizeMb??ql,p=await Is(t.getEndpoint(),t.getAccessToken(),l,f,s),g=new Map;for(let[h,v]of p){if(!v.success||!v.storageKey)continue;let y=c.get(h);if(!y)continue;let b=g.get(y.testId)??{};if(y.field==="screenshot"&&(b.screenshotKey=v.storageKey),y.field==="video"&&(b.videoKey=v.storageKey),y.field==="trace"&&(b.traceKey=v.storageKey),y.field==="visual"&&y.visualIndex!==void 0&&y.visualKey){let k=u.get(y.testId)??new Map,A=k.get(y.visualIndex)??{};A[y.visualKey]=v.storageKey,k.set(y.visualIndex,A),u.set(y.testId,k);}g.set(y.testId,b);}for(let h of n){if(h.visual&&h.visual.length>0){let y=u.get(h.testId);o.set(h.testId,h.visual.map((b,k)=>({...b,...y?.get(k)??{}})));}let v=g.get(h.testId);a.set(h.testId,{...h.artifacts,...v?.screenshotKey?{screenshotKey:v.screenshotKey}:{},...v?.videoKey?{videoKey:v.videoKey}:{},...v?.traceKey?{traceKey:v.traceKey}:{}});}let m=Array.from(p.values()).filter(h=>h.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
4296
- `),{keyMap:a,visualKeyMap:o,total:l.length,uploaded:m}}async function pr(t,e,r,n,s,a,o,i,d,l,c){let u={realtimeFinalizeAttempted:false,realtimeFinalized:false,batchAttempted:false,batchAcknowledged:false,artifactsTotal:0,artifactsUploaded:0,failureReason:null},f=new Be(e?.uploadBudgetMs??12e4),p=g=>{u.failureReason||(u.failureReason=g);};try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){u.realtimeFinalizeAttempted=!0;let h=await t.ensureValidToken(),v=t.getGitMetadata(),y=Xt(c),b={finishedAt:o,duration:i,summary:d,...v?.commitMessage?{commitMessage:v.commitMessage}:{},testType:y.testType,...y.testType==="api"?{apiProtocol:y.apiProtocol,metadata:y.metadata}:{}};if(h){let k=await ys(t.getEndpoint(),t.getAccessToken(),s,b);if(u.realtimeFinalized=k,!k){p("finalize_failed_after_retries");let A=e?.queueDirectory??".testrelic/queue";we(A,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",b,{"Content-Type":"application/json"});}}else {p(t.getFailureReason()??"token_invalid");let k=e?.queueDirectory??".testrelic/queue";we(k,n,"finalize",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",b,{"Content-Type":"application/json"});}}let g=new Map,m=new Map;if(t.isCloudMode()&&l&&l.length>0){let h=await Ul(t,e,n,l,f);g=h.keyMap,m=h.visualKeyMap,u.artifactsTotal=h.total,u.artifactsUploaded=h.uploaded;}if(t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(u.batchAttempted=!0,await t.ensureValidToken()){let v=t.getGitMetadata(),y=V(),b=ur(t),k=zl(jl(a,g),m),A=Zt(k,b,v,y,Hl(c,m),ze()),E=await hs(t.getEndpoint(),t.getAccessToken(),A,async()=>await t.ensureValidToken()?t.getAccessToken():null,e?.timeout,f);if(u.batchAcknowledged=E.success,!E.success){let T=E;p(T.reason);let x=e?.queueDirectory??".testrelic/queue";we(x,n,"batch",T.reason,T.targetEndpoint,T.method,T.payload,{"Content-Type":"application/json"});}}else {p(t.getFailureReason()??"token_invalid");let v=e?.queueDirectory??".testrelic/queue",y=t.getGitMetadata(),b=V(),k=ur(t),A=Zt(a,k,y,b,void 0,ze());we(v,n,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",A,{"Content-Type":"application/json"});}await t.dispose();}catch(g){p(g instanceof Error?g.message:"unexpected_upload_error");try{await t.dispose();}catch{}}return u}function Hl(t,e){return !t||e.size===0?t:t.map(r=>{let n=e.get(r.testId);return n?{...r,visual:n}:r})}function zl(t,e){if(e.size===0)return t;let r=t.timeline.map(n=>{let s=n.tests;if(!Array.isArray(s))return n;let a=false,o=s.map(i=>{let d=i.testId;if(!d)return i;let l=e.get(d);return l?(a=true,{...i,visual:l}):i});return a?{...n,tests:o}:n});return {...t,timeline:r}}function jl(t,e){if(e.size===0)return t;let r=t.timeline.map(n=>{let s=n.testId;if(!s)return n;let a=e.get(s);return a?{...n,...a.screenshotKey?{screenshotKey:a.screenshotKey}:{},...a.videoKey?{videoKey:a.videoKey}:{}}:n});return {...t,timeline:r}}var Vl=new Set(["batch","realtime","both"]),ke=Object.freeze({attempted:false,acknowledged:false,runId:null,endpoint:null,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:"cloud reporting was never initialised"});function $l(t){switch(t){case "no_api_key":return "cloud mode off \u2014 no API key configured";case "cloud_unreachable":case "network_error":return "cloud endpoint unreachable \u2014 the run stayed local";case "invalid_api_key":return "API key rejected as invalid or revoked \u2014 the run stayed local";case "expired_api_key":return "API key has expired \u2014 the run stayed local";case "validation_error":return "API key format rejected \u2014 the run stayed local";case "rate_limited":return "rate limited during authentication \u2014 the run stayed local";case "auth_timeout":return "authentication timed out \u2014 the run stayed local";case "token_expired_no_refresh":case "token_refresh_failed":case "token_refresh_error":return "access token could not be refreshed \u2014 the run stayed local";case "init_error":return "cloud initialisation timed out \u2014 the run stayed local";case "unexpected_error":return "cloud initialisation failed \u2014 the run stayed local";default:return t?`cloud mode off (${t}) \u2014 the run stayed local`:"cloud mode off \u2014 the run stayed local"}}function Es(t,e,r){if(!t)return ke;if(!t.isCloudMode())return {...ke,detail:$l(t.getFailureReason())};let n=e??"batch";if(!Vl.has(n))return {...ke,detail:`upload strategy '${n}' is not recognised \u2014 nothing was sent`};let s=t.getEndpoint(),a=n==="realtime"||n==="both";return a&&r?{attempted:true,acknowledged:true,runId:r,endpoint:s,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:null}:{attempted:true,acknowledged:false,runId:null,endpoint:s,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:a?"run init failed \u2014 the platform did not acknowledge this run":`upload runs at the end of the run under the '${n}' strategy \u2014 not sent yet`}}function fr(t,e,r){if(!t.attempted)return t;if(!e)return {...t,detail:t.acknowledged?"upload timed out before it completed \u2014 the run may be incomplete on the platform":"upload timed out before the platform acknowledged this run",acknowledged:t.acknowledged};let n=t.acknowledged||e.batchAcknowledged,s=t.runId??(e.batchAcknowledged?r:null),a=e.realtimeFinalizeAttempted?e.realtimeFinalized:e.batchAcknowledged,o=null;return n?a||(o="run acknowledged but not closed out \u2014 finalize failed and was queued for retry"):o=e.failureReason?`upload failed (${e.failureReason}) \u2014 queued locally for retry`:"upload failed \u2014 the platform did not acknowledge this run",{attempted:true,acknowledged:n,runId:s,endpoint:t.endpoint,finalized:a,artifactsUploaded:e.artifactsUploaded,artifactsTotal:e.artifactsTotal,detail:o}}function Y(t){try{return readFileSync(t,"utf-8").split(`
4297
- `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function Zl(t){if(!t)return null;let e=t.split(`
4298
- `).map(a=>a.trim()).filter(Boolean);if(e.length===0)return null;let r=e.filter(a=>!/^Error:\s*expect\(/.test(a));if(r.length===0)return e[0]??null;let n=r[0],s=r[1];return s!==void 0&&/^Received:/.test(s)&&/^Expected:/.test(n)?`${n} \xB7 ${s}`:n}function hr(t){switch(t){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function Ql(t,e,r){let n=`${t}::${e}::${r}`;return createHash("sha256").update(n).digest("hex").substring(0,16)}function ed(t){return t.length<=3?"":t[t.length-2]}function td(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Os(t){return t===null?"error":t>=200&&t<300?"2xx":t>=300&&t<400?"3xx":t>=400&&t<500?"4xx":t>=500&&t<600?"5xx":"error"}function rd(t){let e={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},r=e;for(let n of t){let s=typeof n.responseStatusCode=="number"?n.responseStatusCode:null;r[Os(s)]++;}return e}function Ds(t){if(t){for(let e of t)if(e.status==="failed")return {type:e.type,expected:Fs(e.expected),actual:Fs(e.actual),...e.expression?{expression:e.expression}:{}}}}function Fs(t){if(t===void 0)return "undefined";if(t===null)return "null";let e;if(typeof t=="string")e=t;else try{e=JSON.stringify(t)??String(t);}catch{e=String(t);}return e.length>200?e.slice(0,200)+"\u2026":e}function We(t,e){if(!t)return 0;let r=0;for(let n of t)n.status===e&&r++;return r}function qs(t,e){for(let r of t)e[r.category]=(e[r.category]??0)+1,r.children.length>0&&qs(r.children,e);}function nd(t){if(t.length===0)return null;let e=[...t].sort((n,s)=>n-s),r=e.reduce((n,s)=>n+s,0);return {avg:Math.round(r/e.length),min:e[0],max:e[e.length-1],p50:ee(e,50),p95:ee(e,95),p99:ee(e,99)}}var Us=2e5,Ge=1e5;function Bs(t,e,r,n,s,a,o){let i={retryIndex:t,apiCalls:e?.length??0,apiUrls:[],methodCounts:{},statusRanges:{"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},responseTimes:[],passedAssertions:0,failedAssertions:0,assertions:r.length,navigations:n.length,navUrls:[],networkRequests:s,consoleLogs:a,actionSteps:o?.length??0,actionCategories:{}};if(e){let l=new Set;for(let c of e){let u=typeof c.method=="string"?c.method:"OTHER";i.methodCounts[u]=(i.methodCounts[u]??0)+1;let f=typeof c.url=="string"?c.url:null;f&&l.size<Ge&&l.add(jt(f));let p=typeof c.responseStatusCode=="number"?c.responseStatusCode:typeof c.statusCode=="number"?c.statusCode:null,g=p!==null&&Number.isFinite(p)?p:null;i.statusRanges[Os(g)]++;let m=typeof c.responseTimeMs=="number"?c.responseTimeMs:typeof c.durationMs=="number"?c.durationMs:null;m!==null&&Number.isFinite(m)&&i.responseTimes.length<Us&&i.responseTimes.push(m);}i.apiUrls=Array.from(l);}for(let l of r)l.status==="passed"?i.passedAssertions++:i.failedAssertions++;let d=new Set;for(let l of n)l.url&&d.size<Ge&&d.add(l.url);return i.navUrls=Array.from(d),o&&qs(o,i.actionCategories),i}function sd(){return {apiUrlSet:new Set,methodCounts:{},statusRanges:{"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},responseTimes:[],passedAssertions:0,failedAssertions:0,navUrlSet:new Set,actionCategoryCounts:{},volApiCalls:0,volAssertions:0,volNavigations:0,volNetworkRequests:0,volConsoleLogs:0,volActionSteps:0}}function ad(t){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":t?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[t.provider]??"CI":"Local"}function id(){let t=platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function od(t){let e=t.parent?.project?.()?.use;if(!e)return;let{browserName:r,channel:n}=e;if(n){let a=n.toLowerCase();return a==="chrome"||a==="chrome-stable"?"Chrome":a.startsWith("chrome-beta")?"Chrome Beta":a.startsWith("chrome-dev")?"Chrome Dev":a.startsWith("chrome-canary")?"Chrome Canary":a==="msedge"||a==="msedge-stable"?"Microsoft Edge":a.startsWith("msedge-beta")?"Edge Beta":a.startsWith("msedge-dev")?"Edge Dev":a.startsWith("msedge-canary")?"Edge Canary":n}if(r){let a=r.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":r}let s=e.defaultBrowserType;if(s){let a=s.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":s}}function ld(t,e,r){let n=r.parent?.project?.(),s="unknown";n!==void 0&&(n.use.isMobile===true?s="mobile":s="e2e");let a=["e2e","api","unit","mobile"];for(let d of a)if(t.some(l=>l===`@${d}`||l===d))return d;let o=e.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let d of i)if(o.includes(`/${d}/`))return d;return s}var dd="__testrelic_api_config";function cd(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var Ke=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.navigationsCaptured=false;this.memoryPressureWarned=false;this.testCount=0;this.cloudClient=null;this.cloudRunId=null;this.runTimestamp="";this.updatingSnapshots=false;this.cloudReceipt=ke;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,visualChecks:0,visualFailures:0,visualDomChanges:0};this.streamingTestAgg=new Map;this.config=Ur(e),this.apiConfig=qr(e);}upsertAggContribution(e,r){let n=this.streamingTestAgg.get(e);(!n||r.retryIndex>n.retryIndex)&&this.streamingTestAgg.set(e,r);}async onBegin(e,r){try{this.rootDir=e.rootDir;let n=e.updateSnapshots;if(this.updatingSnapshots=n==="all"||n==="changed",this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??randomUUID(),this.config.reportMode==="auto"){let i=r.allTests().length;this.activeReportMode=i>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let s=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${s} tests)
4299
- `),this.activeReportMode==="streaming"){let i=dirname(this.config.outputPath);this.streamingWriter=new he(i);let d=()=>{if(this.streamingWriter){try{this.streamingWriter.writeIndex(this.testIndex);let l={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(),cloudUpload:this.cloudReceipt};this.streamingWriter.writeSummary(l);}catch{}this.streamingWriter.dispose();}try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let l=this.cloudClient.getAccessToken();l&&nr(this.cloudClient.getEndpoint(),l,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",d),process.on("SIGINT",d);}if(this.config.includeArtifacts){let i=dirname(this.config.outputPath);this.runTimestamp=Cn(join(i,"artifacts"));try{Jn(join(i,"artifacts"));}catch{}}let a=V();this.detectedOs=id(),this.detectedSource=ad(a);let o=await Q(async()=>(this.cloudClient=new He(this.config.cloud),await this.cloudClient.initialize(),Ms(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource)),Xn,"Cloud initialization");if(this.cloudRunId=o??null,o===void 0&&this.cloudClient?.switchToLocalMode("init_error"),this.cloudReceipt=Es(this.cloudClient,this.config.cloud?.uploadStrategy,this.cloudRunId),this.activeReportMode!=="streaming"){let i=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let d=this.cloudClient.getAccessToken();d&&nr(this.cloudClient.getEndpoint(),d,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",i),process.on("SIGINT",i);}}catch{}}onTestBegin(e,r){try{e.annotations.push({type:dd,description:cd(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=hr(n.status);let o=n.startTime.toISOString(),i=new Date(n.startTime.getTime()+n.duration).toISOString(),d=e.tags?[...e.tags]:e.annotations.filter(I=>I.type==="tag").map(I=>I.description??""),l=_s(n.attachments,e.annotations,e.title,a==="skipped");(l.navigations.length>0||l.networkRequestsCount>0||l.apiCallsCount>0)&&(this.fixtureDataReceived=!0),l.navigations.length>0&&(this.navigationsCaptured=!0),!this.config.captureNavigation&&l.navigations.length>0&&(l={...l,navigations:[]});let c=null;if(a==="failed"||a==="flaky"){let M=(a==="flaky"?e.results.find(N=>N.status!=="passed")?.errors??[]:n.errors)[0];if(M){let N=zr(this.config.redactPatterns),j=M.location?.file??null,P=l.apiAssertions.find(aa=>aa.status==="failed")?.location??null,re=P!==null&&(j===null||resolve(j)!==resolve(e.location.file)),Sr=re?P.file:j,Qe=re?P.line:M.location?.line??null,fe=null;this.config.includeCodeSnippets&&Qe!==null&&Sr&&(fe=Hr(Sr,Qe,this.config.codeContextLines),fe&&(fe=N(fe))),c={message:N(se(M.message??"Unknown error")),line:Qe,code:fe,stack:this.config.includeStackTrace&&M.stack?N(se(M.stack)):null};}}let u=e.titlePath().filter(Boolean),f=relative(this.rootDir||".",e.location.file).replace(/\\/g,"/"),p=ed(u),g=u.join(" > "),m=f,h=Ql(m,p,g),v=ld(d,m,e),y=v!=="mobile"&&l.apiCallsCount>0?"api":v,b=s==="flaky",k=td(e.results),A=hr(e.expectedStatus),E=hr(n.status),T=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let I=dirname(this.config.outputPath),M=u[u.length-1]??e.title;T=Sn(n.attachments,M,n.retry,I,this.runTimestamp||void 0,h);}let x=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments)try{let I=qn(n.attachments,{updatingSnapshots:this.updatingSnapshots,failureMessage:n.errors.map(M=>M.message??"").join(`
4300
- `)});if(I.length>0){let M=dirname(this.config.outputPath),N=u[u.length-1]??e.title;x=Rn(I,N,n.retry,M,this.runTimestamp||void 0,h);}}catch{}let S=this.config.includeActionSteps&&n.steps?ns(n.steps,n.startTime):null,w=od(e),C={titlePath:u,title:g,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:d,failure:c,specFile:f,navigations:l.navigations,testId:h,filePath:m,suiteName:p,testType:y,isFlaky:b,retryStatus:k,expectedStatus:A,actualStatus:E,artifacts:T,visual:x,apiAssertions:l.apiAssertions,actions:S,networkRequestsFile:l.networkRequestsFile,networkRequestsCount:l.networkRequestsCount,consoleLogsFile:l.consoleLogsFile,consoleLogsCount:l.consoleLogsCount,apiCallsFile:l.apiCallsFile,apiCallsCount:l.apiCallsCount,apiStatusMix:l.apiStatusMix,browser:w,os:this.detectedOs||void 0,source:this.detectedSource||void 0},_=l.consoleLogsFile&&l.consoleLogsCount>0?Y(l.consoleLogsFile):void 0,L=l.networkRequestsFile&&l.networkRequestsCount>0?Y(l.networkRequestsFile):void 0,z=l.apiCallsFile&&l.apiCallsCount>0?Y(l.apiCallsFile):void 0,ce=z?Qt(z):void 0,ue=!L&&z?er(z):void 0,pe=l.apiAssertions&&l.apiAssertions.length>0?tr(l.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:h,title:g,status:a,duration:n.duration,suiteName:p,filePath:m,testType:y,isFlaky:b,startedAt:o,completedAt:i,tags:d,failure:c,retry:n.retry,retryCount:e.results.length-1,retryStatus:k,browser:w,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...S&&S.length>0?{actions:S}:{},...l.navigations&&l.navigations.length>0?{navigations:l.navigations}:{},..._?{consoleLogs:_}:{},...L?{networkRequests:L}:ue?{networkRequests:ue}:{},...ce?{apiCalls:ce}:{},...pe?{protocolAssertions:pe}:{},...x&&x.length>0?{visual:x}:{}});try{let I=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(I==="realtime"||I==="both")){let M=this.cloudClient.getAccessToken();M&&vs(this.cloudClient.getEndpoint(),M,this.cloudRunId,this.buildCloudTestPayload(C));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let I=et(m,u,e.id??"",n.retry),M=n.retry===e.results.length-1,N={id:I,navigations:l.navigations,apiAssertions:l.apiAssertions,actions:S??[],artifacts:T,visual:x,failureDiagnostic:c,hasNetworkFile:l.networkRequestsFile!==null,networkRequestsCount:l.networkRequestsCount,hasConsoleFile:l.consoleLogsFile!==null,consoleLogsCount:l.consoleLogsCount,hasApiCallsFile:l.apiCallsFile!==null,apiCallsCount:l.apiCallsCount,startedAt:o};this.streamingWriter.writeTestDetail(I,N,{networkRequestsFile:l.networkRequestsFile,consoleLogsFile:l.consoleLogsFile,apiCallsFile:l.apiCallsFile});let j={id:I,title:u[u.length-1]??e.title,titlePath:u,filePath:m,status:a,duration:n.duration,project:u[1]??"",retryIndex:n.retry,tags:d,hasNetworkData:l.networkRequestsCount>0,hasConsoleData:l.consoleLogsCount>0,hasArtifacts:T!==null,hasActionSteps:(S?.length??0)>0,visualCount:x?.length??0,visualFailedCount:x?.filter(P=>P.status==="failed").length??0,domChangeCount:x?.reduce((P,re)=>P+(re.domChangeCount??0),0)??0,...(()=>{let P=x?.find(re=>re.diff);return P?.diff?{visualDiffPath:P.diff}:{}})(),errorMessage:Zl(c?.message),networkCount:l.networkRequestsCount,consoleCount:l.consoleLogsCount,actionCount:S?.length??0,testType:y,apiCallCount:l.apiCallsCount,...l.apiStatusMix?{apiStatusMix:l.apiStatusMix}:{},assertionsPassed:We(l.apiAssertions,"passed"),assertionsFailed:We(l.apiAssertions,"failed"),...(()=>{let P=Ds(l.apiAssertions);return P?{firstFailedAssertion:P}:{}})(),isRetry:!M,retryGroupKey:tt(m,u,e.id??"")};if(this.testIndex.push(j),M)switch(this.summaryCounters.total++,a){case "passed":this.summaryCounters.passed++;break;case "failed":this.summaryCounters.failed++;break;case "flaky":this.summaryCounters.flaky++;break;case "skipped":this.summaryCounters.skipped++;break;case "timedout":this.summaryCounters.timedOut++;break;default:this.summaryCounters.interrupted++;break}this.upsertAggContribution(`${m}::${u.join(" > ")}`,Bs(n.retry,z,l.apiAssertions,l.navigations,l.networkRequestsCount,l.consoleLogsCount,S)),(T||x)&&this.pendingArtifactEntries.push({testId:h,artifacts:T??{},visual:x,outputDir:dirname(this.config.outputPath)}),C.actions=null,C.apiAssertions=null,C.navigations=[],C.artifacts=null,C.failure=null,C.networkRequestsFile=null,C.consoleLogsFile=null,C.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(C),this.testCount++,this.checkMemoryPressure();}catch{}}async onEnd(e){try{let r=new Date().toISOString(),n=new Date(this.startedAt).getTime(),a=new Date(r).getTime()-n,o=this.activeReportMode==="streaming"?this.testIndex.some(d=>d.status!=="skipped"):this.collectedTests.some(d=>d.status!=="skipped");!this.fixtureDataReceived&&o&&process.stderr.write(`
4292
+ `);}readRepoCache(e){if(!this.config)return null;let r=join(this.config.queueDirectory,"..","cache","repo.json");try{if(!existsSync(r))return null;let n=readFileSync(r,"utf-8"),s=JSON.parse(n);if(s.gitId!==e||Date.now()-s.resolvedAt>vl)return null;let a=this.hashApiKey();return a&&s.apiKeyHash!==a?null:s}catch{return null}}writeRepoCache(e,r,n){if(!this.config)return;let s=join(this.config.queueDirectory,"..","cache"),a=join(s,"repo.json");try{mkdirSync(s,{recursive:!0});let o={repoId:r,gitId:e,displayName:n,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},i=a+".tmp";writeFileSync(i,JSON.stringify(o,null,2),"utf-8"),renameSync(i,a);}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 e=this.authState.accessToken,r=this.config.queueDirectory,n=this.config.endpoint;this.flushPromise=Promise.race([Ts(r,n,e),As(Rs)]).catch(()=>{});}startHealthCheck(){if(!this.config)return;let e=this.config.endpoint;this.healthCheckTimer=setInterval(async()=>{if(!this.isCloudMode()&&!(!this.failureReason||!["cloud_unreachable","auth_timeout","network_error"].includes(this.failureReason)))try{if(!await Wt(e))return;if(this.config?.apiKey){let n=await Gt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!Kt(n)){let s=n;this.authState={mode:"cloud",accessToken:s.accessToken,refreshToken:s.refreshToken,expiresAt:Date.now()+s.expiresIn*1e3,orgId:s.orgId,orgName:s.orgName,userId:s.userId,userName:s.userName},this.failureReason=null,process.stderr.write(`\u2713 TestRelic: Cloud connectivity restored.
4293
+ `),this.startBackgroundFlush();}}}catch{}},yl),typeof this.healthCheckTimer?.unref=="function"&&this.healthCheckTimer.unref();}};function kl(t,e){return e?t?{"2xx":t["2xx"]+e["2xx"],"3xx":t["3xx"]+e["3xx"],"4xx":t["4xx"]+e["4xx"],"5xx":t["5xx"]+e["5xx"],error:t.error+e.error}:{...e}:t}function _s(t,e,r,n){let s=[],a=[],o=null,i=0,d=null,l=0,c=null,u=0,p=null,g=t.filter(h=>h.name===ATTACHMENT_NAME&&h.body),f=false;if(g.length>0)for(let h of g)try{let v=JSON.parse(h.body.toString());if(isTestRelicFilePayload(v)){s=s.concat(v.navigations),a=a.concat(v.apiAssertions),v.networkRequestsFile&&(o=v.networkRequestsFile,i+=v.networkRequestsCount),v.consoleLogsFile&&(d=v.consoleLogsFile,l+=v.consoleLogsCount),v.apiCallsFile&&(c=v.apiCallsFile,u+=v.apiCallsCount),p=kl(p,v.apiStatusMix),f=!0;continue}if(isTestRelicDataPayload(v)){s=s.concat(v.navigations),Array.isArray(v.apiAssertions)&&(a=a.concat(v.apiAssertions)),i+=v.networkRequests?.length??0,u+=v.apiCalls?.length??0;let y=v.consoleLogs;Array.isArray(y)&&(l+=y.length),f=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
4294
+ `);}return f||(s=e.filter(h=>h.type==="lambdatest-navigation"&&h.description).map(h=>{try{return JSON.parse(h.description)}catch{return null}}).filter(h=>h!==null)),s.length===0&&i===0&&u===0&&!n&&!f&&process.stderr.write(`[testrelic] Warning: No data found for test "${r}". Make sure your tests import { test, expect } from '@testrelic/playwright-analytics/fixture' instead of '@playwright/test'. Without the TestRelic fixture, network logs, video sync, and Test Navigation data cannot be captured.
4295
+ `),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:c,apiCallsCount:u,apiStatusMix:p}}function ze(t=process.env){let e=Cl(t.TESTRELIC_CLOUD_PLATFORM);if(e)return {cloudPlatform:e,cloudBuildId:t.TESTRELIC_CLOUD_BUILD_ID||void 0,cloudSessionId:t.TESTRELIC_CLOUD_SESSION_ID||void 0};if(t.BROWSERSTACK_USERNAME||t.BROWSERSTACK_ACCESS_KEY)return {cloudPlatform:"browserstack",cloudBuildId:t.BROWSERSTACK_BUILD_NAME||t.BROWSERSTACK_BUILD_ID||void 0,cloudSessionId:t.BROWSERSTACK_SESSION_ID||void 0};if(t.LT_USERNAME||t.LAMBDATEST_USERNAME||t.LT_ACCESS_KEY||t.LAMBDATEST_ACCESS_KEY)return {cloudPlatform:"lambdatest",cloudBuildId:t.LT_BUILD||t.LAMBDATEST_BUILD||void 0,cloudSessionId:t.LT_SESSION_ID||t.LAMBDATEST_SESSION_ID||void 0};let r=t.PLAYWRIGHT_WS_ENDPOINT;if(r){if(/cdp\.lambdatest\.com/i.test(r))return {cloudPlatform:"lambdatest"};if(/cdp\.browserstack\.com/i.test(r))return {cloudPlatform:"browserstack"}}return {}}function Cl(t){if(!t)return;let e=t.toLowerCase().trim();if(e==="browserstack"||e==="bs")return "browserstack";if(e==="lambdatest"||e==="lt")return "lambdatest"}var _l=5,je=[1e3,3e3,9e3],ie=3,dr=3e4,Il={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip",".json":"application/json"},or=0,lr=[];async function Ml(){or>=_l&&await new Promise(t=>lr.push(t)),or++;}function Pl(){or--,lr.length>0&&lr.shift()();}async function Ve(t){return new Promise(e=>setTimeout(e,t))}function El(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return Il[e]??"application/octet-stream"}function Ll(t){try{return statSync(t).size}catch{return 0}}async function Nl(t,e,r,n,s){let a=`${t}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:basename(r.filePath),contentType:s,type:r.type,sizeBytes:n});for(let i=0;i<ie;i++)try{let d=await J(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:o},dr);if(d.ok)return await d.json();if(d.status>=500&&i<ie-1){await Ve(je[i]);continue}return null}catch{if(i<ie-1){await Ve(je[i]);continue}return null}return null}async function Dl(t,e,r,n){let s=us(n,dr);for(let a=0;a<ie;a++)try{let o=createReadStream(e),i=Readable.toWeb(o),d=await J(t,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(n)},body:i,duplex:"half"},s);if(d.ok)return !0;if(d.status>=500&&a<ie-1){await Ve(je[a]);continue}return !1}catch{if(a<ie-1){await Ve(je[a]);continue}return false}return false}async function Fl(t,e,r){let n=`${t}/artifacts/confirm`;try{return (await J(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({artifactId:r})},dr)).ok}catch{return false}}async function Bl(t,e,r,n){let s=Ll(r.filePath);if(s===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(s>n*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let a=El(r.filePath);await Ml();try{let o=await Nl(t,e,r,s,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Dl(o.uploadUrl,r.filePath,a,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let d=await Fl(t,e,o.artifactId);return {success:d,storageKey:o.storageKey,artifactId:o.artifactId,error:d?null:"confirm_failed"}}finally{Pl();}}async function Is(t,e,r,n,s){let a=new Map,o=r.map(async i=>{if(s?.expired()){a.set(i.filePath,{success:false,storageKey:null,artifactId:null,error:"upload_budget_exhausted"});return}let d=await Bl(t,e,i,n);a.set(i.filePath,d);});return await Promise.allSettled(o),a}function ur(t){let r=t.getGitMetadata()?.remoteUrl;return r?be(r):t.getConfig()?.projectName??xe(process.cwd())}async function Ms(t,e,r,n,s){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=V(),d=ze(),l=Fe();return (await ms(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:ur(t),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:n,totalTests:null,ciProvider:i?.provider??null,ciRunUrl:i?.runUrl??null,environment:s??d.cloudPlatform??null,cloudPlatform:d.cloudPlatform??null,cloudBuildId:d.cloudBuildId??null,cloudSessionId:d.cloudSessionId??null,...l?{runType:l}:{},testType:"e2e"}))?.runId??null}var ql=[{field:"baseline",keyField:"baselineKey",type:"baseline"},{field:"actual",keyField:"actualKey",type:"screenshot"},{field:"diff",keyField:"diffKey",type:"diff"},{field:"baselineDom",keyField:"baselineDomKey",type:"dom"},{field:"actualDom",keyField:"actualDomKey",type:"dom"}],Hl=true,Ul=50,cr={keyMap:new Map,visualKeyMap:new Map,total:0,uploaded:0};async function zl(t,e,r,n,s){let a=new Map,o=new Map;if(!(e?.uploadArtifacts??Hl)||!await t.ensureValidToken())return cr;let l=[],c=new Map,u=new Map;for(let h of n){if(h.artifacts.screenshot){let y=join(h.outputDir,h.artifacts.screenshot);l.push({filePath:y,runId:r,testId:h.testId,type:"screenshot"}),c.set(y,{testId:h.testId,field:"screenshot"});}if(h.artifacts.video){let y=join(h.outputDir,h.artifacts.video);l.push({filePath:y,runId:r,testId:h.testId,type:"video"}),c.set(y,{testId:h.testId,field:"video"});}if(h.artifacts.trace){let y=join(h.outputDir,h.artifacts.trace);l.push({filePath:y,runId:r,testId:h.testId,type:"trace"}),c.set(y,{testId:h.testId,field:"trace"});}let v=h.visual??[];for(let y=0;y<v.length;y++){let b=v[y];if(b)for(let k of ql){let A=b[k.field];if(!A)continue;let P=join(h.outputDir,A);l.push({filePath:P,runId:r,testId:h.testId,type:k.type}),c.set(P,{testId:h.testId,field:"visual",visualIndex:y,visualKey:k.keyField});}}}if(l.length===0)return cr;let p=e?.artifactMaxSizeMb??Ul,g=await Is(t.getEndpoint(),t.getAccessToken(),l,p,s),f=new Map;for(let[h,v]of g){if(!v.success||!v.storageKey)continue;let y=c.get(h);if(!y)continue;let b=f.get(y.testId)??{};if(y.field==="screenshot"&&(b.screenshotKey=v.storageKey),y.field==="video"&&(b.videoKey=v.storageKey),y.field==="trace"&&(b.traceKey=v.storageKey),y.field==="visual"&&y.visualIndex!==void 0&&y.visualKey){let k=u.get(y.testId)??new Map,A=k.get(y.visualIndex)??{};A[y.visualKey]=v.storageKey,k.set(y.visualIndex,A),u.set(y.testId,k);}f.set(y.testId,b);}for(let h of n){if(h.visual&&h.visual.length>0){let y=u.get(h.testId);o.set(h.testId,h.visual.map((b,k)=>({...b,...y?.get(k)??{}})));}let v=f.get(h.testId);a.set(h.testId,{...h.artifacts,...v?.screenshotKey?{screenshotKey:v.screenshotKey}:{},...v?.videoKey?{videoKey:v.videoKey}:{},...v?.traceKey?{traceKey:v.traceKey}:{}});}let m=Array.from(g.values()).filter(h=>h.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
4296
+ `),{keyMap:a,visualKeyMap:o,total:l.length,uploaded:m}}async function pr(t,e,r,n,s,a,o,i,d,l,c){let u={realtimeFinalizeAttempted:false,realtimeFinalized:false,batchAttempted:false,batchAcknowledged:false,artifactsTotal:0,artifactsUploaded:0,failureReason:null},p=new Be(e?.uploadBudgetMs??12e4),g=f=>{u.failureReason||(u.failureReason=f);};try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){u.realtimeFinalizeAttempted=!0;let h=await t.ensureValidToken(),v=t.getGitMetadata(),y=Xt(c),b={finishedAt:o,duration:i,summary:d,...v?.commitMessage?{commitMessage:v.commitMessage}:{},testType:y.testType,...y.testType==="api"?{apiProtocol:y.apiProtocol,metadata:y.metadata}:{}};if(h){let k=await ys(t.getEndpoint(),t.getAccessToken(),s,b);if(u.realtimeFinalized=k,!k){g("finalize_failed_after_retries");let A=e?.queueDirectory??".testrelic/queue";we(A,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",b,{"Content-Type":"application/json"});}}else {g(t.getFailureReason()??"token_invalid");let k=e?.queueDirectory??".testrelic/queue";we(k,n,"finalize",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",b,{"Content-Type":"application/json"});}}let f=new Map,m=new Map;if(t.isCloudMode()&&l&&l.length>0){let h=await zl(t,e,n,l,p);f=h.keyMap,m=h.visualKeyMap,u.artifactsTotal=h.total,u.artifactsUploaded=h.uploaded;}if(t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(u.batchAttempted=!0,await t.ensureValidToken()){let v=t.getGitMetadata(),y=V(),b=ur(t),k=Vl($l(a,f),m),A=Zt(k,b,v,y,jl(c,m),ze()),P=await hs(t.getEndpoint(),t.getAccessToken(),A,async()=>await t.ensureValidToken()?t.getAccessToken():null,e?.timeout,p);if(u.batchAcknowledged=P.success,!P.success){let T=P;g(T.reason);let x=e?.queueDirectory??".testrelic/queue";we(x,n,"batch",T.reason,T.targetEndpoint,T.method,T.payload,{"Content-Type":"application/json"});}}else {g(t.getFailureReason()??"token_invalid");let v=e?.queueDirectory??".testrelic/queue",y=t.getGitMetadata(),b=V(),k=ur(t),A=Zt(a,k,y,b,void 0,ze());we(v,n,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",A,{"Content-Type":"application/json"});}await t.dispose();}catch(f){g(f instanceof Error?f.message:"unexpected_upload_error");try{await t.dispose();}catch{}}return u}function jl(t,e){return !t||e.size===0?t:t.map(r=>{let n=e.get(r.testId);return n?{...r,visual:n}:r})}function Vl(t,e){if(e.size===0)return t;let r=t.timeline.map(n=>{let s=n.tests;if(!Array.isArray(s))return n;let a=false,o=s.map(i=>{let d=i.testId;if(!d)return i;let l=e.get(d);return l?(a=true,{...i,visual:l}):i});return a?{...n,tests:o}:n});return {...t,timeline:r}}function $l(t,e){if(e.size===0)return t;let r=t.timeline.map(n=>{let s=n.testId;if(!s)return n;let a=e.get(s);return a?{...n,...a.screenshotKey?{screenshotKey:a.screenshotKey}:{},...a.videoKey?{videoKey:a.videoKey}:{}}:n});return {...t,timeline:r}}var Wl=new Set(["batch","realtime","both"]),ke=Object.freeze({attempted:false,acknowledged:false,runId:null,endpoint:null,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:"cloud reporting was never initialised"});function Gl(t){switch(t){case "no_api_key":return "cloud mode off \u2014 no API key configured";case "cloud_unreachable":case "network_error":return "cloud endpoint unreachable \u2014 the run stayed local";case "invalid_api_key":return "API key rejected as invalid or revoked \u2014 the run stayed local";case "expired_api_key":return "API key has expired \u2014 the run stayed local";case "validation_error":return "API key format rejected \u2014 the run stayed local";case "rate_limited":return "rate limited during authentication \u2014 the run stayed local";case "auth_timeout":return "authentication timed out \u2014 the run stayed local";case "token_expired_no_refresh":case "token_refresh_failed":case "token_refresh_error":return "access token could not be refreshed \u2014 the run stayed local";case "init_error":return "cloud initialisation timed out \u2014 the run stayed local";case "unexpected_error":return "cloud initialisation failed \u2014 the run stayed local";default:return t?`cloud mode off (${t}) \u2014 the run stayed local`:"cloud mode off \u2014 the run stayed local"}}function Ps(t,e,r){if(!t)return ke;if(!t.isCloudMode())return {...ke,detail:Gl(t.getFailureReason())};let n=e??"batch";if(!Wl.has(n))return {...ke,detail:`upload strategy '${n}' is not recognised \u2014 nothing was sent`};let s=t.getEndpoint(),a=n==="realtime"||n==="both";return a&&r?{attempted:true,acknowledged:true,runId:r,endpoint:s,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:null}:{attempted:true,acknowledged:false,runId:null,endpoint:s,finalized:false,artifactsUploaded:0,artifactsTotal:0,detail:a?"run init failed \u2014 the platform did not acknowledge this run":`upload runs at the end of the run under the '${n}' strategy \u2014 not sent yet`}}function fr(t,e,r){if(!t.attempted)return t;if(!e)return {...t,detail:t.acknowledged?"upload timed out before it completed \u2014 the run may be incomplete on the platform":"upload timed out before the platform acknowledged this run",acknowledged:t.acknowledged};let n=t.acknowledged||e.batchAcknowledged,s=t.runId??(e.batchAcknowledged?r:null),a=e.realtimeFinalizeAttempted?e.realtimeFinalized:e.batchAcknowledged,o=null;return n?a||(o="run acknowledged but not closed out \u2014 finalize failed and was queued for retry"):o=e.failureReason?`upload failed (${e.failureReason}) \u2014 queued locally for retry`:"upload failed \u2014 the platform did not acknowledge this run",{attempted:true,acknowledged:n,runId:s,endpoint:t.endpoint,finalized:a,artifactsUploaded:e.artifactsUploaded,artifactsTotal:e.artifactsTotal,detail:o}}function Y(t){try{return readFileSync(t,"utf-8").split(`
4297
+ `).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function ed(t){if(!t)return null;let e=t.split(`
4298
+ `).map(a=>a.trim()).filter(Boolean);if(e.length===0)return null;let r=e.filter(a=>!/^Error:\s*expect\(/.test(a));if(r.length===0)return e[0]??null;let n=r[0],s=r[1];return s!==void 0&&/^Received:/.test(s)&&/^Expected:/.test(n)?`${n} \xB7 ${s}`:n}function hr(t){switch(t){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function td(t,e,r){let n=`${t}::${e}::${r}`;return createHash("sha256").update(n).digest("hex").substring(0,16)}function rd(t){return t.length<=3?"":t[t.length-2]}function nd(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Os(t){return t===null?"error":t>=200&&t<300?"2xx":t>=300&&t<400?"3xx":t>=400&&t<500?"4xx":t>=500&&t<600?"5xx":"error"}function sd(t){let e={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},r=e;for(let n of t){let s=typeof n.responseStatusCode=="number"?n.responseStatusCode:null;r[Os(s)]++;}return e}function Ds(t){if(t){for(let e of t)if(e.status==="failed")return {type:e.type,expected:Fs(e.expected),actual:Fs(e.actual),...e.expression?{expression:e.expression}:{}}}}function Fs(t){if(t===void 0)return "undefined";if(t===null)return "null";let e;if(typeof t=="string")e=t;else try{e=JSON.stringify(t)??String(t);}catch{e=String(t);}return e.length>200?e.slice(0,200)+"\u2026":e}function We(t,e){if(!t)return 0;let r=0;for(let n of t)n.status===e&&r++;return r}function qs(t,e){for(let r of t)e[r.category]=(e[r.category]??0)+1,r.children.length>0&&qs(r.children,e);}function ad(t){if(t.length===0)return null;let e=[...t].sort((n,s)=>n-s),r=e.reduce((n,s)=>n+s,0);return {avg:Math.round(r/e.length),min:e[0],max:e[e.length-1],p50:ee(e,50),p95:ee(e,95),p99:ee(e,99)}}var Hs=2e5,Ge=1e5;function Bs(t,e,r,n,s,a,o){let i={retryIndex:t,apiCalls:e?.length??0,apiUrls:[],methodCounts:{},statusRanges:{"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},responseTimes:[],passedAssertions:0,failedAssertions:0,assertions:r.length,navigations:n.length,navUrls:[],networkRequests:s,consoleLogs:a,actionSteps:o?.length??0,actionCategories:{}};if(e){let l=new Set;for(let c of e){let u=typeof c.method=="string"?c.method:"OTHER";i.methodCounts[u]=(i.methodCounts[u]??0)+1;let p=typeof c.url=="string"?c.url:null;p&&l.size<Ge&&l.add(jt(p));let g=typeof c.responseStatusCode=="number"?c.responseStatusCode:typeof c.statusCode=="number"?c.statusCode:null,f=g!==null&&Number.isFinite(g)?g:null;i.statusRanges[Os(f)]++;let m=typeof c.responseTimeMs=="number"?c.responseTimeMs:typeof c.durationMs=="number"?c.durationMs:null;m!==null&&Number.isFinite(m)&&i.responseTimes.length<Hs&&i.responseTimes.push(m);}i.apiUrls=Array.from(l);}for(let l of r)l.status==="passed"?i.passedAssertions++:i.failedAssertions++;let d=new Set;for(let l of n)l.url&&d.size<Ge&&d.add(l.url);return i.navUrls=Array.from(d),o&&qs(o,i.actionCategories),i}function id(){return {apiUrlSet:new Set,methodCounts:{},statusRanges:{"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},responseTimes:[],passedAssertions:0,failedAssertions:0,navUrlSet:new Set,actionCategoryCounts:{},volApiCalls:0,volAssertions:0,volNavigations:0,volNetworkRequests:0,volConsoleLogs:0,volActionSteps:0}}function od(t){return process.env.BROWSERSTACK_USERNAME?"BrowserStack":t?{"github-actions":"GitHub Actions","gitlab-ci":"GitLab CI",jenkins:"Jenkins",circleci:"CircleCI","bitbucket-pipelines":"Bitbucket Pipelines"}[t.provider]??"CI":"Local"}function ld(){let t=platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function dd(t){let e=t.parent?.project?.()?.use;if(!e)return;let{browserName:r,channel:n}=e;if(n){let a=n.toLowerCase();return a==="chrome"||a==="chrome-stable"?"Chrome":a.startsWith("chrome-beta")?"Chrome Beta":a.startsWith("chrome-dev")?"Chrome Dev":a.startsWith("chrome-canary")?"Chrome Canary":a==="msedge"||a==="msedge-stable"?"Microsoft Edge":a.startsWith("msedge-beta")?"Edge Beta":a.startsWith("msedge-dev")?"Edge Dev":a.startsWith("msedge-canary")?"Edge Canary":n}if(r){let a=r.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":r}let s=e.defaultBrowserType;if(s){let a=s.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":s}}function cd(t,e,r){let n=r.parent?.project?.(),s="unknown";n!==void 0&&(n.use.isMobile===true?s="mobile":s="e2e");let a=["e2e","api","unit","mobile"];for(let d of a)if(t.some(l=>l===`@${d}`||l===d))return d;let o=e.replace(/\\/g,"/"),i=["e2e","api","unit"];for(let d of i)if(o.includes(`/${d}/`))return d;return s}var ud="__testrelic_api_config";function pd(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var Ke=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.navigationsCaptured=false;this.memoryPressureWarned=false;this.testCount=0;this.cloudClient=null;this.cloudRunId=null;this.runTimestamp="";this.updatingSnapshots=false;this.cloudReceipt=ke;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,visualChecks:0,visualFailures:0,visualDomChanges:0};this.streamingTestAgg=new Map;this.config=Hr(e),this.apiConfig=qr(e);}upsertAggContribution(e,r){let n=this.streamingTestAgg.get(e);(!n||r.retryIndex>n.retryIndex)&&this.streamingTestAgg.set(e,r);}async onBegin(e,r){try{this.rootDir=e.rootDir;let n=e.updateSnapshots;if(this.updatingSnapshots=n==="all"||n==="changed",this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??randomUUID(),this.config.reportMode==="auto"){let i=r.allTests().length;this.activeReportMode=i>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let s=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${s} tests)
4299
+ `),this.activeReportMode==="streaming"){let i=dirname(this.config.outputPath);this.streamingWriter=new he(i);let d=()=>{if(this.streamingWriter){try{this.streamingWriter.writeIndex(this.testIndex);let l={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(),cloudUpload:this.cloudReceipt};this.streamingWriter.writeSummary(l);}catch{}this.streamingWriter.dispose();}try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let l=this.cloudClient.getAccessToken();l&&nr(this.cloudClient.getEndpoint(),l,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",d),process.on("SIGINT",d);}if(this.config.includeArtifacts){let i=dirname(this.config.outputPath);this.runTimestamp=Cn(join(i,"artifacts"));try{Jn(join(i,"artifacts"));}catch{}}let a=V();this.detectedOs=ld(),this.detectedSource=od(a);let o=await Q(async()=>(this.cloudClient=new Ue(this.config.cloud),await this.cloudClient.initialize(),Ms(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource)),Xn,"Cloud initialization");if(this.cloudRunId=o??null,o===void 0&&this.cloudClient?.switchToLocalMode("init_error"),this.cloudReceipt=Ps(this.cloudClient,this.config.cloud?.uploadStrategy,this.cloudRunId),this.activeReportMode!=="streaming"){let i=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let d=this.cloudClient.getAccessToken();d&&nr(this.cloudClient.getEndpoint(),d,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",i),process.on("SIGINT",i);}}catch{}}onTestBegin(e,r){try{e.annotations.push({type:ud,description:pd(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=hr(n.status);let o=n.startTime.toISOString(),i=new Date(n.startTime.getTime()+n.duration).toISOString(),d=e.tags?[...e.tags]:e.annotations.filter(I=>I.type==="tag").map(I=>I.description??""),l=_s(n.attachments,e.annotations,e.title,a==="skipped");(l.navigations.length>0||l.networkRequestsCount>0||l.apiCallsCount>0)&&(this.fixtureDataReceived=!0),l.navigations.length>0&&(this.navigationsCaptured=!0),!this.config.captureNavigation&&l.navigations.length>0&&(l={...l,navigations:[]});let c=null;if(a==="failed"||a==="flaky"){let M=(a==="flaky"?e.results.find(N=>N.status!=="passed")?.errors??[]:n.errors)[0];if(M){let N=zr(this.config.redactPatterns),j=M.location?.file??null,E=l.apiAssertions.find(aa=>aa.status==="failed")?.location??null,re=E!==null&&(j===null||resolve(j)!==resolve(e.location.file)),Sr=re?E.file:j,Qe=re?E.line:M.location?.line??null,fe=null;this.config.includeCodeSnippets&&Qe!==null&&Sr&&(fe=Ur(Sr,Qe,this.config.codeContextLines),fe&&(fe=N(fe))),c={message:N(se(M.message??"Unknown error")),line:Qe,code:fe,stack:this.config.includeStackTrace&&M.stack?N(se(M.stack)):null};}}let u=e.titlePath().filter(Boolean),p=relative(this.rootDir||".",e.location.file).replace(/\\/g,"/"),g=rd(u),f=u.join(" > "),m=p,h=td(m,g,f),v=cd(d,m,e),y=v!=="mobile"&&l.apiCallsCount>0?"api":v,b=s==="flaky",k=nd(e.results),A=hr(e.expectedStatus),P=hr(n.status),T=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let I=dirname(this.config.outputPath),M=u[u.length-1]??e.title;T=Sn(n.attachments,M,n.retry,I,this.runTimestamp||void 0,h);}let x=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments)try{let I=qn(n.attachments,{updatingSnapshots:this.updatingSnapshots,failureMessage:n.errors.map(M=>M.message??"").join(`
4300
+ `)});if(I.length>0){let M=dirname(this.config.outputPath),N=u[u.length-1]??e.title;x=Rn(I,N,n.retry,M,this.runTimestamp||void 0,h);}}catch{}let S=this.config.includeActionSteps&&n.steps?ns(n.steps,n.startTime):null,w=dd(e),C={titlePath:u,title:f,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:d,failure:c,specFile:p,navigations:l.navigations,testId:h,filePath:m,suiteName:g,testType:y,isFlaky:b,retryStatus:k,expectedStatus:A,actualStatus:P,artifacts:T,visual:x,apiAssertions:l.apiAssertions,actions:S,networkRequestsFile:l.networkRequestsFile,networkRequestsCount:l.networkRequestsCount,consoleLogsFile:l.consoleLogsFile,consoleLogsCount:l.consoleLogsCount,apiCallsFile:l.apiCallsFile,apiCallsCount:l.apiCallsCount,apiStatusMix:l.apiStatusMix,browser:w,os:this.detectedOs||void 0,source:this.detectedSource||void 0},_=l.consoleLogsFile&&l.consoleLogsCount>0?Y(l.consoleLogsFile):void 0,L=l.networkRequestsFile&&l.networkRequestsCount>0?Y(l.networkRequestsFile):void 0,z=l.apiCallsFile&&l.apiCallsCount>0?Y(l.apiCallsFile):void 0,ce=z?Qt(z):void 0,ue=!L&&z?er(z):void 0,pe=l.apiAssertions&&l.apiAssertions.length>0?tr(l.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:h,title:f,status:a,duration:n.duration,suiteName:g,filePath:m,testType:y,isFlaky:b,startedAt:o,completedAt:i,tags:d,failure:c,retry:n.retry,retryCount:e.results.length-1,retryStatus:k,browser:w,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...S&&S.length>0?{actions:S}:{},...l.navigations&&l.navigations.length>0?{navigations:l.navigations}:{},..._?{consoleLogs:_}:{},...L?{networkRequests:L}:ue?{networkRequests:ue}:{},...ce?{apiCalls:ce}:{},...pe?{protocolAssertions:pe}:{},...x&&x.length>0?{visual:x}:{}});try{let I=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(I==="realtime"||I==="both")){let M=this.cloudClient.getAccessToken();M&&vs(this.cloudClient.getEndpoint(),M,this.cloudRunId,this.buildCloudTestPayload(C));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let I=et(m,u,e.id??"",n.retry),M=n.retry===e.results.length-1,N={id:I,navigations:l.navigations,apiAssertions:l.apiAssertions,actions:S??[],artifacts:T,visual:x,failureDiagnostic:c,hasNetworkFile:l.networkRequestsFile!==null,networkRequestsCount:l.networkRequestsCount,hasConsoleFile:l.consoleLogsFile!==null,consoleLogsCount:l.consoleLogsCount,hasApiCallsFile:l.apiCallsFile!==null,apiCallsCount:l.apiCallsCount,startedAt:o};this.streamingWriter.writeTestDetail(I,N,{networkRequestsFile:l.networkRequestsFile,consoleLogsFile:l.consoleLogsFile,apiCallsFile:l.apiCallsFile});let j={id:I,title:u[u.length-1]??e.title,titlePath:u,filePath:m,status:a,duration:n.duration,project:u[1]??"",retryIndex:n.retry,tags:d,hasNetworkData:l.networkRequestsCount>0,hasConsoleData:l.consoleLogsCount>0,hasArtifacts:T!==null,hasActionSteps:(S?.length??0)>0,visualCount:x?.length??0,visualFailedCount:x?.filter(E=>E.status==="failed").length??0,domChangeCount:x?.reduce((E,re)=>E+(re.domChangeCount??0),0)??0,...(()=>{let E=x?.find(re=>re.diff);return E?.diff?{visualDiffPath:E.diff}:{}})(),errorMessage:ed(c?.message),networkCount:l.networkRequestsCount,consoleCount:l.consoleLogsCount,actionCount:S?.length??0,testType:y,apiCallCount:l.apiCallsCount,...l.apiStatusMix?{apiStatusMix:l.apiStatusMix}:{},assertionsPassed:We(l.apiAssertions,"passed"),assertionsFailed:We(l.apiAssertions,"failed"),...(()=>{let E=Ds(l.apiAssertions);return E?{firstFailedAssertion:E}:{}})(),isRetry:!M,retryGroupKey:tt(m,u,e.id??"")};if(this.testIndex.push(j),M)switch(this.summaryCounters.total++,a){case "passed":this.summaryCounters.passed++;break;case "failed":this.summaryCounters.failed++;break;case "flaky":this.summaryCounters.flaky++;break;case "skipped":this.summaryCounters.skipped++;break;case "timedout":this.summaryCounters.timedOut++;break;default:this.summaryCounters.interrupted++;break}this.upsertAggContribution(`${m}::${u.join(" > ")}`,Bs(n.retry,z,l.apiAssertions,l.navigations,l.networkRequestsCount,l.consoleLogsCount,S)),(T||x)&&this.pendingArtifactEntries.push({testId:h,artifacts:T??{},visual:x,outputDir:dirname(this.config.outputPath)}),C.actions=null,C.apiAssertions=null,C.navigations=[],C.artifacts=null,C.failure=null,C.networkRequestsFile=null,C.consoleLogsFile=null,C.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(C),this.testCount++,this.checkMemoryPressure();}catch{}}async onEnd(e){try{let r=new Date().toISOString(),n=new Date(this.startedAt).getTime(),a=new Date(r).getTime()-n,o=this.activeReportMode==="streaming"?this.testIndex.some(d=>d.status!=="skipped"):this.collectedTests.some(d=>d.status!=="skipped");!this.fixtureDataReceived&&o&&process.stderr.write(`
4301
4301
  \u26A0 TestRelic: No fixture data received from any test.
4302
4302
  To enable network logs, video sync, and Test Navigation tracking, import the TestRelic fixture:
4303
4303
  import { test, expect } from '@testrelic/playwright-analytics/fixture';
@@ -4306,18 +4306,18 @@ ${s}
4306
4306
 
4307
4307
  `),this.config.captureNavigation?this.fixtureDataReceived&&!this.navigationsCaptured&&o&&process.stderr.write(`[testrelic] Test Navigation: 0 navigation events captured this run. Navigation is recorded automatically on page.goto()/clicks; if you expected a navigation graph, ensure your tests drive page navigations (and use the '@testrelic/playwright-analytics/fixture' import).
4308
4308
  `):process.stderr.write(`[testrelic] Test Navigation capture is disabled (captureNavigation: false). Remove the option or set it to true to capture the navigation graph.
4309
- `),await Q(()=>kn(),zt,"Artifact flush");let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let d=dirname(this.config.outputPath);i=Wn(d,this.runTimestamp);let l=join(d,"artifact-manifest.json"),c=JSON.stringify(i),u=l+".tmp";writeFileSync(u,c,"utf-8"),renameSync(u,l);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await Q(()=>this.finalizeStreamingReport(r,a,e,i),Ht,"Report finalization");else {let d=this.buildTimeline(),l=new Map;for(let p of this.collectedTests){let g=l.get(p.testId);(!g||p.retry>g.retry)&&l.set(p.testId,p);}let c=Array.from(l.values()),u=rs(c,d.length),f={schemaVersion:Ce,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:a,summary:u,ci:V(),metadata:this.config.metadata,timeline:d,shardRunIds:null};if(this.writeReport(f),await Q(()=>Mt(f,this.config,i),zt,"HTML report write"),Vt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let p=this.collectArtifactEntries(),g=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let m=await Q(()=>pr(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,f,r,a,u,p,g),Ht,"Cloud upload");this.cloudReceipt=fr(this.cloudReceipt,m,this.testRunId);}}}catch{}finally{await this.disposeCloudClient();}}async disposeCloudClient(){let e=this.cloudClient;e&&(this.cloudClient=null,await Q(()=>e.dispose(),Zn,"Cloud client shutdown"));}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let e=dirname(this.config.outputPath),r=[];for(let n of this.collectedTests)(n.artifacts||n.visual)&&r.push({testId:n.testId,artifacts:n.artifacts??{},visual:n.visual,outputDir:e});return r}async finalizeStreamingReport(e,r,n,s){if(!this.streamingWriter)return;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,visualChecks:0,visualFailures:0,visualDomChanges:0};let a=new Map,o=new Map;for(let h of this.testIndex){let v=`${h.filePath}::${h.titlePath.join(" > ")}`,y=a.get(v);(y===void 0||h.retryIndex>y)&&a.set(v,h.retryIndex);}let i=0;for(let h of this.testIndex){let v=`${h.filePath}::${h.titlePath.join(" > ")}`,y=a.get(v);if(h.isRetry=h.retryIndex<y,h.isRetry)continue;switch(i++,this.summaryCounters.total++,h.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}this.summaryCounters.visualChecks+=h.visualCount??0,this.summaryCounters.visualFailures+=h.visualFailedCount??0,this.summaryCounters.visualDomChanges+=h.domChangeCount??0;let b=o.get(h.filePath);switch(b||(b={filePath:h.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},o.set(h.filePath,b)),b.total++,h.status){case "passed":b.passed++;break;case "failed":b.failed++;break;case "flaky":b.flaky++;break;case "skipped":b.skipped++;break;case "timedout":b.timedOut++;break}}let d=Array.from(o.values()),l=sd();for(let h of this.streamingTestAgg.values()){l.volApiCalls+=h.apiCalls,l.volAssertions+=h.assertions,l.volNavigations+=h.navigations,l.volNetworkRequests+=h.networkRequests,l.volConsoleLogs+=h.consoleLogs,l.volActionSteps+=h.actionSteps;for(let v in h.methodCounts)l.methodCounts[v]=(l.methodCounts[v]??0)+h.methodCounts[v];l.statusRanges["2xx"]+=h.statusRanges["2xx"],l.statusRanges["3xx"]+=h.statusRanges["3xx"],l.statusRanges["4xx"]+=h.statusRanges["4xx"],l.statusRanges["5xx"]+=h.statusRanges["5xx"],l.statusRanges.error+=h.statusRanges.error,l.passedAssertions+=h.passedAssertions,l.failedAssertions+=h.failedAssertions;for(let v in h.actionCategories)l.actionCategoryCounts[v]=(l.actionCategoryCounts[v]??0)+h.actionCategories[v];for(let v of h.apiUrls){if(l.apiUrlSet.size>=Ge)break;l.apiUrlSet.add(v);}for(let v of h.navUrls){if(l.navUrlSet.size>=Ge)break;l.navUrlSet.add(v);}for(let v of h.responseTimes){if(l.responseTimes.length>=Us)break;l.responseTimes.push(v);}}this.summaryCounters.totalApiCalls=l.volApiCalls,this.summaryCounters.totalAssertions=l.volAssertions,this.summaryCounters.totalNavigations=l.volNavigations,this.summaryCounters.totalNetworkRequests=l.volNetworkRequests,this.summaryCounters.totalConsoleLogs=l.volConsoleLogs,this.summaryCounters.totalActionSteps=l.volActionSteps,this.streamingWriter.writeIndex(this.testIndex),this.streamingWriter.writeCompactIndex(this.testIndex);let c={reporterTotal:this.summaryCounters.total,indexTotal:i,playwrightStatus:n.status,isValid:this.summaryCounters.total===i};c.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${c.reporterTotal}, index: ${c.indexTotal}
4310
- `);let u={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:l.apiUrlSet.size,apiCallsByMethod:{...l.methodCounts},apiCallsByStatusRange:{"2xx":l.statusRanges["2xx"],"3xx":l.statusRanges["3xx"],"4xx":l.statusRanges["4xx"],"5xx":l.statusRanges["5xx"],error:l.statusRanges.error},apiResponseTime:nd(l.responseTimes),totalAssertions:this.summaryCounters.totalAssertions,passedAssertions:l.passedAssertions,failedAssertions:l.failedAssertions,totalNavigations:this.summaryCounters.totalNavigations,uniqueNavigationUrls:l.navUrlSet.size,totalTimelineSteps:i,totalActionSteps:this.summaryCounters.totalActionSteps,actionStepsByCategory:{...l.actionCategoryCounts},visualChecks:this.summaryCounters.visualChecks,visualFailures:this.summaryCounters.visualFailures,visualDomChanges:this.summaryCounters.visualDomChanges},f={testRunId:this.testRunId,startedAt:this.startedAt,completedAt:e,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:d,enrichedSummary:u,validation:c,writeErrors:this.streamingWriter.getWriteErrors(),cloudUpload:this.cloudReceipt};this.streamingWriter.writeSummary(f);let p={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(p),await Mt(this.buildStreamingReport(f,u,e,r),this.config,s),Vt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let g=this.streamingWriter.getReportDir();process.stderr.write(`[testrelic] Streaming report written to ${g}
4309
+ `),await Q(()=>kn(),zt,"Artifact flush");let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let d=dirname(this.config.outputPath);i=Wn(d,this.runTimestamp);let l=join(d,"artifact-manifest.json"),c=JSON.stringify(i),u=l+".tmp";writeFileSync(u,c,"utf-8"),renameSync(u,l);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await Q(()=>this.finalizeStreamingReport(r,a,e,i),Ut,"Report finalization");else {let d=this.buildTimeline(),l=new Map;for(let g of this.collectedTests){let f=l.get(g.testId);(!f||g.retry>f.retry)&&l.set(g.testId,g);}let c=Array.from(l.values()),u=rs(c,d.length),p={schemaVersion:Ce,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:a,summary:u,ci:V(),metadata:this.config.metadata,timeline:d,shardRunIds:null};if(this.writeReport(p),await Q(()=>Mt(p,this.config,i),zt,"HTML report write"),Vt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let g=this.collectArtifactEntries(),f=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let m=await Q(()=>pr(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,p,r,a,u,g,f),Ut,"Cloud upload");this.cloudReceipt=fr(this.cloudReceipt,m,this.testRunId);}}}catch{}finally{await this.disposeCloudClient();}}async disposeCloudClient(){let e=this.cloudClient;e&&(this.cloudClient=null,await Q(()=>e.dispose(),Zn,"Cloud client shutdown"));}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let e=dirname(this.config.outputPath),r=[];for(let n of this.collectedTests)(n.artifacts||n.visual)&&r.push({testId:n.testId,artifacts:n.artifacts??{},visual:n.visual,outputDir:e});return r}async finalizeStreamingReport(e,r,n,s){if(!this.streamingWriter)return;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,visualChecks:0,visualFailures:0,visualDomChanges:0};let a=new Map,o=new Map;for(let h of this.testIndex){let v=`${h.filePath}::${h.titlePath.join(" > ")}`,y=a.get(v);(y===void 0||h.retryIndex>y)&&a.set(v,h.retryIndex);}let i=0;for(let h of this.testIndex){let v=`${h.filePath}::${h.titlePath.join(" > ")}`,y=a.get(v);if(h.isRetry=h.retryIndex<y,h.isRetry)continue;switch(i++,this.summaryCounters.total++,h.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}this.summaryCounters.visualChecks+=h.visualCount??0,this.summaryCounters.visualFailures+=h.visualFailedCount??0,this.summaryCounters.visualDomChanges+=h.domChangeCount??0;let b=o.get(h.filePath);switch(b||(b={filePath:h.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},o.set(h.filePath,b)),b.total++,h.status){case "passed":b.passed++;break;case "failed":b.failed++;break;case "flaky":b.flaky++;break;case "skipped":b.skipped++;break;case "timedout":b.timedOut++;break}}let d=Array.from(o.values()),l=id();for(let h of this.streamingTestAgg.values()){l.volApiCalls+=h.apiCalls,l.volAssertions+=h.assertions,l.volNavigations+=h.navigations,l.volNetworkRequests+=h.networkRequests,l.volConsoleLogs+=h.consoleLogs,l.volActionSteps+=h.actionSteps;for(let v in h.methodCounts)l.methodCounts[v]=(l.methodCounts[v]??0)+h.methodCounts[v];l.statusRanges["2xx"]+=h.statusRanges["2xx"],l.statusRanges["3xx"]+=h.statusRanges["3xx"],l.statusRanges["4xx"]+=h.statusRanges["4xx"],l.statusRanges["5xx"]+=h.statusRanges["5xx"],l.statusRanges.error+=h.statusRanges.error,l.passedAssertions+=h.passedAssertions,l.failedAssertions+=h.failedAssertions;for(let v in h.actionCategories)l.actionCategoryCounts[v]=(l.actionCategoryCounts[v]??0)+h.actionCategories[v];for(let v of h.apiUrls){if(l.apiUrlSet.size>=Ge)break;l.apiUrlSet.add(v);}for(let v of h.navUrls){if(l.navUrlSet.size>=Ge)break;l.navUrlSet.add(v);}for(let v of h.responseTimes){if(l.responseTimes.length>=Hs)break;l.responseTimes.push(v);}}this.summaryCounters.totalApiCalls=l.volApiCalls,this.summaryCounters.totalAssertions=l.volAssertions,this.summaryCounters.totalNavigations=l.volNavigations,this.summaryCounters.totalNetworkRequests=l.volNetworkRequests,this.summaryCounters.totalConsoleLogs=l.volConsoleLogs,this.summaryCounters.totalActionSteps=l.volActionSteps,this.streamingWriter.writeIndex(this.testIndex),this.streamingWriter.writeCompactIndex(this.testIndex);let c={reporterTotal:this.summaryCounters.total,indexTotal:i,playwrightStatus:n.status,isValid:this.summaryCounters.total===i};c.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${c.reporterTotal}, index: ${c.indexTotal}
4310
+ `);let u={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:l.apiUrlSet.size,apiCallsByMethod:{...l.methodCounts},apiCallsByStatusRange:{"2xx":l.statusRanges["2xx"],"3xx":l.statusRanges["3xx"],"4xx":l.statusRanges["4xx"],"5xx":l.statusRanges["5xx"],error:l.statusRanges.error},apiResponseTime:ad(l.responseTimes),totalAssertions:this.summaryCounters.totalAssertions,passedAssertions:l.passedAssertions,failedAssertions:l.failedAssertions,totalNavigations:this.summaryCounters.totalNavigations,uniqueNavigationUrls:l.navUrlSet.size,totalTimelineSteps:i,totalActionSteps:this.summaryCounters.totalActionSteps,actionStepsByCategory:{...l.actionCategoryCounts},visualChecks:this.summaryCounters.visualChecks,visualFailures:this.summaryCounters.visualFailures,visualDomChanges:this.summaryCounters.visualDomChanges},p={testRunId:this.testRunId,startedAt:this.startedAt,completedAt:e,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:d,enrichedSummary:u,validation:c,writeErrors:this.streamingWriter.getWriteErrors(),cloudUpload:this.cloudReceipt};this.streamingWriter.writeSummary(p);let g={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(g),await Mt(this.buildStreamingReport(p,u,e,r),this.config,s),Vt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let f=this.streamingWriter.getReportDir();process.stderr.write(`[testrelic] Streaming report written to ${f}
4311
4311
  [testrelic] ${this.testIndex.length} test detail files on disk
4312
- [testrelic] View report: npx testrelic serve ${g}
4312
+ [testrelic] View report: npx testrelic serve ${f}
4313
4313
  `),this.streamingWriter.getWriteErrors().length>0&&process.stderr.write(`[testrelic] WARNING: ${this.streamingWriter.getWriteErrors().length} write error(s) during streaming
4314
- `);let m=this.streamingWriter;try{if(this.cloudClient){let h=this.buildStreamingReport(f,u,e,r),v=this.collectArtifactEntries(),y=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let b=await pr(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,h,e,r,u,v,y);this.cloudReceipt=fr(this.cloudReceipt,b,this.testRunId);let k={...f,cloudUpload:this.cloudReceipt};try{m.writeSummary(k);}catch{}}}finally{m.dispose();}this.testIndex.length=0,this.collectedTests.length=0,this.pendingArtifactEntries.length=0,this.cloudTestsBuffer.length=0,this.streamingWriter=null,this.cloudClient=null;}buildStreamingReport(e,r,n,s){return {schemaVersion:Ce,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:n,totalDuration:s,summary:r,ci:V(),metadata:this.config.metadata,timeline:[],shardRunIds:null}}printsToStdio(){return false}checkMemoryPressure(){try{let e=process.memoryUsage(),r=e.heapUsed/1024/1024;if(r<200)return;let n=e.heapUsed/e.heapTotal;n>.9&&this.activeReportMode==="embedded"?(process.stderr.write(`[testrelic] WARNING: High memory (${Math.round(r)} MB). Auto-switching to streaming mode.
4314
+ `);let m=this.streamingWriter;try{if(this.cloudClient){let h=this.buildStreamingReport(p,u,e,r),v=this.collectArtifactEntries(),y=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let b=await pr(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,h,e,r,u,v,y);this.cloudReceipt=fr(this.cloudReceipt,b,this.testRunId);let k={...p,cloudUpload:this.cloudReceipt};try{m.writeSummary(k);}catch{}}}finally{m.dispose();}this.testIndex.length=0,this.collectedTests.length=0,this.pendingArtifactEntries.length=0,this.cloudTestsBuffer.length=0,this.streamingWriter=null,this.cloudClient=null;}buildStreamingReport(e,r,n,s){return {schemaVersion:Ce,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:n,totalDuration:s,summary:r,ci:V(),metadata:this.config.metadata,timeline:[],shardRunIds:null}}printsToStdio(){return false}checkMemoryPressure(){try{let e=process.memoryUsage(),r=e.heapUsed/1024/1024;if(r<200)return;let n=e.heapUsed/e.heapTotal;n>.9&&this.activeReportMode==="embedded"?(process.stderr.write(`[testrelic] WARNING: High memory (${Math.round(r)} MB). Auto-switching to streaming mode.
4315
4315
  `),this.switchToStreamingMode()):n>.8&&r>=500&&!this.memoryPressureWarned&&(this.memoryPressureWarned=!0,process.stderr.write(`[testrelic] WARNING: Memory pressure detected (${Math.round(r)} MB used).
4316
4316
  `));}catch{}}switchToStreamingMode(){try{if(this.activeReportMode==="streaming")return;this.activeReportMode="streaming";let e=dirname(this.config.outputPath);this.streamingWriter=new he(e);for(let r of this.collectedTests){let n=et(r.filePath,r.titlePath,r.testId,r.retry),s=r.apiCallsFile&&r.apiCallsCount>0?Y(r.apiCallsFile):void 0,a={id:n,navigations:r.navigations??[],apiAssertions:r.apiAssertions??[],actions:r.actions??[],artifacts:r.artifacts,failureDiagnostic:r.failure,hasNetworkFile:r.networkRequestsFile!==null,networkRequestsCount:r.networkRequestsCount,hasConsoleFile:r.consoleLogsFile!==null,consoleLogsCount:r.consoleLogsCount,hasApiCallsFile:r.apiCallsFile!==null,apiCallsCount:r.apiCallsCount,startedAt:r.startedAt};this.streamingWriter.writeTestDetail(n,a,{networkRequestsFile:r.networkRequestsFile,consoleLogsFile:r.consoleLogsFile,apiCallsFile:r.apiCallsFile});let o={id:n,title:r.titlePath[r.titlePath.length-1]??r.title,titlePath:r.titlePath,filePath:r.filePath,status:r.status,duration:r.duration,project:r.titlePath[1]??"",retryIndex:r.retry,tags:r.tags,hasNetworkData:r.networkRequestsCount>0,hasConsoleData:r.consoleLogsCount>0,hasArtifacts:r.artifacts!==null,hasActionSteps:(r.actions?.length??0)>0,errorMessage:r.failure?.message?.split(`
4317
- `)[0]??null,networkCount:r.networkRequestsCount,consoleCount:r.consoleLogsCount,actionCount:r.actions?.length??0,testType:r.testType,apiCallCount:r.apiCallsCount,...r.apiStatusMix?{apiStatusMix:r.apiStatusMix}:s?{apiStatusMix:rd(s)}:{},assertionsPassed:We(r.apiAssertions,"passed"),assertionsFailed:We(r.apiAssertions,"failed"),...(()=>{let i=Ds(r.apiAssertions);return i?{firstFailedAssertion:i}:{}})(),isRetry:!1,retryGroupKey:tt(r.filePath,r.titlePath,r.testId)};switch(this.testIndex.push(o),this.summaryCounters.total++,r.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}this.upsertAggContribution(`${r.filePath}::${r.titlePath.join(" > ")}`,Bs(r.retry,s,r.apiAssertions??[],r.navigations??[],r.networkRequestsCount,r.consoleLogsCount,r.actions??null));}this.collectedTests.length=0;}catch{}}buildTimeline(){let e=this.collectedTests.map(r=>({titlePath:r.titlePath,title:r.title,status:r.status,duration:r.duration,startedAt:r.startedAt,completedAt:r.completedAt,retryCount:r.retryCount,retry:r.retry,tags:r.tags,failure:r.failure,specFile:r.specFile,navigations:r.navigations,apiCalls:null,apiAssertions:r.apiAssertions,testId:r.testId,filePath:r.filePath,suiteName:r.suiteName,testType:r.testType,isFlaky:r.isFlaky,retryStatus:r.retryStatus,expectedStatus:r.expectedStatus,actualStatus:r.actualStatus,artifacts:r.artifacts,networkRequests:null,actions:r.actions,consoleLogs:null}));return ts(e,{navigationTypes:this.config.navigationTypes})}readJsonlFile(e){if(!e)return null;let r=Y(e);return r.length>0?r:null}toTestResult(e,r){let n=null,s=null,a=null;return r?.loadFiles&&(n=this.readJsonlFile(e.networkRequestsFile),s=this.readJsonlFile(e.consoleLogsFile),a=this.readJsonlFile(e.apiCallsFile)),{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,visual:e.visual,networkRequests:n,apiCalls:a,apiAssertions:e.apiAssertions,actions:e.actions??null,consoleLogs:s}}buildCloudTestPayload(e){let r={title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retry:e.retry,retryCount:e.retryCount,retryStatus:e.retryStatus,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,visual:e.visual??[],actions:e.actions??[],navigations:e.navigations??[],steps:e.actions??[],browser:e.browser,os:e.os,source:e.source};if(e.apiAssertions&&e.apiAssertions.length>0&&(r.protocolAssertions=tr(e.apiAssertions)),e.consoleLogsFile&&(r.consoleLogs=Y(e.consoleLogsFile)),e.networkRequestsFile&&(r.networkRequests=Y(e.networkRequestsFile)),e.apiCallsFile){let n=Y(e.apiCallsFile);r.apiCalls=Qt(n),(!r.networkRequests||r.networkRequests.length===0)&&(r.networkRequests=er(n));}return r}writeReport(e){try{let r=JSON.stringify(e),n=this.config.outputPath,s=dirname(n);mkdirSync(s,{recursive:!0});let a=n+".tmp";writeFileSync(a,r,"utf-8"),renameSync(a,n);}catch(r){process.stderr.write(`[testrelic] Failed to write report: ${r instanceof Error?r.message:String(r)}
4318
- `);}}};var hd=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function md(t){let e=t.toLowerCase();return hd.some(r=>e.includes(r))}var Je=class t{constructor(e,r){this.page=e;this.records=[];this.listeners=[];this.navCounters=[];this.pendingRequests=new Map;this.networkWriter=null;this.consoleWriter=null;this.pendingBodyReads=[];this.requestIdCounter=0;this.networkRequestCount=0;this.consoleLogCount=0;this.includeNetworkStats=r?.includeNetworkStats??true,this.origGoto=e.goto.bind(e),this.origGoBack=e.goBack.bind(e),this.origGoForward=e.goForward.bind(e),this.origReload=e.reload.bind(e);try{this.includeNetworkStats&&(this.networkWriter=new q("network")),this.consoleWriter=new q("console");}catch{}this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async finalizeCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[,e]of this.pendingRequests)this.networkWriter&&(this.networkWriter.append({url:e.url,method:e.method,resourceType:e.resourceType,statusCode:0,responseTimeMs:Date.now()-e.startTimeMs,startedAt:e.startedAt,requestHeaders:e.headers,requestBody:e.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:e.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.networkRequestCount++);this.pendingRequests.clear(),this.networkWriter?.close(),this.consoleWriter?.close();}static mapConsoleType(e){switch(e){case "log":return "log";case "warning":return "warn";case "error":return "error";case "info":return "info";case "debug":return "debug";default:return "log"}}async getFileData(){this.assembleNetworkStats();let e=this.records.map(r=>({url:r.url,navigationType:r.navigationType,timestamp:r.timestamp,domContentLoadedAt:r.domContentLoadedAt,networkIdleAt:r.networkIdleAt,networkStats:r.networkStats}));return this.includeNetworkStats?await this.finalizeCapturedRequests():this.consoleWriter?.close(),{navigations:e,networkRequestsFile:this.networkWriter?.getCount()?this.networkWriter.getPath():null,networkRequestsCount:this.networkWriter?.getCount()??0,consoleLogsFile:this.consoleWriter?.getCount()?this.consoleWriter.getPath():null,consoleLogsCount:this.consoleWriter?.getCount()??0}}async flushLegacyAnnotations(e){}dispose(){let e=t.asPatchable(this.page);e.goto=this.origGoto,e.goBack=this.origGoBack,e.goForward=this.origGoForward,e.reload=this.origReload;for(let{event:r,handler:n}of this.listeners)this.page.off(r,n);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.pendingBodyReads=[],this.networkWriter?.close(),this.consoleWriter?.close();}getRecords(){return this.assembleNetworkStats(),this.records}static asPatchable(e){return e}interceptMethods(){let e=this,r=this.page,n=t.asPatchable(r);n.goto=async function(s,a){return e.recordNavigation(s,"goto"),e.origGoto(s,a)},n.goBack=async function(s){let a=await e.origGoBack(s);return e.recordNavigation(r.url(),"back"),a},n.goForward=async function(s){let a=await e.origGoForward(s);return e.recordNavigation(r.url(),"forward"),a},n.reload=async function(s){return e.recordNavigation(r.url(),"refresh"),e.origReload(s)};}attachListeners(){let e=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",e),this.listeners.push({event:"domcontentloaded",handler:e});let r=s=>{try{let a=s;if(typeof a.parentFrame=="function"&&a.parentFrame()!==null)return;let o=a.url(),i=this.records[this.records.length-1];if(i&&Date.now()-new Date(i.timestamp).getTime()<50&&i.url===o)return;this.recordNavigation(o,"navigation");}catch{}};this.page.on("framenavigated",r),this.listeners.push({event:"framenavigated",handler:r});let n=s=>{try{let a=s,o=a.type(),i=a.text();if(o==="debug"&&i.startsWith("__testrelic_nav:")){try{let d=JSON.parse(i.slice(16));d.type&&d.url&&this.recordNavigation(d.url,d.type);}catch{}return}{let d=null;try{let c=a.location();c&&c.url&&(d=`${c.url}:${c.lineNumber}:${c.columnNumber}`);}catch{}let l=t.mapConsoleType(o);this.consoleWriter&&(this.consoleWriter.append({level:l,text:i,timestamp:new Date().toISOString(),location:d}),this.consoleLogCount++);}}catch{}};if(this.page.on("console",n),this.listeners.push({event:"console",handler:n}),this.includeNetworkStats){let s=i=>{let d=this.records.length-1,l=this.counterForNav(d);l&&l.totalRequests++;try{let c=i,u=String(this.requestIdCounter++),f=c.postData()??null,p={url:c.url(),method:c.method(),resourceType:this.mapResourceType(c.resourceType()),headers:c.headers(),postData:f,postDataTruncated:!1,startedAt:new Date().toISOString(),startTimeMs:Date.now(),navIndex:d};this.pendingRequests.set(u,p),i.__testrelic_id=u;}catch{}};this.page.on("request",s),this.listeners.push({event:"request",handler:s});let a=i=>{try{let d=i,l=d.request().__testrelic_id,c=l?this.pendingRequests.get(l):void 0,u=this.counterForNav(c?c.navIndex:this.records.length-1);if(u){let y=d.status();y>=400&&(u.failedRequests++,u.failedRequestUrls.push(y+" "+d.url()));let b=d.headers()["content-length"];b&&(u.totalBytes+=parseInt(b,10)||0);let k=d.request().resourceType(),A=this.mapResourceType(k);u.byType[A]++;}if(!l||!c)return;this.pendingRequests.delete(l);let f=Date.now()-c.startTimeMs,p=d.headers(),g=p["content-type"]??null,m=parseInt(p["content-length"]??"0",10)||0,h=g?!md(g):!1,v=(async()=>{let y=null;if(!h)try{y=(await d.body()).toString("utf-8");}catch{}let b={url:c.url,method:c.method,resourceType:c.resourceType,statusCode:d.status(),responseTimeMs:f,startedAt:c.startedAt,requestHeaders:c.headers,requestBody:c.postData,responseBody:y,responseHeaders:p,contentType:g,responseSize:m,requestBodyTruncated:c.postDataTruncated,responseBodyTruncated:!1,isBinary:h,error:null};this.networkWriter&&(this.networkWriter.append(b),this.networkRequestCount++);})();this.pendingBodyReads.push(v);}catch{}};this.page.on("response",a),this.listeners.push({event:"response",handler:a});let o=i=>{let d=i.__testrelic_id,l=d?this.pendingRequests.get(d):void 0,c=this.counterForNav(l?l.navIndex:this.records.length-1);if(c){c.failedRequests++;try{let u=i;c.failedRequestUrls.push("ERR "+u.url());}catch{}}try{let u=i;if(!d||!l)return;this.pendingRequests.delete(d);let f={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:0,responseTimeMs:Date.now()-l.startTimeMs,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:u.failure()?.errorText??"Unknown error"};this.networkWriter&&(this.networkWriter.append(f),this.networkRequestCount++);}catch{}};this.page.on("requestfailed",o),this.listeners.push({event:"requestfailed",handler:o});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let e=history.pushState.bind(history),r=history.replaceState.bind(history);history.pushState=function(...n){e(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...n){r(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(e,r){this.records.push({url:e,navigationType:r,timestamp:new Date().toISOString()}),this.includeNetworkStats&&this.navCounters.push(this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}counterForNav(e){return e>=0?this.navCounters[e]:void 0}assembleNetworkStats(){if(this.includeNetworkStats)for(let e=0;e<this.records.length;e++){let r=this.navCounters[e];r&&(this.records[e].networkStats={totalRequests:r.totalRequests,failedRequests:r.failedRequests,failedRequestUrls:[...r.failedRequestUrls],totalBytes:r.totalBytes,byType:{...r.byType}});}}mapResourceType(e){switch(e){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var yr=Symbol.for("__testrelic_call_id"),yd="__testrelic_api_assertions",te=new WeakMap,oe=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(e){this.assertions.push(e);}getAssertions(){return this.assertions}setCurrentCallId(e){this.currentCallId=e;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(e){this.assertions.length!==0&&e.annotations.push({type:yd,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}},Hs=new Map;function bd(t){let e=Hs.get(t);if(e)return e;try{let r=t.startsWith("file://")?fileURLToPath(t):t,s=readFileSync(r,"utf-8").split(`
4319
- `);return Hs.set(t,s),s}catch{return null}}var zs=(()=>{let t=new Error().stack;if(!t)return null;for(let e of t.split(`
4320
- `)){let r=e.match(/at\s+(?:.*?\s+\()?(.+?):\d+:\d+\)?$/);if(!r||r[1].startsWith("node:"))continue;let n=Math.max(r[1].lastIndexOf("/"),r[1].lastIndexOf("\\"));return n>0?r[1].slice(0,n+1):null}return null})();function xd(t){if(!t.startsWith("file:"))return t;try{return fileURLToPath(t)}catch{return t}}function wd(){let e=new Error().stack;if(!e)return null;let r=e.split(`
4321
- `);return js(r,true)??js(r,false)}function js(t,e){for(let r of t){if(e&&zs!==null&&r.includes(zs)||r.includes("node_modules")||r.includes("node:internal")||r.includes(" at new Error")||r.includes(" at captureAssertionLocation")||r.includes(" at findFrame")||r.includes(" at expectWrapper")||r.includes(" at wrappedMatcher"))continue;let n=r.match(/at\s+(?:.*?\s+\()?(.+?):(\d+):(\d+)\)?$/);if(n)return {file:xd(n[1]),line:parseInt(n[2],10),column:parseInt(n[3],10)}}return null}function kd(t,e){if(!t)return "custom";let r=t.toLowerCase();return r.includes(".status()")&&!r.includes(".statustext()")?r.includes(".ok()")?"statusOk":"status":r.includes(".ok()")?"statusOk":r.includes(".headers()")||r.includes(".headersarray()")?"header":r.includes("tomatchobject")||r.includes("toequal")?"bodyMatch":r.includes("tocontain")||r.includes("tostringcontaining")?"bodyContains":r.includes(".json()")||r.includes(".text()")?"bodyField":"custom"}function Cd(t,e,r){let n=function(i,...d){let l=t(),c=e();if(!l||!c)return r(i,...d);let u=null;if(i!=null&&typeof i=="object"){let m=i[yr];typeof m=="string"&&(u=m);}if(!u&&i!==null&&i!==void 0&&typeof i=="object"&&(u=te.get(i)??null),u||(u=c.getCallIdForValue(i)),u||(u=l.getCurrentCallId()),!u)return r(i,...d);let f=wd(),p;if(f){let m=bd(f.file);m&&f.line>0&&f.line<=m.length&&(p=m[f.line-1].trim());}let g=r(i,...d);return u?Gs(g,{tracker:l,callId:u,received:i,location:f??{file:"unknown",line:0},expression:p}):g},s=r,a=n;for(let o of Object.keys(s))a[o]=s[o];return n}var Vs=Symbol.for("testrelic.activeAssertionContext");function vr(){let t=globalThis,e=t[Vs];return e||(e={tracker:null,apiTracker:null},t[Vs]=e),e}function le(t,e){let r=vr();r.tracker=t,r.apiTracker=e;}function Ye(t){return Cd(()=>vr().tracker,()=>vr().apiTracker,t)}function Gs(t,e){return new Proxy(t,{get(r,n,s){let a=Reflect.get(r,n,s);return typeof a!="function"||typeof n=="symbol"?a:n==="not"?Gs(a,e):function(...i){let d=i[0],l="passed",c=e.received,u=null;try{let f=a.apply(this??r,i);return f&&typeof f=="object"&&typeof f.then=="function"?f.then(()=>{mr(e,n,d,c,"passed");},p=>{throw mr(e,n,d,c,"failed"),p}):f}catch(f){if(l="failed",u=f,f instanceof Error&&f.message){let p=f.message.match(/Received:\s*(.+)/);p&&(c=p[1]);}throw f}finally{(u!==null||l==="passed")&&mr(e,n,d,c,l);}}}})}function mr(t,e,r,n,s){let a=kd(t.expression,t.received),o={callId:t.callId,type:a,expected:$s(r),actual:$s(n),status:s,location:t.location,expression:t.expression};t.tracker.recordAssertion(o);}function $s(t){if(t==null)return t;if(typeof t=="string")return se(t);if(typeof t=="number"||typeof t=="boolean")return t;try{return JSON.stringify(t),t}catch{return String(t)}}var Ks="[REDACTED]";function xr(t,e){if(t===null||e.length===0)return t;let r=new Set(e.map(s=>s.toLowerCase())),n={};for(let s of Object.keys(t))Object.prototype.hasOwnProperty.call(t,s)&&(n[s]=r.has(s.toLowerCase())?Ks:t[s]);return n}function Xe(t,e){if(t===null||e.length===0)return t;let r;try{r=JSON.parse(t);}catch{return t}if(typeof r!="object"||r===null)return t;let n=new Set(e.map(a=>a.toLowerCase())),s=br(r,n);return JSON.stringify(s)}function br(t,e){if(Array.isArray(t))return t.map(r=>br(r,e));if(typeof t=="object"&&t!==null){let r={};for(let n of Object.keys(t)){if(!Object.prototype.hasOwnProperty.call(t,n))continue;let s=t[n];e.has(n.toLowerCase())?r[n]=Ks:r[n]=br(s,e);}return r}return t}var Td=new Set(["access_token","api_key","token","sig"]);function wr(t){if(!t)return t;let e;try{e=new URL(t);}catch{return t}let r=false;for(let n of [...e.searchParams.keys()])Td.has(n.toLowerCase())&&(e.searchParams.delete(n),r=true);return r?e.toString():t}function Ys(t,e,r){if(r.length>0){for(let n of r)if(Js(t,n))return false}if(e.length>0){for(let n of e)if(Js(t,n))return true;return false}return true}function Js(t,e){try{return e instanceof RegExp?e.test(t):Sd(e).test(t)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(e)}`),false}}function Sd(t){let e="",r=0;for(;r<t.length;){let n=t[r];n==="*"&&t[r+1]==="*"?(e+=".*",r+=2,t[r]==="/"&&r++):n==="*"?(e+="[^/]*",r++):n==="?"?(e+="[^/]",r++):".+^${}()|[]\\".includes(n)?(e+="\\"+n,r++):(e+=n,r++);}return new RegExp(e)}var Rd=["get","post","put","patch","delete","head","fetch"],Ad=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function _d(t){let e=t.toLowerCase();return Ad.some(r=>e.includes(r))}function Id(t){if(!t)return null;if(t.data!==void 0&&t.data!==null){let e=t.data;return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("base64"):JSON.stringify(e)}if(t.form!==void 0&&t.form!==null)return JSON.stringify(t.form);if(t.multipart!==void 0&&t.multipart!==null){let e=t.multipart,r={};for(let[n,s]of Object.entries(e))typeof s=="string"||typeof s=="number"||typeof s=="boolean"?r[n]=String(s):s&&typeof s=="object"&&"name"in s?r[n]=`[file: ${s.name}]`:r[n]="[binary]";return JSON.stringify(r)}return null}function Xs(t){return t?"\u2022\u2022\u2022\u2022":""}function Md(t){if(!t)return [];let e;for(let[n,s]of Object.entries(t))if(n.toLowerCase()==="cookie"){e=s;break}if(!e)return [];let r=[];for(let n of e.split(";")){let s=n.trim();if(!s)continue;let a=s.indexOf("="),o=a===-1?s:s.slice(0,a).trim(),i=a===-1?"":s.slice(a+1).trim();o&&r.push({name:o,value:Xs(i)});}return r}function Ed(t){let e=[];for(let r of t)for(let n of r.split(/,(?=\s*[A-Za-z0-9_.\-]+=)/)){let s=n.trim();if(!s)continue;let a=s.split(";"),o=a[0].indexOf("=");if(o===-1)continue;let i=a[0].slice(0,o).trim(),d=a[0].slice(o+1).trim(),l=a.slice(1).map(c=>c.trim()).filter(Boolean).join(" \xB7 ")||void 0;i&&e.push({name:i,value:Xs(d),attributes:l});}return e}var Ze=class Ze{constructor(e,r,n){this.originals=new Map;this.apiCallWriter=null;this.statusMix={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0};this.callCounter=0;this.apiCallCount=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=e,this.assertionTracker=r??null,this.apiConfig=n??Ze.DEFAULT_API_CONFIG;try{this.apiCallWriter=new q("api-calls");}catch{}}get lastCallId(){return this._lastCallId}getCallIdForValue(e){return e!=null&&typeof e=="object"?te.get(e)??null:this.primitiveCallIds.get(e)??null}intercept(){for(let r of Rd){let n=this.context[r].bind(this.context);this.originals.set(r,n),this.context[r]=this.createWrapper(r,n);}let e=this.context.dispose.bind(this.context);this.originals.set("dispose",e),this.context.dispose=async r=>(this.disposed=true,e(r));}tallyStatus(e){if(e===null||e<=0){this.statusMix.error++;return}if(e>=500){this.statusMix["5xx"]++;return}if(e>=400){this.statusMix["4xx"]++;return}if(e>=300){this.statusMix["3xx"]++;return}if(e>=200){this.statusMix["2xx"]++;return}this.statusMix.error++;}getFileData(){return this.apiCallWriter?.close(),{apiCallsFile:this.apiCallWriter?.getCount()?this.apiCallWriter.getPath():null,apiCallsCount:this.apiCallWriter?.getCount()??0,apiStatusMix:{...this.statusMix}}}flushLegacyAnnotations(e){}dispose(){for(let[e,r]of this.originals)this.context[e]=r;this.originals.clear(),this.apiCallWriter?.close(),this.callCounter=0,this.apiCallCount=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCallCount(){return this.apiCallCount}tagResponseMethods(e,r){let n=this,s=e.headers.bind(e);e.headers=function(){let p=s();return te.set(p,r),p};let a=e.headersArray.bind(e);e.headersArray=function(){let p=a();return te.set(p,r),p};let o=e.json.bind(e);e.json=async function(){let p=await o();return p!=null&&typeof p=="object"&&te.set(p,r),p};let i=e.status.bind(e);e.status=function(){let p=i();return n.primitiveCallIds.set(p,r),p};let d=e.statusText.bind(e);e.statusText=function(){let p=d();return n.primitiveCallIds.set(p,r),p};let l=e.ok.bind(e);e.ok=function(){let p=l();return n.primitiveCallIds.set(p,r),p};let c=e.text.bind(e);e.text=async function(){let p=await c();return n.primitiveCallIds.set(p,r),p};let u=e.body.bind(e);e.body=async function(){let p=await u();return te.set(p,r),p};}createWrapper(e,r){let n=this;return async function(a,o){if(!Ys(a,n.apiConfig.apiIncludeUrls,n.apiConfig.apiExcludeUrls))return r(a,o);let i=`api-call-${n.callCounter++}`,d=new Date().toISOString(),l=e==="fetch"?(o?.method??"GET").toUpperCase():e.toUpperCase(),c=Id(o),u=performance.now();n._lastCallId=i,n.assertionTracker&&n.assertionTracker.setCurrentCallId(i);let f;try{f=await r(a,o);}catch(p){let g=performance.now();try{let m=n.apiConfig.captureRequestBody?Xe(c,n.apiConfig.redactBodyFields):null,h={id:i,timestamp:d,method:l,url:wr(a),requestHeaders:null,requestBody:m,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((g-u)*100)/100,isBinary:!1,error:p instanceof Error?p.message:String(p)};n.apiCallWriter&&(n.apiCallWriter.append(h),n.apiCallCount++,n.tallyStatus(null));}catch{}throw p}try{let p=performance.now(),g=f.headers(),m=g["content-type"]??null,h=m?!_d(m):!1,v=null;n.apiConfig.captureRequestHeaders&&o?.headers&&(v=o.headers);let y=null;n.apiConfig.captureResponseHeaders&&(y=g);let b=n.apiConfig.captureRequestBody?c:null,k=null;if(n.apiConfig.captureResponseBody)try{h?k=(await f.body()).toString("base64"):k=await f.text();}catch{}let A=[],E=[];try{if(n.apiConfig.captureRequestHeaders&&(A=Md(o?.headers)),n.apiConfig.captureResponseHeaders){let x=f.headersArray().filter(S=>S.name.toLowerCase()==="set-cookie").map(S=>S.value);E=Ed(x);}}catch{}v=xr(v,n.apiConfig.redactHeaders),y=xr(y,n.apiConfig.redactHeaders),b=Xe(b,n.apiConfig.redactBodyFields),k=Xe(k,n.apiConfig.redactBodyFields);let T={id:i,timestamp:d,method:l,url:wr(f.url()),requestHeaders:v,requestBody:b,responseStatusCode:f.status(),responseStatusText:f.statusText(),responseHeaders:y,responseBody:k,requestCookies:A.length?A:null,responseCookies:E.length?E:null,responseTimeMs:Math.round((p-u)*100)/100,isBinary:h,error:null};n.apiCallWriter&&(n.apiCallWriter.append(T),n.apiCallCount++,n.tallyStatus(T.responseStatusCode));}catch{}try{f[yr]=i,n.tagResponseMethods(f,i);}catch{}return f}}};Ze.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var de=Ze;var Fd=[".png",".jpg",".jpeg"];function Bd(t){let e=t.toLowerCase();return Fd.some(r=>e.endsWith(r))?t:`${t}.png`}function Od(){try{return test.info()}catch{return null}}function qd(t,e){for(let r=e;r<t.length;r++){let n=/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/.exec(t[r]?.name??"");if(n)return n[1]}return null}async function Ud(t,e){if(!Ne(t))return De("Attaching the baseline of a passing comparison"),null;try{let r=t.snapshotPath(e,{kind:"screenshot"}),n=extname(r)||".png",s=basename(r,n);return await t.attach(`${s}-expected${n}`,{path:r}),s}catch{return null}}async function Hd(t,e){try{await t.attach(qt,{body:Buffer.from(JSON.stringify([e])),contentType:"application/json"});}catch{}}async function Cr(t,e,r={}){let n={...r};delete n.tags;let s=Bd(e),a=Od(),o=a?.attachments.length??0,i=true,d="";try{await expect(t).toHaveScreenshot(s,n);}catch(l){i=false,d=l instanceof Error?l.message:String(l);}if(a){let l=i?await Ud(a,s):qd(a.attachments,o);if(l){let c=!i&&!Ee(d)&&!a.attachments.some((u,f)=>f>=o&&u.name.startsWith(`${l}-diff.`));await Hd(a,{stem:l,name:e,status:i?"passed":c?"new":"failed"});}}return {pass:i,name:"toMatchVisualBaseline",message:()=>i?`Expected "${e}" to differ from its visual baseline, but it matched.`:d}}expect.extend({toMatchVisualBaseline:Cr});function Vd(){try{return test.info()}catch{return null}}Bn(Ye(expect),Vd);var $d="__testrelic_api_config",Wd="__testrelic_config_trackApiCalls";function Tr(t){let e=t.annotations.find(n=>n.type===$d&&n.description!==void 0);if(e)try{return JSON.parse(e.description,Gd)}catch{}let r=t.annotations.find(n=>n.type===Wd&&n.description!==void 0);return r?{trackApiCalls:r.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Gd(t,e){if(typeof e=="object"&&e!==null&&e.__regexp===true&&typeof e.source=="string"){let{source:r,flags:n}=e;return new RegExp(r,n)}return e}var ra={page:async({page:t},e,r)=>{let n=new Je(t);try{await n.init();}catch{}await e(t);try{let{navigations:s,networkRequestsFile:a,networkRequestsCount:o,consoleLogsFile:i,consoleLogsCount:d}=await n.getFileData(),l={testRelicData:!0,version:PAYLOAD_VERSION,navigations:s,apiAssertions:[],networkRequestsFile:a,networkRequestsCount:o,consoleLogsFile:i,consoleLogsCount:d,apiCallsFile:null,apiCallsCount:0};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(l)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}n.dispose();},request:async({request:t},e,r)=>{let n=Tr(r);if(!n.trackApiCalls){await e(t);return}let s=new oe,a=new de(t,s,n);a.intercept(),le(s,a);try{await e(t);}finally{le(null,null);}try{let{apiCallsFile:o,apiCallsCount:i,apiStatusMix:d}=a.getFileData(),l=n.captureAssertions?s.getData():[],c={testRelicData:!0,version:PAYLOAD_VERSION,navigations:[],apiAssertions:l,networkRequestsFile:null,networkRequestsCount:0,consoleLogsFile:null,consoleLogsCount:0,apiCallsFile:o,apiCallsCount:i,apiStatusMix:d};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(c)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};test.extend(ra);Ye(expect);var Zd={request:async({request:t},e,r)=>{let n=Tr(r);if(!n.trackApiCalls){await e(t);return}let s=new oe,a=new de(t,s,n);a.intercept(),le(s,a);let o=null;try{o=new q("api-console");}catch{}let i=0,d=process.stdout.write,l=process.stderr.write;process.stdout.write=function(c,...u){try{let f=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!f.startsWith("[testrelic]")&&!f.startsWith("\u2139 TestRelic")&&!f.startsWith("\u2713 TestRelic")&&!f.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stdout",text:f.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null}),i++);}catch{}return d.apply(process.stdout,[c,...u])},process.stderr.write=function(c,...u){try{let f=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!f.startsWith("[testrelic]")&&!f.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stderr",text:f.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null}),i++);}catch{}return l.apply(process.stderr,[c,...u])};try{await e(t);}finally{process.stdout.write=d,process.stderr.write=l,le(null,null);}try{o?.close();let{apiCallsFile:c,apiCallsCount:u,apiStatusMix:f}=a.getFileData(),p=n.captureAssertions?s.getData():[],g={testRelicData:!0,version:PAYLOAD_VERSION,navigations:[],apiAssertions:p,networkRequestsFile:null,networkRequestsCount:0,consoleLogsFile:i>0?o?.getPath()??null:null,consoleLogsCount:i,apiCallsFile:c,apiCallsCount:u,apiStatusMix:f};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(g)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};var na="@testrelic/playwright-analytics";function ec(t){return Array.isArray(t)?t.some(e=>Array.isArray(e)&&typeof e[0]=="string"&&e[0]===na):false}function tc(t,e){let n={video:"on",screenshot:"on",trace:"on",...t.use??{}},s;Array.isArray(t.reporter)?s=t.reporter:typeof t.reporter=="string"?s=[[t.reporter]]:s=[["list"]];let a=ec(s)?s:[...s,[na,e??{}]];return defineConfig({...t,use:n,reporter:a})}var sa=false;function kg(t,e,r="manual_record"){if(!t||!t.annotations){sa||(sa=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
4322
- `));return}let n={url:e,navigationType:r,timestamp:new Date().toISOString()};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(n)});}export{Ce as SCHEMA_VERSION,Ke as default,tc as defineConfig,kg as recordNavigation,Zd as testRelicApiFixture,ra as testRelicFixture};//# sourceMappingURL=index.js.map
4317
+ `)[0]??null,networkCount:r.networkRequestsCount,consoleCount:r.consoleLogsCount,actionCount:r.actions?.length??0,testType:r.testType,apiCallCount:r.apiCallsCount,...r.apiStatusMix?{apiStatusMix:r.apiStatusMix}:s?{apiStatusMix:sd(s)}:{},assertionsPassed:We(r.apiAssertions,"passed"),assertionsFailed:We(r.apiAssertions,"failed"),...(()=>{let i=Ds(r.apiAssertions);return i?{firstFailedAssertion:i}:{}})(),isRetry:!1,retryGroupKey:tt(r.filePath,r.titlePath,r.testId)};switch(this.testIndex.push(o),this.summaryCounters.total++,r.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}this.upsertAggContribution(`${r.filePath}::${r.titlePath.join(" > ")}`,Bs(r.retry,s,r.apiAssertions??[],r.navigations??[],r.networkRequestsCount,r.consoleLogsCount,r.actions??null));}this.collectedTests.length=0;}catch{}}buildTimeline(){let e=this.collectedTests.map(r=>({titlePath:r.titlePath,title:r.title,status:r.status,duration:r.duration,startedAt:r.startedAt,completedAt:r.completedAt,retryCount:r.retryCount,retry:r.retry,tags:r.tags,failure:r.failure,specFile:r.specFile,navigations:r.navigations,apiCalls:null,apiAssertions:r.apiAssertions,testId:r.testId,filePath:r.filePath,suiteName:r.suiteName,testType:r.testType,isFlaky:r.isFlaky,retryStatus:r.retryStatus,expectedStatus:r.expectedStatus,actualStatus:r.actualStatus,artifacts:r.artifacts,networkRequests:null,actions:r.actions,consoleLogs:null}));return ts(e,{navigationTypes:this.config.navigationTypes})}readJsonlFile(e){if(!e)return null;let r=Y(e);return r.length>0?r:null}toTestResult(e,r){let n=null,s=null,a=null;return r?.loadFiles&&(n=this.readJsonlFile(e.networkRequestsFile),s=this.readJsonlFile(e.consoleLogsFile),a=this.readJsonlFile(e.apiCallsFile)),{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,visual:e.visual,networkRequests:n,apiCalls:a,apiAssertions:e.apiAssertions,actions:e.actions??null,consoleLogs:s}}buildCloudTestPayload(e){let r={title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retry:e.retry,retryCount:e.retryCount,retryStatus:e.retryStatus,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,visual:e.visual??[],actions:e.actions??[],navigations:e.navigations??[],steps:e.actions??[],browser:e.browser,os:e.os,source:e.source};if(e.apiAssertions&&e.apiAssertions.length>0&&(r.protocolAssertions=tr(e.apiAssertions)),e.consoleLogsFile&&(r.consoleLogs=Y(e.consoleLogsFile)),e.networkRequestsFile&&(r.networkRequests=Y(e.networkRequestsFile)),e.apiCallsFile){let n=Y(e.apiCallsFile);r.apiCalls=Qt(n),(!r.networkRequests||r.networkRequests.length===0)&&(r.networkRequests=er(n));}return r}writeReport(e){try{let r=JSON.stringify(e),n=this.config.outputPath,s=dirname(n);mkdirSync(s,{recursive:!0});let a=n+".tmp";writeFileSync(a,r,"utf-8"),renameSync(a,n);}catch(r){process.stderr.write(`[testrelic] Failed to write report: ${r instanceof Error?r.message:String(r)}
4318
+ `);}}};var vd=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function yd(t){let e=t.toLowerCase();return vd.some(r=>e.includes(r))}var Je=class t{constructor(e,r){this.page=e;this.records=[];this.listeners=[];this.navCounters=[];this.pendingRequests=new Map;this.networkWriter=null;this.consoleWriter=null;this.pendingBodyReads=[];this.requestIdCounter=0;this.networkRequestCount=0;this.consoleLogCount=0;this.includeNetworkStats=r?.includeNetworkStats??true,this.origGoto=e.goto.bind(e),this.origGoBack=e.goBack.bind(e),this.origGoForward=e.goForward.bind(e),this.origReload=e.reload.bind(e);try{this.includeNetworkStats&&(this.networkWriter=new q("network")),this.consoleWriter=new q("console");}catch{}this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async finalizeCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[,e]of this.pendingRequests)this.networkWriter&&(this.networkWriter.append({url:e.url,method:e.method,resourceType:e.resourceType,statusCode:0,responseTimeMs:Date.now()-e.startTimeMs,startedAt:e.startedAt,requestHeaders:e.headers,requestBody:e.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:e.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.networkRequestCount++);this.pendingRequests.clear(),this.networkWriter?.close(),this.consoleWriter?.close();}static mapConsoleType(e){switch(e){case "log":return "log";case "warning":return "warn";case "error":return "error";case "info":return "info";case "debug":return "debug";default:return "log"}}async getFileData(){this.assembleNetworkStats();let e=this.records.map(r=>({url:r.url,navigationType:r.navigationType,timestamp:r.timestamp,domContentLoadedAt:r.domContentLoadedAt,networkIdleAt:r.networkIdleAt,networkStats:r.networkStats}));return this.includeNetworkStats?await this.finalizeCapturedRequests():this.consoleWriter?.close(),{navigations:e,networkRequestsFile:this.networkWriter?.getCount()?this.networkWriter.getPath():null,networkRequestsCount:this.networkWriter?.getCount()??0,consoleLogsFile:this.consoleWriter?.getCount()?this.consoleWriter.getPath():null,consoleLogsCount:this.consoleWriter?.getCount()??0}}async flushLegacyAnnotations(e){}dispose(){let e=t.asPatchable(this.page);e.goto=this.origGoto,e.goBack=this.origGoBack,e.goForward=this.origGoForward,e.reload=this.origReload;for(let{event:r,handler:n}of this.listeners)this.page.off(r,n);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.pendingBodyReads=[],this.networkWriter?.close(),this.consoleWriter?.close();}getRecords(){return this.assembleNetworkStats(),this.records}static asPatchable(e){return e}interceptMethods(){let e=this,r=this.page,n=t.asPatchable(r);n.goto=async function(s,a){return e.recordNavigation(s,"goto"),e.origGoto(s,a)},n.goBack=async function(s){let a=await e.origGoBack(s);return e.recordNavigation(r.url(),"back"),a},n.goForward=async function(s){let a=await e.origGoForward(s);return e.recordNavigation(r.url(),"forward"),a},n.reload=async function(s){return e.recordNavigation(r.url(),"refresh"),e.origReload(s)};}attachListeners(){let e=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",e),this.listeners.push({event:"domcontentloaded",handler:e});let r=s=>{try{let a=s;if(typeof a.parentFrame=="function"&&a.parentFrame()!==null)return;let o=a.url(),i=this.records[this.records.length-1];if(i&&Date.now()-new Date(i.timestamp).getTime()<50&&i.url===o)return;this.recordNavigation(o,"navigation");}catch{}};this.page.on("framenavigated",r),this.listeners.push({event:"framenavigated",handler:r});let n=s=>{try{let a=s,o=a.type(),i=a.text();if(o==="debug"&&i.startsWith("__testrelic_nav:")){try{let d=JSON.parse(i.slice(16));d.type&&d.url&&this.recordNavigation(d.url,d.type);}catch{}return}{let d=null;try{let c=a.location();c&&c.url&&(d=`${c.url}:${c.lineNumber}:${c.columnNumber}`);}catch{}let l=t.mapConsoleType(o);this.consoleWriter&&(this.consoleWriter.append({level:l,text:i,timestamp:new Date().toISOString(),location:d}),this.consoleLogCount++);}}catch{}};if(this.page.on("console",n),this.listeners.push({event:"console",handler:n}),this.includeNetworkStats){let s=i=>{let d=this.records.length-1,l=this.counterForNav(d);l&&l.totalRequests++;try{let c=i,u=String(this.requestIdCounter++),p=c.postData()??null,g={url:c.url(),method:c.method(),resourceType:this.mapResourceType(c.resourceType()),headers:c.headers(),postData:p,postDataTruncated:!1,startedAt:new Date().toISOString(),startTimeMs:Date.now(),navIndex:d};this.pendingRequests.set(u,g),i.__testrelic_id=u;}catch{}};this.page.on("request",s),this.listeners.push({event:"request",handler:s});let a=i=>{try{let d=i,l=d.request().__testrelic_id,c=l?this.pendingRequests.get(l):void 0,u=this.counterForNav(c?c.navIndex:this.records.length-1);if(u){let y=d.status();y>=400&&(u.failedRequests++,u.failedRequestUrls.push(y+" "+d.url()));let b=d.headers()["content-length"];b&&(u.totalBytes+=parseInt(b,10)||0);let k=d.request().resourceType(),A=this.mapResourceType(k);u.byType[A]++;}if(!l||!c)return;this.pendingRequests.delete(l);let p=Date.now()-c.startTimeMs,g=d.headers(),f=g["content-type"]??null,m=parseInt(g["content-length"]??"0",10)||0,h=f?!yd(f):!1,v=(async()=>{let y=null;if(!h)try{y=(await d.body()).toString("utf-8");}catch{}let b={url:c.url,method:c.method,resourceType:c.resourceType,statusCode:d.status(),responseTimeMs:p,startedAt:c.startedAt,requestHeaders:c.headers,requestBody:c.postData,responseBody:y,responseHeaders:g,contentType:f,responseSize:m,requestBodyTruncated:c.postDataTruncated,responseBodyTruncated:!1,isBinary:h,error:null};this.networkWriter&&(this.networkWriter.append(b),this.networkRequestCount++);})();this.pendingBodyReads.push(v);}catch{}};this.page.on("response",a),this.listeners.push({event:"response",handler:a});let o=i=>{let d=i.__testrelic_id,l=d?this.pendingRequests.get(d):void 0,c=this.counterForNav(l?l.navIndex:this.records.length-1);if(c){c.failedRequests++;try{let u=i;c.failedRequestUrls.push("ERR "+u.url());}catch{}}try{let u=i;if(!d||!l)return;this.pendingRequests.delete(d);let p={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:0,responseTimeMs:Date.now()-l.startTimeMs,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:u.failure()?.errorText??"Unknown error"};this.networkWriter&&(this.networkWriter.append(p),this.networkRequestCount++);}catch{}};this.page.on("requestfailed",o),this.listeners.push({event:"requestfailed",handler:o});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let e=history.pushState.bind(history),r=history.replaceState.bind(history);history.pushState=function(...n){e(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...n){r(...n),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(e,r){this.records.push({url:e,navigationType:r,timestamp:new Date().toISOString()}),this.includeNetworkStats&&this.navCounters.push(this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}counterForNav(e){return e>=0?this.navCounters[e]:void 0}assembleNetworkStats(){if(this.includeNetworkStats)for(let e=0;e<this.records.length;e++){let r=this.navCounters[e];r&&(this.records[e].networkStats={totalRequests:r.totalRequests,failedRequests:r.failedRequests,failedRequestUrls:[...r.failedRequestUrls],totalBytes:r.totalBytes,byType:{...r.byType}});}}mapResourceType(e){switch(e){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var yr=Symbol.for("__testrelic_call_id"),xd="__testrelic_api_assertions",te=new WeakMap,oe=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(e){this.assertions.push(e);}getAssertions(){return this.assertions}setCurrentCallId(e){this.currentCallId=e;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(e){this.assertions.length!==0&&e.annotations.push({type:xd,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}},Us=new Map;function wd(t){let e=Us.get(t);if(e)return e;try{let r=t.startsWith("file://")?fileURLToPath(t):t,s=readFileSync(r,"utf-8").split(`
4319
+ `);return Us.set(t,s),s}catch{return null}}var zs=(()=>{let t=new Error().stack;if(!t)return null;for(let e of t.split(`
4320
+ `)){let r=e.match(/at\s+(?:.*?\s+\()?(.+?):\d+:\d+\)?$/);if(!r||r[1].startsWith("node:"))continue;let n=Math.max(r[1].lastIndexOf("/"),r[1].lastIndexOf("\\"));return n>0?r[1].slice(0,n+1):null}return null})();function kd(t){if(!t.startsWith("file:"))return t;try{return fileURLToPath(t)}catch{return t}}function Cd(){let e=new Error().stack;if(!e)return null;let r=e.split(`
4321
+ `);return js(r,true)??js(r,false)}function js(t,e){for(let r of t){if(e&&zs!==null&&r.includes(zs)||r.includes("node_modules")||r.includes("node:internal")||r.includes(" at new Error")||r.includes(" at captureAssertionLocation")||r.includes(" at findFrame")||r.includes(" at expectWrapper")||r.includes(" at wrappedMatcher"))continue;let n=r.match(/at\s+(?:.*?\s+\()?(.+?):(\d+):(\d+)\)?$/);if(n)return {file:kd(n[1]),line:parseInt(n[2],10),column:parseInt(n[3],10)}}return null}function Td(t,e){if(!t)return "custom";let r=t.toLowerCase();return r.includes(".status()")&&!r.includes(".statustext()")?r.includes(".ok()")?"statusOk":"status":r.includes(".ok()")?"statusOk":r.includes(".headers()")||r.includes(".headersarray()")?"header":r.includes("tomatchobject")||r.includes("toequal")?"bodyMatch":r.includes("tocontain")||r.includes("tostringcontaining")?"bodyContains":r.includes(".json()")||r.includes(".text()")?"bodyField":"custom"}function Sd(t,e,r){let n=function(i,...d){let l=t(),c=e();if(!l||!c)return r(i,...d);let u=null;if(i!=null&&typeof i=="object"){let m=i[yr];typeof m=="string"&&(u=m);}if(!u&&i!==null&&i!==void 0&&typeof i=="object"&&(u=te.get(i)??null),u||(u=c.getCallIdForValue(i)),u||(u=l.getCurrentCallId()),!u)return r(i,...d);let p=Cd(),g;if(p){let m=wd(p.file);m&&p.line>0&&p.line<=m.length&&(g=m[p.line-1].trim());}let f=r(i,...d);return u?Gs(f,{tracker:l,callId:u,received:i,location:p??{file:"unknown",line:0},expression:g}):f},s=r,a=n;for(let o of Object.keys(s))a[o]=s[o];return n}var Vs=Symbol.for("testrelic.activeAssertionContext");function vr(){let t=globalThis,e=t[Vs];return e||(e={tracker:null,apiTracker:null},t[Vs]=e),e}function le(t,e){let r=vr();r.tracker=t,r.apiTracker=e;}function Ye(t){return Sd(()=>vr().tracker,()=>vr().apiTracker,t)}function Gs(t,e){return new Proxy(t,{get(r,n,s){let a=Reflect.get(r,n,s);return typeof a!="function"||typeof n=="symbol"?a:n==="not"?Gs(a,e):function(...i){let d=i[0],l="passed",c=e.received,u=null;try{let p=a.apply(this??r,i);return p&&typeof p=="object"&&typeof p.then=="function"?p.then(()=>{mr(e,n,d,c,"passed");},g=>{throw mr(e,n,d,c,"failed"),g}):p}catch(p){if(l="failed",u=p,p instanceof Error&&p.message){let g=p.message.match(/Received:\s*(.+)/);g&&(c=g[1]);}throw p}finally{(u!==null||l==="passed")&&mr(e,n,d,c,l);}}}})}function mr(t,e,r,n,s){let a=Td(t.expression,t.received),o={callId:t.callId,type:a,expected:$s(r),actual:$s(n),status:s,location:t.location,expression:t.expression};t.tracker.recordAssertion(o);}function $s(t){if(t==null)return t;if(typeof t=="string")return se(t);if(typeof t=="number"||typeof t=="boolean")return t;try{return JSON.stringify(t),t}catch{return String(t)}}var Ks="[REDACTED]";function xr(t,e){if(t===null||e.length===0)return t;let r=new Set(e.map(s=>s.toLowerCase())),n={};for(let s of Object.keys(t))Object.prototype.hasOwnProperty.call(t,s)&&(n[s]=r.has(s.toLowerCase())?Ks:t[s]);return n}function Xe(t,e){if(t===null||e.length===0)return t;let r;try{r=JSON.parse(t);}catch{return t}if(typeof r!="object"||r===null)return t;let n=new Set(e.map(a=>a.toLowerCase())),s=br(r,n);return JSON.stringify(s)}function br(t,e){if(Array.isArray(t))return t.map(r=>br(r,e));if(typeof t=="object"&&t!==null){let r={};for(let n of Object.keys(t)){if(!Object.prototype.hasOwnProperty.call(t,n))continue;let s=t[n];e.has(n.toLowerCase())?r[n]=Ks:r[n]=br(s,e);}return r}return t}var Rd=new Set(["access_token","api_key","token","sig"]);function wr(t){if(!t)return t;let e;try{e=new URL(t);}catch{return t}let r=false;for(let n of [...e.searchParams.keys()])Rd.has(n.toLowerCase())&&(e.searchParams.delete(n),r=true);return r?e.toString():t}function Ys(t,e,r){if(r.length>0){for(let n of r)if(Js(t,n))return false}if(e.length>0){for(let n of e)if(Js(t,n))return true;return false}return true}function Js(t,e){try{return e instanceof RegExp?e.test(t):Ad(e).test(t)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(e)}`),false}}function Ad(t){let e="",r=0;for(;r<t.length;){let n=t[r];n==="*"&&t[r+1]==="*"?(e+=".*",r+=2,t[r]==="/"&&r++):n==="*"?(e+="[^/]*",r++):n==="?"?(e+="[^/]",r++):".+^${}()|[]\\".includes(n)?(e+="\\"+n,r++):(e+=n,r++);}return new RegExp(e)}var _d=["get","post","put","patch","delete","head","fetch"],Id=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function Md(t){let e=t.toLowerCase();return Id.some(r=>e.includes(r))}function Pd(t){if(!t)return null;if(t.data!==void 0&&t.data!==null){let e=t.data;return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("base64"):JSON.stringify(e)}if(t.form!==void 0&&t.form!==null)return JSON.stringify(t.form);if(t.multipart!==void 0&&t.multipart!==null){let e=t.multipart,r={};for(let[n,s]of Object.entries(e))typeof s=="string"||typeof s=="number"||typeof s=="boolean"?r[n]=String(s):s&&typeof s=="object"&&"name"in s?r[n]=`[file: ${s.name}]`:r[n]="[binary]";return JSON.stringify(r)}return null}function Xs(t){return t?"\u2022\u2022\u2022\u2022":""}function Ed(t){if(!t)return [];let e;for(let[n,s]of Object.entries(t))if(n.toLowerCase()==="cookie"){e=s;break}if(!e)return [];let r=[];for(let n of e.split(";")){let s=n.trim();if(!s)continue;let a=s.indexOf("="),o=a===-1?s:s.slice(0,a).trim(),i=a===-1?"":s.slice(a+1).trim();o&&r.push({name:o,value:Xs(i)});}return r}function Ld(t){let e=[];for(let r of t)for(let n of r.split(/,(?=\s*[A-Za-z0-9_.\-]+=)/)){let s=n.trim();if(!s)continue;let a=s.split(";"),o=a[0].indexOf("=");if(o===-1)continue;let i=a[0].slice(0,o).trim(),d=a[0].slice(o+1).trim(),l=a.slice(1).map(c=>c.trim()).filter(Boolean).join(" \xB7 ")||void 0;i&&e.push({name:i,value:Xs(d),attributes:l});}return e}var Ze=class Ze{constructor(e,r,n){this.originals=new Map;this.apiCallWriter=null;this.statusMix={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0};this.callCounter=0;this.apiCallCount=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=e,this.assertionTracker=r??null,this.apiConfig=n??Ze.DEFAULT_API_CONFIG;try{this.apiCallWriter=new q("api-calls");}catch{}}get lastCallId(){return this._lastCallId}getCallIdForValue(e){return e!=null&&typeof e=="object"?te.get(e)??null:this.primitiveCallIds.get(e)??null}intercept(){for(let r of _d){let n=this.context[r].bind(this.context);this.originals.set(r,n),this.context[r]=this.createWrapper(r,n);}let e=this.context.dispose.bind(this.context);this.originals.set("dispose",e),this.context.dispose=async r=>(this.disposed=true,e(r));}tallyStatus(e){if(e===null||e<=0){this.statusMix.error++;return}if(e>=500){this.statusMix["5xx"]++;return}if(e>=400){this.statusMix["4xx"]++;return}if(e>=300){this.statusMix["3xx"]++;return}if(e>=200){this.statusMix["2xx"]++;return}this.statusMix.error++;}getFileData(){return this.apiCallWriter?.close(),{apiCallsFile:this.apiCallWriter?.getCount()?this.apiCallWriter.getPath():null,apiCallsCount:this.apiCallWriter?.getCount()??0,apiStatusMix:{...this.statusMix}}}flushLegacyAnnotations(e){}dispose(){for(let[e,r]of this.originals)this.context[e]=r;this.originals.clear(),this.apiCallWriter?.close(),this.callCounter=0,this.apiCallCount=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCallCount(){return this.apiCallCount}tagResponseMethods(e,r){let n=this,s=e.headers.bind(e);e.headers=function(){let g=s();return te.set(g,r),g};let a=e.headersArray.bind(e);e.headersArray=function(){let g=a();return te.set(g,r),g};let o=e.json.bind(e);e.json=async function(){let g=await o();return g!=null&&typeof g=="object"&&te.set(g,r),g};let i=e.status.bind(e);e.status=function(){let g=i();return n.primitiveCallIds.set(g,r),g};let d=e.statusText.bind(e);e.statusText=function(){let g=d();return n.primitiveCallIds.set(g,r),g};let l=e.ok.bind(e);e.ok=function(){let g=l();return n.primitiveCallIds.set(g,r),g};let c=e.text.bind(e);e.text=async function(){let g=await c();return n.primitiveCallIds.set(g,r),g};let u=e.body.bind(e);e.body=async function(){let g=await u();return te.set(g,r),g};}createWrapper(e,r){let n=this;return async function(a,o){if(!Ys(a,n.apiConfig.apiIncludeUrls,n.apiConfig.apiExcludeUrls))return r(a,o);let i=`api-call-${n.callCounter++}`,d=new Date().toISOString(),l=e==="fetch"?(o?.method??"GET").toUpperCase():e.toUpperCase(),c=Pd(o),u=performance.now();n._lastCallId=i,n.assertionTracker&&n.assertionTracker.setCurrentCallId(i);let p;try{p=await r(a,o);}catch(g){let f=performance.now();try{let m=n.apiConfig.captureRequestBody?Xe(c,n.apiConfig.redactBodyFields):null,h={id:i,timestamp:d,method:l,url:wr(a),requestHeaders:null,requestBody:m,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((f-u)*100)/100,isBinary:!1,error:g instanceof Error?g.message:String(g)};n.apiCallWriter&&(n.apiCallWriter.append(h),n.apiCallCount++,n.tallyStatus(null));}catch{}throw g}try{let g=performance.now(),f=p.headers(),m=f["content-type"]??null,h=m?!Md(m):!1,v=null;n.apiConfig.captureRequestHeaders&&o?.headers&&(v=o.headers);let y=null;n.apiConfig.captureResponseHeaders&&(y=f);let b=n.apiConfig.captureRequestBody?c:null,k=null;if(n.apiConfig.captureResponseBody)try{h?k=(await p.body()).toString("base64"):k=await p.text();}catch{}let A=[],P=[];try{if(n.apiConfig.captureRequestHeaders&&(A=Ed(o?.headers)),n.apiConfig.captureResponseHeaders){let x=p.headersArray().filter(S=>S.name.toLowerCase()==="set-cookie").map(S=>S.value);P=Ld(x);}}catch{}v=xr(v,n.apiConfig.redactHeaders),y=xr(y,n.apiConfig.redactHeaders),b=Xe(b,n.apiConfig.redactBodyFields),k=Xe(k,n.apiConfig.redactBodyFields);let T={id:i,timestamp:d,method:l,url:wr(p.url()),requestHeaders:v,requestBody:b,responseStatusCode:p.status(),responseStatusText:p.statusText(),responseHeaders:y,responseBody:k,requestCookies:A.length?A:null,responseCookies:P.length?P:null,responseTimeMs:Math.round((g-u)*100)/100,isBinary:h,error:null};n.apiCallWriter&&(n.apiCallWriter.append(T),n.apiCallCount++,n.tallyStatus(T.responseStatusCode));}catch{}try{p[yr]=i,n.tagResponseMethods(p,i);}catch{}return p}}};Ze.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var de=Ze;var Od=[".png",".jpg",".jpeg"],qd=/A snapshot doesn't exist at /;function Hd(t){return t.wroteMissing?"new":t.pass?"passed":t.wroteNewBaseline?"new":"failed"}function Ud(t){let e=t.toLowerCase();return Od.some(r=>e.endsWith(r))?t:`${t}.png`}function zd(){try{return test.info()}catch{return null}}function jd(t,e){for(let r=e;r<t.length;r++){let n=/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/.exec(t[r]?.name??"");if(n)return n[1]}return null}async function Vd(t,e){if(!Ne(t))return De("Attaching the baseline of a passing comparison"),null;try{let r=t.snapshotPath(e,{kind:"screenshot"}),n=extname(r)||".png",s=basename(r,n);return await t.attach(`${s}-expected${n}`,{path:r}),s}catch{return null}}async function $d(t,e){try{await t.attach(qt,{body:Buffer.from(JSON.stringify([e])),contentType:"application/json"});}catch{}}async function Cr(t,e,r={}){let n={...r};delete n.tags;let s=Ud(e),a=zd(),o=a?.attachments.length??0,i=a?.errors?.length??0,d=true,l="";try{await expect(t).toHaveScreenshot(s,n);}catch(c){d=false,l=c instanceof Error?c.message:String(c);}if(a){let c=(a.errors??[]).slice(i).some(p=>qd.test(p.message??"")),u=d&&!c?await Vd(a,s):jd(a.attachments,o);if(u){let p=c||!d&&!Pe(l)&&!a.attachments.some((g,f)=>f>=o&&g.name.startsWith(`${u}-diff.`));await $d(a,{stem:u,name:e,status:Hd({pass:d,wroteMissing:c,wroteNewBaseline:p})});}}return {pass:d,name:"toMatchVisualBaseline",message:()=>d?`Expected "${e}" to differ from its visual baseline, but it matched.`:l}}expect.extend({toMatchVisualBaseline:Cr});function Kd(){try{return test.info()}catch{return null}}Bn(Ye(expect),Kd);var Jd="__testrelic_api_config",Yd="__testrelic_config_trackApiCalls";function Tr(t){let e=t.annotations.find(n=>n.type===Jd&&n.description!==void 0);if(e)try{return JSON.parse(e.description,Xd)}catch{}let r=t.annotations.find(n=>n.type===Yd&&n.description!==void 0);return r?{trackApiCalls:r.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Xd(t,e){if(typeof e=="object"&&e!==null&&e.__regexp===true&&typeof e.source=="string"){let{source:r,flags:n}=e;return new RegExp(r,n)}return e}var ra={page:async({page:t},e,r)=>{let n=new Je(t);try{await n.init();}catch{}await e(t);try{let{navigations:s,networkRequestsFile:a,networkRequestsCount:o,consoleLogsFile:i,consoleLogsCount:d}=await n.getFileData(),l={testRelicData:!0,version:PAYLOAD_VERSION,navigations:s,apiAssertions:[],networkRequestsFile:a,networkRequestsCount:o,consoleLogsFile:i,consoleLogsCount:d,apiCallsFile:null,apiCallsCount:0};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(l)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}n.dispose();},request:async({request:t},e,r)=>{let n=Tr(r);if(!n.trackApiCalls){await e(t);return}let s=new oe,a=new de(t,s,n);a.intercept(),le(s,a);try{await e(t);}finally{le(null,null);}try{let{apiCallsFile:o,apiCallsCount:i,apiStatusMix:d}=a.getFileData(),l=n.captureAssertions?s.getData():[],c={testRelicData:!0,version:PAYLOAD_VERSION,navigations:[],apiAssertions:l,networkRequestsFile:null,networkRequestsCount:0,consoleLogsFile:null,consoleLogsCount:0,apiCallsFile:o,apiCallsCount:i,apiStatusMix:d};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(c)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};test.extend(ra);Ye(expect);var rc={request:async({request:t},e,r)=>{let n=Tr(r);if(!n.trackApiCalls){await e(t);return}let s=new oe,a=new de(t,s,n);a.intercept(),le(s,a);let o=null;try{o=new q("api-console");}catch{}let i=0,d=process.stdout.write,l=process.stderr.write;process.stdout.write=function(c,...u){try{let p=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!p.startsWith("[testrelic]")&&!p.startsWith("\u2139 TestRelic")&&!p.startsWith("\u2713 TestRelic")&&!p.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stdout",text:p.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null}),i++);}catch{}return d.apply(process.stdout,[c,...u])},process.stderr.write=function(c,...u){try{let p=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!p.startsWith("[testrelic]")&&!p.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stderr",text:p.replace(/\n$/,""),timestamp:new Date().toISOString(),location:null}),i++);}catch{}return l.apply(process.stderr,[c,...u])};try{await e(t);}finally{process.stdout.write=d,process.stderr.write=l,le(null,null);}try{o?.close();let{apiCallsFile:c,apiCallsCount:u,apiStatusMix:p}=a.getFileData(),g=n.captureAssertions?s.getData():[],f={testRelicData:!0,version:PAYLOAD_VERSION,navigations:[],apiAssertions:g,networkRequestsFile:null,networkRequestsCount:0,consoleLogsFile:i>0?o?.getPath()??null:null,consoleLogsCount:i,apiCallsFile:c,apiCallsCount:u,apiStatusMix:p};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(f)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};var na="@testrelic/playwright-analytics";function sc(t){return Array.isArray(t)?t.some(e=>Array.isArray(e)&&typeof e[0]=="string"&&e[0]===na):false}function ac(t,e){let n={video:"on",screenshot:"on",trace:"on",...t.use??{}},s;Array.isArray(t.reporter)?s=t.reporter:typeof t.reporter=="string"?s=[[t.reporter]]:s=[["list"]];let a=sc(s)?s:[...s,[na,e??{}]];return defineConfig({...t,use:n,reporter:a})}var sa=false;function Rg(t,e,r="manual_record"){if(!t||!t.annotations){sa||(sa=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
4322
+ `));return}let n={url:e,navigationType:r,timestamp:new Date().toISOString()};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(n)});}export{Ce as SCHEMA_VERSION,Ke as default,ac as defineConfig,Rg as recordNavigation,rc as testRelicApiFixture,ra as testRelicFixture};//# sourceMappingURL=index.js.map
4323
4323
  //# sourceMappingURL=index.js.map