mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-29 16:11:01 +03:00
fix(web-test): состояние группы по контролу сворачивания, а не по вёрстке содержимого
На боевой форме вскрылись случаи, которые прежнее правило не покрывало. Замеры показали, что любая эвристика «по первому сиблингу за заголовком» нежизнеспособна: - служебная обёртка .logicGroupContainer пишется двумя способами (у таблицы <дочерний>#group_div, у вложенной группы <дочерний>_div) — знали только первый; - display самой обёртки плавает: block до первого тогла, none после; - первые узлы группы могут быть скрыты своей логикой, а видимое содержимое идёт дальше по цепочке — раскрытая группа читалась как свёрнутая, и постусловие роняло успешный клик. Теперь состояние берётся из контрола сворачивания: у варианта «картинка» — кадр gx спрайта hideshow у каретки (полярность обратна дереву в dom/grid.mjs), у варианта «гиперссылка» каретки нет, там принадлежность по отступу — дети группы смещены глубже её заголовка, свободный сосед стоит на уровне заголовка. База отсчёта — левый край блока заголовка (каретка сдвигает текст вправо), обход ограничен: у последней свёрнутой группы границы за ней нет, и первый видимый узел нашёлся через 107 сиблингов в чужой ветке формы. Клик по заголовку группы теперь сперва скроллит цель в вид: цель кликается по координатам, и ниже вьюпорта клик молча не доходил. Ответ на клик отдаёт clicked.group (техническое имя) и clicked.title (текущий заголовок): заголовок ключом быть не может — он повторяется между блоками формы и меняется при раскрытии (CollapsedRepresentationTitle), после чего клик по прежнему тексту не находит элемент. При смене заголовка hint говорит, чем кликать дальше. Фикстура: вложенная группа первым ребёнком, «скрыт первый узел» в двух вариантах контрола, группа с меняющимся заголовком в конце формы (уезжает за вьюпорт). Каждый кейс проверен на красноту без своей правки. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
006e64405c
commit
d0e81a1715
@@ -101,6 +101,89 @@ export default async function({ navigateSection, openCommand, navigateLink, getF
|
||||
await closeForm();
|
||||
});
|
||||
|
||||
await step('вложенная группа первым ребёнком: обёртка вида <дочерний>_div', async () => {
|
||||
// Служебную обёртку .logicGroupContainer платформа пишет двумя способами: у таблицы —
|
||||
// <дочерний>#group_div, у вложенной группы — <дочерний>_div. Правило, знающее только
|
||||
// первую форму, читает display обёртки (block) и рапортует «раскрыта» у свёрнутой.
|
||||
const виден = (st) => (st.texts || []).some(t => /Содержимое вложенной группы/.test(t.value));
|
||||
const s = await navigateLink('Обработка.СтраницаНастроек');
|
||||
assert.equal(collapsedOf(s, 'ГруппаСВложенной'), true, 'свёрнута сразу после открытия');
|
||||
assert.equal(виден(s), false, 'содержимое вложенной группы не видно');
|
||||
|
||||
let r = await clickElement('Свёрнутая с вложенной группой', { expand: true });
|
||||
assert.equal(collapsedOf(r, 'ГруппаСВложенной'), false, 'раскрыта');
|
||||
assert.equal(виден(r), true, 'содержимое вложенной группы появилось');
|
||||
|
||||
r = await clickElement('Свёрнутая с вложенной группой', { expand: true });
|
||||
assert.equal(r.clicked.toggled, false, 'expand:true повторно — идемпотентно');
|
||||
|
||||
r = await clickElement('Свёрнутая с вложенной группой', { expand: false });
|
||||
assert.equal(collapsedOf(r, 'ГруппаСВложенной'), true, 'свёрнута обратно');
|
||||
assert.equal(виден(r), false, 'содержимое скрылось');
|
||||
await closeForm();
|
||||
});
|
||||
|
||||
await step('скрытый первый узел: состояние берётся не по первому сиблингу', async () => {
|
||||
// Первый элемент группы скрыт своей логикой (visible:false), видимое содержимое — дальше
|
||||
// по цепочке сиблингов. Так ведёт себя боевая форма с таблицей, у которой скрыта командная
|
||||
// панель: чтение «display первого контент-узла» у РАСКРЫТОЙ группы даёт «свёрнута», и
|
||||
// clickElement({expand}) считает свой клик несработавшим.
|
||||
const пары = [
|
||||
['Скрыт первый узел', 'ГруппаСкрытыйПервый', /^Видно только эту декорацию$/],
|
||||
['Скрыт первый узел (картинка)', 'ГруппаСкрытыйПервыйКартинка', /Видно только эту декорацию \(картинка\)/],
|
||||
];
|
||||
for (const [заголовок, имя, маркер] of пары) {
|
||||
const s = await navigateLink('Обработка.СтраницаНастроек');
|
||||
const виден = (st) => (st.texts || []).some(t => маркер.test(t.value));
|
||||
assert.equal(collapsedOf(s, имя), true, `${имя}: свёрнута после открытия`);
|
||||
assert.equal(виден(s), false, `${имя}: содержимое скрыто`);
|
||||
|
||||
let r = await clickElement(заголовок, { expand: true });
|
||||
assert.equal(collapsedOf(r, имя), false, `${имя}: раскрыта (первый узел так и остался скрытым)`);
|
||||
assert.equal(виден(r), true, `${имя}: видимый узел появился`);
|
||||
|
||||
r = await clickElement(заголовок, { expand: true });
|
||||
assert.equal(r.clicked.toggled, false, `${имя}: expand:true повторно — идемпотентно`);
|
||||
|
||||
r = await clickElement(заголовок, { expand: false });
|
||||
assert.equal(collapsedOf(r, имя), true, `${имя}: свёрнута обратно`);
|
||||
assert.equal(виден(r), false, `${имя}: содержимое скрылось`);
|
||||
await closeForm();
|
||||
}
|
||||
});
|
||||
|
||||
await step('меняющийся заголовок + цель ниже вьюпорта: ответ даёт стабильный ключ', async () => {
|
||||
// У группы задан CollapsedRepresentationTitle, поэтому текст заголовка меняется при
|
||||
// раскрытии, и повторный клик по прежнему тексту падает с «not found». Ответ на клик
|
||||
// отдаёт техническое имя (group) и текущий заголовок (title), а hint предупреждает о смене.
|
||||
// Группа последняя на форме: раскрытая выше таблица уводит её за пределы окна — координатный
|
||||
// клик туда раньше не доходил, теперь цель сперва скроллится в вид.
|
||||
const G = 'ГруппаМеняющийсяЗаголовок';
|
||||
const s = await navigateLink('Обработка.СтраницаНастроек');
|
||||
assert.equal(collapsedOf(s, G), true, 'свёрнута после открытия');
|
||||
assert.equal((s.groups || []).find(g => g.name === G)?.title, 'Показать подробности',
|
||||
'в свёрнутом виде — заголовок свёрнутого представления');
|
||||
await clickElement('Свёрнутая с таблицей', { expand: true }); // удлиняем форму
|
||||
|
||||
let r = await clickElement('Показать подробности', { expand: true });
|
||||
assert.equal(r.clicked.toggled, true, 'кликнул (цель за вьюпортом — со скроллом)');
|
||||
assert.equal(collapsedOf(r, G), false, 'раскрыта');
|
||||
assert.equal(r.clicked.group, G, 'clicked.group — техническое имя группы');
|
||||
assert.equal(r.clicked.title, 'Скрыть подробности', 'clicked.title — текущий заголовок');
|
||||
assert.includes(r.hint, 'now titled "Скрыть подробности"', 'hint предупреждает о смене заголовка');
|
||||
|
||||
// Прежний текст больше не находится — ради этого в ответе и есть стабильный ключ.
|
||||
await assert.throws(() => clickElement('Показать подробности', { expand: false }),
|
||||
'клик по прежнему заголовку не проходит');
|
||||
|
||||
r = await clickElement(r.clicked.group, { expand: true });
|
||||
assert.equal(r.clicked.toggled, false, 'по техническому имени expand идемпотентен');
|
||||
r = await clickElement(G, { expand: false });
|
||||
assert.equal(collapsedOf(r, G), true, 'свёрнута обратно по техническому имени');
|
||||
assert.equal(r.clicked.title, 'Показать подробности', 'заголовок вернулся к свёрнутому');
|
||||
await closeForm();
|
||||
});
|
||||
|
||||
await step('растянутая гиперссылка: клик доходит до обработчика', async () => {
|
||||
// Проверка соседнего с дефектом 2 случая. Ссылка растянута на всю ширину формы
|
||||
// (horizontalStretch + autoMaxWidth:false → контейнер 1295px), но промаха тут НЕ бывает:
|
||||
|
||||
Reference in New Issue
Block a user