2

As an exercise in learning Selenium WebDriver I am trying to visit the Twitter log in page and log in. I am finally able to navigate to the page and get the desired* element for the username field:

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

*I have tried to find what types of elements sendKeys operates with but I can't. I think this element is the one I want since the tag is of the <input> type.

When I call sendKeys on the element after assigning it I get an ElementNotInteractableException. I have tried using explicit waits with the ExpectedConditions of visibilityOf and invisibilityOf. The respective interpretation of the TimeoutException and ElementNotInteractableException tells me that the element I mentioned above loads in the DOM tree but never becomes visible*. How do I get around this? Is there a solution using a JavascriptExecutor?

*The surrounding html might reveal why the element remains invisible:

<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">

.

**For those on the hunt, this question is helpful to look at especially if the issue is caused by the click method instead.

Ders
  • 1,068
  • 13
  • 16

2 Answers2

1

You can use this code:

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();
  }
}
Andrei Suvorkov
  • 5,559
  • 5
  • 22
  • 48
  • Is it a good practice/necessary to use `click` before `sendKeys`? – Ders Jun 27 '18 at 22:23
  • Lastly is `JavascriptExecutor` more expensive to use and/or a last resort? – Ders Jun 27 '18 at 22:26
  • Turns out I was trying to locate using `By.name` and there were multiples. `By.xpath` reigns supreme. Thank you. – Ders Jun 27 '18 at 22:48
  • 2
    It's necessary to use click before sendKeys. JavascriptExecutor is also possible and not expencive, but if you can do something easy in Java, there is no point to use JavascriptExecutor. – Andrei Suvorkov Jun 28 '18 at 04:05
1

EDIT: apparently I didn't do quite enough research, although I didn't see this question on StackOverflow. Going to leave this question in case it helps someone.

Using JavascriptExecutor (Source 1.):

  1. Import: import org.openqa.selenium.JavascriptExecutor;
  2. General idea: JavascriptExecutor executor= (JavascriptExecutor) driver; executor.executeScript(script, arguments);
  3. For a sendKeys alternative we need to execute a bit of JS that sets the text value of the element using dot notation. We have to find the element first. (Source 1.) Use document.getElementById('id'), document.getElementsByTagName('name'), or document.getElementsByClassName('class') to find the element (Source 2.). Note that for the last two options for locating the element multiple elements are gathered, so index the one you want.

An example line of code that turned out to be my solution: executor.executeScript("document.getElementsByClassName('js-username-field email-input js-initial-focus')[0].value='someValue';");

Note that .getElementById('id') is probably preferred, but in my case the website designers decided to be uncooperative and not provide an id attribute.

Here are two (incredible!) resources on the subject--check them out!

  1. https://www.softwaretestingmaterial.com/javascriptexecutor-selenium-webdriver/
  2. https://www.w3schools.com/js/js_htmldom_document.asp
Ders
  • 1,068
  • 13
  • 16