Динамическое ожидание, пока элемент станет доступным для кликабельности, не работает

#java #selenium #selenium-webdriver #automation #rpa

Вопрос:

Я написал функцию следующим образом

 public static WebElement waitForElementToBeClickable(WebDriver driver, WebElement webElement, int seconds) {
    
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(webElement));
    element.click();
    return element;
    
}
 

Теперь я импортирую эту функцию и использую ее следующим образом

 private String loginButton = "btnActive";
private String home = "//a[@id='pt1:_UIShome']";
WebElement login = driver.findElement(By.id(loginButton));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();
WebElement homeButton = driver.findElement(By.xpath(home));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, homeButton, 20).click();
    
 

Кнопка входа в систему нажата, но затем, перейдя на следующую страницу, я получаю следующую ошибку —

org.openqa.селен.Исключение StaleElementReferenceException: устаревший элемент ссылка: элемент не прикреплен к документу страницы

Xpath прав, я это проверил. И когда я использую element.click() , это тоже работает, но тогда мне потребуется вручную ввести время сна, что я и делаю. Я бы хотел, чтобы это было динамично. Буду признателен за любую помощь или предложения.

Комментарии:

1. Отображается ли элемент, расположенный с //a[@id='pt1:_UIShome'] XPath, на первой странице, где представлена кнопка входа в систему?

2. Можете ли вы поделиться ссылкой на веб-сайт?

3. Эй, извините, мне не разрешили поделиться ссылкой, но элемент с //a[@id=’pt1:_UIShome’] не находится на странице после того, как я войду в систему

4. Хорошо, есть ли этот элемент в представлении или вам нужно прокрутить его, чтобы вывести на видимый экран? Есть ли какое-то всплывающее окно, вертушка и т. Д. Изначально над ним?

5. Это на виду, не нужно скулить или что-то в этом роде

Ответ №1:

Иногда JS не был завершен, и если вы попытаетесь взаимодействовать с веб-элементом или веб-элементами, которые вы увидите staleElemenent exception .

Однако приведенное ниже решение может сработать для вас :

 new WebDriverWait(driver, 10).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(By.xpath("//a[@id='pt1:_UIShome']")));
driver.findElement(By.xpath("//a[@id='pt1:_UIShome']")).click();
 

Ответ №2:

Возможно, это будет не очень приятно, но я не вижу другого стабильного решения, кроме как добавить туда немного сна. Поэтому, пожалуйста, попробуйте это:

 private String loginButton = "btnActive";
private String home = "//a[@id='pt1:_UIShome']";
WebElement login = driver.findElement(By.id(loginButton));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();
driver.findElement(By.xpath(home));
libraryUtils.waitForElements.waitForElementToBeClickable(driver, homeButton, 20);
try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
}
driver.findElement(By.xpath(home)).click();
 

Комментарии:

1. я уже добавляю режим сна, когда нужно приостановить его вручную, я хотел сделать это динамически, чтобы он работал на нескольких машинах независимо от задержки скорости Интернета. Дело в том, что я должен добавить сон в гораздо большее количество мест, а не только в это. Но спасибо тебе.

2. Я понимаю. В случае, если там есть динамический DOM, я не вижу для этого простого и стабильного решения. Это известная проблема.

3. Пожалуйста, дайте мне знать, если вы найдете какое-то четкое и стабильное решение.

4. Да, конечно, если вы тоже это сделаете, пожалуйста, дайте мне знать

Ответ №3:

Проблема здесь в том, что вы уже выполняете element.click() waitForElementToBeClickable функцию и вызываете click еще раз при вызове этой функции.

libraryUtils.waitForElements.waitForElementToBeClickable(driver, login, 20).click();

Поскольку вы уже нажали, ожидая, пока элемент станет доступным для клика, вам не следует нажимать на него снова. Я надеюсь, что вы получили ответ на StaleElementException

Комментарии:

1. Вход в веб-элемент = драйвер.findElement(By.id(Кнопка входа в систему)); libraryUtils.waitForElements.waitForElementToBeClickable(драйвер, логин, 20); домашняя кнопка веб-элемента = driver.findElement(По.xpath(главная страница)); библиотечные кнопки.waitForElements.waitForElementToBeClickable(драйвер, домашняя кнопка, 20); кнопка оплаты веб-элемента = driver.findElement(По.xpath(кредиторская задолженность)); библиотЕчные кнопки.waitForElements.waitForElementToBeClickable(драйвер, кнопка оплаты, 20);

2. я изменил код, и я выполняю его, как показано выше, он нажимает на элемент homeButton, но не нажимает на элемент payablesButton. Я получаю следующую ошибку — org.openqa.selenium. Исключение ElementClickInterceptedException: перехвачен щелчок элемента: Элемент <идентификатор=»groupNode_payables_1″ класс=»приложение-навигационная метка вверху-навигационная метка» роль=»меню» aria-haspopup=»true» tabindex=»-1″>… </a> не является кликабельным

3. Причина этой ошибки заключается в том, что какой-либо другой дочерний или родительский элемент перекрывает элемент, который вы пытаетесь щелкнуть. Есть несколько способов исправить это: element = driver.find_element_by_css('div[class*="class_name"]') driver.execute_script("arguments[0].click();", element) ИЛИ element = driver.find_element_by_css('div[class*="class_name"]') webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()