Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webdriver wait for one of a multiple elements to appear

Is there a way to get a webDriverWait to wait for one of a number of elements to appear and to act accordingly based on which element appears?

At the moment I do a WebDriverWait within a try loop and if a timeout exception occurs I run the alternative code which waits for the other element to appear. This seems clumsy. Is there a better way? Here is my (clumsy) code:

try:
    self.waitForElement("//a[contains(text(), '%s')]" % mime)
    do stuff ....
except TimeoutException:
    self.waitForElement("//li[contains(text(), 'That file already exists')]")
    do other stuff ...

It involves waiting an entire 10 seconds before it looks to see if the message that the file already exists on the system.

The function waitForElement just does a number of WebDriverWait calls like so:

def waitForElement(self, xPathLocator, untilElementAppears=True):
    self.log.debug("Waiting for element located by:\n%s\nwhen untilElementAppears is set to %s" % (xPathLocator,untilElementAppears))
    if untilElementAppears:
        if xPathLocator.startswith("//title"):
            WebDriverWait(self.driver, 10).until(lambda driver : self.driver.find_element_by_xpath(xPathLocator))
        else:
            WebDriverWait(self.driver, 10).until(lambda driver : self.driver.find_element_by_xpath(xPathLocator).is_displayed())
    else:   
        WebDriverWait(self.driver, 10).until(lambda driver : len(self.driver.find_elements_by_xpath(xPathLocator))==0)

Anybody got any suggestions to accomplish this in a more efficient way?

like image 429
amadain Avatar asked Jul 18 '12 11:07

amadain


2 Answers

Create a function that takes a map of identifiers to xpath queries and returns the identifier that was matched.

def wait_for_one(self, elements):
    self.waitForElement("|".join(elements.values())
    for (key, value) in elements.iteritems():
        try:
            self.driver.find_element_by_xpath(value)
        except NoSuchElementException:
            pass
        else:
            return key

def othermethod(self):

    found = self.wait_for_one({
        "mime": "//a[contains(text(), '%s')]",
        "exists_error": "//li[contains(text(), 'That file already exists')]"
    })

    if found == 'mime':
        do stuff ...
    elif found == 'exists_error':
        do other stuff ...
like image 93
jfocht Avatar answered Nov 15 '22 22:11

jfocht


Something like that:

def wait_for_one(self, xpath0, xpath1):
    self.waitForElement("%s|%s" % (xpath0, xpath1))
    return int(self.selenium.is_element_present(xpath1))
like image 39
Tomasz Wysocki Avatar answered Nov 15 '22 20:11

Tomasz Wysocki