First , We need to understand how an existing expected condition works.
A example when we use an explicitly wait as below:
wait = WebDriverWait(self.driver, timeout) element = wait.until(EC.visibility_of_element_located(tuple_selector))
Let’s take a look on a expected condition already existed in Selenium API:
class visibility_of_element_located(object): def __init__(self, locator): self.locator = locator def __call__(self, driver): try: return _element_if_visible(_find_element(driver, self.locator)) except StaleElementReferenceException: return False
def until(self, method, message=''): """Calls the method provided with the driver as an argument until the \ return value is not False.""" screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)
You see that an expected condition above needs both magic methods __init__ and __call__.
Firstly , when we call: EC.visibility_of_element_located(tuple_selector) , it will create a instance of Class visibility_of_element_located , this is when __init__(self, selector) is executed. object variable self.locator = locator.
And in until method, each time the method is called (value = method(self._driver)) , it actually executes the code in __call__(self, driver) of Class visibility_of_element_located.
So , when understand it , we can create a new expected condition as below. You need pass all needed arguments in __init__ like by, locator, attribute, attribute value.
class ElementAttributeToBe(object):
def __init__(self, tuple_selector, attribute, value):
self.by = tuple_selector[0]
self.locator = tuple_selector[1]
self.attribute = attribute
self.value = value
def __call__(self, driver):
web_element = driver.find_element(self.by, self.locator)
if web_element.get_attribute(self.attribute) == self.value:
return web_element
return False