selenium python dynamic dropdown menu - python

I want to fill form from a website automatically, everything goes well until I need to choose an option from dynamic dropdown menu.
<div id="field_type_group" class="field trigger-option group0" style="">
<div class="label"><label>Input Type</label></div>
<div class="input">
<select>
<option data-item-id="100" value="text_field_validation_type">Text input</option>
<option data-item-id="200" value="dropdown_field_type">Dropdown list</option>
<option data-item-id="300" value="location_field_type">Location based input</option>
</select>
</div>
</div>
<div id="text_field_validation_type" class="field trigger-option group100" style="display: none;">
<div class="label"><label>Input validation</label></div>
<div class="input">
<select>
<option data-item-id="0" data-displayfield="text_raw" value="none">No validation required</option>
<option data-item-id="500" value="text_field_type">Validation required</option>
</select>
</div>
</div>
<div id="dropdown_field_type" class="field trigger-option group200" style="">
<div class="label"><label>Data source for dropdown list</label></div>
<div class="input">
<select>
<option data-item-id="6" data-displayfield="dropdown_static" value="none">Populate with list items specified here</option>
<option data-item-id="7" data-displayfield="dropdown_dynamic" value="none">Retrieve list items from my service</option>
</select>
</div>
</div>
The dropdown menu are like this and I can successfully choose it for the first menu after trying many ways using this code.
wait.until(ec.visibility_of_element_located((By.XPATH, "//select[option[#value='text_field_validation_type']]"))).click()
browser.find_element_by_xpath(".//option[text()[contains(.,'Dropdown list')]]").click()
But the problems appear when I need to select the sub menu.
I have tried many ways (also try using Select and ActionChains) and nothing works.
My code using Select:
select_element = browser.find_element_by_xpath("//select[option[#value='text_field_validation_type']]")
select = Select(select_element)
select.select_by_index(1)
select_element = browser.find_element_by_xpath("//select[option[#data-item-id='6']]")
select = Select(select_element)
select.select_by_index(1)
My other code:
wait.until(ec.visibility_of_element_located((By.XPATH, "//select[option[#data-item-id ='6']]"))).click()
browser.find_element_by_xpath(".//option[#data-displayfield='dropdown_dynamic']").click()
I try many ways with changing the xpath value but nothing works and my environment doesnt support ActionChains.
EDIT:
I found out that I need to click the dropdown first, then I can use the select function, but it still only work on first menu. This is the code.
wait.until(ec.visibility_of_element_located((By.XPATH, "//select[option[#value='text_field_validation_type']]"))).click()
sleep(2)
select_element = browser.find_element_by_xpath("//select[option[#value='dropdown_field_type']]")
select = Select(select_element)
#select.select_by_index(1)
select.select_by_visible_text('Dropdown list')
I also notice that on the dynamic dropdown submenu, they use another div with style="display:none;" when it's not the dropdown submenu of my selected menu, is it affected my problem? I add HTML menu a little.
Can someone help me? Thank you very much.

