Как устранить исключение ElementNotInteractableException, которое выдается методом sendKeys в Selenium WebDriver? - PullRequest
0 голосов
/ 27 июня 2018

В качестве упражнения по изучению Selenium WebDriver я пытаюсь зайти на страницу входа в Twitter и войти в систему. Наконец-то я могу перейти на страницу и получить нужный элемент * для поля имени пользователя:

<input class="text-input email-input js-signin-email" name="session[username_or_email]" type="text">

* Я пытался найти, с какими типами элементов sendKeys работает, но не могу. Я думаю, что этот элемент мне нужен, так как тег имеет тип <input>.

Когда я вызываю sendKeys на элементе после назначения, я получаю ElementNotInteractableException. Я пытался использовать явное ожидание с ExpectedConditions из visibilityOf и invisibilityOf. Соответствующая интерпретация TimeoutException и ElementNotInteractableException говорит мне, что элемент, который я упомянул выше, загружается в дерево DOM, но никогда не становится видимым *. Как мне обойти это? Есть ли решение с использованием JavascriptExecutor?

* Окружающий HTML может показать, почему элемент остается невидимым:

<form class="t1-form clearfix signin js-signin"
action="https://twitter.com/sessions" method="post">
  ::before
  <fieldset>
    <legend class="visuallyhidden">Log in</legend>
    <div class="clearfix field">
      ::before
      <input class="text-input email-input js-signin-email"
      name="session[username_or_email]" type="text">

.

** Для тех, кто на охоте, этот вопрос будет полезен, особенно если проблема вызвана методом click.

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

РЕДАКТИРОВАТЬ: по-видимому, я не сделал достаточно исследований, хотя я не видел этот вопрос на StackOverflow. Оставлю этот вопрос на случай, если он кому-нибудь поможет.

Использование JavascriptExecutor (Источник 1.):

  1. Импорт: import org.openqa.selenium.JavascriptExecutor;
  2. Общая идея: JavascriptExecutor executor= (JavascriptExecutor) driver; executor.executeScript(script, arguments);
  3. Для альтернативы sendKeys нам нужно выполнить бит JS, который устанавливает текстовое значение элемента с помощью точечной нотации. Мы должны сначала найти элемент. (Источник 1.) Используйте document.getElementById('id'), document.getElementsByTagName('name') или document.getElementsByClassName('class'), чтобы найти элемент (Источник 2.). Обратите внимание, что для последних двух вариантов определения местоположения элемента собирается несколько элементов, поэтому индексируйте тот, который вам нужен.

Пример строки кода, которая оказалась моим решением: executor.executeScript("document.getElementsByClassName('js-username-field email-input js-initial-focus')[0].value='someValue';");

Обратите внимание, что .getElementById('id'), вероятно, предпочтительнее, но в моем случае дизайнеры веб-сайтов решили не сотрудничать и не предоставляют атрибут id.

Вот два (невероятных!) Ресурса по теме - посмотрите их!

  1. https://www.softwaretestingmaterial.com/javascriptexecutor-selenium-webdriver/
  2. https://www.w3schools.com/js/js_htmldom_document.asp
0 голосов
/ 27 июня 2018

Вы можете использовать этот код:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Test  {
  public static void main(String[] args) throws InterruptedException {
    final WebDriver driver = new ChromeDriver();

    driver.get("https://twitter.com/login?lang=en");

    WebDriverWait wait = new WebDriverWait(driver, 10);

    // locate login input
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[@placeholder = 'Phone, email or username']")));
    WebElement loginInput = driver.findElement(By.xpath("//input[@placeholder = 'Phone, email or username']"));
    loginInput.click();
    loginInput.sendKeys("login");

    // locate password input
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//fieldset//input[@placeholder = 'Password']")));
    WebElement passInput = driver.findElement(By.xpath("//fieldset//input[@placeholder = 'Password']")); // this xPath does the trick
    passInput.click();
    passInput.sendKeys("password");
    Thread.sleep(3000); // only to see the result

    //locate submit button
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//button[@type= 'submit']")));
    WebElement submitBtn = driver.findElement(By.xpath("//button[@type= 'submit']"));
    submitBtn.click();

    Thread.sleep(3000); // only to see the result
    driver.quit();
  }
}
...