From e58f5c1f82c8842ba92dd2ff460dc7e8c1b4778f Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 28 Feb 2026 15:37:58 +0300 Subject: [PATCH] feat(web-test): add navigateLink() for direct 1C navigation links - navigateLink(url): opens form via Shift+F11 dialog with clipboard paste - Grant clipboard-read/write permissions on browser context creation - Register navigateLink in ACTION_FNS for auto-error detection - Document in SKILL.md with examples (e1cib/list/...) Co-Authored-By: Claude Opus 4.6 --- .claude/skills/web-test/SKILL.md | 12 ++++++++ .claude/skills/web-test/scripts/browser.mjs | 33 ++++++++++++++++++++- .claude/skills/web-test/scripts/run.mjs | 4 +-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/.claude/skills/web-test/SKILL.md b/.claude/skills/web-test/SKILL.md index b7d76c2c..158f9858 100644 --- a/.claude/skills/web-test/SKILL.md +++ b/.claude/skills/web-test/SKILL.md @@ -98,6 +98,7 @@ In `exec` sandbox, all browser.mjs functions are available as globals — no `im |----------|-------------| | `navigateSection(name)` | Go to section (fuzzy match). Returns `{ sections, commands }` | | `openCommand(name)` | Open command from function panel (fuzzy). Returns form state | +| `navigateLink(url)` | Open 1C navigation link via Shift+F11 dialog. Returns form state | | `switchTab(name)` | Switch to open tab/window (fuzzy). Returns form state | ### Reading @@ -214,6 +215,17 @@ Hint: if `readTable()` returns `hierarchical: true`, the list has groups. | `F4` | Reference field focused | Open selection form | | `Alt+F` | List/table form | Open advanced search dialog | +### Navigation links + +```js +// Open any form directly by 1C navigation link (e1cib/...) +await navigateLink('e1cib/list/РегистрНакопления.ЗаказыКлиентов'); +await navigateLink('e1cib/list/Документ.ЗаказКлиента'); +await navigateLink('e1cib/list/Справочник.Контрагенты'); +``` + +Bypasses section/command navigation. Useful for registers, journals, and any form with a known path. + ### Submenu navigation ```js diff --git a/.claude/skills/web-test/scripts/browser.mjs b/.claude/skills/web-test/scripts/browser.mjs index 212bb4fd..ab94222a 100644 --- a/.claude/skills/web-test/scripts/browser.mjs +++ b/.claude/skills/web-test/scripts/browser.mjs @@ -40,7 +40,10 @@ export async function connect(url) { await page.goto(url, { waitUntil: 'domcontentloaded', timeout: LOAD_TIMEOUT }); } else { browser = await chromium.launch({ headless: false, args: ['--start-maximized'] }); - const context = await browser.newContext({ viewport: null }); + const context = await browser.newContext({ + viewport: null, + permissions: ['clipboard-read', 'clipboard-write'], + }); page = await context.newPage(); // Capture seanceId from network requests for graceful logout @@ -337,6 +340,34 @@ export async function switchTab(name) { return await getFormState(); } +/** Navigate to a 1C navigation link via Shift+F11 dialog. Returns new form state. */ +export async function navigateLink(url) { + ensureConnected(); + await dismissPendingErrors(); + const formBefore = await page.evaluate(detectFormScript()); + + // Copy link to clipboard, press Shift+F11 (opens "Go to link" dialog with clipboard content) + await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(url)})`); + await page.keyboard.press('Shift+F11'); + await waitForStable(); + + // Click "Перейти" in the navigation dialog + const dialog = await page.evaluate(detectFormScript()); + if (dialog != null && dialog !== formBefore) { + const btns = await page.$$(`#form${dialog}_container a.press`); + for (const b of btns) { + const txt = (await b.textContent())?.trim(); + if (txt === 'Перейти') { await b.click(); break; } + } + } + + await waitForStable(formBefore); + const state = await getFormState(); + const err = await checkForErrors(); + if (err) state.errors = err; + return state; +} + /** Read current form state. Single evaluate call via combined script. */ export async function getFormState() { ensureConnected(); diff --git a/.claude/skills/web-test/scripts/run.mjs b/.claude/skills/web-test/scripts/run.mjs index bac0921f..cbdc51e8 100644 --- a/.claude/skills/web-test/scripts/run.mjs +++ b/.claude/skills/web-test/scripts/run.mjs @@ -117,8 +117,8 @@ async function executeScript(code) { // and stop execution immediately with diagnostic info const ACTION_FNS = [ 'clickElement', 'fillFields', 'selectValue', 'fillTableRow', - 'deleteTableRow', 'openCommand', 'navigateSection', 'closeForm', - 'filterList', 'unfilterList' + 'deleteTableRow', 'openCommand', 'navigateSection', 'navigateLink', + 'closeForm', 'filterList', 'unfilterList' ]; for (const name of ACTION_FNS) { if (typeof exports[name] !== 'function') continue;