lexxit-automation-framework 2.0.4 → 2.0.6

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';const a14_0x5126e4=a14_0x2804;(function(_0x2f9e6b,_0x4a0491){const _0x28cd42=a14_0x2804,_0x165492=_0x2f9e6b();while(!![]){try{const _0x106e51=parseInt(_0x28cd42(0x1c7))/0x1+parseInt(_0x28cd42(0x182))/0x2+parseInt(_0x28cd42(0x16b))/0x3+-parseInt(_0x28cd42(0x180))/0x4*(-parseInt(_0x28cd42(0x131))/0x5)+-parseInt(_0x28cd42(0x1b3))/0x6*(parseInt(_0x28cd42(0x183))/0x7)+-parseInt(_0x28cd42(0x16e))/0x8+parseInt(_0x28cd42(0x197))/0x9*(parseInt(_0x28cd42(0x1b1))/0xa);if(_0x106e51===_0x4a0491)break;else _0x165492['push'](_0x165492['shift']());}catch(_0x484c0a){_0x165492['push'](_0x165492['shift']());}}}(a14_0x5b92,0xd165c));var a14_0x3a5100=this&&this[a14_0x5126e4(0x179)]||function(_0x2b1755){const _0x2dce94=a14_0x5126e4;return _0x2b1755&&_0x2b1755[_0x2dce94(0x158)]?_0x2b1755:{'default':_0x2b1755};};Object[a14_0x5126e4(0x1a6)](exports,a14_0x5126e4(0x158),{'value':!![]}),exports[a14_0x5126e4(0x170)]=a14_0x4fe0c3,exports[a14_0x5126e4(0x19b)]=a14_0x19a632,exports[a14_0x5126e4(0x1bf)]=a14_0x155808,exports[a14_0x5126e4(0x16f)]=a14_0x249dba,exports['ensureFramework']=a14_0x13d31f,exports[a14_0x5126e4(0x1ac)]=a14_0x119a74,exports['cancelExecution']=a14_0x23c4ee;const a14_0x4ec7c5=require(a14_0x5126e4(0x12f)),a14_0x13c62e=require(a14_0x5126e4(0x135)),a14_0x13cfba=a14_0x3a5100(require(a14_0x5126e4(0x151))),a14_0x18d45d=a14_0x3a5100(require(a14_0x5126e4(0x19a))),a14_0x3f5375=a14_0x3a5100(require('fs')),a14_0x300042=(0x0,a14_0x13c62e[a14_0x5126e4(0x193)])(a14_0x4ec7c5[a14_0x5126e4(0x15b)]),a14_0x49a9d3=(0x0,a14_0x13c62e[a14_0x5126e4(0x193)])(a14_0x4ec7c5[a14_0x5126e4(0x1b8)]),a14_0x3199a4=parseInt(process.env.FRAMEWORK_PORT||a14_0x5126e4(0x190),0xa),a14_0x2e96ed=a14_0x5126e4(0x1bd)+a14_0x3199a4,a14_0x10fb60=a14_0x13cfba[a14_0x5126e4(0x168)][a14_0x5126e4(0x199)](process.env.HOME||process.env.USERPROFILE||a14_0x5126e4(0x18a),a14_0x5126e4(0x11b)),a14_0x211470=a14_0x13cfba[a14_0x5126e4(0x168)][a14_0x5126e4(0x199)](a14_0x10fb60,a14_0x5126e4(0x11a)),a14_0x4de06f=a14_0x13cfba[a14_0x5126e4(0x168)][a14_0x5126e4(0x199)](a14_0x10fb60,'server.log'),a14_0x1a061e=a14_0x13cfba[a14_0x5126e4(0x168)][a14_0x5126e4(0x199)](a14_0x10fb60,a14_0x5126e4(0x136)),a14_0x55db0e=a14_0x5126e4(0x185),a14_0x17ac79=process.env.FRAMEWORK_BUNDLE_URL||a14_0x5126e4(0x1a9);async function a14_0x4fe0c3(){const _0x26aefc=a14_0x5126e4,_0x50be83={'fToik':_0x26aefc(0x191),'UfQNY':function(_0x29ea03,_0x202afa){return _0x29ea03!==_0x202afa;},'eULVo':_0x26aefc(0x15d),'ipDXn':_0x26aefc(0x164),'ghxbs':function(_0x4892f1,_0x183789){return _0x4892f1(_0x183789);}};return new Promise(_0x12cf89=>{const _0x1d6975=_0x26aefc,_0x2a85cd=a14_0x18d45d['default'][_0x1d6975(0x121)](a14_0x2e96ed+_0x1d6975(0x1a2),{'timeout':0x320},_0x22b665=>_0x12cf89(_0x22b665['statusCode']===0xc8));_0x2a85cd['on'](_0x1d6975(0x15a),()=>_0x12cf89(![])),_0x2a85cd['on'](_0x1d6975(0x152),()=>{const _0x37d1ac=_0x1d6975,_0x58c686={'zwqTe':_0x50be83[_0x37d1ac(0x1ad)]};if(_0x50be83['UfQNY'](_0x50be83['eULVo'],_0x50be83['ipDXn']))_0x2a85cd['destroy'](),_0x50be83[_0x37d1ac(0x140)](_0x12cf89,![]);else{try{if(_0x308341[_0x37d1ac(0x168)]['existsSync'](_0x554510))return _0x53aab2[_0x37d1ac(0x168)]['readFileSync'](_0x1783c9,_0x58c686[_0x37d1ac(0x1b6)])[_0x37d1ac(0x124)]();}catch{}return null;}});});}async function a14_0x19a632(){const _0x488e4c=a14_0x5126e4;try{if(a14_0x3f5375[_0x488e4c(0x168)][_0x488e4c(0x116)](a14_0x1a061e))return a14_0x3f5375[_0x488e4c(0x168)][_0x488e4c(0x149)](a14_0x1a061e,_0x488e4c(0x191))[_0x488e4c(0x124)]();}catch{}return null;}async function a14_0x155808(_0x430a45){const _0xb766f4=a14_0x5126e4,_0xe04472={'qIRaM':function(_0x109b03,_0x4b0776){return _0x109b03(_0x4b0776);},'rMzcA':function(_0x1069cb,_0x36aad4){return _0x1069cb!==_0x36aad4;},'MffZd':'FDcMG','QoNoT':_0xb766f4(0x169),'Wubct':function(_0x80798,_0x496468){return _0x80798(_0x496468);},'ljNyR':function(_0x2e0b25){return _0x2e0b25();},'tCYXl':_0xb766f4(0x133),'VXltx':_0xb766f4(0x155),'QoSjx':_0xb766f4(0x159),'awJMc':function(_0x50b75a,_0xdf8887){return _0x50b75a(_0xdf8887);},'VRccR':_0xb766f4(0x146),'DcQWi':_0xb766f4(0x162),'ZkSxu':_0xb766f4(0x142),'FeVkn':function(_0x546e9d,_0x1b0063){return _0x546e9d(_0x1b0063);},'YUsZS':_0xb766f4(0x143),'HuLfa':function(_0x221b66,_0x247e97,_0x4c33c9){return _0x221b66(_0x247e97,_0x4c33c9);},'uyqqw':_0xb766f4(0x1a0)},_0x4b4f8d=_0x5b5082=>{const _0x3c1989=_0xb766f4;console['log'](_0x3c1989(0x128)+_0x5b5082),_0x430a45?.(_0x5b5082);};a14_0x3f5375[_0xb766f4(0x168)]['mkdirSync'](a14_0x10fb60,{'recursive':!![]}),_0xe04472[_0xb766f4(0x18d)](_0x4b4f8d,_0xb766f4(0x14d)+a14_0x55db0e+_0xb766f4(0x189)+a14_0x10fb60+'…');const _0xa417e5=a14_0x17ac79+_0xb766f4(0x163)+a14_0x55db0e+_0xb766f4(0x126),_0x58018f=a14_0x13cfba[_0xb766f4(0x168)][_0xb766f4(0x199)](a14_0x10fb60,_0xb766f4(0x13f));_0x4b4f8d(_0xe04472[_0xb766f4(0x187)]),await new Promise((_0x5ec34d,_0x3d0afa)=>{const _0x291b7a=_0xb766f4,_0x2b0b66={'eURmV':function(_0x1085d9,_0x5083c7){const _0x5e4d54=a14_0x2804;return _0xe04472[_0x5e4d54(0x167)](_0x1085d9,_0x5083c7);},'AtWbs':function(_0x10aff0){return _0xe04472['ljNyR'](_0x10aff0);},'BYYzN':_0xe04472[_0x291b7a(0x12b)],'MLTsU':_0x291b7a(0x146)},_0x134370=a14_0x3f5375[_0x291b7a(0x168)][_0x291b7a(0x17e)](_0x58018f);a14_0x18d45d['default'][_0x291b7a(0x121)](_0xa417e5[_0x291b7a(0x129)](_0xe04472[_0x291b7a(0x19c)],_0xe04472[_0x291b7a(0x1c6)]),_0x594ffd=>{const _0x1549dc=_0x291b7a,_0x355231={'oxfRp':function(_0x1db9c1,_0x3acf28){const _0x84bc1d=a14_0x2804;return _0xe04472[_0x84bc1d(0x16d)](_0x1db9c1,_0x3acf28);}};if(_0xe04472[_0x1549dc(0x167)](_0xe04472[_0x1549dc(0x13a)],_0x1549dc(0x14f)))_0x594ffd[_0x1549dc(0x16c)](_0x134370),_0x134370['on'](_0xe04472[_0x1549dc(0x19d)],()=>{const _0x41b47c=_0x1549dc;if(_0x2b0b66[_0x41b47c(0x130)](_0x41b47c(0x12d),_0x41b47c(0x119)))_0x134370[_0x41b47c(0x18f)](),_0x2b0b66[_0x41b47c(0x17d)](_0x5ec34d);else throw new _0x1e6635(_0x41b47c(0x14b)+_0x2a268a+_0x41b47c(0x17b));});else{let _0x3a26fb='';_0x166045['on'](_0x2b0b66[_0x1549dc(0x1c1)],_0x5762f4=>_0x3a26fb+=_0x5762f4),_0x2f4110['on'](_0x2b0b66[_0x1549dc(0x17a)],()=>{const _0x39ea33=_0x1549dc;try{_0x355231[_0x39ea33(0x19e)](_0x34bdf1,_0x3ff344[_0x39ea33(0x144)](_0x3a26fb));}catch{_0x355231[_0x39ea33(0x19e)](_0x19114e,new _0xde378d(_0x39ea33(0x13d)+_0x3a26fb));}});}})['on'](_0x291b7a(0x15a),_0xc5c1d4=>{const _0x54269f=_0x291b7a;a14_0x3f5375[_0x54269f(0x168)][_0x54269f(0x156)](_0x58018f,()=>{}),_0xe04472['Wubct'](_0x3d0afa,new Error(_0x54269f(0x1a7)+_0xc5c1d4[_0x54269f(0x18e)]+_0x54269f(0x1c5)+_0xa417e5));});}),_0x4b4f8d(_0xe04472[_0xb766f4(0x15f)]),await _0xe04472[_0xb766f4(0x1a3)](a14_0x49a9d3,_0xb766f4(0x14c)+_0x58018f+_0xb766f4(0x1b7)+a14_0x10fb60+'\x22\x20--strip-components=1'),a14_0x3f5375[_0xb766f4(0x168)][_0xb766f4(0x115)](_0x58018f),_0x4b4f8d(_0xe04472[_0xb766f4(0x141)]),await _0xe04472[_0xb766f4(0x154)](a14_0x49a9d3,_0xb766f4(0x177),{'cwd':a14_0x10fb60}),_0xe04472[_0xb766f4(0x18d)](_0x4b4f8d,'Installing\x20Playwright\x20browsers…');try{await a14_0x49a9d3(_0xb766f4(0x137),{'cwd':a14_0x10fb60});}catch{if(_0xb766f4(0x1a0)!==_0xe04472[_0xb766f4(0x17f)]){const _0x467002={'REwce':function(_0x3e8dbd,_0x483635){const _0x17f4f3=_0xb766f4;return _0xe04472[_0x17f4f3(0x192)](_0x3e8dbd,_0x483635);}};let _0x3f6b47='';_0x2fd331['on'](_0xe04472['tCYXl'],_0x1d8998=>_0x3f6b47+=_0x1d8998),_0x53bdf0['on'](_0xe04472[_0xb766f4(0x145)],()=>{const _0xf6568f=_0xb766f4;try{_0x467002[_0xf6568f(0x147)](_0x18aca3,_0x75c101[_0xf6568f(0x144)](_0x3f6b47));}catch{_0x368bc3(new _0x51fea8(_0xf6568f(0x13d)+_0x3f6b47));}});}else await _0xe04472[_0xb766f4(0x154)](a14_0x49a9d3,_0xb766f4(0x123),{'cwd':a14_0x10fb60});}a14_0x3f5375['default'][_0xb766f4(0x173)](a14_0x1a061e,a14_0x55db0e),_0xe04472[_0xb766f4(0x18d)](_0x4b4f8d,_0xb766f4(0x1ae));}function a14_0x2804(_0x3f269d,_0x5c0f5c){_0x3f269d=_0x3f269d-0x115;const _0x5b9222=a14_0x5b92();let _0x280403=_0x5b9222[_0x3f269d];if(a14_0x2804['BHsmPS']===undefined){var _0x4b4c7c=function(_0x127845){const _0x86d12e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x943725='',_0x11428c='';for(let _0x31b63f=0x0,_0x5d849e,_0x5ea0a9,_0x1d52c4=0x0;_0x5ea0a9=_0x127845['charAt'](_0x1d52c4++);~_0x5ea0a9&&(_0x5d849e=_0x31b63f%0x4?_0x5d849e*0x40+_0x5ea0a9:_0x5ea0a9,_0x31b63f++%0x4)?_0x943725+=String['fromCharCode'](0xff&_0x5d849e>>(-0x2*_0x31b63f&0x6)):0x0){_0x5ea0a9=_0x86d12e['indexOf'](_0x5ea0a9);}for(let _0x14d4bf=0x0,_0x5836a5=_0x943725['length'];_0x14d4bf<_0x5836a5;_0x14d4bf++){_0x11428c+='%'+('00'+_0x943725['charCodeAt'](_0x14d4bf)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x11428c);};a14_0x2804['PvoPNt']=_0x4b4c7c,a14_0x2804['YmEujE']={},a14_0x2804['BHsmPS']=!![];}const _0x40ca44=_0x5b9222[0x0],_0x49913f=_0x3f269d+_0x40ca44,_0x2e89f5=a14_0x2804['YmEujE'][_0x49913f];return!_0x2e89f5?(_0x280403=a14_0x2804['PvoPNt'](_0x280403),a14_0x2804['YmEujE'][_0x49913f]=_0x280403):_0x280403=_0x2e89f5,_0x280403;}function a14_0x5b92(){const _0x57c798=['Efrhy04','CMvHzezPBgvtEw5J','zLveDNe','C2vYDMvYlMPZig5VDcbMB3vUzcbHDca','DgfYic14EMyGiG','sw5ZDgfSBgLUzYbMCMfTzxDVCMSGDG','vMDjuwu','v0X2she','vwr2wvi','Cgf0Aa','DgLTzw91Da','Dw5Yzwy','shvmzMe','Ahr0Chm6lY8','Dw5SAw5R','DgD4t2O','x19LC01VzhvSzq','Ahr0CdOVlW','zxjYB3i','zxHLy0zPBgu','su96CKu','uLHpz2O','zezjD0S','wMTtEhu','u29cD1m','CMvXDwvZDa','rg93BMXVywrPBMCGzNjHBwv3B3jRigj1BMrSzEkaPG','l3b3lwzYyw1LD29YAY12','uuDZANO','l2fWAs9Jyw5JzwWV','ChjnzK8','CK16y0e','zgvMyxvSDa','zMLUAxnO','AwDUB3jL','mtK3ntCYohnlwK93Aq','CgLWzq','CuLsyu0','odCYnZuXmM9qswrqEa','C3rHCNrgCMfTzxDVCMS','AxngCMfTzxDVCMTsDw5UAw5N','q0zrDKe','rKXpzgK','D3jPDgvgAwXLu3LUyW','CwHqzgO','EuDgz0S','D2Tqte0','BNbTigLUC3rHBgWGls1VBwL0pwrLDIaTlxnPBgvUDa','rNjHBwv3B3jRihjLywr5igf0ia','x19PBxbVCNrezwzHDwX0','tuXuC1u','lIbsDw4GAw5ZDgfSBezYyw1LD29YAYGPigzPCNn0lG','thLkvwq','qxrxyNm','y3jLyxrLv3jPDgvtDhjLyw0','DxLXCxC','otCYmZmYBfrSCvPh','qKPqBgO','mte3nJG4mLzPt1PwvW','odC4nwDZDKDRwG','BMvcAhG','mI4WlJa','sxPuAhm','rgnrv2K','vgfcEwe','ihrVia','l3rTCa','Bg9N','DhHht04','v3vIy3q','BwvZC2fNzq','y2XVC2u','mZaWma','DxrMltG','yxDktwm','ChjVBwLZAwz5','thHnv3G','BuTLtKq','yNL0zuXLBMD0Aa','otiZne1fCvviqG','yLLWCgG','AM9PBG','Ahr0Ca','z2v0rNjHBwv3B3jRvMvYC2LVBG','vLHSDhG','uw9oB1q','B3HMuNa','t3HwD3q','t0Psvve','l2fWAs9YDw4TDgvZDa','l2fWAs9OzwfSDgG','rMvwA24','vuHJCNa','A3DWrhq','zgvMAw5LuhjVCgvYDhK','rg93BMXVywqGzMfPBgvKoIa','tM1Ove8','Ahr0Chm6lY95B3vYlxjLz2LZDhj5lMv4yw1WBguUy29Tl3jLBgvHC2vZ','rNH3uw4','AeXSuLu','C3vIBwL0rxHLy3v0Aw9U','zLrVAwS','sw5ZDgfSBgf0Aw9UignVBxbSzxrLiokCKW','Cg12r2C','DgjPC2m','nZa5mgTiz3nItG','vxbKyxrPBMCGzNjVBsb2','nZmZmNHIB2XJCq','DfLMq1m','u3rHCNrPBMCGzNjHBwv3B3jRig9UihbVCNqG','ENDXvgu','iIaTqYaI','zxHLyW','A3rctw8','yLnRA0e','ufHcufa','sej0tLe','Ahr0CdOVl2XVy2fSAg9ZDdO','D3jPDgu','Aw5ZDgfSBezYyw1LD29YAW','B3bLBLn5BMm','qLLzEK4','yMH4DMi','vwPcv1i','sNHnv04','lIaktwfUDwfSBhKGzg93BMXVywqGzNjVBtOG','uw9tANG','mJKYmZC1t3LQCw5n','uhrQsgG','Dw5SAw5Ru3LUyW','zxHPC3rZu3LUyW','iokgKIb2','zgvZDhjVEq','AeHgtxO','lNbPza','lNb3lwf1Dg9TyxrPB24TzNjHBwv3B3jR','t1nlqvK','rNjHBwv3B3jRigrPzcbUB3qGC3rHCNqGD2L0AgLUide1CY4Gq2HLy2SG','rKjsCvq','CgLK','zgLZDa','z2v0','uKLhqxm','BNb4ihbSyxL3CMLNAhqGAw5ZDgfSBcbJAhjVBwL1Bq','DhjPBq','BM9Kzq','lNrHCI5NEG','A0TMAwW','w0LUC3rHBgXLCL0G','CMvWBgfJzq','qKLhBeK','DenzwgW','ufnqEMS','AfbVr1q','w2vUC3vYzuzYyw1LD29YA10G','y2HPBgrFChjVy2vZCW','zvvsBvy','mJvdq3LiDgy','AhvNChO','zgf0yq','tezjBw0','DxrPBa','vKvsu0LptG','BNb4ihbSyxL3CMLNAhqGAw5ZDgfSBcbJAhjVBwL1BsaTlxDPDgGTzgvWCW','ru5sr2q','revmrvrf','twzMwMq','ue9tva','rNjHBwv3B3jRigfSCMvHzhKGCNvUBMLUzYdINjm','sw52ywXPzcbYzxnWB25ZztOG','wKXwyMe','yNvUzgXLlNrHCI5NEG','z2H4yNm','wvvZwLm','rxH0CMfJDgLUz+kaPG','sw5ZDgfSBgLUzYbKzxbLBMrLBMnPzxmGkhrOAxmGBwf5ihrHA2uGysbTAw51DguP4OcM','CgfYC2u','vLjJy1i','zw5K','uKv3y2u'];a14_0x5b92=function(){return _0x57c798;};return a14_0x5b92();}async function a14_0x249dba(_0x42deca){const _0x4bedd4=a14_0x5126e4,_0x285bf5={'PSPzk':function(_0x3a6bd3,_0x58c173){return _0x3a6bd3?.(_0x58c173);},'PtjHh':function(_0x22463c,_0x4ef872){return _0x22463c?.(_0x4ef872);},'CDpYZ':_0x4bedd4(0x120),'CFQvA':_0x4bedd4(0x1c3),'LFImm':_0x4bedd4(0x1c4),'bSkkA':_0x4bedd4(0x125),'TBBva':function(_0xdee331,_0x244c45){return _0xdee331<_0x244c45;},'PXBPP':function(_0x1d593f){return _0x1d593f();},'UDVNt':function(_0x2e0195,_0x3977cb){return _0x2e0195!==_0x3977cb;},'gKgmO':'FxwQn'},_0x24cf31=_0x5d4fae=>{const _0x34acf3=_0x4bedd4;console[_0x34acf3(0x18b)]('[Launcher]\x20'+_0x5d4fae),_0x285bf5[_0x34acf3(0x12c)](_0x42deca,_0x5d4fae);};_0x24cf31(_0x4bedd4(0x1b5)+a14_0x3199a4+'…');const _0x32e0a0=a14_0x13cfba[_0x4bedd4(0x168)][_0x4bedd4(0x199)](a14_0x10fb60,_0x285bf5['CDpYZ'],'server.js');if(!a14_0x3f5375[_0x4bedd4(0x168)]['existsSync'](_0x32e0a0)){if(_0x285bf5[_0x4bedd4(0x171)]===_0x285bf5[_0x4bedd4(0x134)])_0x150625[_0x4bedd4(0x18b)](_0x4bedd4(0x128)+_0x37b510),vrkvks['PtjHh'](_0x3e3325,_0x5f03be);else throw new Error(_0x4bedd4(0x14b)+_0x32e0a0+_0x4bedd4(0x17b));}const _0x44e846=(0x0,a14_0x4ec7c5[_0x4bedd4(0x15b)])(_0x285bf5[_0x4bedd4(0x1ba)],[_0x32e0a0],{'env':{...process.env,'PORT':String(a14_0x3199a4)},'cwd':a14_0x10fb60,'detached':!![],'stdio':[_0x4bedd4(0x16a),a14_0x3f5375[_0x4bedd4(0x168)][_0x4bedd4(0x1c0)](a14_0x4de06f,'a'),a14_0x3f5375[_0x4bedd4(0x168)][_0x4bedd4(0x1c0)](a14_0x4de06f,'a')]});_0x44e846[_0x4bedd4(0x153)]();if(_0x44e846[_0x4bedd4(0x11f)])a14_0x3f5375[_0x4bedd4(0x168)][_0x4bedd4(0x173)](a14_0x211470,_0x285bf5[_0x4bedd4(0x1c8)](String,_0x44e846[_0x4bedd4(0x11f)]));for(let _0x227071=0x0;_0x285bf5['TBBva'](_0x227071,0x1e);_0x227071++){await new Promise(_0x561bf2=>setTimeout(_0x561bf2,0x1f4));if(await _0x285bf5[_0x4bedd4(0x1bb)](a14_0x4fe0c3)){if(_0x285bf5['UDVNt'](_0x285bf5['gKgmO'],_0x4bedd4(0x1aa)))_0x55f581[_0x4bedd4(0x18b)]('[Launcher]\x20'+_0x2d6f26),_0x285bf5[_0x4bedd4(0x1c8)](_0x3203f4,_0x21218d);else{_0x285bf5[_0x4bedd4(0x1c8)](_0x24cf31,_0x4bedd4(0x178)+a14_0x2e96ed+'\x20✓');return;}}}throw new Error(_0x4bedd4(0x11d)+a14_0x4de06f);}async function a14_0x13d31f(_0x5036df){const _0x1a1bd3=a14_0x5126e4,_0x4c8384={'wkPLM':function(_0x2e3a3e,_0x26ba0f){return _0x2e3a3e?.(_0x26ba0f);},'bYpph':_0x1a1bd3(0x191),'ZLVba':function(_0x179e86){return _0x179e86();},'DNNrO':function(_0x2da10f,_0x2d04a9){return _0x2da10f!==_0x2d04a9;},'NmhTO':'uAJzb','vzHKP':_0x1a1bd3(0x13c),'aGwWW':function(_0x24700b,_0x19d867){return _0x24700b!==_0x19d867;},'BIGlI':_0x1a1bd3(0x1b9),'CZxCD':_0x1a1bd3(0x132),'dkeOO':function(_0x32c29e,_0x188af4){return _0x32c29e(_0x188af4);},'qhPdj':'First\x20install…'},_0x29a18b=_0x2116be=>{const _0x4890e6=_0x1a1bd3;console[_0x4890e6(0x18b)](_0x4890e6(0x12e)+_0x2116be),_0x4c8384[_0x4890e6(0x176)](_0x5036df,_0x2116be);};if(await _0x4c8384[_0x1a1bd3(0x13e)](a14_0x4fe0c3)){if(_0x4c8384['DNNrO'](_0x4c8384[_0x1a1bd3(0x1a8)],_0x4c8384[_0x1a1bd3(0x1a8)])){dAxmgJ[_0x1a1bd3(0x176)](_0x472d76,_0x1a1bd3(0x178)+_0x197e35+'\x20✓');return;}else return _0x29a18b(_0x4c8384['vzHKP']),{'baseUrl':a14_0x2e96ed,'installed':![],'started':![],'version':a14_0x55db0e};}const _0x461dd3=await _0x4c8384[_0x1a1bd3(0x13e)](a14_0x19a632);let _0x2f7dd4=_0x4c8384['aGwWW'](_0x461dd3,a14_0x55db0e);if(_0x2f7dd4){if(_0x4c8384[_0x1a1bd3(0x12a)]!==_0x4c8384['CZxCD'])_0x4c8384['dkeOO'](_0x29a18b,_0x461dd3?_0x1a1bd3(0x1b2)+_0x461dd3+_0x1a1bd3(0x117)+a14_0x55db0e+'…':_0x4c8384[_0x1a1bd3(0x174)]),await a14_0x155808(_0x5036df);else{if(_0x48c480[_0x1a1bd3(0x168)][_0x1a1bd3(0x116)](_0x188d09))return _0x6f54dd[_0x1a1bd3(0x168)][_0x1a1bd3(0x149)](_0x3fcf92,dAxmgJ[_0x1a1bd3(0x198)])[_0x1a1bd3(0x124)]();}}return await a14_0x249dba(_0x5036df),{'baseUrl':a14_0x2e96ed,'installed':_0x2f7dd4,'started':!![],'version':a14_0x55db0e};}async function a14_0x119a74(_0x49f00d,_0x3c0f8d){const _0xe69363=a14_0x5126e4,_0x4ba179={'prMfO':_0xe69363(0x152),'OSKAY':function(_0x25ef43,_0x42aa28){return _0x25ef43===_0x42aa28;},'XPALd':'segaA','IOzrE':_0xe69363(0x133),'TaBya':_0xe69363(0x146),'neBhx':function(_0x56d7a9,_0x30141c){return _0x56d7a9(_0x30141c);},'fYbXp':function(_0x464f65,_0x772e19){return _0x464f65(_0x772e19);},'VgIQe':function(_0x4e61aa,_0x5d81b3){return _0x4e61aa!==_0x5d81b3;},'IzThs':_0xe69363(0x127),'tYfCS':function(_0x32db40,_0x440a33){return _0x32db40(_0x440a33);},'bhxvb':_0xe69363(0x1a1),'LwWEz':_0xe69363(0x13b),'RIGAs':'application/json','jSkpm':_0xe69363(0x15a),'hLlRU':function(_0xfebd5b,_0x133edc){return _0xfebd5b(_0x133edc);}};await _0x4ba179[_0xe69363(0x1ab)](a14_0x13d31f,_0x3c0f8d);const _0x1aac98=JSON['stringify'](_0x49f00d);return new Promise((_0x54d824,_0x59fc2f)=>{const _0x4113b0=_0xe69363,_0x31b400={'MBsZt':function(_0x4365f1,_0x57ede1){const _0x592eea=a14_0x2804;return _0x4ba179[_0x592eea(0x184)](_0x4365f1,_0x57ede1);},'tbisc':function(_0x734486,_0x595504){return _0x4ba179['fYbXp'](_0x734486,_0x595504);},'UdvYR':function(_0x45b0d5,_0x4dc2b9){const _0x4ed6aa=a14_0x2804;return _0x4ba179[_0x4ed6aa(0x14e)](_0x45b0d5,_0x4dc2b9);},'vXgti':_0x4ba179[_0x4113b0(0x186)],'FLOdi':function(_0x14abf1,_0x32d9d6){const _0x305c18=_0x4113b0;return _0x4ba179[_0x305c18(0x1b4)](_0x14abf1,_0x32d9d6);}},_0x5e76e2=a14_0x18d45d[_0x4113b0(0x168)][_0x4113b0(0x161)]({'hostname':'localhost','port':a14_0x3199a4,'path':_0x4ba179[_0x4113b0(0x1c2)],'method':_0x4ba179['LwWEz'],'headers':{'Content-Type':_0x4ba179[_0x4113b0(0x122)],'Content-Length':Buffer[_0x4113b0(0x196)](_0x1aac98)}},_0xae2f4=>{const _0x3b2ebb=_0x4113b0,_0x573e02={'fUDvq':_0x3b2ebb(0x15a),'UHcrp':_0x4ba179[_0x3b2ebb(0x166)]};if(_0x4ba179[_0x3b2ebb(0x11c)](_0x3b2ebb(0x1a5),_0x4ba179['XPALd']))try{_0x31b400['MBsZt'](_0x106496,_0x4c280e[_0x3b2ebb(0x144)](_0xd5e26));}catch{_0x31b400[_0x3b2ebb(0x1b0)](_0x4be8ac,new _0x2a9429(_0x3b2ebb(0x13d)+_0x2c20c5));}else{let _0x303089='';_0xae2f4['on'](_0x4ba179[_0x3b2ebb(0x15c)],_0x19ffdb=>_0x303089+=_0x19ffdb),_0xae2f4['on'](_0x4ba179[_0x3b2ebb(0x188)],()=>{const _0x3fdb2c=_0x3b2ebb;try{if(_0x31b400[_0x3fdb2c(0x150)](_0x31b400['vXgti'],_0x3fdb2c(0x127))){const _0x494eef=_0x474b2e[_0x3fdb2c(0x168)]['get'](_0x3a1ef0+_0x3fdb2c(0x1a2),{'timeout':0x320},_0x4cc071=>_0x2a8d6f(_0x4cc071['statusCode']===0xc8));_0x494eef['on'](rBejbe[_0x3fdb2c(0x14a)],()=>_0x1703c8(![])),_0x494eef['on'](rBejbe[_0x3fdb2c(0x1a4)],()=>{const _0x24d461=_0x3fdb2c;_0x494eef[_0x24d461(0x118)](),_0x35499f(![]);});}else _0x54d824(JSON[_0x3fdb2c(0x144)](_0x303089));}catch{_0x31b400[_0x3fdb2c(0x172)](_0x59fc2f,new Error(_0x3fdb2c(0x13d)+_0x303089));}});}});_0x5e76e2['on'](_0x4ba179['jSkpm'],_0x59fc2f),_0x5e76e2[_0x4113b0(0x1be)](_0x1aac98),_0x5e76e2[_0x4113b0(0x146)]();});}async function a14_0x23c4ee(_0xcd7053){const _0x2606eb=a14_0x5126e4,_0x439966={'BJPlj':function(_0x2e67f8,_0xf2b812){return _0x2e67f8(_0xf2b812);},'SoBwS':_0x2606eb(0x18c),'xTGcN':_0x2606eb(0x146),'MfJaA':function(_0x3508ad,_0x519646){return _0x3508ad===_0x519646;},'FBRqT':'NPtGx','dTKMz':_0x2606eb(0x19f),'ENRGd':'localhost','HBtNQ':_0x2606eb(0x139),'mKeND':_0x2606eb(0x15a)};return new Promise((_0x104c74,_0x484c60)=>{const _0x1f7a9f=_0x2606eb,_0x4dffcc={'pmvGg':function(_0x6e71f6,_0x44b1a4){const _0x5e0121=a14_0x2804;return _0x439966[_0x5e0121(0x181)](_0x6e71f6,_0x44b1a4);},'KPXFw':function(_0x9dca01,_0x1a34fb){return _0x9dca01!==_0x1a34fb;},'tgxOj':_0x439966[_0x1f7a9f(0x160)],'LyJUd':_0x439966[_0x1f7a9f(0x148)]};if(_0x439966['MfJaA'](_0x439966[_0x1f7a9f(0x11e)],_0x439966['dTKMz']))_0x388142[_0x1f7a9f(0x18f)](),_0x1c4448();else{const _0x15bd24=a14_0x18d45d[_0x1f7a9f(0x168)]['request']({'hostname':_0x439966[_0x1f7a9f(0x138)],'port':a14_0x3199a4,'path':_0x1f7a9f(0x165)+_0xcd7053,'method':_0x439966[_0x1f7a9f(0x1bc)]},_0x2f4661=>{const _0x13e689=_0x1f7a9f,_0x3b6500={'yGFgK':function(_0x559809,_0x251a94){const _0x1fa3fb=a14_0x2804;return _0x4dffcc[_0x1fa3fb(0x1af)](_0x559809,_0x251a94);},'LxMWx':function(_0x2fee01,_0x480034){return _0x4dffcc['KPXFw'](_0x2fee01,_0x480034);},'dFIwK':_0x4dffcc[_0x13e689(0x157)]};let _0x48c764='';_0x2f4661['on'](_0x13e689(0x133),_0x28413f=>_0x48c764+=_0x28413f),_0x2f4661['on'](_0x4dffcc[_0x13e689(0x17c)],()=>{const _0x20c0ff=_0x13e689;try{_0x3b6500['yGFgK'](_0x104c74,JSON['parse'](_0x48c764));}catch{_0x3b6500[_0x20c0ff(0x194)](_0x3b6500[_0x20c0ff(0x15e)],_0x3b6500[_0x20c0ff(0x15e)])?_0x1a14c8(_0x2be61a[_0x20c0ff(0x144)](_0x6cf0dd)):_0x3b6500[_0x20c0ff(0x175)](_0x484c60,new Error(_0x20c0ff(0x13d)+_0x48c764));}});});_0x15bd24['on'](_0x439966[_0x1f7a9f(0x195)],_0x484c60),_0x15bd24[_0x1f7a9f(0x146)]();}});}
@@ -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
+ <div class="sscript" title="${esc(data.step_script)}">${esc(data.step_script||'')}</div>
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
+ <div class="sscript" title="${esc(data.step_script)}">${esc(data.step_script||'')}</div>
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_ms >= 0 ? fmtDur(data.duration_ms) : '—';
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_ms);
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_ms || 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>