No se puede hacer clic en el elemento MyElement en el punto (x, y)... Otro elemento recibiría el clic
Estoy intentando hacer algunas pruebas utilizando Katalon Studio basado en selenio. En una de mis pruebas tengo que escribir dentro de un área de texto. El problema es que me sale el siguiente error:
...Element MyElement is not clickable at point (x, y)... Other element would receive the click...
De hecho, mi elemento se coloca dentro de otra diva que podría ocultarlo, pero ¿cómo puedo hacer que el evento de clic llegue a mi área de texto?
Element ... is not clickable at point (x, y). Other element would receive the click"
puede ser causado por diferentes factores. Podrás abordarlos mediante cualquiera de los siguientes procedimientos:
- No se hace clic en el elemento debido a llamadas JavaScript o AJAX presentes
Intenta usar Actions
Clase:
WebElement element = driver.findElement(By.id("id1"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
- No se hace clic en el elemento porque no está dentro de la ventana gráfica
Intente utilizar JavascriptExecutor
para traer el elemento dentro de Viewport:
JavascriptExecutor jse1 = (JavascriptExecutor)driver;
jse1.executeScript("scroll(250, 0)"); // if the element is on top.
jse1.executeScript("scroll(0, 250)"); // if the element is at bottom.
O
WebElement myelement = driver.findElement(By.id("id1"));
JavascriptExecutor jse2 = (JavascriptExecutor)driver;
jse2.executeScript("arguments[0].scrollIntoView()", myelement);
- La página se actualiza antes de que se pueda hacer clic en el elemento.
En este caso inducir algunos wait
.
- El elemento está presente en el DOM pero no se puede hacer clic en él.
En este caso, agregue algunos ExplicitWait
para que se pueda hacer clic en el elemento.
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.elementToBeClickable(By.id("id1")));
- El elemento está presente pero tiene una superposición temporal.
En este caso, induzca ExplicitWait
con ExpectedConditions
set to invisibilityOfElementLocated
para que la superposición sea invisible.
WebDriverWait wait3 = new WebDriverWait(driver, 10);
wait3.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ele_to_inv")));
- El elemento está presente pero tiene una superposición permanente.
Se utiliza JavascriptExecutor
para enviar el clic directamente sobre el elemento.
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
Supongo que ya ha comprobado que no hay ningún otro componente superpuesto aquí (iframes publicitarios transparentes o algún otro componente del DOM => se ve con bastante frecuencia este tipo de cosas en los elementos de entrada/campo de texto) y, al realizar pasos manualmente (lentamente) su código funciona sin problemas, entonces las llamadas ajax pueden causar este comportamiento.
Para evitar thread.sleep, intente seguir con EventFiringWebDriver y registre un identificador. (Dependiendo de la pila tecnológica de su aplicación, puede trabajarla para Angular, JQuery o wicket en el controlador, por lo que requiere diferentes implementaciones) (Por cierto: este enfoque también me deshizo de cosas "StaleElementException" muchas veces)
ver: org.openqa.selenium.support.events.EventFiringWebDriver org.openqa.selenium.support.events.WebDriverEventListener
driveme = new ChromeDriver();
driver = new EventFiringWebDriver(driveme);
ActivityCapture handle=new ActivityCapture();
driver.register(handle);
=> ActivityCapture implementa WebDriverEventListener, por ejemplo, javascriptExecutor para manejar llamadas Ajax en un techstack wicket/dojo
@Override
public void beforeClickOn(WebElement arg0, WebDriver event1) {
try {
System.out.println("After click "+arg0.toString());
//System.out.println("Start afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
JavascriptExecutor executor = (JavascriptExecutor) event1;
StringBuffer javaScript = new StringBuffer();
javaScript.append("for (var c in Wicket.channelManager.channels) {");
javaScript.append(" if (Wicket.channelManager.channels[c].busy) {");
javaScript.append(" return true;");
javaScript.append(" }");
;
;
;
javaScript.append("}");
javaScript.append("return false;");
//Boolean result = (Boolean) executor.executeScript(javaScript.toString());
WebDriverWait wait = new WebDriverWait(event1, 20);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return !(Boolean) executor.executeScript(javaScript.toString());
}
});
//System.out.println("End afterClickOn - timestamp: System.currentTimeMillis(): " + System.currentTimeMillis());
} catch (Exception ex) {
//ex.printStackTrace();
}
}
Como dijo @DebanjanB, su botón (u otro elemento) podría estar cubierto temporalmente por otro elemento, pero puede esperar y hacer clic en él incluso si no sabe qué elemento cubre el botón.
Para hacer esto, puede definir su propia condición esperada con la acción de hacer clic:
public class SuccessfulClick implements ExpectedCondition<Boolean> {
private WebElement element;
public SuccessfulClick(WebElement element) { //WebElement element
this.element = element;
}
@Override
public Boolean apply(WebDriver driver) {
try {
element.click();
return true;
} catch (ElementClickInterceptedException | StaleElementReferenceException | NoSuchElementException e) {
return false;
}
}
}
y luego usa esto:
WebDriverWait wait10 = new WebDriverWait(driver, 10);
wait10.until(elementToBeClickable(btn));
wait10.until(new SuccessfulClick(btn));