mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-13 17:34:57 +03:00
refactor(web-test): replace fixed delays with smart waitForCondition polls
Add waitForCondition() utility — polls JS expression every 100ms with timeout fallback. Replace key fixed delays: - fillReferenceField paste: 2000ms → poll for EDD/cloud (max 2s) - fillTableRow add: 1000ms → poll for grid INPUT focus (max 2s) - fillTableRow cell paste: 1500ms → poll for EDD/value (max 1.5s) - fillTableRow Tab skip/commit: 300-1000ms → poll for focus change Benchmark: 31.8s vs 32.0s baseline — no measurable speedup because 1C backend response time (~1.5-2s for autocomplete) is the real bottleneck, not our delay calibration. Code is correct and will benefit from faster backends. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -214,6 +214,20 @@ async function waitForStable(previousFormNum = null) {
|
||||
// Fallback: max wait reached
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll until a JS expression returns truthy, or timeout (ms) expires.
|
||||
* Resolves early — typically within 100-300ms instead of fixed delays.
|
||||
*/
|
||||
async function waitForCondition(evalScript, timeout = 2000) {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeout) {
|
||||
const result = await page.evaluate(evalScript);
|
||||
if (result) return result;
|
||||
await page.waitForTimeout(100);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for validation errors / diagnostics after an action.
|
||||
* Detects: inline balloon tooltip, messages panel, modal error dialog.
|
||||
@@ -565,7 +579,18 @@ async function fillReferenceField(selector, fieldName, value, formNum) {
|
||||
// 3. Paste text via clipboard (trusted event → triggers real 1C autocomplete)
|
||||
await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`);
|
||||
await page.keyboard.press('Control+V');
|
||||
await page.waitForTimeout(2000);
|
||||
// Smart wait: poll for EDD dropdown or "not in list" cloud (max 2s)
|
||||
await waitForCondition(`(() => {
|
||||
const edd = document.getElementById('editDropDown');
|
||||
if (edd && edd.offsetWidth > 0) return true;
|
||||
for (const el of document.querySelectorAll('div')) {
|
||||
if (el.offsetWidth === 0) continue;
|
||||
const s = getComputedStyle(el);
|
||||
if ((s.position === 'absolute' || s.position === 'fixed') &&
|
||||
(parseInt(s.zIndex) || 0) >= 100 && (el.innerText || '').includes('нет в списке')) return true;
|
||||
}
|
||||
return false;
|
||||
})()`, ACTION_WAIT);
|
||||
|
||||
// 4. Check editDropDown for autocomplete suggestions
|
||||
const eddState = await page.evaluate(`(() => {
|
||||
@@ -1217,13 +1242,18 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
// 1. Switch tab if requested
|
||||
if (tab) {
|
||||
await clickElement(tab);
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
// 2. Add new row if requested
|
||||
if (add) {
|
||||
await clickElement('Добавить');
|
||||
await page.waitForTimeout(1000);
|
||||
// Smart wait: poll until an INPUT inside a grid gets focus
|
||||
await waitForCondition(`(() => {
|
||||
const f = document.activeElement;
|
||||
if (!f || f.tagName !== 'INPUT') return false;
|
||||
let n = f; while (n) { if (n.classList?.contains('grid')) return true; n = n.parentElement; }
|
||||
return false;
|
||||
})()`, ACTION_WAIT);
|
||||
}
|
||||
|
||||
// 2b. Enter edit mode on existing row by dblclick
|
||||
@@ -1343,9 +1373,10 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
}
|
||||
|
||||
if (!matchedKey) {
|
||||
// Skip this cell
|
||||
// Skip this cell — Tab + wait for focus to move
|
||||
const skipId = cell.id;
|
||||
await page.keyboard.press('Tab');
|
||||
await page.waitForTimeout(300);
|
||||
await waitForCondition(`document.activeElement?.id !== '${skipId}'`, 500);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1356,7 +1387,13 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
await page.keyboard.press('Control+A');
|
||||
await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`);
|
||||
await page.keyboard.press('Control+V');
|
||||
await page.waitForTimeout(1500);
|
||||
// Smart wait: poll for EDD dropdown (reference) or stable input value
|
||||
await waitForCondition(`(() => {
|
||||
const edd = document.getElementById('editDropDown');
|
||||
if (edd && edd.offsetWidth > 0) return true;
|
||||
const f = document.activeElement;
|
||||
return f && f.tagName === 'INPUT' && f.value && f.value.length > 0;
|
||||
})()`, 1500);
|
||||
|
||||
// Check for EDD autocomplete (indicates reference field)
|
||||
const eddItems = await page.evaluate(`(() => {
|
||||
@@ -1411,15 +1448,17 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
|
||||
// Done? If so, don't Tab (avoids creating a new row after last cell)
|
||||
if ([...pending.values()].every(p => p.filled)) break;
|
||||
// Tab to move to next cell
|
||||
// Tab to move to next cell — wait for focus to change
|
||||
const afterEddId = cell.id;
|
||||
await page.keyboard.press('Tab');
|
||||
await page.waitForTimeout(500);
|
||||
await waitForCondition(`document.activeElement?.id !== '${afterEddId}'`, 500);
|
||||
continue;
|
||||
}
|
||||
|
||||
// No EDD — press Tab to commit the value
|
||||
// No EDD — press Tab to commit the value, wait for focus change
|
||||
const commitId = cell.id;
|
||||
await page.keyboard.press('Tab');
|
||||
await page.waitForTimeout(1000);
|
||||
await waitForCondition(`document.activeElement?.id !== '${commitId}'`, 1000);
|
||||
|
||||
// Check for "нет в списке" cloud popup (reference field, value not found)
|
||||
const notInList = await page.evaluate(`(() => {
|
||||
|
||||
Reference in New Issue
Block a user