@testrelic/playwright-analytics 2.16.2 → 2.16.3-next.157
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/api-fixture.cjs +6 -5
- package/dist/api-fixture.cjs.map +1 -1
- package/dist/api-fixture.js +6 -5
- package/dist/api-fixture.js.map +1 -1
- package/dist/fixture.cjs +7 -6
- package/dist/fixture.cjs.map +1 -1
- package/dist/fixture.js +7 -6
- package/dist/fixture.js.map +1 -1
- package/dist/index.cjs +57 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +57 -52
- package/dist/index.js.map +1 -1
- package/dist/reporter-entry.cjs +44 -40
- package/dist/reporter-entry.cjs.map +1 -1
- package/dist/reporter-entry.js +44 -40
- package/dist/reporter-entry.js.map +1 -1
- package/dist/visual.cjs +2 -2
- package/dist/visual.cjs.map +1 -1
- package/dist/visual.js +2 -2
- package/dist/visual.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {randomUUID,createHash}from'crypto';import {statSync,writeFileSync,existsSync,mkdirSync,openSync,writeSync,closeSync,unlinkSync,readFileSync,renameSync,appendFileSync,readdirSync,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
|
|
2
|
-
`),false}}moveFile(e,r){try{renameSync(e,r);}catch{try{
|
|
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 Er=".testrelic",
|
|
4
|
-
`),s}catch{}let a=dirname(e);if(a===e)break;e=a;}return null}function Nr(t){try{let e=readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!Dr(r)?null:r}catch{return null}}function Dr(t){for(let e of Object.keys(t)){if(
|
|
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("$")?Fr(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:Mr}var
|
|
1
|
+
import {randomUUID,createHash}from'crypto';import {statSync,writeFileSync,existsSync,mkdirSync,openSync,writeSync,closeSync,unlinkSync,readFileSync,renameSync,copyFileSync,appendFileSync,readdirSync,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 fa=".testrelic-report";function Qe(t,e,r,n){let s=`${t}|${e.join("|")}|${r}|${n}`;return createHash("sha256").update(s).digest("hex").substring(0,12)}function et(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,fa),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
|
+
`),false}}moveFile(e,r){try{renameSync(e,r);}catch{try{copyFileSync(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 Er=".testrelic",ba="testrelic-config.json",xa=".testrelic",wa=5,ka=new Set(["__proto__","constructor","prototype"]),Mr=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,uploadBudgetMs:12e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${Er}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),Ca={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function Lr(t){let e=resolve(t);for(let r=0;r<=wa;r++){let n=join(e,Er,ba);if(existsSync(n))try{if(statSync(n).isFile())return n}catch{}let s=join(e,xa);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 Nr(t){try{let e=readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!Dr(r)?null:r}catch{return null}}function Dr(t){for(let e of Object.keys(t)){if(ka.has(e))return false;let r=t[e];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!Dr(r))return false}return true}function Fr(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 tt(t){let e=Object.create(null);for(let r of Object.keys(t)){let n=t[r];typeof n=="string"&&n.startsWith("$")?e[r]=Fr(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?e[r]=tt(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=Ca[n];return !s||r<=0?null:r*s}function Br(t,e){let r=Object.create(null);if(Object.assign(r,Mr),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("$")?Fr(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:Mr}var Aa=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],_a=["authorization","cookie","set-cookie","x-api-key"],Ia=["password","secret","token","apiKey","api_key"];function Or(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??[..._a],e.redactBodyFields=t?.redactBodyFields??[...Ia],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function qr(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=[...Aa,...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=Lr(process.cwd()),s=n?Nr(n):null,a=s?tt(s):null,o=Br(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.8.0";function Hr(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 Ur(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
|
|
7
|
+
`)}catch{return null}}function Ur(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 Pa(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 Ea(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 La(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 Na(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 Da(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 Fa=[Pa,Ea,La,Na,Da];function V(t){let e=process.env;for(let r of Fa){let n=r(e);if(n)return n}return null}var rt=`
|
|
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;
|
|
@@ -2888,6 +2888,10 @@ function _updateCard(cls,val){
|
|
|
2888
2888
|
/* Percentages of the capture box: the image may be rendered at any size. */
|
|
2889
2889
|
function domBoxStyle(rect,box){
|
|
2890
2890
|
if(!rect||!box||!box[2]||!box[3])return null;
|
|
2891
|
+
/* A degenerate rect draws a hairline that points at nothing. The platform
|
|
2892
|
+
and Studio drop it; this copy did not, which is exactly the kind of
|
|
2893
|
+
quiet divergence the shared vectors exist to catch. */
|
|
2894
|
+
if(rect[2]<=0||rect[3]<=0)return null;
|
|
2891
2895
|
var left=((rect[0]-box[0])/box[2])*100;
|
|
2892
2896
|
var top=((rect[1]-box[1])/box[3])*100;
|
|
2893
2897
|
var width=(rect[2]/box[2])*100;
|
|
@@ -3999,7 +4003,7 @@ function _updateCard(cls,val){
|
|
|
3999
4003
|
@media (max-width:1100px){
|
|
4000
4004
|
.tband-3,.tband-2{grid-template-columns:1fr}
|
|
4001
4005
|
}
|
|
4002
|
-
`;var
|
|
4006
|
+
`;var Ba=`
|
|
4003
4007
|
(function(){
|
|
4004
4008
|
var data=JSON.parse(document.getElementById('report-data').textContent);
|
|
4005
4009
|
${at}
|
|
@@ -4078,7 +4082,7 @@ ${""}
|
|
|
4078
4082
|
</aside>
|
|
4079
4083
|
<script id="report-data" type="application/json">${n}</script>
|
|
4080
4084
|
${s?`<script id="artifact-manifest-data" type="application/json">${s}</script>`:""}
|
|
4081
|
-
<script>${
|
|
4085
|
+
<script>${Ba}</script>
|
|
4082
4086
|
</body>
|
|
4083
4087
|
</html>`}function kt(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
4088
|
"schemaVersion":"2.0",
|
|
@@ -4248,38 +4252,38 @@ ${o?`<script id="artifact-manifest-data" type="application/json">${o}</script>`:
|
|
|
4248
4252
|
</body>
|
|
4249
4253
|
</html>`}function Ct(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
4254
|
`);});}catch{}}var jr=join(tmpdir(),"testrelic-data"),H=class{constructor(e){this.count=0;this.closed=false;mkdirSync(jr,{recursive:true}),this.filePath=join(jr,`${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 $r(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 Jr=/^[a-f0-9]{12}$/,Rt=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Yr=500;function R(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function Xr(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 Zr(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 Qr(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 en(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(Yr,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,g=a.get("sort")??"file",p=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(g){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=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 tn(t,e,r,n){if(!Jr.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 rn(t,e,r,n,s){if(!Jr.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(Yr,Math.max(1,parseInt(d.get("pageSize")??"50",10)||50)),u,g=join(r,"tests",n,"meta.json");if(existsSync(g))try{let f=JSON.parse(readFileSync(g,"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 p=await $r(o,l,c,u);R(e,200,p);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}function nn(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 sn(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()||!Rt.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 an(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()||!Rt.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 on(t,e,r,n){if(!Rt.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 ln(t,e,r){R(e,200,{status:"shutting_down"}),r.close();}function At(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=Wa[s]??"application/octet-stream",o=$a(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"}),Gr(createReadStream(r,{start:o.start,end:o.end}),e);return}e.writeHead(200,{"Content-Type":a,"Content-Length":n,"Accept-Ranges":"bytes"}),Gr(createReadStream(r),e);}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function Gr(t,e){t.on("error",()=>{t.destroy(),e.destroy();}),e.on("close",()=>{t.destroy();}),t.pipe(e);}function $a(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 Wa={".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 Ya=9323,Xa=10,Za=1800*1e3;function me(t,e){return new Promise((r,n)=>{let s=e?.port??Ya,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();},Za);}let c=e?.htmlPath??null;if(!c){let p=dirname(t);try{let f=readdirSync(p).find(m=>m.endsWith(".html"));f&&(c=join(p,f));}catch{}}let u=createServer((p,f)=>{if(l(),Xr(f),p.method==="OPTIONS"){f.writeHead(204),f.end();return}let m;try{m=new URL(p.url??"/",`http://${p.headers.host??"localhost"}`).pathname;}catch{R(f,400,{error:"Invalid URL"});return}if(p.method==="GET"&&(m==="/"||m==="/index.html")){if(c&&existsSync(c)){At(p,f,c);return}R(f,404,{error:"HTML report not found"});return}if(p.method==="GET"&&m==="/api/health"){Zr(p,f,t,a);return}if(p.method==="GET"&&m==="/api/summary"){Qr(p,f,t);return}if(p.method==="GET"&&m==="/api/tests"){en(p,f,t);return}if(p.method==="GET"&&m==="/api/files"){nn(p,f,t);return}let h=m.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(p.method==="GET"&&h){rn(p,f,t,h[1],h[2]);return}let v=m.match(/^\/api\/tests\/([a-f0-9]+)$/);if(p.method==="GET"&&v){tn(p,f,t,v[1]);return}if(p.method==="GET"&&m==="/api/artifacts"){sn(p,f,d);return}if(p.method==="DELETE"&&m==="/api/artifacts"){an(p,f,d);return}let y=m.match(/^\/api\/artifacts\/(.+)$/);if(p.method==="DELETE"&&y){on(p,f,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(f,400,{error:"Invalid path"});return}At(p,f,join(d,b));return}if(p.method==="POST"&&m==="/api/shutdown"){ln(p,f,u);return}R(f,404,{error:"Not found"});});function g(p){let f=m=>{m.code==="EADDRINUSE"&&i<Xa?(i++,g(p+1)):n(m);};u.once("error",f),u.listen(p,"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());})});});}g(s);})}async function dn(t){let e=await me(t);return {port:e.port,dispose:e.dispose}}function ti(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return zr(n,e,s)}async function It(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),f=join(p,".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=kt(l,c,null,u);}else o=ti(t,null,r);let g=i+".tmp";if(writeFileSync(g,o,"utf-8"),renameSync(g,i),a){if(t.ci===null){let p=dirname(e.outputPath),f=join(p,".testrelic-report"),m=resolve(i);try{if(await ni(),n=await si(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(`
|
|
4255
|
+
`;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 $r(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 Jr=/^[a-f0-9]{12}$/,Rt=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Yr=500;function R(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function Xr(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 Te(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 Zr(t,e,r,n){let s=Te(join(r,"index.json"));R(e,200,{status:"ok",reportMode:"streaming",testCount:s?.length??0,uptime:Math.floor((Date.now()-n)/1e3)});}function Qr(t,e,r){let n=Te(join(r,"summary.json"));if(!n){R(e,404,{error:"Summary not found"});return}R(e,200,n);}function en(t,e,r){let n=Te(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(Yr,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,h=a.get("sort")??"file",f=a.get("order")==="desc"?-1:1,p=n;d&&d.length>0&&(p=p.filter(b=>d.includes(b.status))),l&&(p=p.filter(b=>b.filePath===l||b.filePath.startsWith(l+"/"))),c&&(p=p.filter(b=>b.title.toLowerCase().includes(c)||b.filePath.toLowerCase().includes(c))),u&&u.length>0&&(p=p.filter(b=>u.some(k=>b.tags.includes(k)))),p=[...p].sort((b,k)=>{let T=0;switch(h){case "duration":T=b.duration-k.duration;break;case "status":T=b.status.localeCompare(k.status);break;case "title":T=b.title.localeCompare(k.title);break;default:T=b.filePath.localeCompare(k.filePath);break}return T*f});let m=p.length,g=Math.max(1,Math.ceil(m/i)),v=(o-1)*i,y=p.slice(v,v+i);R(e,200,{tests:y,pagination:{page:o,pageSize:i,totalItems:m,totalPages:g},filters:{status:d,file:l,search:c,tag:u}});}function tn(t,e,r,n){if(!Jr.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 rn(t,e,r,n,s){if(!Jr.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(Yr,Math.max(1,parseInt(d.get("pageSize")??"50",10)||50)),u,h=join(r,"tests",n,"meta.json");if(existsSync(h))try{let p=JSON.parse(readFileSync(h,"utf-8"));switch(s){case "network":u=p.networkRequestsCount;break;case "console":u=p.consoleLogsCount;break;case "api-calls":u=p.apiCallsCount;break}}catch{}let f=await $r(o,l,c,u);R(e,200,f);}catch(i){R(e,500,{error:i instanceof Error?i.message:String(i)});}}function nn(t,e,r){let n=Te(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 sn(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()||!Rt.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 an(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()||!Rt.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 on(t,e,r,n){if(!Rt.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 ln(t,e,r){R(e,200,{status:"shutting_down"}),r.close();}function At(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=Ya[s]??"application/octet-stream",o=Ja(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"}),Gr(createReadStream(r,{start:o.start,end:o.end}),e);return}e.writeHead(200,{"Content-Type":a,"Content-Length":n,"Accept-Ranges":"bytes"}),Gr(createReadStream(r),e);}catch(n){R(e,500,{error:n instanceof Error?n.message:String(n)});}}function Gr(t,e){t.on("error",()=>{t.destroy(),e.destroy();}),e.on("close",()=>{t.destroy();}),t.pipe(e);}function Ja(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 Ya={".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 ei=9323,ti=10,ri=1800*1e3;function me(t,e){return new Promise((r,n)=>{let s=e?.port??ei,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();},ri);}let c=e?.htmlPath??null;if(!c){let f=dirname(t);try{let p=readdirSync(f).find(m=>m.endsWith(".html"));p&&(c=join(f,p));}catch{}}let u=createServer((f,p)=>{if(l(),Xr(p),f.method==="OPTIONS"){p.writeHead(204),p.end();return}let m;try{m=new URL(f.url??"/",`http://${f.headers.host??"localhost"}`).pathname;}catch{R(p,400,{error:"Invalid URL"});return}if(f.method==="GET"&&(m==="/"||m==="/index.html")){if(c&&existsSync(c)){At(f,p,c);return}R(p,404,{error:"HTML report not found"});return}if(f.method==="GET"&&m==="/api/health"){Zr(f,p,t,a);return}if(f.method==="GET"&&m==="/api/summary"){Qr(f,p,t);return}if(f.method==="GET"&&m==="/api/tests"){en(f,p,t);return}if(f.method==="GET"&&m==="/api/files"){nn(f,p,t);return}let g=m.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(f.method==="GET"&&g){rn(f,p,t,g[1],g[2]);return}let v=m.match(/^\/api\/tests\/([a-f0-9]+)$/);if(f.method==="GET"&&v){tn(f,p,t,v[1]);return}if(f.method==="GET"&&m==="/api/artifacts"){sn(f,p,d);return}if(f.method==="DELETE"&&m==="/api/artifacts"){an(f,p,d);return}let y=m.match(/^\/api\/artifacts\/(.+)$/);if(f.method==="DELETE"&&y){on(f,p,d,decodeURIComponent(y[1]));return}if(f.method==="GET"&&m.startsWith("/artifacts/")){let b=decodeURIComponent(m.slice(11));if(b.includes("..")||b.includes("\0")){R(p,400,{error:"Invalid path"});return}At(f,p,join(d,b));return}if(f.method==="POST"&&m==="/api/shutdown"){ln(f,p,u);return}R(p,404,{error:"Not found"});});function h(f){let p=m=>{m.code==="EADDRINUSE"&&i<ti?(i++,h(f+1)):n(m);};u.once("error",p),u.listen(f,"127.0.0.1",()=>{u.removeListener("error",p);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(g=>{clearTimeout(o),u.close(()=>g());})});});}h(s);})}async function dn(t){let e=await me(t);return {port:e.port,dispose:e.dispose}}function ai(t,e,r){let n=JSON.stringify(t),s=r?JSON.stringify(r):null;return zr(n,e,s)}async function It(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 f=dirname(e.outputPath),p=join(f,".testrelic-report");try{let m=join(p,"index-compact.json"),g=join(p,"index.json");existsSync(m)?c=readFileSync(m,"utf-8"):existsSync(g)&&(c=readFileSync(g,"utf-8"));}catch{}u=r?JSON.stringify(r):null,o=kt(l,c,null,u);}else o=ai(t,null,r);let h=i+".tmp";if(writeFileSync(h,o,"utf-8"),renameSync(h,i),a){if(t.ci===null){let f=dirname(e.outputPath),p=join(f,".testrelic-report"),m=resolve(i);try{if(await oi(),n=await li(p),!n){s=await me(p,{htmlPath:m}),n=s.port;let g=setInterval(()=>{},6e4),v=()=>{clearInterval(g),s?.dispose();};process.on("SIGINT",v),process.on("SIGTERM",v),setTimeout(v,1800*1e3).unref();}if(n){process.stderr.write(`
|
|
4252
4256
|
Report server: http://127.0.0.1:${n}
|
|
4253
|
-
`);try{let
|
|
4254
|
-
`);}}var Ie=9323,gn=10;async function ri(){for(let t=Ie;t<Ie+gn;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 ni(){for(let t=Ie;t<Ie+gn;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 si(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(),ri().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 hn=Buffer.from([137,80,78,71,13,10,26,10]),ai=16,ii=20,Me=24;function mn(t){if(t.length<Me||!t.subarray(0,hn.length).equals(hn))return null;let e=t.readUInt32BE(ai),r=t.readUInt32BE(ii);return e===0||r===0?null:{width:e,height:r}}var oi=/(\d+) pixels \(ratio [\d.]+ of all image pixels\) are different/,vn=/Expected an image (\d+)px by (\d+)px, received (\d+)px by (\d+)px/;function yn(t){return t?vn.test(t):false}var li=/^\s*Snapshot:\s*(.+?)\s*$/m;function bn(t){if(!t)return {};let e={},r=oi.exec(t);if(r){let a=Number.parseInt(r[1],10);Number.isFinite(a)&&(e.diffPixels=a);}let n=vn.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=li.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 hi=20,Mt=0,Pt=[];async function ve(t,e){Mt>=hi&&await new Promise(r=>Pt.push(r)),Mt++;try{return await copyFile(t,e),!0}catch{return false}finally{Mt--,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 Et(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 mi=8;function Tn(t,e,r){let n=Et(t),s=r?Et(r).substring(0,mi):"";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),g=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=`${g.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=`${g.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=`${g.join("/")}/${m}`;}return !p.screenshot&&!p.video&&!p.trace?null:p}var Lt="visual",vi=6;function yi(t){let e=createHash("sha256").update(t).digest("hex").substring(0,vi);return `${Et(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 mn(r.subarray(0,n))}catch{return null}finally{if(e!==null)try{closeSync(e);}catch{}}}var bi=[{key:"expectedPath",dest:"baseline",field:"baseline"},{key:"actualPath",dest:"actual",field:"actual"},{key:"diffPath",dest:"diff",field:"diff"},{key:"previousPath",dest:"previous",field:"previous"}],xi=[{key:"baselineDomPath",dest:"baseline.dom.json",field:"baselineDom"},{key:"actualDomPath",dest:"actual.dom.json",field:"actualDom"}];function wi(t,e,r,n){let s=yi(t.name),a=join(e,s);try{mkdirSync(a,{recursive:!0});}catch{return null}let o={},i=false;for(let p of bi){let f=t[p.key];if(!f||!existsSync(f))continue;let m=extname(f)||".png",h=`${p.dest}${m}`;W.push(ve(f,join(a,h)).then(()=>{})),o[p.field]=`${r}/${Lt}/${s}/${h}`,i=true;}let d=t.dom;if(d)for(let p of xi){let f=d[p.key];!f||!existsSync(f)||(W.push(ve(f,join(a,p.dest)).then(()=>{})),o[p.field]=`${r}/${Lt}/${s}/${p.dest}`);}if(!i)return null;let l=t.expectedPath?wn(t.expectedPath):t.actualPath?wn(t.actualPath):null,c=xn(t.diffPixels,l),u=t.committedPath??t.expectedPath,g=u?relative(n,u).replace(/\\/g,"/"):void 0;return {name:t.name,status:t.status,source:t.source,...o,...g?{baselinePath:g}:{},...l?{width:l.width,height:l.height}:{},...t.actualWidth!==void 0?{actualWidth:t.actualWidth}:{},...t.actualHeight!==void 0?{actualHeight:t.actualHeight}:{},...t.diffPixels!==void 0?{diffPixels:t.diffPixels}:{},...c!==void 0?{diffPixelRatio:c}:{},...d?{domChanges:d.changes,domChangeCount:d.total,domRootCauses:d.rootCauses,domTruncated:d.truncated,domCaptureBox:d.captureBox}:{}}}function Rn(t,e,r,n,s,a,o=process.cwd()){if(t.length===0)return null;let i=Tn(e,r,a),d=s?["artifacts",s,i]:["artifacts",i],l=join(n,...d,Lt),c=d.join("/");try{mkdirSync(l,{recursive:!0});}catch{return null}let u=[];for(let g of t){let p=wi(g,l,c,o);p&&u.push(p);}return u.length>0?u: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,g=[],p=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(g.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),g.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:g,truncatedNodes:p}}var Ai=["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"],_i={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"},Ii=["color","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-transform"],Mi=1024*1024,Pi=1500,Ei=200;async function Li(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 Li(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:Ai,defaults:_i,inherited:Ii,maxNodes:e.maxNodes??Pi,maxText:e.maxText??Ei,maskBoxes:r,viewportBox:n,fullPage:t.fullPage===!0};return await t.target.evaluate(An,s)}catch{return null}}function In(t,e=Mi){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 Ni(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 Ni(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 Di=new Set(["moved","resized"]);function Ee(t){return t.some(e=>!Di.has(e))}function Dt(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 Fi(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 Bi(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 Oi(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 g=r.get(u.p);if(g&&g.t!==u.t){s.push(u);continue}g&&!a.has(g)?(a.add(g),n.push({before:g,after:u})):s.push(u);}let o=t.filter(u=>!a.has(u)),i=new Map;for(let u of o){let g=Ln(u);if(!g)continue;let p=i.get(g);p?p.push(u):i.set(g,[u]);}let d=[],l=new Set;for(let u of s){let g=Ln(u),f=(g?i.get(g):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 qi(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 Ft(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}=Oi(o,i),u=[];for(let{before:f,after:m}of d){let h=Fi(f,m),v=a?Bi(f,m):[];v.length>0&&h.push("restyled");let y=qi(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=Ft(m,e.captureBox);u.push({score:k,change:{path:m.p,label:Dt(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=Ft(f,e.captureBox);u.push({score:m,change:{path:f.p,label:Dt(f),kinds:["added"],rect:f.r,areaPct:m}});}for(let f of l){let m=Ft(f,t.captureBox);u.push({score:m,change:{path:f.p,label:Dt(f),kinds:["removed"],baselineRect:f.r,areaPct:m}});}let g=u.filter(f=>Ee(f.change.kinds)).length;return u.sort((f,m)=>{if(g>0){let h=Ee(f.change.kinds)?1:0,v=Ee(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,...g>0&&!Ee(f.change.kinds)?{consequence:true}:{}})),total:u.length,rootCauses:g}}var Hi="__testrelic_snapshot_path_probe__.png",Dn=Symbol.for("testrelic.snapshotPathWarned");function Ui(){let t=globalThis,e=t[Dn];return e||(e={warned:false},t[Dn]=e),e}function Le(t){try{let e=t.snapshotPath(Hi,{kind:"screenshot"});return typeof e=="string"&&!e.includes("[object Object]")}catch{return false}}function Ne(t){let e=Ui();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 Bt="testrelic-visual-dom",
|
|
4257
|
+
`);try{let g=kt(l,c,n,u),v=i+".tmp";writeFileSync(v,g,"utf-8"),renameSync(v,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let f=dirname(e.outputPath),p=join(f,"artifacts");if(existsSync(p))try{let m=await dn(p);n=m.port,process.on("exit",()=>{m.dispose();});}catch{}}if(e.openReport&&t.ci===null)if(a&&n)Ct(`http://127.0.0.1:${n}`);else {let f=resolve(i);Ct(f);}}catch(n){process.stderr.write(`[testrelic] Failed to write HTML report: ${n instanceof Error?n.message:String(n)}
|
|
4258
|
+
`);}}var Ie=9323,gn=10;async function ii(){for(let t=Ie;t<Ie+gn;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 oi(){for(let t=Ie;t<Ie+gn;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 li(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(),ii().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 hn=Buffer.from([137,80,78,71,13,10,26,10]),di=16,ci=20,Me=24;function mn(t){if(t.length<Me||!t.subarray(0,hn.length).equals(hn))return null;let e=t.readUInt32BE(di),r=t.readUInt32BE(ci);return e===0||r===0?null:{width:e,height:r}}var ui=/(\d+) pixels \(ratio [\d.]+ of all image pixels\) are different/,vn=/Expected an image (\d+)px by (\d+)px, received (\d+)px by (\d+)px/;function yn(t){return t?vn.test(t):false}var pi=/^\s*Snapshot:\s*(.+?)\s*$/m;function bn(t){if(!t)return {};let e={},r=ui.exec(t);if(r){let a=Number.parseInt(r[1],10);Number.isFinite(a)&&(e.diffPixels=a);}let n=vn.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=pi.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 bi=20,Mt=0,Pt=[];async function ve(t,e){Mt>=bi&&await new Promise(r=>Pt.push(r)),Mt++;try{return await copyFile(t,e),!0}catch{return false}finally{Mt--,Pt.length>0&&Pt.shift()();}}var W=[];async function Cn(){W.length!==0&&(await Promise.allSettled(W),W.length=0);}function Sn(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 Et(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 xi=8;function Tn(t,e,r){let n=Et(t),s=r?Et(r).substring(0,xi):"";return s&&(n+=`--${s}`),e>0&&(n+=`--retry-${e}`),n}function Rn(t,e,r,n,s,a){let o=t.find(p=>p.name==="screenshot"&&p.path),i=t.find(p=>p.name==="video"&&p.path),d=t.find(p=>p.name==="trace"&&p.path);if(!o&&!i&&!d)return null;let l=Tn(e,r,a),c=s?["artifacts",s,l]:["artifacts",l],u=join(n,...c),h=c,f={};try{mkdirSync(u,{recursive:!0});}catch{return null}if(o?.path&&existsSync(o.path)){let m=`screenshot${extname(o.path)||".png"}`,g=join(u,m);W.push(ve(o.path,g).then(()=>{})),f.screenshot=`${h.join("/")}/${m}`;}if(i?.path&&existsSync(i.path)){let m=`video${extname(i.path)||".webm"}`,g=join(u,m);W.push(ve(i.path,g).then(()=>{})),f.video=`${h.join("/")}/${m}`;}if(d?.path&&existsSync(d.path)){let m=`trace${extname(d.path)||".zip"}`,g=join(u,m);W.push(ve(d.path,g).then(()=>{})),f.trace=`${h.join("/")}/${m}`;}return !f.screenshot&&!f.video&&!f.trace?null:f}var Lt="visual",wi=6;function ki(t){let e=createHash("sha256").update(t).digest("hex").substring(0,wi);return `${Et(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 mn(r.subarray(0,n))}catch{return null}finally{if(e!==null)try{closeSync(e);}catch{}}}var kn=[{key:"expectedPath",dest:"baseline",field:"baseline"},{key:"actualPath",dest:"actual",field:"actual"},{key:"diffPath",dest:"diff",field:"diff"},{key:"previousPath",dest:"previous",field:"previous"}],Ci=[{key:"baselineDomPath",dest:"baseline.dom.json",field:"baselineDom"},{key:"actualDomPath",dest:"actual.dom.json",field:"actualDom"}];function Si(t,e,r,n){let s=ki(t.name),a=join(e,s),o=kn.some(p=>t[p.key]);if(o||t.dom)try{mkdirSync(a,{recursive:!0});}catch{return null}let i={},d=false;for(let p of kn){let m=t[p.key];if(!m||!existsSync(m))continue;let g=extname(m)||".png",v=`${p.dest}${g}`;W.push(ve(m,join(a,v)).then(()=>{})),i[p.field]=`${r}/${Lt}/${s}/${v}`,d=true;}let l=t.dom;if(l)for(let p of Ci){let m=l[p.key];!m||!existsSync(m)||(W.push(ve(m,join(a,p.dest)).then(()=>{})),i[p.field]=`${r}/${Lt}/${s}/${p.dest}`);}if(!d&&o)return null;let c=t.expectedPath?wn(t.expectedPath):t.actualPath?wn(t.actualPath):null,u=xn(t.diffPixels,c),h=t.committedPath??t.expectedPath,f=h?relative(n,h).replace(/\\/g,"/"):void 0;return {name:t.name,status:t.status,source:t.source,...i,...f?{baselinePath:f}:{},...c?{width:c.width,height:c.height}:{},...t.actualWidth!==void 0?{actualWidth:t.actualWidth}:{},...t.actualHeight!==void 0?{actualHeight:t.actualHeight}:{},...t.diffPixels!==void 0?{diffPixels:t.diffPixels}:{},...u!==void 0?{diffPixelRatio:u}:{},...l?{domChanges:l.changes,domChangeCount:l.total,domRootCauses:l.rootCauses,domTruncated:l.truncated,domCaptureBox:l.captureBox}:{}}}function An(t,e,r,n,s,a,o=process.cwd()){if(t.length===0)return null;let i=Tn(e,r,a),d=s?["artifacts",s,i]:["artifacts",i],l=join(n,...d,Lt),c=d.join("/");try{mkdirSync(l,{recursive:!0});}catch{return null}let u=[];for(let h of t){let f=Si(h,l,c,o);f&&u.push(f);}return u.length>0?u:null}function _n(t){let{styleProps:e,defaults:r,inherited:n,maxNodes:s,maxText:a,maskBoxes:o,viewportBox:i,fullPage:d}=t,l={};for(let S=0;S<n.length;S++)l[n[S]]=true;let c=window.scrollX||window.pageXOffset||0,u=window.scrollY||window.pageYOffset||0,h=[],f=0,p=[];for(let S=0;S<o.length;S++){let w=o[S];p.push([w[0]+c,w[1]+u,w[2],w[3]]);}function m(S,w,A,x){for(let C=0;C<p.length;C++){let _=p[C];if(S<_[0]+_[2]&&S+A>_[0]&&w<_[1]+_[3]&&w+x>_[1])return true}return false}function g(S){let w=S.parentElement;if(!w)return 0;let A=w.children,x=0;for(let C=0;C<A.length;C++){let _=A[C];if(_===S)break;_.tagName===S.tagName&&x++;}return x}function v(S){let w="",A=S.childNodes;for(let x=0;x<A.length;x++){let C=A[x];C.nodeType===3&&(w+=C.nodeValue??"");}return w=w.replace(/\s+/g," ").trim(),w.length>a?w.slice(0,a):w}function y(S,w){let A;for(let x=0;x<e.length;x++){let C=e[x],_=S.getPropertyValue(C);if(_){if(l[C]){if(w&&w.getPropertyValue(C)===_)continue}else if(r[C]===_)continue;A||(A={}),A[C]=_;}}return A}let b=[{el:document.body,parentPath:"",parentComputed:null}];for(;b.length>0;){let S=b.pop(),w=S.el,A=window.getComputedStyle(w);if(A.display==="none")continue;let x=w.tagName.toLowerCase(),C=w.id?"#"+w.id:S.parentPath?S.parentPath+">"+x+"["+g(w)+"]":x,_=w.children;for(let E=_.length-1;E>=0;E--)b.push({el:_[E],parentPath:C,parentComputed:A});if(A.visibility==="hidden")continue;let L=w.getBoundingClientRect();if(L.width<=0||L.height<=0)continue;if(h.length>=s){f++;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:x,r:[z,ce,ue,pe]};w.id&&(I.i=w.id);let M=w.getAttribute("class");M&&(I.c=M.replace(/\s+/g," ").trim());let N=v(w);N&&(I.x=N);let j=y(A,S.parentComputed);j&&(I.s=j),m(z,ce,ue,pe)&&(I.m=1),h.push(I);}let k=Math.max(document.documentElement.scrollWidth,window.innerWidth),T=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,T]: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:T},captureBox:P,nodes:h,truncatedNodes:f}}var Mi=["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"],Pi={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"},Ei=["color","font-family","font-size","font-weight","line-height","letter-spacing","text-align","text-transform"],Li=1024*1024,Ni=1500,Di=200;async function Fi(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 In(t){let e=t.config??{};try{let r=t.maskLocators?.length?await Fi(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:Mi,defaults:Pi,inherited:Ei,maxNodes:e.maxNodes??Ni,maxText:e.maxText??Di,maskBoxes:r,viewportBox:n,fullPage:t.fullPage===!0};return await t.target.evaluate(_n,s)}catch{return null}}function Mn(t,e=Li){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 Pn(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 Bi(e)?e:null}catch{return null}}function Ln(t,e){try{return mkdirSync(dirname(t),{recursive:!0}),writeFileSync(t,e,"utf-8"),!0}catch{return false}}function Bi(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 Oi=new Set(["moved","resized"]);function Ee(t){return t.some(e=>!Oi.has(e))}function Dt(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 qi(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 Hi(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 Nn(t){return t.i?"i:"+t.t+"#"+t.i:t.c?"c:"+t.t+"."+t.c:null}function Ui(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 h=r.get(u.p);if(h&&h.t!==u.t){s.push(u);continue}h&&!a.has(h)?(a.add(h),n.push({before:h,after:u})):s.push(u);}let o=t.filter(u=>!a.has(u)),i=new Map;for(let u of o){let h=Nn(u);if(!h)continue;let f=i.get(h);f?f.push(u):i.set(h,[u]);}let d=[],l=new Set;for(let u of s){let h=Nn(u),p=(h?i.get(h):void 0)?.find(m=>!l.has(m));p?(l.add(p),n.push({before:p,after:u})):d.push(u);}let c=o.filter(u=>!l.has(u));return {pairs:n,removed:c,added:d}}function zi(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 Ft(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 Dn(t,e,r={}){let n=r.maxChanges??50,s=r.includeText!==false,a=r.includeStyles!==false,o=t.nodes.filter(p=>p.m!==1),i=e.nodes.filter(p=>p.m!==1),{pairs:d,removed:l,added:c}=Ui(o,i),u=[];for(let{before:p,after:m}of d){let g=qi(p,m),v=a?Hi(p,m):[];v.length>0&&g.push("restyled");let y=zi(p,m);y.length>0&&g.push("attrs");let b=s&&(p.x??"")!==(m.x??"");if(b&&g.push("text"),g.length===0)continue;let k=Ft(m,e.captureBox);u.push({score:k,change:{path:m.p,label:Dt(m),kinds:g,rect:m.r,baselineRect:p.r,areaPct:k,...y.length>0?{attrs:y}:{},...v.length>0?{styles:v}:{},...b?{text:{from:p.x??"",to:m.x??""}}:{}}});}for(let p of c){let m=Ft(p,e.captureBox);u.push({score:m,change:{path:p.p,label:Dt(p),kinds:["added"],rect:p.r,areaPct:m}});}for(let p of l){let m=Ft(p,t.captureBox);u.push({score:m,change:{path:p.p,label:Dt(p),kinds:["removed"],baselineRect:p.r,areaPct:m}});}let h=u.filter(p=>Ee(p.change.kinds)).length;return u.sort((p,m)=>{if(h>0){let g=Ee(p.change.kinds)?1:0,v=Ee(m.change.kinds)?1:0;if(g!==v)return v-g}return m.score-p.score}),{changes:u.slice(0,n).map((p,m)=>({rank:m+1,...p.change,...h>0&&!Ee(p.change.kinds)?{consequence:true}:{}})),total:u.length,rootCauses:h}}var ji="__testrelic_snapshot_path_probe__.png",Fn=Symbol.for("testrelic.snapshotPathWarned");function Vi(){let t=globalThis,e=t[Fn];return e||(e={warned:false},t[Fn]=e),e}function Le(t){try{let e=t.snapshotPath(ji,{kind:"screenshot"});return typeof e=="string"&&!e.includes("[object Object]")}catch{return false}}function Ne(t){let e=Vi();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.
|
|
4259
|
+
`));}var Bt="testrelic-visual-dom",Ji=new Set(["toHaveScreenshot","toMatchVisualBaseline"]);function Bn(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.boundingBox=="function"&&typeof e.page=="function"}function Yi(t){if(typeof t!="object"||t===null)return false;let e=t;return typeof e.evaluate=="function"&&typeof e.screenshot=="function"}function Xi(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 Zi(t){for(let e of t)if(typeof e=="object"&&e!==null&&!Array.isArray(e))return e;return {}}function Qi(t){let e=t.mask;return Array.isArray(e)?e.filter(r=>typeof r=="object"&&r!==null&&typeof r.boundingBox=="function"):[]}function eo(t){return /\.(png|jpg|jpeg)$/i.test(t)?t:`${t}.png`}var to=/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/;function ro(t,e,r){let n=t.attachments;for(let s=e;s<n.length;s++){let a=to.exec(n[s]?.name??"");if(a)return a[1]}return r}async function no(t){let e=Zi(t.args),r=Bn(t.received)?t.received:null,n=r?r.page():t.received;return In({target:n,bounded:r,maskLocators:Qi(e),fullPage:e.fullPage===true})}function so(t){let e=t.config?.updateSnapshots;return e==="all"||e==="changed"}async function ao(t,e){let r=Xi(t.args);if(!r)return;if(!Le(t.testInfo)){Ne("DOM comparison");return}let n=t.testInfo.snapshotPath(eo(r),{kind:"screenshot"}),s=Pn(n),a=ro(t.testInfo,t.attachedBefore,basename(n,extname(n))),o=Mn(e),d=so(t.testInfo)?null:En(s);if(!d){Ln(s,o.json);return}let{changes:l,total:c,rootCauses:u}=Dn(d,e),h;try{h=t.testInfo.outputPath(`${a}.actual.dom.json`),writeFileSync(h,o.json,"utf-8");}catch{h=void 0;}let f={stem:a,changes:l,total:c,rootCauses:u,truncated:o.truncatedBytes||e.truncatedNodes>0,captureBox:e.captureBox,...existsSync(s)?{baselineDomPath:s}:{},...h?{actualDomPath:h}:{}};await t.testInfo.attach(Bt,{body:Buffer.from(JSON.stringify([f])),contentType:"application/json"});}function On(t,e){let r=function(o,...i){let d=t(o,...i);return !(Bn(o)||Yi(o))||typeof d!="object"||d===null?d:new Proxy(d,{get(c,u,h){let f=Reflect.get(c,u,h);if(typeof u!="string"||!Ji.has(u)||typeof f!="function")return f;let p=f;return async function(...g){let v=e(),y=null,b=v?.attachments.length??0;if(v)try{y=await no({received:o,args:g,testInfo:v,attachedBefore:b});}catch{}try{return await p.apply(c,g)}finally{if(v&&y)try{await ao({received:o,args:g,testInfo:v,attachedBefore:b},y);}catch{}}}}})},n=t,s=r;for(let a of Object.keys(n))s[a]=n[a];return r}var Ot="testrelic-visual",io=/^(.+)-(expected|actual|diff|previous)(\.[A-Za-z0-9]+)$/;function oo(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){let a=co(s);a&&e.set(a.stem,a);}}catch{}return e}var lo=["passed","failed","new","updated"];function co(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"||!lo.includes(e.status)?null:{stem:e.stem,name:e.name,status:e.status,...typeof e.committedPath=="string"&&e.committedPath?{committedPath:e.committedPath}:{}}}function uo(t){let e=new Map;for(let r of t)if(!(r.name!==Bt||!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 po(t){let e=new Map;for(let r of t){if(!r.path)continue;let n=io.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 fo(t){return !!(t.actual&&(t.expected||t.diff))}function go(t,e,r){return t.diff||yn(r)?"failed":e?"updated":"new"}function ho(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 Un(t,e={}){if(t.length===0)return [];let r=oo(t),n=uo(t),s=po(t);if(s.size===0&&r.size===0)return [];let a=e.updatingSnapshots===true,o=[];for(let[i,d]of s){let l=r.get(i);!l&&!fo(d)||o.push({name:l?.name??i,status:l?.status??go(d,a,e.failureMessage),source:l?"toMatchVisualBaseline":"toHaveScreenshot",...d.expected?{expectedPath:d.expected}:{},...l?.committedPath?{committedPath:l.committedPath}:{},...d.actual?{actualPath:d.actual}:{},...d.diff?{diffPath:d.diff}:{},...d.previous?{previousPath:d.previous}:{},...n.has(i)?{dom:n.get(i)}:{}});}for(let[i,d]of r)s.has(i)||o.push({name:d.name,status:d.status,source:"toMatchVisualBaseline",...d.committedPath?{committedPath:d.committedPath}:{},...n.has(i)?{dom:n.get(i)}:{}});return mo(o,s,e.failureMessage)}function mo(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"&&qn(o)).map(o=>Hn(o,e)),a=ho(s,n.snapshotName);return a===null?[...t]:t.map(o=>qn(o)&&Hn(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 qn(t){return !!(t.expectedPath||t.actualPath||t.diffPath||t.previousPath)}function Hn(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 vo=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(vo,"")}function zn(t){return t==null?null:se(t)}var yo=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,bo="1.0",qt="visual";function Wn(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 xo(t){if(t.endsWith(".dom.json"))return "dom";let e=basename(t,extname(t));return e==="baseline"?"baseline":e==="diff"?"diff":Wn(t)}function wo(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:`${qt}/${r}/${s.name}`,type:xo(s.name),relativePath:`${e}/${qt}/${r}/${s.name}`,sizeBytes:a.size});}}catch{}return n}function Gn(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===qt){let l=join(t,o.name);for(let c of readdirSync(l,{withFileTypes:!0}))c.isDirectory()&&n.push(...wo(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:Wn(o.name),relativePath:`${s}/${o.name}`,sizeBytes:d.size});}}catch{}return {testName:r,files:n}}function ko(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=Gn(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 Kn(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(yo.test(d.name)){let l=ko(r,d.name);n.push({...l,isCurrentRun:d.name===e});}else {let l=Gn(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:bo,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:n,serverPort:null}}var _o=256;function Io(t){let e=resolve(t);for(let r=0;r<_o;r++){if(existsSync(join(e,".git")))return e;let n=dirname(e);if(n===e)return null;e=n;}return null}function Xn(t){try{let e=Io(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
4260
|
`).map(d=>d.trim()).some(d=>d===s||d===n))return;let a=`
|
|
4257
4261
|
# TestRelic test artifacts
|
|
4258
4262
|
${s}
|
|
4259
|
-
`;appendFileSync(r,a,"utf-8");}catch{}}var
|
|
4263
|
+
`;appendFileSync(r,a,"utf-8");}catch{}}var Zn=Symbol("testrelic.timeout"),Qn=3e4,Ht=12e4,Ut=6e4,es=15e3;async function Q(t,e,r){let n,s=new Promise(a=>{n=setTimeout(()=>a(Zn),e),typeof n?.unref=="function"&&n.unref();});try{let a=await Promise.race([t(),s]);if(a===Zn){process.stderr.write(`[testrelic] ${r} timed out after ${Math.round(e/1e3)}s \u2014 continuing without it. Your tests are unaffected.
|
|
4260
4264
|
`);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
|
|
4265
|
+
`);return}finally{n&&clearTimeout(n);}}function ns(t,e){let r=[];for(let n of t){let s=Mo(n),a=Po(n),o=Eo(n,s,a,e),i=Lo(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(No),Do(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 Mo(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 Po(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 Eo(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 Lo(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:rs(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:rs(s.requestBody)},response:o,...s.error?{error:s.error}:{},assertions:a,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title}})}function No(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?ts(t.callId)-ts(e.callId):0}function ts(t){let e=t.match(/(\d+)$/);return e?parseInt(e[1],10):0}function Do(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 rs(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 zt(t){try{let e=new URL(t);return e.origin+e.pathname}catch{return t}}function Fo(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 ss(t,e){let r=0,n=0,s=0,a=0,o=0;for(let x of t)switch(x.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 x of t)x.apiCalls&&i.push(...x.apiCalls);let d=i.length,l=new Set,c={},u={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},h=[];for(let x of i)l.add(zt(x.url)),c[x.method]=(c[x.method]??0)+1,u[Fo(x.responseStatusCode)]+=1,h.push(x.responseTimeMs);let f=null;if(h.length>0){let x=[...h].sort((_,L)=>_-L),C=x.reduce((_,L)=>_+L,0);f={avg:Math.round(C/x.length),min:x[0],max:x[x.length-1],p50:ee(x,50),p95:ee(x,95),p99:ee(x,99)};}let p=0,m=0,g=0;for(let x of t)if(x.apiAssertions)for(let C of x.apiAssertions)p++,C.status==="passed"?m++:g++;let v=0,y=new Set;for(let x of t){v+=x.navigations.length;for(let C of x.navigations)y.add(C.url);}let b=0,k={};function T(x){for(let C of x)b++,k[C.category]=(k[C.category]??0)+1,C.children.length>0&&T(C.children);}for(let x of t)x.actions&&T(x.actions);let P=0,S=0,w=0,A=0;for(let x of t)if(x.visual)for(let C of x.visual)P++,C.status==="failed"?S++:(C.status==="new"||C.status==="updated")&&w++,A+=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:f,totalAssertions:p,passedAssertions:m,failedAssertions:g,totalNavigations:v,uniqueNavigationUrls:y.size,totalTimelineSteps:e,totalActionSteps:b,actionStepsByCategory:k,visualChecks:P,visualFailures:S,visualNew:w,visualDomChanges:A}}function Bo(t){let e=56-t.length;return e>0?t+" ".repeat(e):t}function F(t){return `\u2502 ${Bo(t)} \u2502
|
|
4262
4266
|
`}function jt(t,e,r,n){if(n||t.total===0)return;let s=`\u250C${"\u2500".repeat(58)}\u2510
|
|
4263
4267
|
`,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,
|
|
4265
|
-
`,process.stderr.write(i);}var
|
|
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
|
|
4267
|
-
`),n=JSON.stringify(
|
|
4268
|
-
`),n=JSON.stringify(
|
|
4269
|
-
`),n=JSON.stringify(
|
|
4270
|
-
`),n=JSON.stringify(
|
|
4268
|
+
`,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,h])=>`${u}: ${h}`);l.length>0&&(i+=F(` ${l.join(" ")}`));let c=Object.entries(t.apiCallsByStatusRange).filter(([,u])=>u>0).map(([u,h])=>`${u}: ${h}`);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
|
|
4269
|
+
`,process.stderr.write(i);}var Oo=new Set(["pw:api","expect","test.step"]);function qo(t){return t==="expect"?"assertion":t==="test.step"?"custom_step":"ui_action"}function Vt(t,e,r){if(Oo.has(t.category)){let n=[];for(let a of t.steps)Vt(a,e,n);let s=t.startTime.getTime()-e.getTime();r.push({title:t.title,category:qo(t.category),timestamp:t.startTime.toISOString(),duration:t.duration,videoOffset:s>=0?s/1e3:null,status:t.error?"failed":"passed",error:zn(t.error?.message),children:n});}else for(let n of t.steps)Vt(n,e,r);}function as(t,e){let r=[];for(let n of t)Vt(n,e,r);return r}var zo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function os(t){let e=new URL(t);if(e.protocol!=="https:"&&!(e.protocol==="http:"&&zo.has(e.hostname)))throw createError(ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${e.protocol}//${e.hostname}`)}var jo=3e3;async function $t(t){let e=new AbortController,r=setTimeout(()=>e.abort(),jo);try{return (await fetch(`${t}/health`,{method:"GET",signal:e.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function ls(t){return new Promise(e=>setTimeout(e,t))}async function is(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 Wt(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 ls(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 is(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 is(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 Gt(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 ds(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 ls(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 cs(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 Ko=5e3;function K(t,e){try{return execSync(t,{cwd:e,timeout:Ko,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function us(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=Jo(t),o=a?be(a):null;return {branch:e,commitSha:r,commitMessage:n,commitAuthor:s,remoteUrl:o}}function Jo(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(`
|
|
4270
|
+
`)[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 ps(t){let e=t.split("/").filter(Boolean);return e[e.length-1]??t}function Kt(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=Kt(t);return e||`local/${basename(t)}`}var Yo=new Set(["smoke","regression","nightly","ci"]);function De(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&Yo.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 fs(t,e){let r=e+Math.ceil(Math.max(0,t)/1e3);return Math.min(6e5,Math.max(3e4,r))}var Fe=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 Qo=1048576,Be=[1e3,3e3,9e3],Oe=3,hs=3e4,el=90*1048576,tl=new Set(["e2e","mobile","unit"]);function Yt(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??[])tl.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 Xt(t,e,r,n,s,a){let o=a?.cloudPlatform?a.cloudPlatform:n?.provider&&n.provider!=="unknown"?n.provider:"local",i=De(),d=Yt(s),l=d.testType==="api"?d:null,c=l&&s?s.map(h=>h.apiProtocol?h:{...h,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 Jt(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function Zt(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:Jt(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:Jt(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 Qt(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:Jt(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 er(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 qe(t){return new Promise(e=>setTimeout(e,t))}function rl(t){let e={};for(let[r,n]of Object.entries(t))n!=null&&(e[r]=n);return e}async function ms(t,e,r,n=hs,s){for(let a=0;a<Oe;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<Oe-1){let d=i.headers.get("Retry-After"),l=d?parseInt(d,10)*1e3:Be[a];!isNaN(l)&&l>0?await qe(l):await qe(Be[a]);continue}if(i.status>=500&&a<Oe-1){await qe(Be[a]);continue}return i}catch{if(a<Oe-1){await qe(Be[a]);continue}return null}}return null}var nl=promisify(gzip);function gs(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 sl=["consoleLogs","networkRequests","apiCalls","actions","navigations","protocolAssertions","visual"];function al(t){if(!Array.isArray(t.tests))return t;let e=new Set(sl),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 il(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 tr(t,e=el){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.
|
|
4271
|
+
`),n=JSON.stringify(gs(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.
|
|
4272
|
+
`),n=JSON.stringify(gs(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.
|
|
4273
|
+
`),n=JSON.stringify(al(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.
|
|
4274
|
+
`),n=JSON.stringify(il(s)));}if(Buffer.byteLength(n,"utf-8")>Qo){r["Content-Encoding"]="gzip";let i=await nl(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 vs(t,e,r,n,s,a){let o=`${t}/runs`,{body:i,headers:d}=await tr(r);d.Authorization=`Bearer ${e}`;let l=await ms(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 ys(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(rl(r))},n??hs);return a.ok?{runId:(await a.json()).runId}:null}catch{return null}}function bs(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 xs(t,e,r,n){let s=`${t}/runs/${r}/finalize`;return (await ms(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)}))?.ok??false}function rr(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 ul="1.0.0",ws=10;function ks(t){return t instanceof Error?t.message:String(t)}function pl(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:ul,queuedAt:new Date(d).toISOString(),reason:n,retryCount:0,targetEndpoint:s,method:a,payload:o,headers:i},h=c+".tmp";writeFileSync(h,JSON.stringify(u,null,2),"utf-8"),renameSync(h,c);}catch(d){d.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
|
|
4271
4275
|
`):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
|
|
4272
|
-
`);}}async function
|
|
4273
|
-
`),unlinkSync(i);continue}d=c;}catch(l){process.stderr.write(`\u26A0 TestRelic: Skipping unreadable queue file ${o}: ${
|
|
4274
|
-
`);try{unlinkSync(i);}catch{}continue}try{let{body:l,headers:c}=await tr(d.payload),u={...d.headers,...c,Authorization:`Bearer ${r}`},
|
|
4275
|
-
`);try{renameSync(i,`${i}.failed`);}catch{try{unlinkSync(i);}catch{}}}else {process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 server returned HTTP ${
|
|
4276
|
-
`);return}}catch(l){process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 ${
|
|
4277
|
-
`);return}}}function
|
|
4278
|
-
`);return}try{if(
|
|
4276
|
+
`);}}async function Rs(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+=ws)s.push(n.slice(a,a+ws));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}
|
|
4277
|
+
`),unlinkSync(i);continue}d=c;}catch(l){process.stderr.write(`\u26A0 TestRelic: Skipping unreadable queue file ${o}: ${ks(l)}
|
|
4278
|
+
`);try{unlinkSync(i);}catch{}continue}try{let{body:l,headers:c}=await tr(d.payload),u={...d.headers,...c,Authorization:`Bearer ${r}`},h=await fetch(d.targetEndpoint,{method:d.method,headers:u,body:l});if(h.ok)unlinkSync(i);else if(pl(h.status)){process.stderr.write(`\u26A0 TestRelic: Queue entry ${o} rejected (HTTP ${h.status}) \u2014 moving aside; it will not be retried.
|
|
4279
|
+
`);try{renameSync(i,`${i}.failed`);}catch{try{unlinkSync(i);}catch{}}}else {process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 server returned HTTP ${h.status} for ${o}; will retry later.
|
|
4280
|
+
`);return}}catch(l){process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 ${ks(l)}; will retry later.
|
|
4281
|
+
`);return}}}function As(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 bl=3e5,xl=864e5,wl=6e4,_s=3e4,ar="https://platform.testrelic.ai/settings/api-keys";function Is(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.
|
|
4282
|
+
`);return}try{if(os(this.config.endpoint),this.gitMetadata=us(),!await $t(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
4283
|
`);return}let r=await Wt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(Gt(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
|
-
`),await this.resolveRepoId(),this.config.queueDirectory&&(
|
|
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()+
|
|
4282
|
-
`));}async dispose(){if(this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=null),this.flushPromise){try{await Promise.race([this.flushPromise,
|
|
4284
|
+
`),await this.resolveRepoId(),this.config.queueDirectory&&(As(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)}
|
|
4285
|
+
`);}}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()+bl<e)return true;if(!this.config||!this.authState.refreshToken)return this.switchToLocalMode("token_expired_no_refresh"),false;try{let r=await ds(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}).
|
|
4286
|
+
`));}async dispose(){if(this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=null),this.flushPromise){try{await Promise.race([this.flushPromise,Is(_s)]);}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
4287
|
\u2192 Manage keys: ${ar}
|
|
4284
4288
|
`);break;case "expired_key":this.setLocalMode("expired_api_key"),process.stderr.write(`\u26A0 TestRelic: API key has expired. Running in local mode.
|
|
4285
4289
|
\u2192 Generate a new key: ${ar}
|
|
@@ -4288,16 +4292,16 @@ ${s}
|
|
|
4288
4292
|
`);break;case "rate_limited":this.setLocalMode("rate_limited"),process.stderr.write(`\u26A0 TestRelic: Rate limited during authentication. Running in local mode.
|
|
4289
4293
|
`);break;case "timeout":this.setLocalMode("auth_timeout"),process.stderr.write(`\u26A0 TestRelic: Authentication timed out. Running in local mode.
|
|
4290
4294
|
`);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
|
|
4291
|
-
`);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?be(this.gitMetadata.remoteUrl):null,r=e?
|
|
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>
|
|
4293
|
-
`),this.startBackgroundFlush();}}}catch{}},
|
|
4294
|
-
`);}return
|
|
4295
|
-
`),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:c,apiCallsCount:u,apiStatusMix:
|
|
4296
|
-
`),{keyMap:a,visualKeyMap:o,total:l.length,uploaded:m}}async function ur(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},
|
|
4297
|
-
`).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function
|
|
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 gr(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
|
|
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&&rr(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=
|
|
4300
|
-
`)});if(I.length>0){let M=dirname(this.config.outputPath),N=u[u.length-1]??e.title;
|
|
4295
|
+
`);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?be(this.gitMetadata.remoteUrl):null,r=e?ps(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 cs(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&&!Kt(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
|
|
4296
|
+
`);}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>xl)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([Rs(r,n,e),Is(_s)]).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 $t(e))return;if(this.config?.apiKey){let n=await Wt(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!Gt(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.
|
|
4297
|
+
`),this.startBackgroundFlush();}}}catch{}},wl),typeof this.healthCheckTimer?.unref=="function"&&this.healthCheckTimer.unref();}};function Tl(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 Ms(t,e,r,n){let s=[],a=[],o=null,i=0,d=null,l=0,c=null,u=0,h=null,f=t.filter(g=>g.name===ATTACHMENT_NAME&&g.body),p=false;if(f.length>0)for(let g of f)try{let v=JSON.parse(g.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),h=Tl(h,v.apiStatusMix),p=!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),p=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
|
|
4298
|
+
`);}return p||(s=e.filter(g=>g.type==="lambdatest-navigation"&&g.description).map(g=>{try{return JSON.parse(g.description)}catch{return null}}).filter(g=>g!==null)),s.length===0&&i===0&&u===0&&!n&&!p&&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.
|
|
4299
|
+
`),{navigations:s,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:c,apiCallsCount:u,apiStatusMix:h}}function Ue(t=process.env){let e=Rl(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 Rl(t){if(!t)return;let e=t.toLowerCase().trim();if(e==="browserstack"||e==="bs")return "browserstack";if(e==="lambdatest"||e==="lt")return "lambdatest"}var Pl=5,ze=[1e3,3e3,9e3],ie=3,lr=3e4,El={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip",".json":"application/json"},ir=0,or=[];async function Ll(){ir>=Pl&&await new Promise(t=>or.push(t)),ir++;}function Nl(){ir--,or.length>0&&or.shift()();}async function je(t){return new Promise(e=>setTimeout(e,t))}function Dl(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return El[e]??"application/octet-stream"}function Fl(t){try{return statSync(t).size}catch{return 0}}async function Bl(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},lr);if(d.ok)return await d.json();if(d.status>=500&&i<ie-1){await je(ze[i]);continue}return null}catch{if(i<ie-1){await je(ze[i]);continue}return null}return null}async function Ol(t,e,r,n){let s=fs(n,lr);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 je(ze[a]);continue}return !1}catch{if(a<ie-1){await je(ze[a]);continue}return false}return false}async function ql(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})},lr)).ok}catch{return false}}async function Hl(t,e,r,n){let s=Fl(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=Dl(r.filePath);await Ll();try{let o=await Bl(t,e,r,s,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Ol(o.uploadUrl,r.filePath,a,s))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let d=await ql(t,e,o.artifactId);return {success:d,storageKey:o.storageKey,artifactId:o.artifactId,error:d?null:"confirm_failed"}}finally{Nl();}}async function Ps(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 Hl(t,e,i,n);a.set(i.filePath,d);});return await Promise.allSettled(o),a}function cr(t){let r=t.getGitMetadata()?.remoteUrl;return r?be(r):t.getConfig()?.projectName??xe(process.cwd())}async function Es(t,e,r,n,s){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=V(),d=Ue(),l=De();return (await ys(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:cr(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 zl=[{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"}],jl=true,Vl=50,dr={keyMap:new Map,visualKeyMap:new Map,total:0,uploaded:0};async function $l(t,e,r,n,s){let a=new Map,o=new Map;if(!(e?.uploadArtifacts??jl)||!await t.ensureValidToken())return dr;let l=[],c=new Map,u=new Map;for(let g of n){if(g.artifacts.screenshot){let y=join(g.outputDir,g.artifacts.screenshot);l.push({filePath:y,runId:r,testId:g.testId,type:"screenshot"}),c.set(y,{testId:g.testId,field:"screenshot"});}if(g.artifacts.video){let y=join(g.outputDir,g.artifacts.video);l.push({filePath:y,runId:r,testId:g.testId,type:"video"}),c.set(y,{testId:g.testId,field:"video"});}if(g.artifacts.trace){let y=join(g.outputDir,g.artifacts.trace);l.push({filePath:y,runId:r,testId:g.testId,type:"trace"}),c.set(y,{testId:g.testId,field:"trace"});}let v=g.visual??[];for(let y=0;y<v.length;y++){let b=v[y];if(b)for(let k of zl){let T=b[k.field];if(!T)continue;let P=join(g.outputDir,T);l.push({filePath:P,runId:r,testId:g.testId,type:k.type}),c.set(P,{testId:g.testId,field:"visual",visualIndex:y,visualKey:k.keyField});}}}if(l.length===0)return dr;let h=e?.artifactMaxSizeMb??Vl,f=await Ps(t.getEndpoint(),t.getAccessToken(),l,h,s),p=new Map;for(let[g,v]of f){if(!v.success||!v.storageKey)continue;let y=c.get(g);if(!y)continue;let b=p.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,T=k.get(y.visualIndex)??{};T[y.visualKey]=v.storageKey,k.set(y.visualIndex,T),u.set(y.testId,k);}p.set(y.testId,b);}for(let g of n){if(g.visual&&g.visual.length>0){let y=u.get(g.testId);o.set(g.testId,g.visual.map((b,k)=>({...b,...y?.get(k)??{}})));}let v=p.get(g.testId);a.set(g.testId,{...g.artifacts,...v?.screenshotKey?{screenshotKey:v.screenshotKey}:{},...v?.videoKey?{videoKey:v.videoKey}:{},...v?.traceKey?{traceKey:v.traceKey}:{}});}let m=Array.from(f.values()).filter(g=>g.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
|
|
4300
|
+
`),{keyMap:a,visualKeyMap:o,total:l.length,uploaded:m}}async function ur(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},h=new Fe(e?.uploadBudgetMs??12e4),f=p=>{u.failureReason||(u.failureReason=p);};try{if(t.isCloudMode()&&s&&(r==="realtime"||r==="both")){u.realtimeFinalizeAttempted=!0;let g=await t.ensureValidToken(),v=t.getGitMetadata(),y=Yt(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(g){let k=await xs(t.getEndpoint(),t.getAccessToken(),s,b);if(u.realtimeFinalized=k,!k){f("finalize_failed_after_retries");let T=e?.queueDirectory??".testrelic/queue";we(T,n,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${s}/finalize`,"POST",b,{"Content-Type":"application/json"});}}else {f(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 p=new Map,m=new Map;if(t.isCloudMode()&&l&&l.length>0){let g=await $l(t,e,n,l,h);p=g.keyMap,m=g.visualKeyMap,u.artifactsTotal=g.total,u.artifactsUploaded=g.uploaded;}if(t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(u.batchAttempted=!0,await t.ensureValidToken()){let v=t.getGitMetadata(),y=V(),b=cr(t),k=Gl(Kl(a,p),m),T=Xt(k,b,v,y,Wl(c,m),Ue()),P=await vs(t.getEndpoint(),t.getAccessToken(),T,async()=>await t.ensureValidToken()?t.getAccessToken():null,e?.timeout,h);if(u.batchAcknowledged=P.success,!P.success){let S=P;f(S.reason);let w=e?.queueDirectory??".testrelic/queue";we(w,n,"batch",S.reason,S.targetEndpoint,S.method,S.payload,{"Content-Type":"application/json"});}}else {f(t.getFailureReason()??"token_invalid");let v=e?.queueDirectory??".testrelic/queue",y=t.getGitMetadata(),b=V(),k=cr(t),T=Xt(a,k,y,b,void 0,Ue());we(v,n,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",T,{"Content-Type":"application/json"});}await t.dispose();}catch(p){f(p instanceof Error?p.message:"unexpected_upload_error");try{await t.dispose();}catch{}}return u}function Wl(t,e){return !t||e.size===0?t:t.map(r=>{let n=e.get(r.testId);return n?{...r,visual:n}:r})}function Gl(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 Kl(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 Jl=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 Yl(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 Ls(t,e,r){if(!t)return ke;if(!t.isCloudMode())return {...ke,detail:Yl(t.getFailureReason())};let n=e??"batch";if(!Jl.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 pr(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(`
|
|
4301
|
+
`).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function nd(t){if(!t)return null;let e=t.split(`
|
|
4302
|
+
`).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 gr(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 sd(t,e,r){let n=`${t}::${e}::${r}`;return createHash("sha256").update(n).digest("hex").substring(0,16)}function ad(t){return t.length<=3?"":t[t.length-2]}function id(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Hs(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 od(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[Hs(s)]++;}return e}function Bs(t){if(t){for(let e of t)if(e.status==="failed")return {type:e.type,expected:Os(e.expected),actual:Os(e.actual),...e.expression?{expression:e.expression}:{}}}}function Os(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 $e(t,e){if(!t)return 0;let r=0;for(let n of t)n.status===e&&r++;return r}function Us(t,e){for(let r of t)e[r.category]=(e[r.category]??0)+1,r.children.length>0&&Us(r.children,e);}function ld(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 zs=2e5,We=1e5;function qs(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 h=typeof c.url=="string"?c.url:null;h&&l.size<We&&l.add(zt(h));let f=typeof c.responseStatusCode=="number"?c.responseStatusCode:typeof c.statusCode=="number"?c.statusCode:null,p=f!==null&&Number.isFinite(f)?f:null;i.statusRanges[Hs(p)]++;let m=typeof c.responseTimeMs=="number"?c.responseTimeMs:typeof c.durationMs=="number"?c.durationMs:null;m!==null&&Number.isFinite(m)&&i.responseTimes.length<zs&&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<We&&d.add(l.url);return i.navUrls=Array.from(d),o&&Us(o,i.actionCategories),i}function dd(){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 cd(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 ud(){let t=platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function pd(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 fd(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 gd="__testrelic_api_config";function hd(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var Ge=class{constructor(e){this.rootDir="";this.configDir="";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=qr(e),this.apiConfig=Or(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,this.configDir=e.configFile?dirname(e.configFile):"";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)
|
|
4303
|
+
`),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&&rr(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=Sn(join(i,"artifacts"));try{Xn(join(i,"artifacts"));}catch{}}let a=V();this.detectedOs=ud(),this.detectedSource=cd(a);let o=await Q(async()=>(this.cloudClient=new He(this.config.cloud),await this.cloudClient.initialize(),Es(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource)),Qn,"Cloud initialization");if(this.cloudRunId=o??null,o===void 0&&this.cloudClient?.switchToLocalMode("init_error"),this.cloudReceipt=Ls(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&&rr(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:gd,description:hd(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let n=r,s=e.outcome(),a;s==="flaky"?a="flaky":s==="skipped"?a="skipped":a=gr(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=Ms(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=Ur(this.config.redactPatterns),j=M.location?.file??null,E=l.apiAssertions.find(ca=>ca.status==="failed")?.location??null,re=E!==null&&(j===null||resolve(j)!==resolve(e.location.file)),Sr=re?E.file:j,Ze=re?E.line:M.location?.line??null,fe=null;this.config.includeCodeSnippets&&Ze!==null&&Sr&&(fe=Hr(Sr,Ze,this.config.codeContextLines),fe&&(fe=N(fe))),c={message:N(se(M.message??"Unknown error")),line:Ze,code:fe,stack:this.config.includeStackTrace&&M.stack?N(se(M.stack)):null};}}let u=e.titlePath().filter(Boolean),h=relative(this.rootDir||".",e.location.file).replace(/\\/g,"/"),f=ad(u),p=u.join(" > "),m=h,g=sd(m,f,p),v=fd(d,m,e),y=v!=="mobile"&&l.apiCallsCount>0?"api":v,b=s==="flaky",k=id(e.results),T=gr(e.expectedStatus),P=gr(n.status),S=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments){let I=dirname(this.config.outputPath),M=u[u.length-1]??e.title;S=Rn(n.attachments,M,n.retry,I,this.runTimestamp||void 0,g);}let w=null;if(this.config.includeArtifacts&&a!=="skipped"&&n.attachments)try{let I=Un(n.attachments,{updatingSnapshots:this.updatingSnapshots,failureMessage:n.errors.map(M=>M.message??"").join(`
|
|
4304
|
+
`)});if(I.length>0){let M=dirname(this.config.outputPath),N=u[u.length-1]??e.title;w=An(I,N,n.retry,M,this.runTimestamp||void 0,g,this.configDir||this.rootDir||process.cwd());}}catch{}let A=this.config.includeActionSteps&&n.steps?as(n.steps,n.startTime):null,x=pd(e),C={titlePath:u,title:p,status:a,duration:n.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:n.retry,tags:d,failure:c,specFile:h,navigations:l.navigations,testId:g,filePath:m,suiteName:f,testType:y,isFlaky:b,retryStatus:k,expectedStatus:T,actualStatus:P,artifacts:S,visual:w,apiAssertions:l.apiAssertions,actions:A,networkRequestsFile:l.networkRequestsFile,networkRequestsCount:l.networkRequestsCount,consoleLogsFile:l.consoleLogsFile,consoleLogsCount:l.consoleLogsCount,apiCallsFile:l.apiCallsFile,apiCallsCount:l.apiCallsCount,apiStatusMix:l.apiStatusMix,browser:x,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?Zt(z):void 0,ue=!L&&z?Qt(z):void 0,pe=l.apiAssertions&&l.apiAssertions.length>0?er(l.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:g,title:p,status:a,duration:n.duration,suiteName:f,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:x,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...A&&A.length>0?{actions:A}:{},...l.navigations&&l.navigations.length>0?{navigations:l.navigations}:{},..._?{consoleLogs:_}:{},...L?{networkRequests:L}:ue?{networkRequests:ue}:{},...ce?{apiCalls:ce}:{},...pe?{protocolAssertions:pe}:{},...w&&w.length>0?{visual:w}:{}});try{let I=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(I==="realtime"||I==="both")){let M=this.cloudClient.getAccessToken();M&&bs(this.cloudClient.getEndpoint(),M,this.cloudRunId,this.buildCloudTestPayload(C));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let I=Qe(m,u,e.id??"",n.retry),M=n.retry===e.results.length-1,N={id:I,navigations:l.navigations,apiAssertions:l.apiAssertions,actions:A??[],artifacts:S,visual:w,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,...T!=="passed"?{expectedStatus:T}:{},duration:n.duration,project:u[1]??"",retryIndex:n.retry,tags:d,hasNetworkData:l.networkRequestsCount>0,hasConsoleData:l.consoleLogsCount>0,hasArtifacts:S!==null,hasActionSteps:(A?.length??0)>0,visualCount:w?.length??0,visualFailedCount:w?.filter(E=>E.status==="failed").length??0,domChangeCount:w?.reduce((E,re)=>E+(re.domChangeCount??0),0)??0,...(()=>{let E=w?.find(re=>re.diff);return E?.diff?{visualDiffPath:E.diff}:{}})(),errorMessage:nd(c?.message),networkCount:l.networkRequestsCount,consoleCount:l.consoleLogsCount,actionCount:A?.length??0,testType:y,apiCallCount:l.apiCallsCount,...l.apiStatusMix?{apiStatusMix:l.apiStatusMix}:{},assertionsPassed:$e(l.apiAssertions,"passed"),assertionsFailed:$e(l.apiAssertions,"failed"),...(()=>{let E=Bs(l.apiAssertions);return E?{firstFailedAssertion:E}:{}})(),isRetry:!M,retryGroupKey:et(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(" > ")}`,qs(n.retry,z,l.apiAssertions,l.navigations,l.networkRequestsCount,l.consoleLogsCount,A)),(S||w)&&this.pendingArtifactEntries.push({testId:g,artifacts:S??{},visual:w,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
4305
|
\u26A0 TestRelic: No fixture data received from any test.
|
|
4302
4306
|
To enable network logs, video sync, and Test Navigation tracking, import the TestRelic fixture:
|
|
4303
4307
|
import { test, expect } from '@testrelic/playwright-analytics/fixture';
|
|
@@ -4306,18 +4310,19 @@ ${s}
|
|
|
4306
4310
|
|
|
4307
4311
|
`),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
4312
|
`):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(()=>
|
|
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:
|
|
4313
|
+
`),await Q(()=>Cn(),Ut,"Artifact flush");let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let d=dirname(this.config.outputPath);i=Kn(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 f of this.collectedTests){let p=l.get(f.testId);(!p||f.retry>p.retry)&&l.set(f.testId,f);}let c=Array.from(l.values()),u=ss(c,d.length),h={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(h),await Q(()=>It(h,this.config,i),Ut,"HTML report write"),jt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let f=this.collectArtifactEntries(),p=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let m=await Q(()=>ur(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,h,r,a,u,f,p),Ht,"Cloud upload");this.cloudReceipt=pr(this.cloudReceipt,m,this.testRunId);}}}catch{}finally{await this.disposeCloudClient();}}async disposeCloudClient(){let e=this.cloudClient;e&&(this.cloudClient=null,await Q(()=>e.dispose(),es,"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 g of this.testIndex){let v=`${g.filePath}::${g.titlePath.join(" > ")}`,y=a.get(v);(y===void 0||g.retryIndex>y)&&a.set(v,g.retryIndex);}let i=0;for(let g of this.testIndex){let v=`${g.filePath}::${g.titlePath.join(" > ")}`,y=a.get(v);if(g.isRetry=g.retryIndex<y,g.isRetry)continue;switch(i++,this.summaryCounters.total++,g.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+=g.visualCount??0,this.summaryCounters.visualFailures+=g.visualFailedCount??0,this.summaryCounters.visualDomChanges+=g.domChangeCount??0;let b=o.get(g.filePath);switch(b||(b={filePath:g.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},o.set(g.filePath,b)),b.total++,g.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=dd();for(let g of this.streamingTestAgg.values()){l.volApiCalls+=g.apiCalls,l.volAssertions+=g.assertions,l.volNavigations+=g.navigations,l.volNetworkRequests+=g.networkRequests,l.volConsoleLogs+=g.consoleLogs,l.volActionSteps+=g.actionSteps;for(let v in g.methodCounts)l.methodCounts[v]=(l.methodCounts[v]??0)+g.methodCounts[v];l.statusRanges["2xx"]+=g.statusRanges["2xx"],l.statusRanges["3xx"]+=g.statusRanges["3xx"],l.statusRanges["4xx"]+=g.statusRanges["4xx"],l.statusRanges["5xx"]+=g.statusRanges["5xx"],l.statusRanges.error+=g.statusRanges.error,l.passedAssertions+=g.passedAssertions,l.failedAssertions+=g.failedAssertions;for(let v in g.actionCategories)l.actionCategoryCounts[v]=(l.actionCategoryCounts[v]??0)+g.actionCategories[v];for(let v of g.apiUrls){if(l.apiUrlSet.size>=We)break;l.apiUrlSet.add(v);}for(let v of g.navUrls){if(l.navUrlSet.size>=We)break;l.navUrlSet.add(v);}for(let v of g.responseTimes){if(l.responseTimes.length>=zs)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}
|
|
4314
|
+
`);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:ld(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},h={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(h);let f={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(f),await It(this.buildStreamingReport(h,u,e,r),this.config,s),jt(u,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let p=this.streamingWriter.getReportDir();process.stderr.write(`[testrelic] Streaming report written to ${p}
|
|
4311
4315
|
[testrelic] ${this.testIndex.length} test detail files on disk
|
|
4312
|
-
[testrelic] View report: npx testrelic serve ${
|
|
4316
|
+
[testrelic] View report: npx testrelic serve ${p}
|
|
4313
4317
|
`),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
|
|
4318
|
+
`);let m=this.streamingWriter;try{if(this.cloudClient){let g=this.buildStreamingReport(h,u,e,r),v=this.collectArtifactEntries(),y=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0;let b=await ur(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,g,e,r,u,v,y);this.cloudReceipt=pr(this.cloudReceipt,b,this.testRunId);let k={...h,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
4319
|
`),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
|
-
`));}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=Qe(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:
|
|
4318
|
-
`);}}};var
|
|
4319
|
-
`);return
|
|
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
|
|
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[vr];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 g=Cd(),p;if(g){let m=wd(g.file);m&&g.line>0&&g.line<=m.length&&(p=m[g.line-1].trim());}let f=r(i,...d);return u?Gs(f,{tracker:l,callId:u,received:i,location:g??{file:"unknown",line:0},expression:p}):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 mr(){let t=globalThis,e=t[Vs];return e||(e={tracker:null,apiTracker:null},t[Vs]=e),e}function le(t,e){let r=mr();r.tracker=t,r.apiTracker=e;}function Je(t){return Sd(()=>mr().tracker,()=>mr().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 g=a.apply(this??r,i);return g&&typeof g=="object"&&typeof g.then=="function"?g.then(()=>{hr(e,n,d,c,"passed");},p=>{throw hr(e,n,d,c,"failed"),p}):g}catch(g){if(l="failed",u=g,g instanceof Error&&g.message){let p=g.message.match(/Received:\s*(.+)/);p&&(c=p[1]);}throw g}finally{(u!==null||l==="passed")&&hr(e,n,d,c,l);}}}})}function hr(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 br(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 Ye(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=yr(r,n);return JSON.stringify(s)}function yr(t,e){if(Array.isArray(t))return t.map(r=>yr(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]=yr(s,e);}return r}return t}var Rd=new Set(["access_token","api_key","token","sig"]);function xr(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 Xe=class Xe{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??Xe.DEFAULT_API_CONFIG;try{this.apiCallWriter=new H("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 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=Pd(o),u=performance.now();n._lastCallId=i,n.assertionTracker&&n.assertionTracker.setCurrentCallId(i);let g;try{g=await r(a,o);}catch(p){let f=performance.now();try{let m=n.apiConfig.captureRequestBody?Ye(c,n.apiConfig.redactBodyFields):null,h={id:i,timestamp:d,method:l,url:xr(a),requestHeaders:null,requestBody:m,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((f-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(),f=g.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 g.body()).toString("base64"):k=await g.text();}catch{}let A=[],P=[];try{if(n.apiConfig.captureRequestHeaders&&(A=Ed(o?.headers)),n.apiConfig.captureResponseHeaders){let x=g.headersArray().filter(S=>S.name.toLowerCase()==="set-cookie").map(S=>S.value);P=Ld(x);}}catch{}v=br(v,n.apiConfig.redactHeaders),y=br(y,n.apiConfig.redactHeaders),b=Ye(b,n.apiConfig.redactBodyFields),k=Ye(k,n.apiConfig.redactBodyFields);let T={id:i,timestamp:d,method:l,url:xr(g.url()),requestHeaders:v,requestBody:b,responseStatusCode:g.status(),responseStatusText:g.statusText(),responseHeaders:y,responseBody:k,requestCookies:A.length?A:null,responseCookies:P.length?P: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{g[vr]=i,n.tagResponseMethods(g,i);}catch{}return g}}};Xe.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=Xe;var qd=[".png",".jpg",".jpeg"],Hd=/A snapshot doesn't exist at /;function Ud(t){return t.wrote?t.existedBefore?"updated":"new":t.pass?"passed":"failed"}function Zs(t){if(!t)return null;try{let e=statSync(t);return {size:e.size,mtimeMs:e.mtimeMs}}catch{return null}}function zd(t,e){if(!Le(t))return null;try{return t.snapshotPath(e,{kind:"screenshot"})}catch{return null}}function jd(t){let e=t.toLowerCase();return qd.some(r=>e.endsWith(r))?t:`${t}.png`}function Vd(){try{return test.info()}catch{return null}}function $d(t,e,r){let n=a=>/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/.exec(a)?.[1]??null,s=t.slice(e);if(r){for(let a of s)if(a.path===r&&/-expected\.[A-Za-z0-9]+$/.test(a.name))return n(a.name)}for(let a of s){let o=n(a.name);if(o)return o}return null}async function Wd(t,e){if(e===null)return Ne("Attaching the baseline of a passing comparison"),null;try{let r=extname(e)||".png",n=basename(e,r);return await t.attach(`${n}-expected${r}`,{path:e}),n}catch{return null}}async function Gd(t,e){try{await t.attach(Ot,{body:Buffer.from(JSON.stringify([e])),contentType:"application/json"});}catch{}}async function kr(t,e,r={}){let n={...r};delete n.tags;let s=jd(e),a=Vd(),o=a?.attachments.length??0,i=a?.errors?.length??0,d=a?zd(a,s):null,l=Zs(d),c=true,u="";try{await expect(t).toHaveScreenshot(s,n);}catch(g){c=false,u=g instanceof Error?g.message:String(g);}if(a){let g=Zs(d),p=d!==null?g!==null&&(l===null||l.size!==g.size||l.mtimeMs!==g.mtimeMs):(a.errors??[]).slice(i).some(h=>Hd.test(h.message??"")),f=Ud({pass:c,wrote:p,existedBefore:l!==null}),m=f==="passed"||f==="updated"?await Wd(a,d):$d(a.attachments,o,d);m&&await Gd(a,{stem:m,name:e,status:f,...d?{committedPath:d}:{}});}return {pass:c,name:"toMatchVisualBaseline",message:()=>c?`Expected "${e}" to differ from its visual baseline, but it matched.`:u}}expect.extend({toMatchVisualBaseline:kr});function Yd(){try{return test.info()}catch{return null}}Bn(Je(expect),Yd);var Xd="__testrelic_api_config",Zd="__testrelic_config_trackApiCalls";function Cr(t){let e=t.annotations.find(n=>n.type===Xd&&n.description!==void 0);if(e)try{return JSON.parse(e.description,Qd)}catch{}let r=t.annotations.find(n=>n.type===Zd&&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 Qd(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 na={page:async({page:t},e,r)=>{let n=new Ke(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=Cr(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(na);Je(expect);var sc={request:async({request:t},e,r)=>{let n=Cr(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 H("api-console");}catch{}let i=0,d=process.stdout.write,l=process.stderr.write;process.stdout.write=function(c,...u){try{let g=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!g.startsWith("[testrelic]")&&!g.startsWith("\u2139 TestRelic")&&!g.startsWith("\u2713 TestRelic")&&!g.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stdout",text:g.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 g=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!g.startsWith("[testrelic]")&&!g.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stderr",text:g.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:g}=a.getFileData(),p=n.captureAssertions?s.getData():[],f={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:g};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(f)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};var sa="@testrelic/playwright-analytics";function ic(t){return Array.isArray(t)?t.some(e=>Array.isArray(e)&&typeof e[0]=="string"&&e[0]===sa):false}function oc(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=ic(s)?s:[...s,[sa,e??{}]];return defineConfig({...t,use:n,reporter:a})}var aa=false;function _g(t,e,r="manual_record"){if(!t||!t.annotations){aa||(aa=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,Ge as default,oc as defineConfig,_g as recordNavigation,sc as testRelicApiFixture,na as testRelicFixture};//# sourceMappingURL=index.js.map
|
|
4320
|
+
`));}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=Qe(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,...r.expectedStatus!=="passed"?{expectedStatus:r.expectedStatus}:{},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(`
|
|
4321
|
+
`)[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:od(s)}:{},assertionsPassed:$e(r.apiAssertions,"passed"),assertionsFailed:$e(r.apiAssertions,"failed"),...(()=>{let i=Bs(r.apiAssertions);return i?{firstFailedAssertion:i}:{}})(),isRetry:!1,retryGroupKey:et(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(" > ")}`,qs(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 ns(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=er(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=Zt(n),(!r.networkRequests||r.networkRequests.length===0)&&(r.networkRequests=Qt(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)}
|
|
4322
|
+
`);}}};var xd=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function wd(t){let e=t.toLowerCase();return xd.some(r=>e.includes(r))}var Ke=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 H("network")),this.consoleWriter=new H("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.page,r=t.asPatchable(e);r.goto=async(n,s)=>(this.recordNavigation(n,"goto"),this.origGoto(n,s)),r.goBack=async n=>{let s=await this.origGoBack(n);return this.recordNavigation(e.url(),"back"),s},r.goForward=async n=>{let s=await this.origGoForward(n);return this.recordNavigation(e.url(),"forward"),s},r.reload=async n=>(this.recordNavigation(e.url(),"refresh"),this.origReload(n));}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++),h=c.postData()??null,f={url:c.url(),method:c.method(),resourceType:this.mapResourceType(c.resourceType()),headers:c.headers(),postData:h,postDataTruncated:!1,startedAt:new Date().toISOString(),startTimeMs:Date.now(),navIndex:d};this.pendingRequests.set(u,f),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(),T=this.mapResourceType(k);u.byType[T]++;}if(!l||!c)return;this.pendingRequests.delete(l);let h=Date.now()-c.startTimeMs,f=d.headers(),p=f["content-type"]??null,m=parseInt(f["content-length"]??"0",10)||0,g=p?!wd(p):!1,v=(async()=>{let y=null;if(!g)try{y=(await d.body()).toString("utf-8");}catch{}let b={url:c.url,method:c.method,resourceType:c.resourceType,statusCode:d.status(),responseTimeMs:h,startedAt:c.startedAt,requestHeaders:c.headers,requestBody:c.postData,responseBody:y,responseHeaders:f,contentType:p,responseSize:m,requestBodyTruncated:c.postDataTruncated,responseBodyTruncated:!1,isBinary:g,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 h={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(h),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 vr=Symbol.for("__testrelic_call_id"),Cd="__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:Cd,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}},js=new Map;function Sd(t){let e=js.get(t);if(e)return e;try{let r=t.startsWith("file://")?fileURLToPath(t):t,s=readFileSync(r,"utf-8").split(`
|
|
4323
|
+
`);return js.set(t,s),s}catch{return null}}var Vs=(()=>{let t=new Error().stack;if(!t)return null;for(let e of t.split(`
|
|
4324
|
+
`)){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 Td(t){if(!t.startsWith("file:"))return t;try{return fileURLToPath(t)}catch{return t}}function Rd(){let e=new Error().stack;if(!e)return null;let r=e.split(`
|
|
4325
|
+
`);return $s(r,true)??$s(r,false)}function $s(t,e){for(let r of t){if(e&&Vs!==null&&r.includes(Vs)||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:Td(n[1]),line:parseInt(n[2],10),column:parseInt(n[3],10)}}return null}function Ad(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 _d(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[vr];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 h=Rd(),f;if(h){let m=Sd(h.file);m&&h.line>0&&h.line<=m.length&&(f=m[h.line-1].trim());}let p=r(i,...d);return u?Js(p,{tracker:l,callId:u,received:i,location:h??{file:"unknown",line:0},expression:f}):p},s=r,a=n;for(let o of Object.keys(s))a[o]=s[o];return n}var Ws=Symbol.for("testrelic.activeAssertionContext");function mr(){let t=globalThis,e=t[Ws];return e||(e={tracker:null,apiTracker:null},t[Ws]=e),e}function le(t,e){let r=mr();r.tracker=t,r.apiTracker=e;}function Je(t){return _d(()=>mr().tracker,()=>mr().apiTracker,t)}function Js(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"?Js(a,e):function(...i){let d=i[0],l="passed",c=e.received,u=null;try{let h=a.apply(this??r,i);return h&&typeof h=="object"&&typeof h.then=="function"?h.then(()=>{hr(e,n,d,c,"passed");},f=>{throw hr(e,n,d,c,"failed"),f}):h}catch(h){if(l="failed",u=h,h instanceof Error&&h.message){let f=h.message.match(/Received:\s*(.+)/);f&&(c=f[1]);}throw h}finally{(u!==null||l==="passed")&&hr(e,n,d,c,l);}}}})}function hr(t,e,r,n,s){let a=Ad(t.expression,t.received),o={callId:t.callId,type:a,expected:Gs(r),actual:Gs(n),status:s,location:t.location,expression:t.expression};t.tracker.recordAssertion(o);}function Gs(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 Ys="[REDACTED]";function br(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())?Ys:t[s]);return n}function Ye(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=yr(r,n);return JSON.stringify(s)}function yr(t,e){if(Array.isArray(t))return t.map(r=>yr(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]=Ys:r[n]=yr(s,e);}return r}return t}var Id=new Set(["access_token","api_key","token","sig"]);function xr(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()])Id.has(n.toLowerCase())&&(e.searchParams.delete(n),r=true);return r?e.toString():t}function Zs(t,e,r){if(r.length>0){for(let n of r)if(Xs(t,n))return false}if(e.length>0){for(let n of e)if(Xs(t,n))return true;return false}return true}function Xs(t,e){try{return e instanceof RegExp?e.test(t):Md(e).test(t)}catch{return process.stderr.write(`[testrelic] Invalid URL filter pattern: ${String(e)}
|
|
4326
|
+
`),false}}function Md(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 Pd=["get","post","put","patch","delete","head","fetch"],Ed=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function Ld(t){let e=t.toLowerCase();return Ed.some(r=>e.includes(r))}function Nd(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 Qs(t){return t?"\u2022\u2022\u2022\u2022":""}function Dd(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:Qs(i)});}return r}function Fd(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:Qs(d),attributes:l});}return e}var Xe=class Xe{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??Xe.DEFAULT_API_CONFIG;try{this.apiCallWriter=new H("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 Pd){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{primitiveCallIds:n}=this,s=e.headers.bind(e);e.headers=function(){let f=s();return te.set(f,r),f};let a=e.headersArray.bind(e);e.headersArray=function(){let f=a();return te.set(f,r),f};let o=e.json.bind(e);e.json=async function(){let f=await o();return f!=null&&typeof f=="object"&&te.set(f,r),f};let i=e.status.bind(e);e.status=function(){let f=i();return n.set(f,r),f};let d=e.statusText.bind(e);e.statusText=function(){let f=d();return n.set(f,r),f};let l=e.ok.bind(e);e.ok=function(){let f=l();return n.set(f,r),f};let c=e.text.bind(e);e.text=async function(){let f=await c();return n.set(f,r),f};let u=e.body.bind(e);e.body=async function(){let f=await u();return te.set(f,r),f};}createWrapper(e,r){return async(n,s)=>{if(!Zs(n,this.apiConfig.apiIncludeUrls,this.apiConfig.apiExcludeUrls))return r(n,s);let a=`api-call-${this.callCounter++}`,o=new Date().toISOString(),i=e==="fetch"?(s?.method??"GET").toUpperCase():e.toUpperCase(),d=Nd(s),l=performance.now();this._lastCallId=a,this.assertionTracker&&this.assertionTracker.setCurrentCallId(a);let c;try{c=await r(n,s);}catch(u){let h=performance.now();try{let f=this.apiConfig.captureRequestBody?Ye(d,this.apiConfig.redactBodyFields):null,p={id:a,timestamp:o,method:i,url:xr(n),requestHeaders:null,requestBody:f,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((h-l)*100)/100,isBinary:!1,error:u instanceof Error?u.message:String(u)};this.apiCallWriter&&(this.apiCallWriter.append(p),this.apiCallCount++,this.tallyStatus(null));}catch{}throw u}try{let u=performance.now(),h=c.headers(),f=h["content-type"]??null,p=f?!Ld(f):!1,m=null;this.apiConfig.captureRequestHeaders&&s?.headers&&(m=s.headers);let g=null;this.apiConfig.captureResponseHeaders&&(g=h);let v=this.apiConfig.captureRequestBody?d:null,y=null;if(this.apiConfig.captureResponseBody)try{p?y=(await c.body()).toString("base64"):y=await c.text();}catch{}let b=[],k=[];try{if(this.apiConfig.captureRequestHeaders&&(b=Dd(s?.headers)),this.apiConfig.captureResponseHeaders){let P=c.headersArray().filter(S=>S.name.toLowerCase()==="set-cookie").map(S=>S.value);k=Fd(P);}}catch{}m=br(m,this.apiConfig.redactHeaders),g=br(g,this.apiConfig.redactHeaders),v=Ye(v,this.apiConfig.redactBodyFields),y=Ye(y,this.apiConfig.redactBodyFields);let T={id:a,timestamp:o,method:i,url:xr(c.url()),requestHeaders:m,requestBody:v,responseStatusCode:c.status(),responseStatusText:c.statusText(),responseHeaders:g,responseBody:y,requestCookies:b.length?b:null,responseCookies:k.length?k:null,responseTimeMs:Math.round((u-l)*100)/100,isBinary:p,error:null};this.apiCallWriter&&(this.apiCallWriter.append(T),this.apiCallCount++,this.tallyStatus(T.responseStatusCode));}catch{}try{c[vr]=a,this.tagResponseMethods(c,a);}catch{}return c}}};Xe.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=Xe;var Hd=[".png",".jpg",".jpeg"],Ud=/A snapshot doesn't exist at /;function zd(t){return t.wrote?t.existedBefore?"updated":"new":t.pass?"passed":"failed"}function jd(t){return t.status==="failed"&&!t.hadBaseline}function ea(t){if(!t)return null;try{let e=statSync(t);return {size:e.size,mtimeMs:e.mtimeMs}}catch{return null}}function Vd(t,e){if(!Le(t))return null;try{return t.snapshotPath(e,{kind:"screenshot"})}catch{return null}}function $d(t){let e=t.toLowerCase();return Hd.some(r=>e.endsWith(r))?t:`${t}.png`}function Wd(){try{return test.info()}catch{return null}}function Gd(t,e,r){let n=a=>/^(.+)-(expected|actual|diff|previous)\.[A-Za-z0-9]+$/.exec(a)?.[1]??null,s=t.slice(e);if(r){for(let a of s)if(a.path===r&&/-expected\.[A-Za-z0-9]+$/.test(a.name))return n(a.name)}for(let a of s){let o=n(a.name);if(o)return o}return null}function Kd(t,e){return e?basename(e,extname(e)||".png"):t.replace(/\.[A-Za-z0-9]+$/,"")}async function Jd(t,e){if(e===null)return Ne("Attaching the baseline of a passing comparison"),null;try{let r=extname(e)||".png",n=basename(e,r);return await t.attach(`${n}-expected${r}`,{path:e}),n}catch{return null}}async function Yd(t,e){try{await t.attach(Ot,{body:Buffer.from(JSON.stringify([e])),contentType:"application/json"});}catch{}}async function kr(t,e,r={}){let n={...r};delete n.tags;let s=$d(e),a=Wd(),o=a?.attachments.length??0,i=a?.errors?.length??0,d=a?Vd(a,s):null,l=ea(d),c=true,u="";try{await expect(t).toHaveScreenshot(s,n);}catch(h){c=false,u=h instanceof Error?h.message:String(h);}if(a){let h=ea(d),f=d!==null?h!==null&&(l===null||l.size!==h.size||l.mtimeMs!==h.mtimeMs):(a.errors??[]).slice(i).some(v=>Ud.test(v.message??"")),p=zd({pass:c,wrote:f,existedBefore:l!==null}),g=(p==="passed"||p==="updated"?await Jd(a,d):Gd(a.attachments,o,d))??(jd({status:p,hadBaseline:l!==null})?Kd(s,d):null);g&&await Yd(a,{stem:g,name:e,status:p,...d?{committedPath:d}:{}});}return {pass:c,name:"toMatchVisualBaseline",message:()=>c?`Expected "${e}" to differ from its visual baseline, but it matched.`:u}}expect.extend({toMatchVisualBaseline:kr});function Qd(){try{return test.info()}catch{return null}}On(Je(expect),Qd);var ec="__testrelic_api_config",tc="__testrelic_config_trackApiCalls";function Cr(t){let e=t.annotations.find(n=>n.type===ec&&n.description!==void 0);if(e)try{return JSON.parse(e.description,rc)}catch{}let r=t.annotations.find(n=>n.type===tc&&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 rc(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 oa={page:async({page:t},e,r)=>{let n=new Ke(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=Cr(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(oa);Je(expect);var oc={request:async({request:t},e,r)=>{let n=Cr(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 H("api-console");}catch{}let i=0,d=process.stdout.write,l=process.stderr.write;process.stdout.write=function(c,...u){try{let h=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!h.startsWith("[testrelic]")&&!h.startsWith("\u2139 TestRelic")&&!h.startsWith("\u2713 TestRelic")&&!h.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stdout",text:h.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 h=typeof c=="string"?c:Buffer.isBuffer(c)?c.toString("utf-8"):String(c);!h.startsWith("[testrelic]")&&!h.startsWith("\u26A0 TestRelic")&&o&&(o.append({level:"stderr",text:h.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:h}=a.getFileData(),f=n.captureAssertions?s.getData():[],p={testRelicData:!0,version:PAYLOAD_VERSION,navigations:[],apiAssertions:f,networkRequestsFile:null,networkRequestsCount:0,consoleLogsFile:i>0?o?.getPath()??null:null,consoleLogsCount:i,apiCallsFile:c,apiCallsCount:u,apiStatusMix:h};await r.attach(ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(p)),contentType:ATTACHMENT_CONTENT_TYPE});}catch{}a.dispose(),s.dispose();}};var la="@testrelic/playwright-analytics";function dc(t){return Array.isArray(t)?t.some(e=>Array.isArray(e)&&typeof e[0]=="string"&&e[0]===la):false}function cc(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=dc(s)?s:[...s,[la,e??{}]];return defineConfig({...t,use:n,reporter:a})}var da=false;function _g(t,e,r="manual_record"){if(!t||!t.annotations){da||(da=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
|
|
4327
|
+
`));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,Ge as default,cc as defineConfig,_g as recordNavigation,oc as testRelicApiFixture,oa as testRelicFixture};//# sourceMappingURL=index.js.map
|
|
4323
4328
|
//# sourceMappingURL=index.js.map
|