ruthless
ruthless

Reputation: 1140

Selenium Webdriver wait.until is not working

So I am starting to use Selenium Webdriver and I am encountering a problem with the until method from selenium.webdriver.support.wait. Below is my code:

from selenium import webdriver
import time
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait


url = "http://shop.uclastore.com/courselistbuilder.aspx"

driver = webdriver.Firefox()
driver.get(url)
time.sleep(1)

departments = Select(driver.find_element_by_id('clDeptSelectBox'))
for department in departments.options:
    # select department
    departments.select_by_value(department.get_attribute('value'))


    elem = driver.find_element_by_xpath("//select[@id='clCourseSelectBox']//option")
    print elem
    print elem.get_attribute('value')

    wait = WebDriverWait(driver, 10, 1.0)
    wait.until(lambda driver: driver.find_element_by_xpath("//select[@id='clCourseSelectBox']//option"))

    # time.sleep(1)

    elem = driver.find_element_by_xpath("//select[@id='clCourseSelectBox']//option")
    print elem
    print elem.get_attribute('value')
    print

The problem is that when I print out the statements before and after I get:

<selenium.webdriver.remote.webelement.WebElement object at 0x108a4af50>
0
<selenium.webdriver.remote.webelement.WebElement object at 0x108a4af90>
0

<selenium.webdriver.remote.webelement.WebElement object at 0x108a4afd0>
0
<selenium.webdriver.remote.webelement.WebElement object at 0x108a4af10>
0

where as when I comment out the wait.until code and uncomment the time.sleep, I get the following:

<selenium.webdriver.remote.webelement.WebElement object at 0x10378de90>
0
<selenium.webdriver.remote.webelement.WebElement object at 0x10378de50>
84082

<selenium.webdriver.remote.webelement.WebElement object at 0x10378df90>
0
<selenium.webdriver.remote.webelement.WebElement object at 0x103767110>
87846

So far, one possibility that I was thinking was that wait already found the elem which would imply that we should not get a zero value for the second print statement. However, that is not the case. So currently I do not know what is happening and need some help to figure it out.

Upvotes: 1

Views: 6580

Answers (1)

Louis
Louis

Reputation: 151541

Problem

Your wait is waiting until driver.find_element_by_xpath("//select[@id='clCourseSelectBox']//option") returns an element. But this is the wrong thing to test for.

The way that page is written, the <select> elements for "Campus" and "Term" are populated with <option> elements and have one <option> preselected. The <select> for "Department" is populated with <option> but has nothing preselected. The <select> elements for "Course" and "Section" are not populated.

The <select> element for "Course" becomes populated when a "Department" is chosen. However, before this <select> is populated, it does contain a placeholder <option> element that contains the text "Loading...". So whenever you look for //select[@id='clCourseSelectBox']//option, you get a hit. In the version of your code with the wait.until, you find the placeholder <option> that exists before the JavaScript code on the page has had a chance to replace it with the real options. In the version of your code with time.sleep(1) you give the time to the JavaScript to do its work. However, note that the wait.until call that you have does exactly what you asked it to do.

Solution

You could wait until the value of the option is not 0:

wait.until(lambda driver: driver.find_element_by_xpath(
    "//select[@id='clCourseSelectBox']//option").get_attribute("value") != "0")

Note that get_attribute requires a round-trip between your script and the browser in addition to the find_element... round-trip. The following code does the same thing but uses only one round-trip:

def cond(driver):
    return driver.execute_script("""
    var option = document.querySelector("select#clCourseSelectBox>option");
    return option.value !== "0";
    """)

wait.until(cond)

The code above has been tested.

Upvotes: 2

Related Questions