feat(web-test): всплывающие (popup) группы — behavior, состояние, клик

Popup-группа надёжно отличается от сворачиваемой по DOM-маркеру панели
<base>#panel_div (+ #CloseBtn). В getFormState().groups она помечается
behavior:'popup', а её collapsed берётся из display панели (закрыта =
collapsed:true), не из инлайн-сиблинга (у popup содержимое в отдельном
слое, а не под mainGroup).

clickElement по заголовку popup и открывает, и закрывает — тот же
словарь {expand}/{toggle}, что и у сворачиваемых. После открытия
содержимое панели становится читаемым в getFormState (fields/
hyperlinks/texts). Тест 25-decoration-form покрывает popup; SKILL
дополнен. Полный регресс 29 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-18 13:18:18 +03:00
co-authored by Claude Opus 4.8
parent bd86ece90e
commit fc2323f321
4 changed files with 50 additions and 25 deletions
+10 -9
View File
@@ -1,4 +1,4 @@
// web-test dom/forms v1.11 — form detection, content read, click-target/field-button resolution
// web-test dom/forms v1.12 — form detection, content read, click-target/field-button resolution
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import { DETECT_FORM_FN, READ_FORM_FN, ROW_CLICK_POINT_FN } from './_shared.mjs';
@@ -105,23 +105,24 @@ export function findClickTargetScript(formNum, text, { tableName, gridSelector }
});
// Сворачиваемые/всплывающие группы — заголовок как цель раскрытия/сворачивания.
// Идентификация: <base>#title_text гиперссылка (TitleHyperlink/popup) ЛИБО рядом есть
// кнопка-каретка <base>#titleBtn (ControlRepresentation=Picture). Обычные группы пропускаем.
// Мишень клика: #titleBtn (вариант «картинка») иначе сам заголовок-гиперссылка.
// Состояние: первый контент-сиблинг за #title_div (display:none = свёрнута).
// Идентификация: <base>#title_text и один из: гиперссылка (TitleHyperlink) ЛИБО кнопка-каретка
// <base>#titleBtn (Picture) ЛИБО панель <base>#panel_div (popup). Обычные группы пропускаем.
// Мишень клика: #titleBtn (вариант «картинка») иначе заголовок (у popup клик по заголовку
// и открывает, и закрывает). Состояние: у popup — display панели, иначе — первый контент-
// сиблинг за #title_div (display:none = свёрнута/закрыта).
[...document.querySelectorAll('[id^="' + p + '"][id$="#title_text"]')]
.filter(el => el.offsetWidth > 0 || el.offsetHeight > 0).forEach(el => {
const base = el.id.slice(0, -('#title_text'.length));
const btn = document.getElementById(base + '#titleBtn');
const btnVisible = btn && (btn.offsetWidth > 0 || btn.offsetHeight > 0);
if (!el.classList.contains('staticTextHyper') && !btnVisible) return; // обычная группа
const panelDiv = document.getElementById(base + '#panel_div');
if (!el.classList.contains('staticTextHyper') && !btnVisible && !panelDiv) return; // обычная группа
const tgt = btnVisible ? btn : el;
const r = tgt.getBoundingClientRect();
const titleDiv = document.getElementById(base + '#title_div');
const sib = titleDiv && titleDiv.nextElementSibling;
const item = { id: '', kind: 'formGroup', name: norm(el.innerText) || base.replace(p, ''),
label: base.replace(p, ''), x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
if (sib) item.collapsed = getComputedStyle(sib).display === 'none';
const stateEl = panelDiv || (document.getElementById(base + '#title_div') || {}).nextElementSibling;
if (stateEl) item.collapsed = getComputedStyle(stateEl).display === 'none';
items.push(item);
});