I have a js file and i want to run it in a webpage. I am defining a lot of variable and function in this js file. I can run the code with execute_script(myScript) but when i do this, i can't use any variable or function in execute_script that defined in previous execute_script.
This is a test code:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.google.com")
driver.execute_script("let testVar = 10")
driver.execute_script("console.log(testVar)")
And this is the error:
selenium.common.exceptions.JavascriptException: Message: javascript
error: testVar is not defined
When declaring a variable with let test_var = 10 the variable will be defined in the script namespace and disappear when the script is finished.
If you want to keep the variable for use by another script, you have to anchor it to the document namespace. You can achieve that by defining an attribute on the document instance for example. If you are worried of namespace pollution, you can define a namespace for your scripts by adding an object attribute to document and storing your variables in this object.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.google.com")
driver.execute_script("document.testVar = 10")
driver.execute_script("console.log(document.testVar)")
Related
I am trying to write custom function using robot framework existing Seleniumlibrary in python to get link from element. But I am keep getting an issue in get_attribute.
Error : 'list' object has no attribute 'get_attribute'
Library imported
from selenium import webdriver
from robot.libraries.BuiltIn import BuiltIn
def get_one_links(locator,attribute):
lib = BuiltIn().get_library_instance('SeleniumLibrary')
links = lib.find_elements(locator).get_attribute(attribute)
return links
That's because you are trying to call the method on a list, you can only call on a single element. See the example below. The "get_attribute" property doesn't exist for lists, but the "get_attribute" property does for single element. For example:
You need to do something like this in your code,
from selenium import webdriver
from robot.libraries.BuiltIn import BuiltIn
def get_one_links(locator,attribute):
lib = BuiltIn().get_library_instance('SeleniumLibrary')
links = lib.find_elements(locator)
for link in links:
return link.get_attribute('href')
#return link if thats what you want
Set-up
I use selenium for a variety of things and found myself defining the same functions over and over again.
I decided to define the functions in a separate file, and import these to my work files.
Simple Example
If I define functions and execute all in one file, things work fine. See the simple full_script.py below,
# import webdriver
from selenium import webdriver
# create browser
browser = webdriver.Firefox(
executable_path='/mypath/geckodriver')
# define short xpath function
def el_xp(x):
return browser.find_element_by_xpath(x)
# navigate to url
browser.get('https://nos.nl')
# obtain title first article
el_xp('/html/body/main/section[1]/div/ul/li[1]/a/div[2]/h3').text
This successfully returns the title of the first article on this news website.
Problem
Now, when I split the script in a xpath_function.py and a run_text.py, and save them in a test folder on my desktop, things don't work fine.
xpath_function.py
# import webdriver
from selenium import webdriver
# create browser
browser = webdriver.Firefox(
executable_path='/mypath/geckodriver')
# define short xpath function
def el_xp(x):
return browser.find_element_by_xpath(x)
run_test.py
import os
os.chdir('/my/Desktop/test')
import xpath_function as xf
# import webdriver
from selenium import webdriver
# create browser
browser = webdriver.Firefox(
executable_path='/Users/lucaspanjaard/Documents/RentIndicator/geckodriver')
browser.get('https://nos.nl')
xf.el_xp('/html/body/main/section[1]/div/ul/li[1]/a/div[2]/h3').text
Executing run_test.py results in 2 browsers opened, of which one navigates to the news website and the following error,
NoSuchElementException: Unable to locate element:
/html/body/main/section[1]/div/ul/li[1]/a/div[2]/h3
I suppose the issue is that in both xpath_function.py and run_test.py I'm defining a browser.
However, if I don't define a browser in xpath_function.py, I get an error in that file that no browser is defined.
How do I solve this?
You can easily fix it by changing the definition of el_exp to include the browser as an extra parameter:
def el_xp(browser, x):
return browser.find_element_by_xpath(x)
now in run_test.py you call it like this:
xf.el_xp(browser, '/html/body/main/section[1]/div/ul/li[1]/a/div[2]/h3').text
I am just trying to run this using headless browser i don't understand why it keeps throwing me the error even if i have provided argument. Here i have read that it requires argument to pass in options.add_argument() :- https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html#module-selenium.webdriver.firefox.options
Error :- TypeError: add_argument() missing 1 required positional argument: 'argument'
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options.add_argument('-headless')
browser = webdriver.Firefox(options)
browser.get('https://intoli.com/blog/email-spy/')
browser.implicitly_wait(50)
heading = browser.find_element_by_xpath('//*[#id="heading-breadcrumb"]/div/div/div/h1').text
print(heading)
browser.close()
You should create an object Options before calling the property on it.
For more informations about how #property works, see this answer.
# create a new object
options = Options()
# calling the property (setter)
options.add_argument('-headless')
Update :
Furthermore, it seems that there are other problems with your code sample.
If you want to provide only firefox_options, you should do it as a keyword argument, so you must provide it explicitly:
browser = webdriver.Firefox(firefox_options=options)
I am using Selenium and Splinter to run my UI tests for my web application. I am generating a random id for the views on the page and would like to select the random ID for testing.
Here is the code I am using
from selenium import webdriver
from splinter import Browser
executable_path = {'executable_path':'./chromedriver.exe'}
browser = Browser('chrome', **executable_path)
data_view_id = browser.find_by_xpath('//ul[#class="nav"]').find_by_xpath('.//a[#href="#"]')[0].get_attribute("data-view-id")
# I am trying to get the id for the first item in the nav list and use it elsewhere
print(data_view_id)
This is the error I am receiving:
AttributeError: 'WebDriverElement' object has no attribute 'get_attribute'
I've looked at the 'readthedocs' page for WebElement and it has the 'get_attribute' value. I cannot find any documentation regarding WebDriverElements and need help accessing the WebElement instead
That WebDriverElement is from Splinter, not Selenium.
In Splinter, you access attributes like a dict (see the Splinter docs)
data_view_id = browser.find_by_xpath('//ul[#class="nav"]').find_by_xpath('.//a[#href="#"]')[0]['data-view-id']
Or if you wanted to do it in Selenium:
browser.find_element_by_xpath('//ul[#class="nav"]').find_element_by_xpath('.//a[#href="#"]').get_attribute("data-view-id")
I am new to python. I have a code in R that I am trying to replace with a python
script. I am running into issues getting python to select a value from a drop
down menu.
This is the code in R that worked:
remDr$findElement(using = 'xpath', "//select[#id = 'groupby1']/option[#value = 'ReportDate']")$clickElement()
This is the HTML code:
select style="" class="dropdown" name="groupby1" id="groupby1" accesskey="" waffle_affected_fields=""
option value="ReportData">Report Date</option>
here are a couple things I tried after searching how to do this in python and I
keep running into errors.
find_element_by_xpath("//select[#id='groupby1']/option[#value='ReportDate']").click()
NameError: name 'find_element_by_xpath' is not defined
Select(driver.find_element_by_css_selector("select#groupby1")).select_by_value('ReportDate').click()
NameError: name 'Select' is not defined
Any help is appropriated!
Select doesn't have click(). Use it like this
Select(driver.find_element_by_id('groupby1')).select_by_value('ReportDate')
# or by text
Select(driver.find_element_by_id('groupby1')).select_by_visible_text('ReportDate')
These functions are properties of your webdriver instance. You need to do something like this:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.python.org")
driver.find_element_by_xpath("//select[#id='groupby1']/option[#value='ReportDate']").click()
See the getting started page for examples.