skopix 2.0.20 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/commands/agent.js +15 -6
- package/package.json +1 -1
package/cli/commands/agent.js
CHANGED
|
@@ -361,10 +361,11 @@ export async function agentCommand(options) {
|
|
|
361
361
|
await page.waitForTimeout(800);
|
|
362
362
|
|
|
363
363
|
} else if (step.action === 'click') {
|
|
364
|
+
await page.waitForTimeout(300);
|
|
364
365
|
let clicked = false;
|
|
365
366
|
const selectors = [step.stableSelector, step.selector].filter(Boolean).map(sanitiseSelector);
|
|
366
|
-
//
|
|
367
|
-
if (step.elementX || step.clickX) {
|
|
367
|
+
// Strategy 1: coordinate-based (best for duplicate elements)
|
|
368
|
+
if (!clicked && (step.elementX || step.clickX)) {
|
|
368
369
|
const tx = step.elementX || step.clickX, ty = step.elementY || step.clickY;
|
|
369
370
|
for (const s of selectors) {
|
|
370
371
|
if (clicked) break;
|
|
@@ -375,17 +376,25 @@ export async function agentCommand(options) {
|
|
|
375
376
|
for (let i = 0; i < count; i++) { try { const box = await page.locator(s).nth(i).boundingBox({ timeout: 2000 }); if (!box) continue; const d = Math.sqrt(Math.pow(box.x+box.width/2-tx,2)+Math.pow(box.y+box.height/2-ty,2)); if (d < bd) { bd=d; bi=i; } } catch {} }
|
|
376
377
|
await page.locator(s).nth(bi).click({ timeout: 5000 }); clicked = true;
|
|
377
378
|
} else if (count === 1) {
|
|
379
|
+
await page.locator(s).first().waitFor({ state: 'visible', timeout: 3000 });
|
|
378
380
|
await page.locator(s).first().click({ timeout: 5000 }); clicked = true;
|
|
379
381
|
}
|
|
380
382
|
} catch {}
|
|
381
383
|
}
|
|
382
384
|
}
|
|
383
|
-
//
|
|
384
|
-
if (!clicked) { for (const s of selectors) { if (clicked) break; try { await page.locator(s).first().click({ timeout: 5000 }); clicked = true; } catch {} } }
|
|
385
|
-
//
|
|
385
|
+
// Strategy 2: normal click
|
|
386
|
+
if (!clicked) { for (const s of selectors) { if (clicked) break; try { await page.locator(s).first().waitFor({ state: 'visible', timeout: 3000 }); await page.locator(s).first().click({ timeout: 5000 }); clicked = true; } catch {} } }
|
|
387
|
+
// Strategy 3: force click
|
|
386
388
|
if (!clicked) { for (const s of selectors) { if (clicked) break; try { await page.locator(s).first().click({ force: true, timeout: 5000 }); clicked = true; } catch {} } }
|
|
389
|
+
// Strategy 4: click clickable ancestor (for icons/SVGs)
|
|
390
|
+
if (!clicked && step.element) {
|
|
391
|
+
const tag = (step.element.tag || '').toLowerCase();
|
|
392
|
+
if (['i', 'svg', 'path', 'span', 'img'].includes(tag)) {
|
|
393
|
+
for (const s of selectors) { if (clicked) break; try { await page.locator(s).first().locator('xpath=ancestor-or-self::*[self::a or self::button or @role="button"][1]').first().click({ timeout: 5000 }); clicked = true; } catch {} }
|
|
394
|
+
}
|
|
395
|
+
}
|
|
387
396
|
if (!clicked) throw new Error('Could not click: ' + selectors.join(', '));
|
|
388
|
-
await page.waitForTimeout(
|
|
397
|
+
await page.waitForTimeout(500);
|
|
389
398
|
|
|
390
399
|
} else if (step.action === 'type') {
|
|
391
400
|
await page.locator(sel).first().click({ timeout: 5000 });
|
package/package.json
CHANGED