mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-09 04:53:20 +03:00
fix(web-test): improve modal detection, surface retry, search regex
- detectFormScript: lower modal threshold from >=2 to >=1 visible elements - clickElement: force:true on third retry when surface overlay persists - filterList/unfilterList: add SearchString pattern for selection forms - fillTableRow: wrap body in try/catch for structured error returns - SKILL.md: add keyboard shortcuts reference (F8, Shift+F4, F4, Alt+F) - gitignore: exclude *.png screenshot artifacts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
c8f58b5461
commit
68e346d645
@@ -202,6 +202,15 @@ Hint: if `readTable()` returns `hierarchical: true`, the list has groups.
|
||||
|
||||
`closeForm()` is preferred over `clickElement('×')` — close buttons on tabs are ambiguous.
|
||||
|
||||
### Keyboard shortcuts
|
||||
|
||||
| Key | Context | Action |
|
||||
|-----|---------|--------|
|
||||
| `F8` | Reference field focused | Open creation form for the field's catalog |
|
||||
| `Shift+F4` | Reference field focused | Clear field value |
|
||||
| `F4` | Reference field focused | Open selection form |
|
||||
| `Alt+F` | List/table form | Open advanced search dialog |
|
||||
|
||||
### Submenu navigation
|
||||
|
||||
```js
|
||||
|
||||
@@ -916,7 +916,16 @@ export async function clickElement(text, { dblclick } = {}) {
|
||||
if (clickErr.message.includes('intercepts pointer events')) {
|
||||
await page.keyboard.press('Escape');
|
||||
await page.waitForTimeout(500);
|
||||
await page.click(selector, { timeout: 5000 });
|
||||
try {
|
||||
await page.click(selector, { timeout: 5000 });
|
||||
} catch (clickErr2) {
|
||||
if (clickErr2.message.includes('intercepts pointer events')) {
|
||||
// Persistent surface (e.g. grid editing overlay) — force click
|
||||
await page.click(selector, { force: true, timeout: 5000 });
|
||||
} else {
|
||||
throw clickErr2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw clickErr;
|
||||
}
|
||||
@@ -1204,6 +1213,7 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
const formNum = await page.evaluate(detectFormScript());
|
||||
if (formNum === null) return { error: 'no_form' };
|
||||
|
||||
try {
|
||||
// 1. Switch tab if requested
|
||||
if (tab) {
|
||||
await clickElement(tab);
|
||||
@@ -1548,6 +1558,11 @@ export async function fillTableRow(fields, { tab, add, row } = {}) {
|
||||
if (notFilled.length > 0) result.notFilled = notFilled;
|
||||
result.form = formData;
|
||||
return result;
|
||||
|
||||
} catch (e) {
|
||||
const form = await getFormState().catch(() => null);
|
||||
return { error: 'fillTableRow_failed', message: e.message, form };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1636,7 +1651,7 @@ export async function filterList(text, { field, exact } = {}) {
|
||||
const searchId = await page.evaluate(`(() => {
|
||||
const p = 'form${formNum}_';
|
||||
const el = [...document.querySelectorAll('input.editInput[id^="' + p + '"]')]
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска/i.test(el.id));
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска|SearchString/i.test(el.id));
|
||||
return el ? el.id : null;
|
||||
})()`);
|
||||
if (!searchId) return { error: 'no_search_field', message: 'No search input found on this form' };
|
||||
@@ -1947,7 +1962,7 @@ export async function unfilterList({ field } = {}) {
|
||||
const searchInfo = await page.evaluate(`(() => {
|
||||
const p = 'form${formNum}_';
|
||||
const el = [...document.querySelectorAll('input.editInput[id^="' + p + '"]')]
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска/i.test(el.id));
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска|SearchString/i.test(el.id));
|
||||
return el ? { id: el.id, value: el.value || '' } : null;
|
||||
})()`);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ const DETECT_FORM_FN = `function detectForm() {
|
||||
const modal = document.getElementById('modalSurface');
|
||||
if (modal && modal.offsetWidth > 0) {
|
||||
const maxForm = Math.max(...candidates);
|
||||
if (counts[maxForm] >= 2) return maxForm;
|
||||
if (counts[maxForm] >= 1) return maxForm;
|
||||
}
|
||||
return candidates.reduce((best, n) => counts[n] > counts[best] ? n : best);
|
||||
}`;
|
||||
@@ -214,7 +214,7 @@ const READ_FORM_FN = `function readForm(p) {
|
||||
});
|
||||
// Also check search field value
|
||||
const searchInput = [...document.querySelectorAll('input.editInput[id^="' + p + '"]')]
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска/i.test(el.id));
|
||||
.find(el => el.offsetWidth > 0 && /Строк[аи]Поиска|SearchString/i.test(el.id));
|
||||
if (searchInput?.value) {
|
||||
filters.push({ type: 'search', value: searchInput.value });
|
||||
}
|
||||
|
||||
+4
-1
@@ -19,6 +19,9 @@ tools/
|
||||
# Локальный реестр баз данных 1С
|
||||
.v8-project.json
|
||||
|
||||
# web-test: Node.js зависимости и runtime
|
||||
# web-test: Node.js зависимости и runtime-артефакты
|
||||
.claude/skills/web-test/scripts/node_modules/
|
||||
.claude/skills/web-test/.browser-session.json
|
||||
|
||||
# Скриншоты (артефакты тестирования web-test)
|
||||
*.png
|
||||
|
||||
Reference in New Issue
Block a user