feat(web-test): readTable отдаёт состояние строки по ведущей иконке

readTable матчил только спрайты pictureCollection (именованные pic-колонки), а
ведущая иконка состояния приходит из convertPicture?url=e1csys/<dir>/<file>.zip&gx=N
и молча дропалась. Проверить «помечен на удаление» можно было только выводом
колонки через «Настроить список» в каждом тесте.

Строка списка объектов теперь отдаёт плоские булевы _deleted / _posted /
_predefined / _completed / _started / _finished и сырьё _rowPic для диагностики.

Ключ словаря — ПОЛНЫЙ путь спрайта, не имя файла: basic/folder.zip и
accnt/folder.zip — разные файлы с одинаковым именем и разной раскладкой gx
(в basic gx=1 элемент, в accnt gx=1 предопределённый).

Отсутствие булева значит «не знаю», а не false: ось неприменима либо кадр не
расшифрован. Дефолт false отвергнут — врал бы молча в зелёную сторону.

Пути и раскладки сняты живьём на ERP; у Task/BusinessProcess раскладка сверена с
данными списка. Кадры 4/5 basic/folder.zip (второе измерение — иерархия
элементов) расшифрованы по байтовому равенству кадров: gx4 ≡ gx1, gx5 ≡ gx3.

Стенд: документы в заданных состояниях + помеченный элемент справочника +
безымянная picture-колонка ПЕРЕД значком состояния — воспроизводит ловушку
«первый .gridBoxImg не тот» (проверено подменой на наивный экстрактор).

Тест 22-row-state; полный регресс 27/27.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-16 20:59:17 +03:00
co-authored by Claude Opus 4.8
parent 115a966f0f
commit ad8a2e5cab
7 changed files with 312 additions and 3 deletions
+16 -2
View File
@@ -1,6 +1,7 @@
// web-test dom/grid v1.12 — grid resolution + table reading + edit-time helpers
// web-test dom/grid v1.13 — grid resolution + table reading + edit-time helpers
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import { ROW_CLICK_POINT_FN, HEADERLESS_GRID_FN } from './_shared.mjs';
import { ROW_STATE_FN } from './row-state.mjs';
/**
* Resolve a specific grid by semantic name (table parameter).
@@ -95,6 +96,16 @@ export function readTableScript(formNum, { maxRows = 20, offset = 0, gridSelecto
return { gx: m ? m[1] : '0' };
}
${HEADERLESS_GRID_FN}
${ROW_STATE_FN}
// Write the leading row-state sprite onto a row: _rowPic (raw, always) + decoded booleans
// (only when the sprite path AND frame are known — absence means "unknown", never false).
function applyRowState(row, line) {
const st = rowStateInfo(line);
if (!st) return;
row._rowPic = st.rowPic;
if (st.axes) Object.keys(st.axes).forEach(k => { row['_' + k] = st.axes[k]; });
}
// DOM-based parsing: gridHead → columns, gridBody → gridLine rows → gridBox cells
const head = grid.querySelector('.gridHead');
@@ -139,12 +150,13 @@ export function readTableScript(formNum, { maxRows = 20, offset = 0, gridSelecto
}
row[c.name] = val;
});
// Row meta — mirrors the headed path (group/parent/tree/level/selected)
// Row meta — mirrors the headed path (group/parent/tree/level/selected/state)
const imgBox = line.querySelector('.gridBoxImg');
if (imgBox) {
if (imgBox.querySelector('.gridListH')) row._kind = 'group';
else if (imgBox.querySelector('.gridListV')) row._kind = 'parent';
}
applyRowState(row, line);
const treeBox = line.querySelector('.gridBoxTree');
if (treeBox) {
const treeIcon = imgBox?.querySelector('[tree="true"]');
@@ -331,6 +343,8 @@ export function readTableScript(formNum, { maxRows = 20, offset = 0, gridSelecto
if (imgBox.querySelector('.gridListH')) row._kind = 'group';
else if (imgBox.querySelector('.gridListV')) row._kind = 'parent';
}
// Leading row-state sprite → _rowPic + decoded booleans
applyRowState(row, line);
// Tree mode: detect expand/collapse state and indent level
const treeBox = line.querySelector('.gridBoxTree');
if (treeBox) {