mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-30 08:26:55 +03:00
fix(web-test): prioritize groups over buttons in highlight() search order
Group names often collide with command bar buttons (e.g. "БизнесПроцессы" matched a tiny 38x35 button instead of the 959x580 panel). Move group search before button/field search with min-size filter (100x50). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
4507d9b59c
commit
85191dc759
@@ -140,7 +140,7 @@ Manually highlight a UI element by name (fuzzy match). Places a semi-transparent
|
|||||||
| `text` | string | Element name — button, link, field, group/panel, section, or command |
|
| `text` | string | Element name — button, link, field, group/panel, section, or command |
|
||||||
|
|
||||||
- Fuzzy match order: exact → startsWith → includes
|
- Fuzzy match order: exact → startsWith → includes
|
||||||
- Search priority: popup items → commands → form elements (buttons, fields) → **form groups/panels** → sections
|
- Search priority: popup items → commands → **form groups/panels** → form elements (buttons, fields) → sections
|
||||||
- Groups are matched by visible title or internal name (e.g., `highlight('Оргструктура')` finds the group panel)
|
- Groups are matched by visible title or internal name (e.g., `highlight('Оргструктура')` finds the group panel)
|
||||||
- `pointer-events: none` — does not block clicks
|
- `pointer-events: none` — does not block clicks
|
||||||
|
|
||||||
|
|||||||
@@ -3536,11 +3536,44 @@ export async function highlight(text, opts = {}) {
|
|||||||
})()`);
|
})()`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Form-scoped search (buttons, links, fields, grid rows)
|
// 2. Form groups/panels — checked BEFORE buttons/fields because group names
|
||||||
|
// often collide with command bar buttons (e.g. "БизнесПроцессы" is both a
|
||||||
|
// panel and a command bar element). Groups are large visual containers;
|
||||||
|
// min-area filter (100x50) prevents matching small elements.
|
||||||
if (!elId) {
|
if (!elId) {
|
||||||
const formNum = await page.evaluate(detectFormScript());
|
const formNum = await page.evaluate(detectFormScript());
|
||||||
if (formNum !== null) {
|
if (formNum !== null) {
|
||||||
// 1a. Try button/link/tab/gridRow via findClickTargetScript
|
elId = await page.evaluate(`(() => {
|
||||||
|
const norm = s => (s?.trim().replace(/\\u00a0/g, ' ') || '').replace(/ё/gi, 'е');
|
||||||
|
const target = ${JSON.stringify(normYo(text.toLowerCase()))};
|
||||||
|
const p = 'form' + ${formNum} + '_';
|
||||||
|
// Collect visible group containers — _container or _div elements (min 100x50 to skip command bars)
|
||||||
|
const groups = [...document.querySelectorAll('[id^="' + p + '"][id$="_container"], [id^="' + p + '"][id$="_div"]')]
|
||||||
|
.filter(el => el.offsetWidth >= 100 && el.offsetHeight >= 50);
|
||||||
|
const items = groups.map(el => {
|
||||||
|
const idName = el.id.replace(p, '').replace(/_(container|div)$/, '');
|
||||||
|
// Try to find a visible title/label for this group
|
||||||
|
const titleEl = document.getElementById(p + idName + '#title_text')
|
||||||
|
|| document.getElementById(p + idName + '_title_text');
|
||||||
|
const label = norm(titleEl?.innerText || '').toLowerCase();
|
||||||
|
const name = norm(idName).toLowerCase();
|
||||||
|
return { id: el.id, name, label };
|
||||||
|
});
|
||||||
|
// Fuzzy match: exact label → exact name → startsWith → includes
|
||||||
|
let found = items.find(i => i.label === target);
|
||||||
|
if (!found) found = items.find(i => i.name === target);
|
||||||
|
if (!found) found = items.find(i => i.label.startsWith(target) || i.name.startsWith(target));
|
||||||
|
if (!found) found = items.find(i => i.label.includes(target) || i.name.includes(target));
|
||||||
|
return found ? found.id : null;
|
||||||
|
})()`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Form-scoped search (buttons, links, fields, grid rows)
|
||||||
|
if (!elId) {
|
||||||
|
const formNum = await page.evaluate(detectFormScript());
|
||||||
|
if (formNum !== null) {
|
||||||
|
// 3a. Try button/link/tab/gridRow via findClickTargetScript
|
||||||
const target = await page.evaluate(findClickTargetScript(formNum, text));
|
const target = await page.evaluate(findClickTargetScript(formNum, text));
|
||||||
if (target && !target.error) {
|
if (target && !target.error) {
|
||||||
if (target.id) {
|
if (target.id) {
|
||||||
@@ -3568,7 +3601,7 @@ export async function highlight(text, opts = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1b. If not found as button — try as field via resolveFieldsScript
|
// 3b. If not found as button — try as field via resolveFieldsScript
|
||||||
if (!elId) {
|
if (!elId) {
|
||||||
const dummyFields = { [text]: '' };
|
const dummyFields = { [text]: '' };
|
||||||
const resolved = await page.evaluate(resolveFieldsScript(formNum, dummyFields));
|
const resolved = await page.evaluate(resolveFieldsScript(formNum, dummyFields));
|
||||||
@@ -3579,36 +3612,6 @@ export async function highlight(text, opts = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Form groups/panels (containers with title text or matching ID name)
|
|
||||||
if (!elId) {
|
|
||||||
const formNum = elId === null ? await page.evaluate(detectFormScript()) : null;
|
|
||||||
if (formNum !== null) {
|
|
||||||
elId = await page.evaluate(`(() => {
|
|
||||||
const norm = s => (s?.trim().replace(/\\u00a0/g, ' ') || '').replace(/ё/gi, 'е');
|
|
||||||
const target = ${JSON.stringify(normYo(text.toLowerCase()))};
|
|
||||||
const p = 'form' + ${formNum} + '_';
|
|
||||||
// Collect visible group containers — _container or _div elements
|
|
||||||
const groups = [...document.querySelectorAll('[id^="' + p + '"][id$="_container"], [id^="' + p + '"][id$="_div"]')]
|
|
||||||
.filter(el => el.offsetWidth > 0 && el.offsetHeight > 0);
|
|
||||||
const items = groups.map(el => {
|
|
||||||
const idName = el.id.replace(p, '').replace(/_(container|div)$/, '');
|
|
||||||
// Try to find a visible title/label for this group
|
|
||||||
const titleEl = document.getElementById(p + idName + '#title_text')
|
|
||||||
|| document.getElementById(p + idName + '_title_text');
|
|
||||||
const label = norm(titleEl?.innerText || '').toLowerCase();
|
|
||||||
const name = norm(idName).toLowerCase();
|
|
||||||
return { id: el.id, name, label };
|
|
||||||
});
|
|
||||||
// Fuzzy match: exact label → exact name → startsWith → includes
|
|
||||||
let found = items.find(i => i.label === target);
|
|
||||||
if (!found) found = items.find(i => i.name === target);
|
|
||||||
if (!found) found = items.find(i => i.label.startsWith(target) || i.name.startsWith(target));
|
|
||||||
if (!found) found = items.find(i => i.label.includes(target) || i.name.includes(target));
|
|
||||||
return found ? found.id : null;
|
|
||||||
})()`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Fallback: sections (sidebar navigation)
|
// 4. Fallback: sections (sidebar navigation)
|
||||||
if (!elId) {
|
if (!elId) {
|
||||||
elId = await page.evaluate(`(() => {
|
elId = await page.evaluate(`(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user