diff --git a/.claude/skills/web-test/SKILL.md b/.claude/skills/web-test/SKILL.md index 7c9b989d..49f52928 100644 --- a/.claude/skills/web-test/SKILL.md +++ b/.claude/skills/web-test/SKILL.md @@ -66,6 +66,9 @@ const form = await getFormState(); console.log(JSON.stringify(form, null, 2)); SCRIPT +# 2b. Execute without video recording (for debugging/testing) +cat script.js | node $RUN exec - --no-record + # 3. Screenshot node $RUN shot result.png @@ -193,7 +196,7 @@ Sections + all open tabs. ### Actions -#### `clickElement(text, { dblclick?, table? })` → form state +#### `clickElement(text, { dblclick?, table?, toggle? })` → form state Click button, hyperlink, tab, or grid row (fuzzy match). - `table` — scope button search to a specific grid's command panel (by name from `tables[]`): @@ -210,7 +213,11 @@ Click button, hyperlink, tab, or grid row (fuzzy match). // r.submenu = ['Расширенный поиск', 'Настройки', ...] await clickElement('Расширенный поиск'); ``` -- Handles tree nodes: clicking a tree icon expands/collapses. +- **Tree nodes**: default click = **select** (highlight row). Use `{ toggle: true }` to **expand/collapse**: + ```js + await clickElement('ИСУ ФХД'); // select row + await clickElement('ИСУ ФХД', { toggle: true }); // expand/collapse + ``` #### `fillFields({ name: value })` → `{ filled, form }` Fill form fields by label (fuzzy match). Auto-detects field type. diff --git a/.claude/skills/web-test/scripts/run.mjs b/.claude/skills/web-test/scripts/run.mjs index 6e61265b..d21833d9 100644 --- a/.claude/skills/web-test/scripts/run.mjs +++ b/.claude/skills/web-test/scripts/run.mjs @@ -24,12 +24,14 @@ import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const SESSION_FILE = resolve(__dirname, '..', '.browser-session.json'); -const [,, cmd, ...args] = process.argv; +const [,, cmd, ...rawArgs] = process.argv; +const flags = { noRecord: rawArgs.includes('--no-record') }; +const args = rawArgs.filter(a => !a.startsWith('--')); switch (cmd) { case 'start': await cmdStart(args[0]); break; case 'run': await cmdRun(args[0], args[1]); break; - case 'exec': await cmdExec(args[0]); break; + case 'exec': await cmdExec(args[0], flags); break; case 'shot': await cmdShot(args[0]); break; case 'stop': await cmdStop(); break; case 'status': cmdStatus(); break; @@ -196,13 +198,18 @@ async function cmdRun(url, fileOrDash) { // exec: send script to running server // ============================================================ -async function cmdExec(fileOrDash) { - if (!fileOrDash) die('Usage: node src/run.mjs exec '); +async function cmdExec(fileOrDash, flags = {}) { + if (!fileOrDash) die('Usage: node src/run.mjs exec [--no-record]'); - const code = fileOrDash === '-' + let code = fileOrDash === '-' ? await readStdin() : readFileSync(resolve(fileOrDash), 'utf-8'); + if (flags.noRecord) { + // Inject no-op record() before user code + code = 'async function record() {} // --no-record\n' + code; + } + const sess = loadSession(); const result = await new Promise((resolve, reject) => { const req = http.request({ @@ -322,10 +329,13 @@ function usage() { die(`Usage: node src/run.mjs [args] Commands: - start Launch browser and connect to 1C web client - run Autonomous: connect, execute script, disconnect - exec Execute script (file path or - for stdin) - shot [file] Take screenshot (default: shot.png) - stop Logout and close browser - status Check session status`); + start Launch browser and connect to 1C web client + run Autonomous: connect, execute script, disconnect + exec [options] Execute script (file path or - for stdin) + shot [file] Take screenshot (default: shot.png) + stop Logout and close browser + status Check session status + +Options for exec: + --no-record Skip video recording (record() becomes no-op)`); }