Valerio
Valerio

Reputation: 57

Why Selenium WebDriverWait does not work properly into a Python class?

I have a problem with Python Selenium WebDriverWait. I was able to write few lines of code in order to open a webpage, scroll the page till I find a botton to click, open the tab and then click again on an argument of the tab. Here's the code:

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

url = 'https://www.ebay.de/sch/i.html?_nkw=sony+a7s&_sacat=0&_oac=1&LH_PrefLoc=2&_ipg=200&_pgn=1'
PATH = str(pathlib.Path(__file__).parent.absolute())+str("\chromedriver.exe")

translator = Translator(to_lang="de")
translation = translator.translate("brand").capitalize()

options = webdriver.ChromeOptions()
options.add_argument('headless')
driver = webdriver.Chrome(options=options, executable_path=PATH)
driver.get(url)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@id='s0-14-11-0-1-2-6-2']"))).click()
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, f"//span[text()='{translation}']")))
element = driver.find_element_by_xpath(f"//span[text()='{translation}']")
driver.execute_script("arguments[0].scrollIntoView(366, 144);", element)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, f"//span[text()='{translation}']"))).click()
response = str(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "x-overlay-sub-panel__col"))).text).split()
print(response)     # prints this: ['Sony', '(149)', 'Artikel', '(149)', 'Sony', 'Ericsson', '(149)', 'Artikel', '(149)', 'Keine', 'Angabe', '(282)', 'Artikel', '(282)']

Now, if I try to do the same thing defining a class and then creating an object calling the function that would do exactly same thing, I am not able to obtain anything in return. Here's the code:

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

class get_available_brands_param(object):

    def __init__(self, url, domain):

        self.PATH = str(pathlib.Path(__file__).parent.absolute()) + str("\chromedriver.exe")

        try:
            if domain == '.de':
                translator = Translator(to_lang="de")
                translation = translator.translate("Brand").capitalize()

                options = webdriver.ChromeOptions()
                options.add_argument('headless')
                driver = webdriver.Chrome(options=options, executable_path=self.PATH)
                driver.get(url)
                WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@id='s0-14-11-0-1-2-6-2']"))).click()
                WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, f"//span[text()={translation}]")))
                element = driver.find_element_by_xpath(f"//span[text()={translation}]")
                driver.execute_script("arguments[0].scrollIntoView(True);", element)
                WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, f"//span[text()={translation}]"))).click()
                response = str(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "x-overlay-sub-panel__col"))).text).split()

            return print(response)
        except:
            print('If you do not get back anything means that no brand selection is available in the website for the in input search term.')

So:

test = get_available_brands_param(url, '.de')   #URL is the same in both cases but returns nothing

For what I saw in the case of the class without the "headless" option is that the workaround stops at the opening of the tab and no click on the argument occurs. Can you please help me to find a solution? I need to create a properly working class! Thank you in advance.

Upvotes: 0

Views: 122

Answers (1)

OctaveL
OctaveL

Reputation: 1045

It actually doesn't have anything to do with Selenium directly: the issue is all subtle differences between your first and second examples.

Setting the code to exactly what is was in the first, working example will work:

class get_available_brands_param(object):

    def __init__(self, url, domain):

        self.PATH = str(pathlib.Path(__file__).parent.absolute()) + str("\chromedriver.exe")

        try:
            if domain == '.de':
                translator = Translator(to_lang="de")
                translation = translator.translate("Brand").capitalize()

                options = webdriver.ChromeOptions()
                options.add_argument('headless')
                driver = webdriver.Chrome(options=options, executable_path=self.PATH)
                driver.get(url)
                WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@id='s0-14-11-0-1-2-6-2']"))).click()
                WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, f"//span[text()='{translation}']")))  # ' around {}!
                element = driver.find_element_by_xpath(f"//span[text()='{translation}']")  # ' around {} as well!
                driver.execute_script("arguments[0].scrollIntoView(366, 144);", element)  # was 'True' instead of '366, 144' in the class example.
                WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, f"//span[text()='{translation}']"))).click()  # ' around {}, final one.
                response = str(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "x-overlay-sub-panel__col"))).text).split()

            return print(response)
        except:
            print('If you do not get back anything means that no brand selection is available in the website for the in input search term.')

Upvotes: 1

Related Questions