Selenium thinks button is clickable when it’s disabled and raises WebDriverException

Tags: , , , ,



I know there’s someone else having the same problem as me, but it turns out he’s using a different code as me. (I’m NOT having the same problem with this : Selenium identifies the button as clickable when it wasn’t) So, apparently I’ve tried to make the page refreshes everytime the button is unclickable or disabled using the WebDriverException error.

So, everytime the Selenium drops an error of WebDriverException which an error that occurs if you attempt to click a disabled object (If I’m not wrong), it’ll refresh the page until it’s enabled. It has worked for a few days back, but for some reason I don’t know what I’ve done, It suddenly starts malfunctioning?.

It acts like nothing happened, and drops no error even though the element is clearly disabled. I tried printing the variable just to check if the element actually stored in the variable. But, it did. So I don’t know what could be causing the problem. I’ve put the code below, every helpful answer I appreciate them!. Thank you!.

purchasenow = browser.find_element_by_xpath("/html/body/div[1]/div/div[2]/div[2]/div[2]/div[2]/div[3]/div/div[5]/div/div/button[2]")
purchasenow.click()
print(purchasenow)

while True:
    try:
        purchasenow.click()
        newtime()
        print("[INFO :] ORDER BUTTON ENABLED!, ATTEMPTING TO PUT ITEM IN CART...")
        webhook = DiscordWebhook(url=logs, content='[INFO :] ORDER BUTTON ENABLED!, ATTEMPTING TO PUT ITEM IN CART...')
        if withlogging == "y":
            response = webhook.execute()
        break
    except WebDriverException:
        newtime()
        print("[INFO :] ORDER BUTTON DISABLED!, REFRESHING THE PAGE...")
        webhook = DiscordWebhook(url=logs, content='[INFO :] ORDER BUTTON DISABLED!, REFRESHING THE PAGE...')
        if withlogging == "y":
            response = webhook.execute()
        browser.refresh()
        continue

EDIT [12/10/2020] : Tried making it sure with the is_enabled(), somehow it was detected as True or clickable. Still looking for possible solutions, please let me know in the Answers!.

Answer

Refreshing the webpage multiple times wouldn’t ensure that the element would turn clickable instantly on page load. Modern websites are increasingly implementing JavaScript, ReactJS, jQuery, Ajax, Vue.js, Ember.js, GWT, etc. to render the dynamic elements within the DOM tree. Hence to invoke click() on a WebElement there is a necessity to wait for the element and its children to completely render and become interactable.


element_to_be_clickable()

element_to_be_clickable is the expectation for checking an element is visible and enabled such that you can click it. It is defined as:

def element_to_be_clickable(locator):
    """ An Expectation for checking an element is visible and enabled such that
    you can click it."""
    def _predicate(driver):
    element = visibility_of_element_located(locator)(driver)
    if element and element.is_enabled():
        return element
    else:
        return False

    return _predicate

So ideally, to wait for the button to be clickable you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following based Locator Strategy:

WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div[2]/div[2]/div[2]/div[3]/div/div[5]/div/div/button[2]"))).click()

Note: You have to add the following imports :

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

References

You can find a couple of relevant detailed discussions in:



Source: stackoverflow