Try code below with Selenium Select, xpath based on label and wait for element to be clickable:
sub_menu = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[#id='dropdown_field_type' and .//label[.='Data source for dropdown list']]//select")))
select = Select(sub_menu)
select.select_by_index(0)
# or
select.select_by_visible_text("Populate with list items specified here")

Can you try using xpath like this ?
dd1 = "//*[text() = 'Input Type']//following::select[1]"
dd2 = "//*[contains(text() , 'Data source')]//following::select[1]"
Select first dropdown by text or value.
select = Select(driver.find_element_by_xpath(dd1))
# select by visible text
select.select_by_visible_text('Dropdown list')
# OR select by value
select.select_by_value('dropdown_field_type')
and then Select second dropdown
select = Select(driver.find_element_by_xpath(dd2))
# select by visible text
select.select_by_visible_text('Populate with list items specified here')
Make sure to add the exact text with the correct case.

After trying many things, the solution is to upgrade the web browser and using the latest geckodriver, then using the Select function. My bad. Thank you very much for the help.

Related

How to access multiple text boxes in selenium

i am trying fill the text boxes. Each time you get into the page the the number of text boxes will be different and the name of them will be different.
<div class="fb-single-line-text">
<div class="display-flex" data-test-single-line-text-input-wrap="true">
<!---->
<input name="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)" id="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)" class="ember-text-field ember-view fb-single-line-text__input" aria-required="true" aria-describedby="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257397,numeric)-error-message" data-test-single-line-text-input="" type="text">
</div>
</div>
the above lines are the html code of first text box
<div class="fb-single-line-text">
<div class="display-flex" data-test-single-line-text-input-wrap="true">
<!---->
<input name="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257389,numeric)" id="urn:li:fs_easyApplyFormElement:(urn:li:fs_normalized_jobPosting:2620509178,30257389,numeric)" class="ember-text-field ember-view fb-single-line-text__input" aria-required="true" aria-describedby="urn:li:fs_easyApplyFormElement:(urn:li:fs_norm
alized_jobPosting:2620509178,30257389,numeric)-error-message" data-test-single-line-text-input="" type="text">
</div>
</div>
So i see all of them class name in comman so i tried to get all the eemphasized textlemnts inside the class . but i could not find a possible way for it. can someone help me with that
There are multiple ways to deal with this situation.
use find_elements to find out how many input boxes are present in UI, also you could send different message to those input box.
total_no_of_input_with_div_single_line_text = len(driver.find_elements(By.CSS_SELECTOR, "div.fb-single-line-text input"))
print(total_no_of_input_with_div_single_line_text)
Now you can send_keys to individual elements like this :-
total_no_of_input_with_div_single_line_text[0].send_keys('some string')
you can always change the index above from 0 to 1, 2 etc.
second in a loop like this :
for ele in driver.find_elements(By.CSS_SELECTOR, "div.fb-single-line-text input"):
ele.send_keys('some value here')
other way would be to use xpath indexing to locate the element.
(//div[#class='fb-single-line-text']/descendant::input)[1]
should locate the first web element input in the page, also you have the access to change that to [2], [3] and so on..

How do I select this dropdown button in Selenium?

I have this html :
<div class="dropdown float-right">
<button class="btn btn-default" type="button" id="export-button" data-toggle="dropdown">
<i class="the-download-export"></i>
Export
</button>
<div class="dropdown-menu dropdown-menu-right"><div class="dropdown-item action-export" data-format="csv" data-store="com" data-reverse-type="single"><i class="text-primary fa fa-upload" aria-hidden="true"></i>Download File</div>
This is a dropdown that has a few options. When the button is clicked, it collapses the dropdown selection and the divs appear(there are more divs for various data formats which i haven't added here for simplicity).
I have tried a few things in order to click the button with the csv data format, but everything has failed. Either not finding it or getting the div only, which is not interactible.
What is the proper way of selecting and clicking this dropdown collapsible button in Python ?
That's very little to work on.
I can recommend either checking whether you can get the data another way (e.g. api call when clicking the button) or something with x-path like
button = getFromXPath(".//button[#id='export-button']")
button.click()

element not interactable: Element is not currently visible and may not be manipulated

Newbie to selenium! I'm trying to list a house for sale on Craigslist using selenium.
And I am having trouble selecting an option from a drop-down select box.
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'D:/apps/chromedriver/chromedriver.exe')
driver.get('https://post.craigslist.org/k/tKNKfCkr6hG7ghq71YXqTA/oj7w8?s=edit')
driver.find_element_by_css_selector("select.housing_type > option[value='6']").click()
I get the following error:
ElementNotInteractableException: Message: element not interactable:
Element is not currently visible and may not be manipulated
Using "Select" also gives the same error:
from selenium.webdriver.support.ui import Select
housing_type = Select(driver.find_element_by_css_selector("select.housing_type"))
housing_type.select_by_visible_text('house')
The element is present:
housing_type = driver.find_element_by_css_selector("select.housing_type")
housing_type
But it is not intractable:
housing_type.click()
ElementNotInteractableException: Message: element not interactable
I noticed the select element is hidden and selection is controlled by next element overplayed on the select box.
<label class="json-form-item select housing_type std variant-select">
<div class="label-wrapper"><span class="label">housing type</span></div>
<select tabindex="1" name="housing_type" class="json-form-input no-js housing_type" id="ui-id-1" style="display: none;">
<option value="1" selected="">apartment</option>
<option value="2">condo</option>
<option value="3">cottage/cabin</option>
<option value="4">duplex</option>
<option value="5">flat</option>
<option value="6">house</option>
<option value="7">in-law</option>
<option value="8">loft</option>
<option value="9">townhouse</option>
<option value="10">manufactured</option>
<option value="11">assisted living</option>
<option value="12">land</option>
</select>
<span class="ui-selectmenu-button ui-widget ui-state-default ui-corner-all" tabindex="0" id="ui-id-1-button" role="combobox" aria-expanded="false" aria-autocomplete="list" aria-owns="ui-id-1-menu" aria-haspopup="true" style="width: 88%;">
<span class="ui-icon ui-icon-triangle-1-s"></span>
<span class="ui-selectmenu-text">apartment</span>
</span>
</label>
I am able to make the selection by activating the element and using down/return keys as follows, but this is not an elegant solution.
from selenium.webdriver.common.keys import Keys
housing_type = driver.find_element_by_id("ui-id-1-button")
housing_type.click()
for i in range(0,5):
housing_type.send_keys(Keys.DOWN)
housing_type.send_keys(Keys.RETURN)
Is there a better way to make the selection?
To select an item from the Housing type dropdown on the page you provided, I would first invoke WebDriverWait on the dropdown menu to ensure that it exists before you try to interact with it. Then, you can use Javascript to click the dropdown trigger and expand the options.
After that, we invoke WebDriverWait once more on the option we wish to click. The following code sample will click the option 'flat':
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# start driver
driver = webdriver.Chrome(executable_path=r'D:/apps/chromedriver/chromedriver.exe')
driver.get('https://post.craigslist.org/k/tKNKfCkr6hG7ghq71YXqTA/oj7w8?s=edit')
# wait for dropdown to exist
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, "//label[contains(#class, 'housing_type')]")))
# expand housing type dropdown using javascript
dropdown_trigger = driver.find_element_by_xpath("//label[contains(#class, 'housing_type')]/span/span[contains(#class, 'ui-icon')]")
driver.execute_script("arguments[0].click();", dropdown_trigger)
# select an option -- this selects 'flat'
dropdown_option = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, "//li[text()='flat']")))
dropdown_option.click()
Unfortunately, this seems to be a problem with how the overlay/dropdown is being used.
I noticed the select element is hidden and selection is controlled by next element overplayed on the select box.
Since the visibility of the dropdown is controlled by some overlay, you'll be forced to click on the dropdown button in order to activate the overlay and make the dropdown button visible. After the dropdown button becomes visible, you should be able to use the Selenium code without further issue. Namely, this snippet of code should be good to use:
housing_type = Select(driver.find_element_by_css_selector("select.housing_type"))
housing_type.select_by_visible_text('house')
I suggest using this approach, rather than your alternative of using the Keys.DOWN actions, as this is a better use of Selenium's built-in functions

how to select value from popup dropdown from below html

I have popup alert with dropdown values present in the popup. The values will be based previous selection list. Can anyone please help me with python selenium module to select value from this drop down.
<div class="none">
<div id="selectfavcolor">
<h3 class="popupTitle">Select your favourite color</h3>
<div class="clearFix pdLR15">
<!--newSelectBox start-->
<div class="newSelectBox">
<div class="dd-select-main clearFix">
<div id="myDropdown"></div>
<label id='SlctColorError' class='dispNone SlctErrors error'></label>
</div>
<div class="pdTB15 alRgt">
Save
</div>
</div>
<!--newSelectBox end-->
</div>
</div>
</div>
I have tried like this . but it doesn't work.
select_make = driver.find_element_by_id('myDropdown')
for option in select_make.find_elements_by_tag_name('SlctColorError'):
if option.text == 'Blue':
option.click() # select() in earlier versions of webdriver
break
Assumming that the option Blue appears on the scereen when any other action is performed,
a better way would be to wait until it appears on the screen and is clickable, and then click on it.
An example (code is in Java, because I don't know Phyton, but I belive you'll manage to convert it to Phyton):
final By blueOption = By.xpath( "//*[ text() = 'Blue' ]" );
/* wait max. 10 seconds then throw an exception if the option has't appeared */
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until( ExpectedConditions.elementToBeClickable( blueOption )).click();

interact with special combobox using selenium webdriver

I'm using selenium2 webdriver with firefox.
Usually, when there is a combobox for e.g. months I set a distinct month by send_keys(monthname).
I have a special listbox this time, where I can't simply send_keys() to it (not with webdriver nor manually). I'm not a web developer, so I have no idea what the actual difference is. This is the HTML Code of that combobox:
<div class="selectArea marke" style="width: 75px; ">
<span class="left"></span>
<span class="center">Month</span>
<span class="selectButton"></span>
<div class="disabled" style="display: none; "></div>
</div>
<select name="sregisterdmc" id="sregisterdmc" class="marke outtaHere" style="width:75px" multiple="">
<option value="">Month</option>
<option value="01">01</option>
...more options...
</select>
I have no idea how I could set an option here. I found out that I can get all the option values with .find_elements_by_tag_name(), but not how I actually set such one now. Thanks in advance!
Do a click on the option element you want selected.

Categories