test(web-test): M4.C+D — drill-down + submenu-read

11-report/drill-down: dblclick по ячейке Номенклатуры сформированного
DCS-отчёта открывает форму элемента (DCS auto-drill). После Сформировать
ищется первая строка с заполненной номенклатурой, проверяется что после
clickElement({row,column},{dblclick:true}) form изменился и есть кнопка
«Записать».

02-crud/more-menu усилен под P2 submenu-read: добавлены явные проверки
clicked.kind='submenu', наличия типовых пунктов «Создать», «Изменить»,
«Расширенный поиск» (length>=5).

Покрыто 2 P2-кейса coverage matrix (11-report/drill-down,
02-crud/submenu-read). Полный регресс 14/14 зелёный (7m 1.6s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-05-11 16:58:28 +03:00
parent 91b39b758b
commit 211a4726d6
2 changed files with 29 additions and 2 deletions
+6 -2
View File
@@ -92,14 +92,18 @@ export default async function({ navigateSection, openCommand, clickElement, clos
await closeForm({ save: false });
});
await step('more-menu: clickElement("Ещё") возвращает submenu[]', async () => {
await step('more-menu / submenu-read: clickElement("Ещё") возвращает submenu[] с типовыми пунктами', async () => {
await navigateSection('Склад');
await openCommand('Контрагенты');
const r = await clickElement('Ещё');
const items = r.submenu || [];
log(`submenu items: ${items.length} sample=${items.slice(0, 5).join(', ')}`);
assert.equal(r.clicked?.kind, 'submenu', 'clicked.kind=submenu');
assert.ok(Array.isArray(r.submenu), 'clickElement("Ещё") должен вернуть submenu[]');
assert.ok(items.length >= 1, 'submenu не должен быть пустым');
assert.ok(items.length >= 5, `submenu должен содержать типовые пункты (got ${items.length})`);
assert.includes(items, 'Создать', 'пункт «Создать»');
assert.includes(items, 'Изменить', 'пункт «Изменить»');
assert.includes(items, 'Расширенный поиск', 'пункт «Расширенный поиск»');
// Закрыть submenu
const page = await getPage();
await page.keyboard.press('Escape');
+23
View File
@@ -95,6 +95,29 @@ export default async function({ navigateSection, openCommand, getFormState, getC
assert.equal(report.totals['Сумма'], baseTotalSum, 'Восстановился исходный итог по Сумме');
});
await step('drill-down: dblclick по ячейке Номенклатура открывает форму элемента', async () => {
// Сформируем отчёт ещё раз для чистого состояния
await clickElement('Сформировать');
await wait(3);
const r = await readSpreadsheet();
const namedIdx = r.data.findIndex(row => row['Номенклатура']);
log(`first row with Номенклатура: idx=${namedIdx} value=${r.data[namedIdx]?.['Номенклатура']}`);
assert.ok(namedIdx >= 0, 'есть строка с заполненной Номенклатурой');
const beforeForm = await getFormState();
const clicked = await clickElement({ row: namedIdx, column: 'Номенклатура' }, { dblclick: true });
log(`clicked: ${JSON.stringify(clicked.clicked)}`);
assert.equal(clicked.clicked?.kind, 'spreadsheetCell', 'clicked.kind=spreadsheetCell');
await wait(1);
const after = await getFormState();
log(`after drill: form=${after.form} buttons=${after.buttons?.map(b => b.name).join(',')}`);
assert.notEqual(after.form, beforeForm.form, 'открыта новая форма (form изменился)');
const hasItemButton = after.buttons?.some(b => b.name === 'Записать и закрыть' || b.name === 'Записать');
assert.ok(hasItemButton, 'открыта форма элемента (есть «Записать»)');
await closeForm();
});
await step('cleanup: закрываем форму отчёта', async () => {
const r = await closeForm();
log(`closed=${r.closed} formCount=${r.formCount}`);