test(web-test): расширить 18-cell-click — reveal-loop, horizontal scroll, skip-checkbox

3 новых шага на расширенном стенде (LongDoc + 18-колоночная ТЧ):

1. reveal-loop — открыть LongDoc через filterList по Комментарий, ТЧ Товары
   виртуализирована (13 строк в окне из 30). Клик с scroll:true по строке
   с Количество=25,000 — должен пролистать PageDown'ом до окна 20..30.

2. horizontal scroll туда-обратно — клик в Признак контроля (последняя,
   18-я колонка, ArrowRight scroll), потом сразу в Количество (2-я колонка,
   ArrowLeft scroll). Проверяет оба направления.

3. focus-click skip checkbox — кластер ВРезерве/НаКомиссии/Подарок у правого
   края дефолтного viewport. Клик в Серия (за пределами viewport) должен
   вызвать ArrowRight scroll с focus-pick на rightmost non-checkbox cell.
   Проверка: boolean'ы в строке 0 не изменились после клика.

Удалил устаревший Note про "перенесём на будущее" — теперь покрыто.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-05-29 12:12:25 +03:00
parent 0e5ad754e8
commit 80323a77cc
+95 -8
View File
@@ -1,10 +1,10 @@
export const name = 'clickElement({row, column}): cell click on grids + spreadsheet backward-compat';
export const tags = ['cell-click', 'smoke'];
export const timeout = 120000;
export const timeout = 180000;
export default async function({
navigateSection, navigateLink, openCommand, clickElement, fillFields, fillTableRow,
readTable, readSpreadsheet, closeForm, getFormState, wait, assert, step, log
filterList, readTable, readSpreadsheet, closeForm, getFormState, wait, assert, step, log
}) {
// ── Spreadsheet backward-compat ─────────────────────────────────────────────
@@ -117,13 +117,100 @@ export default async function({
'Сообщение объясняет про виртуализацию / DOM window');
});
// ── Cleanup ────────────────────────────────────────────────────────────────
await step('cleanup: close document', async () => {
// ── Cleanup the 2-row doc before opening LongDoc ───────────────────────────
await step('cleanup: close 2-row document', async () => {
await closeForm({ save: false });
});
// Note: reveal-loop (scroll:true) algorithm verified manually on bp-demo
// (catalog Контрагенты, group Покупатели, ~22 items requiring page-down).
// The synthetic stand has issues with rapid sequential doc opens that prevent
// a stable >30-row table setup here — left for a future enhancement of _hooks.
// ── Open LongDoc (30 rows in tabular section, fixtures from ЗаполнитьДокументы) ──
await step('setup: open LongDoc (30-row tabular section)', async () => {
await navigateSection('Склад');
await openCommand('Приходная накладная');
await filterList('LongDoc', { field: 'Комментарий' });
// Открываем единственный найденный LongDoc (фикстура создаётся один раз
// при первом запуске базы — даже после многократных прогонов одна штука).
const t = await readTable();
assert.ok(t.rows?.length >= 1, 'LongDoc должен быть в списке');
const num = t.rows[0]['Номер'];
await clickElement(num, { dblclick: true });
await wait(2);
const f = await getFormState();
assert.equal(f.tables?.[0]?.name, 'Товары', 'Открыта форма документа с ТЧ Товары');
});
// ── Reveal-loop: filter row not in current DOM window, scroll:true разворачивает ──
await step('reveal-loop: scroll:true находит строку Количество=25 в LongDoc', async () => {
const tBefore = await readTable({ table: 'Товары', maxRows: 100 });
log(`loaded=${tBefore.rows.length} hasMore=${JSON.stringify(tBefore.hasMore)}`);
assert.ok(tBefore.hasMore?.below === true || tBefore.rows.length >= 20,
'LongDoc виртуализирован или загружено достаточно строк');
// Целевая Количество=25 — заведомо глубоко в списке (LongDoc заполняет 1..30).
const res = await clickElement(
{ row: { 'Количество': '25,000' }, column: 'Сумма' },
{ table: 'Товары', scroll: true }
);
log(`reveal clicked: ${JSON.stringify(res.clicked)}`);
assert.equal(res.clicked?.kind, 'gridCell', 'reveal-loop нашёл строку');
assert.equal(res.clicked?.column, 'Сумма', 'column сохранён');
});
// ── Horizontal scroll: вправо до последней колонки, потом обратно влево ────
await step('horizontal scroll: вправо до Признак контроля, потом влево к Количество', async () => {
const right = await clickElement(
{ row: 0, column: 'Признак контроля' },
{ table: 'Товары' }
);
log(`right click: ${JSON.stringify(right.clicked)}`);
assert.equal(right.clicked?.kind, 'gridCell', 'kind=gridCell для правой');
assert.equal(right.clicked?.column, 'Признак контроля', 'добрались до самой правой колонки');
// Теперь обратно к Количество — направление ArrowLeft, scroll сдвигает viewport влево.
const left = await clickElement(
{ row: 0, column: 'Количество' },
{ table: 'Товары' }
);
log(`left click: ${JSON.stringify(left.clicked)}`);
assert.equal(left.clicked?.kind, 'gridCell', 'kind=gridCell для левой');
assert.equal(left.clicked?.column, 'Количество', 'вернулись к Количество через ArrowLeft scroll');
});
// ── Focus-click skip checkbox: cluster booleans on right edge, click further right ──
await step('focus-click пропускает checkbox-ячейки при выборе focus-точки', async () => {
// После предыдущего шага viewport уехал вправо. Нужно сбросить — выходим из ТЧ
// и заходим заново через клик на Контрагент (вне грида).
await fillFields({ 'Комментарий': 'LongDoc' }); // вернёт к дефолтному viewport
await wait(0.3);
const before = await readTable({ table: 'Товары', maxRows: 5 });
const bools0 = {
ВРезерве: before.rows[0]['В резерве'],
НаКомиссии: before.rows[0]['На комиссии'],
Подарок: before.rows[0]['Подарок'],
};
log(`booleans before: ${JSON.stringify(bools0)}`);
// Клик в дальнюю колонку «Серия» — focus-pick должен выбрать самую правую
// видимую non-frozen non-checkbox ячейку. При дефолтном viewport кластер
// из 3 boolean (ВРезерве/НаКомиссии/Подарок) на правом крае — pick должен
// их пропустить и взять Источник (reference, левее cluster).
const res = await clickElement(
{ row: 0, column: 'Серия' },
{ table: 'Товары' }
);
log(`clicked: ${JSON.stringify(res.clicked)}`);
assert.equal(res.clicked?.kind, 'gridCell', 'клик на Серия (после горизонтального скролла)');
// Главное: booleans в строке 0 НЕ изменились — focus-click не задел чекбоксы.
const after = await readTable({ table: 'Товары', maxRows: 5 });
const bools1 = {
ВРезерве: after.rows[0]['В резерве'],
НаКомиссии: after.rows[0]['На комиссии'],
Подарок: after.rows[0]['Подарок'],
};
log(`booleans after: ${JSON.stringify(bools1)}`);
assert.equal(bools1.ВРезерве, bools0.ВРезерве, 'ВРезерве не переключилось');
assert.equal(bools1.НаКомиссии, bools0.НаКомиссии, 'НаКомиссии не переключилось');
assert.equal(bools1.Подарок, bools0.Подарок, 'Подарок не переключилось');
});
// ── Final cleanup ──────────────────────────────────────────────────────────
await step('cleanup: close LongDoc', async () => {
await closeForm({ save: false });
});
}