0

I'm currently using HtmlUnitDriver, and while I am able to set the username, I keep getting an error that Selenium could not find the password field. I am using JavascriptExecutor to set these values inside the PayPal sandbox form, but I'm still unable to get past the password step.

HtmlUnitDriver driver = new HtmlUnitDriver(BrowserVersion.CHROME)
JavascriptExecutor executor = (JavascriptExecutor)driver

        driver.setJavascriptEnabled(true)
        driver.get(url)
        log.debug "setting username"
        Thread.sleep(5000)
        if(driver.findElement(By.xpath("//*[@id='email']")).displayed){
            executor.executeScript("document.getElementById('email').value = 'email';")
            log.debug "Username was set"

        } else {
            log.debug "We never set the username!"
        }

        if(driver.findElement(By.xpath("//*[@id='password']")).displayed){
            executor.executeScript("document.getElementById('password').value='password';")

        } else {
            log.debug "We never set the password."
        }

I understand that I am setting sleeps in there, and that's bad practice for Selenium testing, but I'm pretty much at my wits end here. The url in that case is the link to express checkout, which is something like this: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=#################

Any help would be greatly appreciated!

Wheh
  • 1
  • I forgot to add this line, but right after that driver.get(url) I have a sleep to load all the JS and get the page fully loaded. – Wheh Aug 29 '18 at 17:14
  • HtmlUnit is not very reliable on modern sites - it uses a JavaScript engine that is not in any popular browser. Maybe switch to headless Chrome? – SiKing Aug 29 '18 at 17:36
  • There's a lot of issues here: 1 - page you directed us to says "no token provided", so we can't see what you see; 2 - sleep is never a good solution, add a proper wait instead. 3 - searching for xpath (and even worse - with the star `//*`!) when you have an ID is a really bad practice; 4 - why are you executing script instead of setting value of the input field? – timbre timbre Aug 29 '18 at 20:18
  • also if sandbox is anything like production paypall, it asks for password after you click Next button. I don't see you clicking it in the script – timbre timbre Aug 29 '18 at 20:19
  • @KirilS. Here's a sandbox checkout link: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-0CS422358A892640E 2. I have updated my if statement to `if(driver.findElement(By.id("password")).displayed)` but I still hit the "We never set the password" portion of the if statement. – Wheh Aug 29 '18 at 20:32
  • I'm executing the script because it's the only way to actually send the information. I have tried using sendKeys, but that does not work. – Wheh Aug 29 '18 at 20:33
  • I have also updated to click the next button after inputting the username, but I'm still hitting the error of actually setting the password. – Wheh Aug 29 '18 at 20:37

1 Answers1

0

As I mentioned earlier, there are multiple issues here:

  1. When I load the initial page, I see this UI: enter image description here

    As you see, Password button is really invisible. So unless we click the Next button, there's no chance that this script will work.

    So the following has to be added in order to achieve any kind of progress:

    driver.findElement(By.id("btnNext")).submit()
    
  2. However unfortunately I cannot get this button to be clicked correctly with HtmlUnitDriver. It seems button is clicked, but nothing happens, so Password field remains hidden. However as soon as I switch to ChromeDriver, this is not an issue anymore, and the same code works. So I guess you've hit one of the HtmlUnitDriver limitations, and need to use Chrome or Gecko driver.

  3. Finally a few adjustments to the code will make it more reliable and faster. Here's the final version that works for "real" browsers (Chrome or Gecko):

        WebDriver driver = new ChromeDriver()
        WebDriverWait wait = new WebDriverWait(driver, 10)
    
        driver.get(url)
    
        // The following line waits for email field to appear. It's more economical and reliable than Thread.sleep
        WebElement email = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("email")))
        log.debug "setting username"
        email.sendKeys("email@gmail.com")
        log.debug "Username was set " + email.getAttribute("value")
    
        driver.findElement(By.id("btnNext")).submit()
    
        // Here again using the same method to verify when password becomes visible         
        WebElement password = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password")))
        log.debug "setting password"
        password.sendKeys("password")
        log.debug "Password was set " + password.getAttribute("value")
    

(note: I wrote this code in Java, so I hope I translated all correctly, but if I didn't feel free to fix it)

The result of this script looks like this in Chrome: enter image description here

With HtmlUnitDriver, script will show an error:

org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.id: email (tried for 10 second(s) with 500 MILLISECONDS interval)

timbre timbre
  • 12,648
  • 10
  • 46
  • 77