25

A lot of times I want the webdriver to wait for presence of one of the two elements. Normally this happens when I am expecting the page to be showing either element1 in some cases or element 2. Currently I am doing this sequentially using two waits, but it's inefficient since I need to wait 2 times. Is there any way to combine the two waits into one? In other words I want to wait until element1 or element2 is present.

try: 
  element = WebDriverWait(self.browser, 15).until(EC.presence_of_element_located((By.ID, "elem1")))
  element.click()
  return "elem1"
except: 
  print "failed to find elem1"

try: 
  element = WebDriverWait(self.browser, 5).until(EC.presence_of_element_located((By.ID, "elem2")))  
  return "elem2"    
except:
  print "sth wrong!"
  raise  Exception("Sth Wrong!") 

return "Should not get here"      
apadana
  • 13,456
  • 15
  • 82
  • 98

5 Answers5

26

You can do an OR

driverWait.until(ExpectedConditions.or(
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.something")),
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.anything"))));
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
13

Not tested, but you can try something like

element = WebDriverWait(self.browser, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, "#elem1, #elem2")))

The comma in the selector is OR.

Guy
  • 46,488
  • 10
  • 44
  • 88
12

You could use a lambda

WebDriverWait(driver,15).until(
    lambda driver: driver.find_elements(By.ID,"Id1") or driver.find_elements(By.ID,"Id2"))
Maeda
  • 1,291
  • 15
  • 16
  • 1
    Be careful if you ALSO use implicitly_wait(n). Each of the lambdas will take n secs before they return. So, if you had called implicitly_wait(15) and then tried WebDriverWait(driver,15).until(), then only the first lambda would be checked. – SoloPilot Nov 02 '19 at 13:40
2

You can use the any_of method which is implemented inside the ExpectedConditionssection to check if any of the elements are available and this is relevant to the logical expression - "OR".

Example:

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

WebDriverWait(driver, 40).until(EC.any_of(
        EC.visibility_of_element_located((By.ID, 'elem1')),
        EC.visibility_of_element_located((By.ID, 'elem2'))
    )
)
Harshana
  • 5,151
  • 1
  • 17
  • 27
0

This is an alternative solution while I was having problems with other solutions.

For example, if we only have 2 conditions, and 1st is never satisfied while the 2nd is already satisfied. Then the other solutions block until the end of wait_delay before return the result; while the following solution skip it:

WebDriverWait(driver, wait_delay).until(
  wait_for_any([
    EC.presence_of_element_located(locator)
    for locator in locators
]))

where

class wait_for_any:
    def __init__(self, methods):
        self.methods = methods

    def __call__(self, driver):
        for method in self.methods:
            try:
                if method(driver):
                    return True
            except Exception:
                pass
            
        return False
BachT
  • 1,058
  • 9
  • 17