Python Selenium selecting option using Select (element not visible?) - python

I've tried to use a few approaches mentioned in similar questions with no luck. In the HTML source code there is clearly 'value' and 'text' properties, but I cannot seem to access those when I use selenium.webdriver to access these?
Note selection lead to change in data on the page...
Edit2:
Guy has pointed out below that the actual drop down maybe a element instead of the element. However using el.click() simply flickers and does not open the drop-down.
EDIT1:
The and elements can now be identified but I am unable to make an selection. I believe the page is also in javascript and hence I'm unsure if this affects methods used.
Original post:
Webpage:
https://www.racv.com.au/on-the-road/driving-maintenance/fuel-prices.html
HTML code of selection, for visibility, some options omitted:
<select name="filter-select-6" id="filter-select-6" class="js-dropdown js-select-map js-filter-select" data-filter="#filter-list-60 .js-tab-item" data-url="/bin/racv/fuelprice" style="display: none;" data-parsley-id="3">
<option value="11" data-index="0">LRP</option>
<option value="2" selected="true" data-index="0">Unleaded</option>
<option value="3" data-index="0">Diesel</option>
<option value="8" data-index="0">Premium Unleaded 98</option>
</select>
I believe I can select the Select element without problem:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
url = 'https://www.racv.com.au/on-the-road/driving-maintenance/fuel-prices.html'
driver = webdriver.Chrome()
driver.get(url)
driver.implicitly_wait(20)
fuel_select = Select(driver.find_element_by_id('filter-select-6'))
When I print the options, I get:
for fuel_option in fuel_select.options:
print(fuel_option)
<selenium.webdriver.remote.webelement.WebElement (session="9a10aa750fa59f4412e0bea4d7aae990", element="0.5927271524692566-2")>
<selenium.webdriver.remote.webelement.WebElement (session="9a10aa750fa59f4412e0bea4d7aae990", element="0.5927271524692566-3")>
<selenium.webdriver.remote.webelement.WebElement (session="9a10aa750fa59f4412e0bea4d7aae990", element="0.5927271524692566-8")>
<selenium.webdriver.remote.webelement.WebElement (session="9a10aa750fa59f4412e0bea4d7aae990", element="0.5927271524692566-11")>
Using select():
for fuel_option in fuel_select.find_elements_by_tag_name('option'):
if fuel_option.text == "Diesel":
fuel_option.select()
Error:
Traceback (most recent call last):
File "C:/file.py", line 18, in <module>
fuel_option.Select()
AttributeError: 'WebElement' object has no attribute 'select'
Using click() or using any of the select_by_xxx():
for fuel_option in fuel_select.find_elements_by_tag_name('option'):
if fuel_option.text == "Diesel":
fuel_option.click()
#or using select_by_xxx
fuel_select.select_by_value('8')
Error:
selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable: Element is not currently visible and may not be manipulated
(Session info: chrome=74.0.3729.169)
(Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729#{#29}),platform=Windows NT 10.0.17134 x86_64)

Select is a wrapper around the WebElement, select() is not a valid method. Please refer to Select doc
Have you tried using select_by_value:
fuel_select = Select(driver.find_element_by_id('filter-select-6'))
fuel_select.select_by_value("8")
Or by visible text:
fuel_select = Select(driver.find_element_by_id('filter-select-6'))
fuel_select.select_by_visible_text("Premium Unleaded 98")
EDIT1
Try to click() first to make the dropdown visible:
el = driver.find_element_by_id('filter-select-6')
el.click()
fuel_select = Select(el)
EDIT2:
I believe your issue is more related to the fact that you use the css property style="display: none;"
You should not be able to see the dropdown manually either.
Please refer to the css syntax doc for more detail
When using None: The element is completely removed
Might not be "ideal" but you can change the value of this property to make it visible again using:
driver.execute_script('arguments[0].style.display = "block";', el)
Code would then look like:
el = driver.find_element_by_id('filter-select-6')
driver.execute_script('arguments[0].style.display = "block";', el)
fuel_select = Select(el)
fuel_select.select_by_value("8")
EDIT3:
Just noticed you provided the website! Very useful.
So the dropdown is hidden being another element and only made available once clicked.
Here's the code and it worked for me
from selenium import webdriver
from selenium.webdriver.common.touch_actions import TouchActions
from selenium.webdriver.support.ui import Select
# Get the first element and tap on it, note you might have to tap few time.
el = driver.find_element_by_css_selector('.chosen-single > div')
action = TouchActions(driver)
action.tap(el).perform()
# once the dropdown is open it does not seems that the Select el is the one to use
els = driver.find_elements_by_css_selector('.active-result')
for el in els:
if el.text == 'Diesel':
el.click()
break

Related

how to change select value use python selenium

I want to get selected option using Selenium WebDriver with Python
but I used select_by_value can't get vaule
I have the following HTML code
<select id="play_date" name="play_date" onclick="javascript:GoodsInfo.GetPlayDate(this);" onmouseover="javascript:GoodsInfo.GetPlayDate(this);" onchange="javascript:GoodsInfo.GetPlayTime(this.value);">
<option value="" selected="">Select Date</option>
<option value="20230202" style="color: black;">Thu, Feb 02, 2023</option></select>
I am trying to get a list of the option values ('20230202') using Selenium.
At the moment I have the following Python code
select_date = Select(wait.until(EC.element_to_be_clickable((By.XPATH, "//*[#id='play_date']"))))
select_date.select_by_value('20230202')
but it's always have is
selenium.common.exceptions.NoSuchElementException: Message: Could not locate element with index 1
Any help or pointers is appreciated, thank you!
If you get error NoSuchElementException it means that you are using a wrong xpath/css_selector or that the element is inside an iframe. You can check by looking at the HTML
So your case is the latter, and to make the xpath work you have first to switch to the iframe, using driver.switch_to.frame() or better EC.frame_to_be_available_and_switch_to_it.
WebDriverWait(driver, 9).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "product_detail_area")))
dropdown_date = WebDriverWait(driver,9).until(EC.element_to_be_clickable((By.ID, "play_date")))
options = []
# open menu so that options are loaded
dropdown_date.click()
# wait until options are loaded
while not options:
options = driver.find_elements(By.CSS_SELECTOR, "#play_date option:not([value=''])")
time.sleep(1)
# close menu
dropdown_date.click()
print('available options:')
for opt in options:
print(opt.get_attribute('value'))
select_date = Select(dropdown_date)
select_date.select_by_value(input('enter value: '))

Identifying html structures with data-v-xxxxxxxx and pressing them using selenium

Trying to identify a javascript button on a website and press it to extend the page.
The website in question is the tencent appstore after performing a basic search. At the bottom of the page is a button titled "div.load-more-new" where upon pressing will extend the page with more apps.
the html is as follows
<div data-v-33600cb4="" class="load-more-btn-new" style="">
<a data-v-33600cb4="" href="javascript:void(0);">加载更多
<i data-v-33600cb4="" class="load-more-icon">
</i>
</a>
</div>
At first I thought I could identify the button using BeautifulSoup but all calls to find result as empty.
from selenium import webdriver
import BeautifulSoup
import time
url = 'https://webcdn.m.qq.com/webapp/homepage/index.html#/appSearch?kw=%25E7%2594%25B5%25E5%25BD%25B1'
WebDriver = webdriver.Chrome('/chromedriver')
WebDriver.get(url)
time.sleep(5)
# Find using BeuatifulSoup
soup = BeautifulSoup(WebDriver.page_source,'lxml')
button = soup.find('div',{'class':'load-more-btn-new'})
[0] []
After looking around here, it became apparent that even if I could it in BeuatifulSoup, it would not help in pressing the button. Next I tried to find the element in the driver and use .click()
driver.find_element_by_class_name('div.load-more-btn-new').click()
[1] NoSuchElementException
driver.find_element_by_css_selector('.load-more-btn-new').click()
[2] NoSuchElementException
driver.find_element_by_class_name('a.load-more-new.load-more-btn-new[data-v-33600cb4]').click()
[3] NoSuchElementException
but all return with the same error: 'NoSuchElementException'
Your selections wont work, cause they do not point on the <a>.
This one selects by class name and you try to click the <div> that holds your <a>:
driver.find_element_by_class_name('div.load-more-btn-new').click()
This one is very close but is missing the a in selection:
driver.find_element_by_css_selector('.load-more-btn-new').click()
This one try to find_element_by_class_name but is a wild mix of tag, attribute and class:
driver.find_element_by_class_name('a.load-more-new.load-more-btn-new[data-v-33600cb4]').click()
How to fix?
Select your element more specific and nearly like in your second apporach:
driver.find_element_by_css_selector('.load-more-btn-new a').click()
or
driver.find_element_by_css_selector('a[data-v-33600cb4]').click()
Note:
While working with newer selenium versions you will get DeprecationWarning: find_element_by_ commands are deprecated. Please use find_element()*
from selenium.webdriver.common.by import By
driver.find_element(By.CSS_SELECTOR, '.load-more-btn-new a').click()

Unable to Click on Dropdown using Python Selenium

I'm trying to select an element from a dropdown but getting an error.
Here is the HTML:
<select id="childContextDDL" data-filter="contains" data-role="dropdownlist" data-template="dcf-context-picker" data-value-field="Value" data-text-field="DisplayText" data-bind="events: { change: childContextListChange }, source: childContextList.ChildContextList" style="display: none;">
<option value="1">NATION</option>
<option value="12">ATLANTIC</option>
<option value="16">CHARLOTTE, NC</option>
And this is the code that I'm trying to run:
mySelect = Select(driver.find_element_by_id("childContextDDL"))
print('MySelect is: ',mySelect)
mySelect.select_by_visible_text('ATLANTIC')
I'm getting this error:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable: Element is not currently visible and may not be manipulated
What's the possible reason for getting this error? I'm very new to Selenium.
I also want to click on that element after selecting it.
The problem was that the style within the html was set to none. So I had to first change that style to block to make it visible and then proceed with the clicking operation.
Here's the code that worked:
driver.execute_script("document.getElementById('childContextDDL').style.display = 'block';")
mySelect = Select(driver.find_element_by_id("childContextDDL"))
print('MySelect is: ',mySelect)
mySelect.select_by_visible_text('ATLANTIC')
randomClick = driver.find_element_by_id('dcf-user-info')
randomClick.click()
I guess the mySelect element (the dropdown menu) is not visible.
So please try the following:
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
mySelect = Select(driver.find_element_by_id("childContextDDL"))
actions.move_to_element(mySelect).perform()
mySelect.select_by_visible_text('ATLANTIC')
If the above doesn't work (I can't see the actual site you are working on), the following can work instead in the element has to be tapped to become enabled
action = TouchActions(driver)
action.tap(mySelect).perform()
mySelect.select_by_visible_text('ATLANTIC')
If it says it is not currently visible, you should try pausing the code with one of this options:
time.sleep(1) #This states to your code to stop for 1 second and the continue with the work.
WebDriverWait(driver, 10).until(EC.element_to_be_visible(BY.value, "12")) # tells the driver to wait a maximum of ten seconds until the value "12" is visible for the driver.

Perform TAB action until active element is the required element - Python

I want to perform TAB action until I have reached a particular web-element. Until the active element is the below mentioned element, TAB action has to be performed.
>name = driver.find_element_by_name("name")
>name.send_keys("ABC")
>group = driver.find_element_by_name("group")
>group.send_keys("DEF")
I am able to find element till the above state. After that, I want to perform TAB action until the below mentioned element is found. I guess using a loop would help.
elem = driver.find_element_by_css_selector('.PeriodCell input')
Please find below the HTML code
<div class="PeriodCell" style="left:px; width:112px;">
<div class="Effort forecasting">
<div class="entity field-value-copy-selected">
<input type="text" value="0.0" data-start="2014-09-20">
</div>
</div>
<div class="Effort unmet zero" title="">0.0
</div>
</div>
Please help. Thanks in Advance.
You can bring the element to the visible part of the screen by using one of the following methods.
Using driver.execute_script("arguments[0].scrollIntoView();", element)
you can read more about scrollIntoView() method here.
Using the Actions class of selenium webdriver.
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_element_by_css_selector('.PeriodCell input')
actions = ActionChains(driver)
actions.move_to_element(element).perform()
You can read the difference between these two methods here
If you still need to use the TAB action to reach the element
from selenium.webdriver.common.keys import Keys
and using .send_keys(Keys.TAB) send the TAB key to the element
To perform TAB Action until you find a particular WebElement would not be as per the best practices. As per your comment the element is hidden so you need to bring the element within the Viewport first and then invoke click()/send_keys() as follows:
myElement = driver.find_element_by_xpath("//div[#class='PeriodCell']//input[#type='text'][#value=\"0.0\"]")
driver.execute_script("return arguments[0].scrollIntoView(true);", myElement)
# perfrom any action on the element
However the alternative using the TAB Action is as follows:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
global element
element = driver.find_element_by_name("name")
element.send_keys("ABC")
element = driver.find_element_by_name("group")
element.send_keys("DEF")
while True:
element.send_keys(Keys.TAB)
element = driver.switch_to_active_element()
if (element.get_attribute("type")=='text' and element.get_attribute("value")=='0.0' and element.get_attribute("data-start")=='2014-09-20'):
print("Element found")
break
# do anythin with the element

selenium python: how to send keys to a hidden password with differnet IDs

I'm currently using selenium with python 2.7 and I'm trying to to insert a password to the following form:
<tr id="mockpass">
<td>
<input type="text" value="something1" onfocus="document.getElementById('mockpass').style.display='none';
document.getElementById('realpass').style.display=''; document.getElementById('Irealpass').focus();">
</td>
</tr>
<tr id="realpass" style="display: none;">
<td>
<input type="password" name="Password" id="Irealpass" onblur="if(this.value=='') {document.getElementById('mockpass').style.display='';
document.getElementById('realpass').style.display='none';}">
</td>
</tr>
I tried using the following code but I keeping getting an error while trying to excute the clear command:
passBoxXpath='//*[#id="mockpass"]/td/input'
passBoxElement = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_xpath(passBoxXpath))
passBoxElement.click()
passElement = WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_xpath('//*[#name="Password"]'))
passElement = driver.execute_script("arguments[0].style.display = 'block'; return arguments[0];",
passElement)
passElement.clear()
passElement.send_keys("myPassword")
The error:
raise exception_class(message, screen, stacktrace)
InvalidElementStateException: Message: Element is not currently interactable and may not be manipulated
I'm not sure if it's something to do with the focus or the blur that changes the element, but I get the element and fail to accsses it.
Thanks in advance!
update: the next line solved my case (still don't know why it didn't work):
driver.execute_script('document.getElementById("Irealpass").setAttribute("value","myPassword");')
In this way I didn't need to use the passBoxElement at all or changing the display style.
According to the docs http://selenium-python.readthedocs.io, this code should work.
elem = driver.find_element_by_css_selector("#mockpass input:first-child")
If you get the error anyway, scroll the browser window to element you are trying to access.
A couple things...
First off, if you are trying to perform user scenarios, you want to avoid using JavascriptExecutor (JSE). JSE allows you to do things on a page that an actual user cannot. Avoid using JSE unless you absolutely have to or if you don't care about user scenarios.
The problem is that the input that you want is hidden in the HTML you provided. You can see that in the 2nd TR, style="display: none;". If you look in the HTML of the first INPUT, you will see that the onfocus hides the first TR
onfocus="document.getElementById('mockpass').style.display='none';
and then unhides the 2nd TR
document.getElementById('realpass').style.display='';
So what you need to do is to focus the first INPUT which will expose the second INPUT.
One thing to note, from the JS in the second INPUT it looks like if you value is empty, it will rehide the second INPUT and expose the first (undoing what you just did).
onblur="if(this.value=='') {docum ...
I would do something like this
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable(By.XPATH, '//*[#id="mockpass"]/td/input')).click()
wait.until(EC.element_to_be_clickable(By.XPATH, '//*[#id="Irealpass"]')).send_keys("myPassword")
Below should be work:
passwdEle = self.driver.find_element(by='id', value='Irealpass')
self.driver.execute_script('arguments[0].setAttribute("value","****")', passwdEle)

Categories

Resources