mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-02 09:47:45 +03:00
refactor(web-test): этап B.5.3 — detectNewForm хелпер (3 копии → 1)
В fillReferenceField, selectValue и fillTableRow была одна и та же логика:
сканировать DOM на наличие элемента с id="form{N}_*" где N > prevFormNum.
Две вариации: strict (только visible interactive — input.editInput/a.press)
и broad (любой [id], учитывает type-dialogs с пустыми button-id).
core/helpers.mjs: detectNewForm(prevFormNum, { strict }) → number|null.
Внутри функций оставлены тонкие локальные обёртки (для совместимости
с уже использующейся сигнатурой без аргументов) — будут убраны на C.8/D.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3fe038277f
commit
09b2084672
@@ -142,7 +142,10 @@ import {
|
|||||||
closeModals, checkForErrors, dismissPendingErrors, fetchErrorStack,
|
closeModals, checkForErrors, dismissPendingErrors, fetchErrorStack,
|
||||||
_detectPlatformDialogs, _closePlatformDialogs,
|
_detectPlatformDialogs, _closePlatformDialogs,
|
||||||
} from './core/errors.mjs';
|
} from './core/errors.mjs';
|
||||||
import { safeClick, findFieldInputId } from './core/helpers.mjs';
|
import {
|
||||||
|
safeClick, findFieldInputId,
|
||||||
|
detectNewForm as helperDetectNewForm,
|
||||||
|
} from './core/helpers.mjs';
|
||||||
// Re-export only what was publicly exported before the refactor.
|
// Re-export only what was publicly exported before the refactor.
|
||||||
// waitForStable/waitForCondition/startNetworkMonitor/closeModals/checkForErrors/
|
// waitForStable/waitForCondition/startNetworkMonitor/closeModals/checkForErrors/
|
||||||
// dismissPendingErrors are internal helpers — imported above for local use only.
|
// dismissPendingErrors are internal helpers — imported above for local use only.
|
||||||
@@ -1408,19 +1411,9 @@ async function fillReferenceField(selector, fieldName, value, formNum) {
|
|||||||
const text = String(value);
|
const text = String(value);
|
||||||
const escapedSel = selector.replace(/'/g, "\\'");
|
const escapedSel = selector.replace(/'/g, "\\'");
|
||||||
|
|
||||||
// Helper: detect new forms opened above the current one
|
// Helper: detect new forms opened above the current one (strict — interactive
|
||||||
async function detectNewForm() {
|
// elements only; fillReferenceField-specific)
|
||||||
return page.evaluate(`(() => {
|
const detectNewForm = () => helperDetectNewForm(formNum, { strict: true });
|
||||||
const forms = {};
|
|
||||||
document.querySelectorAll('input.editInput[id], a.press[id]').forEach(el => {
|
|
||||||
if (el.offsetWidth === 0) return;
|
|
||||||
const m = el.id.match(/^form(\\d+)_/);
|
|
||||||
if (m) forms[m[1]] = true;
|
|
||||||
});
|
|
||||||
const nums = Object.keys(forms).map(Number).filter(n => n > ${formNum});
|
|
||||||
return nums.length > 0 ? Math.max(...nums) : null;
|
|
||||||
})()`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper: clear the field using Shift+F4 (native 1C mechanism)
|
// Helper: clear the field using Shift+F4 (native 1C mechanism)
|
||||||
async function clearField() {
|
async function clearField() {
|
||||||
@@ -2290,20 +2283,9 @@ export async function selectValue(fieldName, searchText, { type } = {}) {
|
|||||||
})()`);
|
})()`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: detect any new form (broader than detectSelectionForm — also finds type dialogs
|
// Helper: detect any new form (broad — finds type dialogs whose a.press
|
||||||
// whose a.press buttons have empty IDs). Looks for any visible element with id="form{N}_*".
|
// buttons have empty IDs). Looks for any visible element with id="form{N}_*".
|
||||||
async function detectNewForm() {
|
const detectNewForm = () => helperDetectNewForm(formNum);
|
||||||
return page.evaluate(`(() => {
|
|
||||||
const forms = {};
|
|
||||||
document.querySelectorAll('[id]').forEach(el => {
|
|
||||||
if (el.offsetWidth === 0 && el.offsetHeight === 0) return;
|
|
||||||
const m = el.id.match(/^form(\\d+)_/);
|
|
||||||
if (m) forms[m[1]] = true;
|
|
||||||
});
|
|
||||||
const nums = Object.keys(forms).map(Number).filter(n => n > ${formNum});
|
|
||||||
return nums.length > 0 ? Math.max(...nums) : null;
|
|
||||||
})()`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper: open selection form and pick value
|
// Helper: open selection form and pick value
|
||||||
async function openFormAndPick() {
|
async function openFormAndPick() {
|
||||||
@@ -3496,16 +3478,7 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for a new form (broad detection — also catches type dialogs whose buttons lack IDs)
|
// Check for a new form (broad detection — also catches type dialogs whose buttons lack IDs)
|
||||||
const newForm = await page.evaluate(`(() => {
|
const newForm = await helperDetectNewForm(formNum);
|
||||||
const forms = {};
|
|
||||||
document.querySelectorAll('[id]').forEach(el => {
|
|
||||||
if (el.offsetWidth === 0 && el.offsetHeight === 0) return;
|
|
||||||
const m = el.id.match(/^form(\\d+)_/);
|
|
||||||
if (m) forms[m[1]] = true;
|
|
||||||
});
|
|
||||||
const nums = Object.keys(forms).map(Number).filter(n => n > ${formNum});
|
|
||||||
return nums.length > 0 ? Math.max(...nums) : null;
|
|
||||||
})()`);
|
|
||||||
|
|
||||||
if (newForm !== null) {
|
if (newForm !== null) {
|
||||||
if (await isTypeDialog(newForm)) {
|
if (await isTypeDialog(newForm)) {
|
||||||
|
|||||||
@@ -53,3 +53,33 @@ export async function findFieldInputId(formNum, fieldName) {
|
|||||||
return el ? el.id : null;
|
return el ? el.id : null;
|
||||||
})()`);
|
})()`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect a new form opened above the given `prevFormNum`. Two modes:
|
||||||
|
* `{ strict: true }` — only counts visible interactive elements
|
||||||
|
* (`input.editInput[id], a.press[id]`); used by fillReferenceField.
|
||||||
|
* default (broad) — any element with `id^=form{N}_` that's visible
|
||||||
|
* in either dimension; also finds type-dialogs whose a.press buttons
|
||||||
|
* have empty IDs. Used by selectValue / fillTableRow.
|
||||||
|
*
|
||||||
|
* @param {number} prevFormNum
|
||||||
|
* @param {object} [opts]
|
||||||
|
* @param {boolean} [opts.strict=false]
|
||||||
|
* @returns {Promise<number|null>} new form number or null
|
||||||
|
*/
|
||||||
|
export async function detectNewForm(prevFormNum, { strict = false } = {}) {
|
||||||
|
const selector = strict ? 'input.editInput[id], a.press[id]' : '[id]';
|
||||||
|
const visibleCheck = strict
|
||||||
|
? 'el.offsetWidth === 0'
|
||||||
|
: 'el.offsetWidth === 0 && el.offsetHeight === 0';
|
||||||
|
return page.evaluate(`(() => {
|
||||||
|
const forms = {};
|
||||||
|
document.querySelectorAll(${JSON.stringify(selector)}).forEach(el => {
|
||||||
|
if (${visibleCheck}) return;
|
||||||
|
const m = el.id.match(/^form(\\d+)_/);
|
||||||
|
if (m) forms[m[1]] = true;
|
||||||
|
});
|
||||||
|
const nums = Object.keys(forms).map(Number).filter(n => n > ${prevFormNum});
|
||||||
|
return nums.length > 0 ? Math.max(...nums) : null;
|
||||||
|
})()`);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user