@testrelic/maestro-analytics 1.2.2 → 1.3.0-next.63

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/cli.cjs CHANGED
@@ -4152,6 +4152,7 @@ function buildUploadPayload(report, repoGitId, git, ci, tests) {
4152
4152
  timeline: report.timeline,
4153
4153
  environment,
4154
4154
  testFramework: "maestro",
4155
+ testType: "mobile",
4155
4156
  ...tests && tests.length > 0 ? { tests } : {},
4156
4157
  ...git?.branch ? { branch: git.branch } : {},
4157
4158
  ...git?.commitSha ? { commit: git.commitSha } : {},
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';var core=require('@testrelic/core'),fs=require('fs'),path=require('path'),fastXmlParser=require('fast-xml-parser'),yaml=require('yaml'),child_process=require('child_process'),os$1=require('os'),crypto=require('crypto'),url=require('url'),zlib=require('zlib'),stream=require('stream');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var bt=".testrelic",Lr="testrelic-config.json",Dr=".testrelic",Nr=5,Or=new Set(["__proto__","constructor","prototype"]),me=Object.freeze({apiKey:null,endpoint:"https://platform.testrelic.ai/api/v1",uploadStrategy:"batch",timeout:3e4,projectName:null,queueMaxAge:6048e5,queueDirectory:`${bt}/queue`,uploadArtifacts:true,artifactMaxSizeMb:50}),Ur={s:1e3,m:60*1e3,h:3600*1e3,d:1440*60*1e3};function ye(e){let t=path.resolve(e);for(let r=0;r<=Nr;r++){let n=path.join(t,bt,Lr);if(fs.existsSync(n))try{if(fs.statSync(n).isFile())return n}catch{}let o=path.join(t,Dr);if(fs.existsSync(o))try{if(fs.statSync(o).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.
2
- `),o}catch{}let s=path.dirname(t);if(s===t)break;t=s;}return null}function be(e){try{let t=fs.readFileSync(e,"utf-8"),r=JSON.parse(t);return typeof r!="object"||r===null||Array.isArray(r)||!xt(r)?null:r}catch{return null}}function xt(e){for(let t of Object.keys(e)){if(Or.has(t))return false;let r=e[t];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!xt(r))return false}return true}function K(e){let t=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(e);if(t)return process.env[t[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(e);return r?process.env[r[1]]??null:e}function Y(e){let t=Object.create(null);for(let r of Object.keys(e)){let n=e[r];typeof n=="string"&&n.startsWith("$")?t[r]=K(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?t[r]=Y(n):t[r]=n;}return t}function he(e){let t=/^(\d+)\s*([smhd])$/.exec(e.trim());if(!t)return null;let r=parseInt(t[1],10),n=t[2],o=Ur[n];return !o||r<=0?null:r*o}function xe(e,t){let r=Object.create(null);if(Object.assign(r,me),e){let l=e.cloud;l&&typeof l=="object"&&(typeof l.endpoint=="string"&&(r.endpoint=l.endpoint),typeof l.upload=="string"&&(r.uploadStrategy=l.upload),typeof l.timeout=="number"&&(r.timeout=l.timeout),typeof l.apiKey=="string"&&l.apiKey.length>0&&(r.apiKey=l.apiKey));let c=e["testrelic-repo"]??e.project;c&&typeof c=="object"&&typeof c.name=="string"&&(r.projectName=c.name);let d=e.queue;if(d&&typeof d=="object"){if(typeof d.maxAge=="string"){let u=he(d.maxAge);u!==null&&(r.queueMaxAge=u);}typeof d.directory=="string"&&(r.queueDirectory=d.directory);}}if(t){if(typeof t.apiKey=="string"&&t.apiKey.length>0){let l=t.apiKey.startsWith("$")?K(t.apiKey):t.apiKey;l&&(r.apiKey=l);}if(typeof t.endpoint=="string"){let l=t.endpoint.startsWith("$")?K(t.endpoint):t.endpoint;l&&(r.endpoint=l);}if(typeof t.upload=="string"&&(r.uploadStrategy=t.upload),typeof t.timeout=="number"&&(r.timeout=t.timeout),typeof t.projectName=="string"&&(r.projectName=t.projectName),typeof t.queueMaxAge=="string"){let l=he(t.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof t.queueDirectory=="string"&&(r.queueDirectory=t.queueDirectory),typeof t.uploadArtifacts=="boolean"&&(r.uploadArtifacts=t.uploadArtifacts),typeof t.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=t.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let o=process.env.TESTRELIC_CLOUD_ENDPOINT;o&&core.isValidEndpointUrl(o)&&(r.endpoint=o);let s=process.env.TESTRELIC_UPLOAD_STRATEGY;s&&["batch","realtime","both"].includes(s)&&(r.uploadStrategy=s);let i=process.env.TESTRELIC_CLOUD_TIMEOUT;if(i){let l=parseInt(i,10);!isNaN(l)&&l>=1e3&&l<=12e4&&(r.timeout=l);}let a=Object.freeze(r);return core.isValidCloudConfig(a)?a:me}var Br=["authorization","cookie","set-cookie","x-api-key"],jr=["password","secret","token","apiKey","api_key"],zr=1024*1024;function qr(e){let t=e??{},r=process.env.TESTRELIC_CAPTURE_NETWORK==="1"||process.env.TESTRELIC_CAPTURE_NETWORK?.toLowerCase()==="true";return Object.freeze({enabled:t.enabled??r??false,proxyPort:t.proxyPort??(process.env.TESTRELIC_PROXY_PORT?Number.parseInt(process.env.TESTRELIC_PROXY_PORT,10):8080),proxyHost:t.proxyHost??process.env.TESTRELIC_PROXY_HOST??"127.0.0.1",harPath:t.harPath??process.env.TESTRELIC_HAR_PATH??null,outputDir:t.outputDir??null,skipCertInstall:t.skipCertInstall??false,includeUrls:Object.freeze(t.includeUrls?[...t.includeUrls]:[]),excludeUrls:Object.freeze(t.excludeUrls?[...t.excludeUrls]:[]),redactHeaders:Object.freeze(t.redactHeaders?[...t.redactHeaders]:[...Br]),redactBodyFields:Object.freeze(t.redactBodyFields?[...t.redactBodyFields]:[...jr]),maxBodyBytes:t.maxBodyBytes??zr})}var Gr=new Set(["__proto__","constructor","prototype"]);function wt(e){if(typeof e!="object"||e===null)return false;for(let t of Object.keys(e))if(Gr.has(t))return true;return false}function Vr(e){if(typeof e!="object"||e===null||wt(e))return false;let t=e;return !(t.outputPath!==void 0&&typeof t.outputPath!="string"||t.htmlReportPath!==void 0&&typeof t.htmlReportPath!="string"||t.openReport!==void 0&&typeof t.openReport!="boolean"||t.includeScreenshots!==void 0&&typeof t.includeScreenshots!="boolean"||t.includeVideo!==void 0&&typeof t.includeVideo!="boolean"||t.includeAiAnalysis!==void 0&&typeof t.includeAiAnalysis!="boolean"||t.includeLogs!==void 0&&typeof t.includeLogs!="boolean"||t.includeFlowMetadata!==void 0&&typeof t.includeFlowMetadata!="boolean"||t.quiet!==void 0&&typeof t.quiet!="boolean"||t.metadata!==void 0&&t.metadata!==null&&(typeof t.metadata!="object"||wt(t.metadata)))}function Jr(e){if(e!==void 0&&!Vr(e))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid Maestro reporter configuration");let t=Object.create(null),r=e?.outputPath??"./test-results/testrelic-maestro.json";return t.outputPath=r,t.htmlReportPath=e?.htmlReportPath??r.replace(/\.json$/,".html"),t.openReport=e?.openReport??true,t.includeScreenshots=e?.includeScreenshots??true,t.includeVideo=e?.includeVideo??true,t.includeAiAnalysis=e?.includeAiAnalysis??true,t.includeLogs=e?.includeLogs??true,t.includeFlowMetadata=e?.includeFlowMetadata??true,t.flowsDir=e?.flowsDir??null,t.testRunId=e?.testRunId??null,t.metadata=e?.metadata??null,t.quiet=e?.quiet??false,t.reportMode=e?.reportMode??"batch",t.cloud=Wr(e?.cloud??null),t.network=qr(e?.network),Object.freeze(t)}function Wr(e){let t=ye(process.cwd()),r=t?be(t):null,n=r?Y(r):null,o=xe(n,e??void 0);return o.apiKey?o:null}var Xr=new fastXmlParser.XMLParser({ignoreAttributes:false,attributeNamePrefix:"@_",allowBooleanAttributes:true,parseAttributeValue:true,trimValues:true});function X(e){return e==null?[]:Array.isArray(e)?e:[e]}function kt(e){return !e||typeof e!="object"?[]:X(e.property).map(n=>({name:String(n["@_name"]??""),value:String(n["@_value"]??"")}))}function Qr(e){let t=String(e["@_name"]??"unnamed"),r=String(e["@_classname"]??t),n=Number(e["@_time"]??0),o=e["@_id"]!=null?String(e["@_id"]):null,s=String(e["@_status"]??"").toUpperCase(),i=e.failure,a=e.error,l=e.skipped!==void 0,c="SUCCESS";return i?c="FAILURE":a?c="ERROR":l?c="SKIPPED":s==="FAILURE"||s==="FAILED"?c="FAILURE":s==="ERROR"?c="ERROR":s==="SKIPPED"&&(c="SKIPPED"),{id:o,name:t,classname:r,time:n,status:c,failureMessage:i?String(i["@_message"]??i["#text"]??""):null,failureType:i?String(i["@_type"]??""):null,errorMessage:a?String(a["@_message"]??a["#text"]??""):null,errorType:a?String(a["@_type"]??""):null,properties:kt(e.properties)}}function vt(e){let t=String(e["@_name"]??"Test Suite"),r=e["@_device"]!=null?String(e["@_device"]):null,n=Number(e["@_tests"]??0),o=Number(e["@_failures"]??0),s=Number(e["@_errors"]??0),i=Number(e["@_skipped"]??0),a=Number(e["@_time"]??0),c=X(e.testcase).map(Qr);return {name:t,device:r,tests:n,failures:o,errors:s,skipped:i,time:a,testCases:c,properties:kt(e.properties)}}function Ct(e){let t=Xr.parse(e),r=[];if(t.testsuites){let l=t.testsuites;r=X(l.testsuite).map(vt);}else t.testsuite&&(r=X(t.testsuite).map(vt));let n=0,o=0,s=0,i=0,a=0;for(let l of r)n+=l.tests,o+=l.failures,s+=l.errors,i+=l.skipped,a+=l.time;return {testSuites:r,totalTests:n,totalFailures:o,totalErrors:s,totalSkipped:i,totalTime:a}}function we(e){let t=fs.readFileSync(e,"utf-8");return Ct(t)}var on=new Set(["tapOn","doubleTapOn","longPressOn","inputText","eraseText","pasteText","swipe","scroll","scrollUntilVisible","hideKeyboard","pressKey","setClipboard","copyTextFrom"]),sn=new Set(["assertVisible","assertNotVisible","assertTrue","assertScreenshot","assertNoDefectsWithAI","assertWithAI","assertCondition"]),an=new Set(["launchApp","killApp","stopApp","clearState","openLink","back","clearKeychain"]),ln=new Set(["setAirplaneMode","toggleAirplaneMode","setLocation","setOrientation","setPermissions","addMedia","travel"]),cn=new Set(["takeScreenshot","startRecording","stopRecording"]),dn=new Set(["runScript","evalScript"]),un=new Set(["runFlow","repeat","retry","waitForAnimationToEnd","extendedWaitUntil"]),pn=new Set(["assertWithAI","assertNoDefectsWithAI","extractTextWithAI"]),fn=new Set(["inputText","pasteText"]),gn=200,mn=400;function Mt(e){return pn.has(e)?"ai":sn.has(e)?"assertion":on.has(e)?"interaction":an.has(e)?"navigation":ln.has(e)?"device":cn.has(e)?"media":dn.has(e)?"script":un.has(e)?"flow_control":"other"}var hn={tapOnElement:"tapOn",assertCondition:"assertVisible",backPress:"back",applyConfiguration:"applyConfiguration",defineVariables:"defineVariables"};function Rt(e){let t=e.replace(/Command$/,"");return hn[t]??t}var yn=new Set(["metadata","command","commandName","name","status","duration","durationMs","timestamp","time","error","errorMessage","selector","commands","subSteps","children","sequenceNumber"]);function bn(e){for(let t of Object.keys(e)){if(yn.has(t))continue;let r=e[t];if(r&&typeof r=="object"&&!Array.isArray(r))return t}}function St(e){if(e.selector&&typeof e.selector=="object"){let t=e.selector;if(typeof t.textRegex=="string")return t.textRegex;if(typeof t.text=="string")return t.text;if(typeof t.id=="string")return `#${t.id}`}if(e.condition&&typeof e.condition=="object"){let t=e.condition,r=t.visible??t.notVisible;if(r){if(typeof r.textRegex=="string")return r.textRegex;if(typeof r.text=="string")return r.text}}if(typeof e.path=="string")return e.path}function At(e,t){return e.length<=t?e:`${e.slice(0,t)}\u2026`}function xn(e){return e.length===0?"":`[REDACTED ${e.length} chars]`}function Tt(e){if(!e||typeof e!="object")return;let t=e;if(typeof t.x=="number"&&typeof t.y=="number")return `${t.x},${t.y}`}function It(e,t){let r={};switch(e){case "inputText":case "pasteText":{let n=t.text??t.value;typeof n=="string"&&(r.text=fn.has(e)?xn(n):n);break}case "swipe":case "scroll":case "scrollUntilVisible":{typeof t.direction=="string"&&(r.direction=t.direction);let n=Tt(t.start??t.startRelative),o=Tt(t.end??t.endRelative);n&&(r.start=n),o&&(r.end=o),typeof t.duration=="number"&&(r.swipeDurationMs=t.duration),typeof t.timeout=="number"&&(r.timeoutMs=t.timeout);break}case "setLocation":{typeof t.latitude=="number"&&(r.latitude=t.latitude),typeof t.longitude=="number"&&(r.longitude=t.longitude);break}case "pressKey":case "back":{typeof t.key=="string"?r.key=t.key:typeof t.code=="string"&&(r.key=t.code);break}case "setOrientation":{typeof t.orientation=="string"&&(r.orientation=t.orientation);break}case "setAirplaneMode":case "toggleAirplaneMode":{(typeof t.value=="string"||typeof t.value=="boolean")&&(r.value=t.value);break}case "setPermissions":{t.permissions&&typeof t.permissions=="object"&&(r.permissions=t.permissions);break}case "addMedia":{Array.isArray(t.mediaPaths)?r.mediaPaths=t.mediaPaths:typeof t.path=="string"&&(r.mediaPaths=[t.path]);break}case "launchApp":case "killApp":case "stopApp":case "clearState":{let n=t.appId??t.packageName??t.bundleId;typeof n=="string"&&(r.appId=n),t.arguments&&(r.arguments=t.arguments);break}case "openLink":{typeof t.url=="string"?r.url=t.url:typeof t.link=="string"&&(r.url=t.link);break}case "runScript":case "evalScript":{typeof t.path=="string"&&(r.path=t.path);let n=t.script??t.scriptString;typeof n=="string"&&(r.script=At(n,gn)),typeof t.sourceDescription=="string"&&(r.sourceDescription=t.sourceDescription);break}case "assertWithAI":case "assertNoDefectsWithAI":case "extractTextWithAI":{let n=t.assertion??t.prompt??t.question;typeof n=="string"&&(r.prompt=At(n,mn));break}case "extendedWaitUntil":case "waitForAnimationToEnd":{typeof t.timeout=="number"&&(r.timeoutMs=t.timeout);break}case "repeat":case "retry":{typeof t.times=="number"&&(r.times=t.times),typeof t.maxRetries=="number"&&(r.maxRetries=t.maxRetries),typeof t.condition=="object"&&t.condition&&(r.condition=t.condition);break}case "runFlow":{typeof t.file=="string"&&(r.file=t.file),typeof t.flowId=="string"&&(r.flowId=t.flowId);break}default:for(let n of ["text","value","url"]){let o=t[n];if(typeof o=="string"||typeof o=="number"||typeof o=="boolean"){r[n]=o;break}}}return Object.keys(r).length>0?r:void 0}function ve(e,t,r){let n=[e.commands,t.commands,t.subSteps,t.children];for(let o of n)if(Array.isArray(o)&&o.length>0)return o.map((s,i)=>ke(s,i,r));return []}function ke(e,t,r){let n,o,s,i=[];if(typeof e.command=="object"&&e.command!==null&&!Array.isArray(e.command)){let y=e.command,h=Object.keys(y)[0]??`step-${t}`;n=Rt(h);let g=y[h]??{};o=St(g),s=It(n,g),i=ve(g,e,r);}else {let y=bn(e);if(y){n=Rt(y);let h=e[y]??{};o=St(h),s=It(n,h),i=ve(h,e,r);}else n=e.command??e.commandName??e.name??`step-${t}`,o=e.selector??void 0,i=ve({},e,r);}let a=e.metadata??{},l=wn(a.status??e.status),c=a.duration??e.duration??e.durationMs??0,d=typeof a.sequenceNumber=="number"?a.sequenceNumber:void 0,u;typeof a.timestamp=="number"?u=new Date(a.timestamp).toISOString():u=e.timestamp??e.time??r;let p=e.error??e.errorMessage??void 0;return {command:n,category:Mt(n),status:l,duration:c,timestamp:u,...o?{selector:o}:{},...p?{error:p}:{},...s?{details:s}:{},...d!==void 0?{sequenceNumber:d}:{},...i.length>0?{children:i}:{}}}function wn(e){if(!e)return "completed";let t=e.toLowerCase();return t==="failed"||t==="error"?"failed":t==="skipped"?"skipped":"completed"}function Et(e,t){let r=t??new Date().toISOString();try{let n=JSON.parse(e);if(Array.isArray(n))return n.map((o,s)=>ke(o,s,r));if(typeof n=="object"&&n!==null){let o=n,s=o.commands??o.steps??o.data;if(Array.isArray(s))return s.map((i,a)=>ke(i,a,r))}return []}catch{return []}}function Ce(e,t){try{let r=fs.readFileSync(e,"utf-8");return Et(r,t)}catch{return []}}function Re(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>path.basename(t).startsWith("commands")&&t.endsWith(".json")).map(t=>path.join(e,t))}catch{return []}}function An(e){let t=[];for(let r of e)if(typeof r=="object"&&r!==null){let n=r;if(typeof n.runFlow=="string")t.push(n.runFlow);else if(typeof n.runFlow=="object"&&n.runFlow!==null){let o=n.runFlow;typeof o.file=="string"&&t.push(o.file);}}return t}function Pt(e){if(!e)return [];let t=[],r=Array.isArray(e)?e:[e];for(let n of r)if(typeof n=="string")t.push(n);else if(typeof n=="object"&&n!==null){let o=n;if(typeof o.runFlow=="string")t.push(o.runFlow);else if(typeof o.runFlow=="object"&&o.runFlow!==null){let s=o.runFlow;typeof s.file=="string"&&t.push(s.file);}typeof o.runScript=="string"&&t.push(o.runScript);}return t}function _t(e,t){let r=e.split(/^---\s*$/m,2),n=r[0]??"",o=r[1]??"",s={};try{let b=yaml.parseDocument(n).toJS();typeof b=="object"&&b!==null&&!Array.isArray(b)&&(s=b);}catch{}let i=[];if(o.trim())try{let b=yaml.parseDocument(o).toJS();Array.isArray(b)&&(i=b);}catch{}let a=typeof s.appId=="string"?s.appId:null,l=typeof s.name=="string"?s.name:null,c=[];if(Array.isArray(s.tags))for(let g of s.tags)typeof g=="string"&&c.push(g);let d={};if(typeof s.env=="object"&&s.env!==null&&!Array.isArray(s.env))for(let[g,b]of Object.entries(s.env))d[g]=String(b);let u={};if(typeof s.properties=="object"&&s.properties!==null&&!Array.isArray(s.properties))for(let[g,b]of Object.entries(s.properties))u[g]=String(b);let p=Pt(s.onFlowStart),y=Pt(s.onFlowComplete),h=An(i);return {appId:a,name:l,tags:c,env:d,properties:u,onFlowStart:p,onFlowComplete:y,subflowRefs:h,filePath:t}}function Se(e){let t=fs.readFileSync(e,"utf-8");return _t(t,e)}function Ae(e){if(!fs.existsSync(e))return [];let t=[];function r(n){try{let o=fs.readdirSync(n,{withFileTypes:!0});for(let s of o){let i=path.join(n,s.name);if(s.isDirectory())r(i);else if(s.isFile()){let a=path.extname(s.name).toLowerCase();(a===".yaml"||a===".yml")&&t.push(i);}}}catch{}}return r(e),t}var Pn=/^(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)\s+\[?\s*(\w+)\s*\]?\s+(.+)$/,_n=/^\[?(\d{2}:\d{2}:\d{2}(?:\.\d+)?)\]?\s+\[?\s*(\w+)\s*\]?\s+(.+)$/;function Lt(e){let t=e.toUpperCase();return t==="DEBUG"||t==="TRACE"||t==="VERBOSE"?"DEBUG":t==="INFO"?"INFO":t==="WARN"||t==="WARNING"?"WARN":t==="ERROR"||t==="FATAL"||t==="SEVERE"?"ERROR":"INFO"}function Ln(e,t){let r=/^(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/.exec(t);if(!r)return new Date().toISOString();let n=Number(r[1]),o=Number(r[2]),s=Number(r[3]),i=r[4]?Number(r[4].padEnd(3,"0")):0;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),n,o,s,i).toISOString()}function Dt(e,t){let r=[],n=e.split(`
2
+ `),o}catch{}let s=path.dirname(t);if(s===t)break;t=s;}return null}function be(e){try{let t=fs.readFileSync(e,"utf-8"),r=JSON.parse(t);return typeof r!="object"||r===null||Array.isArray(r)||!xt(r)?null:r}catch{return null}}function xt(e){for(let t of Object.keys(e)){if(Or.has(t))return false;let r=e[t];if(typeof r=="object"&&r!==null&&!Array.isArray(r)&&!xt(r))return false}return true}function K(e){let t=/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(e);if(t)return process.env[t[1]]??null;let r=/^\$([A-Za-z_][A-Za-z0-9_]*)$/.exec(e);return r?process.env[r[1]]??null:e}function Y(e){let t=Object.create(null);for(let r of Object.keys(e)){let n=e[r];typeof n=="string"&&n.startsWith("$")?t[r]=K(n):typeof n=="object"&&n!==null&&!Array.isArray(n)?t[r]=Y(n):t[r]=n;}return t}function he(e){let t=/^(\d+)\s*([smhd])$/.exec(e.trim());if(!t)return null;let r=parseInt(t[1],10),n=t[2],o=Ur[n];return !o||r<=0?null:r*o}function xe(e,t){let r=Object.create(null);if(Object.assign(r,me),e){let l=e.cloud;l&&typeof l=="object"&&(typeof l.endpoint=="string"&&(r.endpoint=l.endpoint),typeof l.upload=="string"&&(r.uploadStrategy=l.upload),typeof l.timeout=="number"&&(r.timeout=l.timeout),typeof l.apiKey=="string"&&l.apiKey.length>0&&(r.apiKey=l.apiKey));let c=e["testrelic-repo"]??e.project;c&&typeof c=="object"&&typeof c.name=="string"&&(r.projectName=c.name);let d=e.queue;if(d&&typeof d=="object"){if(typeof d.maxAge=="string"){let u=he(d.maxAge);u!==null&&(r.queueMaxAge=u);}typeof d.directory=="string"&&(r.queueDirectory=d.directory);}}if(t){if(typeof t.apiKey=="string"&&t.apiKey.length>0){let l=t.apiKey.startsWith("$")?K(t.apiKey):t.apiKey;l&&(r.apiKey=l);}if(typeof t.endpoint=="string"){let l=t.endpoint.startsWith("$")?K(t.endpoint):t.endpoint;l&&(r.endpoint=l);}if(typeof t.upload=="string"&&(r.uploadStrategy=t.upload),typeof t.timeout=="number"&&(r.timeout=t.timeout),typeof t.projectName=="string"&&(r.projectName=t.projectName),typeof t.queueMaxAge=="string"){let l=he(t.queueMaxAge);l!==null&&(r.queueMaxAge=l);}typeof t.queueDirectory=="string"&&(r.queueDirectory=t.queueDirectory),typeof t.uploadArtifacts=="boolean"&&(r.uploadArtifacts=t.uploadArtifacts),typeof t.artifactMaxSizeMb=="number"&&(r.artifactMaxSizeMb=t.artifactMaxSizeMb);}let n=process.env.TESTRELIC_API_KEY;n&&n.length>0&&(r.apiKey=n);let o=process.env.TESTRELIC_CLOUD_ENDPOINT;o&&core.isValidEndpointUrl(o)&&(r.endpoint=o);let s=process.env.TESTRELIC_UPLOAD_STRATEGY;s&&["batch","realtime","both"].includes(s)&&(r.uploadStrategy=s);let i=process.env.TESTRELIC_CLOUD_TIMEOUT;if(i){let l=parseInt(i,10);!isNaN(l)&&l>=1e3&&l<=12e4&&(r.timeout=l);}let a=Object.freeze(r);return core.isValidCloudConfig(a)?a:me}var Br=["authorization","cookie","set-cookie","x-api-key"],jr=["password","secret","token","apiKey","api_key"],zr=1024*1024;function qr(e){let t=e??{},r=process.env.TESTRELIC_CAPTURE_NETWORK==="1"||process.env.TESTRELIC_CAPTURE_NETWORK?.toLowerCase()==="true";return Object.freeze({enabled:t.enabled??r??false,proxyPort:t.proxyPort??(process.env.TESTRELIC_PROXY_PORT?Number.parseInt(process.env.TESTRELIC_PROXY_PORT,10):8080),proxyHost:t.proxyHost??process.env.TESTRELIC_PROXY_HOST??"127.0.0.1",harPath:t.harPath??process.env.TESTRELIC_HAR_PATH??null,outputDir:t.outputDir??null,skipCertInstall:t.skipCertInstall??false,includeUrls:Object.freeze(t.includeUrls?[...t.includeUrls]:[]),excludeUrls:Object.freeze(t.excludeUrls?[...t.excludeUrls]:[]),redactHeaders:Object.freeze(t.redactHeaders?[...t.redactHeaders]:[...Br]),redactBodyFields:Object.freeze(t.redactBodyFields?[...t.redactBodyFields]:[...jr]),maxBodyBytes:t.maxBodyBytes??zr})}var Gr=new Set(["__proto__","constructor","prototype"]);function wt(e){if(typeof e!="object"||e===null)return false;for(let t of Object.keys(e))if(Gr.has(t))return true;return false}function Vr(e){if(typeof e!="object"||e===null||wt(e))return false;let t=e;return !(t.outputPath!==void 0&&typeof t.outputPath!="string"||t.htmlReportPath!==void 0&&typeof t.htmlReportPath!="string"||t.openReport!==void 0&&typeof t.openReport!="boolean"||t.includeScreenshots!==void 0&&typeof t.includeScreenshots!="boolean"||t.includeVideo!==void 0&&typeof t.includeVideo!="boolean"||t.includeAiAnalysis!==void 0&&typeof t.includeAiAnalysis!="boolean"||t.includeLogs!==void 0&&typeof t.includeLogs!="boolean"||t.includeFlowMetadata!==void 0&&typeof t.includeFlowMetadata!="boolean"||t.quiet!==void 0&&typeof t.quiet!="boolean"||t.metadata!==void 0&&t.metadata!==null&&(typeof t.metadata!="object"||wt(t.metadata)))}function Jr(e){if(e!==void 0&&!Vr(e))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid Maestro reporter configuration");let t=Object.create(null),r=e?.outputPath??"./test-results/testrelic-maestro.json";return t.outputPath=r,t.htmlReportPath=e?.htmlReportPath??r.replace(/\.json$/,".html"),t.openReport=e?.openReport??true,t.includeScreenshots=e?.includeScreenshots??true,t.includeVideo=e?.includeVideo??true,t.includeAiAnalysis=e?.includeAiAnalysis??true,t.includeLogs=e?.includeLogs??true,t.includeFlowMetadata=e?.includeFlowMetadata??true,t.flowsDir=e?.flowsDir??null,t.testRunId=e?.testRunId??null,t.metadata=e?.metadata??null,t.quiet=e?.quiet??false,t.reportMode=e?.reportMode??"batch",t.cloud=Wr(e?.cloud??null),t.network=qr(e?.network),Object.freeze(t)}function Wr(e){let t=ye(process.cwd()),r=t?be(t):null,n=r?Y(r):null,o=xe(n,e??void 0);return o.apiKey?o:null}var Xr=new fastXmlParser.XMLParser({ignoreAttributes:false,attributeNamePrefix:"@_",allowBooleanAttributes:true,parseAttributeValue:true,trimValues:true});function X(e){return e==null?[]:Array.isArray(e)?e:[e]}function kt(e){return !e||typeof e!="object"?[]:X(e.property).map(n=>({name:String(n["@_name"]??""),value:String(n["@_value"]??"")}))}function Qr(e){let t=String(e["@_name"]??"unnamed"),r=String(e["@_classname"]??t),n=Number(e["@_time"]??0),o=e["@_id"]!=null?String(e["@_id"]):null,s=String(e["@_status"]??"").toUpperCase(),i=e.failure,a=e.error,l=e.skipped!==void 0,c="SUCCESS";return i?c="FAILURE":a?c="ERROR":l?c="SKIPPED":s==="FAILURE"||s==="FAILED"?c="FAILURE":s==="ERROR"?c="ERROR":s==="SKIPPED"&&(c="SKIPPED"),{id:o,name:t,classname:r,time:n,status:c,failureMessage:i?String(i["@_message"]??i["#text"]??""):null,failureType:i?String(i["@_type"]??""):null,errorMessage:a?String(a["@_message"]??a["#text"]??""):null,errorType:a?String(a["@_type"]??""):null,properties:kt(e.properties)}}function vt(e){let t=String(e["@_name"]??"Test Suite"),r=e["@_device"]!=null?String(e["@_device"]):null,n=Number(e["@_tests"]??0),o=Number(e["@_failures"]??0),s=Number(e["@_errors"]??0),i=Number(e["@_skipped"]??0),a=Number(e["@_time"]??0),c=X(e.testcase).map(Qr);return {name:t,device:r,tests:n,failures:o,errors:s,skipped:i,time:a,testCases:c,properties:kt(e.properties)}}function Ct(e){let t=Xr.parse(e),r=[];if(t.testsuites){let l=t.testsuites;r=X(l.testsuite).map(vt);}else t.testsuite&&(r=X(t.testsuite).map(vt));let n=0,o=0,s=0,i=0,a=0;for(let l of r)n+=l.tests,o+=l.failures,s+=l.errors,i+=l.skipped,a+=l.time;return {testSuites:r,totalTests:n,totalFailures:o,totalErrors:s,totalSkipped:i,totalTime:a}}function we(e){let t=fs.readFileSync(e,"utf-8");return Ct(t)}var on=new Set(["tapOn","doubleTapOn","longPressOn","inputText","eraseText","pasteText","swipe","scroll","scrollUntilVisible","hideKeyboard","pressKey","setClipboard","copyTextFrom"]),sn=new Set(["assertVisible","assertNotVisible","assertTrue","assertScreenshot","assertNoDefectsWithAI","assertWithAI","assertCondition"]),an=new Set(["launchApp","killApp","stopApp","clearState","openLink","back","clearKeychain"]),ln=new Set(["setAirplaneMode","toggleAirplaneMode","setLocation","setOrientation","setPermissions","addMedia","travel"]),cn=new Set(["takeScreenshot","startRecording","stopRecording"]),dn=new Set(["runScript","evalScript"]),un=new Set(["runFlow","repeat","retry","waitForAnimationToEnd","extendedWaitUntil"]),pn=new Set(["assertWithAI","assertNoDefectsWithAI","extractTextWithAI"]),fn=new Set(["inputText","pasteText"]),gn=200,mn=400;function Mt(e){return pn.has(e)?"ai":sn.has(e)?"assertion":on.has(e)?"interaction":an.has(e)?"navigation":ln.has(e)?"device":cn.has(e)?"media":dn.has(e)?"script":un.has(e)?"flow_control":"other"}var hn={tapOnElement:"tapOn",assertCondition:"assertVisible",backPress:"back",applyConfiguration:"applyConfiguration",defineVariables:"defineVariables"};function Rt(e){let t=e.replace(/Command$/,"");return hn[t]??t}var yn=new Set(["metadata","command","commandName","name","status","duration","durationMs","timestamp","time","error","errorMessage","selector","commands","subSteps","children","sequenceNumber"]);function bn(e){for(let t of Object.keys(e)){if(yn.has(t))continue;let r=e[t];if(r&&typeof r=="object"&&!Array.isArray(r))return t}}function St(e){if(e.selector&&typeof e.selector=="object"){let t=e.selector;if(typeof t.textRegex=="string")return t.textRegex;if(typeof t.text=="string")return t.text;if(typeof t.id=="string")return `#${t.id}`}if(e.condition&&typeof e.condition=="object"){let t=e.condition,r=t.visible??t.notVisible;if(r){if(typeof r.textRegex=="string")return r.textRegex;if(typeof r.text=="string")return r.text}}if(typeof e.path=="string")return e.path}function Tt(e,t){return e.length<=t?e:`${e.slice(0,t)}\u2026`}function xn(e){return e.length===0?"":`[REDACTED ${e.length} chars]`}function At(e){if(!e||typeof e!="object")return;let t=e;if(typeof t.x=="number"&&typeof t.y=="number")return `${t.x},${t.y}`}function It(e,t){let r={};switch(e){case "inputText":case "pasteText":{let n=t.text??t.value;typeof n=="string"&&(r.text=fn.has(e)?xn(n):n);break}case "swipe":case "scroll":case "scrollUntilVisible":{typeof t.direction=="string"&&(r.direction=t.direction);let n=At(t.start??t.startRelative),o=At(t.end??t.endRelative);n&&(r.start=n),o&&(r.end=o),typeof t.duration=="number"&&(r.swipeDurationMs=t.duration),typeof t.timeout=="number"&&(r.timeoutMs=t.timeout);break}case "setLocation":{typeof t.latitude=="number"&&(r.latitude=t.latitude),typeof t.longitude=="number"&&(r.longitude=t.longitude);break}case "pressKey":case "back":{typeof t.key=="string"?r.key=t.key:typeof t.code=="string"&&(r.key=t.code);break}case "setOrientation":{typeof t.orientation=="string"&&(r.orientation=t.orientation);break}case "setAirplaneMode":case "toggleAirplaneMode":{(typeof t.value=="string"||typeof t.value=="boolean")&&(r.value=t.value);break}case "setPermissions":{t.permissions&&typeof t.permissions=="object"&&(r.permissions=t.permissions);break}case "addMedia":{Array.isArray(t.mediaPaths)?r.mediaPaths=t.mediaPaths:typeof t.path=="string"&&(r.mediaPaths=[t.path]);break}case "launchApp":case "killApp":case "stopApp":case "clearState":{let n=t.appId??t.packageName??t.bundleId;typeof n=="string"&&(r.appId=n),t.arguments&&(r.arguments=t.arguments);break}case "openLink":{typeof t.url=="string"?r.url=t.url:typeof t.link=="string"&&(r.url=t.link);break}case "runScript":case "evalScript":{typeof t.path=="string"&&(r.path=t.path);let n=t.script??t.scriptString;typeof n=="string"&&(r.script=Tt(n,gn)),typeof t.sourceDescription=="string"&&(r.sourceDescription=t.sourceDescription);break}case "assertWithAI":case "assertNoDefectsWithAI":case "extractTextWithAI":{let n=t.assertion??t.prompt??t.question;typeof n=="string"&&(r.prompt=Tt(n,mn));break}case "extendedWaitUntil":case "waitForAnimationToEnd":{typeof t.timeout=="number"&&(r.timeoutMs=t.timeout);break}case "repeat":case "retry":{typeof t.times=="number"&&(r.times=t.times),typeof t.maxRetries=="number"&&(r.maxRetries=t.maxRetries),typeof t.condition=="object"&&t.condition&&(r.condition=t.condition);break}case "runFlow":{typeof t.file=="string"&&(r.file=t.file),typeof t.flowId=="string"&&(r.flowId=t.flowId);break}default:for(let n of ["text","value","url"]){let o=t[n];if(typeof o=="string"||typeof o=="number"||typeof o=="boolean"){r[n]=o;break}}}return Object.keys(r).length>0?r:void 0}function ve(e,t,r){let n=[e.commands,t.commands,t.subSteps,t.children];for(let o of n)if(Array.isArray(o)&&o.length>0)return o.map((s,i)=>ke(s,i,r));return []}function ke(e,t,r){let n,o,s,i=[];if(typeof e.command=="object"&&e.command!==null&&!Array.isArray(e.command)){let y=e.command,h=Object.keys(y)[0]??`step-${t}`;n=Rt(h);let g=y[h]??{};o=St(g),s=It(n,g),i=ve(g,e,r);}else {let y=bn(e);if(y){n=Rt(y);let h=e[y]??{};o=St(h),s=It(n,h),i=ve(h,e,r);}else n=e.command??e.commandName??e.name??`step-${t}`,o=e.selector??void 0,i=ve({},e,r);}let a=e.metadata??{},l=wn(a.status??e.status),c=a.duration??e.duration??e.durationMs??0,d=typeof a.sequenceNumber=="number"?a.sequenceNumber:void 0,u;typeof a.timestamp=="number"?u=new Date(a.timestamp).toISOString():u=e.timestamp??e.time??r;let p=e.error??e.errorMessage??void 0;return {command:n,category:Mt(n),status:l,duration:c,timestamp:u,...o?{selector:o}:{},...p?{error:p}:{},...s?{details:s}:{},...d!==void 0?{sequenceNumber:d}:{},...i.length>0?{children:i}:{}}}function wn(e){if(!e)return "completed";let t=e.toLowerCase();return t==="failed"||t==="error"?"failed":t==="skipped"?"skipped":"completed"}function Et(e,t){let r=t??new Date().toISOString();try{let n=JSON.parse(e);if(Array.isArray(n))return n.map((o,s)=>ke(o,s,r));if(typeof n=="object"&&n!==null){let o=n,s=o.commands??o.steps??o.data;if(Array.isArray(s))return s.map((i,a)=>ke(i,a,r))}return []}catch{return []}}function Ce(e,t){try{let r=fs.readFileSync(e,"utf-8");return Et(r,t)}catch{return []}}function Re(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>path.basename(t).startsWith("commands")&&t.endsWith(".json")).map(t=>path.join(e,t))}catch{return []}}function Tn(e){let t=[];for(let r of e)if(typeof r=="object"&&r!==null){let n=r;if(typeof n.runFlow=="string")t.push(n.runFlow);else if(typeof n.runFlow=="object"&&n.runFlow!==null){let o=n.runFlow;typeof o.file=="string"&&t.push(o.file);}}return t}function Pt(e){if(!e)return [];let t=[],r=Array.isArray(e)?e:[e];for(let n of r)if(typeof n=="string")t.push(n);else if(typeof n=="object"&&n!==null){let o=n;if(typeof o.runFlow=="string")t.push(o.runFlow);else if(typeof o.runFlow=="object"&&o.runFlow!==null){let s=o.runFlow;typeof s.file=="string"&&t.push(s.file);}typeof o.runScript=="string"&&t.push(o.runScript);}return t}function _t(e,t){let r=e.split(/^---\s*$/m,2),n=r[0]??"",o=r[1]??"",s={};try{let b=yaml.parseDocument(n).toJS();typeof b=="object"&&b!==null&&!Array.isArray(b)&&(s=b);}catch{}let i=[];if(o.trim())try{let b=yaml.parseDocument(o).toJS();Array.isArray(b)&&(i=b);}catch{}let a=typeof s.appId=="string"?s.appId:null,l=typeof s.name=="string"?s.name:null,c=[];if(Array.isArray(s.tags))for(let g of s.tags)typeof g=="string"&&c.push(g);let d={};if(typeof s.env=="object"&&s.env!==null&&!Array.isArray(s.env))for(let[g,b]of Object.entries(s.env))d[g]=String(b);let u={};if(typeof s.properties=="object"&&s.properties!==null&&!Array.isArray(s.properties))for(let[g,b]of Object.entries(s.properties))u[g]=String(b);let p=Pt(s.onFlowStart),y=Pt(s.onFlowComplete),h=Tn(i);return {appId:a,name:l,tags:c,env:d,properties:u,onFlowStart:p,onFlowComplete:y,subflowRefs:h,filePath:t}}function Se(e){let t=fs.readFileSync(e,"utf-8");return _t(t,e)}function Te(e){if(!fs.existsSync(e))return [];let t=[];function r(n){try{let o=fs.readdirSync(n,{withFileTypes:!0});for(let s of o){let i=path.join(n,s.name);if(s.isDirectory())r(i);else if(s.isFile()){let a=path.extname(s.name).toLowerCase();(a===".yaml"||a===".yml")&&t.push(i);}}}catch{}}return r(e),t}var Pn=/^(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)\s+\[?\s*(\w+)\s*\]?\s+(.+)$/,_n=/^\[?(\d{2}:\d{2}:\d{2}(?:\.\d+)?)\]?\s+\[?\s*(\w+)\s*\]?\s+(.+)$/;function Lt(e){let t=e.toUpperCase();return t==="DEBUG"||t==="TRACE"||t==="VERBOSE"?"DEBUG":t==="INFO"?"INFO":t==="WARN"||t==="WARNING"?"WARN":t==="ERROR"||t==="FATAL"||t==="SEVERE"?"ERROR":"INFO"}function Ln(e,t){let r=/^(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/.exec(t);if(!r)return new Date().toISOString();let n=Number(r[1]),o=Number(r[2]),s=Number(r[3]),i=r[4]?Number(r[4].padEnd(3,"0")):0;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),n,o,s,i).toISOString()}function Dt(e,t){let r=[],n=e.split(`
3
3
  `),o=t instanceof Date?t:null,s=typeof t=="string"?t:t instanceof Date?`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`:new Date().toISOString().split("T")[0];for(let i of n){let a=i.trim();if(!a)continue;let l=Pn.exec(a);if(l){r.push({timestamp:l[1],level:Lt(l[2]),message:l[3],source:null});continue}if(l=_n.exec(a),l){let c=o?Ln(o,l[1]):`${s}T${l[1]}`;r.push({timestamp:c,level:Lt(l[2]),message:l[3],source:null});continue}if(r.length>0){let c=r[r.length-1];r[r.length-1]={...c,message:c.message+`
4
- `+a};}}return r}function Te(e,t){try{let r=fs.readFileSync(e,"utf-8");return Dt(r,t)}catch{return []}}function Ie(e){for(let t of e){let r=t.message.toLowerCase();if(r.includes("android")||r.includes("adb")||r.includes("uiautomator")||r.includes("emulator"))return "android";if(r.includes("ios")||r.includes("xcuitest")||r.includes("simulator")||r.includes("xctest"))return "ios";if(r.includes("web driver")||r.includes("chrome")||r.includes("chromium"))return "web"}return "unknown"}function Me(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>path.basename(t)==="maestro.log"||t.endsWith(".log")).map(t=>path.join(e,t))}catch{return []}}var Bn=/(?:defect|issue|bug|error|warning|problem)/i,jn=/(?:critical|severe|major|blocker)/i,zn=/(?:warning|moderate|minor)/i,Ee=/(?:cut[\s-]?off|overlap|truncat|misalign|overflow|clip|obscur|hidden\s+text|broken\s+layout)/i,Q=/(?:spelling|typo|misspell|grammar)/i,Z=/(?:i18n|internationali[sz]ation|locali[sz]ation|untranslated|missing\s+translation)/i,Le=/(?:layout|spacing|padding|margin|alignment|centering|position)/i,De=/(?:accessib|a11y|contrast|screen\s*reader|alt\s*text|aria)/i;function Fe(e){return Q.test(e)?"spelling":Z.test(e)?"i18n":De.test(e)?"accessibility":Le.test(e)?"layout":"ui"}function Pe(e){return jn.test(e)?"critical":zn.test(e)?"warning":"info"}function _e(e){return e.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim()}function qn(e){let t=[],r=_e(e),n=/<li[^>]*>([\s\S]*?)<\/li>/gi,o;for(;(o=n.exec(e))!==null;){let s=o[1],i=_e(s);!i||i.length<5||(Bn.test(i)||Ee.test(i)||Q.test(i)||Z.test(i))&&t.push({type:Fe(i),severity:Pe(i),description:i,location:null,screenshot:null});}if(t.length===0){let s=/<p[^>]*>([\s\S]*?)<\/p>/gi;for(;(o=s.exec(e))!==null;){let i=_e(o[1]);!i||i.length<10||(Ee.test(i)||Q.test(i)||Z.test(i)||Le.test(i)||De.test(i))&&t.push({type:Fe(i),severity:Pe(i),description:i,location:null,screenshot:null});}}if(t.length===0&&r.length>20){let s=r.split(/[.!?]+/).filter(i=>i.trim().length>10);for(let i of s){let a=i.trim();(Ee.test(a)||Q.test(a)||Z.test(a)||Le.test(a)||De.test(a))&&t.push({type:Fe(a),severity:Pe(a),description:a,location:null,screenshot:null});}}return t}function Nt(e){let t=qn(e);return {defects:t,totalDefects:t.length,hasIssues:t.length>0,rawHtml:e}}function Ne(e){try{let t=fs.readFileSync(e,"utf-8");return Nt(t)}catch{return {defects:[],totalDefects:0,hasIssues:false,rawHtml:null}}}function Oe(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>{let r=path.basename(t).toLowerCase();return path.extname(t).toLowerCase()===".html"&&(r.includes("insight")||r.includes("ai")||r.includes("analysis"))}).map(t=>path.join(e,t))}catch{return []}}var Yn=new Set([".png",".jpg",".jpeg",".webp"]),Xn=new Set([".mp4",".webm",".mov"]);function Ot(e){let t=[];if(!fs.existsSync(e))return t;function r(n){try{let o=fs.readdirSync(n,{withFileTypes:!0});for(let s of o){let i=path.join(n,s.name);s.isDirectory()?r(i):s.isFile()&&t.push(i);}}catch{}}return r(e),t}function Ue(e,t){let r=[],n=[],o=[],s=[],i=[],a=null,l=[];e&&l.push(...Ot(e)),t&&l.push(...Ot(t));let c=new Set;for(let d of l){if(c.has(d))continue;c.add(d);let u=path.basename(d).toLowerCase(),p=path.extname(d).toLowerCase();if(Yn.has(p)){r.push(d);continue}if(Xn.has(p)){n.push(d);continue}if(u==="maestro.log"||p===".log"&&u.includes("maestro")){o.push(d);continue}if(u.startsWith("commands")&&p===".json"){s.push(d);continue}if(p===".html"&&(u.includes("insight")||u.includes("ai")||u.includes("analysis"))){i.push(d);continue}if(p===".xml"&&(u.includes("report")||u.includes("junit"))){a||(a=d);continue}}return {screenshotPaths:r,videoPaths:n,logPaths:o,commandJsonPaths:s,aiReportPaths:i,junitReportPath:a}}function Qn(e){return {screenshots:e.screenshotPaths.length,videos:e.videoPaths.length,logs:e.logPaths.length,commandFiles:e.commandJsonPaths.length,aiReports:e.aiReportPaths.length,junitReport:e.junitReportPath?1:0}}function Zn(e){switch(e){case "interaction":return "ui_action";case "assertion":return "assertion";case "ai":return "assertion";case "navigation":return "navigation";case "device":return "custom_step";case "media":return "custom_step";case "script":return "custom_step";case "flow_control":return "custom_step";case "recording":return "custom_step";default:return "custom_step"}}function eo(e){let t=e.details;if(t)switch(e.command){case "inputText":case "pasteText":if(typeof t.text=="string")return `${e.command} \u2192 ${t.text}`;break;case "swipe":case "scroll":case "scrollUntilVisible":if(typeof t.direction=="string")return `${e.command} ${t.direction}`;break;case "setLocation":if(typeof t.latitude=="number"&&typeof t.longitude=="number")return `setLocation ${t.latitude},${t.longitude}`;break;case "pressKey":if(typeof t.key=="string")return `pressKey ${t.key}`;break;case "setOrientation":if(typeof t.orientation=="string")return `setOrientation ${t.orientation}`;break;case "launchApp":case "killApp":case "stopApp":case "clearState":if(typeof t.appId=="string")return `${e.command} ${t.appId}`;break;case "openLink":if(typeof t.url=="string")return `openLink ${t.url}`;break;case "runScript":case "evalScript":if(typeof t.path=="string")return `${e.command} ${t.path}`;if(typeof t.sourceDescription=="string")return `${e.command} ${t.sourceDescription}`;if(typeof t.script=="string")return `${e.command} ${t.script}`;break;case "assertWithAI":case "assertNoDefectsWithAI":case "extractTextWithAI":if(typeof t.prompt=="string")return `${e.command} \u2192 ${t.prompt}`;break;case "retry":if(typeof t.maxRetries=="number")return `retry \xD7 ${t.maxRetries}`;break;case "repeat":if(typeof t.times=="number")return `repeat \xD7 ${t.times}`;break;case "runFlow":if(typeof t.file=="string")return `runFlow ${t.file}`;break}return e.selector?`${e.command} \u2192 ${e.selector}`:e.command}function He(e,t){let r=Date.parse(e.timestamp),n=Number.isFinite(r)&&Number.isFinite(t)?Math.max(0,(r-t)/1e3):null,o=(e.children??[]).map(s=>He(s,t));return {title:eo(e),category:Zn(e.category),status:e.status==="failed"?"failed":"passed",duration:e.duration,timestamp:e.timestamp,videoOffset:n,error:e.error??null,children:o}}function to(e,t){let r=Date.parse(e.timestamp),n=Date.parse(t.timestamp);return Number.isFinite(r)&&Number.isFinite(n)&&r!==n?r-n:0}function ro(e,t){let r=Date.parse(e.startedAt),n=[...e.commands].sort((l,c)=>{let d=Date.parse(l.timestamp),u=Date.parse(c.timestamp);if(Number.isFinite(d)&&Number.isFinite(u)&&d!==u)return d-u;let p=l.sequenceNumber??0,y=c.sequenceNumber??0;return p-y}),o=[...e.assertions].sort((l,c)=>{let d=Date.parse(l.timestamp),u=Date.parse(c.timestamp);if(Number.isFinite(d)&&Number.isFinite(u)&&d!==u)return d-u;let p=l.sequenceNumber??0,y=c.sequenceNumber??0;return p-y}),s=[...n.map(l=>He(l,r)),...o.map(l=>He(l,r))];s.sort(to);let i=e.screenshotPaths.length>0||e.videoPath?{screenshot:e.screenshotPaths[0]??void 0,video:e.videoPath??void 0}:null,a=[...e.tags];return e.platform!=="unknown"&&!a.includes(e.platform)&&a.push(e.platform),{title:e.flowName,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:0,tags:a,failure:e.failureMessage?{message:e.failureMessage,line:null,code:null,stack:null}:null,testId:`${e.flowFile}::${e.flowName}`,filePath:e.flowFile,suiteName:e.appId??"maestro-suite",testType:"mobile",isFlaky:false,retryStatus:null,expectedStatus:"passed",actualStatus:e.status,artifacts:i,networkRequests:null,apiCalls:t.length>0?[...t]:null,apiAssertions:null,actions:s.length>0?s:null,consoleLogs:null}}function Ut(e,t){let r=`${e.flowFile}::${e.flowName}`,n=t?.get(r)??[],o=ro(e,n);return {url:e.appId??"maestro-flow",navigationType:"page_load",visitedAt:e.startedAt,duration:e.duration,specFile:e.flowFile,domContentLoadedAt:null,networkIdleAt:null,networkStats:null,tests:[o]}}function $e(e,t){return e.map(r=>Ut(r,t))}var Ht={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0};function no(e){return e===null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function Be(e,t){if(e.length===0)return null;let r=Math.min(e.length-1,Math.floor(t/100*e.length));return e[r]}function oo(e){if(e.length===0)return {totalApiCalls:0,uniqueApiUrls:0,apiCallsByMethod:{},apiCallsByStatusRange:{...Ht},apiResponseTime:null};let t={},r={...Ht},n=new Set,o=[];for(let i of e)t[i.method]=(t[i.method]??0)+1,r[no(i.responseStatusCode)]+=1,n.add(i.url),Number.isFinite(i.responseTimeMs)&&i.responseTimeMs>0&&o.push(i.responseTimeMs);o.sort((i,a)=>i-a);let s=o.length>0?{p50:Be(o,50)??0,p95:Be(o,95)??0,p99:Be(o,99)??0,avg:o.reduce((i,a)=>i+a,0)/o.length,min:o[0],max:o[o.length-1]}:null;return {totalApiCalls:e.length,uniqueApiUrls:n.size,apiCallsByMethod:t,apiCallsByStatusRange:r,apiResponseTime:s}}function G(e){let t=0,r=0,n=0,o=0,s=0,i=0,a=0,l=0,c=0,d=e.length,u=0,p={},y=new Set,h=[];for(let b of e){y.add(b.url);for(let x of b.tests){switch(t++,x.status){case "passed":r++;break;case "failed":n++;break;case "flaky":o++;break;case "skipped":s++;break;case "timedout":i++;break}if(x.actions)for(let A of x.actions)if(u++,A.category==="assertion")a++,A.status==="passed"?l++:c++;else {let R=A.category;p[R]=(p[R]??0)+1;}x.apiCalls&&x.apiCalls.length>0&&h.push(...x.apiCalls);}}let g=oo(h);return {total:t,passed:r,failed:n,flaky:o,skipped:s,timedout:i,...g,totalAssertions:a,passedAssertions:l,failedAssertions:c,totalNavigations:d,uniqueNavigationUrls:y.size,totalTimelineSteps:e.length,totalActionSteps:u,actionStepsByCategory:p}}var $t=`
4
+ `+a};}}return r}function Ae(e,t){try{let r=fs.readFileSync(e,"utf-8");return Dt(r,t)}catch{return []}}function Ie(e){for(let t of e){let r=t.message.toLowerCase();if(r.includes("android")||r.includes("adb")||r.includes("uiautomator")||r.includes("emulator"))return "android";if(r.includes("ios")||r.includes("xcuitest")||r.includes("simulator")||r.includes("xctest"))return "ios";if(r.includes("web driver")||r.includes("chrome")||r.includes("chromium"))return "web"}return "unknown"}function Me(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>path.basename(t)==="maestro.log"||t.endsWith(".log")).map(t=>path.join(e,t))}catch{return []}}var Bn=/(?:defect|issue|bug|error|warning|problem)/i,jn=/(?:critical|severe|major|blocker)/i,zn=/(?:warning|moderate|minor)/i,Ee=/(?:cut[\s-]?off|overlap|truncat|misalign|overflow|clip|obscur|hidden\s+text|broken\s+layout)/i,Q=/(?:spelling|typo|misspell|grammar)/i,Z=/(?:i18n|internationali[sz]ation|locali[sz]ation|untranslated|missing\s+translation)/i,Le=/(?:layout|spacing|padding|margin|alignment|centering|position)/i,De=/(?:accessib|a11y|contrast|screen\s*reader|alt\s*text|aria)/i;function Fe(e){return Q.test(e)?"spelling":Z.test(e)?"i18n":De.test(e)?"accessibility":Le.test(e)?"layout":"ui"}function Pe(e){return jn.test(e)?"critical":zn.test(e)?"warning":"info"}function _e(e){return e.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim()}function qn(e){let t=[],r=_e(e),n=/<li[^>]*>([\s\S]*?)<\/li>/gi,o;for(;(o=n.exec(e))!==null;){let s=o[1],i=_e(s);!i||i.length<5||(Bn.test(i)||Ee.test(i)||Q.test(i)||Z.test(i))&&t.push({type:Fe(i),severity:Pe(i),description:i,location:null,screenshot:null});}if(t.length===0){let s=/<p[^>]*>([\s\S]*?)<\/p>/gi;for(;(o=s.exec(e))!==null;){let i=_e(o[1]);!i||i.length<10||(Ee.test(i)||Q.test(i)||Z.test(i)||Le.test(i)||De.test(i))&&t.push({type:Fe(i),severity:Pe(i),description:i,location:null,screenshot:null});}}if(t.length===0&&r.length>20){let s=r.split(/[.!?]+/).filter(i=>i.trim().length>10);for(let i of s){let a=i.trim();(Ee.test(a)||Q.test(a)||Z.test(a)||Le.test(a)||De.test(a))&&t.push({type:Fe(a),severity:Pe(a),description:a,location:null,screenshot:null});}}return t}function Nt(e){let t=qn(e);return {defects:t,totalDefects:t.length,hasIssues:t.length>0,rawHtml:e}}function Ne(e){try{let t=fs.readFileSync(e,"utf-8");return Nt(t)}catch{return {defects:[],totalDefects:0,hasIssues:false,rawHtml:null}}}function Oe(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>{let r=path.basename(t).toLowerCase();return path.extname(t).toLowerCase()===".html"&&(r.includes("insight")||r.includes("ai")||r.includes("analysis"))}).map(t=>path.join(e,t))}catch{return []}}var Yn=new Set([".png",".jpg",".jpeg",".webp"]),Xn=new Set([".mp4",".webm",".mov"]);function Ot(e){let t=[];if(!fs.existsSync(e))return t;function r(n){try{let o=fs.readdirSync(n,{withFileTypes:!0});for(let s of o){let i=path.join(n,s.name);s.isDirectory()?r(i):s.isFile()&&t.push(i);}}catch{}}return r(e),t}function Ue(e,t){let r=[],n=[],o=[],s=[],i=[],a=null,l=[];e&&l.push(...Ot(e)),t&&l.push(...Ot(t));let c=new Set;for(let d of l){if(c.has(d))continue;c.add(d);let u=path.basename(d).toLowerCase(),p=path.extname(d).toLowerCase();if(Yn.has(p)){r.push(d);continue}if(Xn.has(p)){n.push(d);continue}if(u==="maestro.log"||p===".log"&&u.includes("maestro")){o.push(d);continue}if(u.startsWith("commands")&&p===".json"){s.push(d);continue}if(p===".html"&&(u.includes("insight")||u.includes("ai")||u.includes("analysis"))){i.push(d);continue}if(p===".xml"&&(u.includes("report")||u.includes("junit"))){a||(a=d);continue}}return {screenshotPaths:r,videoPaths:n,logPaths:o,commandJsonPaths:s,aiReportPaths:i,junitReportPath:a}}function Qn(e){return {screenshots:e.screenshotPaths.length,videos:e.videoPaths.length,logs:e.logPaths.length,commandFiles:e.commandJsonPaths.length,aiReports:e.aiReportPaths.length,junitReport:e.junitReportPath?1:0}}function Zn(e){switch(e){case "interaction":return "ui_action";case "assertion":return "assertion";case "ai":return "assertion";case "navigation":return "navigation";case "device":return "custom_step";case "media":return "custom_step";case "script":return "custom_step";case "flow_control":return "custom_step";case "recording":return "custom_step";default:return "custom_step"}}function eo(e){let t=e.details;if(t)switch(e.command){case "inputText":case "pasteText":if(typeof t.text=="string")return `${e.command} \u2192 ${t.text}`;break;case "swipe":case "scroll":case "scrollUntilVisible":if(typeof t.direction=="string")return `${e.command} ${t.direction}`;break;case "setLocation":if(typeof t.latitude=="number"&&typeof t.longitude=="number")return `setLocation ${t.latitude},${t.longitude}`;break;case "pressKey":if(typeof t.key=="string")return `pressKey ${t.key}`;break;case "setOrientation":if(typeof t.orientation=="string")return `setOrientation ${t.orientation}`;break;case "launchApp":case "killApp":case "stopApp":case "clearState":if(typeof t.appId=="string")return `${e.command} ${t.appId}`;break;case "openLink":if(typeof t.url=="string")return `openLink ${t.url}`;break;case "runScript":case "evalScript":if(typeof t.path=="string")return `${e.command} ${t.path}`;if(typeof t.sourceDescription=="string")return `${e.command} ${t.sourceDescription}`;if(typeof t.script=="string")return `${e.command} ${t.script}`;break;case "assertWithAI":case "assertNoDefectsWithAI":case "extractTextWithAI":if(typeof t.prompt=="string")return `${e.command} \u2192 ${t.prompt}`;break;case "retry":if(typeof t.maxRetries=="number")return `retry \xD7 ${t.maxRetries}`;break;case "repeat":if(typeof t.times=="number")return `repeat \xD7 ${t.times}`;break;case "runFlow":if(typeof t.file=="string")return `runFlow ${t.file}`;break}return e.selector?`${e.command} \u2192 ${e.selector}`:e.command}function He(e,t){let r=Date.parse(e.timestamp),n=Number.isFinite(r)&&Number.isFinite(t)?Math.max(0,(r-t)/1e3):null,o=(e.children??[]).map(s=>He(s,t));return {title:eo(e),category:Zn(e.category),status:e.status==="failed"?"failed":"passed",duration:e.duration,timestamp:e.timestamp,videoOffset:n,error:e.error??null,children:o}}function to(e,t){let r=Date.parse(e.timestamp),n=Date.parse(t.timestamp);return Number.isFinite(r)&&Number.isFinite(n)&&r!==n?r-n:0}function ro(e,t){let r=Date.parse(e.startedAt),n=[...e.commands].sort((l,c)=>{let d=Date.parse(l.timestamp),u=Date.parse(c.timestamp);if(Number.isFinite(d)&&Number.isFinite(u)&&d!==u)return d-u;let p=l.sequenceNumber??0,y=c.sequenceNumber??0;return p-y}),o=[...e.assertions].sort((l,c)=>{let d=Date.parse(l.timestamp),u=Date.parse(c.timestamp);if(Number.isFinite(d)&&Number.isFinite(u)&&d!==u)return d-u;let p=l.sequenceNumber??0,y=c.sequenceNumber??0;return p-y}),s=[...n.map(l=>He(l,r)),...o.map(l=>He(l,r))];s.sort(to);let i=e.screenshotPaths.length>0||e.videoPath?{screenshot:e.screenshotPaths[0]??void 0,video:e.videoPath??void 0}:null,a=[...e.tags];return e.platform!=="unknown"&&!a.includes(e.platform)&&a.push(e.platform),{title:e.flowName,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:0,tags:a,failure:e.failureMessage?{message:e.failureMessage,line:null,code:null,stack:null}:null,testId:`${e.flowFile}::${e.flowName}`,filePath:e.flowFile,suiteName:e.appId??"maestro-suite",testType:"mobile",isFlaky:false,retryStatus:null,expectedStatus:"passed",actualStatus:e.status,artifacts:i,networkRequests:null,apiCalls:t.length>0?[...t]:null,apiAssertions:null,actions:s.length>0?s:null,consoleLogs:null}}function Ut(e,t){let r=`${e.flowFile}::${e.flowName}`,n=t?.get(r)??[],o=ro(e,n);return {url:e.appId??"maestro-flow",navigationType:"page_load",visitedAt:e.startedAt,duration:e.duration,specFile:e.flowFile,domContentLoadedAt:null,networkIdleAt:null,networkStats:null,tests:[o]}}function $e(e,t){return e.map(r=>Ut(r,t))}var Ht={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0};function no(e){return e===null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function Be(e,t){if(e.length===0)return null;let r=Math.min(e.length-1,Math.floor(t/100*e.length));return e[r]}function oo(e){if(e.length===0)return {totalApiCalls:0,uniqueApiUrls:0,apiCallsByMethod:{},apiCallsByStatusRange:{...Ht},apiResponseTime:null};let t={},r={...Ht},n=new Set,o=[];for(let i of e)t[i.method]=(t[i.method]??0)+1,r[no(i.responseStatusCode)]+=1,n.add(i.url),Number.isFinite(i.responseTimeMs)&&i.responseTimeMs>0&&o.push(i.responseTimeMs);o.sort((i,a)=>i-a);let s=o.length>0?{p50:Be(o,50)??0,p95:Be(o,95)??0,p99:Be(o,99)??0,avg:o.reduce((i,a)=>i+a,0)/o.length,min:o[0],max:o[o.length-1]}:null;return {totalApiCalls:e.length,uniqueApiUrls:n.size,apiCallsByMethod:t,apiCallsByStatusRange:r,apiResponseTime:s}}function G(e){let t=0,r=0,n=0,o=0,s=0,i=0,a=0,l=0,c=0,d=e.length,u=0,p={},y=new Set,h=[];for(let b of e){y.add(b.url);for(let x of b.tests){switch(t++,x.status){case "passed":r++;break;case "failed":n++;break;case "flaky":o++;break;case "skipped":s++;break;case "timedout":i++;break}if(x.actions)for(let T of x.actions)if(u++,T.category==="assertion")a++,T.status==="passed"?l++:c++;else {let R=T.category;p[R]=(p[R]??0)+1;}x.apiCalls&&x.apiCalls.length>0&&h.push(...x.apiCalls);}}let g=oo(h);return {total:t,passed:r,failed:n,flaky:o,skipped:s,timedout:i,...g,totalAssertions:a,passedAssertions:l,failedAssertions:c,totalNavigations:d,uniqueNavigationUrls:y.size,totalTimelineSteps:e.length,totalActionSteps:u,actionStepsByCategory:p}}var $t=`
5
5
  /* \u2500\u2500 Theme Variables (verbatim from Appium) \u2500\u2500 */
6
6
  :root,[data-theme="dark"]{
7
7
  --bg:#0f1117;--bg-1:#161b22;--bg-2:#1c2128;--bg-3:#21262d;--bg-code:#13111c;
@@ -1244,14 +1244,14 @@ document.addEventListener('keydown',function(e){
1244
1244
  Then install + TRUST the mitmproxy CA:
1245
1245
  1. Open http://mitm.it from Safari on the device \u2192 install profile.
1246
1246
  2. Settings \u2192 General \u2192 About \u2192 Certificate Trust Settings \u2192 enable mitmproxy.
1247
- `));}async function Qt(e,t){return new Promise(r=>{let n=t?["-s",t,...e]:e,o=child_process.spawn("adb",n,{shell:true,stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout?.on("data",a=>{s+=a.toString();}),o.stderr?.on("data",a=>{i+=a.toString();}),o.on("error",()=>r({code:127,stdout:s,stderr:i||"adb not on PATH"})),o.on("close",a=>r({code:a??1,stdout:s,stderr:i}));})}async function Ao(e){let{deviceId:t,proxyHost:r,proxyPort:n,quiet:o,skipCertInstall:s}=e;if(!er("adb"))return E(o,"\u26A0 TestRelic: `adb` not on PATH; skipping automatic Android proxy setup. See manual instructions:"),U(o,"android",r,n),$;let i=await Qt(["shell","settings","put","global","http_proxy",`${r}:${n}`],t);return i.code!==0?(E(o,`\u26A0 TestRelic: adb set proxy failed: ${i.stderr.trim()||"unknown error"}`),U(o,"android",r,n),$):(E(o,`\u2139 TestRelic: Android proxy set to ${r}:${n} on ${t??"default device"}.`),s||E(o,`\u2139 TestRelic: if HTTPS calls fail, install the mitmproxy CA on the emulator:
1247
+ `));}async function Qt(e,t){return new Promise(r=>{let n=t?["-s",t,...e]:e,o=child_process.spawn("adb",n,{shell:true,stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout?.on("data",a=>{s+=a.toString();}),o.stderr?.on("data",a=>{i+=a.toString();}),o.on("error",()=>r({code:127,stdout:s,stderr:i||"adb not on PATH"})),o.on("close",a=>r({code:a??1,stdout:s,stderr:i}));})}async function To(e){let{deviceId:t,proxyHost:r,proxyPort:n,quiet:o,skipCertInstall:s}=e;if(!er("adb"))return E(o,"\u26A0 TestRelic: `adb` not on PATH; skipping automatic Android proxy setup. See manual instructions:"),U(o,"android",r,n),$;let i=await Qt(["shell","settings","put","global","http_proxy",`${r}:${n}`],t);return i.code!==0?(E(o,`\u26A0 TestRelic: adb set proxy failed: ${i.stderr.trim()||"unknown error"}`),U(o,"android",r,n),$):(E(o,`\u2139 TestRelic: Android proxy set to ${r}:${n} on ${t??"default device"}.`),s||E(o,`\u2139 TestRelic: if HTTPS calls fail, install the mitmproxy CA on the emulator:
1248
1248
  open http://mitm.it from Chrome on the emulator and follow prompts,
1249
1249
  OR for a system-level install:
1250
1250
  adb root && adb remount && adb push <mitm-ca>.0 /system/etc/security/cacerts/ && adb reboot
1251
- Set --skip-cert-install to silence this hint.`),{teardown:async()=>{await Qt(["shell","settings","put","global","http_proxy",":0"],t);}})}async function To(e){return new Promise(t=>{let r=child_process.spawn("xcrun",e,{shell:true,stdio:["ignore","pipe","pipe"]}),n="",o="";r.stdout?.on("data",s=>{n+=s.toString();}),r.stderr?.on("data",s=>{o+=s.toString();}),r.on("error",()=>t({code:127,stdout:n,stderr:o||"xcrun not on PATH"})),r.on("close",s=>t({code:s??1,stdout:n,stderr:o}));})}async function Io(e){let{proxyHost:t,proxyPort:r,quiet:n,skipCertInstall:o}=e;if(process.platform!=="darwin")return E(n,"\u26A0 TestRelic: iOS simulator capture requires macOS; the host is not Darwin. Skipping setup."),U(n,"ios",t,r),$;if(!er("xcrun"))return E(n,"\u26A0 TestRelic: `xcrun` not on PATH; skipping automatic iOS simulator setup."),U(n,"ios",t,r),$;if(!o){let s=path.join(process.env.HOME??"",".mitmproxy","mitmproxy-ca-cert.pem");if(fs.existsSync(s)){let i=e.deviceId??"booted",a=await To(["simctl","keychain",i,"add-root-cert",s]);a.code===0?E(n,`\u2139 TestRelic: installed mitmproxy CA on iOS simulator (${i}).`):(E(n,`\u26A0 TestRelic: failed to add-root-cert via simctl: ${a.stderr.trim()}`),U(n,"ios",t,r));}else E(n,`\u26A0 TestRelic: mitmproxy CA not found at ${s}. Run mitmdump once to generate it,
1251
+ Set --skip-cert-install to silence this hint.`),{teardown:async()=>{await Qt(["shell","settings","put","global","http_proxy",":0"],t);}})}async function Ao(e){return new Promise(t=>{let r=child_process.spawn("xcrun",e,{shell:true,stdio:["ignore","pipe","pipe"]}),n="",o="";r.stdout?.on("data",s=>{n+=s.toString();}),r.stderr?.on("data",s=>{o+=s.toString();}),r.on("error",()=>t({code:127,stdout:n,stderr:o||"xcrun not on PATH"})),r.on("close",s=>t({code:s??1,stdout:n,stderr:o}));})}async function Io(e){let{proxyHost:t,proxyPort:r,quiet:n,skipCertInstall:o}=e;if(process.platform!=="darwin")return E(n,"\u26A0 TestRelic: iOS simulator capture requires macOS; the host is not Darwin. Skipping setup."),U(n,"ios",t,r),$;if(!er("xcrun"))return E(n,"\u26A0 TestRelic: `xcrun` not on PATH; skipping automatic iOS simulator setup."),U(n,"ios",t,r),$;if(!o){let s=path.join(process.env.HOME??"",".mitmproxy","mitmproxy-ca-cert.pem");if(fs.existsSync(s)){let i=e.deviceId??"booted",a=await Ao(["simctl","keychain",i,"add-root-cert",s]);a.code===0?E(n,`\u2139 TestRelic: installed mitmproxy CA on iOS simulator (${i}).`):(E(n,`\u26A0 TestRelic: failed to add-root-cert via simctl: ${a.stderr.trim()}`),U(n,"ios",t,r));}else E(n,`\u26A0 TestRelic: mitmproxy CA not found at ${s}. Run mitmdump once to generate it,
1252
1252
  then re-run with --capture-network. Falling back to manual instructions:`),U(n,"ios",t,r);}return E(n,`\u2139 TestRelic: in the iOS simulator, configure Wi-Fi \u2192 (i) \u2192 Manual proxy:
1253
1253
  Server: ${t} Port: ${r}
1254
- (We do not set host-wide \`networksetup\` proxy automatically; see docs.)`),$}async function tr(e){switch(e.platform){case "android":return Ao(e);case "ios":return Io(e);case "web":return E(e.quiet,"\u2139 TestRelic: --capture-network ignored for Maestro web flows (browser already handles HTTP)."),$;default:return E(e.quiet,"\u26A0 TestRelic: target platform unknown; printing manual proxy setup instructions:"),U(e.quiet,"android",e.proxyHost,e.proxyPort),U(e.quiet,"ios",e.proxyHost,e.proxyPort),$}}function _o(){let e=crypto.randomBytes(8).toString("hex");return path.join(os$1.tmpdir(),`testrelic-maestro-${e}`)}function nr(e,t){let r=[];e.platform&&r.push("--platform",e.platform),e.device&&r.push("--device",e.device),r.push("test");let n=path.join(t,"report.xml"),o=path.join(t,"artifacts"),s=path.join(t,"debug");if(r.push("--format","junit"),r.push("--output",n),r.push("--test-output-dir",o),r.push("--debug-output",s),e.analyze&&r.push("--analyze"),e.includeTags&&r.push("--include-tags",e.includeTags),e.excludeTags&&r.push("--exclude-tags",e.excludeTags),e.shards&&e.shards>1&&r.push("--shards",String(e.shards)),e.config&&r.push("--config",e.config),e.env)for(let[i,a]of Object.entries(e.env))r.push("-e",`${i}=${a}`);return e.maestroArgs&&r.push(...e.maestroArgs),r.push(...e.flowPaths),r}function Lo(e){switch((e??"").toLowerCase()){case "android":return "android";case "ios":return "ios";case "web":return "web";default:return "unknown"}}function Do(e,t,r,n,o,s,i){return new Promise(a=>{let l=[],c=[],d=child_process.spawn("maestro",e,{stdio:["inherit","pipe","pipe"],shell:true});d.stdout.on("data",u=>{l.push(u),s||process.stdout.write(u);}),d.stderr.on("data",u=>{c.push(u),s||process.stderr.write(u);}),d.on("close",async u=>{try{await i();}catch{}a({exitCode:u??1,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:Buffer.concat(l).toString("utf-8"),stderr:Buffer.concat(c).toString("utf-8"),networkJsonlDir:o});}),d.on("error",async u=>{try{await i();}catch{}a({exitCode:127,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:"",stderr:`Failed to start maestro CLI: ${u.message}`,networkJsonlDir:o});});})}async function No(e,t={}){let r=e.outputDir?path.resolve(e.outputDir):_o();fs.mkdirSync(path.join(r,"artifacts"),{recursive:true}),fs.mkdirSync(path.join(r,"debug"),{recursive:true});let n=nr(e,r),o=path.join(r,"report.xml"),s=path.join(r,"artifacts"),i=path.join(r,"debug"),a=null,l=null,c=t.network;if(c?.enabled){let p=path.join(r,"network");a=await Xt({config:c,outputDir:p,verbose:!e.quiet}),a&&(l=await tr({platform:Lo(e.platform),deviceId:e.device,proxyHost:a.host,proxyPort:a.port,skipCertInstall:c.skipCertInstall,quiet:e.quiet}));}let d=a?.outputDir??null,u=async()=>{if(a&&await new Promise(p=>setTimeout(p,500)),l)try{await l.teardown();}catch{}if(a)try{await a.stop();}catch{}};return Do(n,o,s,i,d,e.quiet,u)}var ir="[REDACTED]";function or(e,t){if(!e)return null;let r=new Set(t.map(o=>o.toLowerCase())),n={};for(let[o,s]of Object.entries(e))n[o]=r.has(o.toLowerCase())?ir:s;return n}function Ve(e,t){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>Ve(n,t));let r={};for(let[n,o]of Object.entries(e))r[n]=t.has(n)?ir:Ve(o,t);return r}function sr(e,t){if(!e||t.length===0)return e;try{let r=JSON.parse(e),n=Ve(r,new Set(t));return JSON.stringify(n)}catch{return e}}function Je(e,t,r){return {...e,requestHeaders:or(e.requestHeaders,t),responseHeaders:or(e.responseHeaders,t),requestBody:sr(e.requestBody,r),responseBody:e.isBinary?e.responseBody:sr(e.responseBody,r)}}function We(e,t,r){let n=o=>typeof o=="string"?e.includes(o):o.test(e);return r.some(n)?false:t.length===0?true:t.some(n)}function Ho(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return typeof r.url!="string"||typeof r.method!="string"?null:{id:r.id??`api-call-${Date.now()}`,timestamp:r.timestamp??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:r.requestHeaders??null,requestBody:r.requestBody??null,responseStatusCode:r.responseStatusCode??null,responseStatusText:r.responseStatusText??null,responseHeaders:r.responseHeaders??null,responseBody:r.responseBody??null,responseTimeMs:typeof r.responseTimeMs=="number"?r.responseTimeMs:0,isBinary:r.isBinary??!1,error:r.error??null}}catch{return null}}function $o(e,t){let r=[];for(let n of e.split(/\r?\n/)){let o=Ho(n);o&&We(o.url,t.includeUrls,t.excludeUrls)&&r.push(Je(o,t.redactHeaders,t.redactBodyFields));}return r}function Bo(e,t){try{return $o(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function jo(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>t.endsWith(".jsonl")).map(t=>path.join(e,t))}catch{return []}}function ar(e){if(!e||e.length===0)return null;let t={};for(let r of e)typeof r.name=="string"&&typeof r.value=="string"&&(t[r.name]=r.value);return Object.keys(t).length>0?t:null}function zo(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.params)?e.params.map(t=>`${encodeURIComponent(t.name)}=${encodeURIComponent(t.value??"")}`).join("&"):null:null}function qo(e){return e?/^(image|audio|video|application\/(octet-stream|pdf|zip|protobuf))/.test(e):false}function Go(e,t){let r=e.request,n=e.response;if(!r?.method||!r.url)return null;let o=n?.content,s=qo(o?.mimeType);return {id:`har-call-${t}`,timestamp:e.startedDateTime??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:ar(r.headers),requestBody:zo(r.postData),responseStatusCode:typeof n?.status=="number"&&n.status>0?n.status:null,responseStatusText:n?.statusText??null,responseHeaders:ar(n?.headers),responseBody:o?.text??null,responseTimeMs:typeof e.time=="number"?e.time:0,isBinary:s,error:null}}function Vo(e,t){let r;try{r=JSON.parse(e);}catch{return []}let n=r.log?.entries??[],o=[];return n.forEach((s,i)=>{let a=Go(s,i);a&&We(a.url,t.includeUrls,t.excludeUrls)&&o.push(Je(a,t.redactHeaders,t.redactBodyFields));}),o}function Jo(e,t){try{return Vo(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function Wo(e,t){let r=new Map;for(let o of t)r.set(o.testId,[]);if(e.length===0||t.length===0)return r;let n=t.map(o=>({testId:o.testId,startMs:Date.parse(o.startedAt),endMs:Date.parse(o.completedAt)}));for(let o of e){let s=Date.parse(o.timestamp);if(!Number.isFinite(s))continue;let i=n.find(l=>Number.isFinite(l.startMs)&&Number.isFinite(l.endMs)&&s>=l.startMs&&s<=l.endMs);if(i){r.get(i.testId).push(o);continue}let a=null;for(let l of n){if(!Number.isFinite(l.startMs)||!Number.isFinite(l.endMs))continue;let c=s<l.startMs?l.startMs-s:s-l.endMs;(!a||c<a.dist)&&(a={testId:l.testId,dist:c});}a&&r.get(a.testId).push(o);}return r}function dr(e,t,r){if(!t.enabled&&!t.harPath)return new Map;let n=[];if(e)for(let o of jo(e))n.push(...Bo(o,t));return t.harPath&&fs.existsSync(t.harPath)&&n.push(...Jo(t.harPath,t)),n.length===0?new Map:Wo(n,r)}function ur(e){return e.map((t,r)=>({...t,id:`api-call-${r}`}))}var Xo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function Ke(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Xo.has(t.hostname)))throw core.createError(core.ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Qo=3e3;async function ee(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Qo);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function fr(e){return new Promise(t=>setTimeout(t,e))}async function pr(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string")return r.message}catch{}return `HTTP ${e.status}`}async function te(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(s.ok){let a=await s.json();return {accessToken:a.accessToken,refreshToken:a.refreshToken,expiresIn:a.expiresIn,orgId:a.orgId,orgName:a.orgName,userId:a.userId,userName:a.userName}}if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;if(!isNaN(l)&&l>0){await fr(l);let c=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(c.ok){let d=await c.json();return {accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn,orgId:d.orgId,orgName:d.orgName,userId:d.userId,userName:d.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return s.status===400?{code:"validation_error",message:await pr(s),statusCode:400}:s.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:s.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await pr(s),statusCode:s.status}}catch(s){return s instanceof DOMException&&s.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(o);}}function re(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function Ye(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal});if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;!isNaN(l)&&l>0&&(await fr(l),s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal}));}if(!s.ok)return null;let i=await s.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn}}catch{return null}finally{clearTimeout(o);}}async function Xe(e,t,r,n,o,s){let i=new AbortController,a=setTimeout(()=>i.abort(),o);try{let l={gitId:r,displayName:n};s&&(l.branch=s);let c=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:i.signal});if(!c.ok)return null;let d=await c.json();return {repoId:d.repoId,displayName:d.displayName}}catch{return null}finally{clearTimeout(a);}}var ns=5e3;function H(e,t){try{return child_process.execSync(e,{cwd:t,timeout:ns,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function Qe(e){let t=H("git rev-parse --abbrev-ref HEAD",e),r=H("git rev-parse --short HEAD",e),n=H("git log -1 --pretty=%s",e),o=H("git log -1 --format=%an",e)??H("git config user.name",e),s=os(e),i=s?j(s):null;return {branch:t,commitSha:r,commitMessage:n,commitAuthor:o,remoteUrl:i}}function os(e){let t=H("git remote get-url origin",e);if(t)return t;let r=H("git remote",e);if(!r)return null;let n=r.split(`
1254
+ (We do not set host-wide \`networksetup\` proxy automatically; see docs.)`),$}async function tr(e){switch(e.platform){case "android":return To(e);case "ios":return Io(e);case "web":return E(e.quiet,"\u2139 TestRelic: --capture-network ignored for Maestro web flows (browser already handles HTTP)."),$;default:return E(e.quiet,"\u26A0 TestRelic: target platform unknown; printing manual proxy setup instructions:"),U(e.quiet,"android",e.proxyHost,e.proxyPort),U(e.quiet,"ios",e.proxyHost,e.proxyPort),$}}function _o(){let e=crypto.randomBytes(8).toString("hex");return path.join(os$1.tmpdir(),`testrelic-maestro-${e}`)}function nr(e,t){let r=[];e.platform&&r.push("--platform",e.platform),e.device&&r.push("--device",e.device),r.push("test");let n=path.join(t,"report.xml"),o=path.join(t,"artifacts"),s=path.join(t,"debug");if(r.push("--format","junit"),r.push("--output",n),r.push("--test-output-dir",o),r.push("--debug-output",s),e.analyze&&r.push("--analyze"),e.includeTags&&r.push("--include-tags",e.includeTags),e.excludeTags&&r.push("--exclude-tags",e.excludeTags),e.shards&&e.shards>1&&r.push("--shards",String(e.shards)),e.config&&r.push("--config",e.config),e.env)for(let[i,a]of Object.entries(e.env))r.push("-e",`${i}=${a}`);return e.maestroArgs&&r.push(...e.maestroArgs),r.push(...e.flowPaths),r}function Lo(e){switch((e??"").toLowerCase()){case "android":return "android";case "ios":return "ios";case "web":return "web";default:return "unknown"}}function Do(e,t,r,n,o,s,i){return new Promise(a=>{let l=[],c=[],d=child_process.spawn("maestro",e,{stdio:["inherit","pipe","pipe"],shell:true});d.stdout.on("data",u=>{l.push(u),s||process.stdout.write(u);}),d.stderr.on("data",u=>{c.push(u),s||process.stderr.write(u);}),d.on("close",async u=>{try{await i();}catch{}a({exitCode:u??1,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:Buffer.concat(l).toString("utf-8"),stderr:Buffer.concat(c).toString("utf-8"),networkJsonlDir:o});}),d.on("error",async u=>{try{await i();}catch{}a({exitCode:127,junitPath:t,testOutputDir:r,debugOutputDir:n,stdout:"",stderr:`Failed to start maestro CLI: ${u.message}`,networkJsonlDir:o});});})}async function No(e,t={}){let r=e.outputDir?path.resolve(e.outputDir):_o();fs.mkdirSync(path.join(r,"artifacts"),{recursive:true}),fs.mkdirSync(path.join(r,"debug"),{recursive:true});let n=nr(e,r),o=path.join(r,"report.xml"),s=path.join(r,"artifacts"),i=path.join(r,"debug"),a=null,l=null,c=t.network;if(c?.enabled){let p=path.join(r,"network");a=await Xt({config:c,outputDir:p,verbose:!e.quiet}),a&&(l=await tr({platform:Lo(e.platform),deviceId:e.device,proxyHost:a.host,proxyPort:a.port,skipCertInstall:c.skipCertInstall,quiet:e.quiet}));}let d=a?.outputDir??null,u=async()=>{if(a&&await new Promise(p=>setTimeout(p,500)),l)try{await l.teardown();}catch{}if(a)try{await a.stop();}catch{}};return Do(n,o,s,i,d,e.quiet,u)}var ir="[REDACTED]";function or(e,t){if(!e)return null;let r=new Set(t.map(o=>o.toLowerCase())),n={};for(let[o,s]of Object.entries(e))n[o]=r.has(o.toLowerCase())?ir:s;return n}function Ve(e,t){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>Ve(n,t));let r={};for(let[n,o]of Object.entries(e))r[n]=t.has(n)?ir:Ve(o,t);return r}function sr(e,t){if(!e||t.length===0)return e;try{let r=JSON.parse(e),n=Ve(r,new Set(t));return JSON.stringify(n)}catch{return e}}function Je(e,t,r){return {...e,requestHeaders:or(e.requestHeaders,t),responseHeaders:or(e.responseHeaders,t),requestBody:sr(e.requestBody,r),responseBody:e.isBinary?e.responseBody:sr(e.responseBody,r)}}function We(e,t,r){let n=o=>typeof o=="string"?e.includes(o):o.test(e);return r.some(n)?false:t.length===0?true:t.some(n)}function Ho(e){let t=e.trim();if(!t)return null;try{let r=JSON.parse(t);return typeof r.url!="string"||typeof r.method!="string"?null:{id:r.id??`api-call-${Date.now()}`,timestamp:r.timestamp??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:r.requestHeaders??null,requestBody:r.requestBody??null,responseStatusCode:r.responseStatusCode??null,responseStatusText:r.responseStatusText??null,responseHeaders:r.responseHeaders??null,responseBody:r.responseBody??null,responseTimeMs:typeof r.responseTimeMs=="number"?r.responseTimeMs:0,isBinary:r.isBinary??!1,error:r.error??null}}catch{return null}}function $o(e,t){let r=[];for(let n of e.split(/\r?\n/)){let o=Ho(n);o&&We(o.url,t.includeUrls,t.excludeUrls)&&r.push(Je(o,t.redactHeaders,t.redactBodyFields));}return r}function Bo(e,t){try{return $o(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function jo(e){if(!fs.existsSync(e))return [];try{return fs.readdirSync(e,{recursive:!0}).map(String).filter(t=>t.endsWith(".jsonl")).map(t=>path.join(e,t))}catch{return []}}function ar(e){if(!e||e.length===0)return null;let t={};for(let r of e)typeof r.name=="string"&&typeof r.value=="string"&&(t[r.name]=r.value);return Object.keys(t).length>0?t:null}function zo(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.params)?e.params.map(t=>`${encodeURIComponent(t.name)}=${encodeURIComponent(t.value??"")}`).join("&"):null:null}function qo(e){return e?/^(image|audio|video|application\/(octet-stream|pdf|zip|protobuf))/.test(e):false}function Go(e,t){let r=e.request,n=e.response;if(!r?.method||!r.url)return null;let o=n?.content,s=qo(o?.mimeType);return {id:`har-call-${t}`,timestamp:e.startedDateTime??new Date().toISOString(),method:r.method,url:r.url,requestHeaders:ar(r.headers),requestBody:zo(r.postData),responseStatusCode:typeof n?.status=="number"&&n.status>0?n.status:null,responseStatusText:n?.statusText??null,responseHeaders:ar(n?.headers),responseBody:o?.text??null,responseTimeMs:typeof e.time=="number"?e.time:0,isBinary:s,error:null}}function Vo(e,t){let r;try{r=JSON.parse(e);}catch{return []}let n=r.log?.entries??[],o=[];return n.forEach((s,i)=>{let a=Go(s,i);a&&We(a.url,t.includeUrls,t.excludeUrls)&&o.push(Je(a,t.redactHeaders,t.redactBodyFields));}),o}function Jo(e,t){try{return Vo(fs.readFileSync(e,"utf-8"),t)}catch{return []}}function Wo(e,t){let r=new Map;for(let o of t)r.set(o.testId,[]);if(e.length===0||t.length===0)return r;let n=t.map(o=>({testId:o.testId,startMs:Date.parse(o.startedAt),endMs:Date.parse(o.completedAt)}));for(let o of e){let s=Date.parse(o.timestamp);if(!Number.isFinite(s))continue;let i=n.find(l=>Number.isFinite(l.startMs)&&Number.isFinite(l.endMs)&&s>=l.startMs&&s<=l.endMs);if(i){r.get(i.testId).push(o);continue}let a=null;for(let l of n){if(!Number.isFinite(l.startMs)||!Number.isFinite(l.endMs))continue;let c=s<l.startMs?l.startMs-s:s-l.endMs;(!a||c<a.dist)&&(a={testId:l.testId,dist:c});}a&&r.get(a.testId).push(o);}return r}function dr(e,t,r){if(!t.enabled&&!t.harPath)return new Map;let n=[];if(e)for(let o of jo(e))n.push(...Bo(o,t));return t.harPath&&fs.existsSync(t.harPath)&&n.push(...Jo(t.harPath,t)),n.length===0?new Map:Wo(n,r)}function ur(e){return e.map((t,r)=>({...t,id:`api-call-${r}`}))}var Xo=new Set(["localhost","127.0.0.1","0.0.0.0"]);function Ke(e){let t=new URL(e);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&Xo.has(t.hostname)))throw core.createError(core.ErrorCode.CLOUD_CONFIG_INVALID,`HTTPS is required for cloud communication. Got: ${t.protocol}//${t.hostname}`)}var Qo=3e3;async function ee(e){let t=new AbortController,r=setTimeout(()=>t.abort(),Qo);try{return (await fetch(`${e}/health`,{method:"GET",signal:t.signal})).ok}catch{return false}finally{clearTimeout(r);}}async function fr(e){return new Promise(t=>setTimeout(t,e))}async function pr(e){try{let r=(await e.json()).error;if(r&&typeof r.message=="string")return r.message}catch{}return `HTTP ${e.status}`}async function te(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(s.ok){let a=await s.json();return {accessToken:a.accessToken,refreshToken:a.refreshToken,expiresIn:a.expiresIn,orgId:a.orgId,orgName:a.orgName,userId:a.userId,userName:a.userName}}if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;if(!isNaN(l)&&l>0){await fr(l);let c=await fetch(`${e}/sdk/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t}),signal:n.signal});if(c.ok){let d=await c.json();return {accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn,orgId:d.orgId,orgName:d.orgName,userId:d.userId,userName:d.userName}}}return {code:"rate_limited",message:"Rate limited during token exchange.",statusCode:429}}return s.status===400?{code:"validation_error",message:await pr(s),statusCode:400}:s.status===401?{code:"invalid_key",message:"API key is invalid or has been revoked.",statusCode:401}:s.status===403?{code:"expired_key",message:"API key has expired.",statusCode:403}:{code:"server_error",message:await pr(s),statusCode:s.status}}catch(s){return s instanceof DOMException&&s.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(o);}}function re(e){return "code"in e&&typeof e.code=="string"&&["invalid_key","expired_key","validation_error","rate_limited","server_error","network_error","timeout"].includes(e.code)}async function Ye(e,t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{let s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal});if(s.status===429){let a=s.headers.get("Retry-After"),l=a?parseInt(a,10)*1e3:5e3;!isNaN(l)&&l>0&&(await fr(l),s=await fetch(`${e}/sdk/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t}),signal:n.signal}));}if(!s.ok)return null;let i=await s.json();return {accessToken:i.accessToken,refreshToken:i.refreshToken,expiresIn:i.expiresIn}}catch{return null}finally{clearTimeout(o);}}async function Xe(e,t,r,n,o,s){let i=new AbortController,a=setTimeout(()=>i.abort(),o);try{let l={gitId:r,displayName:n};s&&(l.branch=s);let c=await fetch(`${e}/repos/resolve`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(l),signal:i.signal});if(!c.ok)return null;let d=await c.json();return {repoId:d.repoId,displayName:d.displayName}}catch{return null}finally{clearTimeout(a);}}var ns=5e3;function H(e,t){try{return child_process.execSync(e,{cwd:t,timeout:ns,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function Qe(e){let t=H("git rev-parse --abbrev-ref HEAD",e),r=H("git rev-parse --short HEAD",e),n=H("git log -1 --pretty=%s",e),o=H("git log -1 --format=%an",e)??H("git config user.name",e),s=os(e),i=s?j(s):null;return {branch:t,commitSha:r,commitMessage:n,commitAuthor:o,remoteUrl:i}}function os(e){let t=H("git remote get-url origin",e);if(t)return t;let r=H("git remote",e);if(!r)return null;let n=r.split(`
1255
1255
  `)[0]?.trim();return n?H(`git remote get-url ${n}`,e):null}function j(e){let t=e.trim();return t=t.replace(/^[a-z+]+:\/\//,""),t=t.replace(/^[^@]+@/,""),t=t.replace(/:(?!\d)/,"/"),t=t.replace(/\.git$/,""),t=t.replace(/\/+$/,""),t=t.replace(/^[^@/]+@/,""),t.toLowerCase()}function Ze(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function gr(e){try{let t=fs.readFileSync(path.join(e,"package.json"),"utf-8"),r=JSON.parse(t);return typeof r.name=="string"&&r.name.length>0?r.name:null}catch{return null}}function z(e){let t=gr(e);return t||`local/${path.basename(e)}`}var ds="1.0.0",mr=10;function oe(e,t,r,n,o,s,i,a){try{fs.mkdirSync(e,{recursive:!0});let l=Date.now(),c=`${l}-${t}-${r}.json`,d=path.join(e,c),u={version:ds,queuedAt:new Date(l).toISOString(),reason:n,retryCount:0,targetEndpoint:o,method:s,payload:i,headers:a},p=d+".tmp";fs.writeFileSync(p,JSON.stringify(u,null,2),"utf-8"),fs.renameSync(p,d);}catch(l){l.code==="ENOSPC"?process.stderr.write(`\u26A0 TestRelic: Disk full \u2014 unable to queue upload data.
1256
1256
  `):process.stderr.write(`\u26A0 TestRelic: Unable to queue upload data.
1257
1257
  `);}}async function tt(e,t,r){let n;try{n=fs.readdirSync(e).filter(s=>s.endsWith(".json")&&!s.endsWith(".tmp")).sort();}catch{return}if(n.length===0)return;let o=[];for(let s=0;s<n.length;s+=mr)o.push(n.slice(s,s+mr));for(let s of o)for(let i of s){let a=path.join(e,i);try{if(!fs.statSync(a).isFile())continue;let c=fs.readFileSync(a,"utf-8"),d=JSON.parse(c);if(!core.isValidQueueEntry(d)){fs.unlinkSync(a);continue}let u=d;if((await fetch(u.targetEndpoint,{method:u.method,headers:{...u.headers,Authorization:`Bearer ${r}`},body:JSON.stringify(u.payload)})).ok)fs.unlinkSync(a);else return}catch{return}}}function rt(e,t){try{let r=fs.readdirSync(e).filter(o=>o.endsWith(".json")&&!o.endsWith(".tmp")),n=Date.now();for(let o of r){let s=path.join(e,o);try{let i=fs.readFileSync(s,"utf-8"),l=JSON.parse(i).queuedAt;if(typeof l=="string"){let c=new Date(l).getTime();n-c>t&&fs.unlinkSync(s);}}catch{try{fs.unlinkSync(s);}catch{}}}}catch{}}var ys=3e5,bs=864e5,xs=6e4,br=3e4,xr="https://platform.testrelic.ai/settings/api-keys",J=class{constructor(t){this.gitMetadata=null;this.repoId=null;this.failureReason=null;this.flushPromise=null;this.healthCheckTimer=null;this.config=t,this.authState={mode:"pending",accessToken:null,refreshToken:null,expiresAt:null,orgId:null,orgName:null,userId:null,userName:null};}async initialize(){if(!this.config||!this.config.apiKey){this.setLocalMode("no_api_key"),process.stderr.write(`\u2139 TestRelic: No API key configured. Running in local mode.
@@ -1266,11 +1266,11 @@ document.addEventListener('keydown',function(e){
1266
1266
  `);break;case "rate_limited":this.setLocalMode("rate_limited"),process.stderr.write(`\u26A0 TestRelic: Rate limited during authentication. Running in local mode.
1267
1267
  `);break;default:this.setLocalMode(`auth_error_${r??"unknown"}`),process.stderr.write(`\u26A0 TestRelic: Cloud authentication failed. Running in local mode.
1268
1268
  `);break}}async resolveRepoId(){if(!this.config||!this.authState.accessToken)return;let t=this.gitMetadata?.remoteUrl?j(this.gitMetadata.remoteUrl):null,r=t?Ze(t):this.config.projectName??z(process.cwd()),n=t??this.config.projectName??z(process.cwd()),o=this.readRepoCache(n);if(o){this.repoId=o.repoId;return}try{let s=await Xe(this.config.endpoint,this.authState.accessToken,n,r,this.config.timeout,this.gitMetadata?.branch);s&&(this.repoId=s.repoId,this.writeRepoCache(n,s.repoId,s.displayName));}catch{}}readRepoCache(t){if(!this.config)return null;let r=path.join(this.config.queueDirectory,"..","cache","repo.json");try{if(!fs.existsSync(r))return null;let n=fs.readFileSync(r,"utf-8"),o=JSON.parse(n);if(o.gitId!==t||Date.now()-o.resolvedAt>bs)return null;let s=this.hashApiKey();return s&&o.apiKeyHash!==s?null:o}catch{return null}}writeRepoCache(t,r,n){if(!this.config)return;let o=path.join(this.config.queueDirectory,"..","cache"),s=path.join(o,"repo.json");try{fs.mkdirSync(o,{recursive:!0});let i={repoId:r,gitId:t,displayName:n,resolvedAt:Date.now(),apiKeyHash:this.hashApiKey()??""},a=s+".tmp";fs.writeFileSync(a,JSON.stringify(i,null,2),"utf-8"),fs.renameSync(a,s);}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 t=this.authState.accessToken,r=this.config.queueDirectory,n=this.config.endpoint;this.flushPromise=Promise.race([tt(r,n,t),new Promise(o=>setTimeout(o,br))]).catch(()=>{});}startHealthCheck(){if(!this.config)return;let t=this.config.endpoint;this.healthCheckTimer=setInterval(async()=>{if(!this.isCloudMode()&&!(!this.failureReason||!["cloud_unreachable","auth_timeout","network_error"].includes(this.failureReason)))try{if(!await ee(t))return;if(this.config?.apiKey){let n=await te(this.config.endpoint,this.config.apiKey,this.config.timeout);if(!re(n)){let o=n;this.authState={mode:"cloud",accessToken:o.accessToken,refreshToken:o.refreshToken,expiresAt:Date.now()+o.expiresIn*1e3,orgId:o.orgId,orgName:o.orgName,userId:o.userId,userName:o.userName},this.failureReason=null,process.stderr.write(`\u2713 TestRelic: Cloud connectivity restored.
1269
- `),this.startBackgroundFlush();}}}catch{}},xs);}};var vs=1048576,se=[1e3,3e3,9e3],ie=3;function le(e,t,r,n,o){let s=n?.provider&&n.provider!=="unknown"?n.provider:"local";return {runId:e.testRunId,repoGitId:t,startedAt:e.startedAt,summary:e.summary,timeline:e.timeline,environment:s,testFramework:"maestro",...o&&o.length>0?{tests:o}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...e.completedAt?{finishedAt:e.completedAt}:{},...e.totalDuration?{duration:e.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{}}}async function ae(e){return new Promise(t=>setTimeout(t,e))}async function wr(e,t,r){for(let n=0;n<ie;n++)try{let o=await fetch(e,t);if(o.ok)return o;if(o.status===401&&r&&n===0){let s=await r();if(s){let i={...t,headers:{...t.headers,Authorization:`Bearer ${s}`}},a=await fetch(e,i);if(a.ok)return a}return null}if(o.status===429&&n<ie-1){let s=o.headers.get("Retry-After"),i=s?parseInt(s,10)*1e3:se[n];!isNaN(i)&&i>0?await ae(i):await ae(se[n]);continue}if(o.status>=500&&n<ie-1){await ae(se[n]);continue}return o}catch{if(n<ie-1){await ae(se[n]);continue}return null}return null}function ks(e){let t=JSON.stringify(e),r={"Content-Type":"application/json"};if(Buffer.byteLength(t,"utf-8")>vs){let n=zlib.gzipSync(Buffer.from(t,"utf-8"));return r["Content-Encoding"]="gzip",{body:n,headers:r}}return {body:t,headers:r}}async function ot(e,t,r,n){let o=`${e}/runs`,{body:s,headers:i}=ks(r);i.Authorization=`Bearer ${t}`;let a=await wr(o,{method:"POST",headers:i,body:s},n);return a?.ok?{success:true,statusCode:a.status,error:null}:a?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:a?`Upload failed with status ${a.status}`:"Upload failed after retries",statusCode:a?.status??null,payload:r,targetEndpoint:o,method:"POST"}}function Cs(e){let t={};for(let[r,n]of Object.entries(e))n!=null&&(t[r]=n);return t}async function Rs(e,t,r){let n=`${e}/runs/init`;try{let o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(Cs(r))});return o.ok?{runId:(await o.json()).runId}:null}catch{return null}}async function Ss(e,t,r,n){let o=`${e}/runs/${r}/finalize`;return (await wr(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(n)}))?.ok??false}var Es=5,ce=[1e3,3e3,9e3],q=3,Fs={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".mov":"video/quicktime",".zip":"application/zip"},st=0,it=[];async function Ps(){st>=Es&&await new Promise(e=>it.push(e)),st++;}function _s(){st--,it.length>0&&it.shift()();}async function de(e){return new Promise(t=>setTimeout(t,e))}function Ls(e){let t=e.substring(e.lastIndexOf(".")).toLowerCase();return Fs[t]??"application/octet-stream"}function Ds(e){try{return fs.statSync(e).size}catch{return 0}}async function Ns(e,t,r,n,o){let s=`${e}/artifacts/upload-url`,i=JSON.stringify({runId:r.runId,testId:r.testId,fileName:path.basename(r.filePath),contentType:o,type:r.type,sizeBytes:n});for(let a=0;a<q;a++)try{let l=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:i});if(l.ok)return await l.json();if(l.status>=500&&a<q-1){await de(ce[a]);continue}return null}catch{if(a<q-1){await de(ce[a]);continue}return null}return null}async function Os(e,t,r,n){for(let o=0;o<q;o++)try{let s=fs.createReadStream(t),i=stream.Readable.toWeb(s),a=await fetch(e,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(n)},body:i,duplex:"half"});if(a.ok)return !0;if(a.status>=500&&o<q-1){await de(ce[o]);continue}return !1}catch{if(o<q-1){await de(ce[o]);continue}return false}return false}async function Us(e,t,r){try{return (await fetch(`${e}/artifacts/confirm`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function vr(e,t,r,n){let o=Ds(r.filePath);if(o===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(o>n*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let s=Ls(r.filePath);await Ps();try{let i=await Ns(e,t,r,o,s);if(!i)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Os(i.uploadUrl,r.filePath,s,o))return {success:!1,storageKey:i.storageKey,artifactId:i.artifactId,error:"presigned_put_failed"};let l=await Us(e,t,i.artifactId);return {success:l,storageKey:i.storageKey,artifactId:i.artifactId,error:l?null:"confirm_failed"}}finally{_s();}}async function at(e,t,r,n){let o=new Map,s=r.map(async i=>{let a=await vr(e,t,i,n);o.set(i.filePath,a);});return await Promise.allSettled(s),o}function Hs(e){return e.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:e.GITHUB_RUN_ID??null,commitSha:e.GITHUB_SHA??null,branch:e.GITHUB_REF_NAME??null,runUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY&&e.GITHUB_RUN_ID?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`:null}}function $s(e){return e.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:e.CI_PIPELINE_ID??null,commitSha:e.CI_COMMIT_SHA??null,branch:e.CI_COMMIT_BRANCH??e.CI_COMMIT_REF_NAME??null,runUrl:e.CI_PIPELINE_URL??null}}function Bs(e){if(!e.JENKINS_URL)return null;let t=e.GIT_BRANCH??null;return t?.startsWith("origin/")&&(t=t.slice(7)),{provider:"jenkins",buildId:e.BUILD_ID??null,commitSha:e.GIT_COMMIT??null,branch:t,runUrl:e.BUILD_URL??null}}function js(e){return e.CIRCLECI!=="true"?null:{provider:"circleci",buildId:e.CIRCLE_BUILD_NUM??null,commitSha:e.CIRCLE_SHA1??null,branch:e.CIRCLE_BRANCH??null,runUrl:e.CIRCLE_BUILD_URL??null}}function zs(e){if(!e.BITBUCKET_PIPELINE_UUID)return null;let t=e.BITBUCKET_WORKSPACE&&e.BITBUCKET_REPO_SLUG&&e.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${e.BITBUCKET_WORKSPACE}/${e.BITBUCKET_REPO_SLUG}/pipelines/results/${e.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:e.BITBUCKET_BUILD_NUMBER??null,commitSha:e.BITBUCKET_COMMIT??null,branch:e.BITBUCKET_BRANCH??null,runUrl:t}}var qs=[Hs,$s,Bs,js,zs];function ue(e){let t=e??process.env;for(let r of qs){let n=r(t);if(n)return n}return null}function Gs(e){let t=[];for(let r of e){let n=r,o=n.tests;if(!Array.isArray(o)||o.length===0){t.push(r);continue}for(let s of o){t.push({timestamp:s.startedAt,title:s.title,category:"test",navigationType:n.navigationType,url:n.url,visitedAt:n.visitedAt,duration:s.duration,status:s.status,test_status:s.status,test_id:s.testId,test_title:s.title,specfile:s.filePath,suiteName:s.suiteName,type:"test",...s.failure?{error:s.failure.message,errorMessage:s.failure.message}:{}});for(let i of s.actions??[])t.push({timestamp:i.timestamp,title:i.title,category:i.category,status:i.status,test_status:s.status,duration:i.duration,error:i.error,test_id:s.testId,test_title:s.title,specfile:s.filePath,url:n.url,type:i.category==="assertion"?"assert":"action"});}}return t}function kr(e){let r=e.getGitMetadata()?.remoteUrl;return r?j(r):e.getConfig()?.projectName??z(process.cwd())}async function lt(e,t,r,n,o,s,i,a,l,c,d){try{let u=d?.length??0,p=(a?.length??0)+(l?.length??0)+u>0;if(e.isCloudMode()&&p&&await e.ensureValidToken()){let h=e.getEndpoint(),g=e.getAccessToken(),b=t?.artifactMaxSizeMb??50,x=[];for(let R of a??[])x.push({filePath:R,runId:r,testId:"maestro-suite",type:"screenshot"});let A=new Set;for(let R of d??[])x.push({filePath:R.path,runId:r,testId:R.testId,type:"video"}),A.add(R.path);for(let R of l??[])A.has(R)||x.push({filePath:R,runId:r,testId:"maestro-suite",type:"video"});if(x.length>0){let R=await at(h,g,x,b),D=Array.from(R.entries()),I=D.filter(([,m])=>m.success).length,f=D.filter(([,m])=>!m.success);if(I>0){let m=x.filter(k=>k.type==="video").length,w=d?.length??0,v=x.filter(k=>k.type==="screenshot").length,S=[];if(v>0&&S.push(`${v} screenshot(s)`),m>0){let k=w>0?` (${w} per-flow)`:"";S.push(`${m} video(s)${k}`);}process.stderr.write(`\u2713 TestRelic: Uploaded ${I} artifact(s) [${S.join(", ")}] to cloud storage.
1269
+ `),this.startBackgroundFlush();}}}catch{}},xs);}};var vs=1048576,se=[1e3,3e3,9e3],ie=3;function le(e,t,r,n,o){let s=n?.provider&&n.provider!=="unknown"?n.provider:"local";return {runId:e.testRunId,repoGitId:t,startedAt:e.startedAt,summary:e.summary,timeline:e.timeline,environment:s,testFramework:"maestro",testType:"mobile",...o&&o.length>0?{tests:o}:{},...r?.branch?{branch:r.branch}:{},...r?.commitSha?{commit:r.commitSha}:{},...r?.commitMessage?{commitMessage:r.commitMessage}:{},...r?.commitAuthor?{commitAuthor:r.commitAuthor}:{},...e.completedAt?{finishedAt:e.completedAt}:{},...e.totalDuration?{duration:e.totalDuration}:{},...n?.provider?{ciProvider:n.provider}:{},...n?.runUrl?{ciRunUrl:n.runUrl}:{}}}async function ae(e){return new Promise(t=>setTimeout(t,e))}async function wr(e,t,r){for(let n=0;n<ie;n++)try{let o=await fetch(e,t);if(o.ok)return o;if(o.status===401&&r&&n===0){let s=await r();if(s){let i={...t,headers:{...t.headers,Authorization:`Bearer ${s}`}},a=await fetch(e,i);if(a.ok)return a}return null}if(o.status===429&&n<ie-1){let s=o.headers.get("Retry-After"),i=s?parseInt(s,10)*1e3:se[n];!isNaN(i)&&i>0?await ae(i):await ae(se[n]);continue}if(o.status>=500&&n<ie-1){await ae(se[n]);continue}return o}catch{if(n<ie-1){await ae(se[n]);continue}return null}return null}function ks(e){let t=JSON.stringify(e),r={"Content-Type":"application/json"};if(Buffer.byteLength(t,"utf-8")>vs){let n=zlib.gzipSync(Buffer.from(t,"utf-8"));return r["Content-Encoding"]="gzip",{body:n,headers:r}}return {body:t,headers:r}}async function ot(e,t,r,n){let o=`${e}/runs`,{body:s,headers:i}=ks(r);i.Authorization=`Bearer ${t}`;let a=await wr(o,{method:"POST",headers:i,body:s},n);return a?.ok?{success:true,statusCode:a.status,error:null}:a?.status===409?{success:true,statusCode:409,error:null}:{success:false,reason:a?`Upload failed with status ${a.status}`:"Upload failed after retries",statusCode:a?.status??null,payload:r,targetEndpoint:o,method:"POST"}}function Cs(e){let t={};for(let[r,n]of Object.entries(e))n!=null&&(t[r]=n);return t}async function Rs(e,t,r){let n=`${e}/runs/init`;try{let o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(Cs(r))});return o.ok?{runId:(await o.json()).runId}:null}catch{return null}}async function Ss(e,t,r,n){let o=`${e}/runs/${r}/finalize`;return (await wr(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(n)}))?.ok??false}var Es=5,ce=[1e3,3e3,9e3],q=3,Fs={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".webm":"video/webm",".mp4":"video/mp4",".mov":"video/quicktime",".zip":"application/zip"},st=0,it=[];async function Ps(){st>=Es&&await new Promise(e=>it.push(e)),st++;}function _s(){st--,it.length>0&&it.shift()();}async function de(e){return new Promise(t=>setTimeout(t,e))}function Ls(e){let t=e.substring(e.lastIndexOf(".")).toLowerCase();return Fs[t]??"application/octet-stream"}function Ds(e){try{return fs.statSync(e).size}catch{return 0}}async function Ns(e,t,r,n,o){let s=`${e}/artifacts/upload-url`,i=JSON.stringify({runId:r.runId,testId:r.testId,fileName:path.basename(r.filePath),contentType:o,type:r.type,sizeBytes:n});for(let a=0;a<q;a++)try{let l=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:i});if(l.ok)return await l.json();if(l.status>=500&&a<q-1){await de(ce[a]);continue}return null}catch{if(a<q-1){await de(ce[a]);continue}return null}return null}async function Os(e,t,r,n){for(let o=0;o<q;o++)try{let s=fs.createReadStream(t),i=stream.Readable.toWeb(s),a=await fetch(e,{method:"PUT",headers:{"Content-Type":r,"Content-Length":String(n)},body:i,duplex:"half"});if(a.ok)return !0;if(a.status>=500&&o<q-1){await de(ce[o]);continue}return !1}catch{if(o<q-1){await de(ce[o]);continue}return false}return false}async function Us(e,t,r){try{return (await fetch(`${e}/artifacts/confirm`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({artifactId:r})})).ok}catch{return false}}async function vr(e,t,r,n){let o=Ds(r.filePath);if(o===0)return {success:false,storageKey:null,artifactId:null,error:"file_not_found_or_empty"};if(o>n*1024*1024)return {success:false,storageKey:null,artifactId:null,error:"file_too_large"};let s=Ls(r.filePath);await Ps();try{let i=await Ns(e,t,r,o,s);if(!i)return {success:!1,storageKey:null,artifactId:null,error:"upload_url_request_failed"};if(!await Os(i.uploadUrl,r.filePath,s,o))return {success:!1,storageKey:i.storageKey,artifactId:i.artifactId,error:"presigned_put_failed"};let l=await Us(e,t,i.artifactId);return {success:l,storageKey:i.storageKey,artifactId:i.artifactId,error:l?null:"confirm_failed"}}finally{_s();}}async function at(e,t,r,n){let o=new Map,s=r.map(async i=>{let a=await vr(e,t,i,n);o.set(i.filePath,a);});return await Promise.allSettled(s),o}function Hs(e){return e.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:e.GITHUB_RUN_ID??null,commitSha:e.GITHUB_SHA??null,branch:e.GITHUB_REF_NAME??null,runUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY&&e.GITHUB_RUN_ID?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`:null}}function $s(e){return e.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:e.CI_PIPELINE_ID??null,commitSha:e.CI_COMMIT_SHA??null,branch:e.CI_COMMIT_BRANCH??e.CI_COMMIT_REF_NAME??null,runUrl:e.CI_PIPELINE_URL??null}}function Bs(e){if(!e.JENKINS_URL)return null;let t=e.GIT_BRANCH??null;return t?.startsWith("origin/")&&(t=t.slice(7)),{provider:"jenkins",buildId:e.BUILD_ID??null,commitSha:e.GIT_COMMIT??null,branch:t,runUrl:e.BUILD_URL??null}}function js(e){return e.CIRCLECI!=="true"?null:{provider:"circleci",buildId:e.CIRCLE_BUILD_NUM??null,commitSha:e.CIRCLE_SHA1??null,branch:e.CIRCLE_BRANCH??null,runUrl:e.CIRCLE_BUILD_URL??null}}function zs(e){if(!e.BITBUCKET_PIPELINE_UUID)return null;let t=e.BITBUCKET_WORKSPACE&&e.BITBUCKET_REPO_SLUG&&e.BITBUCKET_PIPELINE_UUID?`https://bitbucket.org/${e.BITBUCKET_WORKSPACE}/${e.BITBUCKET_REPO_SLUG}/pipelines/results/${e.BITBUCKET_PIPELINE_UUID}`:null;return {provider:"bitbucket-pipelines",buildId:e.BITBUCKET_BUILD_NUMBER??null,commitSha:e.BITBUCKET_COMMIT??null,branch:e.BITBUCKET_BRANCH??null,runUrl:t}}var qs=[Hs,$s,Bs,js,zs];function ue(e){let t=e??process.env;for(let r of qs){let n=r(t);if(n)return n}return null}function Gs(e){let t=[];for(let r of e){let n=r,o=n.tests;if(!Array.isArray(o)||o.length===0){t.push(r);continue}for(let s of o){t.push({timestamp:s.startedAt,title:s.title,category:"test",navigationType:n.navigationType,url:n.url,visitedAt:n.visitedAt,duration:s.duration,status:s.status,test_status:s.status,test_id:s.testId,test_title:s.title,specfile:s.filePath,suiteName:s.suiteName,type:"test",...s.failure?{error:s.failure.message,errorMessage:s.failure.message}:{}});for(let i of s.actions??[])t.push({timestamp:i.timestamp,title:i.title,category:i.category,status:i.status,test_status:s.status,duration:i.duration,error:i.error,test_id:s.testId,test_title:s.title,specfile:s.filePath,url:n.url,type:i.category==="assertion"?"assert":"action"});}}return t}function kr(e){let r=e.getGitMetadata()?.remoteUrl;return r?j(r):e.getConfig()?.projectName??z(process.cwd())}async function lt(e,t,r,n,o,s,i,a,l,c,d){try{let u=d?.length??0,p=(a?.length??0)+(l?.length??0)+u>0;if(e.isCloudMode()&&p&&await e.ensureValidToken()){let h=e.getEndpoint(),g=e.getAccessToken(),b=t?.artifactMaxSizeMb??50,x=[];for(let R of a??[])x.push({filePath:R,runId:r,testId:"maestro-suite",type:"screenshot"});let T=new Set;for(let R of d??[])x.push({filePath:R.path,runId:r,testId:R.testId,type:"video"}),T.add(R.path);for(let R of l??[])T.has(R)||x.push({filePath:R,runId:r,testId:"maestro-suite",type:"video"});if(x.length>0){let R=await at(h,g,x,b),D=Array.from(R.entries()),I=D.filter(([,m])=>m.success).length,f=D.filter(([,m])=>!m.success);if(I>0){let m=x.filter(k=>k.type==="video").length,w=d?.length??0,v=x.filter(k=>k.type==="screenshot").length,S=[];if(v>0&&S.push(`${v} screenshot(s)`),m>0){let k=w>0?` (${w} per-flow)`:"";S.push(`${m} video(s)${k}`);}process.stderr.write(`\u2713 TestRelic: Uploaded ${I} artifact(s) [${S.join(", ")}] to cloud storage.
1270
1270
  `);}if(f.length>0){process.stderr.write(`\u26A0 TestRelic: ${f.length} artifact(s) failed to upload:
1271
1271
  `);for(let[m,w]of f){let v=x.find(k=>k.filePath===m),S=v?`[${v.type}] ${m}`:m;process.stderr.write(` \u2717 ${S} \u2014 reason: ${w.error??"unknown"}
1272
- `);}}}}if(e.isCloudMode())if(await e.ensureValidToken()){let h=e.getGitMetadata(),g=ue(),b=kr(e),x=Gs(n.timeline),A={...n,timeline:x},R=le(A,b,h,g,c),D=await ot(e.getEndpoint(),e.getAccessToken(),R,async()=>await e.ensureValidToken()?e.getAccessToken():null);if(D.success)process.stderr.write(`\u2713 TestRelic: Cloud upload succeeded \u2192 ${e.getEndpoint()}/runs/${r}
1272
+ `);}}}}if(e.isCloudMode())if(await e.ensureValidToken()){let h=e.getGitMetadata(),g=ue(),b=kr(e),x=Gs(n.timeline),T={...n,timeline:x},R=le(T,b,h,g,c),D=await ot(e.getEndpoint(),e.getAccessToken(),R,async()=>await e.ensureValidToken()?e.getAccessToken():null);if(D.success)process.stderr.write(`\u2713 TestRelic: Cloud upload succeeded \u2192 ${e.getEndpoint()}/runs/${r}
1273
1273
  `);else {let I=D,f=t?.queueDirectory??".testrelic/queue";oe(f,r,"batch",I.reason,I.targetEndpoint,I.method,I.payload,{"Content-Type":"application/json"}),process.stderr.write(`\u26A0 TestRelic: Cloud upload failed, queued for retry.
1274
- `);}}else {let h=t?.queueDirectory??".testrelic/queue",g=e.getGitMetadata(),b=ue(),x=kr(e),A=le(n,x,g,b);oe(h,r,"batch",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs`,"POST",A,{"Content-Type":"application/json"});}await e.dispose();}catch{try{await e.dispose();}catch{}}}function Rr(e,t,r){if(t.length===0)return null;let n=path.basename(e,path.extname(e)).toLowerCase(),o=t.find(a=>path.basename(a,path.extname(a)).toLowerCase()===n);if(o)return o;let s=t.find(a=>path.basename(a).toLowerCase().includes(n));if(s)return s;let i=t.find(a=>{let l=path.basename(a,path.extname(a)).toLowerCase();return l.length>=3&&(n.startsWith(l)||n.includes(l))});if(i)return i;if(r){let a=path.basename(r,path.extname(r)).toLowerCase(),l=t.find(d=>path.basename(d,path.extname(d)).toLowerCase()===a);if(l)return l;let c=t.find(d=>path.basename(d).toLowerCase().includes(a));if(c)return c}return null}function Ys(e,t){if(t.length===0)return [];let r=path.basename(e,path.extname(e)).toLowerCase(),n=t.filter(o=>{let s=path.basename(o).toLowerCase(),i=path.basename(o,path.extname(o)).toLowerCase();return s.startsWith(r)||s.includes(r)?true:i.length>=3&&(r.startsWith(i)||r.includes(i))});return n.length>0?n:t.slice()}function Xs(e){for(let t of e)if(t.command==="startRecording"){let r=t.metadata,n=r?.path??r?.recording??r?.fileName;if(typeof n=="string")return n;if(typeof t.selector=="string")return t.selector}return null}function Sr(e){return path.basename(e).replace(/^commands[-_]?/i,"").replace(/\.json$/i,"").replace(/^\(/,"").replace(/\)$/,"").toLowerCase()}function Qs(e){let t=new Map;for(let[r,n]of e){let o=Sr(r),s=Xs(n);s&&o&&t.set(o,s);}return t}function Zs(e,t){let r=path.basename(t,path.extname(t)).toLowerCase();if(!r||e.size===0)return {commands:[],matchedAnyFile:false};let n=o=>Sr(o);for(let[o,s]of e)if(n(o)===r)return {commands:s,matchedAnyFile:true};for(let[o,s]of e){let i=n(o);if(i.length>=3&&i.includes(r))return {commands:s,matchedAnyFile:true}}for(let[o,s]of e){let i=n(o);if(i.length>=3&&r.includes(i))return {commands:s,matchedAnyFile:true}}return {commands:[],matchedAnyFile:false}}function ei(e){switch(e){case "android":return "Android";case "ios":return "iOS";case "web":return "Web";default:return}}function ti(e,t,r){let n=e.logEntries.length>0?e.logEntries.map(o=>({level:o.level.toLowerCase(),message:o.message,timestamp:o.timestamp,source:o.source})):void 0;return {testId:`${e.flowFile}::${e.flowName}`,title:e.flowName,status:e.status,duration:e.duration,suiteName:e.appId??"maestro-suite",filePath:e.flowFile,testType:"mobile",isFlaky:false,startedAt:e.startedAt,completedAt:e.completedAt,tags:e.tags,failure:e.failureMessage?{message:e.failureMessage}:null,retry:0,retryCount:0,retryStatus:null,source:"maestro",platform:e.platform!=="unknown"?e.platform:void 0,os:ei(e.platform),deviceName:e.deviceId,...n?{consoleLogs:n}:{},...t&&t.length>0?{apiCalls:t}:{},...r&&r.length>0?{actions:r}:{}}}function ri(e,t,r){if(e.length===0)return [];let n=Date.parse(t),o=Date.parse(r);return Number.isNaN(n)||Number.isNaN(o)?e.slice():e.filter(s=>{let i=Date.parse(s.timestamp);return Number.isNaN(i)?true:i>=n&&i<=o})}async function ni(e){let{config:t}=e,r=new Date().toISOString(),n=t.testRunId??crypto.randomUUID(),o=Ue(e.testOutputDir,e.debugOutputDir),s=e.junitPath??o.junitReportPath,i=e.debugOutputDir?Me(e.debugOutputDir):o.logPaths,a=[];for(let f of i){let m;try{let{statSync:v}=await import('fs');m=v(f).mtime;}catch{}let w=Te(f,m);w.length>0&&a.push(...w);}let l=e.platform??"unknown";if(l==="unknown"&&a.length>0){let f=Ie(a);f!=="unknown"&&(l=f);}let c=new Map;if(e.flowsDir&&fs.existsSync(e.flowsDir)){let f=Ae(e.flowsDir);for(let m of f){let w=Se(m),v=w.name??m;c.set(v,w);}}let d=new Map,u=e.testOutputDir?Re(e.testOutputDir):o.commandJsonPaths;for(let f of u)d.set(f,Ce(f));let p=[],y=e.testOutputDir?Oe(e.testOutputDir):o.aiReportPaths;for(let f of y){let m=Ne(f);p.push(...m.defects);}let h=Qs(d),g=[];if(s&&fs.existsSync(s)){let f=we(s),m=Array.from(d.values()).flat(),w=m.filter(S=>S.category==="assertion"),v=m.filter(S=>S.category!=="assertion");for(let S of f.testSuites)for(let k of S.testCases){let C=k.name,M=c.get(C),N=k.status==="SUCCESS"?"passed":k.status==="SKIPPED"?"skipped":"failed",F=k.time*1e3,L=k.classname||C,W=path.basename(L,path.extname(L)).toLowerCase(),Tr=h.get(W)??null,{commands:ct,matchedAnyFile:dt}=Zs(d,L),ut=dt?ct.filter(B=>B.category!=="assertion"):v,pt=dt?ct.filter(B=>B.category==="assertion"):w,ft=[...ut,...pt].reduce((B,Ir)=>{let ge=Date.parse(Ir.timestamp);return Number.isFinite(ge)&&ge<B?ge:B},Number.POSITIVE_INFINITY),fe=Number.isFinite(ft)?new Date(ft).toISOString():r,gt=new Date(new Date(fe).getTime()+F).toISOString();g.push({flowName:C,flowFile:L,appId:M?.appId??null,platform:l,deviceId:e.device,status:N,duration:F,startedAt:fe,completedAt:gt,tags:M?.tags??[],properties:M?.properties??{},commands:ut,assertions:pt,screenshotPaths:Ys(L,o.screenshotPaths),videoPath:Rr(L,o.videoPaths,Tr),aiDefects:p,logEntries:ri(a,fe,gt),failureMessage:k.failureMessage??k.errorMessage??null,failureType:k.failureType??k.errorType??null,subflowRefs:M?.subflowRefs??[],metadata:M??null});}}if(g.length===0&&c.size>0)for(let[,f]of c)g.push({flowName:f.name??f.filePath,flowFile:f.filePath,appId:f.appId,platform:l,deviceId:e.device,status:"passed",duration:0,startedAt:r,completedAt:r,tags:f.tags,properties:f.properties,commands:[],assertions:[],screenshotPaths:[],videoPath:null,aiDefects:[],logEntries:a.slice(),failureMessage:null,failureType:null,subflowRefs:f.subflowRefs,metadata:f});let b=(()=>{if(!t.network?.enabled&&!t.network?.harPath)return;let f=g.map(v=>({testId:`${v.flowFile}::${v.flowName}`,startedAt:v.startedAt,completedAt:v.completedAt})),m=dr(e.networkJsonlDir??null,t.network,f);if(m.size===0)return;let w=new Map;for(let[v,S]of m)w.set(v,ur(S));return w})(),x=$e(g,b),A=G(x),R=new Date().toISOString(),D=Date.now()-new Date(r).getTime(),I={schemaVersion:"1.0.0",testRunId:n,startedAt:r,completedAt:R,totalDuration:D,summary:A,ci:null,metadata:t.metadata??null,timeline:x,shardRunIds:null};if(fs.mkdirSync(path.dirname(path.resolve(t.outputPath)),{recursive:true}),fs.writeFileSync(path.resolve(t.outputPath),JSON.stringify(I,null,2),"utf-8"),ze(I,p,o.screenshotPaths,path.resolve(t.htmlReportPath)),qe(A,t.outputPath,t.htmlReportPath,t.quiet,p),t.openReport&&Ge(path.resolve(t.htmlReportPath)),t.cloud){let f=new J(t.cloud);await f.initialize();let m=t.includeVideo?o.videoPaths:[],w=[];if(m.length>0){for(let C of g){let M=path.basename(C.flowFile,path.extname(C.flowFile)).toLowerCase(),N=h.get(M)??null,F=Rr(C.flowFile,m,N);if(F){let L=`${C.flowFile}::${C.flowName}`;w.some(W=>W.path===F&&W.testId===L)||w.push({path:F,testId:L});}}if(m.length===1){let C=m[0];for(let M of g){let N=`${M.flowFile}::${M.flowName}`;w.some(F=>F.testId===N)||w.push({path:C,testId:N});}}}let v=new Set(w.map(C=>C.path)),S=m.filter(C=>!v.has(C)),k=g.map((C,M)=>{let N=`${C.flowFile}::${C.flowName}`,F=x[M]?.tests?.[0];return ti(C,b?.get(N),F?.actions??null)});await lt(f,t.cloud,n,I,R,D,A,t.includeScreenshots?o.screenshotPaths:[],S,k,w);}return {report:I,flowResults:g,aiDefects:p,artifacts:o}}function di(e){return "tests"in e&&"visitedAt"in e}function Ar(e){let t=[],r=[],n="",o="",s="";for(let c of e)try{let d=fs.readFileSync(c,"utf-8"),u=JSON.parse(d);s||(s=u.testRunId),(!n||u.startedAt<n)&&(n=u.startedAt),(!o||u.completedAt&&u.completedAt>o)&&(o=u.completedAt);for(let p of u.timeline)t.push(p),di(p)&&r.push(p);}catch{process.stderr.write(`\u26A0 TestRelic: Unable to read report file: ${c}
1275
- `);}let i=G(r),a=n?new Date(n).getTime():Date.now(),l=o?new Date(o).getTime():Date.now();return {schemaVersion:"1.0.0",testRunId:s||`maestro-merged-${Date.now()}`,startedAt:n||new Date().toISOString(),completedAt:o||new Date().toISOString(),totalDuration:l-a,summary:i,ci:null,metadata:null,timeline:t,shardRunIds:null}}function ui(e,t){if(!fs.existsSync(e))throw new Error(`Directory does not exist: ${e}`);let r=fs.readdirSync(e).filter(o=>path.extname(o)===".json"&&o.includes("testrelic")).map(o=>path.join(e,o)),n=Ar(r);return fs.writeFileSync(t,JSON.stringify(n,null,2),"utf-8"),n}exports.CloudClient=J;exports.DEFAULT_CLOUD_CONFIG=me;exports.buildMaestroArgs=nr;exports.buildSummary=G;exports.buildTimeline=$e;exports.buildTimelineEntry=Ut;exports.buildUploadPayload=le;exports.categorizeCommand=Mt;exports.cleanupExpiredQueue=rt;exports.collectArtifacts=Ue;exports.collectGitMetadata=Qe;exports.deriveNonGitProjectId=z;exports.deriveRepoDisplayName=Ze;exports.detectCI=ue;exports.detectPlatformFromLogs=Ie;exports.discoverAiReports=Oe;exports.discoverCommandFiles=Re;exports.discoverConfigFile=ye;exports.discoverFlowFiles=Ae;exports.discoverLogFiles=Me;exports.enforceHttps=Ke;exports.exchangeToken=te;exports.finalizeAndUpload=lt;exports.finalizeRun=Ss;exports.flushQueue=tt;exports.generateHtmlReport=ze;exports.getArtifactStats=Qn;exports.healthCheck=ee;exports.initRealtimeRun=Rs;exports.isAuthError=re;exports.mergeCloudConfig=xe;exports.mergeReports=Ar;exports.mergeReportsFromDirectory=ui;exports.normalizeGitRemoteUrl=j;exports.openInBrowser=Ge;exports.orchestrateReport=ni;exports.parseAiReportFile=Ne;exports.parseAiReportHtml=Nt;exports.parseCommandsFile=Ce;exports.parseCommandsJson=Et;exports.parseConfigFile=be;exports.parseDuration=he;exports.parseFlowFile=Se;exports.parseFlowYaml=_t;exports.parseJUnitFile=we;exports.parseJUnitXml=Ct;exports.parseLogContent=Dt;exports.parseLogFile=Te;exports.printConsoleSummary=qe;exports.readPackageJsonName=gr;exports.refreshAccessToken=Ye;exports.renderHtmlDocument=je;exports.resolveConfig=Jr;exports.resolveEnvVar=K;exports.resolveEnvVars=Y;exports.resolveRepo=Xe;exports.runMaestro=No;exports.uploadArtifact=vr;exports.uploadArtifacts=at;exports.uploadBatchRun=ot;exports.writeToQueue=oe;//# sourceMappingURL=index.cjs.map
1274
+ `);}}else {let h=t?.queueDirectory??".testrelic/queue",g=e.getGitMetadata(),b=ue(),x=kr(e),T=le(n,x,g,b);oe(h,r,"batch",e.getFailureReason()??"token_invalid",`${e.getEndpoint()}/runs`,"POST",T,{"Content-Type":"application/json"});}await e.dispose();}catch{try{await e.dispose();}catch{}}}function Rr(e,t,r){if(t.length===0)return null;let n=path.basename(e,path.extname(e)).toLowerCase(),o=t.find(a=>path.basename(a,path.extname(a)).toLowerCase()===n);if(o)return o;let s=t.find(a=>path.basename(a).toLowerCase().includes(n));if(s)return s;let i=t.find(a=>{let l=path.basename(a,path.extname(a)).toLowerCase();return l.length>=3&&(n.startsWith(l)||n.includes(l))});if(i)return i;if(r){let a=path.basename(r,path.extname(r)).toLowerCase(),l=t.find(d=>path.basename(d,path.extname(d)).toLowerCase()===a);if(l)return l;let c=t.find(d=>path.basename(d).toLowerCase().includes(a));if(c)return c}return null}function Ys(e,t){if(t.length===0)return [];let r=path.basename(e,path.extname(e)).toLowerCase(),n=t.filter(o=>{let s=path.basename(o).toLowerCase(),i=path.basename(o,path.extname(o)).toLowerCase();return s.startsWith(r)||s.includes(r)?true:i.length>=3&&(r.startsWith(i)||r.includes(i))});return n.length>0?n:t.slice()}function Xs(e){for(let t of e)if(t.command==="startRecording"){let r=t.metadata,n=r?.path??r?.recording??r?.fileName;if(typeof n=="string")return n;if(typeof t.selector=="string")return t.selector}return null}function Sr(e){return path.basename(e).replace(/^commands[-_]?/i,"").replace(/\.json$/i,"").replace(/^\(/,"").replace(/\)$/,"").toLowerCase()}function Qs(e){let t=new Map;for(let[r,n]of e){let o=Sr(r),s=Xs(n);s&&o&&t.set(o,s);}return t}function Zs(e,t){let r=path.basename(t,path.extname(t)).toLowerCase();if(!r||e.size===0)return {commands:[],matchedAnyFile:false};let n=o=>Sr(o);for(let[o,s]of e)if(n(o)===r)return {commands:s,matchedAnyFile:true};for(let[o,s]of e){let i=n(o);if(i.length>=3&&i.includes(r))return {commands:s,matchedAnyFile:true}}for(let[o,s]of e){let i=n(o);if(i.length>=3&&r.includes(i))return {commands:s,matchedAnyFile:true}}return {commands:[],matchedAnyFile:false}}function ei(e){switch(e){case "android":return "Android";case "ios":return "iOS";case "web":return "Web";default:return}}function ti(e,t,r){let n=e.logEntries.length>0?e.logEntries.map(o=>({level:o.level.toLowerCase(),message:o.message,timestamp:o.timestamp,source:o.source})):void 0;return {testId:`${e.flowFile}::${e.flowName}`,title:e.flowName,status:e.status,duration:e.duration,suiteName:e.appId??"maestro-suite",filePath:e.flowFile,testType:"mobile",isFlaky:false,startedAt:e.startedAt,completedAt:e.completedAt,tags:e.tags,failure:e.failureMessage?{message:e.failureMessage}:null,retry:0,retryCount:0,retryStatus:null,source:"maestro",platform:e.platform!=="unknown"?e.platform:void 0,os:ei(e.platform),deviceName:e.deviceId,...n?{consoleLogs:n}:{},...t&&t.length>0?{apiCalls:t}:{},...r&&r.length>0?{actions:r}:{}}}function ri(e,t,r){if(e.length===0)return [];let n=Date.parse(t),o=Date.parse(r);return Number.isNaN(n)||Number.isNaN(o)?e.slice():e.filter(s=>{let i=Date.parse(s.timestamp);return Number.isNaN(i)?true:i>=n&&i<=o})}async function ni(e){let{config:t}=e,r=new Date().toISOString(),n=t.testRunId??crypto.randomUUID(),o=Ue(e.testOutputDir,e.debugOutputDir),s=e.junitPath??o.junitReportPath,i=e.debugOutputDir?Me(e.debugOutputDir):o.logPaths,a=[];for(let f of i){let m;try{let{statSync:v}=await import('fs');m=v(f).mtime;}catch{}let w=Ae(f,m);w.length>0&&a.push(...w);}let l=e.platform??"unknown";if(l==="unknown"&&a.length>0){let f=Ie(a);f!=="unknown"&&(l=f);}let c=new Map;if(e.flowsDir&&fs.existsSync(e.flowsDir)){let f=Te(e.flowsDir);for(let m of f){let w=Se(m),v=w.name??m;c.set(v,w);}}let d=new Map,u=e.testOutputDir?Re(e.testOutputDir):o.commandJsonPaths;for(let f of u)d.set(f,Ce(f));let p=[],y=e.testOutputDir?Oe(e.testOutputDir):o.aiReportPaths;for(let f of y){let m=Ne(f);p.push(...m.defects);}let h=Qs(d),g=[];if(s&&fs.existsSync(s)){let f=we(s),m=Array.from(d.values()).flat(),w=m.filter(S=>S.category==="assertion"),v=m.filter(S=>S.category!=="assertion");for(let S of f.testSuites)for(let k of S.testCases){let C=k.name,M=c.get(C),N=k.status==="SUCCESS"?"passed":k.status==="SKIPPED"?"skipped":"failed",F=k.time*1e3,L=k.classname||C,W=path.basename(L,path.extname(L)).toLowerCase(),Ar=h.get(W)??null,{commands:ct,matchedAnyFile:dt}=Zs(d,L),ut=dt?ct.filter(B=>B.category!=="assertion"):v,pt=dt?ct.filter(B=>B.category==="assertion"):w,ft=[...ut,...pt].reduce((B,Ir)=>{let ge=Date.parse(Ir.timestamp);return Number.isFinite(ge)&&ge<B?ge:B},Number.POSITIVE_INFINITY),fe=Number.isFinite(ft)?new Date(ft).toISOString():r,gt=new Date(new Date(fe).getTime()+F).toISOString();g.push({flowName:C,flowFile:L,appId:M?.appId??null,platform:l,deviceId:e.device,status:N,duration:F,startedAt:fe,completedAt:gt,tags:M?.tags??[],properties:M?.properties??{},commands:ut,assertions:pt,screenshotPaths:Ys(L,o.screenshotPaths),videoPath:Rr(L,o.videoPaths,Ar),aiDefects:p,logEntries:ri(a,fe,gt),failureMessage:k.failureMessage??k.errorMessage??null,failureType:k.failureType??k.errorType??null,subflowRefs:M?.subflowRefs??[],metadata:M??null});}}if(g.length===0&&c.size>0)for(let[,f]of c)g.push({flowName:f.name??f.filePath,flowFile:f.filePath,appId:f.appId,platform:l,deviceId:e.device,status:"passed",duration:0,startedAt:r,completedAt:r,tags:f.tags,properties:f.properties,commands:[],assertions:[],screenshotPaths:[],videoPath:null,aiDefects:[],logEntries:a.slice(),failureMessage:null,failureType:null,subflowRefs:f.subflowRefs,metadata:f});let b=(()=>{if(!t.network?.enabled&&!t.network?.harPath)return;let f=g.map(v=>({testId:`${v.flowFile}::${v.flowName}`,startedAt:v.startedAt,completedAt:v.completedAt})),m=dr(e.networkJsonlDir??null,t.network,f);if(m.size===0)return;let w=new Map;for(let[v,S]of m)w.set(v,ur(S));return w})(),x=$e(g,b),T=G(x),R=new Date().toISOString(),D=Date.now()-new Date(r).getTime(),I={schemaVersion:"1.0.0",testRunId:n,startedAt:r,completedAt:R,totalDuration:D,summary:T,ci:null,metadata:t.metadata??null,timeline:x,shardRunIds:null};if(fs.mkdirSync(path.dirname(path.resolve(t.outputPath)),{recursive:true}),fs.writeFileSync(path.resolve(t.outputPath),JSON.stringify(I,null,2),"utf-8"),ze(I,p,o.screenshotPaths,path.resolve(t.htmlReportPath)),qe(T,t.outputPath,t.htmlReportPath,t.quiet,p),t.openReport&&Ge(path.resolve(t.htmlReportPath)),t.cloud){let f=new J(t.cloud);await f.initialize();let m=t.includeVideo?o.videoPaths:[],w=[];if(m.length>0){for(let C of g){let M=path.basename(C.flowFile,path.extname(C.flowFile)).toLowerCase(),N=h.get(M)??null,F=Rr(C.flowFile,m,N);if(F){let L=`${C.flowFile}::${C.flowName}`;w.some(W=>W.path===F&&W.testId===L)||w.push({path:F,testId:L});}}if(m.length===1){let C=m[0];for(let M of g){let N=`${M.flowFile}::${M.flowName}`;w.some(F=>F.testId===N)||w.push({path:C,testId:N});}}}let v=new Set(w.map(C=>C.path)),S=m.filter(C=>!v.has(C)),k=g.map((C,M)=>{let N=`${C.flowFile}::${C.flowName}`,F=x[M]?.tests?.[0];return ti(C,b?.get(N),F?.actions??null)});await lt(f,t.cloud,n,I,R,D,T,t.includeScreenshots?o.screenshotPaths:[],S,k,w);}return {report:I,flowResults:g,aiDefects:p,artifacts:o}}function di(e){return "tests"in e&&"visitedAt"in e}function Tr(e){let t=[],r=[],n="",o="",s="";for(let c of e)try{let d=fs.readFileSync(c,"utf-8"),u=JSON.parse(d);s||(s=u.testRunId),(!n||u.startedAt<n)&&(n=u.startedAt),(!o||u.completedAt&&u.completedAt>o)&&(o=u.completedAt);for(let p of u.timeline)t.push(p),di(p)&&r.push(p);}catch{process.stderr.write(`\u26A0 TestRelic: Unable to read report file: ${c}
1275
+ `);}let i=G(r),a=n?new Date(n).getTime():Date.now(),l=o?new Date(o).getTime():Date.now();return {schemaVersion:"1.0.0",testRunId:s||`maestro-merged-${Date.now()}`,startedAt:n||new Date().toISOString(),completedAt:o||new Date().toISOString(),totalDuration:l-a,summary:i,ci:null,metadata:null,timeline:t,shardRunIds:null}}function ui(e,t){if(!fs.existsSync(e))throw new Error(`Directory does not exist: ${e}`);let r=fs.readdirSync(e).filter(o=>path.extname(o)===".json"&&o.includes("testrelic")).map(o=>path.join(e,o)),n=Tr(r);return fs.writeFileSync(t,JSON.stringify(n,null,2),"utf-8"),n}exports.CloudClient=J;exports.DEFAULT_CLOUD_CONFIG=me;exports.buildMaestroArgs=nr;exports.buildSummary=G;exports.buildTimeline=$e;exports.buildTimelineEntry=Ut;exports.buildUploadPayload=le;exports.categorizeCommand=Mt;exports.cleanupExpiredQueue=rt;exports.collectArtifacts=Ue;exports.collectGitMetadata=Qe;exports.deriveNonGitProjectId=z;exports.deriveRepoDisplayName=Ze;exports.detectCI=ue;exports.detectPlatformFromLogs=Ie;exports.discoverAiReports=Oe;exports.discoverCommandFiles=Re;exports.discoverConfigFile=ye;exports.discoverFlowFiles=Te;exports.discoverLogFiles=Me;exports.enforceHttps=Ke;exports.exchangeToken=te;exports.finalizeAndUpload=lt;exports.finalizeRun=Ss;exports.flushQueue=tt;exports.generateHtmlReport=ze;exports.getArtifactStats=Qn;exports.healthCheck=ee;exports.initRealtimeRun=Rs;exports.isAuthError=re;exports.mergeCloudConfig=xe;exports.mergeReports=Tr;exports.mergeReportsFromDirectory=ui;exports.normalizeGitRemoteUrl=j;exports.openInBrowser=Ge;exports.orchestrateReport=ni;exports.parseAiReportFile=Ne;exports.parseAiReportHtml=Nt;exports.parseCommandsFile=Ce;exports.parseCommandsJson=Et;exports.parseConfigFile=be;exports.parseDuration=he;exports.parseFlowFile=Se;exports.parseFlowYaml=_t;exports.parseJUnitFile=we;exports.parseJUnitXml=Ct;exports.parseLogContent=Dt;exports.parseLogFile=Ae;exports.printConsoleSummary=qe;exports.readPackageJsonName=gr;exports.refreshAccessToken=Ye;exports.renderHtmlDocument=je;exports.resolveConfig=Jr;exports.resolveEnvVar=K;exports.resolveEnvVars=Y;exports.resolveRepo=Xe;exports.runMaestro=No;exports.uploadArtifact=vr;exports.uploadArtifacts=at;exports.uploadBatchRun=ot;exports.writeToQueue=oe;//# sourceMappingURL=index.cjs.map
1276
1276
  //# sourceMappingURL=index.cjs.map