refactor(web-test): извлечён EDD-домен в dom/edd.mjs

Новое в dom/edd.mjs:
- readEddScript                  — {visible, items:[{name,x,y}]}
- isEddVisibleScript             — boolean, лёгкая проверка
- clickEddItemViaDispatchScript  — клик по name через dispatchEvent (bypass
                                   div.surface); fuzzy с NBSP/ё/bracket-strip
- clickShowAllInEddScript        — "Показать все" в footer

Wrappers в helpers.mjs: readEdd, isEddVisible, clickEddItemViaDispatch,
clickShowAllInEdd. row-fill clickEddItem унифицирован с select-value
вариантом (NBSP/ё normalization теперь работает и для табличных строк).

Метрики: select-value 880 → 827 LOC (−53), row-fill 1065 → 1041 LOC
(−24); evaluates row-fill 20 → 17, select-value 7 → 5. Полный регресс
зелёный.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-05-26 20:57:58 +03:00
co-authored by Claude Opus 4.7
parent 340142b0a2
commit 89efcad125
5 changed files with 155 additions and 100 deletions
@@ -14,6 +14,7 @@ import {
safeClick, findFieldInputId,
detectNewForm as helperDetectNewForm,
isInputFocused, isInputFocusedInGrid, findOpenPopup,
readEdd, isEddVisible, clickEddItemViaDispatch,
} from '../core/helpers.mjs';
import { clickElement } from '../core/click.mjs';
import {
@@ -427,11 +428,7 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
await pasteText(info.value, { confirm: ['Control+a', 'Control+v'] });
await page.waitForTimeout(400);
// Dismiss EDD autocomplete if it appeared
const hasEdd = await page.evaluate(`(() => {
const edd = document.getElementById('editDropDown');
return edd && edd.offsetWidth > 0;
})()`);
if (hasEdd) {
if (await isEddVisible()) {
await page.keyboard.press('Escape');
await page.waitForTimeout(200);
}
@@ -741,13 +738,8 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
}
// Check for EDD autocomplete (indicates reference field)
const eddItems = await page.evaluate(`(() => {
const edd = document.getElementById('editDropDown');
if (!edd || edd.offsetWidth === 0) return null;
return [...edd.querySelectorAll('.eddText')]
.filter(el => el.offsetWidth > 0)
.map(el => el.innerText?.trim() || '');
})()`);
const edd = await readEdd();
const eddItems = edd.visible ? edd.items.map(i => i.name) : null;
if (eddItems && eddItems.length > 0) {
// Reference field with autocomplete — click best match
@@ -763,23 +755,7 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
if (!pick) pick = realItems[0];
// Click EDD item via dispatchEvent (bypasses div.surface overlay)
const pickLower = pick.toLowerCase();
await page.evaluate(`(() => {
const edd = document.getElementById('editDropDown');
if (!edd) return;
for (const el of edd.querySelectorAll('.eddText')) {
if (el.offsetWidth === 0) continue;
if (el.innerText.trim().toLowerCase().includes(${JSON.stringify(pickLower)})) {
const r = el.getBoundingClientRect();
const opts = { bubbles:true, cancelable:true,
clientX: r.x + r.width/2, clientY: r.y + r.height/2 };
el.dispatchEvent(new MouseEvent('mousedown', opts));
el.dispatchEvent(new MouseEvent('mouseup', opts));
el.dispatchEvent(new MouseEvent('click', opts));
return;
}
}
})()`);
await clickEddItemViaDispatch(pick);
await waitForStable();
info.filled = true;
results.push({ field: matchedKey, cell: cell.fullName, ok: true,