is_enabled returns true each time in the loop for Python Selenium

894 views Asked by At

I have the code below which searches for an element. if the element is not found it click on the next page. What I want is, if the element is not found till the last page it should print "Element not found".

elpath=f"//span[contains(text(),[value})]"
while True:
    time sleep(2)
    try:
        driver.find element_by_xpath(elpath).click()
        break
    except Exception:
        if driver.find element_by_xpath("Xpath to click Next Page").is_enabled():
            driver.find_element_by_xpath("Xpath to click Next Page").click()
        else:
            print("Element Not Found")
            break

but when I checked driver.find element_by_xpath("Xpath to click Next Page").is_enabled() returns True even if the next button is disabled(i.e the last page of the list)

Please find below the HTML codes for the Next Button:

For Disabled Button

<button mat-icon-button="" type="button" class="mat-focus-indicator mat-tooltip-trigger mat-paginator-navigation-next mat-icon-button mat-button-base_mat-animation-noopable mat-button-disabled" aria-label="Next page" disabled="true">
<span class="mat-button-wrapper">
<svg viewBox="0 0 24 24" focusable="false" class="mat-paginator-icon"> <path d="M08 6G8.59 8.32 13.23 121-821 4L10 142-6b">
</Path>
</svg>
</span>
<span matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round"> </span><span class="mat-button-focus-overlay">
</span>
</button>

For Normal Button

<button mat-icon-button="" type="button" class="mat-focus-indicator mat-tooltip-trigger mat-paginator-navigation-next mat-icon-button mat-button-base_mat-animation-noopable" aria-label="Next page"> 
<span class="mat-button-wrapper">
<svg viewBox="0 0 24 24" focusable="false" class="mat-paginator-icon"> <path d="M08 6G8.59 8.32 13.23 121-821 4L10 142-6b">
</Path>
</svg>
</span>
<span matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round">
</span>
<span class="mat-button-focus-overlay">
</span>
</button>

Can anyone suggest an alternative method?

Thanks in Advance!!!

3

There are 3 answers

4
pmadhu On

Try the below code once.

try:
    driver.find element_by_xpath(elpath).click()
    break
except Exception:
    if driver.find element_by_xpath("Xpath to click Next Page").get_attribute('disabled') == None:
        driver.find_element_by_xpath("Xpath").click()
    elif driver.find element_by_xpath("Xpath").get_attribute('disabled') == "true":
        print("Element Not Found")
        break
8
Prophet On

I guess your problem is with indentation. Looks like time sleep(2) is not with the same indentation as the inner try-except block.
This causes that immediately after clicking the next page button the next page is not yet loaded so Selenium actually get's the previous page next page element.
Also, you have a typo, you are missing _ it should be find_element_by_xpath.
Also, typo in elpath=f"//span[contains(text(),[value})]" while it should be elpath=f"//span[contains(text(),{value})]"
So, please try this:

elpath=f"//span[contains(text(),{value})]"
while True:
    time sleep(2)
    try:
        driver.find_element_by_xpath(elpath).click()
        break
    except Exception:
        if driver.find_element_by_xpath("Xpath to click Next Page").is_enabled():
            driver.find_element_by_xpath("Xpath to click Next Page").click()
        else:
            print("Element Not Found")
            break
2
JeffC On

I'm assuming you are running into a timing issue. I think the best way to avoid it is to make sure that the page has changed before attempting to click or checking for enabled. In Selenium terms, an element reference has gone "stale" when the page or part of the page changes either by navigating to a new page or through refreshing a portion of the page, etc. The way we can detect this is by using a WebDriverWait and wait for staleness_of.

I also broke out the locators to the top of the code block because it makes the code easier to read and the locators easier to manage if something changes.

See my updates to your code below.

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

ele_locator=(By.XPATH, "//span[contains(text(),[value])]")
next_page_locator = (By.XPATH, "next page XPath")
wait = new WebDriverWait(driver, 10)

while True:
    try:
        driver.find_element(ele_locator).click()
        break
    except Exception:
        next_page = driver.find_element(next_page_locator)
        if next_page.is_enabled():
            next_page.click()
            wait.until(EC.staleness_of(ele))
        else:
            print("Element Not Found")
            break

NOTE: If you are using implicit waits, you will want to turn them off. Mixing implicit and explicit waits (WebDriverWait) is expressly warned against in the docs.