mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-19 17:19:42 +03:00
refactor(web-test): вынести error-stack scraping в dom/errors-stack.mjs (S8)
5 inline page.evaluate блоков (~50 LOC) из fetchStackViaReport (path-1 OpenReport flow платформенных исключений) → новый dom/errors-stack.mjs с 5 экспортами: getOpenReportCoordsScript, isErrorDetailLinkVisibleScript, readLargestVisibleTextareaScript, clickTopCloudOkButtonScript, clickReportCloseButtonScript. Engine-сторона fetchStackViaReport теперь читается как чистый оркестратор 6 шагов без длинных DOM-строк. Поведение 1:1. DOM-extraction iter 2 / S8 из плана. Точечный регресс 14-errors-stack зелёный. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
// web-test dom/errors-stack v1.0 — DOM scripts for fetching error stack via OpenReport link.
|
||||||
|
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
//
|
||||||
|
// Path-1 flow for platform exceptions: click "Сформировать отчет об ошибке" link,
|
||||||
|
// open detailed error dialog, read textarea, close cleanup dialogs.
|
||||||
|
|
||||||
|
/** Find OpenReport link coordinates on the error modal for given formNum. */
|
||||||
|
export function getOpenReportCoordsScript(formNum) {
|
||||||
|
return `(() => {
|
||||||
|
const el = document.getElementById('form${formNum}_OpenReport#text');
|
||||||
|
if (!el || el.offsetWidth <= 2) return null;
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
||||||
|
})()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check whether the "подробный текст ошибки" link is visible (signals report dialog ready). */
|
||||||
|
export function isErrorDetailLinkVisibleScript() {
|
||||||
|
return `(() => {
|
||||||
|
const links = document.querySelectorAll('a, [class*="hyper"], span');
|
||||||
|
for (const el of links) {
|
||||||
|
if (el.offsetWidth > 0 && el.textContent.includes('подробный текст ошибки')) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read the largest visible non-empty textarea — contains the detailed error stack. */
|
||||||
|
export function readLargestVisibleTextareaScript() {
|
||||||
|
return `(() => {
|
||||||
|
let best = null;
|
||||||
|
document.querySelectorAll('textarea').forEach(ta => {
|
||||||
|
if (ta.offsetWidth > 0 && ta.value.length > 0) {
|
||||||
|
if (!best || ta.value.length > best.value.length) best = ta;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return best?.value || null;
|
||||||
|
})()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Click the OK button in the topmost cloud window (closes "Подробный текст ошибки"). */
|
||||||
|
export function clickTopCloudOkButtonScript() {
|
||||||
|
return `(() => {
|
||||||
|
const psWins = [...document.querySelectorAll('[id^="ps"][id$="win"]')]
|
||||||
|
.filter(w => w.offsetWidth > 0)
|
||||||
|
.sort((a, b) => parseInt(b.style?.zIndex || '0') - parseInt(a.style?.zIndex || '0'));
|
||||||
|
for (const w of psWins) {
|
||||||
|
const ok = w.querySelector('button.webBtn, .pressDefault');
|
||||||
|
if (ok && ok.textContent.trim() === 'OK') { ok.click(); return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Click the × CloseButton in the topmost visible cloud window (closes "Отчет об ошибке"). */
|
||||||
|
export function clickReportCloseButtonScript() {
|
||||||
|
return `(() => {
|
||||||
|
const psWins = [...document.querySelectorAll('[id^="ps"][id$="win"]')]
|
||||||
|
.filter(w => w.offsetWidth > 0);
|
||||||
|
for (const w of psWins) {
|
||||||
|
const closeBtn = w.querySelector('[id$="_cmd_CloseButton"]');
|
||||||
|
if (closeBtn && closeBtn.offsetWidth > 0) { closeBtn.click(); break; }
|
||||||
|
}
|
||||||
|
})()`;
|
||||||
|
}
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
// web-test core/errors v1.17 — Error/modal/platform-dialog handling: dismiss, detect, fetch stack from 1C UI.
|
// web-test core/errors v1.18 — Error/modal/platform-dialog handling: dismiss, detect, fetch stack from 1C UI.
|
||||||
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import { page } from './state.mjs';
|
import { page } from './state.mjs';
|
||||||
import { checkErrorsScript } from '../../dom.mjs';
|
import { checkErrorsScript } from '../../dom.mjs';
|
||||||
|
import {
|
||||||
|
getOpenReportCoordsScript, isErrorDetailLinkVisibleScript,
|
||||||
|
readLargestVisibleTextareaScript, clickTopCloudOkButtonScript,
|
||||||
|
clickReportCloseButtonScript,
|
||||||
|
} from '../../dom/errors-stack.mjs';
|
||||||
import { waitForStable } from './wait.mjs';
|
import { waitForStable } from './wait.mjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -205,12 +210,7 @@ export async function fetchErrorStack(formNum, hasReport) {
|
|||||||
*/
|
*/
|
||||||
async function fetchStackViaReport(formNum) {
|
async function fetchStackViaReport(formNum) {
|
||||||
// 1. Get coordinates of the OpenReport link and click via mouse (modalSurface blocks JS clicks)
|
// 1. Get coordinates of the OpenReport link and click via mouse (modalSurface blocks JS clicks)
|
||||||
const coords = await page.evaluate((fn) => {
|
const coords = await page.evaluate(getOpenReportCoordsScript(formNum));
|
||||||
const el = document.getElementById('form' + fn + '_OpenReport#text');
|
|
||||||
if (!el || el.offsetWidth <= 2) return null;
|
|
||||||
const rect = el.getBoundingClientRect();
|
|
||||||
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
|
||||||
}, formNum);
|
|
||||||
if (!coords) return null;
|
if (!coords) return null;
|
||||||
|
|
||||||
await page.mouse.click(coords.x, coords.y);
|
await page.mouse.click(coords.x, coords.y);
|
||||||
@@ -219,13 +219,7 @@ async function fetchStackViaReport(formNum) {
|
|||||||
let found = false;
|
let found = false;
|
||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
found = await page.evaluate(() => {
|
found = await page.evaluate(isErrorDetailLinkVisibleScript());
|
||||||
const links = document.querySelectorAll('a, [class*="hyper"], span');
|
|
||||||
for (const el of links) {
|
|
||||||
if (el.offsetWidth > 0 && el.textContent.includes('подробный текст ошибки')) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (found) break;
|
if (found) break;
|
||||||
}
|
}
|
||||||
if (!found) return null;
|
if (!found) return null;
|
||||||
@@ -235,42 +229,17 @@ async function fetchStackViaReport(formNum) {
|
|||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// 4. Read the textarea with detailed error text (find the largest visible textarea)
|
// 4. Read the textarea with detailed error text (find the largest visible textarea)
|
||||||
const raw = await page.evaluate(() => {
|
const raw = await page.evaluate(readLargestVisibleTextareaScript());
|
||||||
let best = null;
|
|
||||||
document.querySelectorAll('textarea').forEach(ta => {
|
|
||||||
if (ta.offsetWidth > 0 && ta.value.length > 0) {
|
|
||||||
if (!best || ta.value.length > best.value.length) best = ta;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return best?.value || null;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 5. Close "Подробный текст ошибки" dialog (click its OK button)
|
// 5. Close "Подробный текст ошибки" dialog (click its OK button)
|
||||||
try {
|
try {
|
||||||
const okBtn = await page.evaluate(() => {
|
await page.evaluate(clickTopCloudOkButtonScript());
|
||||||
// Find the OK button in the topmost small cloud window
|
|
||||||
const psWins = [...document.querySelectorAll('[id^="ps"][id$="win"]')]
|
|
||||||
.filter(w => w.offsetWidth > 0)
|
|
||||||
.sort((a, b) => parseInt(b.style?.zIndex || '0') - parseInt(a.style?.zIndex || '0'));
|
|
||||||
for (const w of psWins) {
|
|
||||||
const ok = w.querySelector('button.webBtn, .pressDefault');
|
|
||||||
if (ok && ok.textContent.trim() === 'OK') { ok.click(); return true; }
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
// 6. Close "Отчет об ошибке" dialog (click its × close button)
|
// 6. Close "Отчет об ошибке" dialog (click its × close button)
|
||||||
try {
|
try {
|
||||||
await page.evaluate(() => {
|
await page.evaluate(clickReportCloseButtonScript());
|
||||||
const psWins = [...document.querySelectorAll('[id^="ps"][id$="win"]')]
|
|
||||||
.filter(w => w.offsetWidth > 0);
|
|
||||||
for (const w of psWins) {
|
|
||||||
const closeBtn = w.querySelector('[id$="_cmd_CloseButton"]');
|
|
||||||
if (closeBtn && closeBtn.offsetWidth > 0) { closeBtn.click(); break; }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user