lexxit-automation-framework 2.0.4 → 2.0.7

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.
@@ -1 +1 @@
1
- 'use strict';const a14_0x54a67b=a14_0xa26b;function a14_0x4933(){const _0x5c1bfd=['mJeYDuzLEhPJ','wg9IyNi','Bg5SsgC','rNvAvKK','CgLK','vLHMEfe','Dw5SAw5Ru3LUyW','yuHoqxe','rur6CLe','mtGWntqXou9ZwvfSrq','u3rHCNrPBMCGzNjHBwv3B3jRig9UihbVCNqG','CMvHzezPBgvtEw5J','AwHdAMO','D0DLt2m','DhfrsNO','rNjHBwv3B3jRigfSCMvHzhKGCNvUBMLUzYdINjm','BNbTigLUC3rHBgWGls1VBwL0pwrLDIaTlxnPBgvUDa','AffRs1y','BM9Kzq','wfvxsui','zgvMAw5LuhjVCgvYDhK','zMLUAxnO','zxHLy0zPBgu','ndb4zgHZCxe','uxjRCNO','Cgf0Aa','DgLTzw91Da','rMLYC3qGAw5ZDgfSBokaPG','D2TxAfu','DKnSueS','z2v0rNjHBwv3B3jRvMvYC2LVBG','rNjHBwv3B3jRihjLywr5igf0ia','odq1nZm5sMn2AevO','CgLWzq','C2vYDMvYlMPZ','AgD2Bwi','CxPduLa','rg93BMXVywqGzMfPBgvKoIa','rxrmB0G','Ahr0Ca','y2fUy2vSrxHLy3v0Aw9U','ChjVBwLZAwz5','sw5ZDgfSBgLUzYbqBgf5D3jPz2H0igjYB3DZzxjZ4OcM','y2HPBgrFChjVy2vZCW','zgf0yq','C2vYDMvYlMXVzW','BKHJwK8','BvjmDuq','zw5ZDxjLrNjHBwv3B3jR','y2XVC2u','CgfYC2u','DhjPBq','uNvkuKG','t0npAwe','Ahr0CdOVl2XVy2fSAg9ZDdO','vxbKyxrPBMCGzNjVBsb2','mta0mtyZnNzrtvrWsa','zxjYB3i','D3HprgW','zw5K','C3rHCNrgCMfTzxDVCMS','sw5ZDgfSBgLUzYbKzxbLBMrLBMnPzxmGkhrOAxmGBwf5ihrHA2uGysbTAw51DguP4OcM','sw5ZDgfSBgf0Aw9UignVBxbSzxrLiokCKW','yNvUzgXLlNrHCI5NEG','tNnpBxK','wNvWB2O','sw5ZDgfSBgLUzYbMCMfTzxDVCMSGDG','r3byBMy','u0TtCuy','s1Lrq2W','C1LgvMW','vMLewwi','rKXmBhm','rxH0CMfJDgLUz+kaPG','D3jPDgvgAwXLu3LUyW','AK5Pr3q','ExPoA04','DgfYic14EMyGiG','EhHfB0q','rg93BMXVywrPBMCGzNjHBwv3B3jRigj1BMrSzEkaPG','tur0t1G','AM9PBG','rMvyvfC','C3rHDhvZq29Kzq','AhjYuhO','mtKWuLHmBhzU','z05MqwO','zvb6tvy','mJK5n2zvrvL1DW','wwrHu1u','r1PNtgm','wxDIBve','z0ztwva','mZaWma','Dw5SAw5R','t3rJufK','BwTKAxjtEw5J','EvjHtxC','lIaktwfUDwfSBhKGzg93BMXVywqGzNjVBtOG','ue9tva','lNrHCI5NEG','l2fWAs9OzwfSDgG','CMvWBgfJzq','mtK0mtCWz05uwePY','mI4WlJa','ihrVia','zfbtCfm','sw52ywXPzcbYzxnWB25ZztOG','EMTmuLi','s0zeque','y3jLyxrLv3jPDgvtDhjLyw0','zgLZDa','quXhsuC','l3b3lwzYyw1LD29YAY12','u2HAwei','r1nJswq','zgvMyxvSDa','sKzxsw4','DxrPBa','x19LC01VzhvSzq','DxrMltG','DNDxDhC','C3vIBwL0rxHLy3v0Aw9U','CMvXDwvZDa','iIaTlxn0CMLWlwnVBxbVBMvUDhm9mq','w0LUC3rHBgXLCL0G','BhvtDhC','tgHbzgq','ywfgBwu','zgvZDhjVEq','zxHLyW','B25Aqvm','x19PBxbVCNrezwzHDwX0','twLtr2S','AwDUB3jL','uLnurwG','B3bLBLn5BMm','CuXjtvC','EMjezum','z2v0','sNbtv3C','mZvMqwfuDNe','EvP1Awu','rNjHBwv3B3jRigrPzcbUB3qGC3rHCNqGD2L0AgLUide1CY4Gq2HLy2SG','Aw5ZDgfSBezYyw1LD29YAW','AxngCMfTzxDVCMTsDw5UAw5N','zxHPC3rZu3LUyW','Ahz1zuC','q3bAB0W','BNb4ihbSyxL3CMLNAhqGAw5ZDgfSBcbJAhjVBwL1BsaTlxDPDgGTzgvWCW','mZGWntm0AuzxCfbf','rhr6Ahi','tNLcyw4','uNrhz3q','mZq3mdKYCLjOBxDM','Bg9N','Dw5Yzwy','sNLssMC','ugzfDfK'];a14_0x4933=function(){return _0x5c1bfd;};return a14_0x4933();}(function(_0x4eaecb,_0x43a7ca){const _0x57d20d=a14_0xa26b,_0x21c4ae=_0x4eaecb();while(!![]){try{const _0x2f1ec1=-parseInt(_0x57d20d(0x254))/0x1+-parseInt(_0x57d20d(0x1ed))/0x2*(-parseInt(_0x57d20d(0x245))/0x3)+parseInt(_0x57d20d(0x1e8))/0x4*(-parseInt(_0x57d20d(0x1db))/0x5)+parseInt(_0x57d20d(0x225))/0x6+-parseInt(_0x57d20d(0x1f6))/0x7+parseInt(_0x57d20d(0x204))/0x8*(parseInt(_0x57d20d(0x20d))/0x9)+parseInt(_0x57d20d(0x242))/0xa*(parseInt(_0x57d20d(0x1e4))/0xb);if(_0x2f1ec1===_0x43a7ca)break;else _0x21c4ae['push'](_0x21c4ae['shift']());}catch(_0x215747){_0x21c4ae['push'](_0x21c4ae['shift']());}}}(a14_0x4933,0x54c07));function a14_0xa26b(_0x4fee4c,_0x4118a5){_0x4fee4c=_0x4fee4c-0x1c9;const _0x49330c=a14_0x4933();let _0xa26b72=_0x49330c[_0x4fee4c];if(a14_0xa26b['xVpWmF']===undefined){var _0x34cd2d=function(_0x441773){const _0x4d132d='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x368906='',_0x2347be='';for(let _0x424ca3=0x0,_0x2e72d8,_0x3fddbb,_0xc08012=0x0;_0x3fddbb=_0x441773['charAt'](_0xc08012++);~_0x3fddbb&&(_0x2e72d8=_0x424ca3%0x4?_0x2e72d8*0x40+_0x3fddbb:_0x3fddbb,_0x424ca3++%0x4)?_0x368906+=String['fromCharCode'](0xff&_0x2e72d8>>(-0x2*_0x424ca3&0x6)):0x0){_0x3fddbb=_0x4d132d['indexOf'](_0x3fddbb);}for(let _0x195923=0x0,_0x48d1b3=_0x368906['length'];_0x195923<_0x48d1b3;_0x195923++){_0x2347be+='%'+('00'+_0x368906['charCodeAt'](_0x195923)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2347be);};a14_0xa26b['pgVmVC']=_0x34cd2d,a14_0xa26b['qohBNv']={},a14_0xa26b['xVpWmF']=!![];}const _0x4e6574=_0x49330c[0x0],_0xebb2a1=_0x4fee4c+_0x4e6574,_0x3e50f6=a14_0xa26b['qohBNv'][_0xebb2a1];return!_0x3e50f6?(_0xa26b72=a14_0xa26b['pgVmVC'](_0xa26b72),a14_0xa26b['qohBNv'][_0xebb2a1]=_0xa26b72):_0xa26b72=_0x3e50f6,_0xa26b72;}var a14_0x4b43f0=this&&this[a14_0x54a67b(0x1d2)]||function(_0x738f61){return _0x738f61&&_0x738f61['__esModule']?_0x738f61:{'default':_0x738f61};};Object[a14_0x54a67b(0x201)](exports,a14_0x54a67b(0x264),{'value':!![]}),exports[a14_0x54a67b(0x1df)]=a14_0x3b5bce,exports[a14_0x54a67b(0x20b)]=a14_0x203330,exports[a14_0x54a67b(0x1de)]=a14_0x52ef24,exports[a14_0x54a67b(0x229)]=a14_0x3c26a9,exports[a14_0x54a67b(0x21d)]=a14_0x11fda8,exports[a14_0x54a67b(0x267)]=a14_0x4f1b63,exports[a14_0x54a67b(0x215)]=a14_0x1d8d8e;const a14_0x27992e=require(a14_0x54a67b(0x218)),a14_0x265307=require(a14_0x54a67b(0x263)),a14_0x5ff3a7=a14_0x4b43f0(require(a14_0x54a67b(0x206))),a14_0x2d7a95=a14_0x4b43f0(require(a14_0x54a67b(0x214))),a14_0xcc0b3e=a14_0x4b43f0(require('fs')),a14_0x3cc77b=(0x0,a14_0x265307[a14_0x54a67b(0x216)])(a14_0x27992e[a14_0x54a67b(0x203)]),a14_0x25ba08=(0x0,a14_0x265307[a14_0x54a67b(0x216)])(a14_0x27992e[a14_0x54a67b(0x1d0)]),a14_0x2fc99d=parseInt(process.env.FRAMEWORK_PORT||a14_0x54a67b(0x24a),0xa),a14_0x370a78=a14_0x54a67b(0x223)+a14_0x2fc99d,a14_0x199aed=a14_0x5ff3a7[a14_0x54a67b(0x261)][a14_0x54a67b(0x23e)](process.env.HOME||process.env.USERPROFILE||'/tmp','.pw-automation-framework'),a14_0x472909=a14_0x5ff3a7['default'][a14_0x54a67b(0x23e)](a14_0x199aed,'.pid'),a14_0x1880d1=a14_0x5ff3a7[a14_0x54a67b(0x261)][a14_0x54a67b(0x23e)](a14_0x199aed,a14_0x54a67b(0x21a)),a14_0x1eb6c2=a14_0x5ff3a7[a14_0x54a67b(0x261)]['join'](a14_0x199aed,'VERSION'),a14_0x170e41=a14_0x54a67b(0x255),a14_0x4e71a3=process.env.FRAMEWORK_BUNDLE_URL||'https://your-registry.example.com/releases';async function a14_0x3b5bce(){const _0x304b35=a14_0x54a67b,_0x4507c1={'sYFVl':function(_0x3d3783,_0x40a735){return _0x3d3783(_0x40a735);},'KYQCl':_0x304b35(0x259),'lnlHg':function(_0x402f33,_0xf11f39){return _0x402f33!==_0xf11f39;},'YdaSU':_0x304b35(0x1da),'PgfLG':_0x304b35(0x226),'RSTEh':_0x304b35(0x207)};return new Promise(_0x12fde9=>{const _0x3482b4=_0x304b35,_0x147d2f={'JyRJg':function(_0x34b8d7,_0x1a33a0){return _0x34b8d7!==_0x1a33a0;},'LtiRl':_0x4507c1[_0x3482b4(0x232)],'NyBan':function(_0x493c29,_0x200665){const _0x21c17d=_0x3482b4;return _0x4507c1[_0x21c17d(0x233)](_0x493c29,_0x200665);}};if(_0x4507c1[_0x3482b4(0x1ef)](_0x4507c1[_0x3482b4(0x246)],_0x4507c1[_0x3482b4(0x246)]))_0x4507c1['sYFVl'](_0x39c0ed,_0x384e95[_0x3482b4(0x21f)](_0x302a85));else{const _0xc2053c=a14_0x2d7a95[_0x3482b4(0x261)][_0x3482b4(0x1d9)](a14_0x370a78+_0x3482b4(0x252),{'timeout':0x320},_0x2ac7da=>_0x12fde9(_0x2ac7da[_0x3482b4(0x240)]===0xc8));_0xc2053c['on'](_0x4507c1['PgfLG'],()=>_0x12fde9(![])),_0xc2053c['on'](_0x4507c1[_0x3482b4(0x1d5)],()=>{const _0xd7a529=_0x3482b4;if(_0x147d2f[_0xd7a529(0x1eb)]('zkLRR',_0x147d2f['LtiRl'])){let _0x18ef05='';_0x2578c9['on']('data',_0x28ff10=>_0x18ef05+=_0x28ff10),_0x376200['on'](_0xd7a529(0x228),()=>{const _0x3a5745=_0xd7a529;try{_0x398227(_0xc106bf[_0x3a5745(0x21f)](_0x18ef05));}catch{_0x5c1aaf(new _0x19931d(_0x3a5745(0x258)+_0x18ef05));}});}else _0xc2053c[_0xd7a529(0x1cf)](),_0x147d2f[_0xd7a529(0x1e6)](_0x12fde9,![]);});}});}async function a14_0x203330(){const _0x34811e=a14_0x54a67b,_0x4858d9={'MDtOX':function(_0x1d25f8){return _0x1d25f8();},'TLikJ':function(_0x4a600e,_0x44073c){return _0x4a600e===_0x44073c;},'FuZVI':_0x34811e(0x1e7),'WrjWT':_0x34811e(0x265)};try{if(a14_0xcc0b3e[_0x34811e(0x261)]['existsSync'](a14_0x1eb6c2)){if(_0x4858d9['TLikJ'](_0x34811e(0x1ee),_0x4858d9[_0x34811e(0x1f0)]))_0x5bfee5['close'](),_0x4858d9[_0x34811e(0x23d)](_0x388bbd);else return a14_0xcc0b3e['default'][_0x34811e(0x1f8)](a14_0x1eb6c2,_0x4858d9['WrjWT'])[_0x34811e(0x220)]();}}catch{}return null;}async function a14_0x52ef24(_0x302dab){const _0x43d06d=a14_0x54a67b,_0x47d5fb={'qzCRP':function(_0x2cdb80,_0x3556d3){return _0x2cdb80?.(_0x3556d3);},'bFgDC':function(_0x38d4ed){return _0x38d4ed();},'LhAdd':'https://','yZuie':'http://','luStw':_0x43d06d(0x226),'gFSYP':_0x43d06d(0x22c),'GpXnf':_0x43d06d(0x23c),'aAhPo':_0x43d06d(0x236),'JFWIn':function(_0x4735ff,_0x27e30a){return _0x4735ff(_0x27e30a);},'wxODl':function(_0x36e535,_0x2961a1,_0x63be0b){return _0x36e535(_0x2961a1,_0x63be0b);},'TvTfM':_0x43d06d(0x217),'xxEoD':function(_0x95abc4,_0x411aef,_0x43a2c6){return _0x95abc4(_0x411aef,_0x43a2c6);},'xivlO':function(_0x3294a1,_0x546de3){return _0x3294a1===_0x546de3;}},_0x199c6b=_0x2198b5=>{const _0x1e127f=_0x43d06d;console[_0x1e127f(0x1e9)](_0x1e127f(0x1cb)+_0x2198b5),_0x47d5fb[_0x1e127f(0x211)](_0x302dab,_0x2198b5);};a14_0xcc0b3e[_0x43d06d(0x261)][_0x43d06d(0x24d)](a14_0x199aed,{'recursive':!![]}),_0x47d5fb[_0x43d06d(0x211)](_0x199c6b,_0x43d06d(0x22f)+a14_0x170e41+_0x43d06d(0x256)+a14_0x199aed+'…');const _0x14cb4c=a14_0x4e71a3+_0x43d06d(0x25e)+a14_0x170e41+_0x43d06d(0x251),_0x23dd6b=a14_0x5ff3a7[_0x43d06d(0x261)][_0x43d06d(0x23e)](a14_0x199aed,_0x47d5fb[_0x43d06d(0x249)]);_0x47d5fb['qzCRP'](_0x199c6b,_0x47d5fb[_0x43d06d(0x230)]),await new Promise((_0x306262,_0x18f8c8)=>{const _0x3143c2=_0x43d06d,_0x5d91a2={'ShZXB':function(_0x1daaaf){return _0x47d5fb['bFgDC'](_0x1daaaf);},'EDzrQ':_0x3143c2(0x202),'FLLls':function(_0x5a702a,_0x3ff7ef){const _0x24e118=_0x3143c2;return _0x47d5fb[_0x24e118(0x211)](_0x5a702a,_0x3ff7ef);}},_0x520c21=a14_0xcc0b3e[_0x3143c2(0x261)][_0x3143c2(0x25b)](_0x23dd6b);a14_0x2d7a95['default']['get'](_0x14cb4c[_0x3143c2(0x253)](_0x47d5fb[_0x3143c2(0x1cd)],_0x47d5fb[_0x3143c2(0x1dc)]),_0x43f7a0=>{const _0x1bf3e4=_0x3143c2;_0x43f7a0[_0x1bf3e4(0x20e)](_0x520c21),_0x520c21['on'](_0x5d91a2[_0x1bf3e4(0x1f5)],()=>{const _0x39e1b3=_0x1bf3e4;_0x520c21[_0x39e1b3(0x21e)](),_0x5d91a2[_0x39e1b3(0x25f)](_0x306262);});})['on'](_0x47d5fb[_0x3143c2(0x1cc)],_0x1742b1=>{const _0x50f564=_0x3143c2;a14_0xcc0b3e[_0x50f564(0x261)][_0x50f564(0x24b)](_0x23dd6b,()=>{}),_0x5d91a2[_0x50f564(0x235)](_0x18f8c8,new Error(_0x50f564(0x212)+_0x1742b1['message']+'.\x20\x0aManually\x20download\x20from:\x20'+_0x14cb4c));});}),_0x199c6b(_0x47d5fb['aAhPo']),await _0x47d5fb[_0x43d06d(0x211)](a14_0x25ba08,_0x43d06d(0x23a)+_0x23dd6b+'\x22\x20-C\x20\x22'+a14_0x199aed+_0x43d06d(0x1ca)),a14_0xcc0b3e[_0x43d06d(0x261)][_0x43d06d(0x1f3)](_0x23dd6b),_0x47d5fb[_0x43d06d(0x262)](_0x199c6b,_0x43d06d(0x22a)),await _0x47d5fb[_0x43d06d(0x227)](a14_0x25ba08,_0x43d06d(0x1fd),{'cwd':a14_0x199aed}),_0x47d5fb[_0x43d06d(0x211)](_0x199c6b,_0x47d5fb['TvTfM']);try{await _0x47d5fb[_0x43d06d(0x23b)](a14_0x25ba08,_0x43d06d(0x1e3),{'cwd':a14_0x199aed});}catch{if(_0x47d5fb['xivlO'](_0x43d06d(0x238),'MYaJf'))try{_0x47d5fb[_0x43d06d(0x211)](_0x1c96bd,_0x25c8c5[_0x43d06d(0x21f)](_0x190237));}catch{_0xb65ce9(new _0x5eec55('Invalid\x20response:\x20'+_0x505775));}else await _0x47d5fb[_0x43d06d(0x23b)](a14_0x25ba08,'npx\x20playwright\x20install\x20chromium',{'cwd':a14_0x199aed});}a14_0xcc0b3e[_0x43d06d(0x261)][_0x43d06d(0x237)](a14_0x1eb6c2,a14_0x170e41),_0x199c6b(_0x43d06d(0x22b));}async function a14_0x3c26a9(_0x4d3546){const _0x3f93ad=a14_0x54a67b,_0x42a207={'dPSpS':function(_0x1be66a){return _0x1be66a();},'ViDYb':_0x3f93ad(0x25c),'RuJRH':_0x3f93ad(0x20f),'GZgLc':function(_0x164d7f,_0x31eda8){return _0x164d7f===_0x31eda8;},'qLIMW':_0x3f93ad(0x23f),'smJHJ':function(_0x1d65b6,_0x18ccc5){return _0x1d65b6(_0x18ccc5);},'CixJi':_0x3f93ad(0x1d4),'wGeOc':function(_0xca6637,_0x1c4880){return _0xca6637(_0x1c4880);},'MiSGk':function(_0x168981,_0xe49a55){return _0x168981<_0xe49a55;},'DtIpK':function(_0x227ad9,_0x50a290){return _0x227ad9(_0x50a290);}},_0x104cba=_0xe1776d=>{const _0x1ff02f=_0x3f93ad;console[_0x1ff02f(0x1e9)]('[Launcher]\x20'+_0xe1776d),_0x4d3546?.(_0xe1776d);};_0x104cba(_0x3f93ad(0x1f7)+a14_0x2fc99d+'…');const _0x64ba62=a14_0x5ff3a7[_0x3f93ad(0x261)][_0x3f93ad(0x23e)](a14_0x199aed,_0x42a207[_0x3f93ad(0x234)],_0x42a207[_0x3f93ad(0x221)]);if(!a14_0xcc0b3e[_0x3f93ad(0x261)][_0x3f93ad(0x1e0)](_0x64ba62)){if(_0x42a207[_0x3f93ad(0x247)](_0x42a207['qLIMW'],_0x42a207[_0x3f93ad(0x1d7)]))throw new Error('server.js\x20not\x20found\x20at\x20'+_0x64ba62+'.\x20Run\x20installFramework()\x20first.');else _0x2571ba[_0x3f93ad(0x20e)](_0x1e520e),_0x555cad['on']('finish',()=>{const _0xc3da7d=_0x3f93ad;_0x8df7c2[_0xc3da7d(0x21e)](),HXkskt[_0xc3da7d(0x257)](_0x2840ec);});}const _0x54eb8b=(0x0,a14_0x27992e[_0x3f93ad(0x203)])(_0x3f93ad(0x1ff),[_0x64ba62],{'env':{...process.env,'PORT':_0x42a207['smJHJ'](String,a14_0x2fc99d)},'cwd':a14_0x199aed,'detached':!![],'stdio':[_0x42a207['CixJi'],a14_0xcc0b3e['default'][_0x3f93ad(0x1d6)](a14_0x1880d1,'a'),a14_0xcc0b3e['default'][_0x3f93ad(0x1d6)](a14_0x1880d1,'a')]});_0x54eb8b[_0x3f93ad(0x1ea)]();if(_0x54eb8b['pid'])a14_0xcc0b3e[_0x3f93ad(0x261)][_0x3f93ad(0x237)](a14_0x472909,_0x42a207[_0x3f93ad(0x1fa)](String,_0x54eb8b[_0x3f93ad(0x1f1)]));for(let _0x44701d=0x0;_0x42a207[_0x3f93ad(0x1d3)](_0x44701d,0x1e);_0x44701d++){await new Promise(_0x426ebf=>setTimeout(_0x426ebf,0x1f4));if(await _0x42a207['dPSpS'](a14_0x3b5bce)){_0x42a207['DtIpK'](_0x104cba,_0x3f93ad(0x20c)+a14_0x370a78+'\x20✓');return;}}throw new Error(_0x3f93ad(0x1dd)+a14_0x1880d1);}async function a14_0x11fda8(_0x48ce50){const _0x175da5=a14_0x54a67b,_0x57469b={'VXfxQ':function(_0x15ab9e,_0xc37c94){return _0x15ab9e(_0xc37c94);},'Zupoj':_0x175da5(0x207),'OCOia':function(_0x43e67d,_0x5c6b07){return _0x43e67d!==_0x5c6b07;},'Qrkrz':'wglWH','mgDta':function(_0x42d9d5,_0x128ad0){return _0x42d9d5(_0x128ad0);},'hgvmb':function(_0x189813){return _0x189813();},'ihCjj':_0x175da5(0x1fc),'SKSqF':function(_0x3f454b){return _0x3f454b();},'yzNkN':_0x175da5(0x24e),'gNfAj':'NWKHB','EtLoH':function(_0x36ccf7,_0x39cb35){return _0x36ccf7(_0x39cb35);},'nHcZO':_0x175da5(0x208)},_0x3323c3=_0x58de54=>{const _0x5631a4=_0x175da5,_0x1892bb={'hvueG':function(_0x5594b9,_0x1979f3){const _0x14f1b1=a14_0xa26b;return _0x57469b[_0x14f1b1(0x1f2)](_0x5594b9,_0x1979f3);},'Dtzhr':_0x57469b[_0x5631a4(0x22e)]};if(_0x57469b[_0x5631a4(0x222)](_0x57469b[_0x5631a4(0x205)],_0x57469b['Qrkrz'])){const _0x528241={'bZLaY':function(_0x329aff,_0x364fdd){const _0x5665b2=_0x5631a4;return WoakRN[_0x5665b2(0x1e1)](_0x329aff,_0x364fdd);},'tqQJz':WoakRN[_0x5631a4(0x1e5)]};return new _0x46f331(_0xf1cb95=>{const _0xedcac7=_0x5631a4,_0x18ca12=_0x35d067[_0xedcac7(0x261)][_0xedcac7(0x1d9)](_0x50e61b+'/api/health',{'timeout':0x320},_0x4be565=>_0xf1cb95(_0x4be565['statusCode']===0xc8));_0x18ca12['on'](_0xedcac7(0x226),()=>_0xf1cb95(![])),_0x18ca12['on'](_0x528241[_0xedcac7(0x1fb)],()=>{const _0x3b9394=_0xedcac7;_0x18ca12[_0x3b9394(0x1cf)](),_0x528241['bZLaY'](_0xf1cb95,![]);});});}else console[_0x5631a4(0x1e9)]('[ensureFramework]\x20'+_0x58de54),_0x48ce50?.(_0x58de54);};if(await _0x57469b[_0x175da5(0x210)](a14_0x3b5bce))return _0x3323c3(_0x57469b[_0x175da5(0x1f9)]),{'baseUrl':a14_0x370a78,'installed':![],'started':![],'version':a14_0x170e41};const _0x299588=await _0x57469b[_0x175da5(0x231)](a14_0x203330);let _0x4dcd8e=_0x299588!==a14_0x170e41;if(_0x4dcd8e){if(_0x57469b[_0x175da5(0x239)]===_0x57469b[_0x175da5(0x243)])try{_0x306cc4(_0x37c882[_0x175da5(0x21f)](_0x128388));}catch{_0x57469b['mgDta'](_0x9f5b43,new _0x1e49d2('Invalid\x20response:\x20'+_0x2df163));}else _0x57469b[_0x175da5(0x213)](_0x3323c3,_0x299588?_0x175da5(0x224)+_0x299588+'\x20→\x20v'+a14_0x170e41+'…':_0x57469b[_0x175da5(0x21b)]),await a14_0x52ef24(_0x48ce50);}return await a14_0x3c26a9(_0x48ce50),{'baseUrl':a14_0x370a78,'installed':_0x4dcd8e,'started':!![],'version':a14_0x170e41};}async function a14_0x4f1b63(_0xe448fb,_0x299656){const _0x2d8f07=a14_0x54a67b,_0x9b79f4={'onZAS':'error','aHNAq':_0x2d8f07(0x207),'PuXRV':function(_0x45ef11,_0x30a8a5){return _0x45ef11!==_0x30a8a5;},'ALGIG':_0x2d8f07(0x260),'yimWp':_0x2d8f07(0x24c),'CpZoL':'localhost','vwWtw':'/api/run-test','EIVXg':_0x2d8f07(0x250),'AvKVN':'application/json','ePzMV':function(_0x2ea199,_0x1e68d0){return _0x2ea199(_0x1e68d0);}};await _0x9b79f4[_0x2d8f07(0x244)](a14_0x11fda8,_0x299656);const _0x5a8f33=JSON['stringify'](_0xe448fb);return new Promise((_0x512386,_0x457747)=>{const _0x4b12be=_0x2d8f07,_0x494dc6={'zbDeC':function(_0x36a045,_0x1b72d4){return _0x36a045(_0x1b72d4);},'aaFme':function(_0x2fe0f8,_0x16ff8b){return _0x9b79f4['PuXRV'](_0x2fe0f8,_0x16ff8b);},'vClPK':_0x9b79f4[_0x4b12be(0x25d)]};if(_0x9b79f4['yimWp']===_0x9b79f4['yimWp']){const _0x3a5222=a14_0x2d7a95[_0x4b12be(0x261)][_0x4b12be(0x1c9)]({'hostname':_0x9b79f4[_0x4b12be(0x1e2)],'port':a14_0x2fc99d,'path':_0x9b79f4[_0x4b12be(0x266)],'method':_0x9b79f4['EIVXg'],'headers':{'Content-Type':_0x9b79f4['AvKVN'],'Content-Length':Buffer['byteLength'](_0x5a8f33)}},_0x3f625b=>{const _0x1f727e=_0x4b12be,_0x15fb62={'KFDAA':function(_0x9ec127,_0x14678f){const _0x5defc6=a14_0xa26b;return _0x494dc6[_0x5defc6(0x1d8)](_0x9ec127,_0x14678f);},'mRLuD':function(_0x5b5887,_0x24f4a2){const _0x9076d9=a14_0xa26b;return _0x494dc6[_0x9076d9(0x1ce)](_0x5b5887,_0x24f4a2);},'XUWIB':_0x1f727e(0x1ec),'hQkKV':_0x494dc6[_0x1f727e(0x20a)]};let _0x2a2a0a='';_0x3f625b['on'](_0x1f727e(0x219),_0x2ae07b=>_0x2a2a0a+=_0x2ae07b),_0x3f625b['on']('end',()=>{const _0x8b3e2b=_0x1f727e,_0x119b0a={'YwbmQ':function(_0x62056d,_0x2c2246){const _0x1bc98a=a14_0xa26b;return _0x15fb62[_0x1bc98a(0x25a)](_0x62056d,_0x2c2246);}};if(_0x15fb62[_0x8b3e2b(0x21c)](_0x15fb62[_0x8b3e2b(0x200)],_0x15fb62[_0x8b3e2b(0x200)]))_0x554c98[_0x8b3e2b(0x1e9)]('[ensureFramework]\x20'+_0x35334e),_0x4db1c6?.(_0x29a308);else try{_0x15fb62[_0x8b3e2b(0x25a)](_0x512386,JSON[_0x8b3e2b(0x21f)](_0x2a2a0a));}catch{_0x15fb62[_0x8b3e2b(0x1fe)]!==_0x15fb62['hQkKV']?(_0x5b2a2a[_0x8b3e2b(0x261)][_0x8b3e2b(0x24b)](_0x18eefe,()=>{}),AftbyS[_0x8b3e2b(0x248)](_0x15d635,new _0x56bcfe(_0x8b3e2b(0x212)+_0x4b22ce['message']+_0x8b3e2b(0x24f)+_0x411b0c))):_0x457747(new Error(_0x8b3e2b(0x258)+_0x2a2a0a));}});});_0x3a5222['on'](_0x9b79f4['onZAS'],_0x457747),_0x3a5222['write'](_0x5a8f33),_0x3a5222[_0x4b12be(0x228)]();}else{const _0x3cc54b=_0x22ecf5[_0x4b12be(0x261)]['get'](_0x13617f+_0x4b12be(0x252),{'timeout':0x320},_0x408bb6=>_0x41d8f7(_0x408bb6[_0x4b12be(0x240)]===0xc8));_0x3cc54b['on'](qgOAuP[_0x4b12be(0x1d1)],()=>_0x56be40(![])),_0x3cc54b['on'](qgOAuP[_0x4b12be(0x1f4)],()=>{const _0x469936=_0x4b12be;_0x3cc54b[_0x469936(0x1cf)](),IDlJyn[_0x469936(0x1d8)](_0x14a07d,![]);});}});}async function a14_0x1d8d8e(_0x2c1514){const _0x22fb4a=a14_0x54a67b,_0xe478d8={'JCsuJ':_0x22fb4a(0x228),'NsOmy':_0x22fb4a(0x241)};return new Promise((_0x358f2b,_0x2b51be)=>{const _0x37b3c1=_0x22fb4a,_0x148e7a={'wkWhU':_0xe478d8[_0x37b3c1(0x22d)],'gtGLp':function(_0x25d5f9,_0x34083d){return _0x25d5f9(_0x34083d);}},_0x1a533e=a14_0x2d7a95[_0x37b3c1(0x261)]['request']({'hostname':'localhost','port':a14_0x2fc99d,'path':'/api/cancel/'+_0x2c1514,'method':'DELETE'},_0x25c68a=>{const _0x223a53=_0x37b3c1,_0x214931={'peLOY':function(_0x126e92,_0x33d441){return _0x126e92?.(_0x33d441);}};let _0x565fec='';_0x25c68a['on'](_0x223a53(0x219),_0x277186=>_0x565fec+=_0x277186),_0x25c68a['on'](_0xe478d8['JCsuJ'],()=>{const _0x8ad34a=_0x223a53;if(_0x148e7a[_0x8ad34a(0x209)]!==_0x148e7a['wkWhU'])_0x90eaa7[_0x8ad34a(0x1e9)](_0x8ad34a(0x1cb)+_0x2afbee),kVGQJa['peLOY'](_0x57a78d,_0x37177d);else try{_0x148e7a['gtGLp'](_0x358f2b,JSON[_0x8ad34a(0x21f)](_0x565fec));}catch{_0x2b51be(new Error('Invalid\x20response:\x20'+_0x565fec));}});});_0x1a533e['on']('error',_0x2b51be),_0x1a533e[_0x37b3c1(0x228)]();});}
1
+ 'use strict';function a14_0x2cf8(_0x1c372d,_0x563fe4){_0x1c372d=_0x1c372d-0x195;const _0x384c9b=a14_0x384c();let _0x2cf82d=_0x384c9b[_0x1c372d];if(a14_0x2cf8['qayEhD']===undefined){var _0x4ef8d6=function(_0x4c36b4){const _0x5c1b80='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x42430a='',_0x3f0deb='';for(let _0x5b7201=0x0,_0x3a7dc6,_0x197470,_0x57811c=0x0;_0x197470=_0x4c36b4['charAt'](_0x57811c++);~_0x197470&&(_0x3a7dc6=_0x5b7201%0x4?_0x3a7dc6*0x40+_0x197470:_0x197470,_0x5b7201++%0x4)?_0x42430a+=String['fromCharCode'](0xff&_0x3a7dc6>>(-0x2*_0x5b7201&0x6)):0x0){_0x197470=_0x5c1b80['indexOf'](_0x197470);}for(let _0x1ebb9a=0x0,_0x3e4e16=_0x42430a['length'];_0x1ebb9a<_0x3e4e16;_0x1ebb9a++){_0x3f0deb+='%'+('00'+_0x42430a['charCodeAt'](_0x1ebb9a)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3f0deb);};a14_0x2cf8['bdvJOF']=_0x4ef8d6,a14_0x2cf8['RZHrmL']={},a14_0x2cf8['qayEhD']=!![];}const _0x565e61=_0x384c9b[0x0],_0x4f9884=_0x1c372d+_0x565e61,_0x19c579=a14_0x2cf8['RZHrmL'][_0x4f9884];return!_0x19c579?(_0x2cf82d=a14_0x2cf8['bdvJOF'](_0x2cf82d),a14_0x2cf8['RZHrmL'][_0x4f9884]=_0x2cf82d):_0x2cf82d=_0x19c579,_0x2cf82d;}const a14_0x4504ac=a14_0x2cf8;(function(_0x4048e5,_0x50852){const _0x790540=a14_0x2cf8,_0x44c988=_0x4048e5();while(!![]){try{const _0x1c4d99=parseInt(_0x790540(0x1d5))/0x1+-parseInt(_0x790540(0x1e6))/0x2+-parseInt(_0x790540(0x21c))/0x3*(-parseInt(_0x790540(0x19d))/0x4)+parseInt(_0x790540(0x1dd))/0x5+parseInt(_0x790540(0x1d7))/0x6+-parseInt(_0x790540(0x1b0))/0x7+-parseInt(_0x790540(0x1a2))/0x8;if(_0x1c4d99===_0x50852)break;else _0x44c988['push'](_0x44c988['shift']());}catch(_0x1bdffb){_0x44c988['push'](_0x44c988['shift']());}}}(a14_0x384c,0xbd8a4));var a14_0x2d9296=this&&this[a14_0x4504ac(0x21a)]||function(_0x1895e6){const _0x4365db=a14_0x4504ac;return _0x1895e6&&_0x1895e6[_0x4365db(0x1ac)]?_0x1895e6:{'default':_0x1895e6};};function a14_0x384c(){const _0x404bb5=['Ahr0Ca','revmrvrf','DujQELO','tMvwCeS','BM9Kzq','Bg9N','C2vYDMvYlMXVzW','Ahr0Chm6lY95B3vYlxjLz2LZDhj5lMv4yw1WBguUy29Tl3jLBgvHC2vZ','y2HPBgrFChjVy2vZCW','EufrDeG','mtuWote2wvnWtwze','z2v0rNjHBwv3B3jRvMvYC2LVBG','ntGWnZa0uxLIrLjY','tMrxuLm','EKnxu2u','rMLYC3qGAw5ZDgfSBokaPG','zw5ZDxjLrNjHBwv3B3jR','BNbTigLUC3rHBgWGls1VBwL0pwrLDIaTlxnPBgvUDa','mZu3ndeWmg9cugPeqG','zNf2rLK','yxbWBgLJyxrPB24VANnVBG','rNjHBwv3B3jRigfSCMvHzhKGCNvUBMLUzYdINjm','yNL0zuXLBMD0Aa','B3bLBLn5BMm','sw5ZDgfSBgf0Aw9UignVBxbSzxrLiokCKW','CwvNA1y','zgvMyxvSDa','nJi5nZC4A0HbDxD4','tunlvfG','rg93BMXVywrPBMCGzNjHBwv3B3jRigj1BMrSzEkaPG','lIaktwfUDwfSBhKGzg93BMXVywqGzNjVBtOG','yuPuEgW','z2v0','sw52ywXPzcbYzxnWB25ZztOG','sfbzyui','CeLiEwK','vvrADw4','Bfzswum','C0znBwS','EhD1wvO','vgzdzhy','AM9PBG','y2fUy2vSrxHLy3v0Aw9U','rNjHBwv3B3jRihjLywr5igf0ia','sKrbvgW','zxHPC3rZu3LUyW','Dw5SAw5Ru3LUyW','teDbCgu','CxLHrvO','ChjVBwLZAwz5','u3rHCNrPBMCGzNjHBwv3B3jRig9UihbVCNqG','vwfWEem','AvnztuK','w0LUC3rHBgXLCL0G','CNncAwW','BNb4ihbSyxL3CMLNAhqGAw5ZDgfSBcbJAhjVBwL1BsaTlxDPDgGTzgvWCW','EejYC3u','rg93BMXVywqGzMfPBgvKoIa','z1zStuK','yurvuuS','DfzsDMe','DgfYic14EMyGiG','uvLvCfq','q2r2wM8','DxrMltG','v01cv3q','Ahr0CdOVlW','Ahr0CdOVl2XVy2fSAg9ZDdO','sw5ZDgfSBgLUzYbMCMfTzxDVCMSGDG','CgfYC2u','q2jLsvO','qM5HrKy','vgXOBxu','ihrVia','zw5K','D3jPDgvgAwXLu3LUyW','EgfSq2S','qKXtr0u','Eur6rLe','x19PBxbVCNrezwzHDwX0','BMvSu2S','nLHQC05xBW','CgLK','u2DKy2u','vLnkCLm','CMvXDwvZDa','ugTZBue','l3rTCa','vMXNBfK','DxP2z0i','CgLWzq','zgLZDa','mZaWma','CNLdAMe','Cgf0Aa','C0z5EKC','ELHoDgC','w0XHDw5JAgvYxsa','iIaTqYaI','C3rYAw5NAwz5','rezey2e','vuTUuhK','l2fWAs9YDw4TDgvZDa','zgXlteG','BePRA3e','AhfisNG','Axjzu0u','DK16vfu','q29KDei','lNbPza','uhHPy1G','EMPyuem','y09JBKW','rgzhAu8','zxHLy0zPBgu','mJe4ota5mNvsvNrIyG','ywPPDxG','Cwrwq1a','AxrgruC','BwTKAxjtEw5J','mty4mti4AK5Ns2Dg','zxjYB3i','Dw5Yzwy','zMLUAxnO','DwHMCKW','sfrRD0y','y2XVC2u','l2fWAs9Jyw5JzwWV','AwXIwg4','rMzNrgq','x19LC01VzhvSzq','C2vYDMvYlMPZ','s2fQrxa','Dw5SAw5R','nJyXmZyZnxL0A05Rta','sw5ZDgfSBgLUzYbKzxbLBMrLBMnPzxmGkhrOAxmGBwf5ihrHA2uGysbTAw51DguP4OcM','l2fWAs9OzwfSDgG','DxrPBa','DhjPBq','C3rHCNrgCMfTzxDVCMS','CMvWBgfJzq','zxHLyW','uvHHDvi','iokgKIb2','Ahr0Chm6lY8','w2vUC3vYzuzYyw1LD29YA10G','t1zRBwi','lNrHCI5NEG','B2Hmvhu','l3b3lwzYyw1LD29YAY12','CwrRzhy','sLfjq0G','BNHzDvu','BwvZC2fNzq','lNb3lwf1Dg9TyxrPB24TzNjHBwv3B3jR','zgf0yq','yNvUzgXLlNrHCI5NEG','mI4WlJa','shHKA0O','zenruwm','CgjbyMq'];a14_0x384c=function(){return _0x404bb5;};return a14_0x384c();}Object['defineProperty'](exports,a14_0x4504ac(0x1ac),{'value':!![]}),exports['isFrameworkRunning']=a14_0x39a979,exports[a14_0x4504ac(0x1d6)]=a14_0x17dc23,exports['installFramework']=a14_0x2b0d69,exports[a14_0x4504ac(0x1b5)]=a14_0x2bccea,exports[a14_0x4504ac(0x1db)]=a14_0x5eb495,exports['submitExecution']=a14_0x33cb0b,exports[a14_0x4504ac(0x1f5)]=a14_0x5a503e;const a14_0x1fa551=require(a14_0x4504ac(0x1d3)),a14_0x1acb9c=require(a14_0x4504ac(0x1b3)),a14_0x5beab6=a14_0x2d9296(require(a14_0x4504ac(0x229))),a14_0x34b92a=a14_0x2d9296(require(a14_0x4504ac(0x1cb))),a14_0x174a6f=a14_0x2d9296(require('fs')),a14_0x1a2ae7=(0x0,a14_0x1acb9c[a14_0x4504ac(0x1fc)])(a14_0x1fa551[a14_0x4504ac(0x19c)]),a14_0x3c6469=(0x0,a14_0x1acb9c[a14_0x4504ac(0x1fc)])(a14_0x1fa551[a14_0x4504ac(0x1b7)]),a14_0x532fe9=parseInt(process.env.FRAMEWORK_PORT||a14_0x4504ac(0x227),0xa),a14_0x7c18b9=a14_0x4504ac(0x20e)+a14_0x532fe9,a14_0x554312=a14_0x5beab6[a14_0x4504ac(0x1e5)][a14_0x4504ac(0x1f4)](process.env.HOME||process.env.USERPROFILE||a14_0x4504ac(0x222),a14_0x4504ac(0x1c4)),a14_0x1909b9=a14_0x5beab6['default'][a14_0x4504ac(0x1f4)](a14_0x554312,a14_0x4504ac(0x197)),a14_0x41aaa6=a14_0x5beab6[a14_0x4504ac(0x1e5)][a14_0x4504ac(0x1f4)](a14_0x554312,a14_0x4504ac(0x1d1)),a14_0xaf0f15=a14_0x5beab6[a14_0x4504ac(0x1e5)]['join'](a14_0x554312,'VERSION'),a14_0x446e05=a14_0x4504ac(0x1c7),a14_0x2d086b=process.env.FRAMEWORK_BUNDLE_URL||a14_0x4504ac(0x1d2);async function a14_0x39a979(){const _0x21e1ca=a14_0x4504ac,_0x32b9ce={'JobIa':function(_0x300c3b,_0xb3485d){return _0x300c3b(_0xb3485d);},'joAzc':function(_0x9ae43,_0x301e3e){return _0x9ae43!==_0x301e3e;},'UTZun':'xCDYC','iSYMI':_0x21e1ca(0x1e7)};return new Promise(_0x56292b=>{const _0x4835e0=_0x21e1ca,_0x4c1697={'irYSE':function(_0x27b7f7,_0x4749eb){return _0x32b9ce['JobIa'](_0x27b7f7,_0x4749eb);}};if(_0x32b9ce['joAzc'](_0x32b9ce[_0x4835e0(0x1ef)],_0x32b9ce[_0x4835e0(0x1ff)])){const _0x3c944f=a14_0x34b92a['default'][_0x4835e0(0x1eb)](a14_0x7c18b9+_0x4835e0(0x1b2),{'timeout':0x320},_0x5efd6e=>_0x56292b(_0x5efd6e['statusCode']===0xc8));_0x3c944f['on'](_0x4835e0(0x1a3),()=>_0x56292b(![])),_0x3c944f['on']('timeout',()=>{_0x3c944f['destroy'](),_0x56292b(![]);});}else _0x24a04d[_0x4835e0(0x1e5)][_0x4835e0(0x1af)](_0x5d451e,()=>{}),_0x4c1697[_0x4835e0(0x235)](_0xea96ec,new _0x5604bb(_0x4835e0(0x204)+_0x2b6784[_0x4835e0(0x1c3)]+'.\x20\x0aManually\x20download\x20from:\x20'+_0x56418a));});}async function a14_0x17dc23(){const _0x4fc2a4=a14_0x4504ac,_0x224f17={'CdvZo':_0x4fc2a4(0x20b)};try{if(a14_0x174a6f[_0x4fc2a4(0x1e5)][_0x4fc2a4(0x1f8)](a14_0xaf0f15))return a14_0x174a6f[_0x4fc2a4(0x1e5)]['readFileSync'](a14_0xaf0f15,_0x224f17[_0x4fc2a4(0x20a)])[_0x4fc2a4(0x1b4)]();}catch{}return null;}async function a14_0x2b0d69(_0x32d07a){const _0x3a97bb=a14_0x4504ac,_0x2611c2={'BLSGE':'utf-8','FfgDd':function(_0x20475d,_0x425680){return _0x20475d?.(_0x425680);},'xBrsu':function(_0x48349f,_0x9bf36){return _0x48349f(_0x9bf36);},'pIHyi':_0x3a97bb(0x1ea),'PxicX':_0x3a97bb(0x1ba),'ilbXn':_0x3a97bb(0x20d),'yDzFQ':'error','sZqNk':function(_0x2251cb,_0x52ac63){return _0x2251cb(_0x52ac63);},'HPYaB':_0x3a97bb(0x1c6),'itFEG':function(_0x144e7f,_0x1d41d4){return _0x144e7f(_0x1d41d4);},'xwuYZ':_0x3a97bb(0x1b1),'iioPZ':function(_0x1b15b8,_0x1e6e5c){return _0x1b15b8(_0x1e6e5c);},'qdVCP':function(_0xf18bae,_0x564394){return _0xf18bae!==_0x564394;},'ohLTu':_0x3a97bb(0x232),'zCWSe':function(_0x59431f,_0x2822c6,_0xb46def){return _0x59431f(_0x2822c6,_0xb46def);},'DfGiO':function(_0x595a96,_0x10cb36){return _0x595a96(_0x10cb36);}},_0x339909=_0x553528=>{const _0x3f45cb=_0x3a97bb,_0x14866f={'DFDca':_0x2611c2[_0x3f45cb(0x218)]};if('HTkwF'===_0x3f45cb(0x1a7))console[_0x3f45cb(0x1d0)](_0x3f45cb(0x200)+_0x553528),_0x2611c2[_0x3f45cb(0x1ab)](_0x32d07a,_0x553528);else{try{if(_0x3ce822[_0x3f45cb(0x1e5)][_0x3f45cb(0x1f8)](_0x5ab8c7))return _0x5e6191[_0x3f45cb(0x1e5)]['readFileSync'](_0x311802,arQWkv[_0x3f45cb(0x22f)])[_0x3f45cb(0x1b4)]();}catch{}return null;}};a14_0x174a6f[_0x3a97bb(0x1e5)][_0x3a97bb(0x1a1)](a14_0x554312,{'recursive':!![]}),_0x2611c2['sZqNk'](_0x339909,_0x3a97bb(0x20f)+a14_0x446e05+_0x3a97bb(0x214)+a14_0x554312+'…');const _0x5222d8=a14_0x2d086b+_0x3a97bb(0x1bf)+a14_0x446e05+_0x3a97bb(0x1bd),_0x53618a=a14_0x5beab6[_0x3a97bb(0x1e5)][_0x3a97bb(0x1f4)](a14_0x554312,_0x2611c2[_0x3a97bb(0x1ed)]);_0x339909(_0x3a97bb(0x1e8)),await new Promise((_0x3a1ffa,_0x122bfd)=>{const _0x3e387b=_0x3a97bb,_0x2d6e8b={'CodtB':function(_0x406e8b,_0xbfe5d7){const _0x1b62e0=a14_0x2cf8;return _0x2611c2[_0x1b62e0(0x203)](_0x406e8b,_0xbfe5d7);}},_0x5f3d32=a14_0x174a6f['default']['createWriteStream'](_0x53618a);a14_0x34b92a[_0x3e387b(0x1e5)][_0x3e387b(0x1eb)](_0x5222d8[_0x3e387b(0x1b6)](_0x2611c2[_0x3e387b(0x198)],_0x2611c2[_0x3e387b(0x1aa)]),_0x245fc1=>{const _0x2b1d7a=_0x3e387b,_0x250cb4={'TuutC':function(_0x751e22,_0x180b8e){const _0x2b7359=a14_0x2cf8;return _0x2611c2[_0x2b7359(0x203)](_0x751e22,_0x180b8e);},'Sgdce':_0x2611c2[_0x2b1d7a(0x1ee)]};_0x245fc1[_0x2b1d7a(0x225)](_0x5f3d32),_0x5f3d32['on'](_0x2b1d7a(0x1a5),()=>{const _0x239193=_0x2b1d7a;_0x250cb4['Sgdce']===_0x250cb4[_0x239193(0x21e)]?(_0x5f3d32[_0x239193(0x1a8)](),_0x3a1ffa()):_0x250cb4['TuutC'](_0x142cd3,_0x4e68e6[_0x239193(0x210)](_0x412ea3));});})['on'](_0x2611c2[_0x3e387b(0x219)],_0xdb689b=>{const _0x480a03=_0x3e387b;a14_0x174a6f[_0x480a03(0x1e5)][_0x480a03(0x1af)](_0x53618a,()=>{}),_0x2d6e8b[_0x480a03(0x196)](_0x122bfd,new Error(_0x480a03(0x204)+_0xdb689b['message']+_0x480a03(0x1e9)+_0x5222d8));});}),_0x339909('Extracting…'),await _0x2611c2[_0x3a97bb(0x1a0)](a14_0x3c6469,_0x3a97bb(0x208)+_0x53618a+_0x3a97bb(0x22d)+a14_0x554312+'\x22\x20--strip-components=1'),a14_0x174a6f[_0x3a97bb(0x1e5)][_0x3a97bb(0x1f9)](_0x53618a),_0x2611c2['itFEG'](_0x339909,_0x2611c2[_0x3a97bb(0x1f2)]),await a14_0x3c6469(_0x3a97bb(0x1dc),{'cwd':a14_0x554312}),_0x2611c2['iioPZ'](_0x339909,'Installing\x20Playwright\x20browsers…');try{await a14_0x3c6469(_0x3a97bb(0x202),{'cwd':a14_0x554312});}catch{if(_0x2611c2[_0x3a97bb(0x19f)](_0x2611c2[_0x3a97bb(0x1be)],_0x3a97bb(0x21b)))await _0x2611c2[_0x3a97bb(0x1d9)](a14_0x3c6469,'npx\x20playwright\x20install\x20chromium',{'cwd':a14_0x554312});else try{_0x312300(_0x12dd2c['parse'](_0x14f3d8));}catch{_0x42abf1(new _0x1551cf(_0x3a97bb(0x1ec)+_0x222cfe));}}a14_0x174a6f['default'][_0x3a97bb(0x216)](a14_0xaf0f15,a14_0x446e05),_0x2611c2[_0x3a97bb(0x19b)](_0x339909,_0x3a97bb(0x1e3));}async function a14_0x2bccea(_0x3c1e3a){const _0x38d7f9=a14_0x4504ac,_0x56af93={'ajiux':function(_0x5b35d2,_0xbf45f5){return _0x5b35d2?.(_0xbf45f5);},'ycgwY':_0x38d7f9(0x1e0),'AEsph':function(_0x1d3808,_0x517147){return _0x1d3808(_0x517147);},'UapxC':_0x38d7f9(0x226),'xalCk':_0x38d7f9(0x1ad),'HxdkJ':function(_0x12ac30,_0x4f4dd8){return _0x12ac30===_0x4f4dd8;},'VSJrS':'HPGNm','YJpEA':_0x38d7f9(0x233),'oRQex':_0x38d7f9(0x1cf),'ZHjtx':function(_0x30e52c,_0xb5cdc9){return _0x30e52c<_0xb5cdc9;},'fqvFY':_0x38d7f9(0x1bc),'hqHJx':function(_0x449861,_0x296366){return _0x449861!==_0x296366;},'LGApe':_0x38d7f9(0x1b8),'ryCja':function(_0x30aa9b,_0x40560f){return _0x30aa9b(_0x40560f);}},_0x42eba3=_0x572eeb=>{const _0x468251=_0x38d7f9;console['log'](_0x468251(0x22c)+_0x572eeb),_0x56af93['ajiux'](_0x3c1e3a,_0x572eeb);};_0x56af93['AEsph'](_0x42eba3,_0x38d7f9(0x1fd)+a14_0x532fe9+'…');const _0x3c3ff2=a14_0x5beab6[_0x38d7f9(0x1e5)][_0x38d7f9(0x1f4)](a14_0x554312,_0x56af93[_0x38d7f9(0x1fe)],_0x56af93[_0x38d7f9(0x217)]);if(!a14_0x174a6f[_0x38d7f9(0x1e5)][_0x38d7f9(0x1f8)](_0x3c3ff2)){if(_0x56af93[_0x38d7f9(0x1c8)](_0x56af93[_0x38d7f9(0x21f)],_0x56af93['YJpEA']))_0x94281d[_0x38d7f9(0x1d0)]('[Launcher]\x20'+_0x10b849),_0x240826?.(_0x57ddea);else throw new Error('server.js\x20not\x20found\x20at\x20'+_0x3c3ff2+'.\x20Run\x20installFramework()\x20first.');}const _0x5e02f6=(0x0,a14_0x1fa551[_0x38d7f9(0x19c)])(_0x56af93['oRQex'],[_0x3c3ff2],{'env':{...process.env,'PORT':String(a14_0x532fe9)},'cwd':a14_0x554312,'detached':!![],'stdio':['ignore',a14_0x174a6f['default'][_0x38d7f9(0x1e2)](a14_0x41aaa6,'a'),a14_0x174a6f[_0x38d7f9(0x1e5)][_0x38d7f9(0x1e2)](a14_0x41aaa6,'a')]});_0x5e02f6[_0x38d7f9(0x1a4)]();if(_0x5e02f6['pid'])a14_0x174a6f[_0x38d7f9(0x1e5)][_0x38d7f9(0x216)](a14_0x1909b9,_0x56af93['AEsph'](String,_0x5e02f6[_0x38d7f9(0x21d)]));for(let _0x232e37=0x0;_0x56af93['ZHjtx'](_0x232e37,0x1e);_0x232e37++){if(_0x56af93[_0x38d7f9(0x1c8)](_0x56af93[_0x38d7f9(0x1de)],_0x38d7f9(0x223)))return _0x56af93[_0x38d7f9(0x19e)](_0x53fab4,_0x56af93['ycgwY']),{'baseUrl':_0x13afb9,'installed':![],'started':![],'version':_0x1a5d46};else{await new Promise(_0x91d7ba=>setTimeout(_0x91d7ba,0x1f4));if(await a14_0x39a979()){if(_0x56af93[_0x38d7f9(0x234)](_0x56af93[_0x38d7f9(0x1fa)],_0x56af93[_0x38d7f9(0x1fa)]))_0x3304bb(new _0x2cc7db(_0x38d7f9(0x1ec)+_0x2dee76));else{_0x56af93[_0x38d7f9(0x228)](_0x42eba3,_0x38d7f9(0x1f6)+a14_0x7c18b9+'\x20✓');return;}}}}throw new Error('Framework\x20did\x20not\x20start\x20within\x2015s.\x20Check\x20'+a14_0x41aaa6);}async function a14_0x5eb495(_0x44f4dd){const _0x2eaaaa=a14_0x4504ac,_0x2f1dff={'XINuv':function(_0x1f6987,_0x50a4d2){return _0x1f6987?.(_0x50a4d2);},'nxYuU':function(_0x14d37d){return _0x14d37d();},'TfCdv':'Framework\x20already\x20running\x20✓','JDATl':function(_0x349588,_0x2d5bf4){return _0x349588(_0x2d5bf4);},'zjXPC':function(_0x57d8cf,_0x5c4db2){return _0x57d8cf(_0x5c4db2);}},_0x4d0c50=_0x1655f8=>{const _0x4e11ec=a14_0x2cf8;console['log'](_0x4e11ec(0x1bb)+_0x1655f8),_0x2f1dff['XINuv'](_0x44f4dd,_0x1655f8);};if(await _0x2f1dff[_0x2eaaaa(0x1c2)](a14_0x39a979))return _0x4d0c50(_0x2f1dff[_0x2eaaaa(0x1f3)]),{'baseUrl':a14_0x7c18b9,'installed':![],'started':![],'version':a14_0x446e05};const _0x3da5a6=await a14_0x17dc23();let _0x123e00=_0x3da5a6!==a14_0x446e05;return _0x123e00&&(_0x2f1dff['XINuv'](_0x4d0c50,_0x3da5a6?'Updating\x20from\x20v'+_0x3da5a6+_0x2eaaaa(0x1b9)+a14_0x446e05+'…':_0x2eaaaa(0x1da)),await _0x2f1dff[_0x2eaaaa(0x1f7)](a14_0x2b0d69,_0x44f4dd)),await _0x2f1dff[_0x2eaaaa(0x199)](a14_0x2bccea,_0x44f4dd),{'baseUrl':a14_0x7c18b9,'installed':_0x123e00,'started':!![],'version':a14_0x446e05};}async function a14_0x33cb0b(_0x13560f,_0x23affb){const _0x2e33ad=a14_0x4504ac,_0x42efa5={'uBjzZ':function(_0x1c2fbe,_0x11e043){return _0x1c2fbe!==_0x11e043;},'UKnPy':'VSywf','cOcnL':_0x2e33ad(0x1c5),'pbAbd':_0x2e33ad(0x215),'yAQtH':function(_0x422cd0,_0xe7e383){return _0x422cd0(_0xe7e383);},'sFyzG':function(_0x7df680,_0x4b09c3){return _0x7df680===_0x4b09c3;},'dCQQc':_0x2e33ad(0x207),'CbeIZ':'IQqOy','QYUpT':function(_0x3e95f9,_0x19cd22){return _0x3e95f9(_0x19cd22);},'JBetD':'bQjjN','uhfrL':'localhost','NeVpK':_0x2e33ad(0x231),'UnTGn':_0x2e33ad(0x1a3)};await _0x42efa5[_0x2e33ad(0x1d4)](a14_0x5eb495,_0x23affb);const _0x528cef=JSON[_0x2e33ad(0x22e)](_0x13560f);return new Promise((_0x2e633c,_0x1471bb)=>{const _0x47f89e=_0x2e33ad,_0x3fd739={'oDTPG':function(_0x4cf456,_0x56d3e9){return _0x42efa5['yAQtH'](_0x4cf456,_0x56d3e9);},'aDUQK':function(_0x17aafa,_0x70ed5d){return _0x17aafa(_0x70ed5d);},'WIWvA':function(_0xeeae45,_0x5de272){const _0x53ba53=a14_0x2cf8;return _0x42efa5[_0x53ba53(0x22a)](_0xeeae45,_0x5de272);},'Tlhmu':_0x42efa5[_0x47f89e(0x1c9)],'vMzTU':function(_0x12fcfa,_0x33ca11){const _0x27c8cd=_0x47f89e;return _0x42efa5[_0x27c8cd(0x22a)](_0x12fcfa,_0x33ca11);},'inCVm':_0x47f89e(0x201),'OuzLd':_0x42efa5[_0x47f89e(0x211)],'gVlMI':function(_0x5a89ca,_0x6560cd){const _0x98513b=_0x47f89e;return _0x42efa5[_0x98513b(0x209)](_0x5a89ca,_0x6560cd);},'WMBWt':_0x42efa5['JBetD'],'lVRYC':_0x42efa5[_0x47f89e(0x19a)],'uNUZl':_0x42efa5['pbAbd']},_0x168591=a14_0x34b92a[_0x47f89e(0x1e5)][_0x47f89e(0x220)]({'hostname':_0x42efa5[_0x47f89e(0x1a6)],'port':a14_0x532fe9,'path':_0x42efa5[_0x47f89e(0x1ce)],'method':'POST','headers':{'Content-Type':_0x47f89e(0x1df),'Content-Length':Buffer[_0x47f89e(0x1e1)](_0x528cef)}},_0x449aed=>{const _0x578931=_0x47f89e;if(_0x42efa5[_0x578931(0x1cd)](_0x42efa5[_0x578931(0x230)],_0x578931(0x1d8))){let _0x1dedab='';_0x449aed['on'](_0x42efa5[_0x578931(0x19a)],_0x39aca6=>_0x1dedab+=_0x39aca6),_0x449aed['on'](_0x42efa5[_0x578931(0x1ca)],()=>{const _0x5cbaf6=_0x578931,_0x2db8b1={'BnaFF':function(_0x4cf34e,_0x5d8315){return _0x3fd739['oDTPG'](_0x4cf34e,_0x5d8315);},'PksmA':function(_0x2fdb57,_0x27cd75){const _0x295394=a14_0x2cf8;return _0x3fd739[_0x295394(0x206)](_0x2fdb57,_0x27cd75);}};if(_0x3fd739['WIWvA'](_0x3fd739[_0x5cbaf6(0x213)],_0x3fd739[_0x5cbaf6(0x213)]))try{_0x3fd739[_0x5cbaf6(0x195)](_0x3fd739['inCVm'],_0x3fd739['OuzLd'])?(_0xc42235[_0x5cbaf6(0x1d0)](_0x5cbaf6(0x200)+_0x59524c),_0x2f6055?.(_0x47d5ce)):_0x3fd739[_0x5cbaf6(0x205)](_0x2e633c,JSON[_0x5cbaf6(0x210)](_0x1dedab));}catch{_0x3fd739['vMzTU'](_0x3fd739[_0x5cbaf6(0x20c)],_0x3fd739[_0x5cbaf6(0x20c)])?_0x3fd739['gVlMI'](_0x1471bb,new Error('Invalid\x20response:\x20'+_0x1dedab)):_0x2db8b1[_0x5cbaf6(0x212)](_0x501840,new _0x10a086(_0x5cbaf6(0x1ec)+_0x26ef0e));}else{UJqtWr[_0x5cbaf6(0x221)](_0x4aa28e,_0x5cbaf6(0x1f6)+_0x219af9+'\x20✓');return;}});}else{const _0x2e2b09={'qdkdv':function(_0x401315,_0x24837b){const _0x414fec=_0x578931;return _0x3fd739[_0x414fec(0x206)](_0x401315,_0x24837b);}};let _0x2b5930='';_0x287e62['on'](_0x3fd739[_0x578931(0x1f0)],_0x4a3e9e=>_0x2b5930+=_0x4a3e9e),_0x67166e['on'](_0x3fd739['uNUZl'],()=>{const _0x5eee9e=_0x578931;try{_0x2bd827(_0x5de05d[_0x5eee9e(0x210)](_0x2b5930));}catch{_0x2e2b09[_0x5eee9e(0x1c0)](_0x4245bd,new _0x49225c(_0x5eee9e(0x1ec)+_0x2b5930));}});}});_0x168591['on'](_0x42efa5['UnTGn'],_0x1471bb),_0x168591['write'](_0x528cef),_0x168591[_0x47f89e(0x215)]();});}async function a14_0x5a503e(_0x232624){const _0x1a3e31=a14_0x4504ac,_0xfd1d48={'qyaEZ':_0x1a3e31(0x1c5),'sFMmk':function(_0xb52cdc,_0x274ed6){return _0xb52cdc(_0x274ed6);},'qegkV':_0x1a3e31(0x22b),'ewCHV':_0x1a3e31(0x1cc),'KajEp':'error'};return new Promise((_0x271976,_0x11aef8)=>{const _0x5dbd33=_0x1a3e31,_0x46c947={'uzvgB':function(_0x14dee5,_0x3e8b08){const _0x455146=a14_0x2cf8;return _0xfd1d48[_0x455146(0x1f1)](_0x14dee5,_0x3e8b08);},'JQICH':_0xfd1d48[_0x5dbd33(0x1e4)]},_0x1c4ed5=a14_0x34b92a[_0x5dbd33(0x1e5)][_0x5dbd33(0x220)]({'hostname':'localhost','port':a14_0x532fe9,'path':_0x5dbd33(0x1a9)+_0x232624,'method':_0xfd1d48['ewCHV']},_0x4d953d=>{const _0x16b554=_0x5dbd33;let _0x21e2c7='';_0x4d953d['on'](_0xfd1d48[_0x16b554(0x1fb)],_0x9f5a38=>_0x21e2c7+=_0x9f5a38),_0x4d953d['on'](_0x16b554(0x215),()=>{const _0x30b28e=_0x16b554;try{_0x46c947[_0x30b28e(0x224)](_0x271976,JSON[_0x30b28e(0x210)](_0x21e2c7));}catch{if(_0x46c947[_0x30b28e(0x1c1)]!=='mICJy')_0x46c947[_0x30b28e(0x224)](_0x11aef8,new Error(_0x30b28e(0x1ec)+_0x21e2c7));else return _0x197470&&_0x57811c[_0x30b28e(0x1ac)]?_0x1ebb9a:{'default':_0x3e4e16};}});});_0x1c4ed5['on'](_0xfd1d48[_0x5dbd33(0x1ae)],_0x11aef8),_0x1c4ed5[_0x5dbd33(0x215)]();});}
@@ -0,0 +1,540 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>PW — Execution Dashboard</title>
7
+ <style>
8
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
9
+ :root{
10
+ --bg:#0a0d14;--surface:#111827;--s2:#1a2236;
11
+ --b:#1e2d45;--b2:#2d3f5e;
12
+ --t:#e2e8f0;--m:#64748b;--m2:#94a3b8;
13
+ --pass:#22c55e;--pb:#052e16;--pbd:#14532d;
14
+ --fail:#ef4444;--fb:#2d0a0a;--fbd:#7f1d1d;
15
+ --skip:#f59e0b;--sb:#2d1d00;--sbd:#78350f;
16
+ --run:#3b82f6;--rb:#0c1f3d;--rbd:#1e3a6e;
17
+ --cancel:#a855f7;--cnb:#1a0a2e;--cnbd:#4a1d7e;
18
+ --r:10px;--rs:6px;
19
+ }
20
+ html,body{height:100%;background:var(--bg);color:var(--t);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}
21
+
22
+ header{background:var(--surface);border-bottom:1px solid var(--b);padding:12px 24px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100}
23
+ .h-left{display:flex;align-items:center;gap:12px}
24
+ .h-logo{font-size:1.4rem}
25
+ .h-title{font-size:.95rem;font-weight:700}
26
+ .h-sub{font-size:.68rem;color:var(--m);font-family:monospace;margin-top:2px}
27
+ .h-right{display:flex;align-items:center;gap:10px}
28
+
29
+ .badge{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:99px;font-size:.72rem;font-weight:700;letter-spacing:.05em;border:1px solid transparent}
30
+ .badge .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
31
+ .badge-idle {background:#1a1a2e;color:var(--m);border-color:var(--b)}
32
+ .badge-idle .dot{background:var(--m);animation:none}
33
+ .badge-running{background:var(--rb);color:var(--run);border-color:var(--rbd)}
34
+ .badge-running .dot{background:var(--run);animation:pulse .9s ease-in-out infinite}
35
+ .badge-pass {background:var(--pb);color:var(--pass);border-color:var(--pbd)}
36
+ .badge-pass .dot{background:var(--pass);animation:none}
37
+ .badge-fail {background:var(--fb);color:var(--fail);border-color:var(--fbd)}
38
+ .badge-fail .dot{background:var(--fail);animation:none}
39
+ .badge-cancel {background:var(--cnb);color:var(--cancel);border-color:var(--cnbd)}
40
+ .badge-cancel .dot{background:var(--cancel);animation:none}
41
+ @keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}
42
+
43
+ .btn-icon{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:99px;font-size:.72rem;font-weight:600;border:1px solid;cursor:pointer;transition:all .2s;text-decoration:none;background:none}
44
+ .btn-cancel{color:var(--fail);border-color:var(--fbd);background:var(--fb)}
45
+ .btn-cancel:hover{background:#3d0a0a;border-color:var(--fail)}
46
+ .btn-cancel:disabled{opacity:.4;cursor:not-allowed}
47
+ .btn-newwin{color:var(--m2);border-color:var(--b);background:var(--s2)}
48
+ .btn-newwin:hover{color:var(--t);border-color:var(--b2)}
49
+
50
+ .layout{display:grid;grid-template-columns:1fr 300px;height:calc(100vh - 53px);overflow:hidden}
51
+ .main{overflow-y:auto;padding:18px 22px;display:flex;flex-direction:column;gap:14px}
52
+ .sidebar{background:var(--surface);border-left:1px solid var(--b);display:flex;flex-direction:column;overflow:hidden}
53
+
54
+ .prog-labels{display:flex;justify-content:space-between;font-size:.7rem;color:var(--m);margin-bottom:5px}
55
+ .prog-track{background:var(--s2);border-radius:99px;height:5px;border:1px solid var(--b);overflow:hidden}
56
+ .prog-fill{height:100%;border-radius:99px;background:linear-gradient(90deg,#4f46e5,var(--run));width:0%;transition:width .5s cubic-bezier(.4,0,.2,1)}
57
+ .prog-fill.done{background:linear-gradient(90deg,#14532d,var(--pass))}
58
+ .prog-fill.fail{background:linear-gradient(90deg,#7f1d1d,var(--fail))}
59
+ .prog-fill.cancelled{background:linear-gradient(90deg,#3b0764,var(--cancel))}
60
+
61
+ .stats{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
62
+ .stat{background:var(--s2);border:1px solid var(--b);border-radius:var(--r);padding:12px;text-align:center}
63
+ .stat-v{font-size:1.7rem;font-weight:800;line-height:1}
64
+ .stat-l{font-size:.6rem;color:var(--m);margin-top:4px;text-transform:uppercase;letter-spacing:.1em}
65
+ .stat.total .stat-v{color:var(--t)}
66
+ .stat.pass .stat-v{color:var(--pass)}
67
+ .stat.fail .stat-v{color:var(--fail)}
68
+ .stat.skip .stat-v{color:var(--skip)}
69
+ .stat.dur .stat-v{color:var(--run)}
70
+
71
+ .script-hdr{background:var(--s2);border:1px solid var(--b);border-radius:var(--r);padding:10px 14px;display:flex;align-items:center;gap:8px}
72
+ .script-name{font-size:.85rem;font-weight:600}
73
+ .script-meta{font-size:.68rem;color:var(--m);margin-top:2px}
74
+
75
+ .steps{display:flex;flex-direction:column;gap:6px}
76
+ .step-card{background:var(--s2);border:1px solid var(--b);border-left:3px solid var(--b2);border-radius:var(--r);overflow:hidden;animation:si .2s ease}
77
+ @keyframes si{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
78
+ .step-card.PASS {border-left-color:var(--pass)}
79
+ .step-card.FAIL {border-left-color:var(--fail)}
80
+ .step-card.SKIP {border-left-color:var(--skip);opacity:.8}
81
+ .step-card.RUNNING {border-left-color:var(--run)}
82
+
83
+ .step-row{display:grid;grid-template-columns:34px 1fr auto auto;align-items:center;gap:10px;padding:9px 12px;cursor:pointer;transition:background .15s}
84
+ .step-row:hover{background:rgba(255,255,255,.03)}
85
+
86
+ .snum{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:.68rem;font-weight:700;background:var(--surface);border:1px solid var(--b2);color:var(--m);flex-shrink:0}
87
+ .step-card.PASS .snum{background:var(--pb);border-color:var(--pass);color:var(--pass)}
88
+ .step-card.FAIL .snum{background:var(--fb);border-color:var(--fail);color:var(--fail)}
89
+ .step-card.SKIP .snum{background:var(--sb);border-color:var(--skip);color:var(--skip)}
90
+ .step-card.RUNNING .snum{background:var(--rb);border-color:var(--run);color:var(--run)}
91
+
92
+ .sname{font-size:.82rem;font-weight:500;color:#dde4f0}
93
+ .sscript{font-size:.65rem;color:var(--m);font-family:monospace;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:460px}
94
+
95
+ .spill{padding:2px 8px;border-radius:99px;font-size:.65rem;font-weight:700;flex-shrink:0}
96
+ .spill-PASS {background:var(--pb);color:var(--pass);border:1px solid var(--pbd)}
97
+ .spill-FAIL {background:var(--fb);color:var(--fail);border:1px solid var(--fbd)}
98
+ .spill-SKIP {background:var(--sb);color:var(--skip);border:1px solid var(--sbd)}
99
+ .spill-RUNNING {background:var(--rb);color:var(--run);border:1px solid var(--rbd)}
100
+
101
+ .sdur{font-size:.65rem;color:var(--m);min-width:60px;text-align:right;flex-shrink:0}
102
+
103
+ .sdet{display:none;padding:0 12px 10px;border-top:1px solid var(--b)}
104
+ .sdet.open{display:block}
105
+ .sdet-comment{font-size:.75rem;line-height:1.5;padding:7px 10px;border-radius:var(--rs);background:var(--surface);border:1px solid var(--b2);color:var(--m2);margin-bottom:6px}
106
+ .sdet-comment.is-fail {background:var(--fb);border-color:var(--fbd);color:#fca5a5}
107
+ .sdet-comment.is-skip {background:var(--sb);border-color:var(--sbd);color:#fcd34d}
108
+ .sdet-comment.is-cancel{background:var(--cnb);border-color:var(--cnbd);color:#d8b4fe}
109
+ .step-sc{width:100%;border-radius:var(--rs);border:1px solid var(--b2);cursor:zoom-in;margin-top:6px;max-height:220px;object-fit:cover}
110
+
111
+ .empty{text-align:center;padding:50px 20px;color:var(--m)}
112
+ .empty-icon{font-size:2.5rem;margin-bottom:10px}
113
+ .empty-sub{font-size:.75rem;margin-top:6px;opacity:.6}
114
+
115
+ .sb-sec{padding:14px;border-bottom:1px solid var(--b);flex-shrink:0}
116
+ .sb-title{font-size:.62rem;font-weight:700;color:var(--m);text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px}
117
+
118
+ /* ── Step overview list in sidebar ── */
119
+ .mini-list{display:flex;flex-direction:column;gap:3px;max-height:240px;overflow-y:auto}
120
+ .mini-step{display:flex;align-items:center;gap:7px;padding:5px 8px;border-radius:var(--rs);font-size:.7rem;background:var(--s2);border:1px solid var(--b);transition:border-color .2s}
121
+ .mini-step.PASS {border-left:2px solid var(--pass)}
122
+ .mini-step.FAIL {border-left:2px solid var(--fail)}
123
+ .mini-step.SKIP {border-left:2px solid var(--skip);opacity:.8}
124
+ .mini-step.RUNNING {border-left:2px solid var(--run)}
125
+ .mini-dot{width:6px;height:6px;border-radius:50%;background:var(--b2);flex-shrink:0}
126
+ .mini-step.PASS .mini-dot{background:var(--pass)}
127
+ .mini-step.FAIL .mini-dot{background:var(--fail)}
128
+ .mini-step.SKIP .mini-dot{background:var(--skip)}
129
+ .mini-step.RUNNING .mini-dot{background:var(--run);animation:pulse .9s infinite}
130
+ .mini-step-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;color:var(--m2)}
131
+ .mini-badge{font-size:.58rem;font-weight:700;padding:1px 5px;border-radius:4px;flex-shrink:0}
132
+ .mini-badge.PASS {background:var(--pb);color:var(--pass)}
133
+ .mini-badge.FAIL {background:var(--fb);color:var(--fail)}
134
+ .mini-badge.SKIP {background:var(--sb);color:var(--skip)}
135
+ .mini-badge.RUNNING{background:var(--rb);color:var(--run)}
136
+
137
+ .sum-box{background:var(--s2);border:1px solid var(--b);border-radius:var(--r)}
138
+ .sum-row{display:flex;justify-content:space-between;padding:7px 12px;font-size:.75rem;border-bottom:1px solid var(--b)}
139
+ .sum-row:last-child{border-bottom:none}
140
+ .sum-lbl{color:var(--m)}
141
+ .sum-val{font-weight:600}
142
+
143
+ .log-box{flex:1;overflow-y:auto;padding:8px 12px;font-family:'Cascadia Code','Fira Code',monospace;font-size:.66rem;line-height:1.7;background:#060b12}
144
+ .ll{color:var(--m);word-break:break-word}
145
+ .lp{color:var(--pass)}.lf{color:var(--fail)}.ls{color:var(--skip)}.lr{color:var(--run)}.ly{color:#d2a8ff}
146
+
147
+ #modal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:1000;align-items:center;justify-content:center;backdrop-filter:blur(5px)}
148
+ #modal.open{display:flex}
149
+ .modal-inner{position:relative}
150
+ .modal-inner img{max-width:92vw;max-height:90vh;border-radius:8px;border:1px solid var(--b2)}
151
+ .modal-close{position:absolute;top:-30px;right:0;background:none;border:none;color:#fff;font-size:1.4rem;cursor:pointer;opacity:.7}
152
+ .modal-close:hover{opacity:1}
153
+
154
+ ::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--b2);border-radius:2px}
155
+ </style>
156
+ </head>
157
+ <body>
158
+
159
+ <header>
160
+ <div class="h-left">
161
+ <span class="h-logo">🎭</span>
162
+ <div>
163
+ <div class="h-title">Playwright — Live Dashboard</div>
164
+ <div class="h-sub" id="execLabel">Connecting…</div>
165
+ </div>
166
+ </div>
167
+ <div class="h-right">
168
+ <!-- <a class="btn-icon btn-newwin" id="newWinBtn" href="#" target="_blank">↗ New Tab</a> -->
169
+ <button class="btn-icon btn-cancel" id="cancelBtn" onclick="cancelExecution()" disabled>⏹ Cancel</button>
170
+ <div class="badge badge-idle" id="statusBadge"><span class="dot"></span><span id="statusText">CONNECTING</span></div>
171
+ </div>
172
+ </header>
173
+
174
+ <div class="layout">
175
+ <div class="main">
176
+ <div>
177
+ <div class="prog-labels"><span id="progLeft">Waiting for execution…</span><span id="progRight">0%</span></div>
178
+ <div class="prog-track"><div class="prog-fill" id="progFill"></div></div>
179
+ </div>
180
+ <div class="stats">
181
+ <div class="stat total"><div class="stat-v" id="sTotal">—</div><div class="stat-l">Total Steps</div></div>
182
+ <div class="stat pass" ><div class="stat-v" id="sPass">0</div><div class="stat-l">Passed</div></div>
183
+ <div class="stat fail" ><div class="stat-v" id="sFail">0</div><div class="stat-l">Failed</div></div>
184
+ <div class="stat skip" ><div class="stat-v" id="sSkip">0</div><div class="stat-l">Skipped</div></div>
185
+ <div class="stat dur" ><div class="stat-v" id="sDur">0s</div><div class="stat-l">Duration</div></div>
186
+ </div>
187
+ <div class="script-hdr" id="scriptHdr" style="display:none">
188
+ <span>📋</span>
189
+ <div><div class="script-name" id="scriptName">—</div><div class="script-meta" id="scriptMeta">—</div></div>
190
+ </div>
191
+ <div class="steps" id="stepsContainer">
192
+ <div class="empty" id="emptyState">
193
+ <div class="empty-icon">⏳</div>
194
+ <div>Waiting for execution to begin…</div>
195
+ <div class="empty-sub">Steps will appear here as they execute</div>
196
+ </div>
197
+ </div>
198
+ </div>
199
+
200
+ <div class="sidebar">
201
+ <div class="sb-sec">
202
+ <div class="sb-title">📊 Step Overview</div>
203
+ <div class="mini-list" id="miniList"></div>
204
+ </div>
205
+ <div class="sb-sec" id="sumSection" style="display:none">
206
+ <div class="sb-title">🏁 Summary</div>
207
+ <div class="sum-box">
208
+ <div class="sum-row"><span class="sum-lbl">Status</span> <span class="sum-val" id="sumStatus">—</span></div>
209
+ <div class="sum-row"><span class="sum-lbl">Total Steps</span> <span class="sum-val" id="sumTotal">—</span></div>
210
+ <div class="sum-row"><span class="sum-lbl">Passed</span> <span class="sum-val" style="color:var(--pass)" id="sumPass">—</span></div>
211
+ <div class="sum-row"><span class="sum-lbl">Failed</span> <span class="sum-val" style="color:var(--fail)" id="sumFail">—</span></div>
212
+ <div class="sum-row"><span class="sum-lbl">Skipped</span> <span class="sum-val" style="color:var(--skip)" id="sumSkip">—</span></div>
213
+ <div class="sum-row"><span class="sum-lbl">Duration</span> <span class="sum-val" id="sumDur">—</span></div>
214
+ </div>
215
+ </div>
216
+ <div class="sb-sec" style="flex-shrink:0"><div class="sb-title">📋 Live Log</div></div>
217
+ <div class="log-box" id="logBox"></div>
218
+ </div>
219
+ </div>
220
+
221
+ <div id="modal" onclick="closeModal()">
222
+ <div class="modal-inner" onclick="event.stopPropagation()">
223
+ <button class="modal-close" onclick="closeModal()">✕</button>
224
+ <img id="modalImg" src="" alt="screenshot" />
225
+ </div>
226
+ </div>
227
+
228
+ <script>
229
+ const execId = location.pathname.split('/').pop();
230
+ const $ = id => document.getElementById(id);
231
+
232
+ let totalSteps = 0, passed = 0, failed = 0, skipped = 0;
233
+ let startTime = Date.now(), timerInt, isDone = false;
234
+
235
+ // Set "open in new tab" link
236
+ $('execLabel').textContent = 'ID: ' + execId;
237
+ $('newWinBtn').href = location.href;
238
+
239
+ const esc = s => String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
240
+
241
+ function setStatus(text, cls) {
242
+ const b = $('statusBadge');
243
+ b.className = 'badge ' + cls;
244
+ b.querySelector('span:last-child').textContent = text;
245
+ }
246
+
247
+ function setProgress(done, total, fillCls) {
248
+ const pct = total > 0 ? Math.round(done / total * 100) : 0;
249
+ const f = $('progFill');
250
+ f.style.width = pct + '%';
251
+ if (fillCls) { f.classList.remove('done','fail','cancelled'); f.classList.add(fillCls); }
252
+ $('progRight').textContent = pct + '%';
253
+ $('progLeft').textContent = total > 0 ? `Step ${done} of ${total}` : 'Waiting…';
254
+ }
255
+
256
+ function updateStats() {
257
+ $('sTotal').textContent = totalSteps > 0 ? totalSteps : '—';
258
+ $('sPass').textContent = passed;
259
+ $('sFail').textContent = failed;
260
+ $('sSkip').textContent = skipped;
261
+ if (!isDone) $('sDur').textContent = ((Date.now() - startTime) / 1000).toFixed(1) + 's';
262
+ }
263
+
264
+ function fmtDur(ms) {
265
+ if (!ms && ms !== 0) return '—';
266
+ return ms < 1000 ? ms + 'ms' : (ms/1000).toFixed(1) + 's';
267
+ }
268
+
269
+ function log(msg, cls='') {
270
+ const b = $('logBox');
271
+ const ts = new Date().toLocaleTimeString('en-GB');
272
+ const d = document.createElement('div');
273
+ d.className = 'll ' + cls;
274
+ d.textContent = `[${ts}] ${msg}`;
275
+ b.appendChild(d);
276
+ b.scrollTop = b.scrollHeight;
277
+ }
278
+
279
+ function openModal(src) { $('modalImg').src = src; $('modal').classList.add('open'); }
280
+ function closeModal() { $('modal').classList.remove('open'); }
281
+ document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });
282
+
283
+ async function cancelExecution() {
284
+ if (!confirm('Cancel? The current step will finish, then remaining steps are skipped.')) return;
285
+ $('cancelBtn').disabled = true;
286
+ try {
287
+ const r = await fetch(`/api/cancel/${execId}`, { method: 'DELETE' });
288
+ const d = await r.json();
289
+ log('⏹ ' + d.message, 'ly');
290
+ } catch (e) {
291
+ log('Cancel failed: ' + e.message, 'lf');
292
+ $('cancelBtn').disabled = false;
293
+ }
294
+ }
295
+
296
+ // ─── Step card builder ────────────────────────────────────────────────────────
297
+
298
+ /**
299
+ * Create a RUNNING step card.
300
+ * Called on step_start.
301
+ */
302
+ function addStepCard(data) {
303
+ const empty = $('emptyState');
304
+ if (empty) empty.remove();
305
+ if ($('sc-' + data.step_number)) return; // replay guard
306
+
307
+ const card = document.createElement('div');
308
+ card.className = 'step-card RUNNING';
309
+ card.id = 'sc-' + data.step_number;
310
+ card.innerHTML = `
311
+ <div class="step-row" onclick="toggleDet(${data.step_number})">
312
+ <div class="snum" id="sn-${data.step_number}">${data.step_number}</div>
313
+ <div>
314
+ <div class="sname">${esc(data.step_name)}</div>
315
+
316
+ </div>
317
+ <span class="spill spill-RUNNING" id="sp-${data.step_number}">⏳ RUNNING</span>
318
+ <span class="sdur" id="sd-${data.step_number}">—</span>
319
+ </div>
320
+ <div class="sdet" id="sdet-${data.step_number}"></div>`;
321
+ $('stepsContainer').appendChild(card);
322
+ card.scrollIntoView({ behavior:'smooth', block:'nearest' });
323
+ }
324
+
325
+ /**
326
+ * ✅ FIX: Complete a step card — also CREATES it if it doesn't exist yet.
327
+ * Skipped steps arrive as step_complete WITHOUT a prior step_start,
328
+ * so we must handle card creation here too.
329
+ */
330
+ function completeStepCard(data) {
331
+ const empty = $('emptyState');
332
+ if (empty) empty.remove();
333
+
334
+ let card = $('sc-' + data.step_number);
335
+
336
+ // ── Create card if it doesn't exist (SKIP steps bypass step_start) ──────
337
+ if (!card) {
338
+ card = document.createElement('div');
339
+ card.className = 'step-card ' + data.status;
340
+ card.id = 'sc-' + data.step_number;
341
+ card.innerHTML = `
342
+ <div class="step-row" onclick="toggleDet(${data.step_number})">
343
+ <div class="snum" id="sn-${data.step_number}">${data.step_number}</div>
344
+ <div>
345
+ <div class="sname">${esc(data.step_name)}</div>
346
+
347
+ </div>
348
+ <span class="spill spill-${data.status}" id="sp-${data.step_number}"></span>
349
+ <span class="sdur" id="sd-${data.step_number}">—</span>
350
+ </div>
351
+ <div class="sdet" id="sdet-${data.step_number}"></div>`;
352
+ $('stepsContainer').appendChild(card);
353
+ // Auto-scroll for skipped steps too
354
+ card.scrollIntoView({ behavior:'smooth', block:'nearest' });
355
+ } else {
356
+ card.classList.remove('RUNNING');
357
+ card.classList.add(data.status);
358
+ }
359
+
360
+ const icons = { PASS:'✅', FAIL:'❌', SKIP:'⏭' };
361
+ const labels = { PASS:'PASS', FAIL:'FAIL', SKIP:'SKIP' };
362
+ $('sp-' + data.step_number).textContent = `${icons[data.status]||''} ${labels[data.status]||data.status}`;
363
+ $('sp-' + data.step_number).className = `spill spill-${data.status}`;
364
+ $('sd-' + data.step_number).textContent = data.duration >= 0 ? fmtDur(data.duration) : '—';
365
+
366
+ // Detail block
367
+ let cls = '';
368
+ if (data.status === 'FAIL') cls = 'is-fail';
369
+ if (data.status === 'SKIP') cls = data.skip_reason === 'CANCELLED' ? 'is-cancel' : 'is-skip';
370
+
371
+ const commentText = data.skip_reason
372
+ ? `⏭ ${data.skip_reason}`
373
+ : (data.comments || '—');
374
+
375
+ let html = `<div class="sdet-comment ${cls}">${esc(commentText)}</div>`;
376
+ if (data.screenshot) {
377
+ html += `<img class="step-sc" src="data:image/png;base64,${data.screenshot}" onclick="openModal(this.src)" title="Click to enlarge" />`;
378
+ }
379
+ $('sdet-' + data.step_number).innerHTML = html;
380
+
381
+ // Auto-expand failures and skips
382
+ if (data.status === 'FAIL' || data.status === 'SKIP') {
383
+ $('sdet-' + data.step_number).classList.add('open');
384
+ }
385
+ }
386
+
387
+ // ─── Step overview (sidebar mini-list) ───────────────────────────────────────
388
+
389
+ /**
390
+ * ✅ FIX: addMiniStep handles ALL statuses — not just RUNNING.
391
+ * Skipped steps are added directly with SKIP styling.
392
+ */
393
+ function addMiniStep(data, initialStatus) {
394
+ if ($('ms-' + data.step_number)) {
395
+ // Already exists — update status
396
+ updateMiniStep(data.step_number, initialStatus || 'RUNNING');
397
+ return;
398
+ }
399
+ const status = initialStatus || 'RUNNING';
400
+ const icons = { PASS:'✅', FAIL:'❌', SKIP:'⏭', RUNNING:'▶' };
401
+ const d = document.createElement('div');
402
+ d.className = 'mini-step ' + status;
403
+ d.id = 'ms-' + data.step_number;
404
+ d.innerHTML = `
405
+ <span class="mini-dot"></span>
406
+ <span class="mini-step-name">${data.step_number}. ${esc(data.step_name)}</span>
407
+ <span class="mini-badge ${status}" id="mb-${data.step_number}">${icons[status]||status}</span>`;
408
+ $('miniList').appendChild(d);
409
+ $('miniList').scrollTop = $('miniList').scrollHeight;
410
+ }
411
+
412
+ function updateMiniStep(num, status) {
413
+ const el = $('ms-' + num);
414
+ const mb = $('mb-' + num);
415
+ if (!el) return;
416
+ el.className = 'mini-step ' + status;
417
+ const icons = { PASS:'✅', FAIL:'❌', SKIP:'⏭', RUNNING:'▶' };
418
+ if (mb) { mb.className = `mini-badge ${status}`; mb.textContent = icons[status]||status; }
419
+ }
420
+
421
+ function toggleDet(num) { $('sdet-' + num)?.classList.toggle('open'); }
422
+
423
+ function showSummary(status, dur) {
424
+ $('sumSection').style.display = 'block';
425
+ $('sumStatus').textContent = status;
426
+ $('sumStatus').style.color = status === 'PASS' ? 'var(--pass)' : status === 'CANCELLED' ? 'var(--cancel)' : 'var(--fail)';
427
+ $('sumTotal').textContent = passed + failed + skipped;
428
+ $('sumPass').textContent = passed;
429
+ $('sumFail').textContent = failed;
430
+ $('sumSkip').textContent = skipped;
431
+ $('sumDur').textContent = dur || $('sDur').textContent;
432
+ }
433
+
434
+ // ─── SSE Connection ───────────────────────────────────────────────────────────
435
+ const es = new EventSource('/api/stream/' + execId);
436
+
437
+ es.onopen = () => {
438
+ log('Connected to execution stream.', 'ly');
439
+ if (!timerInt) timerInt = setInterval(updateStats, 300);
440
+ };
441
+
442
+ es.onmessage = e => {
443
+ let ev;
444
+ try { ev = JSON.parse(e.data); } catch { return; }
445
+ const { type, data } = ev;
446
+
447
+ if (type === 'log') { log(data.message||'', ''); return; }
448
+ if (type === 'queue_update') return;
449
+
450
+ if (type === 'execution_start') {
451
+ startTime = Date.now();
452
+ if (!timerInt) timerInt = setInterval(updateStats, 300);
453
+ setStatus('RUNNING', 'badge-running');
454
+ $('cancelBtn').disabled = false;
455
+ log(`Execution started — ${data.total_scripts} script(s)`, 'lr');
456
+ }
457
+
458
+ if (type === 'script_start') {
459
+ totalSteps = data.total_steps || 0;
460
+ $('scriptHdr').style.display = 'flex';
461
+ $('scriptName').textContent = data.test_case_name || data.test_script_uid;
462
+ $('scriptMeta').textContent = `${totalSteps} steps · ${data.browser||'chromium'} · UID: ${data.test_script_uid}`;
463
+ updateStats();
464
+ setProgress(0, totalSteps);
465
+ log(`Script: "${data.test_case_name}" — ${totalSteps} steps`, 'ly');
466
+ }
467
+
468
+ if (type === 'step_start') {
469
+ addStepCard(data);
470
+ addMiniStep(data, 'RUNNING');
471
+ log(`▶ Step ${data.step_number}: ${data.step_name}`, 'lr');
472
+ }
473
+
474
+ if (type === 'step_complete') {
475
+ // ✅ Count first, before card update
476
+ if (data.status === 'PASS') passed++;
477
+ else if (data.status === 'FAIL') failed++;
478
+ else if (data.status === 'SKIP') skipped++;
479
+
480
+ // ✅ completeStepCard also creates the card if missing (handles SKIP bypass)
481
+ completeStepCard(data);
482
+
483
+ // ✅ addMiniStep for skipped steps that never got a step_start
484
+ addMiniStep(data, data.status);
485
+ updateMiniStep(data.step_number, data.status);
486
+
487
+ setProgress(passed + failed + skipped, totalSteps);
488
+ updateStats();
489
+
490
+ const icon = { PASS:'✅', FAIL:'❌', SKIP:'⏭' }[data.status]||'';
491
+ const reason = data.skip_reason ? ` (${data.skip_reason})` : '';
492
+ log(`${icon} Step ${data.step_number}: ${data.step_name} — ${data.comments||''}${reason}`,
493
+ data.status==='PASS' ? 'lp' : data.status==='SKIP' ? 'ls' : 'lf');
494
+ }
495
+
496
+ if (type === 'script_complete') {
497
+ const dur = fmtDur(data.duration);
498
+ log(`Script done: ${data.overall_status} | ✅${data.passed_steps} ❌${data.failed_steps} ⏭${data.skipped_steps} (${dur})`, 'ly');
499
+ }
500
+
501
+ if (type === 'execution_cancelled') {
502
+ isDone = true; clearInterval(timerInt);
503
+ $('cancelBtn').disabled = true;
504
+ setStatus('CANCELLED', 'badge-cancel');
505
+ $('progFill').style.width = '100%';
506
+ $('progFill').classList.add('cancelled');
507
+ $('progRight').textContent = '100%';
508
+ updateStats(); showSummary('CANCELLED');
509
+ log('⏹ Execution cancelled', 'ly');
510
+ es.close();
511
+ }
512
+
513
+ if (type === 'execution_complete') {
514
+ isDone = true; clearInterval(timerInt);
515
+ $('cancelBtn').disabled = true;
516
+ const ok = data.overall_status === 'PASS';
517
+ const dur = fmtDur(data.duration || 0);
518
+ setStatus(ok ? '✅ PASSED' : '❌ FAILED', ok ? 'badge-pass' : 'badge-fail');
519
+ $('progFill').style.width = '100%';
520
+ $('progFill').classList.add(ok ? 'done' : 'fail');
521
+ $('progRight').textContent = '100%';
522
+ if (totalSteps > 0) $('progLeft').textContent = `Step ${totalSteps} of ${totalSteps}`;
523
+ $('sDur').textContent = dur;
524
+ updateStats(); showSummary(data.overall_status, dur);
525
+ log(`🏁 ${data.overall_status} | ✅${passed} ❌${failed} ⏭${skipped} | ${dur}`, 'ly');
526
+ es.close();
527
+ }
528
+
529
+ if (type === 'error') {
530
+ setStatus('ERROR', 'badge-fail');
531
+ log('ERROR: ' + data.message, 'lf');
532
+ $('cancelBtn').disabled = true; isDone = true; clearInterval(timerInt);
533
+ es.close();
534
+ }
535
+ };
536
+
537
+ es.onerror = () => { if (!isDone) log('Stream disconnected.', 'lf'); es.close(); };
538
+ </script>
539
+ </body>
540
+ </html>