1

I've got an issue with browser.execute_script while using selenium with python. There is an element that i'd like to click (it's xpath below)

"//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]"

I try to do it with:

navMenu = browser.find_element_by_xpath("//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]")
time.sleep(3)
browser.execute_script(navMenu.click())

And it works (So it clicks desired element) but right after doing it it throws an error that terminates the script:

selenium.common.exceptions.WebDriverException: Message: unknown error: 'script' must be a string

What am I doing wrong? Is there a way to skip this error? Thx for wasting your time on helping me :)

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
ugabuga77
  • 681
  • 2
  • 11
  • 19
  • You are passing a function call to `.execute_script`, you need to pass it a string, or just call `navMenu.click()` – Ryan Wilson Sep 05 '18 at 14:14
  • just use `navMenu.click()` – Nihal Sep 05 '18 at 14:15
  • @RyanWilson ok, so what is the correct way of doing it? – ugabuga77 Sep 05 '18 at 14:16
  • replace `browser.execute_script(navMenu.click())` with `navMenu.click()` – Nihal Sep 05 '18 at 14:16
  • @Nihal - it doesn't work- it throws error "element is not visible" – ugabuga77 Sep 05 '18 at 14:17
  • `navMenu.click()` is the correct way to do it. in which line are you getting error? – Nihal Sep 05 '18 at 14:19
  • @Nihal in the line in which navMenu.click() is, so I know for a fact that this is not correct way of doing it. This element is generated by JS. That is why I have to use .execute_script. As I said- it works because i can see that it clicks defined element. .click() doesn't work at all- script crashes when it tries to execute .click() – ugabuga77 Sep 05 '18 at 14:23
  • https://stackoverflow.com/a/32066753/7053679 – Nihal Sep 05 '18 at 14:25

3 Answers3

3

This error message...

selenium.common.exceptions.WebDriverException: Message: unknown error: 'script' must be a string

...implies that the method execute_script() was invoked with wrong type of parameters.

The execute_script() method is defined as:

execute_script(script, *args)
    Synchronously Executes JavaScript in the current window/frame.

Where:
    script: The JavaScript to execute
    *args: Any applicable arguments for your JavaScript.

In your code trial executeScript() method will take the reference of the element as arguments[0] along with the method to be performed (in this case click()) and the reference should be provided thereafter. So @Andersson's solution should have worked.

navMenu = browser.find_element_by_xpath("//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]")
browser.execute_script("arguments[0].click()", navMenu)

You can find a detailed discussion in What does argument [0] and argument [1] mean in javascriptexecutor in Selenium WebDriver?


The hint to your main issue is the error element not visible which implies either of the following cases:

  • You are trying to invoke click() even before the element is visible/clickable
  • Element is not within the Viewport when click() was invoked.

Solution

Two pottential solutions will be as follows:

  • Induce WebDriverWait for the element to be clickable as follows:

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    # other lines of code
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]"))).click()
    
  • Use executeScript() method to bring the element within the Viewport and then invoke click() as follows:

    navMenu = browser.find_element_by_xpath("//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]")
    browser.execute_script("arguments[0].scrollIntoView(true);",navMenu);
    navMenu.click()
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
2

Instead of

browser.execute_script(navMenu.click())

try

browser.execute_script('arguments[0].click();', navMenu)

or

navMenu.click()
Andersson
  • 51,635
  • 17
  • 77
  • 129
  • It doesn't cause any errors now, but it doesn't actually click anything. I added simple `print('ooo')` right after `browser.execute_script('arguments[0].click();', navMenu)` and I get ooo in the Shell, but nothing happens on the website. I can't use `navMenu.click()` as webdriver doesn't see the element – ugabuga77 Sep 05 '18 at 15:31
  • Share HTML or/and page URL – Andersson Sep 05 '18 at 15:32
  • sorry but I can't share the link as this website contains condfidential information (you would have to log in and obviously I cannot give you credentials). I think that the root of this problem is that the entire website is generated by couple Java Script scripts. I've noticed that when I use `navMenu.click()` in shell (while script is running) it works, but first I have to actually click somewhere Is there a way to activate Java Script? – ugabuga77 Sep 05 '18 at 15:45
  • Or maybe there is a way to tell script not to terminate process after receiving error mentioned in my question? Simpy ignore it and go with another task because as I said- it works, script actually clicks desired element- the problem is that it crashes right after it (but the element that I wanted to be loaded is loaded) – ugabuga77 Sep 05 '18 at 15:47
  • `browser.execute_script(navMenu.click())` just executes `navMenu.click()`. It doesn't matter how you call the method. Using as `browser.execute_script(navMenu.click())` make no sense. Try to implement proper ExplicitWait – Andersson Sep 05 '18 at 15:48
  • I know that it is weir but if I use `navMenu.click()` i get error" element not visible" and the script doesn't even click anything. In case of `browser.execute_script(navMenu.click())` script clicks the element and crashes afterwards because of the error from first post. – ugabuga77 Sep 05 '18 at 15:52
  • Try to wait until element is visble – Andersson Sep 05 '18 at 15:55
  • Thx for trying to help me :) – ugabuga77 Sep 05 '18 at 16:06
2

The correct way to execute a script is to actually write a JavaScript script!.

The click() function of selenium is on the element of the DOM you have located not a script.

As @Andersson suggested try browser.execute_script('arguments[0].click();', navMenu)

I can see you added a sleep for 3 seconds... Using Selenium we generally use WebDriverWait you can learn more about wait's here.

If it's too complicated you can just start with driver.implicitly_wait(3) instead of sleep.

Edit:

If the Element is not displayed yet you can just use navMenu.is_displayed()

Hope this helps you.

Moshe Slavin
  • 5,127
  • 5
  • 23
  • 38
  • It doesn't cause any errors now, but it doesn't actually click anything. I added simple `print('ooo')` right after `browser.execute_script('arguments[0].click();', navMenu)` and I get ooo in the Shell, but nothing happens on the website. Thanks for advice (about using WebDriverWait). – ugabuga77 Sep 05 '18 at 15:30
  • my recommendation is to use wait for element! – Moshe Slavin Sep 05 '18 at 15:32
  • I did, and somehow it sees it but then cannot click on it as it is not visible: `try:#waits until element is prestent element7_present = EC.presence_of_element_located((By.XPATH, "//*[@id='listFav_FI410_23244709400000_FAGNNURROR_IPOF_APP_P43070_W43070A_CP000A001_40']/table/tbody/tr/td[1]"))#web element identification WebDriverWait(browser, 30).until(element7_present)#max sleep time defined except TimeoutException:#error message definition print('Timed out waiting for page to load')` – ugabuga77 Sep 05 '18 at 15:33
  • I know that it sounds stupid- there is wait and script sees it as it goes to another action but then cannot perform the click as "element is not visible" – ugabuga77 Sep 05 '18 at 15:35
  • see edit... if it does not help it may be because the site is built in Angular – Moshe Slavin Sep 05 '18 at 15:38
  • Thx for trying to help me :) – ugabuga77 Sep 05 '18 at 16:05