@testrelic/playwright-analytics 2.11.1-next.77 → 2.11.1-next.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +38 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +39 -39
- package/dist/index.js.map +1 -1
- package/dist/reporter-entry.cjs +33 -33
- package/dist/reporter-entry.cjs.map +1 -1
- package/dist/reporter-entry.js +34 -34
- package/dist/reporter-entry.js.map +1 -1
- package/package.json +2 -2
package/dist/reporter-entry.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';var crypto=require('crypto'),fs$1=require('fs'),path=require('path'),os$1=require('os'),core=require('@testrelic/core'),child_process=require('child_process'),http=require('http'),readline=require('readline'),promises=require('fs/promises'),zlib=require('zlib'),util=require('util'),stream=require('stream');var Kr=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var Qr=".testrelic-report";function ke(t,e,r,s){let n=`${t}|${e.join("|")}|${r}|${s}`;return crypto.createHash("sha256").update(n).digest("hex").substring(0,12)}var J=class{constructor(e){this.writeErrors=[];this.totalBytesWritten=0;this.reportDir=path.join(e,Qr),this.testsDir=path.join(this.reportDir,"tests"),fs$1.mkdirSync(this.testsDir,{recursive:true});}getReportDir(){return this.reportDir}getWriteErrors(){return this.writeErrors}writeTestDetail(e,r,s){try{let n=path.join(this.testsDir,e);fs$1.mkdirSync(n,{recursive:!0});let a=path.join(n,"meta.json"),o=a+".tmp",i=JSON.stringify(r);return fs$1.writeFileSync(o,i,"utf-8"),fs$1.renameSync(o,a),this.totalBytesWritten+=Buffer.byteLength(i,"utf-8"),s?.networkRequestsFile&&this.moveFile(s.networkRequestsFile,path.join(n,"network.jsonl")),s?.consoleLogsFile&&this.moveFile(s.consoleLogsFile,path.join(n,"console.jsonl")),s?.apiCallsFile&&this.moveFile(s.apiCallsFile,path.join(n,"api-calls.jsonl")),!0}catch(n){let a=n instanceof Error?n.message:String(n);return this.writeErrors.push({testId:e,error:a,timestamp:new Date().toISOString()}),process.stderr.write(`[testrelic] Failed to write test detail for ${e}: ${a}
|
|
2
2
|
`),false}}moveFile(e,r){try{fs$1.renameSync(e,r);}catch{try{let{copyFileSync:s}=Kr("fs");s(e,r);try{fs$1.unlinkSync(e);}catch{}}catch(s){process.stderr.write(`[testrelic] Failed to move file ${e} \u2192 ${r}: ${s instanceof Error?s.message:String(s)}
|
|
3
|
-
`);}}}writeIndex(e){let r=path.join(this.reportDir,"index.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeCompactIndex(e){let r=path.join(this.reportDir,"index-compact.json"),s=r+".tmp",n=e.map(({titlePath:o,project:i,...d})=>d),a=JSON.stringify(n);fs$1.writeFileSync(s,a,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(a,"utf-8");}writeSummary(e){let r=path.join(this.reportDir,"summary.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeManifest(e){let r=path.join(this.reportDir,"manifest.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var
|
|
4
|
-
`),n}catch{}let a=path.dirname(e);if(a===e)break;e=a;}return null}function
|
|
5
|
-
`);let u=t.queue;if(u&&typeof u=="object"){if(typeof u.maxAge=="string"){let g=
|
|
3
|
+
`);}}}writeIndex(e){let r=path.join(this.reportDir,"index.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeCompactIndex(e){let r=path.join(this.reportDir,"index-compact.json"),s=r+".tmp",n=e.map(({titlePath:o,project:i,...d})=>d),a=JSON.stringify(n);fs$1.writeFileSync(s,a,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(a,"utf-8");}writeSummary(e){let r=path.join(this.reportDir,"summary.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}writeManifest(e){let r=path.join(this.reportDir,"manifest.json"),s=r+".tmp",n=JSON.stringify(e);fs$1.writeFileSync(s,n,"utf-8"),fs$1.renameSync(s,r),this.totalBytesWritten+=Buffer.byteLength(n,"utf-8");}computeTotalSize(){return this.totalBytesWritten}dispose(){}};var St=".testrelic",ss="testrelic-config.json",ns=".testrelic",as=5,is=new Set(["__proto__","constructor","prototype"]),kt=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${St}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),os={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function Ct(t){let e=path.resolve(t);for(let r=0;r<=as;r++){let s=path.join(e,St,ss);if(fs$1.existsSync(s))try{if(fs$1.statSync(s).isFile())return s}catch{}let n=path.join(e,ns);if(fs$1.existsSync(n))try{if(fs$1.statSync(n).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
|
+
`),n}catch{}let a=path.dirname(e);if(a===e)break;e=a;}return null}function Rt(t){try{let e=fs$1.readFileSync(t,"utf-8"),r=JSON.parse(e);return typeof r!="object"||r===null||Array.isArray(r)||!At(r)?null:r}catch{return null}}function At(t){for(let e of Object.keys(t)){if(is.has(e))return false;let r=t[e];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!At(r))return false}return true}function It(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 Te(t){let e=Object.create(null);for(let r of Object.keys(t)){let s=t[r];typeof s=="string"&&s.startsWith("$")?e[r]=It(s):typeof s=="object"&&s!==null&&!Array.isArray(s)?e[r]=Te(s):e[r]=s;}return e}function Tt(t){let e=/^(\d+)\s*([smhd])$/.exec(t.trim());if(!e)return null;let r=parseInt(e[1],10),s=e[2],n=os[s];return !n||r<=0?null:r*n}function _t(t,e){let r=Object.create(null);if(Object.assign(r,kt),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.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 u=t.queue;if(u&&typeof u=="object"){if(typeof u.maxAge=="string"){let g=Tt(u.maxAge);g!==null&&(r.queueMaxAge=g);}typeof u.directory=="string"&&(r.queueDirectory=u.directory);}}if(e){if(typeof e.apiKey=="string"&&e.apiKey.length>0){let d=e.apiKey.startsWith("$")?It(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.projectName=="string"&&(r.projectName=e.projectName),typeof e.queueMaxAge=="string"){let d=Tt(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 s=process.env.TESTRELIC_API_KEY;s&&s.length>0&&(r.apiKey=s);let n=process.env.TESTRELIC_CLOUD_ENDPOINT;n&&core.isValidEndpointUrl(n)&&(r.endpoint=n);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 core.isValidCloudConfig(i)?i:kt}var us=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],ps=["authorization","cookie","set-cookie","x-api-key"],fs=["password","secret","token","apiKey","api_key"];function Mt(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??[...ps],e.redactBodyFields=t?.redactBodyFields??[...fs],e.apiIncludeUrls=t?.apiIncludeUrls??[],e.apiExcludeUrls=t?.apiExcludeUrls??[],Object.freeze(e)}function Lt(t){if(t!==void 0&&!core.isValidConfig(t))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let e=Object.create(null);e.outputPath=t?.outputPath??"./test-results/analytics-timeline.json",e.includeStackTrace=t?.includeStackTrace??false,e.includeCodeSnippets=t?.includeCodeSnippets??true,e.codeContextLines=t?.codeContextLines??3,e.includeNetworkStats=t?.includeNetworkStats??true,e.captureNavigation=t?.captureNavigation??true,e.navigationTypes=t?.navigationTypes??null,e.redactPatterns=[...us,...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 s=Ct(process.cwd()),n=s?Rt(s):null,a=n?Te(n):null,o=_t(a,t?.cloud);return e.cloud=o.apiKey?o:null,e.reportMode=t?.reportMode??"streaming",e.streamingThreshold=t?.streamingThreshold??0,Object.freeze(e)}var Se="1.3.0";function Et(t,e,r){try{let n=fs$1.readFileSync(t,"utf-8").split(`
|
|
6
6
|
`);if(e<1||e>n.length)return null;let a=Math.max(1,e-r),o=Math.min(n.length,e+r),i=[];for(let d=a;d<=o;d++){let l=d===e?">":" ",u=String(d).padStart(String(o).length," ");i.push(`${l} ${u} | ${n[d-1]}`);}return i.join(`
|
|
7
|
-
`)}catch{return null}}function
|
|
7
|
+
`)}catch{return null}}function Pt(t){return e=>{let r=e;for(let s of t)if(typeof s=="string"){let n=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(n,"g"),"[REDACTED]");}else {let n=s.flags.includes("g")?s.flags:s.flags+"g",a=new RegExp(s.source,n);r=r.replace(a,"[REDACTED]");}return r}}function hs(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 ms(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 vs(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 ys(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 bs(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 xs=[hs,ms,vs,ys,bs];function P(t){let e=process.env;for(let r of xs){let s=r(e);if(s)return s}return null}var Ce=`
|
|
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;
|
|
@@ -2331,7 +2331,7 @@ function _updateCard(cls,val){
|
|
|
2331
2331
|
renderFilterBar();
|
|
2332
2332
|
renderTestGrid();
|
|
2333
2333
|
var _lo=document.getElementById('loading-overlay');if(_lo)_lo.remove();
|
|
2334
|
-
})();`;function
|
|
2334
|
+
})();`;function Nt(t,e,r){let s=t.replace(/<\//g,"<\\/"),n=r?r.replace(/<\//g,"<\\/"):null;return `<!-- TestRelic AI Analytics Report \u2014 self-contained, no external dependencies -->
|
|
2335
2335
|
<!DOCTYPE html>
|
|
2336
2336
|
<html lang="en" data-theme="">
|
|
2337
2337
|
<head>
|
|
@@ -2544,51 +2544,51 @@ ${o?`<script id="artifact-manifest-data" type="application/json">${o}</script>`:
|
|
|
2544
2544
|
<script>${l}</script>
|
|
2545
2545
|
</body>
|
|
2546
2546
|
</html>`}function De(t){try{let e=process.platform,r,s;e==="darwin"?(r="open",s=[t]):e==="win32"?(r="cmd",s=["/c","start","",t]):(r="xdg-open",s=[t]),child_process.execFile(r,s,n=>{n&&process.stderr.write(`[testrelic] Failed to open browser: ${n.message}
|
|
2547
|
-
`);});}catch{}}path.join(os$1.tmpdir(),"testrelic-data");async function
|
|
2547
|
+
`);});}catch{}}path.join(os$1.tmpdir(),"testrelic-data");async function Ft(t,e,r,s){let n=(e-1)*r,a=[],o=0,i=readline.createInterface({input:fs$1.createReadStream(t,{encoding:"utf-8"}),crlfDelay:1/0});for await(let u of i)if(u.length!==0){if(o>=n&&a.length<r)try{a.push(JSON.parse(u));}catch{}if(o++,a.length>=r&&s!==void 0)break}let d=s??o,l=Math.max(1,Math.ceil(d/r));return {items:a,total:d,page:e,pageSize:r,totalPages:l}}var Ot=/^[a-f0-9]{12}$/,Be=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,qt=500;function b(t,e,r){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(r));}function Ht(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 ae(t){try{return fs$1.existsSync(t)?JSON.parse(fs$1.readFileSync(t,"utf-8")):null}catch{return null}}function ie(t){let e=0;try{let r=fs$1.readdirSync(t,{withFileTypes:!0});for(let s of r){let n=path.join(t,s.name);s.isFile()?e+=fs$1.statSync(n).size:s.isDirectory()&&(e+=ie(n));}}catch{}return e}function Ut(t,e,r,s){let n=ae(path.join(r,"index.json"));b(e,200,{status:"ok",reportMode:"streaming",testCount:n?.length??0,uptime:Math.floor((Date.now()-s)/1e3)});}function $t(t,e,r){let s=ae(path.join(r,"summary.json"));if(!s){b(e,404,{error:"Summary not found"});return}b(e,200,s);}function zt(t,e,r){let s=ae(path.join(r,"index.json"));if(!s){b(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(qt,Math.max(1,parseInt(a.get("pageSize")??"100",10)||100)),d=a.get("status")?.split(",").filter(Boolean)??null,l=a.get("file")??null,u=a.get("search")?.toLowerCase()??null,g=a.get("tag")?.split(",").filter(Boolean)??null,m=a.get("sort")??"file",p=a.get("order")==="desc"?-1:1,f=s;d&&d.length>0&&(f=f.filter(x=>d.includes(x.status))),l&&(f=f.filter(x=>x.filePath===l||x.filePath.startsWith(l+"/"))),u&&(f=f.filter(x=>x.title.toLowerCase().includes(u)||x.filePath.toLowerCase().includes(u))),g&&g.length>0&&(f=f.filter(x=>g.some(T=>x.tags.includes(T)))),f=[...f].sort((x,T)=>{let M=0;switch(m){case "duration":M=x.duration-T.duration;break;case "status":M=x.status.localeCompare(T.status);break;case "title":M=x.title.localeCompare(T.title);break;default:M=x.filePath.localeCompare(T.filePath);break}return M*p});let c=f.length,h=Math.max(1,Math.ceil(c/i)),v=(o-1)*i,w=f.slice(v,v+i);b(e,200,{tests:w,pagination:{page:o,pageSize:i,totalItems:c,totalPages:h},filters:{status:d,file:l,search:u,tag:g}});}function jt(t,e,r,s){if(!Ot.test(s)){b(e,400,{error:"Invalid test ID format"});return}let n=path.join(r,"tests",s,"meta.json"),a=path.join(r,"tests",`${s}.json`),o=fs$1.existsSync(n)?n:fs$1.existsSync(a)?a:null;if(!o){b(e,404,{error:`Test not found: ${s}`});return}try{let i=fs$1.readFileSync(o,"utf-8");e.writeHead(200,{"Content-Type":"application/json"}),e.end(i);}catch(i){b(e,500,{error:i instanceof Error?i.message:String(i)});}}async function Vt(t,e,r,s,n){if(!Ot.test(s)){b(e,400,{error:"Invalid test ID format"});return}let o=path.join(r,"tests",s,{network:"network.jsonl",console:"console.jsonl","api-calls":"api-calls.jsonl"}[n]);if(!fs$1.existsSync(o)){b(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),u=Math.min(qt,Math.max(1,parseInt(d.get("pageSize")??"50",10)||50)),g,m=path.join(r,"tests",s,"meta.json");if(fs$1.existsSync(m))try{let f=JSON.parse(fs$1.readFileSync(m,"utf-8"));switch(n){case "network":g=f.networkRequestsCount;break;case "console":g=f.consoleLogsCount;break;case "api-calls":g=f.apiCallsCount;break}}catch{}let p=await Ft(o,l,u,g);b(e,200,p);}catch(i){b(e,500,{error:i instanceof Error?i.message:String(i)});}}function Gt(t,e,r){let s=ae(path.join(r,"index.json"));if(!s){b(e,404,{error:"Test index not found"});return}let n=new Map;for(let o of s){if(o.isRetry)continue;let i=n.get(o.filePath);switch(i||(i={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},n.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(n.entries()).map(([o,i])=>({filePath:o,...i})).sort((o,i)=>o.filePath.localeCompare(i.filePath));b(e,200,{files:a});}function Wt(t,e,r){if(!fs$1.existsSync(r)){b(e,200,{runs:[],totalSizeBytes:0});return}try{let s=[],n=0,a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!Be.test(o.name))continue;let i=path.join(r,o.name),d=ie(i),l=fs$1.readdirSync(i,{withFileTypes:!0}).filter(u=>u.isDirectory());s.push({folderName:o.name,totalSizeBytes:d,testCount:l.length}),n+=d;}s.sort((o,i)=>i.folderName.localeCompare(o.folderName)),b(e,200,{runs:s,totalSizeBytes:n});}catch(s){b(e,500,{error:s instanceof Error?s.message:String(s)});}}function Kt(t,e,r){try{let s=0,n=0;if(fs$1.existsSync(r)){let a=fs$1.readdirSync(r,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||!Be.test(o.name))continue;let i=path.join(r,o.name),d=ie(i);fs$1.rmSync(i,{recursive:!0,force:!0}),n+=d,s++;}}b(e,200,{deletedCount:s,freedBytes:n});}catch(s){b(e,500,{error:s instanceof Error?s.message:String(s)});}}function Jt(t,e,r,s){if(!Be.test(s)){b(e,400,{error:"Invalid folder name"});return}let n=path.join(r,s);try{if(!fs$1.statSync(n).isDirectory()){b(e,404,{error:"Not found"});return}}catch{b(e,404,{error:"Not found"});return}try{let a=ie(n);fs$1.rmSync(n,{recursive:!0,force:!0}),b(e,200,{deleted:s,freedBytes:a});}catch(a){b(e,500,{error:a instanceof Error?a.message:String(a)});}}function Yt(t,e,r){b(e,200,{status:"shutting_down"}),r.close();}function Oe(t,e,r){if(!fs$1.existsSync(r)){b(e,404,{error:"File not found"});return}try{let s=fs$1.readFileSync(r),n=path.extname(r).toLowerCase(),a=Is[n]??"application/octet-stream";e.writeHead(200,{"Content-Type":a}),e.end(s);}catch(s){b(e,500,{error:s instanceof Error?s.message:String(s)});}}var Is={".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 Es=9323,Ps=10,Ns=1800*1e3;function Y(t,e){return new Promise((r,s)=>{let n=e?.port??Es,a=Date.now(),o,i=0,d=fs$1.existsSync(path.join(t,"artifacts"))?path.join(t,"artifacts"):fs$1.existsSync(path.join(t,"..","artifacts"))?path.join(t,"..","artifacts"):path.join(t,"artifacts");function l(){clearTimeout(o),o=setTimeout(()=>{g.close();},Ns);}let u=e?.htmlPath??null;if(!u){let p=path.dirname(t);try{let f=fs$1.readdirSync(p).find(c=>c.endsWith(".html"));f&&(u=path.join(p,f));}catch{}}let g=http.createServer((p,f)=>{if(l(),Ht(f),p.method==="OPTIONS"){f.writeHead(204),f.end();return}let c;try{c=new URL(p.url??"/",`http://${p.headers.host??"localhost"}`).pathname;}catch{b(f,400,{error:"Invalid URL"});return}if(p.method==="GET"&&(c==="/"||c==="/index.html")){if(u&&fs$1.existsSync(u)){Oe(p,f,u);return}b(f,404,{error:"HTML report not found"});return}if(p.method==="GET"&&c==="/api/health"){Ut(p,f,t,a);return}if(p.method==="GET"&&c==="/api/summary"){$t(p,f,t);return}if(p.method==="GET"&&c==="/api/tests"){zt(p,f,t);return}if(p.method==="GET"&&c==="/api/files"){Gt(p,f,t);return}let h=c.match(/^\/api\/tests\/([a-f0-9]+)\/(network|console|api-calls)$/);if(p.method==="GET"&&h){Vt(p,f,t,h[1],h[2]);return}let v=c.match(/^\/api\/tests\/([a-f0-9]+)$/);if(p.method==="GET"&&v){jt(p,f,t,v[1]);return}if(p.method==="GET"&&c==="/api/artifacts"){Wt(p,f,d);return}if(p.method==="DELETE"&&c==="/api/artifacts"){Kt(p,f,d);return}let w=c.match(/^\/api\/artifacts\/(.+)$/);if(p.method==="DELETE"&&w){Jt(p,f,d,decodeURIComponent(w[1]));return}if(p.method==="GET"&&c.startsWith("/artifacts/")){let x=decodeURIComponent(c.slice(11));if(x.includes("..")||x.includes("\0")){b(f,400,{error:"Invalid path"});return}Oe(p,f,path.join(d,x));return}if(p.method==="POST"&&c==="/api/shutdown"){Yt(p,f,g);return}b(f,404,{error:"Not found"});});function m(p){let f=c=>{c.code==="EADDRINUSE"&&i<Ps?(i++,m(p+1)):s(c);};g.once("error",f),g.listen(p,"127.0.0.1",()=>{g.removeListener("error",f);let c=g.address();if(!c||typeof c=="string"){s(new Error("Failed to get server address"));return}l(),r({port:c.port,dispose:()=>new Promise(h=>{clearTimeout(o),g.close(()=>h());})});});}m(n);})}async function Qt(t){let e=await Y(t);return {port:e.port,dispose:e.dispose}}function Bs(t,e,r){let s=JSON.stringify(t),n=r?JSON.stringify(r):null;return Nt(s,e,n)}async function He(t,e,r){try{let s=null,n=null,a=e.reportMode==="streaming"||e.reportMode==="auto"&&t.timeline.length===0&&t.summary.total>=e.streamingThreshold,o,i=e.htmlReportPath,d=path.dirname(i);fs$1.mkdirSync(d,{recursive:!0});let l="",u="[]",g=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=path.dirname(e.outputPath),f=path.join(p,".testrelic-report");try{let c=path.join(f,"index-compact.json"),h=path.join(f,"index.json");fs$1.existsSync(c)?u=fs$1.readFileSync(c,"utf-8"):fs$1.existsSync(h)&&(u=fs$1.readFileSync(h,"utf-8"));}catch{}g=r?JSON.stringify(r):null,o=Fe(l,u,null,g);}else o=Bs(t,null,r);let m=i+".tmp";if(fs$1.writeFileSync(m,o,"utf-8"),fs$1.renameSync(m,i),a){if(t.ci===null){let p=path.dirname(e.outputPath),f=path.join(p,".testrelic-report"),c=path.resolve(i);try{if(await qs(),s=await Hs(f),!s){n=await Y(f,{htmlPath:c}),s=n.port;let h=setInterval(()=>{},6e4),v=()=>{clearInterval(h),n?.dispose();};process.on("SIGINT",v),process.on("SIGTERM",v),setTimeout(v,1800*1e3).unref();}if(s){process.stderr.write(`
|
|
2548
2548
|
Report server: http://127.0.0.1:${s}
|
|
2549
|
-
`);try{let h=Fe(l,u,s,g),v=i+".tmp";fs$1.writeFileSync(v,h,"utf-8"),fs$1.renameSync(v,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let p=path.dirname(e.outputPath),f=path.join(p,"artifacts");if(fs$1.existsSync(f))try{let c=await
|
|
2550
|
-
`);}}var de=9323,
|
|
2549
|
+
`);try{let h=Fe(l,u,s,g),v=i+".tmp";fs$1.writeFileSync(v,h,"utf-8"),fs$1.renameSync(v,i);}catch{}}}catch{}}}else if(e.openReport&&t.ci===null&&e.includeArtifacts){let p=path.dirname(e.outputPath),f=path.join(p,"artifacts");if(fs$1.existsSync(f))try{let c=await Qt(f);s=c.port,process.on("exit",()=>{c.dispose();});}catch{}}if(e.openReport&&t.ci===null)if(a&&s)De(`http://127.0.0.1:${s}`);else {let p=path.resolve(i);De(p);}}catch(s){process.stderr.write(`[testrelic] Failed to write HTML report: ${s instanceof Error?s.message:String(s)}
|
|
2550
|
+
`);}}var de=9323,rr=10;async function Os(){for(let t=de;t<de+rr;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),500),s=await fetch(`http://127.0.0.1:${t}/api/health`,{signal:e.signal});if(clearTimeout(r),s.ok)return t}catch{}return null}async function qs(){for(let t=de;t<de+rr;t++)try{let e=new AbortController,r=setTimeout(()=>e.abort(),1e3);await fetch(`http://127.0.0.1:${t}/api/shutdown`,{method:"POST",signal:e.signal}),clearTimeout(r);}catch{}await new Promise(t=>setTimeout(t,300));}async function Hs(t){let r=[path.join(__dirname,"cli.cjs"),path.join(__dirname,"cli.js"),path.join(__dirname,"..","dist","cli.cjs"),path.join(__dirname,"..","dist","cli.js")].find(s=>fs$1.existsSync(s));if(!r){let s=await Y(t);return process.on("exit",()=>{s?.dispose();}),s.port}return new Promise(s=>{let n=child_process.spawn(process.execPath,[r,"serve",t],{detached:true,stdio:["ignore","ignore","pipe"],env:{...process.env}}),a="",o=false,i=setTimeout(()=>{o||(o=true,n.stderr?.removeAllListeners(),Os().then(s));},5e3);n.stderr?.on("data",d=>{a+=d.toString();let l=a.match(/127\.0\.0\.1:(\d+)/);l&&!o&&(o=true,clearTimeout(i),n.stderr?.removeAllListeners(),n.unref(),s(Number(l[1])));}),n.on("error",()=>{o||(o=true,clearTimeout(i),s(null));}),n.on("exit",()=>{o||(o=true,clearTimeout(i),s(null));}),n.unref();})}var zs=20,Ue=0,$e=[];async function nr(t,e){Ue>=zs&&await new Promise(r=>$e.push(r)),Ue++;try{return await promises.copyFile(t,e),!0}catch{return false}finally{Ue--,$e.length>0&&$e.shift()();}}var Z=[];async function ar(){Z.length!==0&&(await Promise.allSettled(Z),Z.length=0);}function ir(t){let e=new Date,r=a=>String(a).padStart(2,"0"),s=`${e.getFullYear()}-${r(e.getMonth()+1)}-${r(e.getDate())}T${r(e.getHours())}-${r(e.getMinutes())}-${r(e.getSeconds())}`;if(!fs$1.existsSync(path.join(t,s)))return s;let n=1;for(;fs$1.existsSync(path.join(t,`${s}-${n}`));)n++;return `${s}-${n}`}function js(t){let e=t.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return e.length>100&&(e=e.substring(0,100).replace(/-+$/,"")),e||"unnamed-test"}function or(t,e,r,s,n){let a=t.find(m=>m.name==="screenshot"&&m.path),o=t.find(m=>m.name==="video"&&m.path);if(!a&&!o)return null;let i=js(e);r>0&&(i+=`--retry-${r}`);let d=n?["artifacts",n,i]:["artifacts",i],l=path.join(s,...d),u=d,g={};try{fs$1.mkdirSync(l,{recursive:!0});}catch{return null}if(a?.path&&fs$1.existsSync(a.path)){let p=`screenshot${path.extname(a.path)||".png"}`,f=path.join(l,p);Z.push(nr(a.path,f).then(()=>{})),g.screenshot=`${u.join("/")}/${p}`;}if(o?.path&&fs$1.existsSync(o.path)){let p=`video${path.extname(o.path)||".webm"}`,f=path.join(l,p);Z.push(nr(o.path,f).then(()=>{})),g.video=`${u.join("/")}/${p}`;}return !g.screenshot&&!g.video?null:g}var Ws=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(-\d+)?$/,Ks="1.0";function Js(t){let e=path.extname(t).toLowerCase();return [".png",".jpg",".jpeg",".gif",".bmp",".webp"].includes(e)?"screenshot":[".webm",".mp4",".avi",".mov"].includes(e)?"video":"other"}function lr(t,e,r){let s=[];try{let n=fs$1.readdirSync(t,{withFileTypes:!0});for(let a of n){if(!a.isFile())continue;let o=path.join(t,a.name),i=fs$1.statSync(o);s.push({name:a.name,type:Js(a.name),relativePath:`artifacts/${e}/${r}/${a.name}`,sizeBytes:i.size});}}catch{}return {testName:r,files:s}}function Ys(t,e){let r=path.join(t,e),s=[],n=0;try{let o=fs$1.readdirSync(r,{withFileTypes:!0});for(let i of o){if(!i.isDirectory())continue;let d=lr(path.join(r,i.name),e,i.name);s.push(d);for(let l of d.files)n+=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 s.sort((o,i)=>o.testName.localeCompare(i.testName)),{folderName:e,timestamp:a,totalSizeBytes:n,testCount:s.length,tests:s,isCurrentRun:false}}function dr(t,e){let r=path.join(t,"artifacts"),s=[],n=[],a=0;try{let i=fs$1.readdirSync(r,{withFileTypes:!0});for(let d of i)if(d.isDirectory())if(Ws.test(d.name)){let l=Ys(r,d.name);s.push({...l,isCurrentRun:d.name===e});}else {let l=lr(path.join(r,d.name),d.name,d.name);n.push(l);for(let u of l.files)a+=u.sizeBytes;}}catch{}s.sort((i,d)=>d.timestamp.localeCompare(i.timestamp)),n.length>0&&(n.sort((i,d)=>i.testName.localeCompare(d.testName)),s.push({folderName:"__legacy__",timestamp:"1970-01-01T00:00:00",totalSizeBytes:a,testCount:n.length,tests:n,isCurrentRun:false}));let o=s.reduce((i,d)=>i+d.totalSizeBytes,0);return {schemaVersion:Ks,generatedAt:new Date().toISOString(),artifactBaseDir:"artifacts",totalSizeBytes:o,runs:s,serverPort:null}}function rn(t){let e=path.resolve(t);for(;;){if(fs$1.existsSync(path.join(e,".git")))return e;let r=path.dirname(e);if(r===e)return null;e=r;}}function pr(t){try{let e=rn(t);if(!e)return;let r=path.join(e,".gitignore"),s=path.relative(e,t).replace(/\\/g,"/"),n=s.endsWith("/")?s:`${s}/`;if(fs$1.existsSync(r)&&fs$1.readFileSync(r,"utf-8").split(`
|
|
2551
2551
|
`).map(d=>d.trim()).some(d=>d===n||d===s))return;let a=`
|
|
2552
2552
|
# TestRelic test artifacts
|
|
2553
2553
|
${n}
|
|
2554
|
-
`;fs$1.appendFileSync(r,a,"utf-8");}catch{}}function hr(t,e){let r=[];for(let s of t){let n=
|
|
2555
|
-
`}function
|
|
2554
|
+
`;fs$1.appendFileSync(r,a,"utf-8");}catch{}}function hr(t,e){let r=[];for(let s of t){let n=sn(s),a=nn(s),o=an(s,n,a,e),i=on(s,n,a);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:s.startedAt,durationOnUrl:s.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:s.specFile,test:n,tests:[a],_testTitle:s.title});continue}r.push(...o,...i);}return r.sort(ln),dn(r,t),r.map((s,n)=>s.type==="navigation"?{...{index:n,type:"navigation",url:s.url,timestamp:s.timestamp,durationOnUrl:s.durationOnUrl??0,navigationType:s.navigationType,domContentLoadedAt:s.domContentLoadedAt??null,networkIdleAt:s.networkIdleAt??null,networkStats:s.networkStats??null,specFile:s.specFile,test:s.test},tests:s.tests}:{...{index:n,type:"api_call",callId:s.callId,method:s.method,url:s.url,timestamp:s.timestamp,responseTime:s.responseTime??null,request:s.request,response:s.response??null,...s.error?{error:s.error}:{},assertions:s.assertions??[],specFile:s.specFile,test:s.test},tests:s.tests})}function sn(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 nn(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 an(t,e,r,s){let n=[];for(let a of t.navigations)s.navigationTypes!==null&&!s.navigationTypes.includes(a.navigationType)||n.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 n}function on(t,e,r){if(!t.apiCalls||t.apiCalls.length===0)return [];let s=t.apiAssertions??[];return t.apiCalls.map(n=>{let a=s.filter(i=>i.callId===n.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 n.responseStatusCode!==null&&n.responseStatusText!==null&&(o={statusCode:n.responseStatusCode,statusText:n.responseStatusText,headers:n.responseHeaders,body:gr(n.responseBody)}),{type:"api_call",callId:n.id,method:n.method,url:n.url,timestamp:n.timestamp,responseTime:n.error?null:n.responseTimeMs,request:{headers:n.requestHeaders,body:gr(n.requestBody)},response:o,...n.error?{error:n.error}:{},assertions:a,specFile:t.specFile,test:e,tests:[r],_testTitle:t.title}})}function ln(t,e){let r=new Date(t.timestamp).getTime(),s=new Date(e.timestamp).getTime();if(r!==s)return r-s;let n={navigation:0,api_call:1},a=n[t.type],o=n[e.type];return a!==o?a-o:t.type==="api_call"&&e.type==="api_call"&&t.callId&&e.callId?fr(t.callId)-fr(e.callId):0}function fr(t){let e=t.match(/(\d+)$/);return e?parseInt(e[1],10):0}function dn(t,e){for(let r=0;r<t.length;r++){let s=t[r];if(s.type!=="navigation")continue;let n=new Date(s.timestamp).getTime(),a=null;for(let o=r+1;o<t.length;o++)if(t[o]._testTitle===s._testTitle){a=new Date(t[o].timestamp).getTime();break}if(a!==null)s.durationOnUrl=Math.max(0,a-n);else {let o=e.find(i=>i.title===s._testTitle);if(o){let i=new Date(o.completedAt).getTime();s.durationOnUrl=Math.max(0,i-n);}}}}function gr(t){if(t==null)return null;try{return JSON.parse(t)}catch{return t}}function H(t,e){let r=t.length,s=Math.min(Math.ceil(e/100*r)-1,r-1);return t[Math.max(0,s)]}function je(t){try{let e=new URL(t);return e.origin+e.pathname}catch{return t}}function cn(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 mr(t,e){let r=0,s=0,n=0,a=0,o=0;for(let y of t)switch(y.status){case "passed":r++;break;case "failed":s++;break;case "flaky":n++;break;case "skipped":a++;break;case "timedout":o++;break}let i=[];for(let y of t)y.apiCalls&&i.push(...y.apiCalls);let d=i.length,l=new Set,u={},g={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},m=[];for(let y of i)l.add(je(y.url)),u[y.method]=(u[y.method]??0)+1,g[cn(y.responseStatusCode)]+=1,m.push(y.responseTimeMs);let p=null;if(m.length>0){let y=[...m].sort((R,U)=>R-U),k=y.reduce((R,U)=>R+U,0);p={avg:Math.round(k/y.length),min:y[0],max:y[y.length-1],p50:H(y,50),p95:H(y,95),p99:H(y,99)};}let f=0,c=0,h=0;for(let y of t)if(y.apiAssertions)for(let k of y.apiAssertions)f++,k.status==="passed"?c++:h++;let v=0,w=new Set;for(let y of t){v+=y.navigations.length;for(let k of y.navigations)w.add(k.url);}let x=0,T={};function M(y){for(let k of y)x++,T[k.category]=(T[k.category]??0)+1,k.children.length>0&&M(k.children);}for(let y of t)y.actions&&M(y.actions);return {total:t.length,passed:r,failed:s,flaky:n,skipped:a,timedout:o,totalApiCalls:d,uniqueApiUrls:l.size,apiCallsByMethod:u,apiCallsByStatusRange:g,apiResponseTime:p,totalAssertions:f,passedAssertions:c,failedAssertions:h,totalNavigations:v,uniqueNavigationUrls:w.size,totalTimelineSteps:e,totalActionSteps:x,actionStepsByCategory:T}}function un(t){let e=56-t.length;return e>0?t+" ".repeat(e):t}function I(t){return `\u2502 ${un(t)} \u2502
|
|
2555
|
+
`}function Ve(t,e,r,s){if(s||t.total===0)return;let n=`\u250C${"\u2500".repeat(58)}\u2510
|
|
2556
2556
|
`,a=`\u2514${"\u2500".repeat(58)}\u2518
|
|
2557
2557
|
`,o=I(""),i=n;i+=I("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+=I(`Tests: ${t.total} total (${d.join(" ")})`),t.totalNavigations>0&&(i+=I(`Navigations: ${t.totalNavigations} visits across ${t.uniqueNavigationUrls} unique URLs`)),t.totalApiCalls>0){i+=I(`API Calls: ${t.totalApiCalls} calls across ${t.uniqueApiUrls} unique endpoints`);let l=Object.entries(t.apiCallsByMethod).filter(([,g])=>g>0).map(([g,m])=>`${g}: ${m}`);l.length>0&&(i+=I(` ${l.join(" ")}`));let u=Object.entries(t.apiCallsByStatusRange).filter(([,g])=>g>0).map(([g,m])=>`${g}: ${m}`);u.length>0&&(i+=I(` ${u.join(" ")}`)),t.apiResponseTime&&(i+=I(` Avg response: ${t.apiResponseTime.avg}ms P95: ${t.apiResponseTime.p95}ms`));}if(t.totalAssertions>0&&(i+=I(`Assertions: ${t.totalAssertions} total (${t.passedAssertions} \u2713 ${t.failedAssertions} \u2717)`)),t.totalActionSteps>0){let l=[],u=t.actionStepsByCategory;u.ui_action&&l.push(`${u.ui_action} UI`),u.assertion&&l.push(`${u.assertion} assertions`),u.custom_step&&l.push(`${u.custom_step} custom`);let g=l.length>0?` (${l.join(" ")})`:"";i+=I(`Actions: ${t.totalActionSteps} steps${g}`);}i+=I(`Report: ${r}`),i+=I(`Data: ${e}`),i+=a,i+=`For more information visit us at https://docs.testrelic.ai
|
|
2558
|
-
`,process.stderr.write(i);}var
|
|
2559
|
-
`)[0]?.trim();return s?F(`git remote get-url ${s}`,t):null}function ee(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 Sr(t){let e=t.split("/").filter(Boolean);return e[e.length-1]??t}function
|
|
2558
|
+
`,process.stderr.write(i);}var pn=new Set(["pw:api","expect","test.step"]);function fn(t){return t==="expect"?"assertion":t==="test.step"?"custom_step":"ui_action"}function Ge(t,e,r){if(pn.has(t.category)){let s=[];for(let a of t.steps)Ge(a,e,s);let n=t.startTime.getTime()-e.getTime();r.push({title:t.title,category:fn(t.category),timestamp:t.startTime.toISOString(),duration:t.duration,videoOffset:n>=0?n/1e3:null,status:t.error?"failed":"passed",error:t.error?.message??null,children:s});}else for(let s of t.steps)Ge(s,e,r);}function vr(t,e){let r=[];for(let s of t)Ge(s,e,r);return r}var mn=new Set(["localhost","127.0.0.1","0.0.0.0"]);function br(t){let e=new URL(t);if(e.protocol!=="https:"&&!(e.protocol==="http:"&&mn.has(e.hostname)))throw core.createError(core.ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${e.protocol}//${e.hostname}`)}var vn=3e3;async function We(t){let e=new AbortController,r=setTimeout(()=>e.abort(),vn);try{return (await fetch(`${t}/health`,{method:"GET",signal:e.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function xr(t){return new Promise(e=>setTimeout(e,t))}async function yr(t){try{let r=(await t.json()).error;if(r&&typeof r.message=="string"){let s=r.details;if(Array.isArray(s)&&s.length>0){let n=s.map(a=>`${a.field}: ${a.message}`).join(", ");return `${r.message} (${n})`}return r.message}}catch{}return `HTTP ${t.status}`}async function Ke(t,e,r){let s=new AbortController,n=setTimeout(()=>s.abort(),r);try{let a=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:s.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 xr(d);let l=await fetch(`${t}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e}),signal:s.signal});if(l.ok){let u=await l.json();return {accessToken:u.accessToken,refreshToken:u.refreshToken,expiresIn:u.expiresIn,orgId:u.orgId,orgName:u.orgName,userId:u.userId,userName:u.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return a.status===400?{code:"validation_error",message:await yr(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 yr(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(n);}}function Je(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 wr(t,e,r){let s=new AbortController,n=setTimeout(()=>s.abort(),r);try{let a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:s.signal});if(a.status===429){let i=a.headers.get("Retry-After"),d=i?parseInt(i,10)*1e3:5e3;!isNaN(d)&&d>0&&(await xr(d),a=await fetch(`${t}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e}),signal:s.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(n);}}async function kr(t,e,r,s,n,a){let o=new AbortController,i=setTimeout(()=>o.abort(),n);try{let d={gitId:r,displayName:s};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 u=await l.json();return {repoId:u.repoId,displayName:u.displayName}}catch{return null}finally{clearTimeout(i);}}var kn=5e3;function F(t,e){try{return child_process.execSync(t,{cwd:e,timeout:kn,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function Tr(t){let e=F("git rev-parse --abbrev-ref HEAD",t),r=F("git rev-parse --short HEAD",t),s=F("git log -1 --pretty=%s",t),n=F("git log -1 --format=%an",t)??F("git config user.name",t),a=Tn(t),o=a?ee(a):null;return {branch:e,commitSha:r,commitMessage:s,commitAuthor:n,remoteUrl:o}}function Tn(t){let e=F("git remote get-url origin",t);if(e)return e;let r=F("git remote",t);if(!r)return null;let s=r.split(`
|
|
2559
|
+
`)[0]?.trim();return s?F(`git remote get-url ${s}`,t):null}function ee(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 Sr(t){let e=t.split("/").filter(Boolean);return e[e.length-1]??t}function Ye(t){try{let e=fs$1.readFileSync(path.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 te(t){let e=Ye(t);return e||`local/${path.basename(t)}`}var Sn=new Set(["smoke","regression","nightly","ci"]);function ue(){let t=process.env.TESTRELIC_RUN_TYPE?.trim().toLowerCase();if(t&&Sn.has(t))return t}var An=1048576,pe=[1e3,3e3,9e3],fe=3,In=90*1048576,_n=new Set(["e2e","mobile","unit"]);function Ze(t){if(t&&t.length>0&&t.every(n=>n.testType==="api")){let n=new Map;for(let i of t){let d=i.apiProtocol??"rest";n.set(d,(n.get(d)??0)+1);}let a="rest",o=0;for(let[i,d]of n)d>o&&(o=d,a=i);return {testType:"api",apiProtocol:a,metadata:{testType:"api",primaryProtocol:a}}}let e=new Map;for(let n of t??[])_n.has(n.testType)&&e.set(n.testType,(e.get(n.testType)??0)+1);let r=null,s=0;for(let[n,a]of e)a>s&&(s=a,r=n);return {testType:r??"e2e"}}function Xe(t,e,r,s,n,a){let o=a?.cloudPlatform?a.cloudPlatform:s?.provider&&s.provider!=="unknown"?s.provider:"local",i=ue(),d=Ze(n),l=d.testType==="api"?d:null,u=l&&n?n.map(m=>m.apiProtocol?m:{...m,apiProtocol:l.apiProtocol}):n;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},...u&&u.length>0?{tests:u}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...t.completedAt?{finishedAt:t.completedAt}:{},...t.totalDuration?{duration:t.totalDuration}:{},...s?.provider?{ciProvider:s.provider}:{},...s?.runUrl?{ciRunUrl:s.runUrl}:{},...a?.cloudPlatform?{cloudPlatform:a.cloudPlatform}:{},...a?.cloudBuildId?{cloudBuildId:a.cloudBuildId}:{},...a?.cloudSessionId?{cloudSessionId:a.cloudSessionId}:{}}}function Qe(t){return typeof t=="string"?Buffer.byteLength(t,"utf-8"):0}function et(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:Qe(e.responseBody),bytesOut:typeof e.bytesOut=="number"?e.bytesOut:Qe(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 tt(t){return Array.isArray(t)?t.map(e=>{let r=e.responseStatusCode??e.statusCode??0,s=e.timestamp??null;return {method:e.method??"GET",url:e.url??"",status:r,statusCode:r,type:"xhr",size:Qe(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:s,startedAt:s}}):[]}function rt(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 s=r.status==="failed"?"failed":"passed",n=typeof r.expression=="string"&&r.expression.trim()?r.expression.trim():null,a=r.kind??r.type??"assertion",o=s==="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:n??r.description??`${a} assertion`,status:s,detail:o}})}async function ge(t){return new Promise(e=>setTimeout(e,t))}function Mn(t){let e={};for(let[r,s]of Object.entries(t))s!=null&&(e[r]=s);return e}async function Rr(t,e,r){for(let s=0;s<fe;s++)try{let n=await fetch(t,e);if(n.ok)return n;if(n.status===401&&r&&s===0){let a=await r();if(a){let o={...e,headers:{...e.headers,Authorization:`Bearer ${a}`}},i=await fetch(t,o);if(i.ok)return i}return null}if(n.status===429&&s<fe-1){let a=n.headers.get("Retry-After"),o=a?parseInt(a,10)*1e3:pe[s];!isNaN(o)&&o>0?await ge(o):await ge(pe[s]);continue}if(n.status>=500&&s<fe-1){await ge(pe[s]);continue}return n}catch{if(s<fe-1){await ge(pe[s]);continue}return null}return null}var Ln=util.promisify(zlib.gzip);function Cr(t,e){if(!Array.isArray(t.tests))return t;let r=t.tests.map(s=>{let{consoleLogs:n,networkRequests:a,apiCalls:o,...i}=s;return e?i:{...i,...o!==void 0?{apiCalls:o}:{}}});return {...t,tests:r}}var En=["consoleLogs","networkRequests","apiCalls","actions","navigations","protocolAssertions"];function Pn(t){if(!Array.isArray(t.tests))return t;let e=new Set(En),r=t.tests.map(s=>{let n={};for(let a in s)if(!e.has(a))if(a==="failure"&&s[a]&&typeof s[a]=="object"){let o=s[a];n.failure={message:o.message??null,line:o.line??null};}else n[a]=s[a];return n});return {...t,tests:r}}function Nn(t){let e=new Set(["tests","timeline","unifiedTimeline","navigations"]),r={};for(let s in t)e.has(s)||(r[s]=t[s]);return r.tests=[],r}async function st(t,e=In){let r={"Content-Type":"application/json"},s=JSON.stringify(t),n=t,a=Array.isArray(n?.tests)?n.tests.length:0,o=i=>Buffer.byteLength(i,"utf-8")>e;if(a>0&&o(s)){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.
|
|
2560
2560
|
`),s=JSON.stringify(Cr(n,false)),o(s)&&(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.
|
|
2561
2561
|
`),s=JSON.stringify(Cr(n,true))),o(s)&&(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.
|
|
2562
|
-
`),s=JSON.stringify(
|
|
2563
|
-
`),s=JSON.stringify(
|
|
2562
|
+
`),s=JSON.stringify(Pn(n))),o(s)&&(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.
|
|
2563
|
+
`),s=JSON.stringify(Nn(n)));}return Buffer.byteLength(s,"utf-8")>An?(r["Content-Encoding"]="gzip",{body:await Ln(Buffer.from(s,"utf-8")),headers:r}):{body:s,headers:r}}async function Ar(t,e,r,s){let n=`${t}/runs`,{body:a,headers:o}=await st(r);o.Authorization=`Bearer ${e}`;let i=await Rr(n,{method:"POST",headers:o,body:a},s);return i?.ok?{success:true,statusCode:i.status,error:null}:i?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:i?`Upload failed with status ${i.status}`:"Upload failed after retries",statusCode:i?.status??null,payload:r,targetEndpoint:n,method:"POST"}}async function Ir(t,e,r){let s=`${t}/runs/init`;try{let n=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(Mn(r))});return n.ok?{runId:(await n.json()).runId}:null}catch{return null}}function _r(t,e,r,s){let n=`${t}/runs/${r}/tests`;fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(s)}).catch(()=>{});}async function Mr(t,e,r,s){let n=`${t}/runs/${r}/finalize`;return (await Rr(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(s)}))?.ok??false}function nt(t,e,r,s){let n=`${t}/runs/${r}/finalize`,a=new Date,o={finishedAt:a.toISOString(),duration:a.getTime()-new Date(s).getTime(),summary:{}};fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)}).catch(()=>{});}var qn="1.0.0",Lr=10;function Er(t){return t instanceof Error?t.message:String(t)}function Hn(t){return t>=400&&t<500&&t!==408&&t!==429}function re(t,e,r,s,n,a,o,i){try{fs$1.mkdirSync(t,{recursive:!0});let d=Date.now(),l=`${d}-${e}-${r}.json`,u=path.join(t,l),g={version:qn,queuedAt:new Date(d).toISOString(),reason:s,retryCount:0,targetEndpoint:n,method:a,payload:o,headers:i},m=u+".tmp";fs$1.writeFileSync(m,JSON.stringify(g,null,2),"utf-8"),fs$1.renameSync(m,u);}catch(d){d.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
|
|
2564
2564
|
`):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
|
|
2565
2565
|
`);}}async function Dr(t,e,r){let s;try{s=fs$1.readdirSync(t).filter(a=>a.endsWith(".json")&&!a.endsWith(".tmp")).sort();}catch{return}if(s.length===0)return;let n=[];for(let a=0;a<s.length;a+=Lr)n.push(s.slice(a,a+Lr));for(let a of n)for(let o of a){let i=path.join(t,o),d;try{if(!fs$1.statSync(i).isFile())continue;let u=JSON.parse(fs$1.readFileSync(i,"utf-8"));if(!core.isValidQueueEntry(u)){process.stderr.write(`\u26A0 TestRelic: Corrupted queue file deleted: ${o}
|
|
2566
2566
|
`),fs$1.unlinkSync(i);continue}d=u;}catch(l){process.stderr.write(`\u26A0 TestRelic: Skipping unreadable queue file ${o}: ${Er(l)}
|
|
2567
|
-
`);try{fs$1.unlinkSync(i);}catch{}continue}try{let{body:l,headers:u}=await
|
|
2567
|
+
`);try{fs$1.unlinkSync(i);}catch{}continue}try{let{body:l,headers:u}=await st(d.payload),g={...d.headers,...u,Authorization:`Bearer ${r}`},m=await fetch(d.targetEndpoint,{method:d.method,headers:g,body:l});if(m.ok)fs$1.unlinkSync(i);else if(Hn(m.status)){process.stderr.write(`\u26A0 TestRelic: Queue entry ${o} rejected (HTTP ${m.status}) \u2014 moving aside; it will not be retried.
|
|
2568
2568
|
`);try{fs$1.renameSync(i,`${i}.failed`);}catch{try{fs$1.unlinkSync(i);}catch{}}}else {process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 server returned HTTP ${m.status} for ${o}; will retry later.
|
|
2569
2569
|
`);return}}catch(l){process.stderr.write(`\u26A0 TestRelic: Queue flush paused \u2014 ${Er(l)}; will retry later.
|
|
2570
|
-
`);return}}}function Br(t,e){try{let r=fs$1.readdirSync(t).filter(n=>(n.endsWith(".json")||n.endsWith(".failed"))&&!n.endsWith(".tmp")),s=Date.now();for(let n of r){let a=path.join(t,n);try{let o=fs$1.readFileSync(a,"utf-8"),d=JSON.parse(o).queuedAt;if(typeof d=="string"){let l=new Date(d).getTime();s-l>e&&fs$1.unlinkSync(a);}}catch{try{fs$1.unlinkSync(a);}catch{}}}}catch{}}var
|
|
2571
|
-
`);return}try{if(br(this.config.endpoint),this.gitMetadata=Tr(),!await
|
|
2572
|
-
`);return}let r=await
|
|
2570
|
+
`);return}}}function Br(t,e){try{let r=fs$1.readdirSync(t).filter(n=>(n.endsWith(".json")||n.endsWith(".failed"))&&!n.endsWith(".tmp")),s=Date.now();for(let n of r){let a=path.join(t,n);try{let o=fs$1.readFileSync(a,"utf-8"),d=JSON.parse(o).queuedAt;if(typeof d=="string"){let l=new Date(d).getTime();s-l>e&&fs$1.unlinkSync(a);}}catch{try{fs$1.unlinkSync(a);}catch{}}}}catch{}}var Wn=3e5,Kn=864e5,Jn=6e4,Or=3e4,ot="https://platform.testrelic.ai/settings/api-keys",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.
|
|
2571
|
+
`);return}try{if(br(this.config.endpoint),this.gitMetadata=Tr(),!await We(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.
|
|
2572
|
+
`);return}let r=await Ke(this.config.endpoint,this.config.apiKey,this.config.timeout);if(Je(r)){this.handleAuthError(r.code,r.statusCode);return}let s=r;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},process.stderr.write(`\u2713 TestRelic: Connected to cloud (${s.orgName} / ${s.userName})
|
|
2573
2573
|
`),await this.resolveRepoId(),this.config.queueDirectory&&(Br(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)}
|
|
2574
|
-
`);}}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()+
|
|
2574
|
+
`);}}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()+Wn<e)return true;if(!this.config||!this.authState.refreshToken)return this.switchToLocalMode("token_expired_no_refresh"),false;try{let r=await wr(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}).
|
|
2575
2575
|
`));}async dispose(){if(this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=null),this.flushPromise){try{await Promise.race([this.flushPromise,new Promise(e=>setTimeout(e,Or))]);}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.
|
|
2576
|
-
\u2192 Manage keys: ${
|
|
2576
|
+
\u2192 Manage keys: ${ot}
|
|
2577
2577
|
`);break;case "expired_key":this.setLocalMode("expired_api_key"),process.stderr.write(`\u26A0 TestRelic: API key has expired. Running in local mode.
|
|
2578
|
-
\u2192 Generate a new key: ${
|
|
2578
|
+
\u2192 Generate a new key: ${ot}
|
|
2579
2579
|
`);break;case "validation_error":this.setLocalMode("validation_error"),process.stderr.write(`\u26A0 TestRelic: API key format invalid. Running in local mode.
|
|
2580
|
-
\u2192 Manage keys: ${
|
|
2580
|
+
\u2192 Manage keys: ${ot}
|
|
2581
2581
|
`);break;case "rate_limited":this.setLocalMode("rate_limited"),process.stderr.write(`\u26A0 TestRelic: Rate limited during authentication. Running in local mode.
|
|
2582
2582
|
`);break;case "timeout":this.setLocalMode("auth_timeout"),process.stderr.write(`\u26A0 TestRelic: Authentication timed out. Running in local mode.
|
|
2583
2583
|
`);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
|
|
2584
|
-
`);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?ee(this.gitMetadata.remoteUrl):null,r=e?Sr(e):this.config.projectName??te(process.cwd()),s=e??this.config.projectName??te(process.cwd()),n=this.readRepoCache(s);if(n){this.repoId=n.repoId;return}try{let a=await kr(this.config.endpoint,this.authState.accessToken,s,r,this.config.timeout,this.gitMetadata?.branch);a&&(this.repoId=a.repoId,this.writeRepoCache(s,a.repoId,a.displayName));}catch{}!e&&!this.config.projectName&&!
|
|
2585
|
-
`);}readRepoCache(e){if(!this.config)return null;let r=path.join(this.config.queueDirectory,"..","cache","repo.json");try{if(!fs$1.existsSync(r))return null;let s=fs$1.readFileSync(r,"utf-8"),n=JSON.parse(s);if(n.gitId!==e||Date.now()-n.resolvedAt>
|
|
2586
|
-
`),this.startBackgroundFlush();}}}catch{}},
|
|
2584
|
+
`);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let e=this.gitMetadata?.remoteUrl?ee(this.gitMetadata.remoteUrl):null,r=e?Sr(e):this.config.projectName??te(process.cwd()),s=e??this.config.projectName??te(process.cwd()),n=this.readRepoCache(s);if(n){this.repoId=n.repoId;return}try{let a=await kr(this.config.endpoint,this.authState.accessToken,s,r,this.config.timeout,this.gitMetadata?.branch);a&&(this.repoId=a.repoId,this.writeRepoCache(s,a.repoId,a.displayName));}catch{}!e&&!this.config.projectName&&!Ye(process.cwd())&&process.stderr.write(`\u2139 TestRelic: No git remote or package.json detected. Set project.name in .testrelic for stable project identity.
|
|
2585
|
+
`);}readRepoCache(e){if(!this.config)return null;let r=path.join(this.config.queueDirectory,"..","cache","repo.json");try{if(!fs$1.existsSync(r))return null;let s=fs$1.readFileSync(r,"utf-8"),n=JSON.parse(s);if(n.gitId!==e||Date.now()-n.resolvedAt>Kn)return null;let a=this.hashApiKey();return a&&n.apiKeyHash!==a?null:n}catch{return null}}writeRepoCache(e,r,s){if(!this.config)return;let n=path.join(this.config.queueDirectory,"..","cache"),a=path.join(n,"repo.json");try{fs$1.mkdirSync(n,{recursive:!0});let o={repoId:r,gitId:e,displayName:s,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},i=a+".tmp";fs$1.writeFileSync(i,JSON.stringify(o,null,2),"utf-8"),fs$1.renameSync(i,a);}catch{}}hashApiKey(){return this.config?.apiKey?crypto.createHash("sha256").update(this.config.apiKey).digest("hex").substring(0,16):null}startBackgroundFlush(){if(!this.config||!this.authState.accessToken)return;let e=this.authState.accessToken,r=this.config.queueDirectory,s=this.config.endpoint;this.flushPromise=Promise.race([Dr(r,s,e),new Promise(n=>setTimeout(n,Or))]).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 We(e))return;if(this.config?.apiKey){let s=await Ke(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!Je(s)){let n=s;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},this.failureReason=null,process.stderr.write(`\u2713 TestRelic: Cloud connectivity restored.
|
|
2586
|
+
`),this.startBackgroundFlush();}}}catch{}},Jn);}};function qr(t,e,r,s){let n=[],a=[],o=null,i=0,d=null,l=0,u=null,g=0,m=t.filter(c=>c.name===core.ATTACHMENT_NAME&&c.body),p=false;if(m.length>0)for(let c of m)try{let h=JSON.parse(c.body.toString());if(core.isTestRelicFilePayload(h)){n=n.concat(h.navigations),a=a.concat(h.apiAssertions),h.networkRequestsFile&&(o=h.networkRequestsFile,i+=h.networkRequestsCount),h.consoleLogsFile&&(d=h.consoleLogsFile,l+=h.consoleLogsCount),h.apiCallsFile&&(u=h.apiCallsFile,g+=h.apiCallsCount),p=!0;continue}if(core.isTestRelicDataPayload(h)){n=n.concat(h.navigations),Array.isArray(h.apiAssertions)&&(a=a.concat(h.apiAssertions)),i+=h.networkRequests?.length??0,g+=h.apiCalls?.length??0;let v=h.consoleLogs;Array.isArray(v)&&(l+=v.length),p=!0;}}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${r}"
|
|
2587
2587
|
`);}return p||(n=e.filter(c=>c.type==="lambdatest-navigation"&&c.description).map(c=>{try{return JSON.parse(c.description)}catch{return null}}).filter(c=>c!==null)),n.length===0&&i===0&&g===0&&!s&&!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.
|
|
2588
|
-
`),{navigations:n,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:u,apiCallsCount:g}}function me(t=process.env){let e=
|
|
2589
|
-
`),n}async function
|
|
2590
|
-
`).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function
|
|
2591
|
-
`),this.activeReportMode==="streaming"){let a=path.dirname(this.config.outputPath);this.streamingWriter=new J(a);let o=()=>{if(this.streamingWriter){try{this.streamingWriter.writeIndex(this.testIndex);let i={testRunId:this.testRunId??"",startedAt:this.startedAt,completedAt:new Date().toISOString(),totalDuration:Date.now()-new Date(this.startedAt).getTime(),...this.summaryCounters,metadata:null,reportMode:"streaming",files:[],enrichedSummary:null,validation:null,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(i);}catch{}this.streamingWriter.dispose();}try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let i=this.cloudClient.getAccessToken();i&&
|
|
2588
|
+
`),{navigations:n,apiAssertions:a,networkRequestsFile:o,networkRequestsCount:i,consoleLogsFile:d,consoleLogsCount:l,apiCallsFile:u,apiCallsCount:g}}function me(t=process.env){let e=Xn(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 Xn(t){if(!t)return;let e=t.toLowerCase().trim();if(e==="browserstack"||e==="bs")return "browserstack";if(e==="lambdatest"||e==="lt")return "lambdatest"}var na=5,ve=[1e3,3e3,9e3],j=3,aa={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip"},lt=0,dt=[];async function ia(){lt>=na&&await new Promise(t=>dt.push(t)),lt++;}function oa(){lt--,dt.length>0&&dt.shift()();}async function ye(t){return new Promise(e=>setTimeout(e,t))}function la(t){let e=t.substring(t.lastIndexOf(".")).toLowerCase();return aa[e]??"application/octet-stream"}function da(t){try{return fs$1.statSync(t).size}catch{return 0}}async function ca(t,e,r,s,n){let a=`${t}/artifacts/upload-url`,o=JSON.stringify({runId:r.runId,testId:r.testId,fileName:path.basename(r.filePath),contentType:n,type:r.type,sizeBytes:s});for(let i=0;i<j;i++)try{let d=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:o});if(d.ok)return await d.json();if(d.status>=500&&i<j-1){await ye(ve[i]);continue}return null}catch{if(i<j-1){await ye(ve[i]);continue}return null}return null}async function ua(t,e,r,s){for(let n=0;n<j;n++)try{let a=fs$1.createReadStream(e),o=stream.Readable.toWeb(a),i=await fetch(t,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(s)},body:o,duplex:"half"});if(i.ok)return !0;if(i.status>=500&&n<j-1){await ye(ve[n]);continue}return !1}catch{if(n<j-1){await ye(ve[n]);continue}return false}return false}async function pa(t,e,r){let s=`${t}/artifacts/confirm`;try{return (await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function fa(t,e,r,s){let n=da(r.filePath);if(n===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(n>s*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let a=la(r.filePath);await ia();try{let o=await ca(t,e,r,n,a);if(!o)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await ua(o.uploadUrl,r.filePath,a,n))return {success:!1,storageKey:o.storageKey,artifactId:o.artifactId,error:"presigned_put_failed"};let d=await pa(t,e,o.artifactId);return {success:d,storageKey:o.storageKey,artifactId:o.artifactId,error:d?null:"confirm_failed"}}finally{oa();}}async function Hr(t,e,r,s){let n=new Map,a=r.map(async o=>{let i=await fa(t,e,o,s);n.set(o.filePath,i);});return await Promise.allSettled(a),n}function ct(t){let r=t.getGitMetadata()?.remoteUrl;return r?ee(r):t.getConfig()?.projectName??te(process.cwd())}async function $r(t,e,r,s,n){if(!t.isCloudMode()||e!=="realtime"&&e!=="both"||!await t.ensureValidToken())return null;let o=t.getGitMetadata(),i=P(),d=me(),l=ue();return (await Ir(t.getEndpoint(),t.getAccessToken(),{runId:r,repoGitId:ct(t),branch:o?.branch??null,commit:o?.commitSha??null,commitMessage:o?.commitMessage??null,commitAuthor:o?.commitAuthor??null,startedAt:s,totalTests:null,ciProvider:i?.provider??null,ciRunUrl:i?.runUrl??null,environment:n??d.cloudPlatform??null,cloudPlatform:d.cloudPlatform??null,cloudBuildId:d.cloudBuildId??null,cloudSessionId:d.cloudSessionId??null,...l?{runType:l}:{},testType:"e2e"}))?.runId??null}var ga=true,ha=50;async function ma(t,e,r,s){let n=new Map;if(!(e?.uploadArtifacts??ga)||!await t.ensureValidToken())return n;let i=[],d=new Map;for(let p of s){if(p.artifacts.screenshot){let f=path.join(p.outputDir,p.artifacts.screenshot);i.push({filePath:f,runId:r,testId:p.testId,type:"screenshot"}),d.set(f,{testId:p.testId,field:"screenshot"});}if(p.artifacts.video){let f=path.join(p.outputDir,p.artifacts.video);i.push({filePath:f,runId:r,testId:p.testId,type:"video"}),d.set(f,{testId:p.testId,field:"video"});}}if(i.length===0)return n;let l=e?.artifactMaxSizeMb??ha,u=await Hr(t.getEndpoint(),t.getAccessToken(),i,l),g=new Map;for(let[p,f]of u){if(!f.success||!f.storageKey)continue;let c=d.get(p);if(!c)continue;let h=g.get(c.testId)??{};c.field==="screenshot"&&(h.screenshotKey=f.storageKey),c.field==="video"&&(h.videoKey=f.storageKey),g.set(c.testId,h);}for(let p of s){let f=g.get(p.testId);n.set(p.testId,{...p.artifacts,...f?.screenshotKey?{screenshotKey:f.screenshotKey}:{},...f?.videoKey?{videoKey:f.videoKey}:{}});}let m=Array.from(u.values()).filter(p=>p.success).length;return m>0&&process.stderr.write(`\u2713 TestRelic: Uploaded ${m} artifact(s) to cloud storage.
|
|
2589
|
+
`),n}async function ut(t,e,r,s,n,a,o,i,d,l,u){try{if(t.isCloudMode()&&n&&(r==="realtime"||r==="both")){let m=await t.ensureValidToken(),p=t.getGitMetadata(),f=Ze(u),c={finishedAt:o,duration:i,summary:d,...p?.commitMessage?{commitMessage:p.commitMessage}:{},testType:f.testType,...f.testType==="api"?{apiProtocol:f.apiProtocol,metadata:f.metadata}:{}};if(m){if(!await Mr(t.getEndpoint(),t.getAccessToken(),n,c)){let v=e?.queueDirectory??".testrelic/queue";re(v,s,"finalize","finalize_failed_after_retries",`${t.getEndpoint()}/runs/${n}/finalize`,"POST",c,{"Content-Type":"application/json"});}}else {let h=e?.queueDirectory??".testrelic/queue";re(h,s,"finalize",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs/${n}/finalize`,"POST",c,{"Content-Type":"application/json"});}}let g=new Map;if(t.isCloudMode()&&l&&l.length>0&&(g=await ma(t,e,s,l)),t.isCloudMode()&&(!r||r==="batch"||r==="both"))if(await t.ensureValidToken()){let p=t.getGitMetadata(),f=P(),c=ct(t),h=va(a,g),v=Xe(h,c,p,f,u,me()),w=await Ar(t.getEndpoint(),t.getAccessToken(),v,async()=>await t.ensureValidToken()?t.getAccessToken():null);if(!w.success){let x=w,T=e?.queueDirectory??".testrelic/queue";re(T,s,"batch",x.reason,x.targetEndpoint,x.method,x.payload,{"Content-Type":"application/json"});}}else {let p=e?.queueDirectory??".testrelic/queue",f=t.getGitMetadata(),c=P(),h=ct(t),v=Xe(a,h,f,c,void 0,me());re(p,s,"batch",t.getFailureReason()??"token_invalid",`${t.getEndpoint()}/runs`,"POST",v,{"Content-Type":"application/json"});}await t.dispose();}catch{try{await t.dispose();}catch{}}}function va(t,e){if(e.size===0)return t;let r=t.timeline.map(s=>{let n=s.testId;if(!n)return s;let a=e.get(n);return a?{...s,...a.screenshotKey?{screenshotKey:a.screenshotKey}:{},...a.videoKey?{videoKey:a.videoKey}:{}}:s});return {...t,timeline:r}}function B(t){try{return fs$1.readFileSync(t,"utf-8").split(`
|
|
2590
|
+
`).filter(r=>r.length>0).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(r=>r!==null)}catch{return []}}function ft(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 Sa(t,e,r){let s=`${t}::${e}::${r}`;return crypto.createHash("sha256").update(s).digest("hex").substring(0,16)}function Ca(t){return t.length<=3?"":t[t.length-2]}function Ra(t){let e=t.findIndex(r=>r.status==="passed");return e>0?`passed on retry ${e}`:null}function Aa(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 Gr(t,e){for(let r of t)e[r.category]=(e[r.category]??0)+1,r.children.length>0&&Gr(r.children,e);}function Ia(t){if(t.length===0)return null;let e=[...t].sort((s,n)=>s-n),r=e.reduce((s,n)=>s+n,0);return {avg:Math.round(r/e.length),min:e[0],max:e[e.length-1],p50:H(e,50),p95:H(e,95),p99:H(e,99)}}var Wr=2e5,be=1e5;function Vr(t,e,r,s,n,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:s.length,navUrls:[],networkRequests:n,consoleLogs:a,actionSteps:o?.length??0,actionCategories:{}};if(e){let l=new Set;for(let u of e){let g=typeof u.method=="string"?u.method:"OTHER";i.methodCounts[g]=(i.methodCounts[g]??0)+1;let m=typeof u.url=="string"?u.url:null;m&&l.size<be&&l.add(je(m));let p=typeof u.responseStatusCode=="number"?u.responseStatusCode:typeof u.statusCode=="number"?u.statusCode:null,f=p!==null&&Number.isFinite(p)?p:null;i.statusRanges[Aa(f)]++;let c=typeof u.responseTimeMs=="number"?u.responseTimeMs:typeof u.durationMs=="number"?u.durationMs:null;c!==null&&Number.isFinite(c)&&i.responseTimes.length<Wr&&i.responseTimes.push(c);}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 s)l.url&&d.size<be&&d.add(l.url);return i.navUrls=Array.from(d),o&&Gr(o,i.actionCategories),i}function _a(){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 Ma(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 La(){let t=os$1.platform();return t==="win32"?"Windows":t==="darwin"?"macOS":"Linux"}function Ea(t){let e=t.parent?.project?.()?.use;if(!e)return;let{browserName:r,channel:s}=e;if(s){let a=s.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":s}if(r){let a=r.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":r}let n=e.defaultBrowserType;if(n){let a=n.toLowerCase();return a==="chromium"?"Chromium":a==="firefox"?"Firefox":a==="webkit"?"WebKit":n}}function Pa(t,e,r){let s=r.parent?.project?.(),n="unknown";s!==void 0&&(s.use.isMobile===true?n="mobile":n="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 n}var Na="__testrelic_api_config";function Fa(t){return JSON.stringify(t,(e,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var xe=class{constructor(e){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.fixtureDataReceived=false;this.navigationsCaptured=false;this.testCount=0;this.cloudClient=null;this.cloudRunId=null;this.runTimestamp="";this.pendingArtifactEntries=[];this.detectedOs="";this.detectedSource="";this.cloudTestsBuffer=[];this.activeReportMode="embedded";this.streamingWriter=null;this.testIndex=[];this.summaryCounters={total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0,interrupted:0,totalApiCalls:0,totalAssertions:0,totalNavigations:0,totalNetworkRequests:0,totalConsoleLogs:0,totalActionSteps:0};this.streamingTestAgg=new Map;this.config=Lt(e),this.apiConfig=Mt(e);}upsertAggContribution(e,r){let s=this.streamingTestAgg.get(e);(!s||r.retryIndex>s.retryIndex)&&this.streamingTestAgg.set(e,r);}async onBegin(e,r){try{if(this.rootDir=e.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??crypto.randomUUID(),this.config.reportMode==="auto"){let a=r.allTests().length;this.activeReportMode=a>=this.config.streamingThreshold?"streaming":"embedded";}else this.activeReportMode=this.config.reportMode;let s=r.allTests().length;if(process.stderr.write(`[testrelic] Report mode: ${this.activeReportMode} (${s} tests)
|
|
2591
|
+
`),this.activeReportMode==="streaming"){let a=path.dirname(this.config.outputPath);this.streamingWriter=new J(a);let o=()=>{if(this.streamingWriter){try{this.streamingWriter.writeIndex(this.testIndex);let i={testRunId:this.testRunId??"",startedAt:this.startedAt,completedAt:new Date().toISOString(),totalDuration:Date.now()-new Date(this.startedAt).getTime(),...this.summaryCounters,metadata:null,reportMode:"streaming",files:[],enrichedSummary:null,validation:null,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(i);}catch{}this.streamingWriter.dispose();}try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let i=this.cloudClient.getAccessToken();i&&nt(this.cloudClient.getEndpoint(),i,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",o),process.on("SIGINT",o);}if(this.config.includeArtifacts){let a=path.dirname(this.config.outputPath);this.runTimestamp=ir(path.join(a,"artifacts"));try{pr(path.join(a,"artifacts"));}catch{}}let n=P();this.detectedOs=La(),this.detectedSource=Ma(n);try{this.cloudClient=new he(this.config.cloud),await this.cloudClient.initialize(),this.cloudRunId=await $r(this.cloudClient,this.config.cloud?.uploadStrategy,this.testRunId,this.startedAt,this.detectedSource);}catch{this.cloudClient?.switchToLocalMode("init_error");}if(this.activeReportMode!=="streaming"){let a=()=>{try{if(this.cloudClient?.isCloudMode()&&this.cloudRunId){let o=this.cloudClient.getAccessToken();o&&nt(this.cloudClient.getEndpoint(),o,this.cloudRunId,this.startedAt);}}catch{}};process.on("SIGTERM",a),process.on("SIGINT",a);}}catch{}}onTestBegin(e,r){try{e.annotations.push({type:Na,description:Fa(this.apiConfig)});}catch{}}onTestEnd(e,r){try{let s=r,n=e.outcome(),a;n==="flaky"?a="flaky":n==="skipped"?a="skipped":a=ft(s.status);let o=s.startTime.toISOString(),i=new Date(s.startTime.getTime()+s.duration).toISOString(),d=e.tags?[...e.tags]:e.annotations.filter(C=>C.type==="tag").map(C=>C.description??""),l=qr(s.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 u=null;if(a==="failed"||a==="flaky"){let S=(a==="flaky"?e.results.find(O=>O.status!=="passed")?.errors??[]:s.errors)[0];if(S){let O=Pt(this.config.redactPatterns),G=S.location?.line??null,W=null;this.config.includeCodeSnippets&&G!==null&&S.location?.file&&(W=Et(S.location.file,G,this.config.codeContextLines),W&&(W=O(W))),u={message:O(S.message??"Unknown error"),line:G,code:W,stack:this.config.includeStackTrace&&S.stack?O(S.stack):null};}}let g=e.titlePath().filter(Boolean),m=path.relative(this.rootDir||".",e.location.file),p=Ca(g),f=g.join(" > "),c=m,h=Sa(c,p,f),v=Pa(d,c,e),w=v!=="mobile"&&l.apiCallsCount>0?"api":v,x=n==="flaky",T=Ra(e.results),M=ft(e.expectedStatus),y=ft(s.status),k=null;if(this.config.includeArtifacts&&a!=="skipped"&&s.attachments){let C=path.dirname(this.config.outputPath),S=g[g.length-1]??e.title;k=or(s.attachments,S,s.retry,C,this.runTimestamp||void 0);}let R=this.config.includeActionSteps&&s.steps?vr(s.steps,s.startTime):null,U=Ea(e),L={titlePath:g,title:f,status:a,duration:s.duration,startedAt:o,completedAt:i,retryCount:e.results.length-1,retry:s.retry,tags:d,failure:u,specFile:m,navigations:l.navigations,testId:h,filePath:c,suiteName:p,testType:w,isFlaky:x,retryStatus:T,expectedStatus:M,actualStatus:y,artifacts:k,apiAssertions:l.apiAssertions,actions:R,networkRequestsFile:l.networkRequestsFile,networkRequestsCount:l.networkRequestsCount,consoleLogsFile:l.consoleLogsFile,consoleLogsCount:l.consoleLogsCount,apiCallsFile:l.apiCallsFile,apiCallsCount:l.apiCallsCount,browser:U,os:this.detectedOs||void 0,source:this.detectedSource||void 0},gt=l.consoleLogsFile&&l.consoleLogsCount>0?B(l.consoleLogsFile):void 0,we=l.networkRequestsFile&&l.networkRequestsCount>0?B(l.networkRequestsFile):void 0,V=l.apiCallsFile&&l.apiCallsCount>0?B(l.apiCallsFile):void 0,ht=V?et(V):void 0,mt=!we&&V?tt(V):void 0,vt=l.apiAssertions&&l.apiAssertions.length>0?rt(l.apiAssertions):void 0;this.cloudTestsBuffer.push({testId:h,title:f,status:a,duration:s.duration,suiteName:p,filePath:c,testType:w,isFlaky:x,startedAt:o,completedAt:i,tags:d,failure:u,retry:s.retry,retryCount:e.results.length-1,retryStatus:T,browser:U,os:this.detectedOs||void 0,source:this.detectedSource||void 0,...R&&R.length>0?{actions:R}:{},...l.navigations&&l.navigations.length>0?{navigations:l.navigations}:{},...gt?{consoleLogs:gt}:{},...we?{networkRequests:we}:mt?{networkRequests:mt}:{},...ht?{apiCalls:ht}:{},...vt?{protocolAssertions:vt}:{}});try{let C=this.config.cloud?.uploadStrategy;if(this.cloudClient?.isCloudMode()&&this.cloudRunId&&(C==="realtime"||C==="both")){let S=this.cloudClient.getAccessToken();S&&_r(this.cloudClient.getEndpoint(),S,this.cloudRunId,this.buildCloudTestPayload(L));}}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter){let C=ke(c,g,e.id??"",s.retry),S=s.retry===e.results.length-1,O={id:C,navigations:l.navigations,apiAssertions:l.apiAssertions,actions:R??[],artifacts:k,failureDiagnostic:u,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(C,O,{networkRequestsFile:l.networkRequestsFile,consoleLogsFile:l.consoleLogsFile,apiCallsFile:l.apiCallsFile});let G={id:C,title:g[g.length-1]??e.title,titlePath:g,filePath:c,status:a,duration:s.duration,project:g[1]??"",retryIndex:s.retry,tags:d,hasNetworkData:l.networkRequestsCount>0,hasConsoleData:l.consoleLogsCount>0,hasArtifacts:k!==null,hasActionSteps:(R?.length??0)>0,errorMessage:u?.message?.split(`
|
|
2592
2592
|
`)[0]??null,networkCount:l.networkRequestsCount,consoleCount:l.consoleLogsCount,actionCount:R?.length??0,isRetry:!S};if(this.testIndex.push(G),S)switch(this.summaryCounters.total++,a){case "passed":this.summaryCounters.passed++;break;case "failed":this.summaryCounters.failed++;break;case "flaky":this.summaryCounters.flaky++;break;case "skipped":this.summaryCounters.skipped++;break;case "timedout":this.summaryCounters.timedOut++;break;default:this.summaryCounters.interrupted++;break}this.upsertAggContribution(`${c}::${g.join(" > ")}`,Vr(s.retry,V,l.apiAssertions,l.navigations,l.networkRequestsCount,l.consoleLogsCount,R)),k&&this.pendingArtifactEntries.push({testId:h,artifacts:k,outputDir:path.dirname(this.config.outputPath)}),L.actions=null,L.apiAssertions=null,L.navigations=[],L.artifacts=null,L.failure=null,L.networkRequestsFile=null,L.consoleLogsFile=null,L.apiCallsFile=null;}this.activeReportMode!=="streaming"&&this.collectedTests.push(L),this.testCount++,this.checkMemoryPressure();}catch{}}async onEnd(e){try{let r=new Date().toISOString(),s=new Date(this.startedAt).getTime(),a=new Date(r).getTime()-s,o=this.activeReportMode==="streaming"?this.testIndex.some(d=>d.status!=="skipped"):this.collectedTests.some(d=>d.status!=="skipped");!this.fixtureDataReceived&&o&&process.stderr.write(`
|
|
2593
2593
|
\u26A0 TestRelic: No fixture data received from any test.
|
|
2594
2594
|
To enable network logs, video sync, and Test Navigation tracking, import the TestRelic fixture:
|
|
@@ -2598,14 +2598,14 @@ ${n}
|
|
|
2598
2598
|
|
|
2599
2599
|
`),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).
|
|
2600
2600
|
`):process.stderr.write(`[testrelic] Test Navigation capture is disabled (captureNavigation: false). Remove the option or set it to true to capture the navigation graph.
|
|
2601
|
-
`),await
|
|
2602
|
-
`);let g={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:
|
|
2601
|
+
`),await ar();let i=null;if(this.config.includeArtifacts&&this.runTimestamp)try{let d=path.dirname(this.config.outputPath);i=dr(d,this.runTimestamp);let l=path.join(d,"artifact-manifest.json"),u=JSON.stringify(i),g=l+".tmp";fs$1.writeFileSync(g,u,"utf-8"),fs$1.renameSync(g,l);}catch{}if(this.activeReportMode==="streaming"&&this.streamingWriter)await this.finalizeStreamingReport(r,a,e,i);else {let d=this.buildTimeline(),l=new Map;for(let p of this.collectedTests){let f=l.get(p.testId);(!f||p.retry>f.retry)&&l.set(p.testId,p);}let u=Array.from(l.values()),g=mr(u,d.length),m={schemaVersion:Se,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:a,summary:g,ci:P(),metadata:this.config.metadata,timeline:d,shardRunIds:null};if(this.writeReport(m),await He(m,this.config,i),Ve(g,this.config.outputPath,this.config.htmlReportPath,this.config.quiet),this.cloudClient){let p=this.collectArtifactEntries(),f=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await ut(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,m,r,a,g,p,f);}}}catch{}}collectArtifactEntries(){if(this.activeReportMode==="streaming")return this.pendingArtifactEntries;let e=path.dirname(this.config.outputPath),r=[];for(let s of this.collectedTests)s.artifacts&&r.push({testId:s.testId,artifacts:s.artifacts,outputDir:e});return r}async finalizeStreamingReport(e,r,s,n){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};let a=new Map,o=new Map;for(let c of this.testIndex){let h=`${c.filePath}::${c.titlePath.join(" > ")}`,v=a.get(h);(v===void 0||c.retryIndex>v)&&a.set(h,c.retryIndex);}let i=0;for(let c of this.testIndex){let h=`${c.filePath}::${c.titlePath.join(" > ")}`,v=a.get(h);if(c.isRetry=c.retryIndex<v,c.isRetry)continue;switch(i++,this.summaryCounters.total++,c.status){case "passed":this.summaryCounters.passed++;break;case "failed":this.summaryCounters.failed++;break;case "flaky":this.summaryCounters.flaky++;break;case "skipped":this.summaryCounters.skipped++;break;case "timedout":this.summaryCounters.timedOut++;break;default:this.summaryCounters.interrupted++;break}let w=o.get(c.filePath);switch(w||(w={filePath:c.filePath,total:0,passed:0,failed:0,flaky:0,skipped:0,timedOut:0},o.set(c.filePath,w)),w.total++,c.status){case "passed":w.passed++;break;case "failed":w.failed++;break;case "flaky":w.flaky++;break;case "skipped":w.skipped++;break;case "timedout":w.timedOut++;break}}let d=Array.from(o.values()),l=_a();for(let c of this.streamingTestAgg.values()){l.volApiCalls+=c.apiCalls,l.volAssertions+=c.assertions,l.volNavigations+=c.navigations,l.volNetworkRequests+=c.networkRequests,l.volConsoleLogs+=c.consoleLogs,l.volActionSteps+=c.actionSteps;for(let h in c.methodCounts)l.methodCounts[h]=(l.methodCounts[h]??0)+c.methodCounts[h];l.statusRanges["2xx"]+=c.statusRanges["2xx"],l.statusRanges["3xx"]+=c.statusRanges["3xx"],l.statusRanges["4xx"]+=c.statusRanges["4xx"],l.statusRanges["5xx"]+=c.statusRanges["5xx"],l.statusRanges.error+=c.statusRanges.error,l.passedAssertions+=c.passedAssertions,l.failedAssertions+=c.failedAssertions;for(let h in c.actionCategories)l.actionCategoryCounts[h]=(l.actionCategoryCounts[h]??0)+c.actionCategories[h];for(let h of c.apiUrls){if(l.apiUrlSet.size>=be)break;l.apiUrlSet.add(h);}for(let h of c.navUrls){if(l.navUrlSet.size>=be)break;l.navUrlSet.add(h);}for(let h of c.responseTimes){if(l.responseTimes.length>=Wr)break;l.responseTimes.push(h);}}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 u={reporterTotal:this.summaryCounters.total,indexTotal:i,playwrightStatus:s.status,isValid:this.summaryCounters.total===i};u.isValid||process.stderr.write(`[testrelic] WARNING: Summary count mismatch \u2014 reporter: ${u.reporterTotal}, index: ${u.indexTotal}
|
|
2602
|
+
`);let g={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:Ia(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}},m={testRunId:this.testRunId,startedAt:this.startedAt,completedAt:e,totalDuration:r,...this.summaryCounters,metadata:this.config.metadata,reportMode:"streaming",files:d,enrichedSummary:g,validation:u,writeErrors:this.streamingWriter.getWriteErrors()};this.streamingWriter.writeSummary(m);let p={schemaVersion:"2.0",generatedAt:new Date().toISOString(),reportMode:"streaming",summaryFile:"summary.json",indexFile:"index.json",testsDir:"tests",artifactsDir:"artifacts",testCount:this.testIndex.length,totalSizeBytes:this.streamingWriter.computeTotalSize()};this.streamingWriter.writeManifest(p),await He(this.buildStreamingReport(m,g,e,r),this.config,n),Ve(g,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);let f=this.streamingWriter.getReportDir();if(process.stderr.write(`[testrelic] Streaming report written to ${f}
|
|
2603
2603
|
[testrelic] ${this.testIndex.length} test detail files on disk
|
|
2604
2604
|
[testrelic] View report: npx testrelic serve ${f}
|
|
2605
2605
|
`),this.streamingWriter.getWriteErrors().length>0&&process.stderr.write(`[testrelic] WARNING: ${this.streamingWriter.getWriteErrors().length} write error(s) during streaming
|
|
2606
|
-
`),this.streamingWriter.dispose(),this.cloudClient){let c=this.buildStreamingReport(m,g,e,r),h=this.collectArtifactEntries(),v=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await
|
|
2606
|
+
`),this.streamingWriter.dispose(),this.cloudClient){let c=this.buildStreamingReport(m,g,e,r),h=this.collectArtifactEntries(),v=this.cloudTestsBuffer.slice();this.cloudTestsBuffer.length=0,await ut(this.cloudClient,this.config.cloud,this.config.cloud?.uploadStrategy,this.testRunId,this.cloudRunId,c,e,r,g,h,v);}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,s,n){return {schemaVersion:Se,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:s,totalDuration:n,summary:r,ci:P(),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 s=e.heapUsed/e.heapTotal;s>.9&&this.activeReportMode==="embedded"?(process.stderr.write(`[testrelic] WARNING: High memory (${Math.round(r)} MB). Auto-switching to streaming mode.
|
|
2607
2607
|
`),this.switchToStreamingMode()):s>.8&&process.stderr.write(`[testrelic] WARNING: Memory pressure detected (${Math.round(r)} MB used).
|
|
2608
2608
|
`);}catch{}}switchToStreamingMode(){try{if(this.activeReportMode==="streaming")return;this.activeReportMode="streaming";let e=path.dirname(this.config.outputPath);this.streamingWriter=new J(e);for(let r of this.collectedTests){let s=ke(r.filePath,r.titlePath,r.testId,r.retry),n=r.apiCallsFile&&r.apiCallsCount>0?B(r.apiCallsFile):void 0,a={id:s,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(s,a,{networkRequestsFile:r.networkRequestsFile,consoleLogsFile:r.consoleLogsFile,apiCallsFile:r.apiCallsFile});let o={id:s,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(`
|
|
2609
|
-
`)[0]??null,networkCount:r.networkRequestsCount,consoleCount:r.consoleLogsCount,actionCount:r.actions?.length??0,isRetry:!1};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(" > ")}`,Vr(r.retry,n,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 hr(e,{navigationTypes:this.config.navigationTypes})}readJsonlFile(e){if(!e)return null;let r=B(e);return r.length>0?r:null}toTestResult(e,r){let s=null,n=null,a=null;return r?.loadFiles&&(s=this.readJsonlFile(e.networkRequestsFile),n=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,networkRequests:s,apiCalls:a,apiAssertions:e.apiAssertions,actions:e.actions??null,consoleLogs:n}}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,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=
|
|
2609
|
+
`)[0]??null,networkCount:r.networkRequestsCount,consoleCount:r.consoleLogsCount,actionCount:r.actions?.length??0,isRetry:!1};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(" > ")}`,Vr(r.retry,n,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 hr(e,{navigationTypes:this.config.navigationTypes})}readJsonlFile(e){if(!e)return null;let r=B(e);return r.length>0?r:null}toTestResult(e,r){let s=null,n=null,a=null;return r?.loadFiles&&(s=this.readJsonlFile(e.networkRequestsFile),n=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,networkRequests:s,apiCalls:a,apiAssertions:e.apiAssertions,actions:e.actions??null,consoleLogs:n}}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,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=rt(e.apiAssertions)),e.consoleLogsFile&&(r.consoleLogs=B(e.consoleLogsFile)),e.networkRequestsFile&&(r.networkRequests=B(e.networkRequestsFile)),e.apiCallsFile){let s=B(e.apiCallsFile);r.apiCalls=et(s),(!r.networkRequests||r.networkRequests.length===0)&&(r.networkRequests=tt(s));}return r}writeReport(e){try{let r=JSON.stringify(e),s=this.config.outputPath,n=path.dirname(s);fs$1.mkdirSync(n,{recursive:!0});let a=s+".tmp";fs$1.writeFileSync(a,r,"utf-8"),fs$1.renameSync(a,s);}catch(r){process.stderr.write(`[testrelic] Failed to write report: ${r instanceof Error?r.message:String(r)}
|
|
2610
2610
|
`);}}};module.exports=xe;//# sourceMappingURL=reporter-entry.cjs.map
|
|
2611
2611
|
//# sourceMappingURL=reporter-entry.cjs.map
|