Search code examples
pythonselenium-webdriverwebdriverwaitexpected-condition

With Selenium python, do I need to refresh the page when waiting for hidden btn to appear and be clickable?


I'm trying to make a small program that looks at a web page at a hidden button (uses hide in the class) and waits for it to be clickable before clicking it. The code is below. I'm wondering if the WebDriverWait and element_to_be_clickable functions will already by refreshing things or if I would have to manually refresh the page.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.common.exceptions import WebDriverException

driver = webdriver.Firefox()
driver.get(<URL>)

print("beginning 120s wait")
time.sleep(120)
print("finished 120s wait")

try:
    element = WebDriverWait(driver, 1000).until(
        EC.element_to_be_clickable((By.CLASS_NAME, "btn add"))

    )
    print("It went through")
    element.click()
    driver.execute_script("alert('It went through!');")
finally:
    driver.execute_script("alert('Did it work?');")

First of all, I am not really sure if just searching by the class name minus the "hide" part will actually find the correct element, but the larger issue is that I do not know if the button will only be visible after refreshing the page. If I need to refresh, then it gets annoying because most sites throw up additional captchas for both Firefox or Chrome when they figure out a bot is accessing the site. (That's why I have the initial sleep: so that I can finish any captcha manually first)

So, do I need to have a refresh in my code, or will it be fine without it? If I do need it, how do I implement it? Do I just add it like:

try:
    element = WebDriverWait(driver, 1000).until(
        drive.refresh()
        EC.element_to_be_clickable((By.CLASS_NAME, "btn add"))

    )

And sorry if this has been answered elsewhere, I searched a bunch, but I have not quite found the answer on this site.


Solution

  • First, you shouldn't use sleep the WebDriverWait with the correct EC will do the trick.

    As for the EC.element_to_be_clickable this is the code behind the function:

    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
    

    As you can see the EC.element_to_be_clickable function does not refresh the browser.

    If you insist you need the refresh the correct way to implement it will be:

    try:
        element = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CLASS_NAME, "btn add"))
    
    except (NoSuchElementException, StaleElementReferenceException):
        driver.refresh()
        element = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CLASS_NAME, "btn add"))
    

    I don't think the refresh will help with the hidden element...