0

I have the following code in which I enter a page and search for a product, I want to execute a JavaScript code

from selenium import webdriver
from getpass import getpass
#-------------------------------------------PRODUCT SEARCH-----------------------------------------------------------------------------------
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
options.add_argument("--disable-blink-features=AutomationControlled")

driver = webdriver.Chrome("C:\\Users\\stbaz\\Documents\\Python\\ChromeTools\\chromedriver.exe", options=options)
driver.get("https://www.innvictus.com/")
product_textbox = driver.find_element_by_id("is-navigation__search-bar__input")
product_textbox.send_keys("FW7093")
product_textbox.submit()
#------------------------------------------PRODUCT SEARCH END--------------------------------------------------------------------------------------

driver.implicitly_wait(5)
js='javascript:document.getElementsByClassName("buy-button buy-button--sticky buy-button--buy-now visible-xs visible-sm")[1].click();window.open("/checkout")'
driver.execute_script(js)

But I get the following error

selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot read property 'click' of undefined

I can run that code manually in chrome, I use a bookmark, but I want to run it in Python, what am I doing wrong?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Jesus Torres
  • 63
  • 1
  • 7

3 Answers3

0

Mainly Getting an error "Cannot read property 'click' of undefined" is if selector or class cannot be found in the DOM. I believe the error happens if JavaScript cannot find the selector in the markup/DOM or if it does not exist. Maybe you should try js='javascript:document.getElementsByClassName("buy-button buy-button--sticky buy-button--buy-now visible-xs visible-sm").click();window.open("/checkout")' with out the index. check Cannot read property 'click' of undefined while using Java Script Executor in Selenium It may help

Gyaneshwor
  • 21
  • 1
  • 6
0

This error message...

selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot read property 'click' of undefined

...implies that the click() method can't be executed as the WebElement haven't completely rendered within the DOM Tree and the element is still an undefined element.


Solution

To execute the JavaScript, you need to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".buy-button.buy-button--sticky.buy-button--buy-now.visible-xs.visible-sm")))
    driver.execute_script("var x= document.getElementsByClassName('buy-button buy-button--sticky buy-button--buy-now visible-xs visible-sm')[0];"+"x.click();")
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//*[@class='buy-button buy-button--sticky buy-button--buy-now visible-xs visible-sm']")))
    driver.execute_script("var x= document.getElementsByClassName('buy-button buy-button--sticky buy-button--buy-now visible-xs visible-sm')[0];"+"x.click();")
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Now I have this selenium.common.exceptions.TimeoutException: Message: – Jesus Torres Nov 26 '20 at 21:58
  • Can you update the question with the relevant HTML? – undetected Selenium Nov 26 '20 at 22:00
  • The problem its that there is not a specific html code, my JavaScript code works when I use it as a bookmark on chrome, and it works when i click on it, for example https://www.innvictus.com/hombres/basket/tenis/nike/tenis-nike-kyrie-7-black-white/p/000000000000175791 use this link, and the JavaScript should send you to checkout – Jesus Torres Nov 26 '20 at 22:15
  • Ummm, I still see _...The owner of this website (www.innvictus.com) has banned the country or region your IP address is in (IN) from accessing this website...._ – undetected Selenium Nov 26 '20 at 22:17
0

So, I included the main program without using JavaScript; but, under the Main Program Reference, I included the method for using JavaScript as well.

To achieve this solution without JS, I used xpath to validate that the page loaded successfully. Then, after that, I found the xpath for the search button

//nav[@class='is-navigation']//span[contains(@class, 'search-btn')]

Once I discovered the xpath for this, I clicked the search button and then I created a method to search for a specific product. In my example, I used the "Converse" shoes as an example.

