The snippet
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[0])) and
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))
just evaluates to
EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))
So it always only checks that condition and that condition only, i.e it always only tries to find Doe
, completely ignoring John
. Which is why you find Jane Doe
since it appears before.
This is not how you check for multiple conditions, you need to pass a function-like object to .until
, that can check for multiple conditions and return a truthy/falsy value.
For your specific needs that function could look like-
def presence_of_element_with_both(driver):
name = "John Doe"
first = EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[0]))(driver)
second = EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, name.split(' ', 1)[1]))(driver)
if first == second:
# Both elements exist and they are the same
return first
else:
return False
This will try finding an element with partial link text "John" and then it will try finding an element with partial link text "Doe" - if both of the elements are found and if both point to the same element - you're gold.
You can use it in your until like so-
WebDriverWait(driver, 10).until(presence_of_element_with_both)
You might, however, find it convenient to generalize this-
def presence_of_element_with_all(locators):
def inner(driver):
# Get all the elements that match each given locator
results = [EC.presence_of_element_located(locator)(driver) for locator in locators]
# Check if all the elements are the same
# If they are, all the conditions have been met
# If they are not, all the conditions did not meet
return results[0] if len(set(results)) == 1 else False
return inner
This will find the singular element that satisfies all locators given.
You can use this like so-
first_name, last_name = "John Doe".split(' ')
WebDriverWait(driver, 10).until(presence_of_element_with_all([(By.PARTIAL_LINK_TEXT, first_name), (By.PARTIAL_LINK_TEXT, last_name)]))
Do note that, I'm using the closure pattern to do this. Internally, selenium
uses a class
with an __init__
and __call__
function to do the same - this is called a function like object and you can use this too if you want-
class presence_of_element_with_all:
def __init__(self, locators):
self.locators = locators
def __call__(self, driver):
results = [EC.presence_of_element_located(locator)(driver) for locator in self.locators]
# Check if all the elements are the same
# If they are, all the conditions have been met
# If they are not, all the conditions did not meet
return results[0] if len(set(results)) == 1 else False
You'd use this the exact same way as the closure pattern.