@unotest/web 0.30.0 → 0.31.0

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
- const _0x240e79=_0x25e6;(function(_0x1021cd,_0x23d64a){const _0x4d546c={_0x14c545:0x1e9,_0x2063da:0x1d1,_0x1fee5d:0x1f2,_0x3c9a7c:0x1d2,_0x1da06a:0x1e8,_0x19d116:0x1f3},_0x11231d=_0x25e6,_0x5969af=_0x1021cd();while(!![]){try{const _0x445241=-parseInt(_0x11231d(_0x4d546c._0x14c545))/0x1+-parseInt(_0x11231d(0x1e2))/0x2*(-parseInt(_0x11231d(0x1d0))/0x3)+parseInt(_0x11231d(_0x4d546c._0x2063da))/0x4*(parseInt(_0x11231d(_0x4d546c._0x1fee5d))/0x5)+parseInt(_0x11231d(_0x4d546c._0x3c9a7c))/0x6*(parseInt(_0x11231d(_0x4d546c._0x1da06a))/0x7)+-parseInt(_0x11231d(0x1e3))/0x8*(parseInt(_0x11231d(0x1dc))/0x9)+parseInt(_0x11231d(0x1ee))/0xa+-parseInt(_0x11231d(_0x4d546c._0x19d116))/0xb;if(_0x445241===_0x23d64a)break;else _0x5969af['push'](_0x5969af['shift']());}catch(_0x2ac0a9){_0x5969af['push'](_0x5969af['shift']());}}}(_0x41b5,0xe6e42));var __defProp=Object['defineProperty'],__name=(_0x2fb7db,_0x22975e)=>__defProp(_0x2fb7db,_0x240e79(0x1d6),{'value':_0x22975e,'configurable':!![]});import{mkdir,writeFile}from'fs/promises';import{existsSync}from'fs';import{join}from'path';var templates={'jsconfigJson':_0x240e79(0x1e6),'scenarioTemplate':_0x240e79(0x1ea),'agentsMd':'#\x20@unotest/web\x20—\x20guide\x20for\x20AI\x20agents\x20(and\x20humans)\x0a\x0aThis\x20project\x20uses\x20[`@unotest/web`](https://www.npmjs.com/package/@unotest/web)\x0afor\x20end-to-end\x20testing\x20of\x20web\x20applications.\x0a\x0a##\x20Writing\x20a\x20test\x20—\x20use\x20the\x20skill\x20+\x20MCP\x0a\x0aFor\x20ANY\x20request\x20to\x20write,\x20record,\x20or\x20run\x20an\x20e2e\x20test:\x0a\x0a1.\x20Open\x20the\x20**`write-e2e-test`**\x20skill\x20—\x20`.claude/skills/write-e2e-test/SKILL.md`\x0a\x20\x20\x20(in\x20Claude\x20Code\x20you\x20can\x20also\x20run\x20`/write-e2e-test`)\x20—\x20and\x20follow\x20it.\x0a2.\x20Drive\x20the\x20browser\x20through\x20the\x20**`unotest-web`\x20MCP\x20tools**:\x20`new_context`\x20→\x0a\x20\x20\x20`explore_start`\x20→\x20`explore_step`\x20→\x20`get_page_snapshot`\x20→\x20`run_test`.\x0a\x0aDo\x20NOT\x20hand-author\x20tests\x20blind\x20or\x20map\x20the\x20project\x20with\x20`find`/`ls`/`awk`\x20—\x20the\x0askill\x27s\x20Phase\x200\x20names\x20the\x20exact\x20files\x20to\x20read.\x20Runnable,\x20copy-pasteable\x0aexamples\x20live\x20in\x20`unotest/e2e/examples/`.\x0a\x0a##\x20Layout\x0a\x0a-\x20`unotest/e2e/<feature>/<name>.js`\x20—\x20test\x20scenarios,\x20grouped\x20by\x20feature/page\x0a\x20\x20(one\x20`test_*`\x20function\x20per\x20file).\x20**Required:**\x20every\x20scenario\x20lives\x20in\x20a\x0a\x20\x20feature\x20subfolder.\x20A\x20test\x20file\x20placed\x20directly\x20in\x20`unotest/e2e/`\x20is\x20rejected\x0a\x20\x20by\x20the\x20linter\x20(`lint:scenario-in-root`).\x0a-\x20`unotest/e2e/_helpers/`\x20—\x20project-specific\x20helpers\x20(visible\x20to\x20all\x20scenarios)\x0a-\x20`unotest/e2e/_template.js`\x20—\x20starting-point\x20template\x20(copy\x20into\x20a\x20feature\x20folder)\x0a\x0a##\x20DSL\x20conventions\x0a\x0aThe\x20DSL\x20is\x20a\x20strict\x20JS\x20subset\x20parsed\x20by\x20@unotest/dsl.\x20Method\x20chains,\x20options-\x0aobjects,\x20and\x20variables\x20are\x20allowed.\x20Multi-line\x20strings\x20use\x0abackticks\x20but\x20`${...}`\x20interpolation\x20is\x20forbidden\x20(sandbox\x20boundary\x20—\x0apass\x20values\x20via\x20positional\x20args).\x0a\x0a**Every\x20step\x20must\x20sit\x20inside\x20a\x20`step(\x22description\x22,\x20()\x20=>\x20{\x20…\x20})`\x20block\x20(linter\x0aenforces).**\x20The\x20title\x20is\x20plain-English\x20intent;\x20the\x20steps\x20inside\x20are\x20the\x0aimplementation.\x20When\x20a\x20step\x20later\x20breaks\x20(selector\x20drift),\x20you\x20read\x20the\x0atitle\x20to\x20understand\x20what\x20the\x20group\x20was\x20trying\x20to\x20do\x20and\x20repair\x20it.\x20Group\x20by\x0aintent,\x20one\x20block\x20per\x20logical\x20chunk:\x0a\x0a```js\x0afunction\x20test_login()\x20{\x0a\x20\x20step(\x22Sign\x20in\x20as\x20the\x20demo\x20user\x22,\x20()\x20=>\x20{\x0a\x20\x20\x20\x20goto(\x27https://app.example.com/login\x27);\x0a\x20\x20\x20\x20fill(getByLabel(\x27Email\x27),\x20\x27demo@example.com\x27);\x0a\x20\x20\x20\x20click(getByRole(\x27button\x27,\x20{name:\x20\x27Log\x20in\x27}));\x0a\x20\x20});\x0a\x0a\x20\x20step(\x22Dashboard\x20shows\x20the\x20signed-in\x20user\x22,\x20()\x20=>\x20{\x0a\x20\x20\x20\x20assertText(getByRole(\x27heading\x27),\x20\x27Welcome\x27);\x0a\x20\x20});\x0a}\x0a```\x0a\x0a**Base\x20URL\x20—\x20write\x20relative\x20paths.**\x20`APP_BASE_URL`\x20(in\x20`unotest/.env`)\x20is\x20the\x0aapp\x27s\x20base;\x20`goto(\x27/login\x27)`\x20resolves\x20against\x20it.\x20Don\x27t\x20concatenate\x0a(`goto(APP_BASE_URL\x20+\x20\x27/login\x27)`)\x20—\x20just\x20pass\x20the\x20path:\x0a\x0a```js\x0agoto(\x27/login\x27);\x0afill(getByLabel(\x27Password\x27),\x20TEST_USER_PASSWORD);\x0a```\x0a\x0a**Environments.**\x20Override\x20`APP_BASE_URL`\x20(and\x20any\x20var)\x20per\x20environment\x20with\x0aoverlay\x20files\x20—\x20`unotest/.env.staging`,\x20`unotest/.env.production`\x20(secrets:\x0a`unotest/.secrets.<env>`).\x20Select\x20one\x20at\x20run\x20time:\x20`npx\x20@unotest/web\x20e2e\x20<name>\x0a--env\x20staging`.\x20The\x20overlay\x20layers\x20over\x20the\x20base\x20`.env`\x20(overlay\x20wins).\x0a\x0a**External\x20variables\x20&\x20secrets:**\x20reference\x20logins\x20/\x20tokens\x20by\x20a\x20bare\x0a`UPPER_SNAKE`\x20name\x20—\x20resolved\x20from\x20`unotest/.env`\x20(normal)\x20or\x20`unotest/.secrets`\x0a(secret,\x20masked\x20in\x20logs).\x20No\x20`env()`/`secret()`\x20wrapper.\x20A\x20lowercase\x20name\x20is\x20an\x0ain-scenario\x20binding;\x20an\x20unknown\x20`UPPER_SNAKE`\x20fails\x20the\x20run\x20asking\x20you\x20to\x20add\x20it\x0ato\x20`unotest/.env`.\x0a\x0a**Selector\x20hierarchy\x20(D-22\x20—\x20linter\x20enforces):**\x0a1.\x20`getByTestId(id)`\x20—\x20most\x20stable\x0a2.\x20`getByRole(role,\x20{name})`\x20—\x20semantic,\x20a11y-aware\x0a3.\x20`getByLabel(text)`\x20—\x20for\x20form\x20fields\x0a4.\x20`getByText(text)`\x20—\x20for\x20unique\x20text\x0a5.\x20`locator(css)`\x20—\x20last\x20resort\x20(linter\x20warns)\x0a\x0aFull\x20reference\x20shipped\x20with\x20the\x20package:\x0a-\x20`node_modules/@unotest/web/guides/dsl-reference.md`\x20—\x20DSL\x20functions\x20+\x20linter\x20codes\x0a\x0a##\x20Running\x20(CLI)\x0a\x0a-\x20`npx\x20@unotest/web\x20e2e\x20<feature>/<name>`\x20—\x20run\x20a\x20scenario\x20by\x20name\x0a-\x20`npx\x20@unotest/web\x20lint`\x20—\x20static\x20check\x20of\x20all\x20scenarios\x20+\x20helpers\x0a-\x20`npx\x20@unotest/web\x20mcp`\x20—\x20start\x20the\x20MCP\x20server\x20for\x20agent\x20control\x0a\x0a##\x20Via\x20MCP\x20(Claude\x20Code\x20/\x20Claude\x20Desktop\x20/\x20Cursor)\x0a\x0aThe\x20MCP\x20server\x20exposes:\x0a-\x20`run_test\x20name=\x22<name>\x22\x20mode=\x22step\x22\x20pauseOnFailure=true`\x20—\x20run\x20with\x20step-mode\x0a-\x20`step`\x20/\x20`resume`\x20—\x20advance\x20one\x20AST\x20node\x20/\x20run\x20until\x20next\x20pause\x0a-\x20`inspect_runtime`\x20—\x20current\x20state,\x20last\x20error,\x20locals\x20dump\x0a-\x20`abort_runtime`\x20—\x20kill\x20a\x20paused\x20runtime\x0a\x0aFor\x20agent-fix\x20workflows\x20on\x20flaky\x20tests:\x20`agent_fix\x20testId=\x22<id>\x22`\x20returns\x20a\x0astructured\x20context\x20bundle\x20(see\x20D-25\x20—\x20we\x20never\x20call\x20LLMs\x20or\x20auto-apply\x0adiffs,\x20the\x20diff\x20comes\x20from\x20your\x20MCP-host\x20agent).\x0a','claudeMdBody':_0x240e79(0x1d5),'examples':{'01-smoke.js':_0x240e79(0x1f5),'02-form-fill.js':_0x240e79(0x1cf)},'secretsExample':_0x240e79(0x1de),'envExample':_0x240e79(0x1f0)};function unotestConfigMjs(_0x55a1db){const _0x50dc45={_0x2a38c2:0x1d8,_0x11f930:0x1ed},_0x319753=_0x240e79,_0x39ce27=_0x55a1db===void 0x0?_0x319753(0x1df):_0x319753(0x1db)+JSON['stringify'](_0x55a1db)+',';return _0x319753(_0x50dc45._0x2a38c2)+_0x39ce27+_0x319753(_0x50dc45._0x11f930);}__name(unotestConfigMjs,_0x240e79(0x1da));function suitePackageJson(_0x1e7251){const _0x4c41e6=_0x240e79;return JSON['stringify']({'name':_0x4c41e6(0x1e1),'private':!![],'devDependencies':{'@unotest/web':'^'+_0x1e7251}},null,0x2)+'\x0a';}__name(suitePackageJson,_0x240e79(0x1e4));import{readFileSync}from'fs';import{dirname,resolve}from'path';function _0x25e6(_0x211068,_0x34759f){_0x211068=_0x211068-0x1cb;const _0x41b5de=_0x41b5();let _0x25e6be=_0x41b5de[_0x211068];if(_0x25e6['AMWHXl']===undefined){var _0x413613=function(_0x3f49cb){const _0x465543='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2fb7db='',_0x22975e='';for(let _0x55a1db=0x0,_0x39ce27,_0x1e7251,_0x3e186e=0x0;_0x1e7251=_0x3f49cb['charAt'](_0x3e186e++);~_0x1e7251&&(_0x39ce27=_0x55a1db%0x4?_0x39ce27*0x40+_0x1e7251:_0x1e7251,_0x55a1db++%0x4)?_0x2fb7db+=String['fromCharCode'](0xff&_0x39ce27>>(-0x2*_0x55a1db&0x6)):0x0){_0x1e7251=_0x465543['indexOf'](_0x1e7251);}for(let _0x41b919=0x0,_0x59e4cd=_0x2fb7db['length'];_0x41b919<_0x59e4cd;_0x41b919++){_0x22975e+='%'+('00'+_0x2fb7db['charCodeAt'](_0x41b919)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x22975e);};_0x25e6['zbEVVG']=_0x413613,_0x25e6['DLmGxS']={},_0x25e6['AMWHXl']=!![];}const _0x2cc505=_0x41b5de[0x0],_0x2e4a8b=_0x211068+_0x2cc505,_0x2b537b=_0x25e6['DLmGxS'][_0x2e4a8b];return!_0x2b537b?(_0x25e6be=_0x25e6['zbEVVG'](_0x25e6be),_0x25e6['DLmGxS'][_0x2e4a8b]=_0x25e6be):_0x25e6be=_0x2b537b,_0x25e6be;}import{fileURLToPath}from'url';function readOwnVersion(){const _0xa7d67b={_0xf1abcf:0x1d4,_0x1fda29:0x1d9,_0x13370b:0x1e5,_0x12bcf8:0x1f7},_0x3c0810=_0x240e79,_0x3e186e=dirname(fileURLToPath(import.meta.url)),_0x41b919=resolve(_0x3e186e,_0x3c0810(0x1cb)),_0x59e4cd=readFileSync(_0x41b919,_0x3c0810(_0xa7d67b._0xf1abcf)),_0xde33e3=JSON[_0x3c0810(_0xa7d67b._0x1fda29)](_0x59e4cd);if(typeof _0xde33e3[_0x3c0810(0x1e5)]!==_0x3c0810(0x1d3)||_0xde33e3[_0x3c0810(_0xa7d67b._0x13370b)][_0x3c0810(0x1d7)]===0x0)throw new Error(_0x3c0810(_0xa7d67b._0x12bcf8)+_0x41b919+'\x20has\x20no\x20usable\x20\x22version\x22\x20field');return _0xde33e3['version'];}__name(readOwnVersion,_0x240e79(0x1f1));function _0x41b5(){const _0x2975eb=['nti1wgrYy0n3','mJq5nJGWrNDduwL3','lY8Gtw92zsaRihjLBMfTzsb0AgLZigzPBguGDg8GpgzLyxr1CMu+lZX5B3vYx25HBwu+lMPZicHLlMCUcI8Vigf1DgGVBg9NAw4UANmPigfUzcb0AguGzNvUy3rPB24GyMvSB3CGDg8GDgvZDf88Ew91CL9Uyw1LpIGPlIbty2vUyxjPB3mGBgL2zqOVlYbPBIbMzwf0DxjLihn1yMzVBgrLCNmSie5pvcb0AguGztjLihjVB3qG4OcuihrOzsbSAw50zxiGkgXPBNq6C2nLBMfYAw8TAw4TCM9VDcKklY8GCMvQzwn0CYbHihrLC3qGzMLSzsbWBgfJzwqGzgLYzwn0BhKGAw4GDw5VDgvZDc9LmMuVlIbuAguGBg9HzgvYigrLCML2zxmGDgHLcI8VigvUDhj5ig5HBwuGzNjVBsb0AguGzMLSzsbIyxnLBMfTzsdIGjqGA2vIywiTy2fZzsbKyxnOzxmGyMvJB21LihvUzgvYC2nVCMvZlGOklY8GrxzLCNKGzxHLy3v0ywjSzsbZDgvWig11C3qGC2L0igLUC2LKzsbHihn0zxaOiI4UlIiSicGPid0+ihSG4OcMih0PigjSB2nRlIbuAguklY8GDgL0BguGAxmGysbWBgfPBI1fBMDSAxnOigrLC2nYAxb0Aw9Uig9MihrOzsbNCM91CdSGDgHLihn0zxbZigLUC2LKzsbHCMuklY8GDgHLigLTCgXLBwvUDgf0Aw9UlIbhCM91CcbIEsbPBNrLBNqGkfnLDhvWic8Grw50zxiGlYbby3qGlYbbC3nLCNqGB3iklY8GD2HHDgv2zxiGCMvHzhmGD2vSBcKG4Ocuig9UzsbIBg9JAYbWzxiGBg9NAwnHBcbJAhvUAY4kcMz1BMn0Aw9UihrLC3rFEw91CL9Uyw1Lx2HLCMuOksb7cIaGC3rLCcGIu2vLzcbHigTUB3DUihvZzxiGDMLHiercic8GqvbjigzPEhr1CMvZigzYB20Gx2HLBhbLCNmViIWGkcKGpt4GEWOGicaGlY8GicaGD2LWzv9LmMvFDxnLCNmOktSkicaGic8VicaGihvZzxjFAwqGpsbZzwvKx3vZzxiOj2fSAwnLqgv4yw1WBguUy29TjYWGj3nLy3jLDcCPoWOGih0PoWOkicbZDgvWkcjtAwDUigLUigfZihrOzsbZzwvKzwqGDxnLCIiSicGPid0+ihSkicaGigDVDg8Oj2H0DhbZoI8VEw91CI1HChaUDgvZDc9SB2DPBICPoWOGicaGlY8GicaGzMLSBcHNzxrcEuXHyMvSkcDfBwfPBcCPlcaNywXPy2vazxHHBxbSzs5JB20NktSkicaGic8VicaGigzPBgWOz2v0qNLmywjLBcGNugfZC3DVCMqNksWGj3nLy3jLDcCPoWOGicaGlY8GicaGy2XPy2SOz2v0qNLsB2XLkcDIDxr0B24Nlcb7BMfTztOGj0XVzYbPBID9ksK7cIaGFsK7cGOGihn0zxaOiKfZC2vYDcb0AguGzgfZAgjVyxjKihnOB3DZihrOzsbZAwDUzwqTAw4GDxnLCIiSicGPid0+ihSkicaGic8VicaGigfZC2vYDfvYBcGNl2rHC2HIB2fYzcCPoWOGicaGlY8GicaGyxnZzxj0vgv4DcHNzxrcEvjVBguOj2HLywrPBMCNksWGj1DLBgnVBwuSiefSAwnLjYK7cIaGicaVlYaGicbJB3vUDca9igrIuxvLCNKOj1nftevdvcbJB3vUDcGQksbguK9nihvZzxjZifDirvjfigfJDgL2zsa9ihrYDwuNktSkicaGic8VicaGigfZC2vYDfrYDwuOy291BNqGpIaWlcaNzxHWzwn0zwqGyxqGBgvHC3qGB25LigfJDgL2zsb1C2vYjYK7cIaGFsK7cN0k','zw52rxHHBxbSzq','ChvZAa','cIaGlY8GDMLLD2vYoIb7cIaGlY8GicbWB3j0oIa1mtCZlcaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGic8VigrLzMf1Bhq6ihjHBMrVBsbMCMvLihbVCNqkicaVlYaGigjYB3DZzxi6ihrYDwuSicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GzgvMyxvSDdOGDhj1zsaOyxv0BY1VCgvUig9Uigb2Awv3zxjGkqOGic8Vih0ScN07cG','mti3mtGYmdbsywPUsLC','CgfJA2fNzs5QC29U','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','CMvHze93BLzLCNnPB24','mZbkqxnSzw0','mZCXodmYmdfyDLnKEuu','ANnJB25MAwDkC29U','lY8GrxHHBxbSzsaWmsdIGjqGC21VA2u6ig5HDMLNyxrLicSGy2XPy2SGkYbvuKWGyxnZzxj0Aw9UlGOVlWOVlYbuAguGBwLUAw1HBcb0AhjLzs1ZDgvWihbHDhrLCM4UieHPDhmGCgXHEwDYB3vUzc51BM90zxn0lMnVBsbZBYbUBYbWCM9Qzwn0cI8VihnLDhvWigLZig5LzwrLzc4GuNvUihDPDgG6icbUChGGqhvUB3rLC3qVD2vIiguYzsbLEgfTCgXLCY8Wms1ZBw9RzqOkzNvUy3rPB24GDgvZDf9ZBw9Rzv9WBgf5z3jVDw5KkcKGEWOGihn0zxaOiK9Wzw4GDgHLiejPzYbuywjSzsbZy2vUyxjPBYbMCM9TihrOzsbWBgf5z3jVDw5KigLUzgv4iIWGkcKGpt4GEWOGicaGz290BYGNlYCPoWOGicaGy2XPy2SOz2v0qNLsB2XLkcDSAw5RjYWGE25HBwu6icDcAwCGvgfIBguNlcbLEgfJDdOGDhj1zx0PktSkicaGigfZC2vYDfvYBcGNl3nJzw5HCMLVCY9IAwCTDgfIBguNktSkicb9ktSkFqO','ztjL','CgfJA2fNzs5QC29Uigf0ia','lI4VlI4VCgfJA2fNzs5QC29U','x2HLBhbLCNm','C2nHzMzVBgrxB3jRC3bHy2u','zxHHBxbSzxm','lY8GrxHHBxbSzsaWmIdIGjqGzMLSBcbHBIbPBNb1DcaRigfZC2vYDcb0AguGyxbWihjLywn0zwqUcI8VcI8ViefNywLUC3qGCgXHEwDYB3vUzc51BM90zxn0lMnVBs9Zy2vUyxjPB3mVyMLNlxrHyMXLlIbezw1VBNn0CMf0zxmGz2v0qNLsB2XLcI8VigzVCIbHigXHyMvSBgvKigLUChv0lcb0ExbLzcbPBNb1Dcb2AweGzMLSBcGPlcbHBMqGysbSB2nHDg9Yig1LDgHVzc1JAgfPBGOVlYaOz2v0qNLsB2XLkcDYB3CNks5MAwX0zxiOE2HHC1rLEhr9ks5MAxjZDcGPksbPBIbHBIbHC3nLCNrPB24UcI8Vifj1BIb3AxrOoIaGBNb4ieb1BM90zxn0l3DLyIbLmMuGzxHHBxbSzxmVmdiTzM9YBs1MAwXScGPMDw5JDgLVBIb0zxn0x2zVCM1FzMLSBf9OyxbWEv9WyxrOkcKGEWOGihn0zxaOiKzPBhrLCIb0AguGqMLNifrHyMXLigj5igeGBMfTzsiSicGPid0+ihSkicaGigDVDg8OjY9Zy2vUyxjPB3mVyMLNlxrHyMXLjYK7cIaGicbMAwXSkgDLDej5uM9SzsGNDgv4DgjVEcCSihTUyw1LoIaNrMLSDgvYigj5ig5HBwuNFsKSicDvBweGuxvPBM4NktSkicb9ktSkcIaGC3rLCcGIrMLSDgvYAw5NihjLDMvHBhmGDgHLienSzwfYigzPBhrLCIbJB250CM9SigfUzcbTyxrJAgLUzYbYB3DZiIWGkcKGpt4GEWOGicaGyxnZzxj0vMLZAwjSzsHNzxrcEvjVBguOj2j1DhrVBICSihTUyw1LoIaNq2XLyxiGzMLSDgvYj30PktSkicaGigfZC2vYDfzPC2LIBguOz2v0qNLsB2XLkcDYB3CNks5MAwX0zxiOE2HHC1rLEhq6icDvBweGuxvPBM4NFsKUzMLYC3qOksK7cIaGFsK7cN0k','mJiXngPrtvPxzq','otCZmte2vw9VBLPL','mtq2nJa0CeLttfH1','C3rYAw5N','DxrMoa','iYmGrtjfihrLC3rPBMCGD2L0AcbaDw5VDgvZDc93zwikcKbbr0vovfmUBwqkcKzVCIbHBNKGCMvXDwvZDcb0BYb3CML0zsWGCMvJB3jKlcbVCIbYDw4Gyw4Gzw5KlxrVlwvUzcb0zxn0lcbVCgvUihrOzqPGD3jPDguTztjLlxrLC3rGihnRAwXSicHVCIbYDw4Gyc93CML0zs1LmMuTDgvZDgaPigfUzcbKCML2zsb0AguGyNjVD3nLCIb0AhjVDwDOcNrOzsbGDw5VDgvZDc13zwjGie1ducb0B29SCYaOyg5LD19JB250zxH0ycdIHPiGygv4CgXVCMvFC3rLCgaG4OAsigbNzxrFCgfNzv9ZBMfWC2HVDgak4OAsigbYDw5FDgvZDgaPlIbeBYbUB3qGAgfUzc1HDxrOB3iGDgvZDhmGyMXPBMqGB3iGBwfWihrOzsbWCM9Qzwn0ihDPDgGkygzPBMrGl2bSC2aVygf3A2aG4OcuihrOzsbZA2LSBcDZifbOyxnLidaGBgLZDhmGDgHLigzPBgvZihrVihjLywqU','BMfTzq','BgvUz3rO','lY8GqhvUB3rLC3qVD2vIihbYB2PLy3qGy29UzMLNlIbbBgWGzMLLBgrZigfYzsbVChrPB25HBcdIGjqGzgvMyxvSDhmGyxbWBhKklY8GD2HLBIbVBwL0DgvKlGOVlWOVlYbtyxzLzcbHCYaUBwPZihnVihrOzsbYDw50Aw1LigXVywrZigL0igfZievttsbYzwDHCMrSzxnZig9MihrOzsbWCM9Qzwn0j3mklY8GCgfJA2fNzs5QC29Uicj0ExbLiIbMAwvSzc4GrM9YieLersbHDxrVy29TCgXLDguSihr5CguTAw1WB3j0ihrOzsbZy2HLBwe6cI8VcI8VicaGlYOQieb0ExbLihTqyxj0AwfSpgLTCg9YDcGNqhvUB3rLC3qVD2vIjYKUvw5VDgvZDenVBMzPzZ59icOVcI8VicaGzxHWB3j0igrLzMf1BhqGEYbIyxnLvxjSoIaNAhr0Chm6lY95B3vYlwfWCc50zxn0jYb9oWOklYOQieb0ExbLihTqyxj0AwfSpgLTCg9YDcGNqhvUB3rLC3qVD2vIjYKUvw5VDgvZDenVBMzPzZ59icOVcMv4Cg9YDcbKzwzHDwX0ihSkicaVlYbIyxnLvxjSoIaNAhr0Chm6lY95B3vYlwfWCc50zxn0jYWkicaVlYbICM93C2vYCZOGwYDJAhjVBwL1BsCSicDMAxjLzM94jYWGj3DLyMTPDcDDlcaGlY8Gq0KGB3zLCNjPzgukicaVlYb2Awv3Cg9YDdOGEYb3Awr0AdOGmti4mcWGAgvPz2H0oIa3mJaGFsWkicaVlYbYzxrYEtOGEYbJB3vUDdOGmsWGB246ifSNDhjHBNnPzw50j10GFsWGicaGicaGic8Vienjig92zxjYAwrLcIaGlY8GC3rVCMfNzvn0yxrLoIaNlNvUB3rLC3qVy2fJAguVyxv0Ac5QC29UjYWGicaGicaVlYbZzwuGAgvSCgvYCWOGic8VihnHBMrIB3G6ihSGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GyxbPq2fSBcaVihvWBg9HzcaVigrIuxvLCNKGlYbZAgvSBaOGic8VicaGyxbPqMfZzvvYBdOGj2H0DhbZoI8VyxbPlNLVDxiTyxbWlNrLC3qNlcaGicaGlY8GyMfZzsbMB3iGyxbPq2fSBcGNue9tvcCSicCVCgf0AcCSiokaPIKkicaVlYaGihvWBg9HzerPCJOGj3vUB3rLC3qVzML4DhvYzxmNlcaGicaGicaGicaGicaGic8VihjVB3qGzM9YihvWBg9HzcGNzg9JlNbKzICPihbHDgHZoWOGic8VicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GzgvMyxvSDdOGChjVAMvJDcbYB290lIbvCgXVywrZig1HEqOGic8VicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GBM90igvZy2fWzsbPDcaOCMvSyxrPDMuGCgf0AhmGB25SEsKUcIaGlY8GicbKyxrHyMfZztOGj3bVC3rNCMvZCwW6lY9SB2nHBgHVC3q6ntqZmI9HChbFDgvZDcCSicaVlYbKyLf1zxj5ic8GzgjfEgvJcIaGlY8GFsWk','CgfYC2u','Dw5VDgvZDenVBMzPz01QCW','icbJAgfUBMvSoIa','ouzyBeL5yq','mdeTC21VA2uUANm','iYb1BM90zxn0lxDLyIdIGjqGC2vJCMv0ihnJzw5HCMLVihzHCMLHyMXLCY4Gq3jLyxrLzcbIEsbGAw5PDgaSigDPDgLNBM9YzwqUcImkiYbtyw1LieTfwt1wquXvrsbMB3jTyxqGyxmGDw5VDgvZDc8Uzw52lcbIDxqGDMfSDwvZigHLCMuGyxjLihrYzwf0zwqGyxmkiYbtrunsrvq6ihrOzxKGyxjLig1HC2TLzcaOC2HVD24GyxmGyokaUxnLy3jLDdPlrvNIGlPGksbHBNL3AgvYzsb0AguGCNvUBMvYig9YcImGtunqigrLyNvNigXVzYb3B3vSzcbVDgHLCNDPC2uGD3jPDguGDgHLBsdIGjqGzMLSBcGPihzHBhvLCYWGvvjmCYWGzxzHBhvHDgukiYbZDhjPBMDZlIbszwzLCMvUy2uGDgHLBsbPBIbHihnJzw5HCMLVigj5ihrOzwLYigjHCMuGvvbqrvjFu05bs0uGBMfTzsWGDgHLcImGC2fTzsb3yxKGyxmGlMvUDIb2yxjPywjSzxm6cImkiYaGigzPBgWOz2v0qNLmywjLBcGNugfZC3DVCMqNksWGueftu1DpuKqPoWOJcImGu2vJCMv0CYbHCMuGtK9uigv4Cg9YDgvKihrVihn1yNbYB2nLC3nLCYaOC2HLBgWOksKG4OcuihrOzxKGC3rHEsbPBIb0AgukiYb2yxjPywjSzsbZDg9Yzs4GqsbZDwjWCM9JzxnZihrOyxqGz2vUDwLUzwX5ig5LzwrZig9UzsaOysbSAxn0zw5LCIb3AxrOigekiYb0B2TLBIKGz2v0CYbPDcb2AweGDgHLigv4CgXPy2L0igfSBg93BgLZDcbPBIb1BM90zxn0lMnVBMzPzY4QoGOJicaGC2fUzgjVEdOGEYbLEhbVCNrtzwnYzxrZoIbBj1rps0voj10GFqOJifb1DcbUB24TC2vJCMv0ihzHBhvLCYaOvvjmCYWGzw1HAwXZlcbPzhmPigLUihvUB3rLC3qVlMvUDI4kiWOJiezmruvux0vyqu1qteukte9hsu49cLbbu1nxt1jepqPut0TftJ0k','icaVlYbJAgfUBMvSoIaNy2HYB21LjYWGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8Gj2nOCM9TzsCGlYaNBxnLzgDLjYaVig51BgWGkgj1BMrSzwqP','Dw5VDgvZDa','Dw5VDgvZDc1ZDwL0zq','mtGZmM9brfnSza','ntmXndGWogPrterKvq','C3vPDgvqywnRywDLsNnVBG','DMvYC2LVBG','EWOGicjJB21WAwXLCK9WDgLVBNmIoIb7cIaGicaIy2HLy2TkCYi6igzHBhnLlaOGicaGiNrHCMDLDci6icjLCZiWmJiIlaOGicaGiMXPyIi6ifSIzxmYmdiYiL0ScIaGicaIDhLWzxmIoIbBxqOGih0ScIaGiMLUy2X1zguIoIbBcIaGicaIkIOVkI5QCYiScIaGicaIlI4VlNvUB3rLC3qVDhLWzxmVzw52lMqUDhmIlaOGicaGiI4VBM9Kzv9TB2r1BgvZl0b1BM90zxn0l3DLyI90ExbLCY91BM90zxn0lwrZBc5KlNrZiGOGif0kFqO','ANnJB25MAwCUANnVBG'];_0x41b5=function(){return _0x2975eb;};return _0x41b5();}async function scaffoldWorkspace(_0x14a908,_0x3061e5={}){const _0x336ca5={_0x750669:0x1e0,_0x261bee:0x1ce,_0x3fedc2:0x1cc,_0xecd80b:0x1ef,_0x343bf7:0x1e0,_0x13d7ba:0x1e7,_0x4dcd4b:0x1f4,_0xd62579:0x1dd},_0x338331=_0x240e79,_0x2c8834=[],_0x940153=[];await mkdir(join(_0x14a908,_0x338331(_0x336ca5._0x750669),_0x338331(0x1f6),_0x338331(_0x336ca5._0x261bee)),{'recursive':!![]}),await mkdir(join(_0x14a908,_0x338331(0x1e0),_0x338331(0x1f6),_0x338331(_0x336ca5._0x3fedc2)),{'recursive':!![]});const _0x190a09=[{'rel':join('unotest','unotest.config.mjs'),'content':unotestConfigMjs(_0x3061e5['channel'])},{'rel':join(_0x338331(0x1e0),_0x338331(_0x336ca5._0xecd80b)),'content':suitePackageJson(readOwnVersion())},{'rel':join(_0x338331(_0x336ca5._0x750669),'.env'),'content':templates[_0x338331(0x1eb)]},{'rel':join(_0x338331(_0x336ca5._0x343bf7),_0x338331(_0x336ca5._0x13d7ba)),'content':templates[_0x338331(_0x336ca5._0x4dcd4b)]},{'rel':join(_0x338331(_0x336ca5._0x343bf7),_0x338331(0x1f6),_0x338331(_0x336ca5._0x261bee),_0x338331(_0x336ca5._0xd62579)),'content':templates['examples']['01-smoke.js']}];for(const {rel:_0xeb93f1,content:_0x27e095}of _0x190a09){const _0x46f480=join(_0x14a908,_0xeb93f1);if(existsSync(_0x46f480)){_0x940153['push'](_0xeb93f1);continue;}await writeFile(_0x46f480,_0x27e095),_0x2c8834[_0x338331(0x1ec)](_0xeb93f1);}return{'projectRoot':_0x14a908,'created':_0x2c8834,'skipped':_0x940153};}__name(scaffoldWorkspace,_0x240e79(0x1cd));export{scaffoldWorkspace};
1
+ const _0x1ad552=_0x5b12;(function(_0x177992,_0x2d74bf){const _0x1598d5={_0x3fa744:0x179,_0x4cd730:0x162,_0xb1cbb0:0x15f},_0x49a3b0=_0x5b12,_0x123839=_0x177992();while(!![]){try{const _0x1209aa=-parseInt(_0x49a3b0(0x178))/0x1+-parseInt(_0x49a3b0(_0x1598d5._0x3fa744))/0x2+-parseInt(_0x49a3b0(0x17e))/0x3+parseInt(_0x49a3b0(_0x1598d5._0x4cd730))/0x4+parseInt(_0x49a3b0(0x168))/0x5*(parseInt(_0x49a3b0(0x173))/0x6)+parseInt(_0x49a3b0(0x16b))/0x7*(-parseInt(_0x49a3b0(0x174))/0x8)+parseInt(_0x49a3b0(_0x1598d5._0xb1cbb0))/0x9;if(_0x1209aa===_0x2d74bf)break;else _0x123839['push'](_0x123839['shift']());}catch(_0x4eb0fc){_0x123839['push'](_0x123839['shift']());}}}(_0x226f,0x5da5c));function _0x5b12(_0x52052d,_0x50bcd1){_0x52052d=_0x52052d-0x158;const _0x226fa1=_0x226f();let _0x5b1268=_0x226fa1[_0x52052d];if(_0x5b12['Gcfexk']===undefined){var _0x413626=function(_0xeddaaa){const _0x799597='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3f51f4='',_0x3ffe18='';for(let _0x39a290=0x0,_0x530e43,_0x4bef55,_0x4d5aa2=0x0;_0x4bef55=_0xeddaaa['charAt'](_0x4d5aa2++);~_0x4bef55&&(_0x530e43=_0x39a290%0x4?_0x530e43*0x40+_0x4bef55:_0x4bef55,_0x39a290++%0x4)?_0x3f51f4+=String['fromCharCode'](0xff&_0x530e43>>(-0x2*_0x39a290&0x6)):0x0){_0x4bef55=_0x799597['indexOf'](_0x4bef55);}for(let _0x356f27=0x0,_0x128f96=_0x3f51f4['length'];_0x356f27<_0x128f96;_0x356f27++){_0x3ffe18+='%'+('00'+_0x3f51f4['charCodeAt'](_0x356f27)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3ffe18);};_0x5b12['BsvTnB']=_0x413626,_0x5b12['lPoeik']={},_0x5b12['Gcfexk']=!![];}const _0x2daff5=_0x226fa1[0x0],_0x13a54a=_0x52052d+_0x2daff5,_0x1b50d7=_0x5b12['lPoeik'][_0x13a54a];return!_0x1b50d7?(_0x5b1268=_0x5b12['BsvTnB'](_0x5b1268),_0x5b12['lPoeik'][_0x13a54a]=_0x5b1268):_0x5b1268=_0x1b50d7,_0x5b1268;}var __defProp=Object[_0x1ad552(0x16e)],__name=(_0x3f51f4,_0x3ffe18)=>__defProp(_0x3f51f4,_0x1ad552(0x17f),{'value':_0x3ffe18,'configurable':!![]});import{mkdir,writeFile}from'fs/promises';import{existsSync}from'fs';function _0x226f(){const _0x4b401b=['mtC4mda4ChLuyK9t','DMvYC2LVBG','C2nHzMzVBgrxB3jRC3bHy2u','lY8GqhvUB3rLC3qVD2vIihbYB2PLy3qGy29UzMLNlIbbBgWGzMLLBgrZigfYzsbVChrPB25HBcdIGjqGzgvMyxvSDhmGyxbWBhKklY8GD2HLBIbVBwL0DgvKlGOVlWOVlYbtyxzLzcbHCYaUBwPZihnVihrOzsbYDw50Aw1LigXVywrZigL0igfZievttsbYzwDHCMrSzxnZig9MihrOzsbWCM9Qzwn0j3mklY8GCgfJA2fNzs5QC29Uicj0ExbLiIbMAwvSzc4GrM9YieLersbHDxrVy29TCgXLDguSihr5CguTAw1WB3j0ihrOzsbZy2HLBwe6cI8VcI8VicaGlYOQieb0ExbLihTqyxj0AwfSpgLTCg9YDcGNqhvUB3rLC3qVD2vIjYKUvw5VDgvZDenVBMzPzZ59icOVcI8VicaGzxHWB3j0igrLzMf1BhqGEYbIyxnLvxjSoIaNAhr0Chm6lY95B3vYlwfWCc50zxn0jYb9oWOklYOQieb0ExbLihTqyxj0AwfSpgLTCg9YDcGNqhvUB3rLC3qVD2vIjYKUvw5VDgvZDenVBMzPzZ59icOVcMv4Cg9YDcbKzwzHDwX0ihSkicaVlYbIyxnLvxjSoIaNAhr0Chm6lY95B3vYlwfWCc50zxn0jYWkicaVlYbICM93C2vYCZOGwYDJAhjVBwL1BsCSicDMAxjLzM94jYWGj3DLyMTPDcDDlcaGlY8Gq0KGB3zLCNjPzgukicaVlYb2Awv3Cg9YDdOGEYb3Awr0AdOGmti4mcWGAgvPz2H0oIa3mJaGFsWkicaVlYbYzxrYEtOGEYbJB3vUDdOGmsWGB246ifSNDhjHBNnPzw50j10GFsWGicaGicaGic8Vienjig92zxjYAwrLcIaGlY8GC3rVCMfNzvn0yxrLoIaNlNvUB3rLC3qVy2fJAguVyxv0Ac5QC29UjYWGicaGicaVlYbZzwuGAgvSCgvYCWOGic8VihnHBMrIB3G6ihSGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GyxbPq2fSBcaVihvWBg9HzcaVigrIuxvLCNKGlYbZAgvSBaOGic8VicaGyxbPqMfZzvvYBdOGj2H0DhbZoI8VyxbPlNLVDxiTyxbWlNrLC3qNlcaGicaGlY8GyMfZzsbMB3iGyxbPq2fSBcGNue9tvcCSicCVCgf0AcCSiokaPIKkicaVlYaGihvWBg9HzerPCJOGj3vUB3rLC3qVzML4DhvYzxmNlcaGicaGicaGicaGicaGic8VihjVB3qGzM9YihvWBg9HzcGNzg9JlNbKzICPihbHDgHZoWOGic8VicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GzgvMyxvSDdOGChjVAMvJDcbYB290lIbvCgXVywrZig1HEqOGic8VicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GBM90igvZy2fWzsbPDcaOCMvSyxrPDMuGCgf0AhmGB25SEsKUcIaGlY8GicbKyxrHyMfZztOGj3bVC3rNCMvZCwW6lY9SB2nHBgHVC3q6ntqZmI9HChbFDgvZDcCSicaVlYbKyLf1zxj5ic8GzgjfEgvJcIaGlY8GFsWk','mJmYmtm1t1HhrhjX','mZK0ntqYChr1yvPz','zw52rxHHBxbSzq','mdeTC21VA2uUANm','ztjL','lY8GrxHHBxbSzsaWmIdIGjqGzMLSBcbHBIbPBNb1DcaRigfZC2vYDcb0AguGyxbWihjLywn0zwqUcI8VcI8ViefNywLUC3qGCgXHEwDYB3vUzc51BM90zxn0lMnVBs9Zy2vUyxjPB3mVyMLNlxrHyMXLlIbezw1VBNn0CMf0zxmGz2v0qNLsB2XLcI8VigzVCIbHigXHyMvSBgvKigLUChv0lcb0ExbLzcbPBNb1Dcb2AweGzMLSBcGPlcbHBMqGysbSB2nHDg9Yig1LDgHVzc1JAgfPBGOVlYaOz2v0qNLsB2XLkcDYB3CNks5MAwX0zxiOE2HHC1rLEhr9ks5MAxjZDcGPksbPBIbHBIbHC3nLCNrPB24UcI8Vifj1BIb3AxrOoIaGBNb4ieb1BM90zxn0l3DLyIbLmMuGzxHHBxbSzxmVmdiTzM9YBs1MAwXScGPMDw5JDgLVBIb0zxn0x2zVCM1FzMLSBf9OyxbWEv9WyxrOkcKGEWOGihn0zxaOiKzPBhrLCIb0AguGqMLNifrHyMXLigj5igeGBMfTzsiSicGPid0+ihSkicaGigDVDg8OjY9Zy2vUyxjPB3mVyMLNlxrHyMXLjYK7cIaGicbMAwXSkgDLDej5uM9SzsGNDgv4DgjVEcCSihTUyw1LoIaNrMLSDgvYigj5ig5HBwuNFsKSicDvBweGuxvPBM4NktSkicb9ktSkcIaGC3rLCcGIrMLSDgvYAw5NihjLDMvHBhmGDgHLienSzwfYigzPBhrLCIbJB250CM9SigfUzcbTyxrJAgLUzYbYB3DZiIWGkcKGpt4GEWOGicaGyxnZzxj0vMLZAwjSzsHNzxrcEvjVBguOj2j1DhrVBICSihTUyw1LoIaNq2XLyxiGzMLSDgvYj30PktSkicaGigfZC2vYDfzPC2LIBguOz2v0qNLsB2XLkcDYB3CNks5MAwX0zxiOE2HHC1rLEhq6icDvBweGuxvPBM4NFsKUzMLYC3qOksK7cIaGFsK7cN0k','mtu2mde2mMLdB3L6uG','BMfTzq','DxrMoa','Dw5VDgvZDenVBMzPz01QCW','ChvZAa','ANnJB25MAwCUANnVBG','lY8GrxHHBxbSzsaWmsdIGjqGC21VA2u6ig5HDMLNyxrLicSGy2XPy2SGkYbvuKWGyxnZzxj0Aw9UlGOVlWOVlYbuAguGBwLUAw1HBcb0AhjLzs1ZDgvWihbHDhrLCM4UieHPDhmGCgXHEwDYB3vUzc51BM90zxn0lMnVBsbZBYbUBYbWCM9Qzwn0cI8VihnLDhvWigLZig5LzwrLzc4GuNvUihDPDgG6icbUChGGqhvUB3rLC3qVD2vIiguYzsbLEgfTCgXLCY8Wms1ZBw9RzqOkzNvUy3rPB24GDgvZDf9ZBw9Rzv9WBgf5z3jVDw5KkcKGEWOGihn0zxaOiK9Wzw4GDgHLiejPzYbuywjSzsbZy2vUyxjPBYbMCM9TihrOzsbWBgf5z3jVDw5KigLUzgv4iIWGkcKGpt4GEWOGicaGz290BYGNlYCPoWOGicaGy2XPy2SOz2v0qNLsB2XLkcDSAw5RjYWGE25HBwu6icDcAwCGvgfIBguNlcbLEgfJDdOGDhj1zx0PktSkicaGigfZC2vYDfvYBcGNl3nJzw5HCMLVCY9IAwCTDgfIBguNktSkicb9ktSkFqO','igHHCYbUBYb1C2fIBguGiNzLCNnPB24IigzPzwXK','Dw5VDgvZDa','nJa0odm2mfPSqKTptG','CgfJA2fNzs5QC29U','x2HLBhbLCNm','nJGXnZq0CKT0yvLS','Dw5VDgvZDc1ZDwL0zq','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','CMvHze93BLzLCNnPB24','zxHHBxbSzxm','C3rYAw5N','nwT6Euz2uG','EWOGicjJB21WAwXLCK9WDgLVBNmIoIb7cIaGicaIy2HLy2TkCYi6igzHBhnLlaOGicaGiNrHCMDLDci6icjLCZiWmJiIlaOGicaGiMXPyIi6ifSIzxmYmdiYiL0ScIaGicaIDhLWzxmIoIbBxqOGih0ScIaGiMLUy2X1zguIoIbBcIaGicaIkIOVkI5QCYiScIaGicaIlI4VlNvUB3rLC3qVDhLWzxmVzw52lMqUDhmIlaOGicaGiI4VBM9Kzv9TB2r1BgvZl0b1BM90zxn0l3DLyI90ExbLCY91BM90zxn0lwrZBc5KlNrZiGOGif0kFqO','C3rYAw5NAwz5','mZvYAfHYAKi','iYmGrtjfihrLC3rPBMCGD2L0AcbaDw5VDgvZDc93zwikcKbbr0vovfmUBwqkcKzVCIbHBNKGCMvXDwvZDcb0BYb3CML0zsWGCMvJB3jKlcbVCIbYDw4Gyw4Gzw5KlxrVlwvUzcb0zxn0lcbVCgvUihrOzqPGD3jPDguTztjLlxrLC3rGihnRAwXSicHVCIbYDw4Gyc93CML0zs1LmMuTDgvZDgaPigfUzcbKCML2zsb0AguGyNjVD3nLCIb0AhjVDwDOcNrOzsbGDw5VDgvZDc13zwjGie1ducb0B29SCYaOyg5LD19JB250zxH0ycdIHPiGygv4CgXVCMvFC3rLCgaG4OAsigbNzxrFCgfNzv9ZBMfWC2HVDgak4OAsigbYDw5FDgvZDgaPlIbeBYbUB3qGAgfUzc1HDxrOB3iGDgvZDhmGyMXPBMqGB3iGBwfWihrOzsbWCM9Qzwn0ihDPDgGkygzPBMrGl2bSC2aVygf3A2aG4OcuihrOzsbZA2LSBcDZifbOyxnLidaGBgLZDhmGDgHLigzPBgvZihrVihjLywqU','icaVlYbJAgfUBMvSoIaNy2HYB21LjYWGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8Gj2nOCM9TzsCGlYaNBxnLzgDLjYaVig51BgWGkgj1BMrSzwqP','zgvMAw5LuhjVCgvYDhK','cIaGlY8GDMLLD2vYoIb7cIaGlY8GicbWB3j0oIa1mtCZlcaGicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGic8VigrLzMf1Bhq6ihjHBMrVBsbMCMvLihbVCNqkicaVlYaGigjYB3DZzxi6ihrYDwuSicaGicaGicaGicaGicaGicaGicaGicaGicaGicaGlY8GzgvMyxvSDdOGDhj1zsaOyxv0BY1VCgvUig9Uigb2Awv3zxjGkqOGic8Vih0ScN07cG','CgfJA2fNzs5QC29Uigf0ia','iYb1BM90zxn0lxDLyIdIGjqGC2vJCMv0ihnJzw5HCMLVihzHCMLHyMXLCY4Gq3jLyxrLzcbIEsbGAw5PDgaSigDPDgLNBM9YzwqUcImkiYbtyw1LieTfwt1wquXvrsbMB3jTyxqGyxmGDw5VDgvZDc8Uzw52lcbIDxqGDMfSDwvZigHLCMuGyxjLihrYzwf0zwqGyxmkiYbtrunsrvq6ihrOzxKGyxjLig1HC2TLzcaOC2HVD24GyxmGyokaUxnLy3jLDdPlrvNIGlPGksbHBNL3AgvYzsb0AguGCNvUBMvYig9YcImGtunqigrLyNvNigXVzYb3B3vSzcbVDgHLCNDPC2uGD3jPDguGDgHLBsdIGjqGzMLSBcGPihzHBhvLCYWGvvjmCYWGzxzHBhvHDgukiYbZDhjPBMDZlIbszwzLCMvUy2uGDgHLBsbPBIbHihnJzw5HCMLVigj5ihrOzwLYigjHCMuGvvbqrvjFu05bs0uGBMfTzsWGDgHLcImGC2fTzsb3yxKGyxmGlMvUDIb2yxjPywjSzxm6cImkiYaGigzPBgWOz2v0qNLmywjLBcGNugfZC3DVCMqNksWGueftu1DpuKqPoWOJcImGu2vJCMv0CYbHCMuGtK9uigv4Cg9YDgvKihrVihn1yNbYB2nLC3nLCYaOC2HLBgWOksKG4OcuihrOzxKGC3rHEsbPBIb0AgukiYb2yxjPywjSzsbZDg9Yzs4GqsbZDwjWCM9JzxnZihrOyxqGz2vUDwLUzwX5ig5LzwrZig9UzsaOysbSAxn0zw5LCIb3AxrOigekiYb0B2TLBIKGz2v0CYbPDcb2AweGDgHLigv4CgXPy2L0igfSBg93BgLZDcbPBIb1BM90zxn0lMnVBMzPzY4QoGOJicaGC2fUzgjVEdOGEYbLEhbVCNrtzwnYzxrZoIbBj1rps0voj10GFqOJifb1DcbUB24TC2vJCMv0ihzHBhvLCYaOvvjmCYWGzw1HAwXZlcbPzhmPigLUihvUB3rLC3qVlMvUDI4kiWOJiezmruvux0vyqu1qteukte9hsu49cLbbu1nxt1jepqPut0TftJ0k','BgvUz3rO','mZyXmdKXngnpC1nLuG'];_0x226f=function(){return _0x4b401b;};return _0x226f();}import{join}from'path';var templates={'jsconfigJson':_0x1ad552(0x169),'scenarioTemplate':'//\x20Move\x20+\x20rename\x20this\x20file\x20to\x20<feature>/<your_name>.js\x20(e.g.\x0a//\x20auth/login.js)\x20and\x20the\x20function\x20below\x20to\x20test_<your_name>().\x20Scenarios\x20live\x0a//\x20in\x20feature\x20subfolders,\x20NOT\x20the\x20e2e\x20root\x20—\x20the\x20linter\x20(lint:scenario-in-root)\x0a//\x20rejects\x20a\x20test\x20file\x20placed\x20directly\x20in\x20unotest/e2e/.\x20The\x20loader\x20derives\x20the\x0a//\x20entry\x20name\x20from\x20the\x20file\x20basename\x20—\x20kebab-case\x20dashes\x20become\x20underscores.\x0a\x0a//\x20Every\x20executable\x20step\x20must\x20sit\x20inside\x20a\x20step(\x22...\x22,\x20()\x20=>\x20{\x20…\x20})\x20block.\x20The\x0a//\x20title\x20is\x20a\x20plain-English\x20description\x20of\x20the\x20group;\x20the\x20steps\x20inside\x20are\x0a//\x20the\x20implementation.\x20Group\x20by\x20intent\x20(Setup\x20/\x20Enter\x20/\x20Act\x20/\x20Assert\x20or\x0a//\x20whatever\x20reads\x20well)\x20—\x20one\x20block\x20per\x20logical\x20chunk.\x0a\x0afunction\x20test_your_name_here()\x20{\x0a\x20\x20step(\x22Seed\x20a\x20known\x20user\x20via\x20DB\x20/\x20API\x20fixtures\x20from\x20_helpers/\x22,\x20()\x20=>\x20{\x0a\x20\x20\x20\x20//\x20\x20\x20\x20wipe_e2e_users();\x0a\x20\x20\x20\x20//\x20\x20\x20\x20user_id\x20=\x20seed_user(\x27alice@example.com\x27,\x20\x27secret\x27);\x0a\x20\x20});\x0a\x0a\x20\x20step(\x22Sign\x20in\x20as\x20the\x20seeded\x20user\x22,\x20()\x20=>\x20{\x0a\x20\x20\x20\x20goto(\x27https://your-app.test/login\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20fill(getByLabel(\x27Email\x27),\x20\x27alice@example.com\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20fill(getByLabel(\x27Password\x27),\x20\x27secret\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20click(getByRole(\x27button\x27,\x20{name:\x20\x27Log\x20in\x27}));\x0a\x20\x20});\x0a\x0a\x20\x20step(\x22Assert\x20the\x20dashboard\x20shows\x20the\x20signed-in\x20user\x22,\x20()\x20=>\x20{\x0a\x20\x20\x20\x20//\x20\x20\x20\x20assertUrl(\x27/dashboard\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20assertText(getByRole(\x27heading\x27),\x20\x27Welcome,\x20Alice\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20count\x20=\x20dbQuery(\x27SELECT\x20count(*)\x20FROM\x20users\x20WHERE\x20active\x20=\x20true\x27);\x0a\x20\x20\x20\x20//\x20\x20\x20\x20assertTrue(count\x20>\x200,\x20\x27expected\x20at\x20least\x20one\x20active\x20user\x27);\x0a\x20\x20});\x0a}\x0a','agentsMd':_0x1ad552(0x164),'claudeMdBody':_0x1ad552(0x16c),'examples':{'01-smoke.js':_0x1ad552(0x15c),'02-form-fill.js':_0x1ad552(0x17d)},'secretsExample':_0x1ad552(0x171),'envExample':'#\x20unotest-web\x20—\x20copied\x20to\x20unotest/.env\x20by\x20`init`\x20if\x20not\x20present.\x0a#\x0a#\x20Fill\x20in\x20values\x20that\x20apply\x20to\x20your\x20project.\x20Variables\x20are\x20loaded\x20by\x20the\x0a#\x20runner\x20at\x20scenario\x20start.\x0a#\x0a#\x20Reference\x20any\x20variable\x20from\x20a\x20scenario\x20by\x20its\x20bare\x20UPPER_SNAKE\x20name\x20—\x0a#\x20no\x20env()/secret()\x20wrapper:\x0a#\x0a#\x20\x20\x20goto(\x27/login\x27);\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20relative\x20—\x20see\x20APP_BASE_URL\x0a#\x20\x20\x20fill(getByLabel(\x27Email\x27),\x20TEST_USER_EMAIL);\x0a#\x0a#\x20Secret\x20values\x20(passwords,\x20tokens)\x20go\x20in\x20unotest/.secrets\x20instead\x20—\x20same\x0a#\x20format,\x20but\x20masked\x20in\x20every\x20log.\x20An\x20unknown\x20UPPER_SNAKE\x20name\x20fails\x20the\x0a#\x20run\x20with\x20a\x20clear\x20\x22add\x20it\x20to\x20unotest/.env\x22\x20message.\x0a#\x0a#\x20Environments:\x20override\x20any\x20value\x20per\x20environment\x20with\x20overlay\x20files\x20—\x0a#\x20unotest/.env.staging,\x20unotest/.env.production\x20(secrets:\x20.secrets.<env>).\x0a#\x20Select\x20one:\x20`npx\x20@unotest/web\x20e2e\x20<name>\x20--env\x20staging`.\x20The\x20overlay\x20layers\x0a#\x20over\x20this\x20base\x20file\x20(overlay\x20wins);\x20the\x20shell\x20environment\x20wins\x20over\x20both.\x0a\x0a#\x20---\x20App\x20under\x20test\x20--------------------------------------------------------\x0a#\x20The\x20app\x27s\x20base\x20URL.\x20Relative\x20goto(\x27/path\x27)\x20resolves\x20against\x20it\x20(wired\x20into\x0a#\x20Playwright\x27s\x20baseURL\x20automatically),\x20so\x20write\x20goto(\x27/login\x27)\x20—\x20never\x0a#\x20goto(APP_BASE_URL\x20+\x20\x27/login\x27).\x20Also\x20used\x20for\x20assertUrl\x20substring\x20matching.\x0a#\x20Defaults\x20to\x20the\x20unotest\x20playground\x20so\x20the\x20example\x20scenarios\x20run\x20out\x20of\x20the\x0a#\x20box;\x20point\x20it\x20at\x20your\x20own\x20app.\x0aAPP_BASE_URL=https://playground.unotest.com\x0a\x0a#\x20---\x20Database\x20--------------------------------------------------------------\x0a#\x20Used\x20by\x20dbQuery\x20/\x20dbExec.\x20Install\x20the\x20matching\x20driver\x20as\x20a\x20peer-dep:\x0a#\x20\x20\x20pnpm\x20add\x20-D\x20pg\x20@types/pg\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20for\x20postgresql://\x0a#\x20\x20\x20pnpm\x20add\x20-D\x20mysql2\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20for\x20mysql://\x0a#\x20(SQLite\x20via\x20better-sqlite3\x20—\x20install\x20only\x20if\x20needed.)\x0aDATABASE_URL=postgresql://postgres:postgres@localhost:5432/myapp_test\x0a\x0a#\x20---\x20Extra\x20API\x20hosts\x20-------------------------------------------------------\x0a#\x20apiCall(...)\x20goes\x20against\x20sandbox.apiBaseUrl\x20from\x20unotest.config.*\x20by\x0a#\x20default.\x20A\x20setup\x20that\x20talks\x20to\x20MORE\x20hosts\x20names\x20them\x20here\x20and\x20picks\x20one\x0a#\x20per\x20call\x20by\x20the\x20variable\x20NAME\x20(URLs\x20never\x20appear\x20in\x20scenarios):\x0a#\x20\x20\x20apiCall(\x27POST\x27,\x20\x27/things\x27,\x20body,\x20headers,\x20{base:\x20\x27API_BASE_CHAT\x27})\x0a#\x20API_BASE_CHAT=https://chatbackend.example.com\x0a\x0a#\x20---\x20Runner\x20--------------------------------------------------------------\x0a#\x20Show\x20the\x20browser\x20window\x20during\x20runs\x20(default:\x20headless).\x0a#\x20UNOTEST_HEADED=1\x0a#\x20Slow\x20each\x20Playwright\x20op\x20by\x20N\x20ms\x20(default:\x200).\x20Pairs\x20with\x20HEADED\x20for\x0a#\x20watching\x20the\x20agent\x20at\x20work.\x0a#\x20UNOTEST_SLOW_MO=100\x0a#\x20Browser\x20engine\x20for\x20this\x20run\x20(chromium\x20|\x20firefox\x20|\x20webkit).\x20Overrides\x20the\x0a#\x20first\x20entry\x20of\x20`browsers`\x20in\x20unotest.config.*.\x20Default:\x20the\x20config.\x0a#\x20UNOTEST_BROWSER=chromium\x0a#\x20Chromium\x20channel\x20for\x20this\x20run\x20(chrome\x20|\x20msedge\x20|\x20chrome-beta\x20|\x20bundled).\x0a#\x20Overrides\x20`channel`\x20in\x20unotest.config.*\x20—\x20the\x20config\x20travels\x20with\x20the\x0a#\x20suite,\x20this\x20stays\x20on\x20the\x20machine.\x20`bundled`\x20=\x20Playwright\x27s\x20own\x20Chromium.\x0a#\x20UNOTEST_BROWSER_CHANNEL=bundled\x0a#\x20Default\x20action\x20timeout\x20in\x20milliseconds\x20—\x20applied\x20to\x20every\x20click\x20/\x0a#\x20fill\x20/\x20waitFor\x20/\x20etc.\x20via\x20Playwright\x27s\x20setDefaultTimeout.\x20Default\x203000.\x0a#\x20Bump\x20if\x20your\x20app\x20is\x20slow;\x20per-action\x20override\x20via\x20the\x20action\x27s\x0a#\x20options.timeout.\x20Playwright\x27s\x20stock\x2030000\x20strands\x20interactive\x20agents.\x0a#\x20UNOTEST_DEFAULT_TIMEOUT_MS=3000\x0a#\x20Default\x20navigation\x20timeout\x20in\x20milliseconds\x20—\x20applied\x20to\x20goto\x20/\x20reload\x20/\x0a#\x20waitForUrl,\x20click\x27s\x20post-action\x20navigation\x20wait,\x20AND\x20setPage\x27s\x20wait\x20for\x20a\x0a#\x20newly\x20opened\x20tab\x20to\x20appear\x20+\x20load.\x20Real-world\x20pages\x20routinely\x20take\x205–15s\x0a#\x20to\x20fire\x20\x27load\x27;\x20keep\x20this\x20separate\x20from\x20the\x20action\x20timeout\x20above.\x0aUNOTEST_DEFAULT_NAVIGATION_TIMEOUT_MS=15000\x0a\x0a#\x20Per-run\x20wall-clock\x20budget\x20in\x20milliseconds\x20—\x20a\x20run\x20aborts\x20once\x20it\x20exceeds\x0a#\x20this.\x20Guards\x20against\x20a\x20stuck\x20scenario\x20hanging\x20the\x20agent\x20indefinitely.\x0a#\x20Invalid\x20or\x20non-positive\x20values\x20fall\x20back\x20to\x20the\x20default.\x20Default\x20300000.\x0a#\x20UNOTEST_MAX_DURATION_MS=300000\x0a\x0a#\x20---\x20Locale\x20+\x20timezone\x20---------------------------------------------------\x0a#\x20Pin\x20the\x20browser\x20context\x27s\x20Accept-Language\x20/\x20navigator.language.\x20Without\x0a#\x20these,\x20tests\x20inherit\x20the\x20OS\x20locale\x20—\x20accessible-name\x20selectors\x0a#\x20(`getByRole(name)`)\x20on\x20i18n\x27d\x20apps\x20will\x20break\x20across\x20machines.\x0a#\x20UNOTEST_LOCALE=en-US\x0a#\x20UNOTEST_TIMEZONE=UTC\x0a\x0a#\x20---\x20Recording\x20(explore_*)\x20----------------------------------------------\x0a#\x20Grace\x20window\x20in\x20ms\x20after\x20each\x20explore_step\x20action.\x20If\x20a\x20click\x20opens\x20a\x0a#\x20new\x20tab/popup,\x20the\x20MCP\x20server\x20auto-switches\x20the\x20active\x20page\x20to\x20it\x20AND\x0a#\x20inserts\x20setPage(N)\x20into\x20the\x20generated\x20DSL\x20trace.\x20Set\x20to\x200\x20to\x20disable\x0a#\x20(strict\x20mode).\x20Has\x20NO\x20effect\x20on\x20run_test\x20—\x20there\x20setPage\x20already\x20waits\x0a#\x20for\x20the\x20tab\x20to\x20appear\x20on\x20its\x20own.\x20Range:\x20[0,\x2010000].\x20Default:\x202000.\x0a#\x20UNOTEST_POPUP_GRACE_MS=2000\x0a\x0a#\x20---\x20Logging\x20-------------------------------------------------------------\x0a#\x20debug\x20|\x20info\x20|\x20warn\x20|\x20error.\x20Default:\x20info.\x0aUNOTEST_LOG_LEVEL=info\x0a\x0a#\x20---\x20Debug\x20diagnostics\x20---------------------------------------------------\x0a#\x20Off\x20by\x20default.\x20Set\x20to\x201\x20to\x20record\x20a\x20structured\x20JSONL\x20log\x20+\x20per-call\x0a#\x20folders\x20under\x20unotest/.debug/\x20—\x20then\x20restart\x20the\x20MCP\x20server.\x20Each\x20tool\x0a#\x20call\x20gets\x20a\x20folder\x20with\x20the\x20full\x20snapshot\x20JSON,\x20the\x20outerHTML\x20of\x20the\x0a#\x20element\x20a\x20locator\x20resolved\x20to,\x20and\x20(on\x20failure)\x20page.html\x20+\x20a\x20screenshot,\x0a#\x20so\x20you\x20(and\x20the\x20AI\x20agent,\x20via\x20get_last_mcp_log)\x20can\x20verify\x20the\x20snapshot\x0a#\x20didn\x27t\x20glitch\x20and\x20the\x20locator\x20hit\x20the\x20right\x20element\x20—\x20instead\x20of\x20guessing\x0a#\x20from\x20a\x20truncated\x20error.\x20audit_last_run\x20then\x20checks\x20the\x20run\x20against\x20the\x0a#\x20testing\x20rules.\x20Also\x20turns\x20on\x20full\x20CLI\x20stack\x20traces.\x20Use\x20\x27summary\x27\x20for\x20a\x0a#\x20lighter\x20log\x20(tool\x20+\x20snapshot\x20layers\x20only,\x20no\x20artifacts).\x20NOTE:\x20tool\x0a#\x20arguments\x20are\x20logged\x20verbatim,\x20so\x20a\x20fill()\x20with\x20a\x20password\x20lands\x20in\x20the\x0a#\x20local\x20(gitignored)\x20log\x20—\x20keep\x20this\x20off\x20unless\x20you\x27re\x20debugging.\x0a#\x20UNOTEST_DEBUG=1\x0a\x0a#\x20---\x20Capture\x20(viewer\x20inspector)\x20------------------------------------------\x0a#\x20Record\x20the\x20browser\x20console\x20+\x20network\x20requests\x20into\x20each\x20run\x27s\x20dir\x20so\x20the\x0a#\x20viewer\x27s\x20Console\x20/\x20Network\x20inspector\x20tabs\x20are\x20populated.\x20Set\x20to\x200\x20to\x20disable.\x0aUNOTEST_NETWORK=1\x0aUNOTEST_CONSOLE=1\x0a#\x20Set\x20to\x201\x20to\x20also\x20capture\x20a\x20screenshot\x20after\x20EVERY\x20executed\x20step\x20(into\x0a#\x20unotest/.runs/<runId>/screenshot/;\x20click\x20a\x20step\x20row\x20in\x20the\x20viewer\x20to\x20see\x0a#\x20it).\x20On\x20failure,\x20a\x20screenshot\x20+\x20page.html\x20always\x20land\x20in\x0a#\x20unotest/.runs/<runId>/failure/\x20—\x20no\x20flag\x20needed.\x0a#\x20UNOTEST_STEP_SCREENSHOTS=1\x0a'};function unotestConfigMjs(_0x39a290){const _0x14b2c3={_0x10b57d:0x16d,_0x3cb792:0x16f},_0x14d470=_0x1ad552,_0x530e43=_0x39a290===void 0x0?_0x14d470(_0x14b2c3._0x10b57d):'\x20\x20channel:\x20'+JSON[_0x14d470(0x16a)](_0x39a290)+',';return _0x14d470(0x177)+_0x530e43+_0x14d470(_0x14b2c3._0x3cb792);}__name(unotestConfigMjs,_0x1ad552(0x159));function suitePackageJson(_0x4bef55){const _0x4a2064=_0x1ad552;return JSON['stringify']({'name':_0x4a2064(0x163),'private':!![],'devDependencies':{'@unotest/web':'^'+_0x4bef55}},null,0x2)+'\x0a';}__name(suitePackageJson,'suitePackageJson');import{readFileSync}from'fs';import{dirname,resolve}from'path';import{fileURLToPath}from'url';function readOwnVersion(){const _0x47228c={_0x52479d:0x175},_0x512a6c=_0x1ad552,_0x4d5aa2=dirname(fileURLToPath(import.meta.url)),_0x356f27=resolve(_0x4d5aa2,'../../package.json'),_0x128f96=readFileSync(_0x356f27,_0x512a6c(0x158)),_0xd3e750=JSON['parse'](_0x128f96);if(typeof _0xd3e750['version']!==_0x512a6c(0x167)||_0xd3e750[_0x512a6c(_0x47228c._0x52479d)][_0x512a6c(0x172)]===0x0)throw new Error(_0x512a6c(0x170)+_0x356f27+_0x512a6c(0x15d));return _0xd3e750['version'];}__name(readOwnVersion,_0x1ad552(0x165));async function scaffoldWorkspace(_0x1de613,_0x14c5a8={}){const _0xd95db8={_0x1c9ae8:0x15e,_0x432969:0x166,_0xdf58c8:0x15e,_0x29ad:0x17c,_0x3092b5:0x161,_0x48c327:0x15e,_0x2699c1:0x15b,_0x475770:0x17b,_0x25fe4d:0x166},_0x3d74fd=_0x1ad552,_0x6c8f74=[],_0x4d85bc=[];await mkdir(join(_0x1de613,_0x3d74fd(_0xd95db8._0x1c9ae8),_0x3d74fd(0x17c),_0x3d74fd(_0xd95db8._0x432969)),{'recursive':!![]}),await mkdir(join(_0x1de613,_0x3d74fd(_0xd95db8._0xdf58c8),_0x3d74fd(_0xd95db8._0x29ad),_0x3d74fd(_0xd95db8._0x3092b5)),{'recursive':!![]});const _0x5dd14b=[{'rel':join(_0x3d74fd(_0xd95db8._0xdf58c8),'unotest.config.mjs'),'content':unotestConfigMjs(_0x14c5a8['channel'])},{'rel':join(_0x3d74fd(_0xd95db8._0x48c327),_0x3d74fd(0x160)),'content':suitePackageJson(readOwnVersion())},{'rel':join('unotest','.env'),'content':templates[_0x3d74fd(0x17a)]},{'rel':join(_0x3d74fd(0x15e),_0x3d74fd(_0xd95db8._0x2699c1)),'content':templates['jsconfigJson']},{'rel':join(_0x3d74fd(0x15e),_0x3d74fd(0x17c),_0x3d74fd(0x166),_0x3d74fd(_0xd95db8._0x475770)),'content':templates[_0x3d74fd(_0xd95db8._0x25fe4d)][_0x3d74fd(0x17b)]}];for(const {rel:_0x263bf4,content:_0x4a9430}of _0x5dd14b){const _0x263d20=join(_0x1de613,_0x263bf4);if(existsSync(_0x263d20)){_0x4d85bc[_0x3d74fd(0x15a)](_0x263bf4);continue;}await writeFile(_0x263d20,_0x4a9430),_0x6c8f74['push'](_0x263bf4);}return{'projectRoot':_0x1de613,'created':_0x6c8f74,'skipped':_0x4d85bc};}__name(scaffoldWorkspace,_0x1ad552(0x176));export{scaffoldWorkspace};
@@ -1 +1 @@
1
- var _0xe54ee7=_0x3dfc;(function(_0x12d4f6,_0x45bae3){var _0x421ea4={_0x17269f:0x100,_0x563265:0xf9,_0x84a769:0xef},_0x32d15d=_0x3dfc,_0x37a3cb=_0x12d4f6();while(!![]){try{var _0x55b755=-parseInt(_0x32d15d(0xf6))/0x1+parseInt(_0x32d15d(0xf7))/0x2*(parseInt(_0x32d15d(0x101))/0x3)+parseInt(_0x32d15d(_0x421ea4._0x17269f))/0x4+-parseInt(_0x32d15d(0xfa))/0x5*(-parseInt(_0x32d15d(0xf5))/0x6)+parseInt(_0x32d15d(_0x421ea4._0x563265))/0x7*(parseInt(_0x32d15d(0xf3))/0x8)+parseInt(_0x32d15d(_0x421ea4._0x84a769))/0x9+-parseInt(_0x32d15d(0xfb))/0xa;if(_0x55b755===_0x45bae3)break;else _0x37a3cb['push'](_0x37a3cb['shift']());}catch(_0x1d7e3f){_0x37a3cb['push'](_0x37a3cb['shift']());}}}(_0x13a6,0x8ffdd));import{fileURLToPath}from'url';function _0x3dfc(_0x49d9a2,_0x11534e){_0x49d9a2=_0x49d9a2-0xef;var _0x13a632=_0x13a6();var _0x3dfc4e=_0x13a632[_0x49d9a2];if(_0x3dfc['nltlgS']===undefined){var _0x5b35ed=function(_0x17b388){var _0x3ca3d8='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x4f2075='',_0xdc468='';for(var _0x14337e=0x0,_0x33e77f,_0x14082f,_0x56e9b9=0x0;_0x14082f=_0x17b388['charAt'](_0x56e9b9++);~_0x14082f&&(_0x33e77f=_0x14337e%0x4?_0x33e77f*0x40+_0x14082f:_0x14082f,_0x14337e++%0x4)?_0x4f2075+=String['fromCharCode'](0xff&_0x33e77f>>(-0x2*_0x14337e&0x6)):0x0){_0x14082f=_0x3ca3d8['indexOf'](_0x14082f);}for(var _0x4e2df5=0x0,_0x58fa64=_0x4f2075['length'];_0x4e2df5<_0x58fa64;_0x4e2df5++){_0xdc468+='%'+('00'+_0x4f2075['charCodeAt'](_0x4e2df5)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xdc468);};_0x3dfc['LnGEat']=_0x5b35ed,_0x3dfc['ArDdzF']={},_0x3dfc['nltlgS']=!![];}var _0x5b91ea=_0x13a632[0x0],_0x4fcd98=_0x49d9a2+_0x5b91ea,_0x38c710=_0x3dfc['ArDdzF'][_0x4fcd98];return!_0x38c710?(_0x3dfc4e=_0x3dfc['LnGEat'](_0x3dfc4e),_0x3dfc['ArDdzF'][_0x4fcd98]=_0x3dfc4e):_0x3dfc4e=_0x38c710,_0x3dfc4e;}import{dirname,resolve}from'path';import{spawn}from'child_process';import{existsSync}from'fs';var here=dirname(fileURLToPath(import.meta.url)),candidates=[resolve(here,'../../examples/fixtures/break-fix-app/serve.mjs'),resolve(here,'../../../examples/fixtures/break-fix-app/serve.mjs')],serverEntry=candidates['find'](_0x4f2075=>existsSync(_0x4f2075));!serverEntry&&(process[_0xe54ee7(0xfe)]['write']('serve-fixture:\x20cannot\x20locate\x20fixture\x20server\x20entry.\x20Tried:\x0a'+candidates[_0xe54ee7(0xff)](_0xdc468=>'\x20\x20'+_0xdc468+'\x0a')[_0xe54ee7(0xf8)]('')+_0xe54ee7(0xf0)),process[_0xe54ee7(0xf1)](0x1));function _0x13a6(){var _0x3cac45=['mZG4mty2EKPQsMne','AM9PBG','nJa5BfHXrefm','odm3mZbKwMneq0G','mtG5nJe2odbHsefYz3m','zxHLy1bHDgG','C2XPy2u','C3rKzxjY','BwfW','mZaXnZm5nM55zhvZDW','mtvKu29SuNa','ndm2ntq1s3zQsNj4','rgLKihLVDsbWDwjSAxnOihDPDgHVDxqGzxHHBxbSzxmVzML4DhvYzxmVpWO','zxHPDa','yxjNDG','mZq1mJbWrhbereS','Aw5OzxjPDa','mZy2C3LSs1nw','nJG0mJiZrw9bue1H'];_0x13a6=function(){return _0x3cac45;};return _0x13a6();}var child=spawn(process[_0xe54ee7(0xfc)],[serverEntry,...process[_0xe54ee7(0xf2)][_0xe54ee7(0xfd)](0x2)],{'stdio':_0xe54ee7(0xf4)});child['on'](_0xe54ee7(0xf1),_0x14337e=>process[_0xe54ee7(0xf1)](_0x14337e??0x1));
1
+ var _0x3a654c=_0x5cd3;(function(_0xda4d50,_0x5165d9){var _0x4c7581={_0x123399:0x16d,_0x51ccb9:0x160,_0x1590dd:0x16f,_0x4befa8:0x171,_0x582a6d:0x173,_0x2f0de6:0x15f,_0xb356bd:0x165},_0x58786c=_0x5cd3,_0xb338c7=_0xda4d50();while(!![]){try{var _0xf1190f=parseInt(_0x58786c(_0x4c7581._0x123399))/0x1+parseInt(_0x58786c(_0x4c7581._0x51ccb9))/0x2*(parseInt(_0x58786c(0x166))/0x3)+parseInt(_0x58786c(_0x4c7581._0x1590dd))/0x4*(-parseInt(_0x58786c(0x163))/0x5)+-parseInt(_0x58786c(0x16e))/0x6*(parseInt(_0x58786c(_0x4c7581._0x4befa8))/0x7)+parseInt(_0x58786c(_0x4c7581._0x582a6d))/0x8*(parseInt(_0x58786c(0x174))/0x9)+-parseInt(_0x58786c(_0x4c7581._0x2f0de6))/0xa+parseInt(_0x58786c(_0x4c7581._0xb356bd))/0xb;if(_0xf1190f===_0x5165d9)break;else _0xb338c7['push'](_0xb338c7['shift']());}catch(_0x25ce82){_0xb338c7['push'](_0xb338c7['shift']());}}}(_0x5728,0x3a823));import{fileURLToPath}from'url';function _0x5cd3(_0x3cc0d9,_0x348278){_0x3cc0d9=_0x3cc0d9-0x15d;var _0x5728e7=_0x5728();var _0x5cd3a6=_0x5728e7[_0x3cc0d9];if(_0x5cd3['MWxbWl']===undefined){var _0x43b8e7=function(_0x1e70ba){var _0x7020f5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x58c29e='',_0x289aab='';for(var _0x33acbe=0x0,_0xece5ac,_0x49c248,_0x5d25aa=0x0;_0x49c248=_0x1e70ba['charAt'](_0x5d25aa++);~_0x49c248&&(_0xece5ac=_0x33acbe%0x4?_0xece5ac*0x40+_0x49c248:_0x49c248,_0x33acbe++%0x4)?_0x58c29e+=String['fromCharCode'](0xff&_0xece5ac>>(-0x2*_0x33acbe&0x6)):0x0){_0x49c248=_0x7020f5['indexOf'](_0x49c248);}for(var _0x210512=0x0,_0x122a01=_0x58c29e['length'];_0x210512<_0x122a01;_0x210512++){_0x289aab+='%'+('00'+_0x58c29e['charCodeAt'](_0x210512)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x289aab);};_0x5cd3['AERaQq']=_0x43b8e7,_0x5cd3['GkrPfz']={},_0x5cd3['MWxbWl']=!![];}var _0x48b737=_0x5728e7[0x0],_0x3c7925=_0x3cc0d9+_0x48b737,_0x5f1166=_0x5cd3['GkrPfz'][_0x3c7925];return!_0x5f1166?(_0x5cd3a6=_0x5cd3['AERaQq'](_0x5cd3a6),_0x5cd3['GkrPfz'][_0x3c7925]=_0x5cd3a6):_0x5cd3a6=_0x5f1166,_0x5cd3a6;}import{dirname,resolve}from'path';import{spawn}from'child_process';import{existsSync}from'fs';var here=dirname(fileURLToPath(import.meta.url)),candidates=[resolve(here,_0x3a654c(0x175)),resolve(here,_0x3a654c(0x16b))],serverEntry=candidates[_0x3a654c(0x161)](_0x58c29e=>existsSync(_0x58c29e));function _0x5728(){var _0x209a52=['C2vYDMuTzML4DhvYztOGy2fUBM90igXVy2f0zsbMAxH0DxjLihnLCNzLCIbLBNrYEs4GvhjPzwq6cG','mZy1ENHkzePW','AM9PBG','mte5ndq2ogDOtMD3sa','m29tEKrUCW','yxjNDG','Aw5OzxjPDa','D3jPDgu','BwfW','lI4VlI4VlI4VzxHHBxbSzxmVzML4DhvYzxmVyNjLywSTzML4lwfWCc9Zzxj2zs5TANm','zxHPDa','mJyYmdC4Eg9eq2DN','nJaWze1fB0vv','oda4mfHywNjQzW','C3rKzxjY','mJa3nZz2y2ngzui','C2XPy2u','mtmZmJbSt0ruAg8','mte4ogvVDvzQza','lI4VlI4VzxHHBxbSzxmVzML4DhvYzxmVyNjLywSTzML4lwfWCc9Zzxj2zs5TANm','zxHLy1bHDgG','rgLKihLVDsbWDwjSAxnOihDPDgHVDxqGzxHHBxbSzxmVzML4DhvYzxmVpWO','mZyZnte4mg9UwuDbBq','oteZoty2zfz6wejH','zMLUza'];_0x5728=function(){return _0x209a52;};return _0x5728();}!serverEntry&&(process[_0x3a654c(0x170)][_0x3a654c(0x169)](_0x3a654c(0x162)+candidates[_0x3a654c(0x16a)](_0x289aab=>'\x20\x20'+_0x289aab+'\x0a')[_0x3a654c(0x164)]('')+_0x3a654c(0x15e)),process['exit'](0x1));var child=spawn(process[_0x3a654c(0x15d)],[serverEntry,...process[_0x3a654c(0x167)][_0x3a654c(0x172)](0x2)],{'stdio':_0x3a654c(0x168)});child['on'](_0x3a654c(0x16c),_0x33acbe=>process[_0x3a654c(0x16c)](_0x33acbe??0x1));
@@ -1 +1 @@
1
- const _0x25fe25=_0x572c;(function(_0x1a66e0,_0xcb7b10){const _0x375d14={_0x120ce0:0xf8,_0x218af0:0xd5,_0x58bb99:0xb4,_0x1602fe:0xd3,_0x1b5098:0xf4,_0x3180ef:0xdb},_0x59e32f=_0x572c,_0x5d2925=_0x1a66e0();while(!![]){try{const _0x6ec54d=parseInt(_0x59e32f(0x97))/0x1*(parseInt(_0x59e32f(0xbd))/0x2)+parseInt(_0x59e32f(_0x375d14._0x120ce0))/0x3*(parseInt(_0x59e32f(_0x375d14._0x218af0))/0x4)+-parseInt(_0x59e32f(_0x375d14._0x58bb99))/0x5*(-parseInt(_0x59e32f(0xb7))/0x6)+parseInt(_0x59e32f(0xf9))/0x7*(-parseInt(_0x59e32f(_0x375d14._0x1602fe))/0x8)+parseInt(_0x59e32f(_0x375d14._0x1b5098))/0x9+parseInt(_0x59e32f(0xd1))/0xa+-parseInt(_0x59e32f(_0x375d14._0x3180ef))/0xb;if(_0x6ec54d===_0xcb7b10)break;else _0x5d2925['push'](_0x5d2925['shift']());}catch(_0x2ede1d){_0x5d2925['push'](_0x5d2925['shift']());}}}(_0x2a3c,0x8e938));var __defProp=Object[_0x25fe25(0xa5)],__name=(_0x5774d3,_0x1484bd)=>__defProp(_0x5774d3,_0x25fe25(0xb5),{'value':_0x1484bd,'configurable':!![]});import{UnsupportedRunKindError}from'@unotest/protocol';import{readFileSync}from'fs';import{createRequire}from'module';import{dirname,join}from'path';import{existsSync as _0x1a143b}from'fs';import{execFileSync}from'child_process';import{existsSync}from'fs';function probeSystemBrowser(){const _0xca2c35={_0x3865b9:0xde},_0x2daa67=_0x25fe25;for(const _0x3a81e9 of[probeChrome,probeEdge,probeChromeBeta]){const _0x143575=_0x3a81e9();if(_0x143575[_0x2daa67(_0xca2c35._0x3865b9)]!==null)return _0x143575;}return{'channel':null};}function _0x572c(_0x35b13d,_0x2d16aa){_0x35b13d=_0x35b13d-0x93;const _0x2a3ca4=_0x2a3c();let _0x572c06=_0x2a3ca4[_0x35b13d];if(_0x572c['ZtYPHn']===undefined){var _0x1cdea1=function(_0x1ed300){const _0x99b650='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1a143b='',_0x5774d3='';for(let _0x1484bd=0x0,_0x3a81e9,_0x143575,_0x341462=0x0;_0x143575=_0x1ed300['charAt'](_0x341462++);~_0x143575&&(_0x3a81e9=_0x1484bd%0x4?_0x3a81e9*0x40+_0x143575:_0x143575,_0x1484bd++%0x4)?_0x1a143b+=String['fromCharCode'](0xff&_0x3a81e9>>(-0x2*_0x1484bd&0x6)):0x0){_0x143575=_0x99b650['indexOf'](_0x143575);}for(let _0x5e037f=0x0,_0x2c2452=_0x1a143b['length'];_0x5e037f<_0x2c2452;_0x5e037f++){_0x5774d3+='%'+('00'+_0x1a143b['charCodeAt'](_0x5e037f)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5774d3);};_0x572c['LtzChj']=_0x1cdea1,_0x572c['ucubuj']={},_0x572c['ZtYPHn']=!![];}const _0x2bf216=_0x2a3ca4[0x0],_0x1e43ac=_0x35b13d+_0x2bf216,_0x1a359b=_0x572c['ucubuj'][_0x1e43ac];return!_0x1a359b?(_0x572c06=_0x572c['LtzChj'](_0x572c06),_0x572c['ucubuj'][_0x1e43ac]=_0x572c06):_0x572c06=_0x1a359b,_0x572c06;}__name(probeSystemBrowser,_0x25fe25(0xba));function probeChrome(){const _0x4f7bfb={_0x5b1f0b:0xc9},_0xc325d3=_0x25fe25,_0x341462=firstExistingPath(CHROME_PATHS)??whichOf(CHROME_BIN_NAMES);if(_0x341462)return{'channel':_0xc325d3(_0x4f7bfb._0x5b1f0b),'path':_0x341462,'label':_0xc325d3(0xca)};return{'channel':null};}__name(probeChrome,_0x25fe25(0x95));function probeEdge(){const _0x2bfa1f={_0x39c597:0xdc},_0x54217a=_0x25fe25,_0x5e037f=firstExistingPath(EDGE_PATHS)??whichOf(EDGE_BIN_NAMES);if(_0x5e037f)return{'channel':_0x54217a(_0x2bfa1f._0x39c597),'path':_0x5e037f,'label':_0x54217a(0xe5)};return{'channel':null};}__name(probeEdge,'probeEdge');function probeChromeBeta(){const _0x7881ae=_0x25fe25,_0x2c2452=firstExistingPath(CHROME_BETA_PATHS);if(_0x2c2452)return{'channel':_0x7881ae(0x9b),'path':_0x2c2452,'label':_0x7881ae(0xb6)};return{'channel':null};}__name(probeChromeBeta,_0x25fe25(0x9f));var CHROME_PATHS=((()=>{const _0xea51eb={_0x1324f0:0xcb,_0x5ca95f:0x96,_0x28cbd4:0xf2,_0xfb4637:0xad},_0x50173c=_0x25fe25;switch(process[_0x50173c(0xd4)]){case'darwin':return['/Applications/Google\x20Chrome.app/Contents/MacOS/Google\x20Chrome'];case _0x50173c(_0xea51eb._0x1324f0):return[process[_0x50173c(_0xea51eb._0x5ca95f)][_0x50173c(0xe9)]+_0x50173c(_0xea51eb._0x28cbd4),process['env']['ProgramFiles(x86)']+_0x50173c(_0xea51eb._0x28cbd4),process['env'][_0x50173c(_0xea51eb._0xfb4637)]+_0x50173c(0xf2)];default:return[_0x50173c(0xa4),'/usr/bin/google-chrome-stable',_0x50173c(0xf7),'/usr/bin/chromium','/usr/bin/chromium-browser'];}})()),CHROME_BIN_NAMES=['google-chrome','google-chrome-stable','chromium',_0x25fe25(0xc1)],EDGE_PATHS=((()=>{const _0x1cb05c={_0x24199d:0xe0,_0x3aade2:0xcb},_0xa65302=_0x25fe25;switch(process[_0xa65302(0xd4)]){case _0xa65302(0xbf):return[_0xa65302(_0x1cb05c._0x24199d)];case _0xa65302(_0x1cb05c._0x3aade2):return[process[_0xa65302(0x96)]['ProgramFiles']+'\x5cMicrosoft\x5cEdge\x5cApplication\x5cmsedge.exe',process[_0xa65302(0x96)]['ProgramFiles(x86)']+_0xa65302(0xc6)];default:return['/usr/bin/microsoft-edge',_0xa65302(0xc5)];}})()),EDGE_BIN_NAMES=['microsoft-edge',_0x25fe25(0xbc)],CHROME_BETA_PATHS=((()=>{const _0xfa8750={_0x473c8a:0xe9,_0x54b7f2:0xcf},_0x2bf419=_0x25fe25;switch(process[_0x2bf419(0xd4)]){case _0x2bf419(0xbf):return[_0x2bf419(0xb3)];case'win32':return[process[_0x2bf419(0x96)][_0x2bf419(_0xfa8750._0x473c8a)]+_0x2bf419(_0xfa8750._0x54b7f2)];default:return[_0x2bf419(0xa8)];}})());function firstExistingPath(_0x48f46b){const _0xc48728=_0x25fe25;for(const _0x49a995 of _0x48f46b){if(!_0x49a995||_0x49a995[_0xc48728(0xa7)](_0xc48728(0xa1)))continue;if(existsSync(_0x49a995))return _0x49a995;}return null;}__name(firstExistingPath,_0x25fe25(0xe8));function whichOf(_0x4ed8e2){const _0x40e4c8={_0x209618:0xcb,_0x148d59:0xbb,_0x10515b:0x99,_0x4fc4a8:0xb2,_0x2441ce:0x9e},_0x482a1b=_0x25fe25;if(process[_0x482a1b(0xd4)]===_0x482a1b(_0x40e4c8._0x209618))return void 0x0;for(const _0xf5e2c4 of _0x4ed8e2){try{const _0x30ac48=execFileSync(_0x482a1b(_0x40e4c8._0x148d59),[_0xf5e2c4],{'encoding':_0x482a1b(_0x40e4c8._0x10515b)})[_0x482a1b(_0x40e4c8._0x4fc4a8)]();if(_0x30ac48[_0x482a1b(_0x40e4c8._0x2441ce)]>0x0&&existsSync(_0x30ac48))return _0x30ac48;}catch{}}return void 0x0;}__name(whichOf,_0x25fe25(0xab));function runEnvironmentChecks(_0x482d20={}){const _0x553b4a={_0x11360b:0xd7},_0x36b48d=_0x25fe25,_0x1adcea=_0x482d20[_0x36b48d(_0x553b4a._0x11360b)]??process[_0x36b48d(0xd7)]();return[checkNodeVersion(),checkSystemBrowser(),checkWritableCwd(_0x1adcea)];}__name(runEnvironmentChecks,_0x25fe25(0xb8));function checkNodeVersion(){const _0x56ebd8={_0x5429d8:0x94,_0x2fc0d5:0xb0,_0x34fdf3:0xae,_0x106d28:0x9d},_0x4ee876=_0x25fe25,_0x4d08fb=process[_0x4ee876(_0x56ebd8._0x5429d8)]['node'],_0x33392b=Number(_0x4d08fb[_0x4ee876(_0x56ebd8._0x2fc0d5)]('.')[0x0]);if(!Number[_0x4ee876(_0x56ebd8._0x34fdf3)](_0x33392b)||_0x33392b<0x14)return{'name':_0x4ee876(0xdd),'severity':'error','message':_0x4ee876(_0x56ebd8._0x106d28)+_0x4d08fb+')','detail':'Install\x20Node\x2020+\x20via\x20nvm\x20/\x20fnm\x20/\x20volta\x20and\x20re-run.'};return{'name':'Node.js\x20version','severity':'ok','message':_0x4d08fb};}__name(checkNodeVersion,_0x25fe25(0xce));function checkSystemBrowser(){const _0x4c466c={_0x3889f7:0xde,_0x28ed29:0xd2,_0x41a954:0xe3},_0x6c9872=_0x25fe25,_0x1f9c7b=probeSystemBrowser();if(_0x1f9c7b[_0x6c9872(_0x4c466c._0x3889f7)]!==null)return{'name':_0x6c9872(0xe7),'severity':'ok','message':_0x1f9c7b[_0x6c9872(0xe2)]+_0x6c9872(_0x4c466c._0x28ed29),'detail':_0x1f9c7b[_0x6c9872(0x9c)]};return{'name':'System\x20browser','severity':_0x6c9872(_0x4c466c._0x41a954),'message':'no\x20Chrome\x20/\x20Edge\x20/\x20Chromium\x20detected','detail':_0x6c9872(0xb1)};}__name(checkSystemBrowser,'checkSystemBrowser');function checkWritableCwd(_0x42e4f7){const _0x40c60b={_0x12dc48:0xc0,_0xb8a753:0xc4},_0x2edade=_0x25fe25;if(!_0x1a143b(_0x42e4f7))return{'name':'Target\x20directory','severity':_0x2edade(0xf0),'message':_0x2edade(0x93)+_0x42e4f7+'\x20does\x20not\x20exist','detail':_0x2edade(_0x40c60b._0x12dc48)};return{'name':_0x2edade(_0x40c60b._0xb8a753),'severity':'ok','message':_0x42e4f7};}function _0x2a3c(){const _0x4b0f6e=['D2HPy2G','BwLJCM9ZB2z0lwvKz2uTC3rHyMXL','mte1odK5ofv0AMzruq','y2HLy2TxCML0ywjSzun3za','zgfYD2LU','q3jLyxrLihrOzsbKAxjLy3rVCNKGB3iGCNvUigLUAxqGAw4Gyw4GzxHPC3rPBMCGChjVAMvJDcbYB290lG','y2HYB21PDw0TyNjVD3nLCG','C3vWCg9YDgvKs2LUzhm','ls1IywLS','vgfYz2v0igrPCMvJDg9YEq','l3vZCI9IAw4VBwLJCM9ZB2z0lwvKz2uTC3rHyMXL','xe1Py3jVC29MDfXfzgDLxefWCgXPy2f0Aw9Uxg1ZzwrNzs5LEgu','ls1ICMvHAW','yxv0Ag9Y','y2HYB21L','r29Vz2XLienOCM9Tzq','D2LUmZi','A2LUza','ChvZAa','y2HLy2ToB2rLvMvYC2LVBG','xeDVB2DSzvXdAhjVBwuGqMv0yvXbChbSAwnHDgLVBLXJAhjVBwuUzxHL','yxv0Ag9YAw5N','mZK1otu2meXjy1vXCG','igzVDw5K','mtzzEhHoEgy','CgXHDgzVCM0','mtjWquztAwS','AM9PBG','y3DK','ztjL','CgfYC2u','ls13B3jRzxjZpq','mta1mZC5nJDkz1PcB2u','BxnLzgDL','tM9Kzs5QCYb2zxjZAw9U','y2HHBM5LBa','ChjVAMvJDfjVB3q','l0fWCgXPy2f0Aw9UCY9nAwnYB3nVzNqGrwrNzs5HChaVq29UDgvUDhmVtwfJt1mVtwLJCM9ZB2z0ievKz2u','v2vIuNvUBMvYqwrHChrLCG','BgfIzwW','D2fYBMLUzW','D29YA2vYCW','twLJCM9ZB2z0ievKz2u','C3vMzML4','u3LZDgvTigjYB3DZzxi','zMLYC3rfEgLZDgLUz1bHDgG','uhjVz3jHBuzPBgvZ','vu5pvevtvf9iruferuq','CMvZB2X2zq','B2jQzwn0','C2nOzwr1BgvZ','qhvUB3rLC3qVD2vI','yxbWu2vYDMvYqxjNCW','zxjYB3i','zg9JDg9Y','xeDVB2DSzvXdAhjVBwvCqxbWBgLJyxrPB25Cy2HYB21LlMv4zq','C2nOzwr1BgvZqxjNCW','oda4mJK5mgz5C0Lvta','C3rYAw5N','DMfSDwvZ','l3nUyxaVyMLUl2DVB2DSzs1JAhjVBwu','mJiZmta3zhPUvezJ','mJeXmteXnMnjCfjXqG','DgfYz2v0ia','DMvYC2LVBNm','ChjVyMvdAhjVBwu','zw52','munZEvHJwq','CMvZB2X2zujPBG','DxrMoa','zgvIDwC','y2HYB21LlwjLDge','Cgf0Aa','CMvXDwLYzxmGtM9KzsdIIAuYmcaOCNvUBMLUzYa','BgvUz3rO','ChjVyMvdAhjVBwvczxrH','yMLU','Dw5KzwzPBMvK','ls1QC29U','y29SBgvJDgLVBG','l3vZCI9IAw4Vz29Vz2XLlwnOCM9Tzq','zgvMAw5LuhjVCgvYDhK','yNvPBgrbCMDZ','C3rHCNrZv2L0Aa','l3vZCI9IAw4Vz29Vz2XLlwnOCM9Tzs1IzxrH','Dw5VDgvZDc13zwi','l3bHy2THz2uUANnVBG','D2HPy2HpzG','ihbHy2THz2uUANnVBIbKzwnSyxjLCYbUBYaNyMLUjYbMAwvSzcdIGjqGyNjVA2vUigLUC3rHBgW/','te9dquXbufbeqvrb','AxngAw5PDgu','yNvPBgrfBNy','C3bSAxq','Aw5PDcb3AwXSig9MzMvYihrVigrVD25SB2fKigj1BMrSzwqGq2HYB21PDw0Gkh4XntaGtuiPlIbbBhrLCM5HDgL2zwX5lcbPBNn0ywXSienOCM9TzsbMCM9TigH0DhbZoI8VD3D3lMDVB2DSzs5JB20Vy2HYB21LigfUzcbYzs1YDw4U','DhjPBq','l0fWCgXPy2f0Aw9UCY9hB29NBguGq2HYB21LiejLDgeUyxbWl0nVBNrLBNrZl01Hy09tl0DVB2DSzsbdAhjVBwuGqMv0yq','mZqXnxfnuLfcCa','BMfTzq','r29Vz2XLienOCM9TzsbczxrH','ndi2C0nIthD1','CNvUrw52AxjVBM1LBNrdAgvJA3m','C2nLBMfYAw8','ChjVyMvtExn0zw1cCM93C2vY'];_0x2a3c=function(){return _0x4b0f6e;};return _0x2a3c();}__name(checkWritableCwd,_0x25fe25(0xbe));var PACKAGE_NAME=_0x25fe25(0xee),WebRunnerAdapter=class{static{__name(this,_0x25fe25(0xe1));}[_0x25fe25(0xb5)]=PACKAGE_NAME;[_0x25fe25(0xe6)]='';[_0x25fe25(0x9a)]={'picker':!![],'attach':!![],'resumeFromFailure':![]};[_0x25fe25(0xc2)]=[_0x25fe25(0xb9),'collection','authoring'];[_0x25fe25(0x98)](){const _0x2ca9af={_0x5dce20:0xac},_0x3e8087=_0x25fe25,_0x4acc94=createRequire(import.meta.url),_0x395ebc=_0x4acc94[_0x3e8087(0xeb)](PACKAGE_NAME+_0x3e8087(0xaa)),_0x51bf80=JSON[_0x3e8087(0xd9)](readFileSync(_0x395ebc,_0x3e8087(0x99))),_0x2403e4=pickBin(_0x51bf80);if(!_0x2403e4)throw new Error(PACKAGE_NAME+_0x3e8087(_0x2ca9af._0x5dce20));return join(dirname(_0x395ebc),_0x2403e4);}[_0x25fe25(0xa6)](_0x29d9ce){const _0x5f3868={_0xc8998a:0xb9,_0x39d945:0xd8,_0x36dead:0x9a,_0x1ca748:0xcd,_0x70c7e7:0xc7,_0x1b2c1c:0xd6,_0x42fe94:0xcc,_0x2aea3b:0xa3,_0x306a9c:0xe4,_0x282a39:0xc3,_0x513fda:0xd0,_0x4f671a:0xc8,_0x583234:0xcc},_0x4bfb2f=_0x25fe25;if(_0x29d9ce[_0x4bfb2f(0xcc)]===_0x4bfb2f(_0x5f3868._0xc8998a)){const _0x12b656=[_0x4bfb2f(_0x5f3868._0x39d945),_0x29d9ce[_0x4bfb2f(0xb9)]];if(_0x29d9ce[_0x4bfb2f(_0x5f3868._0x36dead)])_0x12b656[_0x4bfb2f(0xcd)]('--debug');return _0x29d9ce['breakpoints']&&_0x29d9ce['breakpoints'][_0x4bfb2f(0x9e)]>0x0&&_0x12b656[_0x4bfb2f(_0x5f3868._0x1ca748)](_0x4bfb2f(_0x5f3868._0x70c7e7),_0x29d9ce['breakpoints'][_0x4bfb2f(_0x5f3868._0x1b2c1c)](',')),_0x12b656;}if(_0x29d9ce[_0x4bfb2f(_0x5f3868._0x42fe94)]==='collection'){const _0x3766d6=['collection',_0x29d9ce[_0x4bfb2f(_0x5f3868._0x2aea3b)]];_0x29d9ce['workers']!==void 0x0&&_0x29d9ce[_0x4bfb2f(_0x5f3868._0x306a9c)]>0x1&&_0x3766d6['push'](_0x4bfb2f(0xda)+_0x29d9ce['workers']);if(_0x29d9ce['bail'])_0x3766d6[_0x4bfb2f(0xcd)](_0x4bfb2f(_0x5f3868._0x282a39));return _0x3766d6;}if(_0x29d9ce[_0x4bfb2f(0xcc)]===_0x4bfb2f(_0x5f3868._0x513fda))return[_0x4bfb2f(_0x5f3868._0x4f671a),_0x29d9ce[_0x4bfb2f(0xb9)]];const _0x42b162=_0x29d9ce;throw new UnsupportedRunKindError(_0x42b162[_0x4bfb2f(_0x5f3868._0x583234)],this['name']);}[_0x25fe25(0xaf)](_0x5658cc){const _0x8f8202=_0x25fe25,_0x27789d={};if(_0x5658cc['headed'])_0x27789d[_0x8f8202(0xea)]='1';return _0x27789d;}[_0x25fe25(0xef)](){return['app-server'];}[_0x25fe25(0xf3)](){const _0x403619={_0x257e7d:0xed},_0x13bae6=_0x25fe25;return[_0x13bae6(_0x403619._0x257e7d),_0x13bae6(0xa2)];}async[_0x25fe25(0xf1)](_0x58549c){const _0x4562cf={_0x1ad4e4:0xdf},_0x455340=_0x25fe25;return runEnvironmentChecks({'cwd':_0x58549c[_0x455340(_0x4562cf._0x1ad4e4)]});}},webRunnerAdapter=new WebRunnerAdapter(),web_runner_adapter_default=webRunnerAdapter;function pickBin(_0x1e6698){const _0x2f2546={_0x5ceb13:0xf5,_0x5bd0ce:0xa0,_0x2c121f:0xf6},_0x2ceec6=_0x25fe25;if(typeof _0x1e6698['bin']===_0x2ceec6(_0x2f2546._0x5ceb13))return _0x1e6698['bin'];if(_0x1e6698[_0x2ceec6(0xa0)]&&typeof _0x1e6698[_0x2ceec6(_0x2f2546._0x5bd0ce)]===_0x2ceec6(0xec))return _0x1e6698[_0x2ceec6(0xa0)][_0x2ceec6(0xa9)]??Object[_0x2ceec6(_0x2f2546._0x2c121f)](_0x1e6698['bin'])[0x0]??null;return null;}__name(pickBin,'pickBin');export{web_runner_adapter_default as default,webRunnerAdapter};
1
+ const _0x8fe9bb=_0x515c;(function(_0x4c4c9b,_0x1968ca){const _0x370a39={_0x1ed841:0x1b8,_0x17e18a:0x18d,_0x450f50:0x18c,_0x20410c:0x189,_0x72bf94:0x1c2},_0x5b35df=_0x515c,_0x422a24=_0x4c4c9b();while(!![]){try{const _0x1f14f7=parseInt(_0x5b35df(0x1b2))/0x1*(parseInt(_0x5b35df(_0x370a39._0x1ed841))/0x2)+parseInt(_0x5b35df(0x1b3))/0x3*(-parseInt(_0x5b35df(0x19c))/0x4)+-parseInt(_0x5b35df(0x162))/0x5*(parseInt(_0x5b35df(0x190))/0x6)+-parseInt(_0x5b35df(_0x370a39._0x17e18a))/0x7+-parseInt(_0x5b35df(0x174))/0x8*(-parseInt(_0x5b35df(_0x370a39._0x450f50))/0x9)+-parseInt(_0x5b35df(_0x370a39._0x20410c))/0xa+-parseInt(_0x5b35df(0x1ae))/0xb*(-parseInt(_0x5b35df(_0x370a39._0x72bf94))/0xc);if(_0x1f14f7===_0x1968ca)break;else _0x422a24['push'](_0x422a24['shift']());}catch(_0x468fe7){_0x422a24['push'](_0x422a24['shift']());}}}(_0xed3b,0x9badf));var __defProp=Object[_0x8fe9bb(0x1c0)],__name=(_0x431c63,_0x19bc98)=>__defProp(_0x431c63,_0x8fe9bb(0x1b4),{'value':_0x19bc98,'configurable':!![]});import{UnsupportedRunKindError}from'@unotest/protocol';import{readFileSync}from'fs';function _0x515c(_0x14df0f,_0x2de924){_0x14df0f=_0x14df0f-0x15b;const _0xed3b6d=_0xed3b();let _0x515cbe=_0xed3b6d[_0x14df0f];if(_0x515c['zzertE']===undefined){var _0x381bbf=function(_0x690e31){const _0x5306d7='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x136f58='',_0x431c63='';for(let _0x19bc98=0x0,_0x3dbb9b,_0x929070,_0x50a6ab=0x0;_0x929070=_0x690e31['charAt'](_0x50a6ab++);~_0x929070&&(_0x3dbb9b=_0x19bc98%0x4?_0x3dbb9b*0x40+_0x929070:_0x929070,_0x19bc98++%0x4)?_0x136f58+=String['fromCharCode'](0xff&_0x3dbb9b>>(-0x2*_0x19bc98&0x6)):0x0){_0x929070=_0x5306d7['indexOf'](_0x929070);}for(let _0x5eccdd=0x0,_0x110d6c=_0x136f58['length'];_0x5eccdd<_0x110d6c;_0x5eccdd++){_0x431c63+='%'+('00'+_0x136f58['charCodeAt'](_0x5eccdd)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x431c63);};_0x515c['QmvnjN']=_0x381bbf,_0x515c['XDgJvL']={},_0x515c['zzertE']=!![];}const _0x25c2ae=_0xed3b6d[0x0],_0x55aebc=_0x14df0f+_0x25c2ae,_0x5f590c=_0x515c['XDgJvL'][_0x55aebc];return!_0x5f590c?(_0x515cbe=_0x515c['QmvnjN'](_0x515cbe),_0x515c['XDgJvL'][_0x55aebc]=_0x515cbe):_0x515cbe=_0x5f590c,_0x515cbe;}import{createRequire}from'module';import{dirname,join}from'path';import{existsSync as _0x136f58}from'fs';import{execFileSync}from'child_process';import{existsSync}from'fs';function probeSystemBrowser(){const _0x3f7039={_0xb12709:0x17c},_0x26800c=_0x8fe9bb;for(const _0x3dbb9b of[probeChrome,probeEdge,probeChromeBeta]){const _0x929070=_0x3dbb9b();if(_0x929070[_0x26800c(_0x3f7039._0xb12709)]!==null)return _0x929070;}return{'channel':null};}__name(probeSystemBrowser,_0x8fe9bb(0x1b6));function probeChrome(){const _0x5dfb62={_0xf6c944:0x164},_0xb10358=_0x8fe9bb,_0x50a6ab=firstExistingPath(CHROME_PATHS)??whichOf(CHROME_BIN_NAMES);if(_0x50a6ab)return{'channel':_0xb10358(_0x5dfb62._0xf6c944),'path':_0x50a6ab,'label':'Google\x20Chrome'};return{'channel':null};}__name(probeChrome,_0x8fe9bb(0x183));function probeEdge(){const _0x49eaf2={_0x325253:0x175},_0x2c5d16=_0x8fe9bb,_0x5eccdd=firstExistingPath(EDGE_PATHS)??whichOf(EDGE_BIN_NAMES);if(_0x5eccdd)return{'channel':_0x2c5d16(_0x49eaf2._0x325253),'path':_0x5eccdd,'label':_0x2c5d16(0x15e)};return{'channel':null};}__name(probeEdge,_0x8fe9bb(0x177));function probeChromeBeta(){const _0x110d6c=firstExistingPath(CHROME_BETA_PATHS);if(_0x110d6c)return{'channel':'chrome-beta','path':_0x110d6c,'label':'Google\x20Chrome\x20Beta'};return{'channel':null};}__name(probeChromeBeta,'probeChromeBeta');var CHROME_PATHS=((()=>{const _0x4d915c={_0x456165:0x176,_0x3ac9c8:0x18b,_0x2be53c:0x195,_0xb2279:0x1ab,_0x45b0a3:0x171,_0x3a9ee6:0x1ac,_0x29094e:0x197,_0x25ec39:0x17d},_0x431418=_0x8fe9bb;switch(process['platform']){case _0x431418(_0x4d915c._0x456165):return['/Applications/Google\x20Chrome.app/Contents/MacOS/Google\x20Chrome'];case _0x431418(_0x4d915c._0x3ac9c8):return[process[_0x431418(0x1ab)]['ProgramFiles']+_0x431418(0x1ac),process[_0x431418(0x1ab)][_0x431418(_0x4d915c._0x2be53c)]+_0x431418(0x1ac),process[_0x431418(_0x4d915c._0xb2279)][_0x431418(_0x4d915c._0x45b0a3)]+_0x431418(_0x4d915c._0x3a9ee6)];default:return[_0x431418(0x1a4),_0x431418(0x1b9),_0x431418(_0x4d915c._0x29094e),_0x431418(_0x4d915c._0x25ec39),_0x431418(0x18f)];}})()),CHROME_BIN_NAMES=[_0x8fe9bb(0x16b),_0x8fe9bb(0x168),_0x8fe9bb(0x19d),_0x8fe9bb(0x1bb)],EDGE_PATHS=((()=>{const _0x53dcf3={_0x22adf3:0x176,_0x27a161:0x18b,_0x10eb5b:0x1ab,_0x1620d9:0x166,_0x1ad4e1:0x1a3},_0x43f56b=_0x8fe9bb;switch(process['platform']){case _0x43f56b(_0x53dcf3._0x22adf3):return[_0x43f56b(0x1ba)];case _0x43f56b(_0x53dcf3._0x27a161):return[process[_0x43f56b(_0x53dcf3._0x10eb5b)][_0x43f56b(_0x53dcf3._0x1620d9)]+_0x43f56b(0x15f),process[_0x43f56b(0x1ab)]['ProgramFiles(x86)']+'\x5cMicrosoft\x5cEdge\x5cApplication\x5cmsedge.exe'];default:return[_0x43f56b(_0x53dcf3._0x1ad4e1),'/usr/bin/microsoft-edge-stable'];}})()),EDGE_BIN_NAMES=[_0x8fe9bb(0x1b0),_0x8fe9bb(0x1aa)],CHROME_BETA_PATHS=((()=>{const _0x4f8734={_0x4f350a:0x1b5,_0xe26f2d:0x18b},_0x54f3d7=_0x8fe9bb;switch(process[_0x54f3d7(0x15b)]){case'darwin':return[_0x54f3d7(_0x4f8734._0x4f350a)];case _0x54f3d7(_0x4f8734._0xe26f2d):return[process['env'][_0x54f3d7(0x166)]+'\x5cGoogle\x5cChrome\x20Beta\x5cApplication\x5cchrome.exe'];default:return[_0x54f3d7(0x1bc)];}})());function _0xed3b(){const _0x3d1c05=['l3vZCI9IAw4Vz29Vz2XLlwnOCM9Tzs1IzxrH','y3DK','Cgf0Aa','ls1IywLS','zgvMAw5LuhjVCgvYDhK','DxrMoa','mteXnKHqwNDRCG','zMLYC3rfEgLZDgLUz1bHDgG','ls1QC29U','igzVDw5K','CgXHDgzVCM0','CMvXDwLYzxmGtM9KzsdIIAuYmcaOCNvUBMLUzYa','y2HLy2TxCML0ywjSzun3za','twLJCM9ZB2z0ievKz2u','xe1Py3jVC29MDfXfzgDLxefWCgXPy2f0Aw9Uxg1ZzwrNzs5LEgu','BM9Kzq','yMfPBa','mtyZmdq2nvPAqxHhvG','AM9PBG','y2HYB21L','v2vIuNvUBMvYqwrHChrLCG','uhjVz3jHBuzPBgvZ','ls1ICMvHAW','z29Vz2XLlwnOCM9Tzs1ZDgfIBgu','yNvPBgrfBNy','ls13B3jRzxjZpq','z29Vz2XLlwnOCM9Tzq','vgfYz2v0igrPCMvJDg9YEq','CMvZB2X2zq','zxjYB3i','C3vWCg9YDgvKs2LUzhm','AgvHzgvK','te9dquXbufbeqvrb','Dw5VDgvZDc13zwi','vu5pvevtvf9iruferuq','nZqYodHoqNHZr2u','BxnLzgDL','zgfYD2LU','ChjVyMvfzgDL','DhjPBq','C2nLBMfYAw8','u3LZDgvTigjYB3DZzxi','yxbWu2vYDMvYqxjNCW','y2HHBM5LBa','l3vZCI9IAw4Vy2HYB21PDw0','yNjLywTWB2LUDhm','l3bHy2THz2uUANnVBG','tM9Kzs5QCYb2zxjZAw9U','y2HLy2TtExn0zw1cCM93C2vY','BgvUz3rO','ChjVyMvdAhjVBwu','C3bSAxq','Aw5PDcb3AwXSig9MzMvYihrVigrVD25SB2fKigj1BMrSzwqGq2HYB21PDw0Gkh4XntaGtuiPlIbbBhrLCM5HDgL2zwX5lcbPBNn0ywXSienOCM9TzsbMCM9TigH0DhbZoI8VD3D3lMDVB2DSzs5JB20Vy2HYB21LigfUzcbYzs1YDw4U','C3rHCNrZv2L0Aa','sw5ZDgfSBcboB2rLidiWkYb2AweGBNzTic8GzM5Tic8GDM9SDgeGyw5KihjLlxj1BI4','BgfIzwW','ndq2ndm3mfzPrwDStW','DgfYz2v0ia','D2LUmZi','nJntAMHfz3a','mJmYodi4nfjwAuPiwG','yMLU','l3vZCI9IAw4Vy2HYB21PDw0TyNjVD3nLCG','mtjbvgDxy1O','igrVzxmGBM90igv4Axn0','A2LUza','C3rYAw5N','ihbHy2THz2uUANnVBIbKzwnSyxjLCYbUBYaNyMLUjYbMAwvSzcdIGjqGyNjVA2vUigLUC3rHBgW/','uhjVz3jHBuzPBgvZkhG4nIK','yxbWlxnLCNzLCG','l3nUyxaVyMLUl2DVB2DSzs1JAhjVBwu','D29YA2vYCW','B2jQzwn0','CgfYC2u','y29SBgvJDgLVBG','mtzLv2DyBNm','y2HYB21PDw0','D2HPy2G','D2fYBMLUzW','D2HPy2HpzG','zgvIDwC','ChvZAa','l3vZCI9IAw4VBwLJCM9ZB2z0lwvKz2u','l3vZCI9IAw4Vz29Vz2XLlwnOCM9Tzq','ls1Kzwj1zW','q3jLyxrLihrOzsbKAxjLy3rVCNKGB3iGCNvUigLUAxqGAw4Gyw4GzxHPC3rPBMCGChjVAMvJDcbYB290lG','CMvZB2X2zujPBG','yxv0Ag9Y','CNvUrw52AxjVBM1LBNrdAgvJA3m','BwLJCM9ZB2z0lwvKz2uTC3rHyMXL','zw52','xeDVB2DSzvXdAhjVBwvCqxbWBgLJyxrPB25Cy2HYB21LlMv4zq','y2HLy2ToB2rLvMvYC2LVBG','mZuYmdG4rgjWsMzZ','ztjL','BwLJCM9ZB2z0lwvKz2u','qhvUB3rLC3qVD2vI','mJK0mZG4svnzvMDV','otuWndi3sKTpCgPp','BMfTzq','l0fWCgXPy2f0Aw9UCY9hB29NBguGq2HYB21LiejLDgeUyxbWl0nVBNrLBNrZl01Hy09tl0DVB2DSzsbdAhjVBwuGqMv0yq','ChjVyMvtExn0zw1cCM93C2vY','yNvPBgrbCMDZ','mLriEeTzzG','l3vZCI9IAw4Vz29Vz2XLlwnOCM9Tzs1ZDgfIBgu','l0fWCgXPy2f0Aw9UCY9nAwnYB3nVzNqGrwrNzs5HChaVq29UDgvUDhmVtwfJt1mVtwLJCM9ZB2z0ievKz2u','y2HYB21PDw0TyNjVD3nLCG'];_0xed3b=function(){return _0x3d1c05;};return _0xed3b();}function firstExistingPath(_0x412b6f){const _0x4a671f=_0x8fe9bb;for(const _0x3b711c of _0x412b6f){if(!_0x3b711c||_0x3b711c[_0x4a671f(0x186)]('undefined'))continue;if(existsSync(_0x3b711c))return _0x3b711c;}return null;}__name(firstExistingPath,_0x8fe9bb(0x1c3));function whichOf(_0x47fada){const _0x2dc17c={_0x1d1750:0x19e,_0x128192:0x1c1,_0x291819:0x182},_0x225e56=_0x8fe9bb;if(process['platform']==='win32')return void 0x0;for(const _0x1cb82c of _0x47fada){try{const _0xacf910=execFileSync(_0x225e56(_0x2dc17c._0x1d1750),[_0x1cb82c],{'encoding':_0x225e56(_0x2dc17c._0x128192)})[_0x225e56(0x178)]();if(_0xacf910[_0x225e56(_0x2dc17c._0x291819)]>0x0&&existsSync(_0xacf910))return _0xacf910;}catch{}}return void 0x0;}__name(whichOf,_0x8fe9bb(0x1a0));function runEnvironmentChecks(_0x2665b4={}){const _0x8d1511={_0x552113:0x1bd},_0xed080d=_0x8fe9bb,_0x5f16f6=_0x2665b4[_0xed080d(_0x8d1511._0x552113)]??process[_0xed080d(_0x8d1511._0x552113)]();return[checkNodeVersion(),checkSystemBrowser(),checkWritableCwd(_0x5f16f6)];}__name(runEnvironmentChecks,_0x8fe9bb(0x1a9));function checkNodeVersion(){const _0x54e5e1={_0x1e2b47:0x184,_0x295030:0x16e,_0xd8c92f:0x187},_0x333f95=_0x8fe9bb,_0x5cb5ff=process['versions'][_0x333f95(0x160)],_0x394c7f=Number(_0x5cb5ff[_0x333f95(_0x54e5e1._0x1e2b47)]('.')[0x0]);if(!Number['isFinite'](_0x394c7f)||_0x394c7f<0x14)return{'name':'Node.js\x20version','severity':_0x333f95(_0x54e5e1._0x295030),'message':_0x333f95(0x15c)+_0x5cb5ff+')','detail':_0x333f95(_0x54e5e1._0xd8c92f)};return{'name':_0x333f95(0x180),'severity':'ok','message':_0x5cb5ff};}__name(checkNodeVersion,_0x8fe9bb(0x1ad));function checkSystemBrowser(){const _0x33e335={_0x429b30:0x17c,_0x32c4a2:0x17a,_0x1fd13d:0x1c5,_0x5e409d:0x17a,_0x25164b:0x19f,_0x309bdb:0x185},_0x1d6ba1=_0x8fe9bb,_0x214a31=probeSystemBrowser();if(_0x214a31[_0x1d6ba1(_0x33e335._0x429b30)]!==null)return{'name':_0x1d6ba1(_0x33e335._0x32c4a2),'severity':'ok','message':_0x214a31[_0x1d6ba1(0x188)]+_0x1d6ba1(_0x33e335._0x1fd13d),'detail':_0x214a31[_0x1d6ba1(0x1be)]};return{'name':_0x1d6ba1(_0x33e335._0x5e409d),'severity':_0x1d6ba1(_0x33e335._0x25164b),'message':'no\x20Chrome\x20/\x20Edge\x20/\x20Chromium\x20detected','detail':_0x1d6ba1(_0x33e335._0x309bdb)};}__name(checkSystemBrowser,_0x8fe9bb(0x181));function checkWritableCwd(_0x413879){const _0x20438e={_0x1cf799:0x18a,_0x259fc3:0x16c},_0x38457d=_0x8fe9bb;if(!_0x136f58(_0x413879))return{'name':_0x38457d(0x16c),'severity':'error','message':_0x38457d(_0x20438e._0x1cf799)+_0x413879+_0x38457d(0x191),'detail':_0x38457d(0x1a6)};return{'name':_0x38457d(_0x20438e._0x259fc3),'severity':'ok','message':_0x413879};}__name(checkWritableCwd,_0x8fe9bb(0x15d));var PACKAGE_NAME=_0x8fe9bb(0x1b1),WebRunnerAdapter=class{static{__name(this,_0x8fe9bb(0x165));}[_0x8fe9bb(0x1b4)]=PACKAGE_NAME;['suffix']='';[_0x8fe9bb(0x1a1)]={'picker':!![],'attach':!![],'resumeFromFailure':![]};[_0x8fe9bb(0x16f)]=[_0x8fe9bb(0x179),_0x8fe9bb(0x19b),'authoring'];[_0x8fe9bb(0x1a7)](){const _0x48026c={_0x307cdc:0x16d,_0xe62af4:0x194},_0x4d9f27=_0x8fe9bb,_0xa7e903=createRequire(import.meta.url),_0x2f4e4a=_0xa7e903[_0x4d9f27(_0x48026c._0x307cdc)](PACKAGE_NAME+_0x4d9f27(0x17f)),_0x2a47e6=JSON[_0x4d9f27(0x19a)](readFileSync(_0x2f4e4a,_0x4d9f27(0x1c1))),_0x16c901=pickBin(_0x2a47e6);if(!_0x16c901)throw new Error(PACKAGE_NAME+_0x4d9f27(_0x48026c._0xe62af4));return join(dirname(_0x2f4e4a),_0x16c901);}[_0x8fe9bb(0x1b7)](_0x2c5b2e){const _0x595ec4={_0x5063d1:0x192,_0xc340a5:0x179,_0x76c7f7:0x17e,_0xb0a0a7:0x182,_0x16a921:0x1a2,_0x2e3ccf:0x19b,_0x605c04:0x198,_0x5239b4:0x16a,_0x1cb08a:0x161,_0x298fc7:0x1a2,_0x205492:0x1bf,_0x327a05:0x1a8,_0x4bb9c7:0x1b4},_0x57af38=_0x8fe9bb;if(_0x2c5b2e[_0x57af38(_0x595ec4._0x5063d1)]===_0x57af38(_0x595ec4._0xc340a5)){const _0x508cbb=[_0x57af38(0x1af),_0x2c5b2e['scenario']];if(_0x2c5b2e['debug'])_0x508cbb['push'](_0x57af38(0x1a5));return _0x2c5b2e['breakpoints']&&_0x2c5b2e[_0x57af38(_0x595ec4._0x76c7f7)][_0x57af38(_0x595ec4._0xb0a0a7)]>0x0&&_0x508cbb[_0x57af38(_0x595ec4._0x16a921)](_0x57af38(0x167),_0x2c5b2e[_0x57af38(0x17e)][_0x57af38(0x163)](',')),_0x508cbb;}if(_0x2c5b2e[_0x57af38(0x192)]===_0x57af38(_0x595ec4._0x2e3ccf)){const _0x8f709f=[_0x57af38(0x19b),_0x2c5b2e[_0x57af38(0x19b)]];_0x2c5b2e[_0x57af38(0x198)]!==void 0x0&&_0x2c5b2e[_0x57af38(_0x595ec4._0x605c04)]>0x1&&_0x8f709f[_0x57af38(0x1a2)](_0x57af38(_0x595ec4._0x5239b4)+_0x2c5b2e[_0x57af38(_0x595ec4._0x605c04)]);if(_0x2c5b2e[_0x57af38(_0x595ec4._0x1cb08a)])_0x8f709f[_0x57af38(_0x595ec4._0x298fc7)](_0x57af38(_0x595ec4._0x205492));return _0x8f709f;}if(_0x2c5b2e[_0x57af38(_0x595ec4._0x5063d1)]==='authoring')return[_0x57af38(_0x595ec4._0x327a05),_0x2c5b2e['scenario']];const _0x43d860=_0x2c5b2e;throw new UnsupportedRunKindError(_0x43d860['kind'],this[_0x57af38(_0x595ec4._0x4bb9c7)]);}[_0x8fe9bb(0x169)](_0x32b388){const _0xbdd4e9=_0x8fe9bb,_0x3989c7={};if(_0x32b388[_0xbdd4e9(0x170)])_0x3989c7[_0xbdd4e9(0x173)]='1';return _0x3989c7;}[_0x8fe9bb(0x17b)](){const _0x185c6c={_0x5d722f:0x196},_0x5fc1e=_0x8fe9bb;return[_0x5fc1e(_0x185c6c._0x5d722f)];}['schedulesArgs'](){const _0x45cc0f={_0x12c2d2:0x1c4},_0x5e24cc=_0x8fe9bb;return['schedules',_0x5e24cc(_0x45cc0f._0x12c2d2)];}async['doctor'](_0x241d06){return runEnvironmentChecks({'cwd':_0x241d06['projectRoot']});}},webRunnerAdapter=new WebRunnerAdapter(),web_runner_adapter_default=webRunnerAdapter;function pickBin(_0xacd148){const _0x1addc7={_0x5d51e3:0x193,_0x5609d3:0x18e,_0x578600:0x199,_0x4a8438:0x172},_0x5e3dcf=_0x8fe9bb;if(typeof _0xacd148[_0x5e3dcf(0x18e)]===_0x5e3dcf(_0x1addc7._0x5d51e3))return _0xacd148[_0x5e3dcf(_0x1addc7._0x5609d3)];if(_0xacd148[_0x5e3dcf(_0x1addc7._0x5609d3)]&&typeof _0xacd148[_0x5e3dcf(0x18e)]===_0x5e3dcf(_0x1addc7._0x578600))return _0xacd148[_0x5e3dcf(0x18e)][_0x5e3dcf(_0x1addc7._0x4a8438)]??Object['values'](_0xacd148[_0x5e3dcf(0x18e)])[0x0]??null;return null;}__name(pickBin,'pickBin');export{web_runner_adapter_default as default,webRunnerAdapter};
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  status: stable
3
- last_updated: 2026-05-14
3
+ last_updated: 2026-09-03
4
4
  ---
5
5
 
6
6
  # Agent integration
@@ -70,7 +70,7 @@ manual setup).
70
70
  `new_context`, `close_context`, `goto`, `reload`, `get_url`, `get_title`,
71
71
  `click`, `double_click`, `fill`, `press`, `check`, `uncheck`,
72
72
  `select_option`, `hover`, `scroll_into_view`, `wait_for`, `wait_for_url`,
73
- `wait_for_text`, `get_page_snapshot`, `get_frame_snapshot`,
73
+ `wait_for_text`, `screenshot`, `get_page_snapshot`, `get_frame_snapshot`,
74
74
  `get_aria_snapshot`, `find_element`.
75
75
 
76
76
  `get_page_snapshot` / `get_frame_snapshot` return a compact outline of
@@ -309,6 +309,47 @@ effective `baseUrl`. A missing variable error also lists the searched
309
309
  layers, and every CLI run prints a one-line header with the layers and
310
310
  the effective baseUrl.
311
311
 
312
+ ## Watching a collection run
313
+
314
+ An agent that starts `npx @unotest/web collection <name>` in the
315
+ background gets the CLI's per-scenario lines only when the process
316
+ ends — a piped stdout is block-buffered. The run's own journal is the
317
+ progress source, and it is written line by line as the run goes:
318
+
319
+ ```
320
+ unotest/.runs/<yyyy>/<mm>/<dd>/col-<name>-<id>/steps.jsonl
321
+ ```
322
+
323
+ `.runs` becomes `.runs.<env>` for a `--env <name>` run; the date shard
324
+ is UTC. `col-<name>-` is the collection run's id prefix and the `<id>`
325
+ tail is a timestamp plus random hex, so take the newest directory with
326
+ that prefix once the run has started.
327
+
328
+ The file holds one JSON object per line, four kinds:
329
+
330
+ | `kind` | Fields | When |
331
+ | --- | --- | --- |
332
+ | `collection-run:started` | `runId`, `collection`, `scenarios[]` (in order) | before the first scenario |
333
+ | `collection-run:scenario-started` | `scenario`, `scenarioRunId` | each scenario takes a worker |
334
+ | `collection-run:scenario-finished` | `scenario`, `scenarioRunId`, `outcome` | `completed` / `failed` / `aborted` / `interrupted` |
335
+ | `collection-run:finished` | `outcome` | the run is over — nothing follows |
336
+
337
+ Every line also carries `t` (epoch ms). `scenarioRunId` names the
338
+ scenario's own run directory under the same `.runs` root, where its
339
+ `steps.jsonl` and failure bundle live. A line that does not parse is the
340
+ one being written — retry on the next read, never treat it as the end.
341
+
342
+ ```sh
343
+ tail -f unotest/.runs/2026/09/03/col-smoke-*/steps.jsonl \
344
+ | jq -c 'select(.kind | startswith("collection-run:scenario"))
345
+ | {kind, scenario, outcome}'
346
+ ```
347
+
348
+ This shape is a published contract: the event types
349
+ (`CollectionRunArtifact`) and the file name (`STEPS_FILE`) are exported
350
+ from `@unotest/protocol` under semver, and the box daemon reads the same
351
+ events for its metrics.
352
+
312
353
  ## Debug logging
313
354
 
314
355
  Set `UNOTEST_DEBUG=1` in `unotest/.env` and restart the MCP server to
@@ -37,6 +37,68 @@ function test_my_scenario() {
37
37
  > one block per logical chunk; anything is allowed inside a block (nested
38
38
  > blocks, control flow, comments).
39
39
 
40
+ ### `step(...)` forms — tags and soft steps
41
+
42
+ ```
43
+ step("label", () => { … });
44
+ step("label", {tag: <expr>}, () => { … });
45
+ step.soft("label", () => { … });
46
+ step.soft("label", {tag: <expr>}, () => { … });
47
+ ```
48
+
49
+ - **`label`** is a string literal — the intent a human reads.
50
+ - **`{tag: <expr>}`** names the case a data-driven step is on: any
51
+ expression (`q.id`, `textJoin(['q-', i])`), evaluated when the block
52
+ starts. It rides on every event of the block (`Question [q17]` in the
53
+ CLI line, a chip on the step in the viewer). `tag` is the only option.
54
+ - **`step.soft(...)`** — a failure inside the body is *recorded* instead
55
+ of stopping the run: the rest of that body is skipped (as after
56
+ `expect.soft` inside a Playwright `test.step`), execution continues
57
+ with the statement after the block, and the test still ends **failed**
58
+ with every soft failure listed:
59
+
60
+ ```
61
+ ✗ test: test_control_questions (12.4s)
62
+ 3 soft step(s) failed: Question [q17]: …; Question [q42]: …; Question [q58]: …
63
+ ✗ soft step "Question" [q17]: judge said no: …
64
+ ✗ soft step "Question" [q42]: …
65
+ ```
66
+
67
+ `return` / `break` / `continue` pass through a soft step untouched. A
68
+ hard failure after soft ones ends the run with *that* error; the soft
69
+ list is still attached. The failure bundle shows the page at the moment
70
+ of the **first** soft failure (`failure.json` carries `soft: true` and
71
+ `stepTag`); later ones are in the journal (`step-block:finished`) and in
72
+ `run_test`'s reply (`next.softFailures`).
73
+ - `step.soft` is allowed **inside `test_*` only** (validator
74
+ `step-shape`): a helper has no test to report a soft failure on.
75
+ Nesting is free — the usual shape is a plain outer step, a loop, and
76
+ tagged soft steps inside it. A soft failure does **not** change the
77
+ outer step's own outcome: the group is not an assertion.
78
+ - In the debugger, resuming past a failure inside a soft step continues
79
+ with the next statement and records nothing — same as resuming past
80
+ any failure on web.
81
+
82
+ The data-driven gate, in full (`readJsonLine` reads the cases; the outer
83
+ `step` satisfies step coverage):
84
+
85
+ ```js
86
+ function test_control_questions() {
87
+ step("Control questions", () => {
88
+ for (i = 1; i < 11; i = i + 1) {
89
+ q = readJsonLine('questions.jsonl', {slot: i});
90
+ step.soft("Question", {tag: q.id}, () => {
91
+ fill(getByRole('textbox', {name: 'Message'}), q.text);
92
+ press(getByRole('textbox', {name: 'Message'}), 'Enter');
93
+ answer = textContent(getByTestId('last-answer'));
94
+ screenshot(q.id);
95
+ assertJudge(answer, q.rubric);
96
+ });
97
+ }
98
+ });
99
+ }
100
+ ```
101
+
40
102
  > **Locator quality matters (D-22).** Prefer `getByTestId` →
41
103
  > `getByRole(name)` → `getByLabel` → `getByText` → `locator(css)`. The AST
42
104
  > linter (`unotest-web lint`) flags brittle selectors — see
@@ -303,8 +365,14 @@ check(getByRole('checkbox', {name: 'Subscribe'}))
303
365
 
304
366
  ```js
305
367
  hover(getByRole('button', {name: 'Help'}))
368
+ // A tall chat bubble whose menu appears only near its top edge: hover
369
+ // the centre and nothing shows — hover an offset inside the element.
370
+ hover(getByTestId('message-42'), {position: {x: 24, y: 8}})
306
371
  ```
307
372
 
373
+ **Options:** `force?`, `timeout?`, `position?` (no `modifiers` — that
374
+ is a `click` option).
375
+
308
376
  ### `selectOption(loc, value, options?)`
309
377
 
310
378
  Native `<select>` only. `value` can be a string, an array of strings, or
@@ -453,6 +521,11 @@ Semantics:
453
521
  a separate `preamble` field: the model saw the two concatenated, and
454
522
  the split says which half came from the scenario and which from the
455
523
  environment.
524
+ - **In the viewer** the verdict sits under the step (`judge ✓/✗ ·
525
+ rubric · text`, open by default when it said no), and the error card
526
+ of a failed judge step carries the whole verdict — rubric, judged
527
+ text, reasoning, model. See `note()` below for attaching the question
528
+ and the answer next to it.
456
529
  - A judge is not deterministic: the judge itself re-asks on `fail`
457
530
  (`UNOTEST_JUDGE_RETRIES`, first `pass` wins); temperature is pinned to 0
458
531
  where the backend accepts it (vertex/gemini). The runner's retry layer is
@@ -881,6 +954,30 @@ step("A personal chat must not leak into the project feed", () => {
881
954
  });
882
955
  ```
883
956
 
957
+ ### `readJsonLine(path, filter)` → `object`
958
+
959
+ The no-wait form of `waitForJsonLine` for a file that **already exists**:
960
+ read it once and return the first line matching `filter`. Use it for
961
+ fixtures and finished exports — a data-driven test reads its cases from
962
+ a JSONL file this way. Same filter rules as `waitForJsonLine` (strict
963
+ equality per key, dot paths for nesting, unparsable lines skipped).
964
+
965
+ ```js
966
+ step("Ask control question 3", () => {
967
+ q = readJsonLine('questions.jsonl', {slot: 3});
968
+ fill(getByRole('textbox', {name: 'Message'}), q.text);
969
+ screenshot(q.id);
970
+ });
971
+ ```
972
+
973
+ - No options and no poll: a missing file fails at once with
974
+ `file not found: <path>`, a missing line with
975
+ `no line matches {…} in <path>` plus the same parse stats and
976
+ closest-line hint `waitForJsonLine` reports on timeout.
977
+ - Pick `waitForJsonLine` when the file is still being written to (a
978
+ background listener's output); its timeout is what makes that safe,
979
+ and what would only hide a wrong path here.
980
+
884
981
  ### `waitForFileCount(path, pattern, count, options?)` → `number`
885
982
 
886
983
  Wait until **at least** `count` lines match, then return how many there
@@ -1152,8 +1249,18 @@ screenshot('bot-reply'); // 002-bot-reply.png
1152
1249
  screenshot('landing', {fullPage: true}); // full scroll height
1153
1250
  ```
1154
1251
 
1155
- - `name` is slugified to `[a-z0-9._-]` (`'Bot Reply!'` `bot-reply`);
1156
- omitted `shot`. Files are numbered in capture order.
1252
+ - `name` is any string value, not only a literal a data-driven test
1253
+ names its evidence after the case it is on:
1254
+
1255
+ ```js
1256
+ q = waitForJsonLine('questions.jsonl', {slot: 3});
1257
+ screenshot(q.id); // 003-q-17.png
1258
+ screenshot(textJoin(['q-', q.id, '-answer']));
1259
+ ```
1260
+
1261
+ - `name` is slugified to `[a-z0-9._-]` (`'Bot Reply!'` → `bot-reply`,
1262
+ `'Q 17/a'` → `q-17-a`); omitted → `shot`. Files are numbered in
1263
+ capture order.
1157
1264
  - **Options:** `fullPage?` (default `false` — viewport only).
1158
1265
  - Before capturing, the call waits for the network to go quiet and for a
1159
1266
  painted frame (up to 2s). Without it a `screenshot()` right after
@@ -1174,17 +1281,50 @@ screenshot('landing', {fullPage: true}); // full scroll height
1174
1281
 
1175
1282
  ---
1176
1283
 
1177
- ## Logging
1284
+ ## Logging and notes
1178
1285
 
1179
1286
  ### `log(...args)`
1180
1287
 
1181
- Routes through the runtime's `Logger.info`. Non-string args are
1182
- `JSON.stringify`'d.
1288
+ Writes one line to the runner's output (the terminal, the live System
1289
+ pane in the viewer) **and** to the run journal (`steps.jsonl`, as a
1290
+ `log` event under the current step), so a finished run still shows it
1291
+ under the step that wrote it and in the System pane. Non-string args
1292
+ are `JSON.stringify`'d.
1183
1293
 
1184
1294
  ```js
1185
1295
  log('user id:', userId);
1186
1296
  ```
1187
1297
 
1298
+ ### `note(label, value)`
1299
+
1300
+ Attach a labelled value to the **current step**: the question a
1301
+ data-driven case asked, the answer it got, an id worth seeing next to
1302
+ the verdict. Lives in the journal, not in stdout — the viewer shows it
1303
+ under the step (an `ⓘ N` chip on the row; the list opens by default
1304
+ when the step failed or a judge said no) during and after the run.
1305
+
1306
+ ```js
1307
+ step.soft("Question", {tag: q.id}, () => {
1308
+ note('question', q.text);
1309
+ fill(getByRole('textbox', {name: 'Message'}), q.text);
1310
+ press(getByRole('textbox', {name: 'Message'}), 'Enter');
1311
+ answer = textContent(getByTestId('last-answer'));
1312
+ note('answer', answer);
1313
+ assertJudge(getByTestId('last-answer'), q.rubric);
1314
+ });
1315
+ ```
1316
+
1317
+ - `label` is a string; `value` is anything — a string as it is, a
1318
+ number, an object or array serialized as JSON.
1319
+ - Long values are cut at 4 KB (marked `truncated`); secrets are masked
1320
+ like everywhere in the run directory.
1321
+ - Each `note` / `log` event records where it was called (`file`, `line`,
1322
+ `col`) and the nearest statement of the entry file (`entryLine`,
1323
+ `entryCol`) — a note from inside a helper lands under the entry step
1324
+ that called the helper.
1325
+ - Without a run journal (exploration, an ad-hoc runtime) `note` goes to
1326
+ the logger instead; nothing fails.
1327
+
1188
1328
  ---
1189
1329
 
1190
1330
  ## Variables, control flow, types
@@ -1192,8 +1332,13 @@ log('user id:', userId);
1192
1332
  The DSL is JavaScript-shaped but parsed by a small AST engine
1193
1333
  (`vendor/dsl/`), not V8. What's supported in scenario files:
1194
1334
 
1195
- - **`function test_*(): { … }`** — scenario entry; each top-level
1196
- `function test_*` is a separately runnable test.
1335
+ - **`function test_*(): { … }`** — the scenario entry, **exactly one per
1336
+ file**: a collection runs files, and the viewer projects a run onto
1337
+ the first `test_*` it finds. A second `test_*` is reported by
1338
+ `lint:one-test-per-file` (a warning in 0.31, an error in a later
1339
+ release) — fold the cases into one test with tagged steps
1340
+ (`step("…", {tag: id}, …)`), or move shared journeys to
1341
+ `unotest/e2e/_helpers/`.
1197
1342
  - **Assignments** — `name = expression;` (no `let`/`const`/`var`).
1198
1343
  - **`if` / `else`** and **`for` in the canonical shape**
1199
1344
  `for (i = 0; i < N; i = i + 1) { … }` (increment must be an
@@ -1249,8 +1394,10 @@ exact grammar deltas from the upstream parser.
1249
1394
  ## Conventions
1250
1395
 
1251
1396
  - **Snake-case test names** — `function test_login_happy_path()`.
1252
- - **One scenario file = one feature.** Multiple `test_*` entries are
1253
- fine when they share a feature surface.
1397
+ - **One scenario file = one test.** The file is the unit a collection
1398
+ runs and the viewer shows; several cases of one feature are one
1399
+ `test_*` with a loop and `step("…", {tag: id}, …)` per case, not
1400
+ several `test_*`.
1254
1401
  - **Helpers stay in `unotest/e2e/_helpers/`** — these are project-owned,
1255
1402
  not part of the core surface. Use sandbox primitives there.
1256
1403
  - **Two kinds of helper.** A `flow_*` helper is a composite journey —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unotest/web",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "AI-native E2E testing for web applications. MCP server (run_test / step / resume / inspect_runtime / agent_fix) + CLI runner + JavaScript DSL scenarios on a sandboxed AST engine + semantic DOM snapshots.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -83,18 +83,18 @@
83
83
  "tsx": "^4.19.2",
84
84
  "yaml": "^2.6.0",
85
85
  "zod": "^3.23.8",
86
- "@unotest/core": "^0.30.0",
87
- "@unotest/viewer": "^0.30.0",
88
- "@unotest/grounder-client": "^0.30.0",
89
- "@unotest/dsl": "^0.30.0",
90
- "@unotest/protocol": "^0.30.0"
86
+ "@unotest/core": "^0.31.0",
87
+ "@unotest/dsl": "^0.31.0",
88
+ "@unotest/viewer": "^0.31.0",
89
+ "@unotest/grounder-client": "^0.31.0",
90
+ "@unotest/protocol": "^0.31.0"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@types/node": "^22.10.0",
94
94
  "javascript-obfuscator": "^4.1.1",
95
95
  "tsup": "^8.5.1",
96
96
  "typescript": "^5.7.2",
97
- "@unotest/judge": "^0.30.0",
98
- "@unotest/grounder": "^0.30.0"
97
+ "@unotest/judge": "^0.31.0",
98
+ "@unotest/grounder": "^0.31.0"
99
99
  }
100
100
  }
@@ -49,6 +49,14 @@ The linter rejects a test in the e2e root (`lint:scenario-in-root`), and
49
49
  from the area of the app under test. Shared helpers live in
50
50
  `unotest/e2e/_helpers/`; `_template.js` is a starting point to copy.
51
51
 
52
+ One `test_*` per file. The file is what a collection runs and what the viewer
53
+ shows (its Steps tree projects the run onto the first `test_*`; any other
54
+ runs unseen). Several cases of one feature are ONE test with a loop and
55
+ `step("…", {tag: id}, () => { … })` per case — `step.soft` when a failed case
56
+ must not stop the run; shared journeys are `flow_*` helpers in
57
+ `unotest/e2e/_helpers/`. A second `test_*` is flagged by
58
+ `lint:one-test-per-file` (a warning today, an error in a later release).
59
+
52
60
  ## Locator hierarchy (D-22, hard rule)
53
61
 
54
62
  When choosing a selector, prefer in this exact order:
@@ -310,7 +318,9 @@ A login (or any setup block) that many tests share should be a reusable
310
318
  - **Flow already exists** (it's in `availableFlows`): call
311
319
  `explore_run_flow({ explorationId, name })`. It replays the flow LIVE (you end
312
320
  up logged in) and records a single `flow_<name>()` call — don't re-record the
313
- steps.
321
+ steps. A flow with parameters (`params` in `availableFlows`) takes them as
322
+ `args`, positional — `args: ["{{LOGIN}}", "{{PASSWORD}}"]` replays on the
323
+ values and records `flow_login(LOGIN, PASSWORD)`; the count must match.
314
324
  - **First time** (no flow yet): record the block normally but put
315
325
  `flow:"signin"` on every step of it (`explore_step({…, flow:"signin"})`).
316
326
  On `save_exploration_as_test`, those steps are extracted into