@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.
- package/.claude/skills/write-e2e-test/SKILL.md +12 -0
- package/.claude/skills/write-e2e-test-ground/SKILL.md +12 -0
- package/CHANGELOG.md +266 -0
- package/bin/unotest-web.js +3 -1
- package/dist/config/schema.d.ts +9 -9
- package/dist/config/schema.js +1 -1
- package/dist/driver/index.d.ts +11 -3
- package/dist/driver/index.js +1 -1
- package/dist/dsl/index.d.ts +34 -4
- package/dist/dsl/index.js +1 -1
- package/dist/dsl/web-dsl-language-service.d.ts +22 -2
- package/dist/dsl/web-dsl-language-service.js +1 -1
- package/dist/inspection/page-inject.d.ts +1 -1
- package/dist/{interfaces-BluheUKs.d.ts → interfaces-B34N4rfI.d.ts} +8 -0
- package/dist/legacy-layout-By62PkbP.d.ts +8 -0
- package/dist/linter-Yf4gPe5J.d.ts +36 -0
- package/dist/mcp/server.js +1 -1
- package/dist/runner/cli.d.ts +13 -2
- package/dist/runner/cli.js +1 -1
- package/dist/runner/init/chrome-probe.js +1 -1
- package/dist/runner/init.js +1 -1
- package/dist/runner/install-chromium.js +1 -1
- package/dist/runner/prepare-fix.js +1 -1
- package/dist/runner/scaffold-workspace.js +1 -1
- package/dist/runner/serve-fixture.js +1 -1
- package/dist/runner/web-runner-adapter.js +1 -1
- package/guides/agent-integration.md +43 -2
- package/guides/dsl-reference.md +156 -9
- package/package.json +8 -8
- package/src/mcp/prompts/agent-test-author.md +11 -1
- package/types/unotest-dsl.d.ts +29 -5
- package/dist/linter-CM2CpIyW.d.ts +0 -21
|
@@ -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
|
|
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-
|
|
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
|
package/guides/dsl-reference.md
CHANGED
|
@@ -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
|
|
1156
|
-
|
|
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
|
-
|
|
1182
|
-
`
|
|
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
|
|
1196
|
-
|
|
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
|
|
1253
|
-
|
|
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.
|
|
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.
|
|
87
|
-
"@unotest/
|
|
88
|
-
"@unotest/
|
|
89
|
-
"@unotest/
|
|
90
|
-
"@unotest/protocol": "^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.
|
|
98
|
-
"@unotest/grounder": "^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
|