fix(web-test): заполнение data-ячеек безголового грида + устранение мигания чекбокса

Два фикса в fillTableRow на гридах:

1. Безголовые гриды (без .gridHead): правка data-ячейки (число/ссылка)
   молча возвращала filled:[]. В режиме редактирования INPUT рендерится
   в оверлее .inputs ВНЕ .gridBox, поэтому readActiveGridCell не доставал
   colindex через предков → синтетическое имя Колонка{N} не матчилось в
   Tab-цикле. Теперь colindex резолвится по x-координате INPUT относительно
   ячеек тела грида — тем же приёмом, что и шапочная ветка, через единый
   synthHeaderlessColumns.

2. Чекбокс-ячейки: безусловный первичный клик по центру ячейки тогглил
   чекбокс ДО checkbox-логики, которая затем «доправляла» значение обратно
   — лишний клик и видимое мигание (снимаем→ставим) при установке в уже
   текущее значение. Детект чекбокса (findCheckboxAtPoint, читает состояние
   из DOM без режима редактирования) перенесён ДО первичного клика: кликаем
   по иконке только когда текущее состояние != желаемого (0 кликов на
   идемпотентном тоггле). Затрагивало любые таблицы, не только безголовые.

Тест 21-headerless расширен шагами на заполнение data-ячеек (число direct,
ссылка dropdown) и клик по data-колонке (через API, без raw DOM).

Полный регресс web-test: 25 passed, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-29 12:55:34 +03:00
parent 03d90b6960
commit 3a7f1c1763
3 changed files with 65 additions and 27 deletions
+27 -1
View File
@@ -6,7 +6,9 @@ export const timeout = 180000;
// - БезшапочнаяТаблица (ValueTable, отдельная колонка-чекбокс)
// - МножественныйВыбор → Через флажки (марк-список, комбинированная ячейка галка+текст)
// Деривация колонок едина (synthHeaderlessColumns): Колонка{N} + (checkbox), привязка по colindex.
// Правка data-ячейки на безголовом ValueTable — follow-up (edit-Tab-loop row-fill), здесь не тестируется.
// Правка data-ячейки на безголовом ValueTable (число/ссылка через edit-Tab-loop) — тоже покрыта:
// в режиме редактирования INPUT рендерится в оверлее вне .gridBox, colindex резолвится по
// x-координате относительно ячеек тела (grid-edit v1.2), иначе synth-имя Колонка{N} не матчилось.
export default async function({
navigateLink, clickElement, fillTableRow, readTable, getFormState, wait, assert, step, log, closeForm
@@ -65,6 +67,30 @@ export default async function({
assert.equal(r1['(checkbox)'], want, `клик переключил галку Позиция 003 в ${want}`);
});
await step('fillTableRow: правка числовой data-ячейки Колонка2 по индексу (method=direct)', async () => {
const r = await fillTableRow({ 'Колонка2': '777' }, { row: 1 });
log(`filled: ${JSON.stringify(r.filled)}`);
assert.ok(r.filled?.[0]?.ok && r.filled[0].method === 'direct', 'method=direct, ok');
const t = await readTable({ maxRows: 5 });
assert.ok(t.rows[1]['Колонка2'].startsWith('777'), `Колонка2 строки 1 = 777, got ${t.rows[1]['Колонка2']}`);
});
await step('fillTableRow: правка ссылочной data-ячейки Колонка1 по фильтру (выбор из списка)', async () => {
const r = await fillTableRow({ 'Колонка1': 'Позиция 001' }, { row: { 'Колонка1': 'Позиция 003' } });
log(`filled: ${JSON.stringify(r.filled)}`);
assert.ok(r.filled?.[0]?.ok, 'ok');
assert.ok(['dropdown', 'form'].includes(r.filled[0].method), `method dropdown|form, got ${r.filled[0].method}`);
const t = await readTable({ maxRows: 5 });
assert.equal(t.rows.filter(x => x['Колонка1'] === 'Позиция 001').length, 2, 'две строки Позиция 001 (была 001 + перезаписанная 003)');
});
await step('clickElement: клик по data-ячейке резолвит синтетическую колонку Колонка3', async () => {
const r = await clickElement({ row: { 'Колонка1': 'Позиция 002' }, column: 'Колонка3' });
log(`clicked: ${JSON.stringify(r.clicked)}`);
assert.equal(r.clicked?.kind, 'gridCell', 'клик по ячейке грида');
assert.equal(r.clicked?.column, 'Колонка3', 'резолвнутая колонка — синтетическая Колонка3');
});
// ── Марк-список (комбинированная ячейка галка+текст в одной .gridBox) ────────
await step('марк-список: readTable → (checkbox) + Колонка1, расщепление одной ячейки', async () => {
await navigateLink('Обработка.МножественныйВыбор');