momentic 2.3.3 → 2.3.4
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/bin/cli.js
CHANGED
|
@@ -46,7 +46,7 @@ globstar while`,e,u,t,m,h),this.matchOne(e.slice(u),t.slice(m),r))return this.de
|
|
|
46
46
|
First test path: ${u}
|
|
47
47
|
|
|
48
48
|
Second test path: ${o}`)}t.tests[p.id]={type:Ae.TEST,name:p.name,id:p.id,description:p.description??void 0,labels:p.labels,...d};return}catch(p){r.warn(`Skipping file '${o}' because it is missing Momentic test metadata: ${p}`);return}case Ae.MODULE:try{let p=At.parse(a);t.modules[p.moduleId]={type:Ae.MODULE,name:p.name,id:p.moduleId,description:p.description??void 0,...d};let u=d.fileName.replace(".module.yaml","");!BS&&Ne(p.name)!==u&&r.warn(`The module with ID ${p.moduleId} has a name (${p.name}) that does not match its file name (${u}). We recommend renaming the module or the file to be consistent to avoid confusion and issues with module resolution.`);return}catch(p){r.warn(`Skipping file '${o}' because it is missing Momentic module metadata: ${p}`);return}default:r.warn(`Unsupported file type ${l}, skipping...`);return}}var Qo="momentic.config.yaml",zS="momentic.workspace.yaml",sP=ue.object({projects:ue.string().array().describe("list of glob patterns to find project (momentic.config.yaml) files")}),lP=ue.union([ue.string(),ue.object({fromFile:ue.string(),json:ue.boolean().optional()})]),cP=ue.object({name:jd,baseUrl:ue.string(),envFile:ue.string().optional().describe("path to a file on disk to read environment variables from. can be relative to project root or absolute."),envVariables:ue.record(ue.string(),lP).optional(),inheritFromShell:ue.boolean().optional().describe("inherit all environment variables from the shell - might be noisy"),browser:Mr.optional()}),dP=ue.object({postSave:ue.string().optional()}),pP=ue.object({name:jd,include:ue.string().array().optional().describe("list of glob patterns that match momentic files (optional)"),exclude:ue.string().array().optional().describe("opposite of include, takes precedence over include"),goldenFileDir:ue.string().optional(),reporterDir:ue.string().optional(),outputDir:ue.string().optional(),retries:ue.number().optional().describe("number of retries per test"),parallel:ue.number().optional().describe("degree of parallelism"),environments:ue.array(cP).optional(),gitMainBranch:ue.string().optional(),gitProtectedBranches:ue.string().array().optional(),ai:ad.extend({aiPageFiltering:ue.boolean().optional().describe("rag v2 flag")}).optional(),browser:Mr.extend({autoExpandIframes:ue.boolean().optional(),disableSecondaryCacheResolution:ue.boolean().optional(),showZeroOpacityElements:ue.boolean().optional(),globalLocatorRedirect:ue.boolean().optional(),visualActions:ue.boolean().optional()}).optional(),advanced:Yh.optional(),hooks:dP.optional()});function $S(n,e){let t;try{t=oP(n,"utf-8")}catch(o){y.warn(`Could not read possible Momentic ${e} file at ${n}: ${o}`);return}let r;try{if(r=jS.parse(t),typeof r!="object"||r===null)throw new Error(`The ${e} file should parse as a map with key-value pairs, but is type ${typeof r} instead`)}catch(o){y.warn(`Possible Momentic ${e} file at ${n} does not parse as valid YAML: ${o}`);return}return r}function Wd(n){let e=$S(n,"project configuration");if(e!==void 0)try{return pP.parse(e)}catch(t){y.warn(`Possible Momentic project configuration file at ${n} does not adhere to the required schema: ${t}`);return}}function uP(n){let e=$S(n,"workspace configuration");if(e!==void 0)try{return sP.parse(e)}catch(t){y.warn(`Possible Momentic workspace configuration file at ${n} does not adhere to the required schema: ${t}`);return}}function mP(){let n=[],e=Gd(),t=eo.parse(e).root,r=15,o=0;for(;o<r;){o++;let i=eo.basename(e);if(Is.includes(i))return y.warn(`Stopping search for Momentic projects since the current directory name (${i}) is likely a system artifact folder.`),n;for(let a of iP(e))if(a.endsWith(Qo)){let s=eo.join(e,a),l=Wd(s);l&&n.push({configFilePath:s,config:l,rootDir:HS(s)})}if(n.length)return n;if(e=eo.dirname(e),e===t)break}return n}function nn(n={}){let{configFilePath:e,nameFilter:t}=n,r=Vd(e);if(t&&(r=r.filter(o=>o.config.name===t)),r.length>1)throw new Error(`Multiple valid projects were found in the same directory. Please use the '-c / --config' flag to disambiguate:
|
|
49
|
-
${r.map(o=>o.configFilePath)}`);if(r.length===0)throw new Error("No valid Momentic project file available.");return y.debug(`Found valid project configuration at ${r[0].configFilePath}`),r[0]}function hP(n){let e=uP(n);if(!e||!e.projects||!e.projects.length)return;let t=e.projects.map(i=>(i.endsWith("/")||(i+="/"),`${i}*${Qo}`)),r=Zo(t,{absolute:!1,cwd:Gd(),dotRelative:!1,maxDepth:$d,nodir:!0}),o=[];for(let i of r){let a=eo.join(Gd(),i),s=Wd(a);s&&o.push({configFilePath:a,config:s,rootDir:HS(a)})}return o}function Vd(n){if(n){n=eo.resolve(n);let t=Wd(n);return t||(console.error(`No valid Momentic project file found at ${n}.`),process.exit(1)),[{config:t,configFilePath:n,rootDir:eo.dirname(n)}]}if(rP(zS)){let t=hP(zS);if(t)return t}return mP()}function ei(n,e){let t=jS.stringify(n);aP(e,t)}import ti from"fs";import qd from"path";import{z as Kd}from"zod";var GS="golden/visual-diff",WS="reports",VS="test-results";var gP=Kd.object({width:Kd.number(),height:Kd.number()}),ni=class{defaultGoldenScreenshotDir;regenerateGoldenFiles;constructor(e,t){let r=qd.join(e.rootDir,e.config.goldenFileDir??GS);this.defaultGoldenScreenshotDir=r,this.regenerateGoldenFiles=t}async prepareGoldenScreenshotForComparison(e,t,r){if(t.screenshot?.data?.startsWith("https://")){let a=await fetch(t.screenshot.data);return{buffer:Buffer.from(await a.arrayBuffer()),width:t.screenshot.width,height:t.screenshot.height}}let o=t.screenshot?.data;o||(o=qd.join(this.defaultGoldenScreenshotDir,`${t.id}.jpg`));let i=`${o}.metadata.json`;if(this.regenerateGoldenFiles)return ti.mkdirSync(qd.dirname(o),{recursive:!0}),ti.writeFileSync(o,r.buffer),ti.writeFileSync(i,JSON.stringify({width:r.width,height:r.height})),{buffer:Buffer.from(r.buffer),width:r.width,height:r.height};if(ti.existsSync(o)){let a=ti.readFileSync(o),s=gP.parse(JSON.parse(ti.readFileSync(i,"utf-8")));return{buffer:a,width:s.width,height:s.height}}else throw new R("UserConfigurationError",`Cannot execute visual diff without a saved baseline screenshot at ${o}`)}};var ri=class{flags;constructor(e){this.flags={auto_expand_iframes:e.browser?.autoExpandIframes??!1,rag_v2:e.ai?.aiPageFiltering??!1,faker_constant_seed:e.advanced?.fakerConstantSeed??!1,disable_secondary_cache_resolution:e.browser?.disableSecondaryCacheResolution??!1,show_zero_opacity_elements:e.browser?.showZeroOpacityElements??!1,global_locator_redirect:e.browser?.globalLocatorRedirect??!1,visual_actions:e.browser?.visualActions??!1,mini_model_initial_assertion:!1,mini_model_initial_locator:!1,show_test_plans:!1,icon_knowledge_base:!1,disable_clickhouse_caches:!1,disable_clickhouse_last_updated_endpoint:!1}}isBooleanFlagEnabled(e){return this.flags[e]}getAllFlags(){return{...this.flags}}getFlagPayload(e){}async refresh(){}};import fP from"simple-git";var ve=fP();function ll(n){if(n.startsWith("git@")){let e=n.split(":");if(e.length===2){let t=e[1].replace(".git","").split("/");if(t.length===2){let r=t[0],o=t[1];return`${r}/${o}`}}}else if(n.startsWith("http")||n.startsWith("https")){let t=new URL(n).pathname.split("/").filter(Boolean);if(t.length>=2){let r=t[0],o=t[1].replace(".git","");return`${r}/${o}`}}}async function xe(n,e){try{return(await e).trim()}catch(t){n.error({err:t},"Failed to run git command");return}}function SP(){if(process.env.GITHUB_ACTION)return"GithubActions";if(process.env.GITLAB_CI)return"GitlabCI";if(process.env.CIRCLECI)return"CircleCI";if(process.env.BUILDKITE)return"Buildkite";if(process.env["System.CollectionUri"]?.includes("azure"))return"AzureDevOps"}async function yP(n){let[e,t,r,o]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.GITHUB_SHA,gitCommitShaShort:process.env.GITHUB_SHA?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.GITHUB_HEAD_REF||process.env.GITHUB_REF_NAME,gitOriginUrl:t,gitCommitMessage:r,gitCommitAuthorName:o,githubRepository:process.env.GITHUB_REPOSITORY,pipelineId:`${process.env.GITHUB_RUN_ID}:${process.env.GITHUB_RUN_ATTEMPT}`}}async function bP(n){let[e,t,r]=await Promise.all([xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.CI_COMMIT_SHA,gitCommitShaShort:process.env.CI_COMMIT_SHORT_SHA,gitCommitTimestamp:process.env.CI_COMMIT_TIMESTAMP?new Date(process.env.CI_COMMIT_TIMESTAMP):void 0,gitBranchName:process.env.CI_COMMIT_BRANCH||process.env.CI_COMMIT_REF_NAME,gitOriginUrl:e,gitCommitMessage:t,gitCommitAuthorName:r,gitlabProjectPath:process.env.CI_SERVER_HOST,pipelineId:`${process.env.CI_PIPELINE_ID}:${process.env.CI_JOB_ID}`}}async function wP(n){let[e,t,r,o]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),i=t?.includes("github.com"),a=t?.includes("gitlab.com"),s=t?ll(t):void 0;return{gitCommitSha:process.env.CIRCLE_SHA1,gitCommitShaShort:process.env.CIRCLE_SHA1?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.CIRCLE_BRANCH,gitOriginUrl:process.env.CIRCLE_REPOSITORY_URL,gitCommitMessage:r,gitCommitAuthorName:o,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.CIRCLE_WORKFLOW_ID}:${process.env.CIRCLE_WORKFLOW_JOB_ID}`}}async function vP(n){let[e,t,r]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),o=process.env.BUILDKITE_REPO,i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env.BUILDKITE_COMMIT,gitCommitShaShort:process.env.BUILDKITE_COMMIT?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.BUILDKITE_BRANCH,gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:r,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.BUILDKITE_PIPELINE_ID}:${process.env.BUILDKITE_BUILD_ID}:${process.env.BUILDKITE_JOB_ID}`}}async function xP(n){let[e,t,r]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),o=process.env["Build.Repository.Uri"],i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env["Build.SourceVersion"],gitCommitShaShort:process.env["Build.SourceVersion"]?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env["Build.SourceBranchName"],gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:r,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env["System.JobId"]}:${process.env["System.JobAttempt"]}`}}async function TP(n,e){let[t,r,o,i,a,s,l,c]=await Promise.all([xe(n,ve.revparse(["HEAD"])),xe(n,ve.revparse(["--short","HEAD"])),xe(n,ve.revparse(["--abbrev-ref","HEAD"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"])),e?xe(n,ve.raw(["merge-base","--fork-point",e])):Promise.resolve(void 0)]),d=c?await xe(n,ve.show(["--no-patch","--format=%ci",c])):void 0,p=i?.includes("github.com"),u=i?.includes("gitlab.com"),m=i?ll(i):void 0;return{gitCommitSha:t,gitCommitShaShort:r,gitBranchName:o,gitOriginUrl:i,gitCommitTimestamp:a?new Date(a):void 0,gitCommitMessage:s,gitCommitAuthorName:l,lastCommitOnMainSha:c,lastCommitOnMainTimestamp:d?new Date(d):void 0,githubRepository:p?m:void 0,gitlabProjectPath:u?m:void 0,pipelineId:void 0}}async function EP(n){let e=n.config.gitProtectedBranches??[];return n.config.gitMainBranch&&e.push(n.config.gitMainBranch),{gitMainBranch:n.config.gitMainBranch,gitProtectedBranches:e}}async function CP(n,e){let t=SP();if(!t)return TP(n,e);switch(t){case"GithubActions":return yP(n);case"GitlabCI":return bP(n);case"CircleCI":return wP(n);case"Buildkite":return vP(n);case"AzureDevOps":return xP(n)}}async function RP(n,e,t){if(t.lastCommitOnMainSha&&t.lastCommitOnMainTimestamp)return{};if(t.gitlabProjectPath){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let r=await e.getMergeBaseCommitFromGitlab(t.gitlabProjectPath,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:r.sha,lastCommitOnMainTimestamp:r.committer.date}}catch(r){return n.warn({err:r},"Failed to get remote metadata from Gitlab"),{}}}if(t.githubRepository){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let[r,o]=t.githubRepository.split("/"),i=await e.getMergeBaseCommitFromGithub(r,o,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:i.sha,lastCommitOnMainTimestamp:i.committer.date}}catch(r){return n.warn({err:r},"Failed to get remote metadata from Github"),{}}}return{}}async function oi(n,e,t){let r=await EP(t),o=await CP(n,r.gitMainBranch),i={...r,...o},a=await RP(n,e,i);return{...r,...o,...a}}import DN from"http";import{z as Xd}from"zod";var H="v1",Aa="2.3.3";var hr=class extends Error{constructor(e){super(e),this.name="TimeoutError"}};var qS=n=>{let e=n.reason===void 0?new DOMException("This operation was aborted.","AbortError"):n.reason;return e instanceof Error?e:new DOMException(e,"AbortError")};async function D(n,e){let{milliseconds:t,fallback:r,message:o,customTimers:i={setTimeout,clearTimeout}}=e,a,s;return new Promise((l,c)=>{if(typeof t!="number"||Math.sign(t)!==1)throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${t}\``);if(e.signal){let{signal:p}=e;p.aborted&&c(qS(p)),s=()=>{c(qS(p))},p.addEventListener("abort",s)}if(t===Number.POSITIVE_INFINITY){n.then(l,c);return}let d=new hr;a=i.setTimeout.call(void 0,()=>{if(r){try{l(r())}catch(p){c(p)}return}"cancel"in n&&typeof n.cancel=="function"&&n.cancel(),o instanceof Error?c(o):(d.message=o??`Promise timed out after ${t} milliseconds`,c(d))},t),(async()=>{try{l(await n)}catch(p){c(p)}})()}).catch(l=>{throw l}).finally(()=>{a!==void 0&&i.clearTimeout.call(void 0,a),s!==void 0&&e.signal&&e.signal.removeEventListener("abort",s)})}var cl=class{limit;windowMs;userActions;constructor(e,t){this.limit=e,this.windowMs=t,this.userActions=new Map}_cleanup(e,t="DEFAULT_USER"){let r=Date.now(),o=`${t}:${e}`;if(this.userActions.has(o)){let a=this.userActions.get(o)?.filter(s=>r-s<=this.windowMs)??[];a.length>0?this.userActions.set(o,a):this.userActions.delete(o)}}increment(e,t="DEFAULT_USER"){let r=Date.now(),o=`${t}:${e}`;this._cleanup(t,e),this.userActions.has(o)||this.userActions.set(o,[]);let i=this.userActions.get(o);return i.length>=this.limit?!0:(i.push(r),!1)}};var Yd=["ability","able","aboard","about","above","accept","accident","according","account","accurate","acres","across","act","action","active","activity","actual","actually","add","addition","additional","adjective","adult","adventure","advice","affect","afraid","after","afternoon","again","against","age","ago","agree","ahead","aid","air","airplane","alike","alive","all","allow","almost","alone","along","aloud","alphabet","already","also","although","am","among","amount","ancient","angle","angry","animal","announced","another","answer","ants","any","anybody","anyone","anything","anyway","anywhere","apart","apartment","appearance","apple","applied","appropriate","are","area","arm","army","around","arrange","arrangement","arrive","arrow","art","article","as","aside","ask","asleep","at","ate","atmosphere","atom","atomic","attached","attack","attempt","attention","audience","author","automobile","available","average","avoid","aware","away","baby","back","bad","badly","bag","balance","ball","balloon","band","bank","bar","bare","bark","barn","base","baseball","basic","basis","basket","bat","battle","be","bean","bear","beat","beautiful","beauty","became","because","become","becoming","bee","been","before","began","beginning","begun","behavior","behind","being","believed","bell","belong","below","belt","bend","beneath","bent","beside","best","bet","better","between","beyond","bicycle","bigger","biggest","bill","birds","birth","birthday","bit","bite","black","blank","blanket","blew","blind","block","blood","blow","blue","board","boat","body","bone","book","border","born","both","bottle","bottom","bound","bow","bowl","box","boy","brain","branch","brass","brave","bread","break","breakfast","breath","breathe","breathing","breeze","brick","bridge","brief","bright","bring","broad","broke","broken","brother","brought","brown","brush","buffalo","build","building","built","buried","burn","burst","bus","bush","business","busy","but","butter","buy","by","cabin","cage","cake","call","calm","came","camera","camp","can","canal","cannot","cap","capital","captain","captured","car","carbon","card","care","careful","carefully","carried","carry","case","cast","castle","cat","catch","cattle","caught","cause","cave","cell","cent","center","central","century","certain","certainly","chain","chair","chamber","chance","change","changing","chapter","character","characteristic","charge","chart","check","cheese","chemical","chest","chicken","chief","child","children","choice","choose","chose","chosen","church","circle","circus","citizen","city","class","classroom","claws","clay","clean","clear","clearly","climate","climb","clock","close","closely","closer","cloth","clothes","clothing","cloud","club","coach","coal","coast","coat","coffee","cold","collect","college","colony","color","column","combination","combine","come","comfortable","coming","command","common","community","company","compare","compass","complete","completely","complex","composed","composition","compound","concerned","condition","congress","connected","consider","consist","consonant","constantly","construction","contain","continent","continued","contrast","control","conversation","cook","cookies","cool","copper","copy","corn","corner","correct","correctly","cost","cotton","could","count","country","couple","courage","course","court","cover","cow","cowboy","crack","cream","create","creature","crew","crop","cross","crowd","cry","cup","curious","current","curve","customs","cut","cutting","daily","damage","dance","danger","dangerous","dark","darkness","date","daughter","dawn","day","dead","deal","dear","death","decide","declared","deep","deeply","deer","definition","degree","depend","depth","describe","desert","design","desk","detail","determine","develop","development","diagram","diameter","did","die","differ","difference","different","difficult","difficulty","dig","dinner","direct","direction","directly","dirt","dirty","disappear","discover","discovery","discuss","discussion","disease","dish","distance","distant","divide","division","do","doctor","does","dog","doing","doll","dollar","done","donkey","door","dot","double","doubt","down","dozen","draw","drawn","dream","dress","drew","dried","drink","drive","driven","driver","driving","drop","dropped","drove","dry","duck","due","dug","dull","during","dust","duty","each","eager","ear","earlier","early","earn","earth","easier","easily","east","easy","eat","eaten","edge","education","effect","effort","egg","eight","either","electric","electricity","element","elephant","eleven","else","empty","end","enemy","energy","engine","engineer","enjoy","enough","enter","entire","entirely","environment","equal","equally","equator","equipment","escape","especially","essential","establish","even","evening","event","eventually","ever","every","everybody","everyone","everything","everywhere","evidence","exact","exactly","examine","example","excellent","except","exchange","excited","excitement","exciting","exclaimed","exercise","exist","expect","experience","experiment","explain","explanation","explore","express","expression","extra","eye","face","facing","fact","factor","factory","failed","fair","fairly","fall","fallen","familiar","family","famous","far","farm","farmer","farther","fast","fastened","faster","fat","father","favorite","fear","feathers","feature","fed","feed","feel","feet","fell","fellow","felt","fence","few","fewer","field","fierce","fifteen","fifth","fifty","fight","fighting","figure","fill","film","final","finally","find","fine","finest","finger","finish","fire","fireplace","firm","first","fish","five","fix","flag","flame","flat","flew","flies","flight","floating","floor","flow","flower","fly","fog","folks","follow","food","foot","football","for","force","foreign","forest","forget","forgot","forgotten","form","former","fort","forth","forty","forward","fought","found","four","fourth","fox","frame","free","freedom","frequently","fresh","friend","friendly","frighten","frog","from","front","frozen","fruit","fuel","full","fully","fun","function","funny","fur","furniture","further","future","gain","game","garage","garden","gas","gasoline","gate","gather","gave","general","generally","gentle","gently","get","getting","giant","gift","girl","give","given","giving","glad","glass","globe","go","goes","gold","golden","gone","good","goose","got","government","grabbed","grade","gradually","grain","grandfather","grandmother","graph","grass","gravity","gray","great","greater","greatest","greatly","green","grew","ground","group","grow","grown","growth","guard","guess","guide","gulf","gun","habit","had","hair","half","halfway","hall","hand","handle","handsome","hang","happen","happened","happily","happy","harbor","hard","harder","hardly","has","hat","have","having","hay","he","headed","heading","health","heard","hearing","heart","heat","heavy","height","held","hello","help","helpful","her","herd","here","herself","hidden","hide","high","higher","highest","highway","hill","him","himself","his","history","hit","hold","hole","hollow","home","honor","hope","horn","horse","hospital","hot","hour","house","how","however","huge","human","hundred","hung","hungry","hunt","hunter","hurried","hurry","hurt","husband","ice","idea","identity","if","ill","image","imagine","immediately","importance","important","impossible","improve","in","inch","include","including","income","increase","indeed","independent","indicate","individual","industrial","industry","influence","information","inside","instance","instant","instead","instrument","interest","interior","into","introduced","invented","involved","iron","is","island","it","its","itself","jack","jar","jet","job","join","joined","journey","joy","judge","jump","jungle","just","keep","kept","key","kids","kill","kind","kitchen","knew","knife","know","knowledge","known","label","labor","lack","lady","laid","lake","lamp","land","language","large","larger","largest","last","late","later","laugh","law","lay","layers","lead","leader","leaf","learn","least","leather","leave","leaving","led","left","leg","length","lesson","let","letter","level","library","lie","life","lift","light","like","likely","limited","line","lion","lips","liquid","list","listen","little","live","living","load","local","locate","location","log","lonely","long","longer","look","loose","lose","loss","lost","lot","loud","love","lovely","low","lower","luck","lucky","lunch","lungs","lying","machine","machinery","mad","made","magic","magnet","mail","main","mainly","major","make","making","man","managed","manner","manufacturing","many","map","mark","market","married","mass","massage","master","material","mathematics","matter","may","maybe","me","meal","mean","means","meant","measure","meat","medicine","meet","melted","member","memory","men","mental","merely","met","metal","method","mice","middle","might","mighty","mile","military","milk","mill","mind","mine","minerals","minute","mirror","missing","mission","mistake","mix","mixture","model","modern","molecular","moment","money","monkey","month","mood","moon","more","morning","most","mostly","mother","motion","motor","mountain","mouse","mouth","move","movement","movie","moving","mud","muscle","music","musical","must","my","myself","mysterious","nails","name","nation","national","native","natural","naturally","nature","near","nearby","nearer","nearest","nearly","necessary","neck","needed","needle","needs","negative","neighbor","neighborhood","nervous","nest","never","new","news","newspaper","next","nice","night","nine","no","nobody","nodded","noise","none","noon","nor","north","nose","not","note","noted","nothing","notice","noun","now","number","numeral","nuts","object","observe","obtain","occasionally","occur","ocean","of","off","offer","office","officer","official","oil","old","older","oldest","on","once","one","only","onto","open","operation","opinion","opportunity","opposite","or","orange","orbit","order","ordinary","organization","organized","origin","original","other","ought","our","ourselves","out","outer","outline","outside","over","own","owner","oxygen","pack","package","page","paid","pain","paint","pair","palace","pale","pan","paper","paragraph","parallel","parent","park","part","particles","particular","particularly","partly","parts","party","pass","passage","past","path","pattern","pay","peace","pen","pencil","people","per","percent","perfect","perfectly","perhaps","period","person","personal","pet","phrase","physical","piano","pick","picture","pictured","pie","piece","pig","pile","pilot","pine","pink","pipe","pitch","place","plain","plan","plane","planet","planned","planning","plant","plastic","plate","plates","play","pleasant","please","pleasure","plenty","plural","plus","pocket","poem","poet","poetry","point","pole","police","policeman","political","pond","pony","pool","poor","popular","population","porch","port","position","positive","possible","possibly","post","pot","potatoes","pound","pour","powder","power","powerful","practical","practice","prepare","present","president","press","pressure","pretty","prevent","previous","price","pride","primitive","principal","principle","printed","private","prize","probably","problem","process","produce","product","production","program","progress","promised","proper","properly","property","protection","proud","prove","provide","public","pull","pupil","pure","purple","purpose","push","put","putting","quarter","queen","question","quick","quickly","quiet","quietly","quite","rabbit","race","radio","railroad","rain","raise","ran","ranch","range","rapidly","rate","rather","raw","rays","reach","read","reader","ready","real","realize","rear","reason","recall","receive","recent","recently","recognize","record","red","refer","refused","region","regular","related","relationship","religious","remain","remarkable","remember","remove","repeat","replace","replied","report","represent","require","research","respect","rest","result","return","review","rhyme","rhythm","rice","rich","ride","riding","right","ring","rise","rising","river","road","roar","rock","rocket","rocky","rod","roll","roof","room","root","rope","rose","rough","round","route","row","rubbed","rubber","rule","ruler","run","running","rush","sad","saddle","safe","safety","said","sail","sale","salmon","salt","same","sand","sang","sat","satellites","satisfied","save","saved","saw","say","scale","scared","scene","school","science","scientific","scientist","score","screen","sea","search","season","seat","second","secret","section","see","seed","seeing","seems","seen","seldom","select","selection","sell","send","sense","sent","sentence","separate","series","serious","serve","service","sets","setting","settle","settlers","seven","several","shade","shadow","shake","shaking","shall","shallow","shape","share","sharp","she","sheep","sheet","shelf","shells","shelter","shine","shinning","ship","shirt","shoe","shoot","shop","shore","short","shorter","shot","should","shoulder","shout","show","shown","shut","sick","sides","sight","sign","signal","silence","silent","silk","silly","silver","similar","simple","simplest","simply","since","sing","single","sink","sister","sit","sitting","situation","six","size","skill","skin","sky","slabs","slave","sleep","slept","slide","slight","slightly","slip","slipped","slope","slow","slowly","small","smaller","smallest","smell","smile","smoke","smooth","snake","snow","so","soap","social","society","soft","softly","soil","solar","sold","soldier","solid","solution","solve","some","somebody","somehow","someone","something","sometime","somewhere","son","song","soon","sort","sound","source","south","southern","space","speak","special","species","specific","speech","speed","spell","spend","spent","spider","spin","spirit","spite","split","spoken","sport","spread","spring","square","stage","stairs","stand","standard","star","stared","start","state","statement","station","stay","steady","steam","steel","steep","stems","step","stepped","stick","stiff","still","stock","stomach","stone","stood","stop","stopped","store","storm","story","stove","straight","strange","stranger","straw","stream","street","strength","stretch","strike","string","strip","strong","stronger","struck","structure","struggle","stuck","student","studied","studying","subject","substance","success","successful","such","sudden","suddenly","sugar","suggest","suit","sum","summer","sun","sunlight","supper","supply","support","suppose","sure","surface","surprise","surrounded","swam","sweet","swept","swim","swimming","swing","swung","syllable","symbol","system","table","tail","take","taken","tales","talk","tall","tank","tape","task","taste","taught","tax","tea","teach","teacher","team","tears","teeth","telephone","television","tell","temperature","ten","tent","term","terrible","test","than","thank","that","thee","them","themselves","then","theory","there","therefore","these","they","thick","thin","thing","think","third","thirty","this","those","thou","though","thought","thousand","thread","three","threw","throat","through","throughout","throw","thrown","thumb","thus","thy","tide","tie","tight","tightly","till","time","tin","tiny","tip","tired","title","to","tobacco","today","together","told","tomorrow","tone","tongue","tonight","too","took","tool","top","topic","torn","total","touch","toward","tower","town","toy","trace","track","trade","traffic","trail","train","transportation","trap","travel","treated","tree","triangle","tribe","trick","tried","trip","troops","tropical","trouble","truck","trunk","truth","try","tube","tune","turn","twelve","twenty","twice","two","type","typical","uncle","under","underline","understanding","unhappy","union","unit","universe","unknown","unless","until","unusual","up","upon","upper","upward","us","use","useful","using","usual","usually","valley","valuable","value","vapor","variety","various","vast","vegetable","verb","vertical","very","vessels","victory","view","village","visit","visitor","voice","volume","vote","vowel","voyage","wagon","wait","walk","wall","want","war","warm","warn","was","wash","waste","watch","water","wave","way","we","weak","wealth","wear","weather","week","weigh","weight","welcome","well","went","were","west","western","wet","whale","what","whatever","wheat","wheel","when","whenever","where","wherever","whether","which","while","whispered","whistle","white","who","whole","whom","whose","why","wide","widely","wife","wild","will","willing","win","wind","window","wing","winter","wire","wise","wish","with","within","without","wolf","women","won","wonder","wonderful","wood","wooden","wool","word","wore","work","worker","world","worried","worry","worse","worth","would","wrapped","write","writer","writing","written","wrong","wrote","yard","year","yellow","yes","yesterday","yet","you","young","younger","your","yourself","youth","zero","zebra","zipper","zoo","zulu"];function KS(n){return new Array(n).fill(0).map(()=>Yd[Math.floor(Math.random()*Yd.length)]).join("-")}var AP=9e4,IP=15e3,yn=class extends Error{status;rawError;constructor(e,t,r,o={}){super(r,o),this.status=e,this.rawError=t}};async function PP(n){return n.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var Jd=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return Aa&&(e[Jh]=Aa),e}async sendRequest(e,t,r=3,o=AP){let i=r,a,s={path:e,baseUrl:this.baseUrl,method:t.method};for(;r>0;)try{return r--,await this.sendSingleRequestHelper(e,t,o)}catch(l){if(a=l,l instanceof yn&&l.status>=400&&l.status<500)throw l;if(l instanceof Error&&l.name==="AbortError"&&(a=new hr),r===0)throw a;let c=1500,d=i-r,p=Math.min(c*Math.pow(2,d-1),IP);await new Promise(u=>setTimeout(u,p))}throw this.logger.warn({...s,err:a},"Got fatal error response from Momentic server"),a}async sendSingleRequestHelper(e,t,r){let o={path:e,baseUrl:this.baseUrl,method:t.method},i=new AbortController,a=setTimeout(()=>i.abort(),r),s=()=>i.abort();t.signal&&t.signal.addEventListener("abort",s);let l={...this.getHeaders(),...t.extraHeaders};try{let c=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!c.ok){let p=await PP(c);throw new yn(c.status,p,`Request to ${e} failed with status ${c.status}: ${p}`)}let d;if(c.status===204)d={};else{let p=await c.text();try{d=JSON.parse(p)}catch{d=p}}return this.logger&&!t.noLog&&d&&this.logger.debug({result:d,status:c.status,...o},"Got response from Momentic server"),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Nt=class extends Jd{apiKey;constructor(e){super(e),this.apiKey=e.apiKey}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`}}};var lt=class extends Nt{constructor(e){super(e)}getAppUrl(){return this.baseUrl.replace(/\/\/api/,"//app")}async getAuthInfo(){let e=await this.sendRequest(`/${H}/auth/check`,{method:"GET",noLog:!0},10,5e3),{orgId:t,userId:r}=fg.parse(e);return{orgId:t,userId:r}}async bulkGetRunStatus(e){let t=await this.sendRequest(`/${H}/runs/status`,{method:"POST",body:e,noLog:!0},3,1e4);return ug.parse(t)}async getTestYAMLExport(e){let t=await this.sendRequest(`/${H}/tests/export`,{method:"POST",body:e},3,3e4);return sg.parse(t)}async updateStepCaches(e,t){await this.sendRequest(`/${H}/cache`,{method:"PATCH",body:e,extraHeaders:t},3,1e4)}async getStepCacheForTest(e,t){let r=await this.sendRequest(`/${H}/cache`,{method:"POST",body:e,extraHeaders:t},10,3e4);return lg.parse(r)}async queueTests(e){let t=await this.sendRequest(`/${H}/tests/queue`,{method:"POST",body:e},3,1e4);return ag.parse(t)}async uploadScreenshot(e){let t=await this.sendRequest(`/${H}/screenshots`,{method:"POST",body:e,noLog:!0},3,5e3);return gg.parse(t)}async getAllEnvironments(){let e=await this.sendRequest(`/${H}/environments`,{method:"GET"},3,5e3);return Sg.parse(e)}async acquireCacheLock(e,t){let r=await this.sendRequest(`/${H}/result-cache/lock`,{method:"POST",body:e,signal:t},3,3e4);return Eg.parse(r)}async releaseCacheLock(e){await this.sendRequest(`/${H}/result-cache/lock`,{method:"DELETE",body:{key:e}},3,5e3)}async deleteCacheResult(e){await this.sendRequest(`/${H}/result-cache/entry`,{method:"DELETE",body:e},3,5e3)}async setCacheResult(e){await this.sendRequest(`/${H}/result-cache/entry`,{method:"PATCH",body:e},3,5e3)}async getCacheResult(e){try{return await this.sendRequest(`/${H}/result-cache/entry`,{method:"POST",body:e},3,5e3)}catch(t){if(t instanceof Error&&t.message.includes("404"))return null;throw t}}async queueSuiteRuns(e){let t=await this.sendRequest(`/${H}/suites/queue`,{method:"POST",body:e},3,5e3);return yg.parse(t)}async bulkGetRunGroupStatus(e){let t={runGroupIds:e},r=await this.sendRequest(`/${H}/run-groups/status`,{method:"POST",body:t,noLog:!0},3,5e3);return Jm.array().parse(r)}async updateCacheLastUsedDate(e,t,r,o){try{await this.sendRequest(`/${H}/cache/last-used-at`,{method:"PATCH",body:{uniqueKeys:t,testId:e},noLog:!0,extraHeaders:o},3,7500)}catch(i){r.error({err:i},"Failed to update cache last used date")}}async uploadProposedSteps(e,t){try{await this.sendRequest(`/${H}/test-fragments/`,{method:"POST",body:e},3,1e4)}catch(r){t.error({err:r},"Failed to upload proposed steps")}}async uploadSnapshotScreenshot(e,t,r){try{await this.sendRequest(`/${H}/snapshots/${t}/screenshot`,{method:"POST",body:r,noLog:!0},3,1e4)}catch(o){e.error({err:o},"Failed to upload screenshot")}}async generateConsoleLogsForRunAttemptUploadUrl(e,t,r){let o=await this.sendRequest(`/${H}/runs/${t}/attempts/${r}/console-logs`,{method:"POST",noLog:!0},3,5e3);return na.parse(o)}async generateNetworkLogsForRunAttemptUploadUrl(e,t,r){let o=await this.sendRequest(`/${H}/runs/${t}/attempts/${r}/network-logs`,{method:"POST",noLog:!0},3,1e4);return na.parse(o)}async generateHtmlSnapshotUploadUrl(e,t){let r=await this.sendRequest(`/${H}/snapshots/${t}/html`,{method:"POST",noLog:!0},3,1e4);return na.parse(r)}async reportBillableEvents(e,t){try{await this.sendRequest(`/${H}/billing/events`,{method:"POST",body:t,noLog:!0},10,1e4)}catch(r){e.error({err:r},"Failed to report billable event")}}async fetchTestFragment(e){let t=await this.sendRequest(`/${H}/test-fragments/${e}`,{method:"GET",noLog:!0},3,1e4);return bg.parse(t)}async patchTestFragment(e,t){await this.sendRequest(`/${H}/test-fragments/${e}`,{method:"PATCH",body:t},3,1e4)}async getPastTestResults(e,t){let r=await this.sendRequest(`/${H}/results/tests/${e}`,{method:"POST",body:t},3,1e4);return wg.parse(r)}async generateTestResultsUploadUrl(){let e=await this.sendRequest(`/${H}/results/uploads`,{method:"POST",noLog:!0},3,1e4);return vg.parse(e)}async startProcessingResultsUpload(e,t){let r=await this.sendRequest(`/${H}/results/uploads/${e}/process`,{method:"POST",noLog:!0,body:t},3,1e4);return xg.parse(r)}async fetchIconKnowledgeBase(e,t){try{let r=await this.sendRequest(`/${H}/knowledge-base/icons`,{method:"GET",noLog:!0},3,5e3);return Lg.parse(r)}catch(r){return t.error({err:r},"Failed to fetch icon knowledge base"),null}}async saveNewIcons(e,t){try{await this.sendRequest(`/${H}/knowledge-base/icons`,{method:"POST",body:e,noLog:!0},3,5e3)}catch(r){t.error({err:r},"Failed to save new icons to icon knowledge base")}}async getMergeBaseCommitFromGithub(e,t,r,o){let i=new URLSearchParams;i.set("base",r),i.set("head",o);let a=await this.sendRequest(`/${H}/git/github/${e}/${t}/merge-base-commit?${i.toString()}`,{method:"GET",noLog:!0},3,1e4);return cd.parse(a)}async getMergeBaseCommitFromGitlab(e,t,r){let o=new URLSearchParams;o.set("base",t),o.set("head",r);let i=await this.sendRequest(`/${H}/git/gitlab/${e}/merge-base-commit?${o.toString()}`,{method:"GET",noLog:!0},3,5e3);return cd.parse(i)}async getAgentConfig(){let e=await this.sendRequest(`/${H}/web-agent/agent-config`,{method:"GET",noLog:!0},3,5e3);return Xd.record(Xd.string(),Xd.string()).parse(e)}};import{randomUUID as YS}from"crypto";var dl=class{apiClient;constructor(e){this.apiClient=e}async reportBillableEvent(e,t,r){try{return await this.apiClient.reportBillableEvents(e,[{event:t,timestamp:new Date().toISOString(),transactionId:r?.eventId??YS(),properties:Xc({},r)}])}catch(o){e.error({err:o},"Failed to report billable event")}}async reportCreditsUsed(e,t,r,o){if(r)try{return await this.apiClient.reportBillableEvents(e,[{event:"credits-used",timestamp:new Date().toISOString(),transactionId:o?.eventId??YS(),properties:Xc({creditsUsed:r,usedBy:t},o)}])}catch(i){e.error({err:i},"Failed to report credits used")}}};function ii(n,e,t){return fetch(n,{method:"PUT",body:t,headers:{"Content-Type":e}})}var pl=class{constructor(e){this.client=e}async storeConsoleLogsForRunAttempt(e,t,r,o){try{let i=JSON.stringify(o),{uploadUrl:a}=await this.client.generateConsoleLogsForRunAttemptUploadUrl(e,t,r),s=await ii(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(i){e.error({err:i},"Failed to upload console logs")}}async storeNetworkLogsForRunAttempt(e,t,r,o){let i=JSON.stringify(o);try{let{uploadUrl:a}=await this.client.generateNetworkLogsForRunAttemptUploadUrl(e,t,r),s=await ii(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(a){e.error({err:a},"Failed to upload network logs")}}async storeHtmlSnapshot(e,t,r){try{let{uploadUrl:o}=await this.client.generateHtmlSnapshotUploadUrl(e,t),i=await ii(o,"text/html",r);if(!i.ok)throw new Error(`Failed to upload network logs: ${i.statusText}`)}catch(o){e.error({err:o},"Failed to upload html snapshot")}}async storeScreenshot(e,t,r){try{await this.client.uploadSnapshotScreenshot(e,t,{screenshot:r.toString("base64")})}catch(o){e.error({err:o},"Failed to upload screenshot")}}async storeA11yTreeSnapshot(e,t,r){return Promise.resolve()}async getConsoleLogsForRunAttempt(e,t,r){}async getNetworkLogsForRunAttempt(e,t,r){}async getHtmlSnapshot(e,t){}async getA11yTreeSnapshot(e,t){}async getScreenshot(e,t){}};var ai=class{constructor(e,t){this.client=e;this.orgId=t}async acquireCacheLock(e,t){return this.client.acquireCacheLock(e,t)}async uploadScreenshot(e){return(await this.client.uploadScreenshot({screenshot:e.toString("base64")})).key}async releaseCacheLock(e){return this.client.releaseCacheLock(e)}async deleteCacheResult(e){return this.client.deleteCacheResult(e)}async setCacheResult(e){return this.client.setCacheResult(e)}async getCacheResult(e){return this.client.getCacheResult(e)}fetchIconKnowledgeBase(e,t){return this.client.fetchIconKnowledgeBase(e,t)}saveNewIcons(e,t,r){return this.client.saveNewIcons(t,r)}};import{Faker as LP,en as OP}from"@faker-js/faker";var si="v1",gr=class{httpClient;fakerInstance;type="API_CLIENT";sms={send:this.sendSms.bind(this),fetchLatest:this.fetchLatestSms.bind(this)};email={send:this.sendEmail.bind(this),fetchLatest:this.fetchLatestEmail.bind(this),fetchAll:this.fetchAllEmails.bind(this)};ai={generate:this.sendAiGenerate.bind(this)};constructor(e){this.httpClient=e.httpClient,e.fakerSeed&&(this.fakerInstance=new LP({locale:OP}),this.fakerInstance.seed(e.fakerSeed))}async sendAiGenerate(e){let t=typeof e=="string"?{input:e}:e;return this.httpClient.sendRequest(`/${si}/tools/ai/generate`,{method:"POST",body:t}).catch(r=>{throw r instanceof yn?new Error(r.rawError):new Error(`Failed to send AI generation: ${r.message}`)})}async sendSms(e){return this.httpClient.sendRequest(`/${si}/tools/sms/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send sms: ${t.message}`)})}async fetchLatestSms(e){return this.httpClient.sendRequest(`/${si}/tools/sms/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):t})}async sendEmail(e){return this.httpClient.sendRequest(`/${si}/tools/email/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send email: ${t.message}`)})}async fetchAllEmails(e){return this.httpClient.sendRequest(`/${si}/tools/email/fetchAll`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch all emails: ${t.message}`)})}async fetchLatestEmail(e){return this.httpClient.sendRequest(`/${si}/tools/email/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch latest emails: ${t.message}`)})}};import{z as MP}from"zod";var li=class extends Nt{agentConfig;constructor(e,t){super(t),this.agentConfig=e}async rankChunksWithAi(e,t){let r={...e,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/recommend-chunks-ai`,{method:"POST",body:r,signal:t.abortSignal});return ph.parse(o)}async rankChunksWithRag(e,t){let r=await this.sendRequest(`/${H}/web-agent/recommend-chunks`,{method:"POST",body:{cliVersion:Aa,...e},signal:t.abortSignal});return dh.parse(r)}async getScreenshotFromS3(e){let t=await this.sendRequest(`/${H}/s3/visual-diff-screenshot`,{method:"POST",body:{url:e}});return MP.string().parse(t)}async getElementLocation(e,t){let r={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${H}/web-agent/locate-element`,{method:"POST",body:r,signal:t.abortSignal});return og.parse(o)}async getAssertionResult(e,t){let r={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${H}/web-agent/assertion`,{method:"POST",body:r,signal:t.abortSignal});return sd.parse(o)}async getLintStepResult(e,t){let r={...e,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/lint/step`,{method:"POST",body:r,signal:t.abortSignal});return rg.parse(o)}async getVisualAssertionResult(e,t){let r={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/visual-assertion`,{method:"POST",body:r,signal:t.abortSignal});return sd.parse(o)}async getAiActionCommand(e,t){let r=await this.sendRequest(`/${H}/web-agent/next-command-dynamic`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return ng.parse(r)}async getMultiturnAiActionCommand(e,t){return await this.sendRequest(`/${H}/web-agent/ai-action/next-command`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal})}async getMultiturnAiActionEvaluation(e,t){let r=await this.sendRequest(`/${H}/web-agent/ai-action/evaluate`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Cc.parse(r)}async getReverseMappedDescription(e,t){let r=await this.sendRequest(`/${H}/web-agent/reverse-mapped-description`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return ig.parse(r)}async getTextExtraction(e,t){let r={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/text-extraction`,{method:"POST",body:r,signal:t.abortSignal});return Ec.parse(o)}async getTestResultClassification(e,t){let r=await this.sendRequest(`/${H}/web-agent/result-classification`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Fc.parse(r)}async getExtractedKeywords(e,t){let r=await this.sendRequest(`/${H}/web-agent/extract-keywords`,{method:"POST",body:{goal:e,disableCache:t.disableCache,context:e},signal:t.abortSignal});return ch.parse(r)}async getAutohealingProposal(e,t){let r=await this.sendRequest(`/${H}/web-agent/autoheal-section`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Zu.parse(r)}async getFailureRecoveryProposal(e,t){let r=await this.sendRequest(`/${H}/web-agent/failure-recovery`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Qu.parse(r)}async getIframeRegex(e,t){let r=await this.sendRequest(`/${H}/web-agent/iframe-regex`,{method:"POST",body:e,signal:t.abortSignal});return Nu.parse(r)}};var ci=class extends Nt{generator;constructor(e,t){super(e),this.generator=t}async runTemplateMatching(e,t={}){let r=await this.sendRequest(`/${H}/web-agent/template-matching`,{method:"POST",body:e,signal:t?.signal});return ku.parse(r)}async constructIframeRegex(e,t={}){return this.generator.getIframeRegex(e,{abortSignal:t.signal})}};var ul=class{constructor(e){this.client=e}async uploadResultsArchive(e,t){let{uploadUrl:r,id:o}=await this.client.generateTestResultsUploadUrl(),i=await ii(r,"application/zip",t);if(!i.ok)throw new Error(`Failed to upload test results: ${await i.text()}`);let{runGroupId:a}=await this.client.startProcessingResultsUpload(o,{runGroupId:e});return a}};function di({client:n,gitMetadata:e,alwaysSaveCache:t,noCache:r}){return r?new Ls:new Zd(n,e,t)}var Zd=class{constructor(e,{gitMainBranch:t,gitBranchName:r,gitProtectedBranches:o,gitCommitTimestamp:i,lastCommitOnMainSha:a,lastCommitOnMainTimestamp:s},l){this.client=e;this.cacheHeaders={},t&&(this.cacheHeaders[Xh]=t),r&&(this.cacheHeaders[Zh]=r),i&&(this.cacheHeaders[Qh]=i.toISOString()),a&&(this.cacheHeaders[eg]=a),s&&(this.cacheHeaders[tg]=s.toISOString()),l?this.writeCaches=!0:r?this.writeCaches=!o.includes(r):this.writeCaches=!0}cacheHeaders;writeCaches;async saveStepCacheEntries(e,t,r){if(!this.writeCaches){r.debug("Skipping cache storage because branch is protected");return}try{await this.client.updateStepCaches({entries:e,testId:t},this.cacheHeaders)}catch(o){r.error({err:o},"Failed to save step cache entries")}}async resolveStepCacheEntries(e){let t=await this.client.getStepCacheForTest({testId:e.testId,organizationId:e.organizationId,steps:e.steps,schemaVersion:e.schemaVersion},this.cacheHeaders);if(!this.writeCaches){e.logger.debug("Skipping cache last used at update because branch is protected");return}let{uniqueKeysHit:r}=Uo({steps:e.steps,stepCacheEntries:t,logger:e.logger});this.client.updateCacheLastUsedDate(e.testId,r,e.logger,this.cacheHeaders)}};import{Server as lN}from"socket.io";import{cloneDeep as NP}from"lodash-es";var kP={showOverlay:!1},Qd=class{sessions=new Map;sessionCountByIp=new Map;getCurrentConnectionsByIp(e){return this.sessionCountByIp.get(e)??0}getCurrentSessionsByIp(){return Object.fromEntries(this.sessionCountByIp)}reserveCapacityByIp(e){e&&this.sessionCountByIp.set(e,(this.sessionCountByIp.get(e)??0)+1)}releaseCapacityByIp(e){e&&this.sessionCountByIp.set(e,Math.max(this.getCurrentConnectionsByIp(e)-1,0))}registerSession({controller:e,context:t,cleanup:r,clientIp:o,sessionId:i,browserbaseSessionId:a}){return this.sessions.set(i,{controller:e,context:t,cleanup:r,clientIp:o,browserbaseSessionId:a,browserBehavior:NP(kP)}),i}removeSession(e,t){(async()=>{let o=this.sessions.get(e);if(!o)return;this.releaseCapacityByIp(o.clientIp);let{controller:i}=o;try{i.setClosed(),await i.browser.cleanup()}catch(a){t.error({err:a},"Error cleaning up browser in global state manager")}try{await o.cleanup?.()}catch(a){t.error({err:a},"Error running cleanup function in global state manager")}this.sessions.delete(e)})()}getSession(e){return this.sessions.get(e)}},Q=new Qd;function JS(n,e,t){let r=Date.now(),o=Date.now(),i,a,s,l,c=!1,d=async(h,g)=>{if(!h.closed&&!h.isInPageLoad)try{let f=s;s=void 0;let S=h.url(),w=g.toEditorDisplayCopy();JSON.stringify(w)===JSON.stringify(i)&&S===l&&r>o||(n.emit("browserState",{logsPerPage:f?.logsPerPage,harPages:f?.harPages,harEntries:f?.harEntries,viewport:h.getViewport(),url:S,iframeSrcUrls:a??[],context:w,isInPageLoad:h.isInPageLoad}),r=Date.now()),l=S,i=w}catch(f){if(!n.connected)return;let S=f instanceof Error?f.message:`${f}`;if(S.includes("Frame was detached")||S.includes("Not attached to an active page")||S.includes("browser has been closed")||S.includes("UserInfrastructureError"))return;t.error({err:f,sessionId:e},"Error grabbing browser state")}},p=setInterval(()=>{let h=Q.getSession(e),g=h?.controller?.browser;if(!g||g.closed){t.debug("Clearing browser state socket cron due to the browser being closed"),clearInterval(p);return}d(g,h.context)},1e3),u=(h,g)=>!!(JSON.stringify(h)!==JSON.stringify(a)||g.logsPerPage.some(f=>f.length>0)||g.harPages&&Object.keys(g.harPages).length>0||g.harEntries&&Object.keys(g.harEntries).length>0),m=setInterval(async()=>{let g=Q.getSession(e)?.controller?.browser;if(!g||g.closed){clearInterval(m);return}else if(c)return;c=!0;try{let f=await g.getAllFrameUrls(),S=g.retrieveAndClearDebugData();u(f,S)&&(a=f,s=S,o=Date.now())}catch(f){t.warn({err:f},"Failed to fetch extended details")}finally{c=!1}},2500);return{timers:[p,m]}}var fr={};var _P=n=>()=>{let{sessionId:e}=n.metadata;fr[e]?.abort?.abort()},XS={event:"cancelApiTest",createHandler:_P};import{CookieJar as eL}from"tough-cookie";import{randomUUID as $P}from"crypto";import{faker as DP}from"@faker-js/faker";import FP from"assert";import UP from"axios";import BP from"moment";import*as zP from"otpauth";import HP from"pg";async function ZS(n){let e;try{e=new URL(n.url).hostname}catch{}let t=[];return n.headers.getSetCookie()?.forEach(r=>{let o=xs(r,e);t.push(...o)}),t}var jP=Object.getPrototypeOf(async function(){}).constructor;async function QS(n,e,t){let r=e.code;e.options.fragment&&(r=`return ${e.code}`);let{env:o}=e.bindings,i=e.tools,a={},s=(f,S)=>{o[f]=S,a[f]=S},l={},c=(f,S)=>{o[f]=S,l[f]=S},d;r.includes("Octokit")&&(d=(await import("@octokit/rest")).Octokit);let p;r.includes("createAppAuth")&&(p=(await import("@octokit/auth-app")).createAppAuth);let u=async()=>await Promise.resolve(new jP("axios","moment","faker","assert","pg","Octokit","createAppAuth","OTPAuth","extractCookiesFromResponse","env","setVariable","setPersistentVariable","sendSms","waitForLatestSms","email","sms","ai",r)(UP,BP,i.fakerInstance??DP,FP,HP,d,p,zP,ZS,o,s,c,S=>i.sms.send(S),S=>i.sms.fetchLatest(S),i.email,i.sms,i.ai)),m=!0,h,g;try{h=await D(u(),{milliseconds:e.options.timeoutMs,message:`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`,signal:e.signal})}catch(f){t.error({err:f,env:o,evalCode:r},`[${n}] Error executing code: ${f}`),m=!1,f instanceof hr?g=`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`:g=f instanceof Error?f.message:`${f}`}return{result:h,variableUpdates:a,persistentVariableUpdates:l,success:m,error:g}}async function ey({code:n,fragment:e,context:t,localTools:r,logger:o,signal:i,timeoutMs:a=ar}){let s=$P(),l=await QS(s,{code:n,options:{fragment:e,timeoutMs:a},bindings:t.toObjectCopy(),tools:r,signal:i},o);return y.debug(`[${s}] Got execution result: ${JSON.stringify(l)}`),l}import{createHmac as GP,randomUUID as WP}from"crypto";import VP from"fetch-retry";var qP=VP(global.fetch,{retries:3,retryOn:function(n,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(n){return Math.pow(2,n)*500}}),ty=process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT,ny=process.env.MOMENTIC_LAMBDA_AUTH_SECRET;async function ry({orgId:n,code:e,fragment:t,context:r,timeoutMs:o=ar,retries:i=2,signal:a,logger:s}){if(!ty)throw new Error("GCP_JS_EVAL_FUNCTION_ENDPOINT environment variable not set");let l,c,d=0;if(!ny)throw new Error("Missing lambda auth secret.");let p=GP("sha256",ny).update(n).digest("hex");for(;d<=i;){d++,a?.throwIfAborted();let m={id:WP(),orgId:n,momenticLambdaAuthHash:p,code:e,fragment:t,state:r.toObjectCopy(),timeoutMs:o};try{if(l=await D(qP(ty,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(m)}),{milliseconds:o,message:`Timeout of ${o}ms exceeded for code execution`,signal:a}),!l)throw new Error("Got empty response from code evaluation server");if(!l.ok)throw new Error(`Code evaluation server returned error code ${l.status}`);c=void 0;break}catch(h){c=h}}if(c)throw s.error({err:c},"Failed to evaluate code remotely"),c;if(!l)throw new Error(`An unexpected code evaluation error occurred${c?`: ${c}`:""}`);let u;try{u=bh.parse(await l.json())}catch(m){throw new Error(`Code evaluation server returned invalid response: ${m}`)}if(u.error)throw new Error(`Code evaluation error: ${u.error}`);return u}async function Kn(n){let e;if(process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT)e=await ry(n);else if(n.localTools)e=await ey({...n,localTools:n.localTools});else throw new Error("No code evaluation environment available");if(e.error){let t=`Failed to evaluate code:
|
|
49
|
+
${r.map(o=>o.configFilePath)}`);if(r.length===0)throw new Error("No valid Momentic project file available.");return y.debug(`Found valid project configuration at ${r[0].configFilePath}`),r[0]}function hP(n){let e=uP(n);if(!e||!e.projects||!e.projects.length)return;let t=e.projects.map(i=>(i.endsWith("/")||(i+="/"),`${i}*${Qo}`)),r=Zo(t,{absolute:!1,cwd:Gd(),dotRelative:!1,maxDepth:$d,nodir:!0}),o=[];for(let i of r){let a=eo.join(Gd(),i),s=Wd(a);s&&o.push({configFilePath:a,config:s,rootDir:HS(a)})}return o}function Vd(n){if(n){n=eo.resolve(n);let t=Wd(n);return t||(console.error(`No valid Momentic project file found at ${n}.`),process.exit(1)),[{config:t,configFilePath:n,rootDir:eo.dirname(n)}]}if(rP(zS)){let t=hP(zS);if(t)return t}return mP()}function ei(n,e){let t=jS.stringify(n);aP(e,t)}import ti from"fs";import qd from"path";import{z as Kd}from"zod";var GS="golden/visual-diff",WS="reports",VS="test-results";var gP=Kd.object({width:Kd.number(),height:Kd.number()}),ni=class{defaultGoldenScreenshotDir;regenerateGoldenFiles;constructor(e,t){let r=qd.join(e.rootDir,e.config.goldenFileDir??GS);this.defaultGoldenScreenshotDir=r,this.regenerateGoldenFiles=t}async prepareGoldenScreenshotForComparison(e,t,r){if(t.screenshot?.data?.startsWith("https://")){let a=await fetch(t.screenshot.data);return{buffer:Buffer.from(await a.arrayBuffer()),width:t.screenshot.width,height:t.screenshot.height}}let o=t.screenshot?.data;o||(o=qd.join(this.defaultGoldenScreenshotDir,`${t.id}.jpg`));let i=`${o}.metadata.json`;if(this.regenerateGoldenFiles)return ti.mkdirSync(qd.dirname(o),{recursive:!0}),ti.writeFileSync(o,r.buffer),ti.writeFileSync(i,JSON.stringify({width:r.width,height:r.height})),{buffer:Buffer.from(r.buffer),width:r.width,height:r.height};if(ti.existsSync(o)){let a=ti.readFileSync(o),s=gP.parse(JSON.parse(ti.readFileSync(i,"utf-8")));return{buffer:a,width:s.width,height:s.height}}else throw new R("UserConfigurationError",`Cannot execute visual diff without a saved baseline screenshot at ${o}`)}};var ri=class{flags;constructor(e){this.flags={auto_expand_iframes:e.browser?.autoExpandIframes??!1,rag_v2:e.ai?.aiPageFiltering??!1,faker_constant_seed:e.advanced?.fakerConstantSeed??!1,disable_secondary_cache_resolution:e.browser?.disableSecondaryCacheResolution??!1,show_zero_opacity_elements:e.browser?.showZeroOpacityElements??!1,global_locator_redirect:e.browser?.globalLocatorRedirect??!1,visual_actions:e.browser?.visualActions??!1,mini_model_initial_assertion:!1,mini_model_initial_locator:!1,show_test_plans:!1,icon_knowledge_base:!1,disable_clickhouse_caches:!1,disable_clickhouse_last_updated_endpoint:!1}}isBooleanFlagEnabled(e){return this.flags[e]}getAllFlags(){return{...this.flags}}getFlagPayload(e){}async refresh(){}};import fP from"simple-git";var ve=fP();function ll(n){if(n.startsWith("git@")){let e=n.split(":");if(e.length===2){let t=e[1].replace(".git","").split("/");if(t.length===2){let r=t[0],o=t[1];return`${r}/${o}`}}}else if(n.startsWith("http")||n.startsWith("https")){let t=new URL(n).pathname.split("/").filter(Boolean);if(t.length>=2){let r=t[0],o=t[1].replace(".git","");return`${r}/${o}`}}}async function xe(n,e){try{return(await e).trim()}catch(t){n.error({err:t},"Failed to run git command");return}}function SP(){if(process.env.GITHUB_ACTION)return"GithubActions";if(process.env.GITLAB_CI)return"GitlabCI";if(process.env.CIRCLECI)return"CircleCI";if(process.env.BUILDKITE)return"Buildkite";if(process.env["System.CollectionUri"]?.includes("azure"))return"AzureDevOps"}async function yP(n){let[e,t,r,o]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.GITHUB_SHA,gitCommitShaShort:process.env.GITHUB_SHA?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.GITHUB_HEAD_REF||process.env.GITHUB_REF_NAME,gitOriginUrl:t,gitCommitMessage:r,gitCommitAuthorName:o,githubRepository:process.env.GITHUB_REPOSITORY,pipelineId:`${process.env.GITHUB_RUN_ID}:${process.env.GITHUB_RUN_ATTEMPT}`}}async function bP(n){let[e,t,r]=await Promise.all([xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.CI_COMMIT_SHA,gitCommitShaShort:process.env.CI_COMMIT_SHORT_SHA,gitCommitTimestamp:process.env.CI_COMMIT_TIMESTAMP?new Date(process.env.CI_COMMIT_TIMESTAMP):void 0,gitBranchName:process.env.CI_COMMIT_BRANCH||process.env.CI_COMMIT_REF_NAME,gitOriginUrl:e,gitCommitMessage:t,gitCommitAuthorName:r,gitlabProjectPath:process.env.CI_SERVER_HOST,pipelineId:`${process.env.CI_PIPELINE_ID}:${process.env.CI_JOB_ID}`}}async function wP(n){let[e,t,r,o]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),i=t?.includes("github.com"),a=t?.includes("gitlab.com"),s=t?ll(t):void 0;return{gitCommitSha:process.env.CIRCLE_SHA1,gitCommitShaShort:process.env.CIRCLE_SHA1?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.CIRCLE_BRANCH,gitOriginUrl:process.env.CIRCLE_REPOSITORY_URL,gitCommitMessage:r,gitCommitAuthorName:o,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.CIRCLE_WORKFLOW_ID}:${process.env.CIRCLE_WORKFLOW_JOB_ID}`}}async function vP(n){let[e,t,r]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),o=process.env.BUILDKITE_REPO,i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env.BUILDKITE_COMMIT,gitCommitShaShort:process.env.BUILDKITE_COMMIT?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.BUILDKITE_BRANCH,gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:r,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.BUILDKITE_PIPELINE_ID}:${process.env.BUILDKITE_BUILD_ID}:${process.env.BUILDKITE_JOB_ID}`}}async function xP(n){let[e,t,r]=await Promise.all([xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"]))]),o=process.env["Build.Repository.Uri"],i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env["Build.SourceVersion"],gitCommitShaShort:process.env["Build.SourceVersion"]?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env["Build.SourceBranchName"],gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:r,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env["System.JobId"]}:${process.env["System.JobAttempt"]}`}}async function TP(n,e){let[t,r,o,i,a,s,l,c]=await Promise.all([xe(n,ve.revparse(["HEAD"])),xe(n,ve.revparse(["--short","HEAD"])),xe(n,ve.revparse(["--abbrev-ref","HEAD"])),xe(n,ve.listRemote(["--get-url","origin"])),xe(n,ve.show(["--no-patch","--format=%ci"])),xe(n,ve.show(["-s","--pretty=%B"])),xe(n,ve.show(["-s","--pretty=%an"])),e?xe(n,ve.raw(["merge-base","--fork-point",e])):Promise.resolve(void 0)]),d=c?await xe(n,ve.show(["--no-patch","--format=%ci",c])):void 0,p=i?.includes("github.com"),u=i?.includes("gitlab.com"),m=i?ll(i):void 0;return{gitCommitSha:t,gitCommitShaShort:r,gitBranchName:o,gitOriginUrl:i,gitCommitTimestamp:a?new Date(a):void 0,gitCommitMessage:s,gitCommitAuthorName:l,lastCommitOnMainSha:c,lastCommitOnMainTimestamp:d?new Date(d):void 0,githubRepository:p?m:void 0,gitlabProjectPath:u?m:void 0,pipelineId:void 0}}async function EP(n){let e=n.config.gitProtectedBranches??[];return n.config.gitMainBranch&&e.push(n.config.gitMainBranch),{gitMainBranch:n.config.gitMainBranch,gitProtectedBranches:e}}async function CP(n,e){let t=SP();if(!t)return TP(n,e);switch(t){case"GithubActions":return yP(n);case"GitlabCI":return bP(n);case"CircleCI":return wP(n);case"Buildkite":return vP(n);case"AzureDevOps":return xP(n)}}async function RP(n,e,t){if(t.lastCommitOnMainSha&&t.lastCommitOnMainTimestamp)return{};if(t.gitlabProjectPath){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let r=await e.getMergeBaseCommitFromGitlab(t.gitlabProjectPath,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:r.sha,lastCommitOnMainTimestamp:r.committer.date}}catch(r){return n.warn({err:r},"Failed to get remote metadata from Gitlab"),{}}}if(t.githubRepository){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let[r,o]=t.githubRepository.split("/"),i=await e.getMergeBaseCommitFromGithub(r,o,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:i.sha,lastCommitOnMainTimestamp:i.committer.date}}catch(r){return n.warn({err:r},"Failed to get remote metadata from Github"),{}}}return{}}async function oi(n,e,t){let r=await EP(t),o=await CP(n,r.gitMainBranch),i={...r,...o},a=await RP(n,e,i);return{...r,...o,...a}}import DN from"http";import{z as Xd}from"zod";var H="v1",Aa="2.3.4";var hr=class extends Error{constructor(e){super(e),this.name="TimeoutError"}};var qS=n=>{let e=n.reason===void 0?new DOMException("This operation was aborted.","AbortError"):n.reason;return e instanceof Error?e:new DOMException(e,"AbortError")};async function D(n,e){let{milliseconds:t,fallback:r,message:o,customTimers:i={setTimeout,clearTimeout}}=e,a,s;return new Promise((l,c)=>{if(typeof t!="number"||Math.sign(t)!==1)throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${t}\``);if(e.signal){let{signal:p}=e;p.aborted&&c(qS(p)),s=()=>{c(qS(p))},p.addEventListener("abort",s)}if(t===Number.POSITIVE_INFINITY){n.then(l,c);return}let d=new hr;a=i.setTimeout.call(void 0,()=>{if(r){try{l(r())}catch(p){c(p)}return}"cancel"in n&&typeof n.cancel=="function"&&n.cancel(),o instanceof Error?c(o):(d.message=o??`Promise timed out after ${t} milliseconds`,c(d))},t),(async()=>{try{l(await n)}catch(p){c(p)}})()}).catch(l=>{throw l}).finally(()=>{a!==void 0&&i.clearTimeout.call(void 0,a),s!==void 0&&e.signal&&e.signal.removeEventListener("abort",s)})}var cl=class{limit;windowMs;userActions;constructor(e,t){this.limit=e,this.windowMs=t,this.userActions=new Map}_cleanup(e,t="DEFAULT_USER"){let r=Date.now(),o=`${t}:${e}`;if(this.userActions.has(o)){let a=this.userActions.get(o)?.filter(s=>r-s<=this.windowMs)??[];a.length>0?this.userActions.set(o,a):this.userActions.delete(o)}}increment(e,t="DEFAULT_USER"){let r=Date.now(),o=`${t}:${e}`;this._cleanup(t,e),this.userActions.has(o)||this.userActions.set(o,[]);let i=this.userActions.get(o);return i.length>=this.limit?!0:(i.push(r),!1)}};var Yd=["ability","able","aboard","about","above","accept","accident","according","account","accurate","acres","across","act","action","active","activity","actual","actually","add","addition","additional","adjective","adult","adventure","advice","affect","afraid","after","afternoon","again","against","age","ago","agree","ahead","aid","air","airplane","alike","alive","all","allow","almost","alone","along","aloud","alphabet","already","also","although","am","among","amount","ancient","angle","angry","animal","announced","another","answer","ants","any","anybody","anyone","anything","anyway","anywhere","apart","apartment","appearance","apple","applied","appropriate","are","area","arm","army","around","arrange","arrangement","arrive","arrow","art","article","as","aside","ask","asleep","at","ate","atmosphere","atom","atomic","attached","attack","attempt","attention","audience","author","automobile","available","average","avoid","aware","away","baby","back","bad","badly","bag","balance","ball","balloon","band","bank","bar","bare","bark","barn","base","baseball","basic","basis","basket","bat","battle","be","bean","bear","beat","beautiful","beauty","became","because","become","becoming","bee","been","before","began","beginning","begun","behavior","behind","being","believed","bell","belong","below","belt","bend","beneath","bent","beside","best","bet","better","between","beyond","bicycle","bigger","biggest","bill","birds","birth","birthday","bit","bite","black","blank","blanket","blew","blind","block","blood","blow","blue","board","boat","body","bone","book","border","born","both","bottle","bottom","bound","bow","bowl","box","boy","brain","branch","brass","brave","bread","break","breakfast","breath","breathe","breathing","breeze","brick","bridge","brief","bright","bring","broad","broke","broken","brother","brought","brown","brush","buffalo","build","building","built","buried","burn","burst","bus","bush","business","busy","but","butter","buy","by","cabin","cage","cake","call","calm","came","camera","camp","can","canal","cannot","cap","capital","captain","captured","car","carbon","card","care","careful","carefully","carried","carry","case","cast","castle","cat","catch","cattle","caught","cause","cave","cell","cent","center","central","century","certain","certainly","chain","chair","chamber","chance","change","changing","chapter","character","characteristic","charge","chart","check","cheese","chemical","chest","chicken","chief","child","children","choice","choose","chose","chosen","church","circle","circus","citizen","city","class","classroom","claws","clay","clean","clear","clearly","climate","climb","clock","close","closely","closer","cloth","clothes","clothing","cloud","club","coach","coal","coast","coat","coffee","cold","collect","college","colony","color","column","combination","combine","come","comfortable","coming","command","common","community","company","compare","compass","complete","completely","complex","composed","composition","compound","concerned","condition","congress","connected","consider","consist","consonant","constantly","construction","contain","continent","continued","contrast","control","conversation","cook","cookies","cool","copper","copy","corn","corner","correct","correctly","cost","cotton","could","count","country","couple","courage","course","court","cover","cow","cowboy","crack","cream","create","creature","crew","crop","cross","crowd","cry","cup","curious","current","curve","customs","cut","cutting","daily","damage","dance","danger","dangerous","dark","darkness","date","daughter","dawn","day","dead","deal","dear","death","decide","declared","deep","deeply","deer","definition","degree","depend","depth","describe","desert","design","desk","detail","determine","develop","development","diagram","diameter","did","die","differ","difference","different","difficult","difficulty","dig","dinner","direct","direction","directly","dirt","dirty","disappear","discover","discovery","discuss","discussion","disease","dish","distance","distant","divide","division","do","doctor","does","dog","doing","doll","dollar","done","donkey","door","dot","double","doubt","down","dozen","draw","drawn","dream","dress","drew","dried","drink","drive","driven","driver","driving","drop","dropped","drove","dry","duck","due","dug","dull","during","dust","duty","each","eager","ear","earlier","early","earn","earth","easier","easily","east","easy","eat","eaten","edge","education","effect","effort","egg","eight","either","electric","electricity","element","elephant","eleven","else","empty","end","enemy","energy","engine","engineer","enjoy","enough","enter","entire","entirely","environment","equal","equally","equator","equipment","escape","especially","essential","establish","even","evening","event","eventually","ever","every","everybody","everyone","everything","everywhere","evidence","exact","exactly","examine","example","excellent","except","exchange","excited","excitement","exciting","exclaimed","exercise","exist","expect","experience","experiment","explain","explanation","explore","express","expression","extra","eye","face","facing","fact","factor","factory","failed","fair","fairly","fall","fallen","familiar","family","famous","far","farm","farmer","farther","fast","fastened","faster","fat","father","favorite","fear","feathers","feature","fed","feed","feel","feet","fell","fellow","felt","fence","few","fewer","field","fierce","fifteen","fifth","fifty","fight","fighting","figure","fill","film","final","finally","find","fine","finest","finger","finish","fire","fireplace","firm","first","fish","five","fix","flag","flame","flat","flew","flies","flight","floating","floor","flow","flower","fly","fog","folks","follow","food","foot","football","for","force","foreign","forest","forget","forgot","forgotten","form","former","fort","forth","forty","forward","fought","found","four","fourth","fox","frame","free","freedom","frequently","fresh","friend","friendly","frighten","frog","from","front","frozen","fruit","fuel","full","fully","fun","function","funny","fur","furniture","further","future","gain","game","garage","garden","gas","gasoline","gate","gather","gave","general","generally","gentle","gently","get","getting","giant","gift","girl","give","given","giving","glad","glass","globe","go","goes","gold","golden","gone","good","goose","got","government","grabbed","grade","gradually","grain","grandfather","grandmother","graph","grass","gravity","gray","great","greater","greatest","greatly","green","grew","ground","group","grow","grown","growth","guard","guess","guide","gulf","gun","habit","had","hair","half","halfway","hall","hand","handle","handsome","hang","happen","happened","happily","happy","harbor","hard","harder","hardly","has","hat","have","having","hay","he","headed","heading","health","heard","hearing","heart","heat","heavy","height","held","hello","help","helpful","her","herd","here","herself","hidden","hide","high","higher","highest","highway","hill","him","himself","his","history","hit","hold","hole","hollow","home","honor","hope","horn","horse","hospital","hot","hour","house","how","however","huge","human","hundred","hung","hungry","hunt","hunter","hurried","hurry","hurt","husband","ice","idea","identity","if","ill","image","imagine","immediately","importance","important","impossible","improve","in","inch","include","including","income","increase","indeed","independent","indicate","individual","industrial","industry","influence","information","inside","instance","instant","instead","instrument","interest","interior","into","introduced","invented","involved","iron","is","island","it","its","itself","jack","jar","jet","job","join","joined","journey","joy","judge","jump","jungle","just","keep","kept","key","kids","kill","kind","kitchen","knew","knife","know","knowledge","known","label","labor","lack","lady","laid","lake","lamp","land","language","large","larger","largest","last","late","later","laugh","law","lay","layers","lead","leader","leaf","learn","least","leather","leave","leaving","led","left","leg","length","lesson","let","letter","level","library","lie","life","lift","light","like","likely","limited","line","lion","lips","liquid","list","listen","little","live","living","load","local","locate","location","log","lonely","long","longer","look","loose","lose","loss","lost","lot","loud","love","lovely","low","lower","luck","lucky","lunch","lungs","lying","machine","machinery","mad","made","magic","magnet","mail","main","mainly","major","make","making","man","managed","manner","manufacturing","many","map","mark","market","married","mass","massage","master","material","mathematics","matter","may","maybe","me","meal","mean","means","meant","measure","meat","medicine","meet","melted","member","memory","men","mental","merely","met","metal","method","mice","middle","might","mighty","mile","military","milk","mill","mind","mine","minerals","minute","mirror","missing","mission","mistake","mix","mixture","model","modern","molecular","moment","money","monkey","month","mood","moon","more","morning","most","mostly","mother","motion","motor","mountain","mouse","mouth","move","movement","movie","moving","mud","muscle","music","musical","must","my","myself","mysterious","nails","name","nation","national","native","natural","naturally","nature","near","nearby","nearer","nearest","nearly","necessary","neck","needed","needle","needs","negative","neighbor","neighborhood","nervous","nest","never","new","news","newspaper","next","nice","night","nine","no","nobody","nodded","noise","none","noon","nor","north","nose","not","note","noted","nothing","notice","noun","now","number","numeral","nuts","object","observe","obtain","occasionally","occur","ocean","of","off","offer","office","officer","official","oil","old","older","oldest","on","once","one","only","onto","open","operation","opinion","opportunity","opposite","or","orange","orbit","order","ordinary","organization","organized","origin","original","other","ought","our","ourselves","out","outer","outline","outside","over","own","owner","oxygen","pack","package","page","paid","pain","paint","pair","palace","pale","pan","paper","paragraph","parallel","parent","park","part","particles","particular","particularly","partly","parts","party","pass","passage","past","path","pattern","pay","peace","pen","pencil","people","per","percent","perfect","perfectly","perhaps","period","person","personal","pet","phrase","physical","piano","pick","picture","pictured","pie","piece","pig","pile","pilot","pine","pink","pipe","pitch","place","plain","plan","plane","planet","planned","planning","plant","plastic","plate","plates","play","pleasant","please","pleasure","plenty","plural","plus","pocket","poem","poet","poetry","point","pole","police","policeman","political","pond","pony","pool","poor","popular","population","porch","port","position","positive","possible","possibly","post","pot","potatoes","pound","pour","powder","power","powerful","practical","practice","prepare","present","president","press","pressure","pretty","prevent","previous","price","pride","primitive","principal","principle","printed","private","prize","probably","problem","process","produce","product","production","program","progress","promised","proper","properly","property","protection","proud","prove","provide","public","pull","pupil","pure","purple","purpose","push","put","putting","quarter","queen","question","quick","quickly","quiet","quietly","quite","rabbit","race","radio","railroad","rain","raise","ran","ranch","range","rapidly","rate","rather","raw","rays","reach","read","reader","ready","real","realize","rear","reason","recall","receive","recent","recently","recognize","record","red","refer","refused","region","regular","related","relationship","religious","remain","remarkable","remember","remove","repeat","replace","replied","report","represent","require","research","respect","rest","result","return","review","rhyme","rhythm","rice","rich","ride","riding","right","ring","rise","rising","river","road","roar","rock","rocket","rocky","rod","roll","roof","room","root","rope","rose","rough","round","route","row","rubbed","rubber","rule","ruler","run","running","rush","sad","saddle","safe","safety","said","sail","sale","salmon","salt","same","sand","sang","sat","satellites","satisfied","save","saved","saw","say","scale","scared","scene","school","science","scientific","scientist","score","screen","sea","search","season","seat","second","secret","section","see","seed","seeing","seems","seen","seldom","select","selection","sell","send","sense","sent","sentence","separate","series","serious","serve","service","sets","setting","settle","settlers","seven","several","shade","shadow","shake","shaking","shall","shallow","shape","share","sharp","she","sheep","sheet","shelf","shells","shelter","shine","shinning","ship","shirt","shoe","shoot","shop","shore","short","shorter","shot","should","shoulder","shout","show","shown","shut","sick","sides","sight","sign","signal","silence","silent","silk","silly","silver","similar","simple","simplest","simply","since","sing","single","sink","sister","sit","sitting","situation","six","size","skill","skin","sky","slabs","slave","sleep","slept","slide","slight","slightly","slip","slipped","slope","slow","slowly","small","smaller","smallest","smell","smile","smoke","smooth","snake","snow","so","soap","social","society","soft","softly","soil","solar","sold","soldier","solid","solution","solve","some","somebody","somehow","someone","something","sometime","somewhere","son","song","soon","sort","sound","source","south","southern","space","speak","special","species","specific","speech","speed","spell","spend","spent","spider","spin","spirit","spite","split","spoken","sport","spread","spring","square","stage","stairs","stand","standard","star","stared","start","state","statement","station","stay","steady","steam","steel","steep","stems","step","stepped","stick","stiff","still","stock","stomach","stone","stood","stop","stopped","store","storm","story","stove","straight","strange","stranger","straw","stream","street","strength","stretch","strike","string","strip","strong","stronger","struck","structure","struggle","stuck","student","studied","studying","subject","substance","success","successful","such","sudden","suddenly","sugar","suggest","suit","sum","summer","sun","sunlight","supper","supply","support","suppose","sure","surface","surprise","surrounded","swam","sweet","swept","swim","swimming","swing","swung","syllable","symbol","system","table","tail","take","taken","tales","talk","tall","tank","tape","task","taste","taught","tax","tea","teach","teacher","team","tears","teeth","telephone","television","tell","temperature","ten","tent","term","terrible","test","than","thank","that","thee","them","themselves","then","theory","there","therefore","these","they","thick","thin","thing","think","third","thirty","this","those","thou","though","thought","thousand","thread","three","threw","throat","through","throughout","throw","thrown","thumb","thus","thy","tide","tie","tight","tightly","till","time","tin","tiny","tip","tired","title","to","tobacco","today","together","told","tomorrow","tone","tongue","tonight","too","took","tool","top","topic","torn","total","touch","toward","tower","town","toy","trace","track","trade","traffic","trail","train","transportation","trap","travel","treated","tree","triangle","tribe","trick","tried","trip","troops","tropical","trouble","truck","trunk","truth","try","tube","tune","turn","twelve","twenty","twice","two","type","typical","uncle","under","underline","understanding","unhappy","union","unit","universe","unknown","unless","until","unusual","up","upon","upper","upward","us","use","useful","using","usual","usually","valley","valuable","value","vapor","variety","various","vast","vegetable","verb","vertical","very","vessels","victory","view","village","visit","visitor","voice","volume","vote","vowel","voyage","wagon","wait","walk","wall","want","war","warm","warn","was","wash","waste","watch","water","wave","way","we","weak","wealth","wear","weather","week","weigh","weight","welcome","well","went","were","west","western","wet","whale","what","whatever","wheat","wheel","when","whenever","where","wherever","whether","which","while","whispered","whistle","white","who","whole","whom","whose","why","wide","widely","wife","wild","will","willing","win","wind","window","wing","winter","wire","wise","wish","with","within","without","wolf","women","won","wonder","wonderful","wood","wooden","wool","word","wore","work","worker","world","worried","worry","worse","worth","would","wrapped","write","writer","writing","written","wrong","wrote","yard","year","yellow","yes","yesterday","yet","you","young","younger","your","yourself","youth","zero","zebra","zipper","zoo","zulu"];function KS(n){return new Array(n).fill(0).map(()=>Yd[Math.floor(Math.random()*Yd.length)]).join("-")}var AP=9e4,IP=15e3,yn=class extends Error{status;rawError;constructor(e,t,r,o={}){super(r,o),this.status=e,this.rawError=t}};async function PP(n){return n.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var Jd=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return Aa&&(e[Jh]=Aa),e}async sendRequest(e,t,r=3,o=AP){let i=r,a,s={path:e,baseUrl:this.baseUrl,method:t.method};for(;r>0;)try{return r--,await this.sendSingleRequestHelper(e,t,o)}catch(l){if(a=l,l instanceof yn&&l.status>=400&&l.status<500)throw l;if(l instanceof Error&&l.name==="AbortError"&&(a=new hr),r===0)throw a;let c=1500,d=i-r,p=Math.min(c*Math.pow(2,d-1),IP);await new Promise(u=>setTimeout(u,p))}throw this.logger.warn({...s,err:a},"Got fatal error response from Momentic server"),a}async sendSingleRequestHelper(e,t,r){let o={path:e,baseUrl:this.baseUrl,method:t.method},i=new AbortController,a=setTimeout(()=>i.abort(),r),s=()=>i.abort();t.signal&&t.signal.addEventListener("abort",s);let l={...this.getHeaders(),...t.extraHeaders};try{let c=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!c.ok){let p=await PP(c);throw new yn(c.status,p,`Request to ${e} failed with status ${c.status}: ${p}`)}let d;if(c.status===204)d={};else{let p=await c.text();try{d=JSON.parse(p)}catch{d=p}}return this.logger&&!t.noLog&&d&&this.logger.debug({result:d,status:c.status,...o},"Got response from Momentic server"),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Nt=class extends Jd{apiKey;constructor(e){super(e),this.apiKey=e.apiKey}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`}}};var lt=class extends Nt{constructor(e){super(e)}getAppUrl(){return this.baseUrl.replace(/\/\/api/,"//app")}async getAuthInfo(){let e=await this.sendRequest(`/${H}/auth/check`,{method:"GET",noLog:!0},10,5e3),{orgId:t,userId:r}=fg.parse(e);return{orgId:t,userId:r}}async bulkGetRunStatus(e){let t=await this.sendRequest(`/${H}/runs/status`,{method:"POST",body:e,noLog:!0},3,1e4);return ug.parse(t)}async getTestYAMLExport(e){let t=await this.sendRequest(`/${H}/tests/export`,{method:"POST",body:e},3,3e4);return sg.parse(t)}async updateStepCaches(e,t){await this.sendRequest(`/${H}/cache`,{method:"PATCH",body:e,extraHeaders:t},3,1e4)}async getStepCacheForTest(e,t){let r=await this.sendRequest(`/${H}/cache`,{method:"POST",body:e,extraHeaders:t},10,3e4);return lg.parse(r)}async queueTests(e){let t=await this.sendRequest(`/${H}/tests/queue`,{method:"POST",body:e},3,1e4);return ag.parse(t)}async uploadScreenshot(e){let t=await this.sendRequest(`/${H}/screenshots`,{method:"POST",body:e,noLog:!0},3,5e3);return gg.parse(t)}async getAllEnvironments(){let e=await this.sendRequest(`/${H}/environments`,{method:"GET"},3,5e3);return Sg.parse(e)}async acquireCacheLock(e,t){let r=await this.sendRequest(`/${H}/result-cache/lock`,{method:"POST",body:e,signal:t},3,3e4);return Eg.parse(r)}async releaseCacheLock(e){await this.sendRequest(`/${H}/result-cache/lock`,{method:"DELETE",body:{key:e}},3,5e3)}async deleteCacheResult(e){await this.sendRequest(`/${H}/result-cache/entry`,{method:"DELETE",body:e},3,5e3)}async setCacheResult(e){await this.sendRequest(`/${H}/result-cache/entry`,{method:"PATCH",body:e},3,5e3)}async getCacheResult(e){try{return await this.sendRequest(`/${H}/result-cache/entry`,{method:"POST",body:e},3,5e3)}catch(t){if(t instanceof Error&&t.message.includes("404"))return null;throw t}}async queueSuiteRuns(e){let t=await this.sendRequest(`/${H}/suites/queue`,{method:"POST",body:e},3,5e3);return yg.parse(t)}async bulkGetRunGroupStatus(e){let t={runGroupIds:e},r=await this.sendRequest(`/${H}/run-groups/status`,{method:"POST",body:t,noLog:!0},3,5e3);return Jm.array().parse(r)}async updateCacheLastUsedDate(e,t,r,o){try{await this.sendRequest(`/${H}/cache/last-used-at`,{method:"PATCH",body:{uniqueKeys:t,testId:e},noLog:!0,extraHeaders:o},3,7500)}catch(i){r.error({err:i},"Failed to update cache last used date")}}async uploadProposedSteps(e,t){try{await this.sendRequest(`/${H}/test-fragments/`,{method:"POST",body:e},3,1e4)}catch(r){t.error({err:r},"Failed to upload proposed steps")}}async uploadSnapshotScreenshot(e,t,r){try{await this.sendRequest(`/${H}/snapshots/${t}/screenshot`,{method:"POST",body:r,noLog:!0},3,1e4)}catch(o){e.error({err:o},"Failed to upload screenshot")}}async generateConsoleLogsForRunAttemptUploadUrl(e,t,r){let o=await this.sendRequest(`/${H}/runs/${t}/attempts/${r}/console-logs`,{method:"POST",noLog:!0},3,5e3);return na.parse(o)}async generateNetworkLogsForRunAttemptUploadUrl(e,t,r){let o=await this.sendRequest(`/${H}/runs/${t}/attempts/${r}/network-logs`,{method:"POST",noLog:!0},3,1e4);return na.parse(o)}async generateHtmlSnapshotUploadUrl(e,t){let r=await this.sendRequest(`/${H}/snapshots/${t}/html`,{method:"POST",noLog:!0},3,1e4);return na.parse(r)}async reportBillableEvents(e,t){try{await this.sendRequest(`/${H}/billing/events`,{method:"POST",body:t,noLog:!0},10,1e4)}catch(r){e.error({err:r},"Failed to report billable event")}}async fetchTestFragment(e){let t=await this.sendRequest(`/${H}/test-fragments/${e}`,{method:"GET",noLog:!0},3,1e4);return bg.parse(t)}async patchTestFragment(e,t){await this.sendRequest(`/${H}/test-fragments/${e}`,{method:"PATCH",body:t},3,1e4)}async getPastTestResults(e,t){let r=await this.sendRequest(`/${H}/results/tests/${e}`,{method:"POST",body:t},3,1e4);return wg.parse(r)}async generateTestResultsUploadUrl(){let e=await this.sendRequest(`/${H}/results/uploads`,{method:"POST",noLog:!0},3,1e4);return vg.parse(e)}async startProcessingResultsUpload(e,t){let r=await this.sendRequest(`/${H}/results/uploads/${e}/process`,{method:"POST",noLog:!0,body:t},3,1e4);return xg.parse(r)}async fetchIconKnowledgeBase(e,t){try{let r=await this.sendRequest(`/${H}/knowledge-base/icons`,{method:"GET",noLog:!0},3,5e3);return Lg.parse(r)}catch(r){return t.error({err:r},"Failed to fetch icon knowledge base"),null}}async saveNewIcons(e,t){try{await this.sendRequest(`/${H}/knowledge-base/icons`,{method:"POST",body:e,noLog:!0},3,5e3)}catch(r){t.error({err:r},"Failed to save new icons to icon knowledge base")}}async getMergeBaseCommitFromGithub(e,t,r,o){let i=new URLSearchParams;i.set("base",r),i.set("head",o);let a=await this.sendRequest(`/${H}/git/github/${e}/${t}/merge-base-commit?${i.toString()}`,{method:"GET",noLog:!0},3,1e4);return cd.parse(a)}async getMergeBaseCommitFromGitlab(e,t,r){let o=new URLSearchParams;o.set("base",t),o.set("head",r);let i=await this.sendRequest(`/${H}/git/gitlab/${e}/merge-base-commit?${o.toString()}`,{method:"GET",noLog:!0},3,5e3);return cd.parse(i)}async getAgentConfig(){let e=await this.sendRequest(`/${H}/web-agent/agent-config`,{method:"GET",noLog:!0},3,5e3);return Xd.record(Xd.string(),Xd.string()).parse(e)}};import{randomUUID as YS}from"crypto";var dl=class{apiClient;constructor(e){this.apiClient=e}async reportBillableEvent(e,t,r){try{return await this.apiClient.reportBillableEvents(e,[{event:t,timestamp:new Date().toISOString(),transactionId:r?.eventId??YS(),properties:Xc({},r)}])}catch(o){e.error({err:o},"Failed to report billable event")}}async reportCreditsUsed(e,t,r,o){if(r)try{return await this.apiClient.reportBillableEvents(e,[{event:"credits-used",timestamp:new Date().toISOString(),transactionId:o?.eventId??YS(),properties:Xc({creditsUsed:r,usedBy:t},o)}])}catch(i){e.error({err:i},"Failed to report credits used")}}};function ii(n,e,t){return fetch(n,{method:"PUT",body:t,headers:{"Content-Type":e}})}var pl=class{constructor(e){this.client=e}async storeConsoleLogsForRunAttempt(e,t,r,o){try{let i=JSON.stringify(o),{uploadUrl:a}=await this.client.generateConsoleLogsForRunAttemptUploadUrl(e,t,r),s=await ii(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(i){e.error({err:i},"Failed to upload console logs")}}async storeNetworkLogsForRunAttempt(e,t,r,o){let i=JSON.stringify(o);try{let{uploadUrl:a}=await this.client.generateNetworkLogsForRunAttemptUploadUrl(e,t,r),s=await ii(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(a){e.error({err:a},"Failed to upload network logs")}}async storeHtmlSnapshot(e,t,r){try{let{uploadUrl:o}=await this.client.generateHtmlSnapshotUploadUrl(e,t),i=await ii(o,"text/html",r);if(!i.ok)throw new Error(`Failed to upload network logs: ${i.statusText}`)}catch(o){e.error({err:o},"Failed to upload html snapshot")}}async storeScreenshot(e,t,r){try{await this.client.uploadSnapshotScreenshot(e,t,{screenshot:r.toString("base64")})}catch(o){e.error({err:o},"Failed to upload screenshot")}}async storeA11yTreeSnapshot(e,t,r){return Promise.resolve()}async getConsoleLogsForRunAttempt(e,t,r){}async getNetworkLogsForRunAttempt(e,t,r){}async getHtmlSnapshot(e,t){}async getA11yTreeSnapshot(e,t){}async getScreenshot(e,t){}};var ai=class{constructor(e,t){this.client=e;this.orgId=t}async acquireCacheLock(e,t){return this.client.acquireCacheLock(e,t)}async uploadScreenshot(e){return(await this.client.uploadScreenshot({screenshot:e.toString("base64")})).key}async releaseCacheLock(e){return this.client.releaseCacheLock(e)}async deleteCacheResult(e){return this.client.deleteCacheResult(e)}async setCacheResult(e){return this.client.setCacheResult(e)}async getCacheResult(e){return this.client.getCacheResult(e)}fetchIconKnowledgeBase(e,t){return this.client.fetchIconKnowledgeBase(e,t)}saveNewIcons(e,t,r){return this.client.saveNewIcons(t,r)}};import{Faker as LP,en as OP}from"@faker-js/faker";var si="v1",gr=class{httpClient;fakerInstance;type="API_CLIENT";sms={send:this.sendSms.bind(this),fetchLatest:this.fetchLatestSms.bind(this)};email={send:this.sendEmail.bind(this),fetchLatest:this.fetchLatestEmail.bind(this),fetchAll:this.fetchAllEmails.bind(this)};ai={generate:this.sendAiGenerate.bind(this)};constructor(e){this.httpClient=e.httpClient,e.fakerSeed&&(this.fakerInstance=new LP({locale:OP}),this.fakerInstance.seed(e.fakerSeed))}async sendAiGenerate(e){let t=typeof e=="string"?{input:e}:e;return this.httpClient.sendRequest(`/${si}/tools/ai/generate`,{method:"POST",body:t}).catch(r=>{throw r instanceof yn?new Error(r.rawError):new Error(`Failed to send AI generation: ${r.message}`)})}async sendSms(e){return this.httpClient.sendRequest(`/${si}/tools/sms/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send sms: ${t.message}`)})}async fetchLatestSms(e){return this.httpClient.sendRequest(`/${si}/tools/sms/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):t})}async sendEmail(e){return this.httpClient.sendRequest(`/${si}/tools/email/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send email: ${t.message}`)})}async fetchAllEmails(e){return this.httpClient.sendRequest(`/${si}/tools/email/fetchAll`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch all emails: ${t.message}`)})}async fetchLatestEmail(e){return this.httpClient.sendRequest(`/${si}/tools/email/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch latest emails: ${t.message}`)})}};import{z as MP}from"zod";var li=class extends Nt{agentConfig;constructor(e,t){super(t),this.agentConfig=e}async rankChunksWithAi(e,t){let r={...e,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/recommend-chunks-ai`,{method:"POST",body:r,signal:t.abortSignal});return ph.parse(o)}async rankChunksWithRag(e,t){let r=await this.sendRequest(`/${H}/web-agent/recommend-chunks`,{method:"POST",body:{cliVersion:Aa,...e},signal:t.abortSignal});return dh.parse(r)}async getScreenshotFromS3(e){let t=await this.sendRequest(`/${H}/s3/visual-diff-screenshot`,{method:"POST",body:{url:e}});return MP.string().parse(t)}async getElementLocation(e,t){let r={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${H}/web-agent/locate-element`,{method:"POST",body:r,signal:t.abortSignal});return og.parse(o)}async getAssertionResult(e,t){let r={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${H}/web-agent/assertion`,{method:"POST",body:r,signal:t.abortSignal});return sd.parse(o)}async getLintStepResult(e,t){let r={...e,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/lint/step`,{method:"POST",body:r,signal:t.abortSignal});return rg.parse(o)}async getVisualAssertionResult(e,t){let r={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/visual-assertion`,{method:"POST",body:r,signal:t.abortSignal});return sd.parse(o)}async getAiActionCommand(e,t){let r=await this.sendRequest(`/${H}/web-agent/next-command-dynamic`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return ng.parse(r)}async getMultiturnAiActionCommand(e,t){return await this.sendRequest(`/${H}/web-agent/ai-action/next-command`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal})}async getMultiturnAiActionEvaluation(e,t){let r=await this.sendRequest(`/${H}/web-agent/ai-action/evaluate`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Cc.parse(r)}async getReverseMappedDescription(e,t){let r=await this.sendRequest(`/${H}/web-agent/reverse-mapped-description`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return ig.parse(r)}async getTextExtraction(e,t){let r={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${H}/web-agent/text-extraction`,{method:"POST",body:r,signal:t.abortSignal});return Ec.parse(o)}async getTestResultClassification(e,t){let r=await this.sendRequest(`/${H}/web-agent/result-classification`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Fc.parse(r)}async getExtractedKeywords(e,t){let r=await this.sendRequest(`/${H}/web-agent/extract-keywords`,{method:"POST",body:{goal:e,disableCache:t.disableCache,context:e},signal:t.abortSignal});return ch.parse(r)}async getAutohealingProposal(e,t){let r=await this.sendRequest(`/${H}/web-agent/autoheal-section`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Zu.parse(r)}async getFailureRecoveryProposal(e,t){let r=await this.sendRequest(`/${H}/web-agent/failure-recovery`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Qu.parse(r)}async getIframeRegex(e,t){let r=await this.sendRequest(`/${H}/web-agent/iframe-regex`,{method:"POST",body:e,signal:t.abortSignal});return Nu.parse(r)}};var ci=class extends Nt{generator;constructor(e,t){super(e),this.generator=t}async runTemplateMatching(e,t={}){let r=await this.sendRequest(`/${H}/web-agent/template-matching`,{method:"POST",body:e,signal:t?.signal});return ku.parse(r)}async constructIframeRegex(e,t={}){return this.generator.getIframeRegex(e,{abortSignal:t.signal})}};var ul=class{constructor(e){this.client=e}async uploadResultsArchive(e,t){let{uploadUrl:r,id:o}=await this.client.generateTestResultsUploadUrl(),i=await ii(r,"application/zip",t);if(!i.ok)throw new Error(`Failed to upload test results: ${await i.text()}`);let{runGroupId:a}=await this.client.startProcessingResultsUpload(o,{runGroupId:e});return a}};function di({client:n,gitMetadata:e,alwaysSaveCache:t,noCache:r}){return r?new Ls:new Zd(n,e,t)}var Zd=class{constructor(e,{gitMainBranch:t,gitBranchName:r,gitProtectedBranches:o,gitCommitTimestamp:i,lastCommitOnMainSha:a,lastCommitOnMainTimestamp:s},l){this.client=e;this.cacheHeaders={},t&&(this.cacheHeaders[Xh]=t),r&&(this.cacheHeaders[Zh]=r),i&&(this.cacheHeaders[Qh]=i.toISOString()),a&&(this.cacheHeaders[eg]=a),s&&(this.cacheHeaders[tg]=s.toISOString()),l?this.writeCaches=!0:r?this.writeCaches=!o.includes(r):this.writeCaches=!0}cacheHeaders;writeCaches;async saveStepCacheEntries(e,t,r){if(!this.writeCaches){r.debug("Skipping cache storage because branch is protected");return}try{await this.client.updateStepCaches({entries:e,testId:t},this.cacheHeaders)}catch(o){r.error({err:o},"Failed to save step cache entries")}}async resolveStepCacheEntries(e){let t=await this.client.getStepCacheForTest({testId:e.testId,organizationId:e.organizationId,steps:e.steps,schemaVersion:e.schemaVersion},this.cacheHeaders);if(!this.writeCaches){e.logger.debug("Skipping cache last used at update because branch is protected");return}let{uniqueKeysHit:r}=Uo({steps:e.steps,stepCacheEntries:t,logger:e.logger});this.client.updateCacheLastUsedDate(e.testId,r,e.logger,this.cacheHeaders)}};import{Server as lN}from"socket.io";import{cloneDeep as NP}from"lodash-es";var kP={showOverlay:!1},Qd=class{sessions=new Map;sessionCountByIp=new Map;getCurrentConnectionsByIp(e){return this.sessionCountByIp.get(e)??0}getCurrentSessionsByIp(){return Object.fromEntries(this.sessionCountByIp)}reserveCapacityByIp(e){e&&this.sessionCountByIp.set(e,(this.sessionCountByIp.get(e)??0)+1)}releaseCapacityByIp(e){e&&this.sessionCountByIp.set(e,Math.max(this.getCurrentConnectionsByIp(e)-1,0))}registerSession({controller:e,context:t,cleanup:r,clientIp:o,sessionId:i,browserbaseSessionId:a}){return this.sessions.set(i,{controller:e,context:t,cleanup:r,clientIp:o,browserbaseSessionId:a,browserBehavior:NP(kP)}),i}removeSession(e,t){(async()=>{let o=this.sessions.get(e);if(!o)return;this.releaseCapacityByIp(o.clientIp);let{controller:i}=o;try{i.setClosed(),await i.browser.cleanup()}catch(a){t.error({err:a},"Error cleaning up browser in global state manager")}try{await o.cleanup?.()}catch(a){t.error({err:a},"Error running cleanup function in global state manager")}this.sessions.delete(e)})()}getSession(e){return this.sessions.get(e)}},Q=new Qd;function JS(n,e,t){let r=Date.now(),o=Date.now(),i,a,s,l,c=!1,d=async(h,g)=>{if(!h.closed&&!h.isInPageLoad)try{let f=s;s=void 0;let S=h.url(),w=g.toEditorDisplayCopy();JSON.stringify(w)===JSON.stringify(i)&&S===l&&r>o||(n.emit("browserState",{logsPerPage:f?.logsPerPage,harPages:f?.harPages,harEntries:f?.harEntries,viewport:h.getViewport(),url:S,iframeSrcUrls:a??[],context:w,isInPageLoad:h.isInPageLoad}),r=Date.now()),l=S,i=w}catch(f){if(!n.connected)return;let S=f instanceof Error?f.message:`${f}`;if(S.includes("Frame was detached")||S.includes("Not attached to an active page")||S.includes("browser has been closed")||S.includes("UserInfrastructureError"))return;t.error({err:f,sessionId:e},"Error grabbing browser state")}},p=setInterval(()=>{let h=Q.getSession(e),g=h?.controller?.browser;if(!g||g.closed){t.debug("Clearing browser state socket cron due to the browser being closed"),clearInterval(p);return}d(g,h.context)},1e3),u=(h,g)=>!!(JSON.stringify(h)!==JSON.stringify(a)||g.logsPerPage.some(f=>f.length>0)||g.harPages&&Object.keys(g.harPages).length>0||g.harEntries&&Object.keys(g.harEntries).length>0),m=setInterval(async()=>{let g=Q.getSession(e)?.controller?.browser;if(!g||g.closed){clearInterval(m);return}else if(c)return;c=!0;try{let f=await g.getAllFrameUrls(),S=g.retrieveAndClearDebugData();u(f,S)&&(a=f,s=S,o=Date.now())}catch(f){t.warn({err:f},"Failed to fetch extended details")}finally{c=!1}},2500);return{timers:[p,m]}}var fr={};var _P=n=>()=>{let{sessionId:e}=n.metadata;fr[e]?.abort?.abort()},XS={event:"cancelApiTest",createHandler:_P};import{CookieJar as eL}from"tough-cookie";import{randomUUID as $P}from"crypto";import{faker as DP}from"@faker-js/faker";import FP from"assert";import UP from"axios";import BP from"moment";import*as zP from"otpauth";import HP from"pg";async function ZS(n){let e;try{e=new URL(n.url).hostname}catch{}let t=[];return n.headers.getSetCookie()?.forEach(r=>{let o=xs(r,e);t.push(...o)}),t}var jP=Object.getPrototypeOf(async function(){}).constructor;async function QS(n,e,t){let r=e.code;e.options.fragment&&(r=`return ${e.code}`);let{env:o}=e.bindings,i=e.tools,a={},s=(f,S)=>{o[f]=S,a[f]=S},l={},c=(f,S)=>{o[f]=S,l[f]=S},d;r.includes("Octokit")&&(d=(await import("@octokit/rest")).Octokit);let p;r.includes("createAppAuth")&&(p=(await import("@octokit/auth-app")).createAppAuth);let u=async()=>await Promise.resolve(new jP("axios","moment","faker","assert","pg","Octokit","createAppAuth","OTPAuth","extractCookiesFromResponse","env","setVariable","setPersistentVariable","sendSms","waitForLatestSms","email","sms","ai",r)(UP,BP,i.fakerInstance??DP,FP,HP,d,p,zP,ZS,o,s,c,S=>i.sms.send(S),S=>i.sms.fetchLatest(S),i.email,i.sms,i.ai)),m=!0,h,g;try{h=await D(u(),{milliseconds:e.options.timeoutMs,message:`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`,signal:e.signal})}catch(f){t.error({err:f,env:o,evalCode:r},`[${n}] Error executing code: ${f}`),m=!1,f instanceof hr?g=`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`:g=f instanceof Error?f.message:`${f}`}return{result:h,variableUpdates:a,persistentVariableUpdates:l,success:m,error:g}}async function ey({code:n,fragment:e,context:t,localTools:r,logger:o,signal:i,timeoutMs:a=ar}){let s=$P(),l=await QS(s,{code:n,options:{fragment:e,timeoutMs:a},bindings:t.toObjectCopy(),tools:r,signal:i},o);return y.debug(`[${s}] Got execution result: ${JSON.stringify(l)}`),l}import{createHmac as GP,randomUUID as WP}from"crypto";import VP from"fetch-retry";var qP=VP(global.fetch,{retries:3,retryOn:function(n,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(n){return Math.pow(2,n)*500}}),ty=process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT,ny=process.env.MOMENTIC_LAMBDA_AUTH_SECRET;async function ry({orgId:n,code:e,fragment:t,context:r,timeoutMs:o=ar,retries:i=2,signal:a,logger:s}){if(!ty)throw new Error("GCP_JS_EVAL_FUNCTION_ENDPOINT environment variable not set");let l,c,d=0;if(!ny)throw new Error("Missing lambda auth secret.");let p=GP("sha256",ny).update(n).digest("hex");for(;d<=i;){d++,a?.throwIfAborted();let m={id:WP(),orgId:n,momenticLambdaAuthHash:p,code:e,fragment:t,state:r.toObjectCopy(),timeoutMs:o};try{if(l=await D(qP(ty,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(m)}),{milliseconds:o,message:`Timeout of ${o}ms exceeded for code execution`,signal:a}),!l)throw new Error("Got empty response from code evaluation server");if(!l.ok)throw new Error(`Code evaluation server returned error code ${l.status}`);c=void 0;break}catch(h){c=h}}if(c)throw s.error({err:c},"Failed to evaluate code remotely"),c;if(!l)throw new Error(`An unexpected code evaluation error occurred${c?`: ${c}`:""}`);let u;try{u=bh.parse(await l.json())}catch(m){throw new Error(`Code evaluation server returned invalid response: ${m}`)}if(u.error)throw new Error(`Code evaluation error: ${u.error}`);return u}async function Kn(n){let e;if(process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT)e=await ry(n);else if(n.localTools)e=await ey({...n,localTools:n.localTools});else throw new Error("No code evaluation environment available");if(e.error){let t=`Failed to evaluate code:
|
|
50
50
|
${e.error}
|
|
51
51
|
Code received:
|
|
52
52
|
${n.code}`;throw n.logger.error({err:e.error,code:n.code,env:n.context.toObjectCopy()},t),new Error(t)}if(e.variableUpdates)for(let[t,r]of Object.entries(e.variableUpdates))n.context.setVariable(t,r);if(e.persistentVariableUpdates&&Object.keys(e.persistentVariableUpdates).length>0){await n.callbacks?.onPersistentVariableUpdates?.(e.persistentVariableUpdates);for(let[t,r]of Object.entries(e.persistentVariableUpdates))n.context.setVariable(t,r)}return e.result}import{set as KP}from"lodash-es";async function Ht(n){let{orgId:e,s:t,context:r,logger:o,signal:i,flagStore:a,retries:s=2,timeoutMs:l=ar,allowUndefined:c=!1}=n,d=/{{(.*?)}}/g,p=t.matchAll(d),u=t;for(let m of p){if(m.length<2)continue;let h=m[1].trim(),g;try{g=await Kn({orgId:e,code:h,fragment:!0,context:r,timeoutMs:l,logger:o,retries:s,localTools:n.localTools,signal:i,flagStore:a})}catch(S){throw o.error({err:S,value:t},"Error evaluating template string"),S}if(g===void 0&&!c)throw new R("UserConfigurationError",`Template fragment '${h}' evaluated to undefined. Please ensure that the variable name is spelled correctly and it is only referenced after being assigned a value.`);let f=typeof g=="string"?g:`${g}`;f=f.replaceAll(/\$/g,"$$$$"),u=u.replace(m[0],f)}return u}async function pi(n){return oy(n)}async function oy({obj:n,bannedKeys:e,allowList:t,context:r,prefixPath:o=[],replacements:i=[],...a}){for(let s in n){if(e.includes(s))continue;let l=!1;if(t)if(t.includes(s))l=!0;else continue;let c=n[s],d=[...o,s];if(typeof c=="string"&&c.includes("{{")){let p=await Ht({s:c,context:r,...a});if(c===p)continue;i.push({path:d,original:c}),n[s]=p}else typeof c=="object"&&c!==null&&!Array.isArray(c)&&await oy({obj:c,bannedKeys:e,context:r,prefixPath:d,replacements:i,allowList:l?void 0:t,...a})}return i}function iy(n,e){for(let{path:t,original:r}of e)KP(n,t,r)}import YP from"fetch-retry";var DX=process.env.MAILINATOR_API_KEY,FX=YP(global.fetch,{retryOn:function(n,e,t){return n>3?!1:!!(e!==null||t&&t.status>=400)},retryDelay:function(n){return 500}});import XP from"fetch-cookie";import{cloneDeep as ZP}from"lodash-es";var JP=3e4;async function ml({command:n,logger:e,baseUrl:t,fetchImplementation:r=fetch}){let o=n.timeout??JP/1e3,i=Object.fromEntries(Object.entries(n.headers||{}).filter(([m,h])=>m&&h)),a=new URLSearchParams;Object.entries(n.params||{}).filter(([m,h])=>m&&h).forEach(([m,h])=>{a.append(m,h)});let s=a.toString(),l;if(Bo(n.url)&&(l=n.url),t&&zo(n.url,t)&&(l=new URL(n.url,t).toString()),!l)throw new R("ActionFailureError",`Invalid URL: ${n.url}`);e.debug({url:l,searchParams:s,headers:i,body:n.body,method:n.method},"Making HTTP request");let d=await D((async()=>{let m=s?`${l}?${s}`:l;try{return await r(m,{headers:i,method:n.method,body:n.body})}catch(h){throw e.error({err:h},"Failed to make HTTP request"),new Error(`Failed to make HTTP request: ${h}`)}})(),{milliseconds:o*1e3,fallback:()=>{throw new R("ActionFailureError",`Fetch request timed out after ${o} seconds`)}});if(!d.ok){let m;try{m=await d.text()}catch(h){m=`Failed to read response body: ${h}`}throw new R("ActionFailureError",`Fetch request failed with status ${d.status}: ${m}`)}let p={};d.headers.forEach((m,h)=>{p[h]=m});let u={status:d.status,headers:p};if(d.headers.get("content-type")?.includes("json"))try{u.json=await d.json()}catch{}else d.headers.get("content-type")?.includes("text")&&(u.text=await d.text());return u}async function ay(n){let{fixtures:e,inputs:t}=n,{context:r}=e,{orgId:o,step:i}=t,a=ZP(i);await pi({obj:a,orgId:o,bannedKeys:["code"],...e});let s=await QP(n);return a.envKey&&s.data&&r.setVariable(a.envKey,s.data),s}async function QP(n){let{fixtures:e,inputs:t}=n,{step:r,orgId:o,baseUrl:i}=t,{cookieJar:a}=e,s=new Date;switch(r.type){case"JAVASCRIPT":{let c=await Kn({code:r.code,orgId:o,fragment:!!r.fragment,timeoutMs:r.timeout?r.timeout*1e3:void 0,...e});try{JSON.stringify(c)}catch(d){return{...r,startedAt:s,finishedAt:new Date,status:"FAILED",message:`JavaScript return value is not serializable: ${d instanceof Error?d.message:`${d}`}`}}return{...r,startedAt:s,finishedAt:new Date,message:"JavaScript code executed successfully",status:"SUCCESS",data:c}}case"REQUEST":{let c=XP(fetch,a),d=await ml({command:r,logger:e.logger,baseUrl:i,fetchImplementation:c});return{...r,startedAt:s,finishedAt:new Date,status:"SUCCESS",message:"Request executed successfully",data:d}}default:return(c=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(r)}}async function sy(n){let{inputs:e,fixtures:t,callbacks:r}=n,{signal:o}=t,{steps:i,orgId:a,baseUrl:s}=e,{test:l,step:c}=r,d={startedAt:new Date,status:"RUNNING",results:[]},p=d.results,u=new eL,m={cookieJar:u,...t};for(let h of i){let g=new Date;c.onStarted?.(h.id);let f;try{o?.throwIfAborted(),f=await ay({inputs:{step:h,baseUrl:s,orgId:a},fixtures:m})}catch(S){o?.aborted?f={...h,startedAt:g,finishedAt:new Date,status:"CANCELLED",message:"Step cancelled by user."}:f={...h,startedAt:g,finishedAt:new Date,status:"FAILED",message:`Step failed: ${S instanceof Error?S.message:`${S}`}`}}if(p.push(f),c.onFinished?.({result:f,cookies:Es(u,new URL(s).hostname)}),l.updateAttemptProgress?.({results:p}),f.status!=="SUCCESS"){d.status=f.status==="CANCELLED"?"CANCELLED":"FAILED";break}}return d.status==="RUNNING"&&(d.status="PASSED"),d.finishedAt=new Date,l.onFinished?.(),d}async function ly(n){let{socket:e,storage:t}=n,r=n.socket.id,{testId:o}=e.handshake.query;if(typeof o!="string")throw new Error(`Received invalid test ID that does not parse as a string: ${o}`);let i=await t.getOrgId({type:"api-test",testId:o}),{baseUrl:a,envName:s,environmentVariables:l}=await ep({testId:o,orgId:i,logger:n.logger,storage:t,authorization:n.authorization}),c={type:"api-test",orgId:await n.storage.getOrgId({type:"api-test",testId:o}),testId:o,sessionId:r,latestContext:new It({baseUrl:a||"",currentUrl:a||"",variablesFromEnvironment:l,envName:s})};return fr[r]=c,c}async function ep({testId:n,orgId:e,logger:t,storage:r,authorization:o}){let i=await r.fetchApiTestMetadata(n,e,t);if(!i)throw new Error(`Failed to fetch API test metadata for test ID: ${n}`);let a;o?.type==="API_KEY"&&(a=new gr({httpClient:new Nt({...o,logger:t}),fakerSeed:void 0}));let s=i.envs?.find(p=>p.default),l;s&&(l=await r.fetchEnvironment(e,s.name,t));let c=i.baseUrl||l?.variables?.[Ge];if(!c)throw new Error("Base URL is empty in both API test options and the configured environment");let d={...l?.variables};return{baseUrl:c,envName:l?.name,environmentVariables:d,localCodeEvalTools:a}}var tL=n=>async(e,t)=>{let{steps:r}=e,{authorization:o,metadata:i,socket:a,storage:s,logger:l,flagStoreFactory:c}=n,{orgId:d,testId:p,sessionId:u}=i,m=l.child({testId:p,orgId:d,sessionId:u}),h=fr[u];if(!h)throw new Error(`No api testing session with id ${u} could be found. Please reconnect and try again.`);let g=new AbortController;h.abort=g;let f=h.latestContext,{localCodeEvalTools:S,baseUrl:w}=await ep({testId:p,orgId:d,logger:m,storage:s,authorization:o}),v={context:f,logger:m,localTools:S,signal:g.signal,flagStore:await c(d)},C=await sy({inputs:{steps:r,orgId:d,baseUrl:w},fixtures:v,callbacks:{test:{onFinished:()=>{a.emit("apiTestFinished")}},step:{onStarted:A=>{a.emit("apiStepStarted",A)},onFinished:A=>{a.emit("apiStepFinished",A)}}}});t({result:C})},cy={event:"executeApiTest",createHandler:tL};var nL=({metadata:n,logger:e})=>{let{sessionId:t}=n;return async()=>{e.info({sessionId:t},"Cancel event received");let r=Q.getSession(t);if(!r)throw new Error("No active session found");try{r.controller.setClosed()}catch{}}},dy={event:"cancel",createHandler:nL};var rL=({metadata:n,logger:e})=>{let{sessionId:t}=n;return async(r,o)=>{let i=Q.getSession(t);if(!i)throw new Error("No active session found");i.controller.setOpen();let a=i.controller.browser;try{let l=(await a.getBrowserState({skipWait:!0})).serialize();e.debug({a11yTree:l},"Fetched a11y tree from the browser"),o({a11yTree:l})}catch(s){e.error({err:s},"Error fetching a11y tree from the browser"),o({err:s.message})}}},py={event:"fetchA11yTree",createHandler:rL};var oL=({metadata:n,logger:e})=>{let{sessionId:t}=n;return async(r,o)=>{let i=Q.getSession(t);if(!i)throw new Error("No active session found");i.controller.setOpen();let a=i.controller.browser;try{let s=await a.html();o({html:s})}catch(s){e.error({err:s},"Error fetching DOM from the browser"),s.name==="TimeoutError"?o({err:"Timed out fetching DOM tree. This page may be too large for Momentic to process."}):o({err:s.message})}}},uy={event:"fetchDom",createHandler:oL};var iL=({metadata:n,logger:e})=>{let{sessionId:t,type:r}=n;return o=>{e.info({sessionId:t,reason:o},`Disconnect event received (${o})`),r==="e2e"?Q.removeSession(t,e):r==="api-test"&&delete fr[t]}},my={event:"disconnect",createHandler:iL};function rn(n){let{result:e,nestedResults:t}=n;if(!n.nestedResults.length)return;let{firstMetadata:r,lastMetadata:o}=aL(t);sL(e,r,o);let i=[...n.asyncTasks];n.asyncTasks.push((async()=>{try{await lL(i,e,r,o)}catch(a){n.logger.error({result:n.result,err:a},"Error hoisting scalar result metadata")}})())}function aL(n){let e=n[0],t;for(;;){switch(e.type){case"PRESET_ACTION":{t=e;break}case"CONDITIONAL":if(e.assertion){t=e;break}break;case"AI_ACTION_DYNAMIC":case"AI_ACTION":case"MODULE":case"SECTION":case"IFRAME":if(!e.results.length){t=e;break}e=e.results[e.results.length-1];break;default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e)}if(t)break}let r=n[n.length-1],o;for(;;){switch(r.type){case"PRESET_ACTION":{o=r;break}case"AI_ACTION_DYNAMIC":case"CONDITIONAL":case"AI_ACTION":case"MODULE":case"SECTION":case"IFRAME":if(!r.results.length){o=r;break}r=r.results[r.results.length-1];break;default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(r)}if(o)break}return{firstMetadata:t,lastMetadata:o}}function sL(n,e,t){e&&(n.beforeUrl=e.beforeUrl),t&&(n.afterUrl=t.afterUrl,n.data=t.data,t.status!=="SUCCESS"&&(n.message=t.message))}async function lL(n,e,t,r){await Promise.allSettled(n),t&&(e.beforeSnapshot=t.beforeSnapshot),r&&(e.afterSnapshot=r.afterSnapshot)}import Ia from"os";import cL from"v8";var hy,Ln,dL=Ia.platform(),pL=Ia.cpus().map(n=>({model:n.model,speed:n.speed}));function gy(n){let e=()=>{try{let t=!1,r=uL(),o=mL();r.freeMemory<1e6&&(t=!0);let i=cL.getHeapStatistics(),a=i.used_heap_size,s=i.heap_size_limit;a/s>.9&&(t=!0),t?n.warn({memory:r,cpu:o,heapStats:i},"Critical resource usage metrics detected"):n.debug({memory:r,cpu:o},"Got machine resource usage metrics")}catch{}};return e(),{interval:setInterval(e,1e4),cpuMetadata:pL,platform:dL}}function uL(){let n=Ia.totalmem(),e=Ia.freemem(),t=n-e;return{totalMemory:n,freeMemory:e,usedMemory:t}}function mL(){let n=Ia.cpus(),e=Date.now(),t={measurementTime:e,user:0,nice:0,sys:0,idle:0,irq:0,total:0};for(let o of n)t.user+=o.times.user,t.nice+=o.times.nice,t.sys+=o.times.sys,t.idle+=o.times.idle,t.irq+=o.times.irq;if(t.total=t.user+t.nice+t.sys+t.idle+t.irq,!Ln)return Ln=t,null;let r={user:t.user-Ln.user,nice:t.nice-Ln.nice,sys:t.sys-Ln.sys,idle:t.idle-Ln.idle,irq:t.irq-Ln.irq,total:t.total-Ln.total};return hy={measurementTime:e,intervalMs:e-Ln.measurementTime,user:r.user/r.total*100,nice:r.nice/r.total*100,sys:r.sys/r.total*100,idle:r.idle/r.total*100,irq:r.irq/r.total*100,total:100-r.idle/r.total*100},Ln=t,hy}import{hostname as yL}from"os";async function Sy(n){let{command:e,tracer:t,timeoutMs:r,targetingWrapper:o,disableCache:i,fixtures:a}=n,{logger:s,abortSignal:l}=a;if(e.target&&!rr(e.target))throw new Error("Element assertion with x/y is not supported yet");let c=e.assertion.type==="ELEMENT_EXISTENCE"&&e.assertion.negated&&(e.assertion.condition==="EXISTS"||e.assertion.condition==="VISIBLE"),d=Date.now(),p=0,u,m=500;for(;p<2||Date.now()-d<r;){p++,p>1&&await ne(m,l),l?.throwIfAborted();try{let{newTarget:h,elementInteractedDisplayString:g,result:f}=await o({ctx:a.ctx,tracer:t,command:e,target:e.target,cache:e.cache?.target,action:async S=>hL(S.locator,n),options:{disableCache:i,useSelector:!!e.useSelector,iframeUrl:e.iframeUrl,disableGlobalLocatorRedirect:!0,source:Or(e)}});if(u={success:f.success,data:f.data,err:f.err,newTarget:h,elementInteractedDisplayString:g},!f.success){u=f,m=Math.min(m*2,1e4);continue}return u}catch(h){if(l?.throwIfAborted(),c)return{success:!0,thoughts:`The element described does not exist on the page: ${h.message}`};if(s.warn({err:h},"Element assertion ended in error, retrying..."),!(h instanceof R)||h.reason!="ActionFailureError")throw h;u={success:!1,err:h}}}if(!u)throw new Error(`Failed to evaluate manual element assertion in ${r}ms.`);return u}async function hL(n,{command:e,fixtures:t}){let r=e.assertion;await t.browser.highlight(n);let o=!0,i,a;switch(r.type){case"ELEMENT_CONTENT":{let s=await n.textContent()??"";if(a={elementTextContent:ze(s,500,!0)},!fy(s,r.value,r.operation,!!r.negated)){let l=r.negated?lr[r.operation]:cr[r.operation];o=!1,i=new R("AssertionFailureError",`The content ${l} '${r.value}': ${s}`)}break}case"ELEMENT_ATTRIBUTE":{a={elementOuterHtml:ze(await n.evaluate(l=>l.cloneNode(!1).outerHTML),500,!0)};let s;try{s=await n.getAttribute(r.attr,{timeout:3e3})??""}catch(l){i=new R("AssertionFailureError",`The element does not have an attribute named ${r.attr}: ${l}`),o=!1;break}if(!fy(s,r.value,r.operation,!!r.negated)){let l=r.negated?lr[r.operation]:cr[r.operation];o=!1,r.operation==="EXISTS"?i=r.negated?new R("AssertionFailureError",`The attribute ${r.attr} ${l}: ${s}`):new R("AssertionFailureError",`The attribute ${r.attr} ${l}`):i=new R("AssertionFailureError",`The attribute ${r.attr} ${l} '${r.value}': ${s}`)}break}case"ELEMENT_EXISTENCE":{switch(r.condition){case"VISIBLE":{o=await n.evaluate(async(l,c)=>{let d=Date.now();for(;Date.now()-d<c;){let p=l.getBoundingClientRect();if(p.width>0&&p.height>0)return!0;await new Promise(u=>setTimeout(u,250))}return!1},En*1e3);break}case"EDITABLE":{o=await n.isEditable({timeout:En*1e3});break}case"EXISTS":{o=!0;break}case"ENABLED":{o=await n.isEnabled({timeout:En*1e3});break}default:return(l=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(r.condition)}if(o=r.negated?!o:o,!o){let s=r.negated?md[r.condition]:hd[r.condition];i=new R("AssertionFailureError",`The element ${s}`)}break}}return{success:o,data:a,err:i}}function fy(n,e,t,r){let o;switch(t){case"CONTAINS":{o=n.includes(e);break}case"EQUALS":{o=n.trim()===e.trim();break}case"STARTS_WITH":{o=n.trim().startsWith(e);break}case"EXISTS":{o=n.trim().length>0;break}default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(t)}return r?!o:o}import{Jimp as gL}from"jimp";async function Pa(n,e){let t=await n.screenshot(e),r=await gL.fromBuffer(t);return{buffer:t,width:Math.ceil(r.bitmap.width??0),height:Math.ceil(r.bitmap.height??0)}}import{Jimp as yy}from"jimp";import tp from"jpeg-js";import fL from"pixelmatch";async function by({ctx:n,tracer:e,command:t,disableCache:r,browser:o,targetingWrapper:i,logger:a,screenshotStorage:s}){if(t.target&&!rr(t.target))throw new Error("Visual Diff with x/y is not supported yet");await o.waitForDOMStability({logger:a});let l={clearHighlights:!0,hideCaret:!0},c;t.target?.elementDescriptor?c=(await i({ctx:n,tracer:e,command:t,target:t.target,cache:t.cache?.target??t.target?.a11yData,action:async U=>Pa(o,{locator:U.locator,...l}),options:{disableCache:!!r,useSelector:!!t.useSelector,iframeUrl:t.iframeUrl,disableGlobalLocatorRedirect:!0}})).result:c=await Pa(o,l);let d=await s.prepareGoldenScreenshotForComparison(a,t,c);if((c.height!==d.height||c.width!==d.width)&&a.debug({currHeight:c.height,currWidth:c.width,savedHeight:d.height,savedWidth:d.width},"Mismatched before and after visual diff screenshot sizes"),Math.abs(c.height-d.height)>10||Math.abs(c.width-d.width)>10){let j=`${c.width}x${c.height}`,U=`${d.width}x${d.height}`;return{fail:!0,thoughts:`Current screenshot (${j}) does not match saved screenshot dimensions (${U}) - did you change the size of the target or the viewport?`,beforeScreenshotOverride:d.buffer,afterScreenshotOverride:c.buffer,succeedImmediately:!1,urlAfterCommand:o.url()}}let p=await yy.fromBuffer(c.buffer),u={width:c.width,height:c.height},m=await yy.fromBuffer(d.buffer),h={width:d.width,height:d.height},g,f=u.width*u.height,S=h.width*h.height,w=Math.abs(u.height-h.height),v=Math.abs(u.width-h.width);if(f>S){let j=p.cover({w:h.width,h:h.height});c.buffer=await j.getBuffer("image/jpeg"),g="current",c.width=h.width,c.height=h.height}else if(S>f){let j=m.cover({w:u.width,h:u.height});d.buffer=await j.getBuffer("image/jpeg"),g="saved"}let b={data:Buffer.alloc(c.width*c.height*4),width:c.width,height:c.height},T=t.threshold??.1,A=fL(tp.decode(d.buffer).data,tp.decode(c.buffer).data,b.data,c.width,c.height,{threshold:T,diffColorAlt:[0,255,0]})/(c.width*c.height)*100,k=A>T*100,L=`Visual diff of ${A.toFixed(2)}% detected, which is ${k?"over":"under"} the threshold of ${T*100}%.`;if(g&&(L+=` The ${g} screenshot was cropped since it was taller by ${w} pixels and wider by ${v} pixels.`),k)throw new R("ActionFailureError",L);return{fail:k,thoughts:L,beforeScreenshotOverride:c.buffer,afterScreenshotOverride:tp.encode(b,75).data,succeedImmediately:!1,urlAfterCommand:o.url()}}var SL=5e3;async function hl({timeout:n=En,...e}){let t=Date.now(),r=n*1e3,o=r+1e4,i,a=0,s=500;for(;a-t<r;){if(Date.now()-t>o){e.logger.warn("Exceeded max system timeout for page assertion, exiting...");break}e.signal.throwIfAborted();let l=Date.now();i=await wy(e),a=Date.now();let c=a-l;if(c>1e3&&e.logger.warn({pageAssertDuration:c},"Page assertion took longer than expected"),!i.success)await ne(s,e.signal),s=Math.min(Math.floor(s*1.5),SL);else return i}return i=await wy(e),i}async function wy({assertion:n,browser:e,flagStore:t}){switch(n.type){case"CONTENT":{let o,i=!1,a;try{let s;if(t.isBooleanFlagEnabled("auto_expand_iframes")){let l=await e.evaluateFunctionInAllFrames(vy,{value:n.value,negated:!!n.negated,returnHtml:!1});i=n.negated?l.every(c=>c.evaluation):l.some(c=>c.evaluation),s=l.find(c=>c.pageHtml)?.pageHtml}else({evaluation:i,pageHtml:s}=await e.evaluateFunctionInPage(vy,{value:n.value,negated:!!n.negated,returnHtml:!0},"checking page content"));if(!i){let l=n.negated?lr.CONTAINS:cr.CONTAINS;a=new R("AssertionFailureError",`The page ${l} '${n.value}'.`),o=s}}catch(s){a=new R("AssertionFailureError",`Failed to evaluate page content assertion: ${s instanceof Error?s.message:`${s}`}`)}return{success:i,err:a,data:i||!o?void 0:{pageContent:o}}}default:return(o=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n.type)}}function vy({value:n,negated:e,returnHtml:t}){let r=document.documentElement.outerHTML,o=r.includes(n)===!e;return r.length>1e4&&(r=r.slice(0,1e4)+"...TRUNCATED"),{evaluation:o,pageHtml:!o&&t?r:void 0}}var np=async n=>{let{step:e,resolvedInputs:t}=n.moduleParams,{logger:r,context:o,storage:i,codeEvalTools:a,controller:s}=n.fixtures,l=s.browser,{orgId:c,runId:d}=n.inputs,p=s.executeAbortController.signal;Object.keys(t).length>0&&(o.setInputs(t),r.debug({inputs:t,moduleId:e.moduleId},"Set module inputs"));let u,m=!1,h,g;if(e.cacheConfig||e.defaultCacheAllInvocations){let f=e.cacheConfig?.cacheKey||e.defaultCacheKey||"",S=await Ht({orgId:c,s:f,context:o,logger:r,localTools:a,signal:p,flagStore:s.flagStore});g={orgId:c,cacheKeys:[S,...Object.entries(t).map(([v,b])=>`${v}:${b}`)]},r.debug({original:f,keyParams:g},"Module cache key params");let w=Date.now();for(;Date.now()-w<Kh;){p?.throwIfAborted();let v=await i.getCacheResult(g);if(v){r.debug({cacheResult:v},"Got result from module execution cache"),u=gl(e,t,"SUCCESS"),u.message="Used cached module result.",u.data=JSON.parse(v),m=!0;break}else r.debug({cacheKey:f,keyParams:g},"No cache result found, continuing with lock acquisition");let b=await i.acquireCacheLock({keyParams:g,clientMetadata:`hostName:${yL()};runId:${d}`},p);if(b.acquired){h=b.keyPrefix,r.info({cacheKeyPrefixIfLockAcquired:h,cacheKey:f,keyParams:g},"Acquired cache lock and proceeding with module execution");break}else r.debug({cacheKeyPrefixIfLockAcquired:h,cacheKey:f,keyParams:g},"Failed to acquire cache lock, retrying...");await ne(2500+Math.random()*1e4,p)}}try{if(!u)u=await bL(n);else if(e.autoAuth){let f=Ts.safeParse(u.data);if(!f.success)throw new R("UserConfigurationError",`Cached authentication module result is not a valid storage state: ${f.error.message}`);r.debug("Automatically loading auth state after cached module result"),await l.loadAuthState(f.data);let S=!1,w=e.advanced?.cacheInvalidation;if(w&&w.type==="PAGE_CHECK"){let v={type:"CONTENT",value:w.substring},b=await hl({timeout:En,assertion:v,browser:l,flagStore:s.flagStore,logger:r,signal:p});b.success?r.debug({invalResult:b},"Cached result still valid after page check, continuing..."):(r.info({invalResult:b},"Invalidating cached result due to page check failure"),S=!0)}if(g&&S)return await i.deleteCacheResult(g),np(n)}}finally{try{h!==void 0&&!m&&u?.status==="SUCCESS"&&await wL({step:e,result:u,browser:s.browser,cacheKeyPrefix:h,logger:r,storage:i})}finally{h!==void 0&&await i.releaseCacheLock(h)}}return u},bL=async n=>{let{step:e,tracer:t}=n.moduleParams,r=gl(e,n.moduleParams.resolvedInputs,"SUCCESS"),o=await t.startSubSteps(),{status:i,results:a}=await Sr(n.work,()=>n.executeStepList({...n,listParams:{steps:e.steps,containerName:`module ('${e.name}')`,tracer:o}}));return r.results=a,r.status=i,r.finishedAt=new Date,rn({asyncTasks:n.work.asyncTasks,nestedResults:a,result:r,logger:n.fixtures.logger}),r};function gl(n,e,t){let r={};return Object.entries(e).forEach(([i,a])=>{r[i]=JSON.stringify(a)}),{type:"MODULE",id:n.id,moduleId:n.moduleId,moduleName:n.name,startedAt:new Date,cacheConfig:n.cacheConfig,inputs:r,results:[],finishedAt:new Date,status:t}}async function xy({orgId:n,step:e,context:t,logger:r,flagStore:o,codeEvalTools:i,signal:a}){let s={};try{for(let l of e.parameters??[]){let c=e.inputs?.[l]??e.defaultParameters?.[l];if(!c){r.warn(`No value or default found for parameter '${l}' that is required by module '${e.name}'`);continue}s[l]=await Kn({orgId:n,code:c,fragment:!0,context:t,logger:r,localTools:i,signal:a,flagStore:o})}return s}catch(l){throw a?.throwIfAborted(),new R("UserConfigurationError",`Failed to evaluate module inputs: ${l}`)}}async function wL({step:n,result:e,browser:t,cacheKeyPrefix:r,logger:o,storage:i}){let a=n.cacheConfig?.cacheExpiryMs;(!a||a===Cg)&&(a=n.defaultCacheTtl??Rg);let s;n.autoAuth?s=JSON.stringify(await t.saveAuthState()):e.data!==void 0?s=JSON.stringify(e.data):s='""',o.debug({cacheKeyPrefix:r,ttlMs:a,truncatedCacheResultJson:Zg(s)},"Setting module cache result"),await i.setCacheResult({result:s,keyPrefix:r,ttlMs:a})}async function yr(n,e,t){let r=new Date;try{return t.throwIfAborted(),await e()}catch(o){let i=new Date,a="FAILED",s;if(t.aborted||o instanceof DOMException&&o.name==="AbortError"?(s="Step aborted by user.",a="CANCELLED"):o instanceof R?s=`${o}`:s=`An unexpected error occurred: ${o.message}`,n.type==="RESOLVED_MODULE"){let l=gl(n,{},"FAILED");return l.message=s,l.startedAt=r,l.finishedAt=i,l}return{...zs(n),startedAt:r,finishedAt:i,status:a,data:null,message:s,results:[]}}}async function Sr(n,e){let t=!1;try{return n&&!n.state.failureRecoveryDisabled&&(n.state.failureRecoveryDisabled=!0,t=!0),await e()}finally{n&&t&&(n.state.failureRecoveryDisabled=void 0)}}import{randomUUID as Ty}from"crypto";import{cloneDeep as xL}from"lodash-es";function fl(n,e){n.state.healingDetails?n.state.healingDetails.push(e):n.state.healingDetails=[e]}var Sl=async n=>{let{step:e,tracer:t}=n.presetParams,{logger:r,controller:o,context:i,billingReporter:a}=n.fixtures,{collectDebugData:s}=n.options,{testMetadata:l,suiteMetadata:c}=n.inputs,d=e.command.type,p=r.child({commandType:d,stepId:e.id,commandId:e.command.id}),u=Qi(e.command);n.work.asyncTasks.push(a.reportCreditsUsed(p,d,u,{testId:l?.id,testName:l?.name,suiteId:c?.id,suiteName:c?.name}));let m=o.browser.url(),h=new Date,g,f=Ty(),S=Ty();if(s)try{g=await o.browser.screenshot({retries:1,clearHighlights:!0});let C=await o.browser.getRawCondensedHtml();t.attachBeforeHtmlSnapshot({logger:p,snapshotId:f,html:C}),n.work.asyncTasks.push(n.fixtures.debugDataStorage.storeHtmlSnapshot(p,f,C))}catch(C){p.debug({err:C},"Failed to take screenshot before step, likely because the page is still loading. This is non-fatal and does not affect the test.")}let w,v,b,T=bs();try{let C=await o.executePresetCommand(T,t,e.command,i,l?.advanced.disableAICaching??!1);C.beforeScreenshotOverride&&(g=C.beforeScreenshotOverride),b=C.afterScreenshotOverride;let{proposedStep:A}=TL({work:n.work,step:e,newTargets:C.newTargets,logger:p}),k=new Date,L=o.browser.url();v={beforeUrl:m,afterUrl:L,startedAt:h,finishedAt:k,viewport:o.browser.getViewport(),status:C.fail?"FAILED":"SUCCESS",elementInteracted:C.elementInteracted},w={...e,message:C.thoughts??EL(C.newTargets)??"Successfully executed preset action.",beforeUrl:m,afterUrl:L,finishedAt:k,startedAt:h,status:C.fail?"FAILED":"SUCCESS",data:C.data,results:[v],details:T.details,proposedStep:A},"assertion"in e.command&&(w.message=C.thoughts||"Assertion passed.")}catch(C){p.error({message:C.message,stack:C.stack},`Failed executing preset step ${jr(e.command)}`);let A=o.browser.url(),k=new Date,L=C instanceof Error?C.message:`${C}`;C instanceof R&&C.getLastScreenshotBuffer()&&(b=C.getLastScreenshotBuffer()),v={beforeUrl:m,afterUrl:A,startedAt:h,finishedAt:k,viewport:o.browser.getViewport(),status:C instanceof DOMException&&C.name==="AbortError"?"CANCELLED":"FAILED",message:L},w={...e,startedAt:h,finishedAt:k,beforeUrl:m,afterUrl:A,status:C instanceof DOMException&&C.name==="AbortError"?"CANCELLED":"FAILED",message:L,failureReason:C instanceof R?C.reason:void 0,results:[v],details:T.details}}if(s)try{b||(b=await o.browser.screenshot({retries:1}));let C=await o.browser.getRawCondensedHtml();t.attachAfterHtmlSnapshot({logger:p,snapshotId:S,html:C}),n.work.asyncTasks.push(n.fixtures.debugDataStorage.storeHtmlSnapshot(p,S,C))}catch(C){p.debug({err:C},"Failed store debug data after step, likely because the page is still loading. This is non-fatal and does not affect the test.")}return v.beforeSnapshot=f,w.beforeSnapshot=f,v.afterSnapshot=S,w.afterSnapshot=S,g&&(t.attachBeforeScreenshot({logger:p,snapshotId:f,screenshot:g}),n.work.asyncTasks.push(n.fixtures.debugDataStorage.storeScreenshot(p,f,g))),b&&(t.attachAfterScreenshot({logger:p,snapshotId:S,screenshot:b}),n.work.asyncTasks.push(n.fixtures.debugDataStorage.storeScreenshot(p,S,b))),w};function TL({work:n,step:e,newTargets:t,logger:r}){if(!t?.length)return{proposedStep:void 0};let o=e.command;Wg(o,t,r);let i=t[0]?.description;if(i&&"target"in o&&o.target&&o.target.type==="description"){let a={...o,target:{...o.target,elementDescriptor:i}},s={...xL(e),command:a};return fl(n,{type:"DESCRIPTION_UPDATE",thoughts:`Updated element description after the original element could not be found on the page. New element location reasoning: ${t[0]?.thoughts}`}),{proposedStep:s}}return{proposedStep:void 0}}function EL(n){if(n?.length){if(n.length===1&&n[0]?.thoughts)return n[0].thoughts;if(n.length===2&&n.every(e=>e.thoughts))return`Located first element: ${n[0]?.thoughts}
|
|
@@ -3810,7 +3810,7 @@ ${a.stack}`),l.status(500).send("Internal Server Error")}),n){let a=nv.static(n,
|
|
|
3810
3810
|
for /f "tokens=5" %a in ('netstat -ano ^| findstr :58888') do taskkill /PID %a /F
|
|
3811
3811
|
`)}import Zk from"events";import ic from"fs";import Qk from"open";import oc from"path";import{fileURLToPath as e_}from"url";import nk from"diff-lines";import{gt as rk}from"semver";import{execSync as UN}from"child_process";import{platform as BN}from"os";function Jp(){return av()?(y.dimmed("Setting device pixel ratio to 2 automatically since a Mac OS Retina screen was detected."),y.dimmed(`If you are using a low pixel-density monitor, you should manually set --pixel-ratio to 1 to avoid incorrect viewport calculations. Confirm your device's pixel-ratio at https://www.mydevice.io.
|
|
3812
3812
|
`),2):(y.dimmed("Setting device pixel ratio to 1."),y.dimmed(`If you are using Momentic on a high-pixel density (HiDPI) monitor, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations. Confirm your device's pixel-ratio at https://www.mydevice.io.
|
|
3813
|
-
l.`),1)}function av(){return BN()==="darwin"&&UN("system_profiler SPDisplaysDataType").toString().includes("Retina")}function Xp(n){av()&&n===1&&(y.warn("If you are using Momentic on a Retina screen, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations."),y.warn("Confirm your device's pixel-ratio at https://www.mydevice.io."))}import zN from"@actions/exec";import HN from"@actions/io";import jN from"quote";import $N from"string-argv";async function sv(n,e=!0){let t=$N(n),r=await HN.which(t[0],!0),o=t.slice(1),i=zN.exec(jN(r),o,{delay:100});if(e)return i}import{existsSync as GN,statSync as WN}from"fs";var xi=!!process.env.CI||!!process.env.GITHUB_ACTIONS||!!process.env.GITHUB_RUN_ID||!!process.env.GITLAB_CI||!!process.env.CI_COMMIT_SHA||!!process.env.JENKINS_URL||!!process.env.BUILD_NUMBER||!!process.env.JENKINS_HOME||!!process.env.CIRCLECI||!!process.env.CIRCLE_BUILD_NUM||!!process.env.TRAVIS||!!process.env.TRAVIS_BUILD_NUMBER||!!process.env.BITBUCKET_BUILD_NUMBER||!!process.env.BITBUCKET_COMMIT||!!process.env.CODEBUILD_BUILD_ID||!!process.env.TF_BUILD||!!process.env.BUILD_BUILDID||!!process.env.AGENT_ID||!!process.env.BUILDER_SA_EMAIL||!!process.env.HEROKU_TEST_RUN_ID||!!process.env.CI_NODE_INDEX||!!process.env.TEAMCITY_VERSION||!!process.env.BUILD_VCS_NUMBER||!!process.env.BUILDKITE||!!process.env.BUILDKITE_BUILD_NUMBER||!!process.env.APPVEYOR||!!process.env.APPVEYOR_BUILD_NUMBER||!!process.env.DRONE||!!process.env.DRONE_BUILD_NUMBER||!!process.env.SHIPPABLE||!!process.env.BUILD_URL||!!process.env.SEMAPHORE||!!process.env.SEMAPHORE_EXECUTABLE_UUID||!!process.env.WOODPECKER||!!process.env.CI_BUILD_NUMBER||!!process.env.WERCKER_MAIN_PIPELINE_STARTED||!!process.env.BUDDY_EXECUTION_ID;function lv(n){try{return GN(n)&&WN(n).isDirectory()}catch(e){return y.error({err:e},`Error reading path ${n} during directory existence check`),!1}}import VN from"csv-parser";import{createReadStream as qN}from"fs";function Zp(n){return new Promise((e,t)=>{let r=[];qN(n).pipe(VN()).on("data",o=>r.push(o)).on("end",()=>e(r)).on("error",o=>t(o))})}import Hl from"semver";import{z as jl}from"zod";var wn="2.3.3",KN="https://registry.npmjs.org/momentic",YN=jl.object({versions:jl.record(jl.string(),jl.unknown()).optional()});async function cv(n){try{await JN(n)}catch(e){y.warn({err:e},"Failed to check CLI version against NPM servers")}}async function JN(n){if(!wn){n.warn("Unable to check CLI version because CLI_VERSION is not set");return}let e;for(let r=0;r<2;r++)try{let o=await D(fetch(KN),{milliseconds:5e3});if(!o.ok)throw new Error(`Got error status code ${o.statusText}`);let i=await o.json();e=YN.parse(i).versions;break}catch(o){n.warn({err:o},"Failed to fetch npm registry data")}if(!e){n.warn("Failed to fetch npm registry data. Skipping version check.");return}let t;for(let r of Object.keys(e))Hl.valid(r)&&(!t||Hl.gt(r,t))&&Hl.gt(r,wn)&&Hl.lt(r,"2.0.0")&&!r.includes("alpha")&&(t=r);t&&(y.warn(`Update available: v${wn} -> v${t}`),y.warn("This version may be missing critical fixes, features, and security updates."),y.warn(`Run "npx momentic@${t} -V" to update`))}import{existsSync as ZN,mkdirSync as QN,statSync as ek}from"fs";import{dirname as tk}from"path";import pv from"readline/promises";import{hostname as XN}from"os";var ee=Dl({app:"cli",clientToken:"pub7eb923f18fb3f1d42ac5eba8c5ea13a5",hostname:XN(),disableConsoleLogs:!0}).child({version:"2.3.3"});var Qp=!1,uv=(()=>{try{return ek("/.dockerenv"),!0}catch{return!1}})();async function ft(n,e){if(xi||Qp||uv)return!0;ee.flush(),await new Promise(a=>setTimeout(a,500));let t=pv.createInterface({input:process.stdin,output:process.stdout}),r=n.split("."),o;if(r.length===1)o=n;else{let a=`${r.slice(0,r.length-1).join(".").trim()}.`;e?y.warn(a):y.log(a),o=r[r.length-1].trim()}let i=await t.question(`${o} ('y' for yes / n for no / 'A' to accept all) `);return t.close(),i==="A"?(Qp=!0,setTimeout(()=>{Qp=!1},3e3),!0):i.toLowerCase()==="y"}async function eu(n){let e=tk(n);return lv(e)?ZN(n)?ft(`File '${dv(n)}' already exists. Overwrite existing content?`,!0):!0:await ft(`Directory '${dv(e)}' doesn't exist. Create it now?`,!0)?(QN(e,{recursive:!0}),!0):!1}function dv(n){return n.replace(/(\s+)/g,"\\$1")}async function mv(n,e){if(xi||uv)return e;let t=pv.createInterface({input:process.stdin,output:process.stdout}),r=await t.question(`${n} `);return t.close(),r.trim()||e}async function hv({test:n,fragment:e,entities:t,client:r,logger:o,yes:i}){rk(e.schemaVersion,_e)&&(y.error(`This version of the CLI does not support the schema version of the fragment (${e.schemaVersion}). Please update to the latest version of the CLI and retry this command.`),process.exit(1)),Gg(e.steps).forEach(g=>{t.modules[g]||(y.error(`The test patch contains a module with id ${g} that could not be found in the current project. This suggests that either this test patch or your local file system may be out of date.`),process.exit(1))}),e.createdAt.getTime()<Date.now()-7*24*60*60*1e3&&!i&&!await ft("The test patch you are applying is more than 7 days old. Are you sure you want to continue?",!0)&&process.exit(1);let s=n.lastModified.getTime();e.createdAt.getTime()+60*60*1e3<s&&!i&&!await ft("The test patch you are applying was created before the test was last updated. Are you sure you want to continue?",!0)&&process.exit(1);let l=Xr(n.fullFilePath,o,t),c=l.steps;if(!Array.isArray(c))throw new Error(`Test ${n.fullFilePath} is missing steps array`);let d,p;if(e.schemaVersion!==_e){let{steps:g,newVersion:f}=await oa({metadata:{id:e.id,schemaVersion:e.schemaVersion},steps:e.steps,logger:y});d=f,p=Ie.array().parse(g)}else p=Ie.array().parse(e.steps);let{stepsToSave:u,moduleUpdates:m}=await Zt({stepLists:{steps:p}});u.beforeSteps=l.beforeSteps??void 0,u.afterSteps=l.afterSteps??void 0;let h=nk(JSON.stringify(c,void 0,2),JSON.stringify(u,void 0,2),{n_surrounding:5});y.dimmed("=".repeat(30)),y.dimmed(h),y.dimmed("=".repeat(30)),y.dimmed(""),d&&y.warn(`If this patch is applied, your test will also be automatically upgraded to the latest schema version (${d}). Schema upgrades have no impact on functionality, although you may notice minor differences in the test YAML.`),!i&&!await ft("Do you want to apply this patch?")&&(y.dimmed("Cancelled."),process.exit(1)),Wn({relativeTestPath:n.relativePath,steps:u,schemaVersion:d??e.schemaVersion,project:t.project}),y.success("Patch applied successfully."),await r.patchTestFragment(e.id,{applied:!0,appliedAt:new Date})}import{randomUUID as po}from"crypto";import{z as _v}from"zod";var jt=" ".repeat(6);import kv from"chalk";import{Argument as lo,Option as Oe}from"@commander-js/extra-typings";import{validateHeaderValue as ok}from"http";import{cpus as gv}from"os";import{parse as wme}from"yaml";import{z as q}from"zod";var $l=58888,tu=30*60*1e3,Jn=new Oe("--api-key <key>","API key for authentication. If not supplied, attempts to read the MOMENTIC_API_KEY env var."),Xn=new Oe("--server <server>","Momentic server to use. Leave unchanged unless using Momentic on-premise."),co=new Oe("-y, --yes","Skip all confirmation prompts.").env("CI"),nu=new Oe("-w, --wait","Wait for tests to finish running before exiting. Only applicable when running tests remotely").implies({remote:!0}),ru=new Oe("--wait-timeout <waitTimeout>",`The maximum number of seconds to wait for tests to complete. Only applicable when the --wait option is specified. Defaults to ${tu/1e3} seconds.`),Gl=new Oe("--custom-headers <customHeaders...>","Specify custom headers in the form HEADER=VALUE to be sent with each request during the test. Multiple entries can be provided."),Sv=new Oe("--reporter <reporter>","Output report files in a standardized format to a local directory. See the --reporter-dir flag for information on the output directory.").choices(Object.values(Yi)),yv=new Oe("--reporter-dir <reporterDir>","Output directory to store report files. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. Defaults to 'reports' if unset."),ou=new Oe("--output-dir <outputDir>","[Alpha] Output directory to store run artifacts such as screenshots, results, and logs. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. This directory will be cleared at the start of execution."),bv=new Oe("--upload-results","Upload test results to Momentic Cloud. By default, this option is disabled."),wv=new Oe("--include <includePatterns...>","Only include tests that match the provided regex patterns. Multiple patterns can be provided. The patterns will be matched against the test file paths and the pattern only needs to match a part of the path for the test to be included."),vv=new Oe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),iu=new Oe("--pixel-ratio <pixelRatio>","Device pixel ratio of your screen or monitor. Mac OS Retina displays and machines marketed as 'HiDPI' should set this to 2. Visit https://www.mydevice.io/ to find your device's pixel ratio."),xv=new Oe("--port <port>",`Port to run the app on. Defaults to ${$l}.`),au=new Oe("--input-csv <inputCsv>","Path to a CSV file on disk where each row represents a set of inputs that will be made available to all tests that are ran. The first line of the CSV must be the input names."),Wl=new Oe("--env <env>","Name of the environment to use when running tests."),Vl=new Oe("--url-override <urlOverride>","Fully qualified url (e.g. https://www.google.com) to start all tests from. Overrides any default starting url set from the test or environment."),Tv=new Oe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(n=>parseInt(n,10)),Fn=new Oe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file (*.momentic.config.yaml)"),su=new Oe("-f, --filter <filter>","Run tests within the project that has a name equal to the filter provided. This option cannot be used together with file path or directory arguments, but substring matches are allowed."),Ev=new Oe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(n=>parseInt(n,10)),Cv=new Oe("--fix","Attempt to fix any issues found. This option will write changes to your local file system."),lu=new Oe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on the protected branches configured in the momentic.config.yaml.").env("CI"),cu=new Oe("--disable-cache","Disable caching of test results. This will cause all tests to be re-run every time."),Rv=new lo("<tests...>",`One or more test paths to queue on Momentic Cloud.
|
|
3813
|
+
l.`),1)}function av(){return BN()==="darwin"&&UN("system_profiler SPDisplaysDataType").toString().includes("Retina")}function Xp(n){av()&&n===1&&(y.warn("If you are using Momentic on a Retina screen, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations."),y.warn("Confirm your device's pixel-ratio at https://www.mydevice.io."))}import zN from"@actions/exec";import HN from"@actions/io";import jN from"quote";import $N from"string-argv";async function sv(n,e=!0){let t=$N(n),r=await HN.which(t[0],!0),o=t.slice(1),i=zN.exec(jN(r),o,{delay:100});if(e)return i}import{existsSync as GN,statSync as WN}from"fs";var xi=!!process.env.CI||!!process.env.GITHUB_ACTIONS||!!process.env.GITHUB_RUN_ID||!!process.env.GITLAB_CI||!!process.env.CI_COMMIT_SHA||!!process.env.JENKINS_URL||!!process.env.BUILD_NUMBER||!!process.env.JENKINS_HOME||!!process.env.CIRCLECI||!!process.env.CIRCLE_BUILD_NUM||!!process.env.TRAVIS||!!process.env.TRAVIS_BUILD_NUMBER||!!process.env.BITBUCKET_BUILD_NUMBER||!!process.env.BITBUCKET_COMMIT||!!process.env.CODEBUILD_BUILD_ID||!!process.env.TF_BUILD||!!process.env.BUILD_BUILDID||!!process.env.AGENT_ID||!!process.env.BUILDER_SA_EMAIL||!!process.env.HEROKU_TEST_RUN_ID||!!process.env.CI_NODE_INDEX||!!process.env.TEAMCITY_VERSION||!!process.env.BUILD_VCS_NUMBER||!!process.env.BUILDKITE||!!process.env.BUILDKITE_BUILD_NUMBER||!!process.env.APPVEYOR||!!process.env.APPVEYOR_BUILD_NUMBER||!!process.env.DRONE||!!process.env.DRONE_BUILD_NUMBER||!!process.env.SHIPPABLE||!!process.env.BUILD_URL||!!process.env.SEMAPHORE||!!process.env.SEMAPHORE_EXECUTABLE_UUID||!!process.env.WOODPECKER||!!process.env.CI_BUILD_NUMBER||!!process.env.WERCKER_MAIN_PIPELINE_STARTED||!!process.env.BUDDY_EXECUTION_ID;function lv(n){try{return GN(n)&&WN(n).isDirectory()}catch(e){return y.error({err:e},`Error reading path ${n} during directory existence check`),!1}}import VN from"csv-parser";import{createReadStream as qN}from"fs";function Zp(n){return new Promise((e,t)=>{let r=[];qN(n).pipe(VN()).on("data",o=>r.push(o)).on("end",()=>e(r)).on("error",o=>t(o))})}import Hl from"semver";import{z as jl}from"zod";var wn="2.3.4",KN="https://registry.npmjs.org/momentic",YN=jl.object({versions:jl.record(jl.string(),jl.unknown()).optional()});async function cv(n){try{await JN(n)}catch(e){y.warn({err:e},"Failed to check CLI version against NPM servers")}}async function JN(n){if(!wn){n.warn("Unable to check CLI version because CLI_VERSION is not set");return}let e;for(let r=0;r<2;r++)try{let o=await D(fetch(KN),{milliseconds:5e3});if(!o.ok)throw new Error(`Got error status code ${o.statusText}`);let i=await o.json();e=YN.parse(i).versions;break}catch(o){n.warn({err:o},"Failed to fetch npm registry data")}if(!e){n.warn("Failed to fetch npm registry data. Skipping version check.");return}let t;for(let r of Object.keys(e))Hl.valid(r)&&(!t||Hl.gt(r,t))&&Hl.gt(r,wn)&&Hl.lt(r,"2.0.0")&&!r.includes("alpha")&&(t=r);t&&(y.warn(`Update available: v${wn} -> v${t}`),y.warn("This version may be missing critical fixes, features, and security updates."),y.warn(`Run "npx momentic@${t} -V" to update`))}import{existsSync as ZN,mkdirSync as QN,statSync as ek}from"fs";import{dirname as tk}from"path";import pv from"readline/promises";import{hostname as XN}from"os";var ee=Dl({app:"cli",clientToken:"pub7eb923f18fb3f1d42ac5eba8c5ea13a5",hostname:XN(),disableConsoleLogs:!0}).child({version:"2.3.4"});var Qp=!1,uv=(()=>{try{return ek("/.dockerenv"),!0}catch{return!1}})();async function ft(n,e){if(xi||Qp||uv)return!0;ee.flush(),await new Promise(a=>setTimeout(a,500));let t=pv.createInterface({input:process.stdin,output:process.stdout}),r=n.split("."),o;if(r.length===1)o=n;else{let a=`${r.slice(0,r.length-1).join(".").trim()}.`;e?y.warn(a):y.log(a),o=r[r.length-1].trim()}let i=await t.question(`${o} ('y' for yes / n for no / 'A' to accept all) `);return t.close(),i==="A"?(Qp=!0,setTimeout(()=>{Qp=!1},3e3),!0):i.toLowerCase()==="y"}async function eu(n){let e=tk(n);return lv(e)?ZN(n)?ft(`File '${dv(n)}' already exists. Overwrite existing content?`,!0):!0:await ft(`Directory '${dv(e)}' doesn't exist. Create it now?`,!0)?(QN(e,{recursive:!0}),!0):!1}function dv(n){return n.replace(/(\s+)/g,"\\$1")}async function mv(n,e){if(xi||uv)return e;let t=pv.createInterface({input:process.stdin,output:process.stdout}),r=await t.question(`${n} `);return t.close(),r.trim()||e}async function hv({test:n,fragment:e,entities:t,client:r,logger:o,yes:i}){rk(e.schemaVersion,_e)&&(y.error(`This version of the CLI does not support the schema version of the fragment (${e.schemaVersion}). Please update to the latest version of the CLI and retry this command.`),process.exit(1)),Gg(e.steps).forEach(g=>{t.modules[g]||(y.error(`The test patch contains a module with id ${g} that could not be found in the current project. This suggests that either this test patch or your local file system may be out of date.`),process.exit(1))}),e.createdAt.getTime()<Date.now()-7*24*60*60*1e3&&!i&&!await ft("The test patch you are applying is more than 7 days old. Are you sure you want to continue?",!0)&&process.exit(1);let s=n.lastModified.getTime();e.createdAt.getTime()+60*60*1e3<s&&!i&&!await ft("The test patch you are applying was created before the test was last updated. Are you sure you want to continue?",!0)&&process.exit(1);let l=Xr(n.fullFilePath,o,t),c=l.steps;if(!Array.isArray(c))throw new Error(`Test ${n.fullFilePath} is missing steps array`);let d,p;if(e.schemaVersion!==_e){let{steps:g,newVersion:f}=await oa({metadata:{id:e.id,schemaVersion:e.schemaVersion},steps:e.steps,logger:y});d=f,p=Ie.array().parse(g)}else p=Ie.array().parse(e.steps);let{stepsToSave:u,moduleUpdates:m}=await Zt({stepLists:{steps:p}});u.beforeSteps=l.beforeSteps??void 0,u.afterSteps=l.afterSteps??void 0;let h=nk(JSON.stringify(c,void 0,2),JSON.stringify(u,void 0,2),{n_surrounding:5});y.dimmed("=".repeat(30)),y.dimmed(h),y.dimmed("=".repeat(30)),y.dimmed(""),d&&y.warn(`If this patch is applied, your test will also be automatically upgraded to the latest schema version (${d}). Schema upgrades have no impact on functionality, although you may notice minor differences in the test YAML.`),!i&&!await ft("Do you want to apply this patch?")&&(y.dimmed("Cancelled."),process.exit(1)),Wn({relativeTestPath:n.relativePath,steps:u,schemaVersion:d??e.schemaVersion,project:t.project}),y.success("Patch applied successfully."),await r.patchTestFragment(e.id,{applied:!0,appliedAt:new Date})}import{randomUUID as po}from"crypto";import{z as _v}from"zod";var jt=" ".repeat(6);import kv from"chalk";import{Argument as lo,Option as Oe}from"@commander-js/extra-typings";import{validateHeaderValue as ok}from"http";import{cpus as gv}from"os";import{parse as wme}from"yaml";import{z as q}from"zod";var $l=58888,tu=30*60*1e3,Jn=new Oe("--api-key <key>","API key for authentication. If not supplied, attempts to read the MOMENTIC_API_KEY env var."),Xn=new Oe("--server <server>","Momentic server to use. Leave unchanged unless using Momentic on-premise."),co=new Oe("-y, --yes","Skip all confirmation prompts.").env("CI"),nu=new Oe("-w, --wait","Wait for tests to finish running before exiting. Only applicable when running tests remotely").implies({remote:!0}),ru=new Oe("--wait-timeout <waitTimeout>",`The maximum number of seconds to wait for tests to complete. Only applicable when the --wait option is specified. Defaults to ${tu/1e3} seconds.`),Gl=new Oe("--custom-headers <customHeaders...>","Specify custom headers in the form HEADER=VALUE to be sent with each request during the test. Multiple entries can be provided."),Sv=new Oe("--reporter <reporter>","Output report files in a standardized format to a local directory. See the --reporter-dir flag for information on the output directory.").choices(Object.values(Yi)),yv=new Oe("--reporter-dir <reporterDir>","Output directory to store report files. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. Defaults to 'reports' if unset."),ou=new Oe("--output-dir <outputDir>","[Alpha] Output directory to store run artifacts such as screenshots, results, and logs. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. This directory will be cleared at the start of execution."),bv=new Oe("--upload-results","Upload test results to Momentic Cloud. By default, this option is disabled."),wv=new Oe("--include <includePatterns...>","Only include tests that match the provided regex patterns. Multiple patterns can be provided. The patterns will be matched against the test file paths and the pattern only needs to match a part of the path for the test to be included."),vv=new Oe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),iu=new Oe("--pixel-ratio <pixelRatio>","Device pixel ratio of your screen or monitor. Mac OS Retina displays and machines marketed as 'HiDPI' should set this to 2. Visit https://www.mydevice.io/ to find your device's pixel ratio."),xv=new Oe("--port <port>",`Port to run the app on. Defaults to ${$l}.`),au=new Oe("--input-csv <inputCsv>","Path to a CSV file on disk where each row represents a set of inputs that will be made available to all tests that are ran. The first line of the CSV must be the input names."),Wl=new Oe("--env <env>","Name of the environment to use when running tests."),Vl=new Oe("--url-override <urlOverride>","Fully qualified url (e.g. https://www.google.com) to start all tests from. Overrides any default starting url set from the test or environment."),Tv=new Oe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(n=>parseInt(n,10)),Fn=new Oe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file (*.momentic.config.yaml)"),su=new Oe("-f, --filter <filter>","Run tests within the project that has a name equal to the filter provided. This option cannot be used together with file path or directory arguments, but substring matches are allowed."),Ev=new Oe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(n=>parseInt(n,10)),Cv=new Oe("--fix","Attempt to fix any issues found. This option will write changes to your local file system."),lu=new Oe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on the protected branches configured in the momentic.config.yaml.").env("CI"),cu=new Oe("--disable-cache","Disable caching of test results. This will cause all tests to be re-run every time."),Rv=new lo("<tests...>",`One or more test paths to queue on Momentic Cloud.
|
|
3814
3814
|
|
|
3815
3815
|
A test path is a lowercased version of your test name where spaces are replaced with dashes: 'npx momentic pull hello-world'.`),Av=new lo("<tests...>",`One or more test paths to import from Momentic Cloud.
|
|
3816
3816
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "momentic",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "momentic",
|
|
9
|
-
"version": "2.3.
|
|
9
|
+
"version": "2.3.4",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@actions/exec": "^1.1.1",
|
|
12
12
|
"@actions/io": "^1.1.3",
|