fix(web-test): highlight commands before form elements

When the function panel is open over a form, highlight() was finding
buttons from the hidden form instead of visible commands on the panel.
Move command search (cmd_XXX_txt) to step 1 — before form-scoped
search — so visible panel commands always take priority. Form elements
searched at step 2 only if no command matched.

Highlight search order is now:
0. Open submenu/popup (elementFromPoint overlay)
1. Commands on function panel (visible cmd_ elements)
2. Form elements (buttons, fields, grid rows)
3. Sections (sidebar navigation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-02 19:14:26 +03:00
co-authored by Claude Opus 4.6
parent 98ece6206e
commit 98c416b5a7
+20 -13
View File
@@ -2699,9 +2699,24 @@ export async function highlight(text, opts = {}) {
}
}
// 1. Form-scoped search (buttons, links, fields, grid rows)
// Priority: form elements > sections/commands — avoids false matches
// like "ОК" matching section "Покупки" via .includes()
// 1. Visible commands on the function panel (cmd_XXX_txt elements)
// Must be checked BEFORE form search: when the section content panel
// is showing, the form behind it is hidden but detectFormScript still
// finds it, and form buttons match before commands.
if (!elId) {
elId = await page.evaluate(`(() => {
const norm = s => (s?.trim().replace(/\\u00a0/g, ' ') || '').replace(/ё/gi, 'е');
const target = ${JSON.stringify(normYo(text.toLowerCase()))};
const cmds = [...document.querySelectorAll('[id^="cmd_"][id$="_txt"]')].filter(e => e.offsetWidth > 0);
if (cmds.length === 0) return null;
let el = cmds.find(e => norm(e.innerText).toLowerCase() === target);
if (!el) el = cmds.find(e => norm(e.innerText).toLowerCase().startsWith(target));
if (!el) el = cmds.find(e => norm(e.innerText).toLowerCase().includes(target));
return el ? el.id : null;
})()`);
}
// 2. Form-scoped search (buttons, links, fields, grid rows)
if (!elId) {
const formNum = await page.evaluate(detectFormScript());
if (formNum !== null) {
@@ -2744,24 +2759,16 @@ export async function highlight(text, opts = {}) {
}
}
// 2. Fallback: section or command (outside form scope)
// 3. Fallback: sections (sidebar navigation)
if (!elId) {
elId = await page.evaluate(`(() => {
const norm = s => (s?.trim().replace(/\\u00a0/g, ' ') || '').replace(/ё/gi, 'е');
const target = ${JSON.stringify(normYo(text.toLowerCase()))};
// Sections (exact → startsWith → includes)
const secs = [...document.querySelectorAll('[id^="themesCell_theme_"]')];
let el = secs.find(e => norm(e.innerText).toLowerCase() === target);
if (!el) el = secs.find(e => norm(e.innerText).toLowerCase().startsWith(target));
if (!el) el = secs.find(e => norm(e.innerText).toLowerCase().includes(target));
if (el) return el.id;
// Commands (exact → startsWith → includes)
const cmds = [...document.querySelectorAll('[id^="cmd_"][id$="_txt"]')].filter(e => e.offsetWidth > 0);
el = cmds.find(e => norm(e.innerText).toLowerCase() === target);
if (!el) el = cmds.find(e => norm(e.innerText).toLowerCase().startsWith(target));
if (!el) el = cmds.find(e => norm(e.innerText).toLowerCase().includes(target));
if (el) return el.id;
return null;
return el ? el.id : null;
})()`);
}