implement wait_for_xpath function to enhance XPath handling in interactions_service, ensuring proper validation and timeout management
Build and Push Docker Images / build-and-push (push) Successful in 22s

This commit is contained in:
2026-04-29 16:29:52 +02:00
parent be4719fe01
commit 9aa863f42d
+30 -4
View File
@@ -307,6 +307,27 @@ async def interactions_service(
if not action: if not action:
raise ValueError("Interaction must contain an action") raise ValueError("Interaction must contain an action")
async def wait_for_xpath(xp: str, timeout_ms: int = 30000) -> None:
# Accept both raw XPath ("//div") and Playwright-style ("xpath=//div").
normalized = xp[len("xpath=") :] if xp.startswith("xpath=") else xp
await page.wait_for_function(
"""(xpath) => {
try {
return !!document.evaluate(
xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;
} catch (e) {
return false;
}
}""",
normalized,
timeout=timeout_ms,
)
# Prefer selector-based interactions when selectors are provided (CSS first, then XPath). # Prefer selector-based interactions when selectors are provided (CSS first, then XPath).
if selector or xpath_selector: if selector or xpath_selector:
if action == "click": if action == "click":
@@ -322,7 +343,9 @@ async def interactions_service(
selector, selector,
) )
else: else:
await page.wait_for_selector(f"xpath={xpath_selector}", timeout=30000) if not xpath_selector:
raise ValueError("xpath_selector must be a non-empty string")
await wait_for_xpath(xpath_selector, timeout_ms=30000)
await page.evaluate( await page.evaluate(
"""(xpath) => { """(xpath) => {
const el = document.evaluate( const el = document.evaluate(
@@ -335,7 +358,7 @@ async def interactions_service(
if (!el) throw new Error(`No element for xpath: ${xpath}`); if (!el) throw new Error(`No element for xpath: ${xpath}`);
el.click(); el.click();
}""", }""",
xpath_selector, xpath_selector[len("xpath=") :] if xpath_selector.startswith("xpath=") else xpath_selector,
) )
elif action == "type": elif action == "type":
@@ -358,7 +381,10 @@ async def interactions_service(
{"sel": selector, "value": text}, {"sel": selector, "value": text},
) )
else: else:
await page.wait_for_selector(f"xpath={xpath_selector}", timeout=30000) if not xpath_selector:
raise ValueError("xpath_selector must be a non-empty string")
await wait_for_xpath(xpath_selector, timeout_ms=30000)
normalized_xpath = xpath_selector[len("xpath=") :] if xpath_selector.startswith("xpath=") else xpath_selector
await page.evaluate( await page.evaluate(
"""({ xpath, value }) => { """({ xpath, value }) => {
const el = document.evaluate( const el = document.evaluate(
@@ -376,7 +402,7 @@ async def interactions_service(
el.dispatchEvent(new Event('change', { bubbles: true })); el.dispatchEvent(new Event('change', { bubbles: true }));
} }
}""", }""",
{"xpath": xpath_selector, "value": text}, {"xpath": normalized_xpath, "value": text},
) )
else: else: