Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

selenium python clicking a href by text inside

I am trying to switch countries programmatically in this site for some automation testing, the prices are different in each country so I am programming a little tool to help me decide where to buy from.

First, I get all the currencies into a list by doing this:

def get_all_countries():
    one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
    one.click()
    el = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    list_return = []
    a_tags = el.find_elements_by_tag_name('a')
    for a in a_tags:
        list_return.append(a.text)
    return list_return

For example, it returns: ['United Kingdom', 'United States', 'France', 'Deutschland', 'España', 'Australia', 'Россия'] and then, I iterate through the list and each time calling this function:

def set_country(text):
    is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
    if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open. Check if it is open before clicking it.
        one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
        one.click()
    div = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = div.find_elements_by_tag_name('a')
    for a in a_tags:
        try:
            if a.text == text:
                driver1.get(a.get_attribute("href"))
        except StaleElementReferenceException:
            set_country(text)

When comparing a.text to text, I got a StaleElementReferenceException, I read online that it means the object is changed from when I saved it, and a simple solution is to call the function again. However, I don't like this solution and this code a lot, I think it is not effective and takes too much time, any ideas?

EDIT:

def main(url):
    driver1.get(url)
    to_return_string = ''
    one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
    one.click()
    el = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = el.find_elements_by_tag_name('a')
    for a in a_tags:
        atext = a.text
        ahref = a.get_attribute('href')
        try:
            is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
            if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open.
                one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
                one.click()
            driver1.get(ahref)
            current_price = WebDriverWait(driver1, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, ".current-price")))
            to_return_string += ("In " + atext + " : " + current_price.text + ' \n')
            print("In", atext, ":", current_price.text)
        except TimeoutException:
            print("In", atext, ":", "Timed out waiting for page to load")
            to_return_string += ("In " + atext + " : " + " Timed out waiting for page to load" + ' \n')
    return to_return_string


main('http://us.asos.com/asos//prd/7011279')
like image 554
DAVIDBALAS1 Avatar asked Apr 11 '26 18:04

DAVIDBALAS1


1 Answers

If I understand the problem statement correctly, Adding break statement solves the problem:

def set_country(text):
    is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
    if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open. Check if it is open before clicking it.
        one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
        one.click()
    div = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = div.find_elements_by_tag_name('a')
    for a in a_tags:
        try:
            if a.text == text:
                driver1.get(a.get_attribute("href"))
                break
        except StaleElementReferenceException:
            set_country(text)

DOM is updated once driver.get is called. so, the references related to old page (i.e., a_tags) won't work.

Instead, you should break the loop and come out as soon as the given country page is retrieved using driver.get once the condition is satisfied. So, you set the country you want and no need to iterate over and over again to check if condition, which obviously results in StaleElementReferenceException.

like image 128
Naveen Kumar R B Avatar answered Apr 14 '26 08:04

Naveen Kumar R B



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!