Search code examples
pythonseleniumselenium-webdriverxpathwebdriverwait

Click on link only with href


Task: using selenium in Pyhton, I need to click on link, which consists only href:enter image description here

My solution:

from selenium import webdriver
from credentials import DRIVER_PATH, LINK
from selenium.webdriver.common.by import By
import time

DRIVER_PATH = 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedgedriver.exe'
LINK = 'https://petstore.octoperf.com/actions/Catalog.action'

class Chart(object):
    def __init__(self, driver):
        self.driver = driver

        self.fish_selection = "//a[@href='/actions/Catalog.action?viewCategory=&categoryId=FISH']"

    def add_to_chart(self):
        self.driver.find_element(By.XPATH, self.fish_selection).click()
        time.sleep(3)


def setup():
    return webdriver.Edge(executable_path=DRIVER_PATH)


def additiontest():
    driver = setup()
    driver.get(LINK)
    driver.maximize_window()
    welcome_page = Chart(driver)
    welcome_page.add_to_chart()
    driver.quit()

if __name__ == "__main__":
    additiontest()

Error:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//a[@href='/actions/Catalog.action?viewCategory=&categoryId=CATS']"} (Session info: MicrosoftEdge=107.0.1418.42)


Solution

    1. The href value of that element is dynamically changing, so you need to locate that element by fixed part of href attribute.
    2. You need to wait for element to become clickable.
      This should work better:
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    wait = WebDriverWait(driver, 20)
    
    wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(@href,'FISH')]"))).click()
    

    UPD
    Accordingly to your project structure I think you should use something like this:

    class Chart(object):
        def __init__(self, driver):
            self.driver = driver
    
            self.fish_selection = "//a[contains(@href,'FISH')]"
            self.wait = WebDriverWait(self.driver, 20)
    
        def add_to_chart(self):
            self.wait.until(EC.element_to_be_clickable((By.XPATH, self.fish_selection))).click()
            time.sleep(3)