estemendoza estemendoza - 2 months ago 24
Javascript Question

Selenium Webdriver: execute_script can't execute custom methods and external javascript files

I'm working with Selenium and Python and I'm trying to do two things:


  • Import an external javascript file and execute a method defined there

  • Define methods on a string and call them after evaluating



This is the output for the first case:

test.js

function hello(){
document.body.innerHTML = "testing";
}


Python code

>>> from selenium import webdriver
>>> f = webdriver.Firefox()
>>> f.execute_script("var s=document.createElement('script');\
... s.src='file://C:/test.js';\
... s.type = 'text/javascript';\
... document.head.appendChild(s)")
>>> f.execute_script("hello")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 394, in execute_script
{'script': script, 'args':converted_args})['value']
File "C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 166, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriver\remote\errorhandler.py", line 164, in check_response
raise exception_class(message, screen, stacktrace) selenium.common.exceptions.WebDriverException: Message: u'hello is not defined' ; Stacktrace:
at anonymous (about:blank:68)
at handleEvaluateEvent (about:blank:68)


And for the second case:

>>> js = "function blah(){document.body.innerHTML='testing';}"
>>> f.execute_script(js)
>>> f.execute_script("blah")
...
raise exception_class(message, screen, stacktrace) selenium.common.exceptions.WebDriverException: Message: u'blah is not defined' ; Stacktrace:

Answer

I can get your first case to work if I create an empty html file and issue:

f = webdriver.Firefox()
f.get("file://path/to/empty.html")

After this, the JavaScript you've shown will execute without issue. When I try the code you've shown in the question, Firefox does not give me an error but Chrome says: "Not allowed to load local resource". I believe the problem is cross-domain requests.

The issue with your second case is that behind the scenes Selenium wraps your JavaScript code in an anonymous function. So your blah function is local to this anonymous function. If you want to make it global, you have to assign it to window, like this:

>>> from selenium import webdriver
>>> f = webdriver.Firefox()
>>> f.execute_script("window.blah = function () {document.body.innerHTML='testing';}")
>>> f.execute_script("blah()")