Home > Back-end >  How to use expected_conditions.element_to_be_clickable on a WebElement? "argument after * must
How to use expected_conditions.element_to_be_clickable on a WebElement? "argument after * must

Time:08-26

I'm needing to add a new condition to the code below because my click and arrow_right commands have sometimes been (unknowingly) failing:

        value_items = \
            (selection_section.find_elements_by_class_name("stuff")  
             selection_section.find_elements_by_class_name("stuff1")) or \
            (selection_section.find_elements_by_css_selector(".stuff2.stuff3"))


        for value in value_items:
            if value.text in values_to_select:
                self.browser.execute_script("arguments[0].scrollIntoView();", value)

                # Removing "move_to_element" from the ActionChains below seems to result in a marginal speed-up, but often causes the run
                # to fail when running headless. (The run can also fail with "move_to_element", just not as often)
                
                self.wait.until(expected_conditions.element_to_be_clickable(value))

                ActionChains(self.browser).click(value).send_keys(Keys.ARROW_RIGHT).perform()

The documentation for element_to_be_clickable states that it accepts either a locator or a WebElement, but when I run the code above I get the following error:

TypeError: selenium.webdriver.remote.webdriver.WebDriver.find_element() argument after * must be an iterable, not WebElement

CodePudding user response:

Your code is wrong

You use element_to_be_clickable too later (after value_items = ....)

You need use element_to_be_clickable before your 1st line value_items = ....

CodePudding user response:

As per the documentation element_to_be_clickable() should be called within a tuple as it is not a function but a class, where the initializer expects just 1 argument beyond the implicit self:

def element_to_be_clickable(mark):
    """
    An Expectation for checking an element is visible and enabled such that
    you can click it.

    element is either a locator (text) or an WebElement
    """

    # renamed argument to 'mark', to indicate that both locator
    # and WebElement args are valid
    def _predicate(driver):
        target = mark
        if not isinstance(target, WebElement):  # if given locator instead of WebElement
                target = driver.find_element(*target)  # grab element at locator
        target = visibility_of(target)(driver)
        if target and target.is_enabled():
            return target
        else:
            return False

    return _predicate

So irrespective of a locator or a WebElement you have to pass as a tuple.


This usecase

Your effective line of code will be:

self.wait.until(expected_conditions.element_to_be_clickable((value)))
  • Related