def search_for_text(driver : ChromeDriver, text : str):
    driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").send_keys(text)
    time.sleep(2)
    if driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").get_attribute('value').__len__() != text.__len__():
        raise Exception("Failed to populate our search textbox")
    else:
        driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").send_keys(Keys.RETURN)
        time.sleep(2)
        wait_displayed(driver, "//div[@class='is-pw__products']//div[contains(@class, 'products-list')]", 30)
        print(f'Your search for {text} was successful')

In that method, you see that I used wait_displayed to validate that my product list displays properly.

MAIN PROGRAM - FOR REFERENCE

from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver as ChromeDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait as DriverWait
from selenium.webdriver.support import expected_conditions as DriverConditions
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.keys import Keys
import time


def get_chrome_driver():
    """This sets up our Chrome Driver and returns it as an object"""
    path_to_chrome = "F:\Selenium_Drivers\Windows_Chrome87_Driver\chromedriver.exe"
    chrome_options = webdriver.ChromeOptions() 
    
    # Browser is displayed in a custom window size
    chrome_options.add_argument("window-size=1500,1000")
    
    return webdriver.Chrome(executable_path = path_to_chrome,
                            options = chrome_options)

    
def wait_displayed(driver : ChromeDriver, xpath: str, int = 5):
    try:
         DriverWait(driver, int).until(
            DriverConditions.presence_of_element_located(locator = (By.XPATH, xpath))
        )
    except:
        raise WebDriverException(f'Timeout: Failed to find {xpath}')
    
    
def is_displayed(driver : ChromeDriver, xpath: str, int = 5):
    try:
         webElement = DriverWait(driver, int).until(
            DriverConditions.presence_of_element_located(locator = (By.XPATH, xpath))
        )
         return True if webElement != None else False
    except:
        return False
    
    
def click_search(driver : ChromeDriver):
    driver.find_element(By.XPATH, "//nav[@class='is-navigation']//span[contains(@class, 'search-btn')]").click()
    time.sleep(2)
    if is_displayed(driver, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]") == False:
        raise Exception("Failed to click our search button")
    else:
        print('You clicked the Search Button Successfully')
    
    
def search_for_text(driver : ChromeDriver, text : str):
    driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").send_keys(text)
    time.sleep(2)
    if driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").get_attribute('value').__len__() != text.__len__():
        raise Exception("Failed to populate our search textbox")
    else:
        driver.find_element(By.XPATH, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]").send_keys(Keys.RETURN)
        time.sleep(2)
        wait_displayed(driver, "//div[@class='is-pw__products']//div[contains(@class, 'products-list')]", 30)
        print(f'Your search for {text} was successful')
        


# Gets our chrome driver and opens our site
chrome_driver = get_chrome_driver()
chrome_driver.get("https://www.innvictus.com/")
wait_displayed(chrome_driver, "(//nav[@class='is-navigation']//div[contains(@class, 'desktop-menu')]//a[contains(@href, 'lanzamientos')])[1]")
wait_displayed(chrome_driver, "//div[@class='content-page']//div[@class='scrolling-wrapper-flexbox']")
wait_displayed(chrome_driver, "//nav[@class='is-navigation']//span[contains(@class, 'search-btn')]")
click_search(chrome_driver)
search_for_text(chrome_driver, "Converse")
chrome_driver.quit()
chrome_driver.service.stop()

COMMAND FOR CLICKING THE SEARCH BUTTON USING JAVASCRIPT

jsText = "document.querySelector('nav').querySelector('div .is-navigation__main').querySelector('div .is-navigation__main__right').querySelector('span').click()"
driver.execute_script(jsText)

METHOD

def click_search_using_javaScript(driver : ChromeDriver):
    jsText = "document.querySelector('nav').querySelector('div .is-navigation__main').querySelector('div .is-navigation__main__right').querySelector('span').click()"
    driver.execute_script(jsText)
    time.sleep(2)
    if is_displayed(driver, "//form[@id='formSearch']//input[contains(@data-options, 'SearchBox')]") == False:
        raise Exception("Failed to click our search button")
    else:
        print('You clicked the Search Button Successfully')