how to locate an element inside expanded list - python

I have a little problem. I am writing an automatic test, that has to go to webpage, enter some keys to search, then go to advanced search options, choose one from a list and search. The point is, that I have absolutely no idea on how to locate element on a list. It looks like this: http://www.e-podroznik.pl/public/searcherFinal.do. If you click on "więcej opcji" you'll se a list of options about journey. My question: how to locate element on this expanded "więcej opcji"-list using python selenium? I have tried everything, from find_element_by* to execute_script; nothing works. I get errors like 'unable to locate element', 'compound not permitted' etc.
The HTML:
<div class="advanced-searcher dNone more-options" style="display: block;">
<label class="lblDepartureArrival"></label>
<label class="lblRadio frmButtonFlat lblDeparture"></label>
<label class="lblRadio frmButtonFlat lblDeparture"></label>
<span class="lblOmmit"></span>
<label class="lblCaptionCarrierType"></label>
<label class="lblCarrierType lblCheckbox frmButtonFlat carrierType-bus"></label>
<label class="lblCarrierType lblCheckbox frmButtonFlat carrierType-rail"></label>
<label class="lblCarrierType lblCheckbox frmButtonFlat carrierType-aut"></label>
<label class="lblCarrierType lblCheckbox frmButtonFlat carrierType-city"></label>
<label class="lblCaptionJourneyMode"></label>
<span class=""></span>
<span class=""></span>
<span class=""></span>
<label class="lblSort">
<span class="fldCaption">
Sortuj według:
</span>
<span class="fldContainer">
<select id="sortTypeV_1399324651976" name="formCompositeSearchingResults.formCompositeSearcherFinalH.sortTypeV" style="display: none;">
<option selected="selected" value="departure"></option>
<option value="time"></option>
<option value="price"></option>
</select>
<span class="frmDropdown"></span>
</span>
</label>
<a class="lnkSwitchSearcherType" title="Wyszukiwarka zaawansowana" href="/public/searcher.do?method=task&advanced=false"></a>
</div>
I specifically need to expand list:
"<select id="sortTypeV_1399324651976" name="formCompositeSearchingResults.formCompositeSearcherFinalH.sortTypeV" style="display: none;">" and then click "<option value="time"></option>
This doesn't work:
def do_the_advanced_search(self):
self.driver.find_element_by_xpath('//*[#id="frm_1399323992507"]/fieldset/div/div[2]/label[3]').click()
time.sleep(3)
neither this:
self.driver.execute_script("document.getElementById('sortTypeV_1399324651976').style=='display: inline block';")
Thanks for any help.

To expand the part that contains the dropdown, you can use this:
self.driver.find_element_by_css_selector("a>span.imageSprite.sprite-label-left").click()
Then you can use execute_script to set the value:
self.driver.execute_script("document.getElementsByClassName('current').value = 'Najkrótszy czas';")
The select itself is hidden via style=display:none; so it cannot be manipulated directly.

Related

Select option problem via Selenium - Unable to locate element error

I am new to Python and Selenium. I couldn't find how to select option on web page.
Website code Screenshoot of select tag
<div class="col-xs-6 middle">
<select class="form-control select-box hisse" size="1" id="MENKUL_NO" name="MENKUL_NO" style="display: none;">
<option value="" selected="">Seçiniz</option>
<option value="1368">ACSEL-ACIPAYAM SELÜLOZ</option>
<option value="207">ADEL-ADEL KALEMCILIK</option>
</select>
<div class="chosen-container chosen-container-single chosen-container-active chosen-with-drop" style="width: 429px;" title="" id="MENKUL_NO_chosen">
<a class="chosen-single" tabindex="-1">
<span>Seçiniz</span>
<div><b></b></div></a>
<div class="chosen-drop">
<div class="chosen-search">
<input type="text" autocomplete="off">
</div>
<ul class="chosen-results">
<li class="active-result result-selected highlighted" data-option-array-index="0" style="">Seçiniz</li>
<li class="active-result" data-option-array-index="1" style="">ACSEL-ACIPAYAM SELÜLOZ</li>
<li class="active-result" data-option-array-index="2" style="">ADEL-ADEL KALEMCILIK</li>
</ul></div></div></div>
I try this but doesn't find element Select(browser.find_element_by_xpath('//*[#id="MENKUL_NO"]')).select_by_value(1)
Try this
select_by_value("ADEL-ADEL KALEMCILIK") or
select_by_index(1)
I see that it is select and option tag in HTML. You can use the below code with Explicit wait.
select = Select(wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "select[id='MENKUL_NO'][name='MENKUL_NO']"))))
select.select_by_visible_text('ACSEL-ACIPAYAM SELÜLOZ')
Imports :
from selenium.webdriver.support.select import Select
First, try a different locator for the main element, as even id may be not unique.
Afterwards, try finding by index.
locator = driver.find_element_by_xpath('//select[#class="form-control select-box hisse"]')
select = Select(locator)
select.select_by_index(1)
Also, try selecting by value:
select.select_by_value('1368')
Value is dropdown option value which is 1368 or 207. The first option does not have a value. If you want to select the first element, use select_by_index(1)
Or, use:
select.select_by_visible_text('Seçiniz')
I found there is a frame tag. that is why it couldnt find.
browser.switch_to_frame("ifr")
with this code. I accomplish my task.
Thank you all who responses

how to get the second value of the same class in selenium?

I am trying to simulate in selenium when two input types are left blank and when the input field gets unfocused it will return an invalid message. What I want to do is get both of this invalid message that has the same span classname.
Here is my python code:
fn_input = driver.find_element(By.XPATH, "//input[#name='fn']")
fn_input.send_keys('')
ln_input = driver.find_element(By.XPATH, "//input[#name='ln']")
ln_input.send_keys('')
driver.find_element_by_id('submit_search').click()
time.sleep(5)
fn_error_field = driver.find_element_by_class_name('formfield__message')
Above code works fine for finding the invalid message for fn_input. My question is how do I get the second invalid message for ln_input?
HTML:
<div class="formfield formfield--notification formfield--column-view">
<div class="formfield__label">First name</div>
<div class="formfield__input-wrapper">
<input
name="fn"
id="fn"
type="text"
class="input formfield__input"
value=""
/><span
class="formfield__icon-secondary icon-close icon-color-notification"
></span
><span class="formfield__message">Invalid field</span>
</div>
</div>
<div
class="formfield formfield--notification formfield--column-view capitalized"
>
<div class="formfield__label">Last Name</div>
<div class="formfield__input-wrapper">
<input
name="ln"
id="ln"
type="text"
class="input formfield__input"
value=""
/><span
class="formfield__icon-secondary icon-close icon-color-notification"
></span
><span class="formfield__message">Invalid field</span>
</div>
</div>
<button id="submit_search" type="button" class="button button--primary">
</i>submit
</button>
There are several ways to achieve this.
Collect your element use list with .find_elements_*:
elements = driver.find_elements_by_class_name('formfield__message')
#for second element
elements[1].text
Use following xpath with following-sibling:
element = driver.find_element_by_xpath('//input[#name="ln"]//following-sibling::span[#class="formfield__message"]')
XPath Axes
If you have locators with same name you need to use findelements in selenium
List<WebElement> Selects=driver.findElements(By.Xpath("//input[#name='ln']"));
// if you want select 2 nd element use below line
Selects.get(1).click();

Need help in writing XPATH for Selenium with Python

Below is the element in DOM.
<div style="float:left;width: 40px">
<label class="radio inline">
<input id="formData99991:Select" class="sample" data-ng-model="sampletId" size="" name="formData99991Select" sample-value="true" style="" value="1234" checked="checked" type="radio"/>
A
</label>
</div>
I tried with //input[contains(#id,'formData99991:Select') and contains(text(),'A')] but it doesn't work.
There are multiple similar elements on the web page and I need to identify each element with combo of id and text.
You can try with following x-path,
//label[contains(.,'A')]/input[#id="formData99991:Select"]

Upload a photo in selenium python when file path input is not visible

This is a html code of upload a photo:
<div id="choose-photo" class="controls avatar-settings inline-upload-avatar dropdown center">
<div class="uploader-image uploader-avatar clearfix">
<div class="dropdown-menu">
<div class="dropdown-caret">
<span class="caret-outer"></span>
<span class="caret-inner"></span>
</div>
<ul tabindex="-1" role="menu" aria-hidden="true">
<li id="photo-choose-existing" class="photo-choose-existing upload-photo" role="presentation">
<button type="button" class="dropdown-link" role="menuitem">Prześlij zdjęcie</button>
<div class="photo-selector">
<button class="btn" type="button">
Zmień zdjęcie
</button>
<span class="photo-file-name">Nie wybrano pliku</span>
<div class="image-selector">
<input type="hidden" name="media_file_name" class="file-name">
<input type="hidden" name="media_data_empty" class="file-data">
<label class="t1-label">
<span class="u-hiddenVisually">Dodaj zdjęcie</span>
<input type="file" name="media_empty" class="file-input js-tooltip" tabindex="-1" accept="image/gif,image/jpeg,image/jpg,image/png" data-original-title="Dodaj zdjęcie">
</label>
</div>
</div>
</li>
<li id="photo-choose-webcam" class="u-hidden" role="presentation">
<button type="button" class="dropdown-link">Zrób zdjęcie</button>
</li>
<li id="photo-delete-image" class="u-hidden" role="presentation">
<button type="button" class="dropdown-link" role="menuitem">Usuń</button>
</li>
<li class="dropdown-divider" role="presentation"></li>
<li class="cancel-options" role="presentation">
<button type="button" class="dropdown-link" role="menuitem">Anuluj</button>
</li>
</ul>
</div>
</div>
</div>
I've created a simple method to send text to input (it's not visible on screen):
fileInput = driver.find_element_by_name('media_empty')
fileInput.send_keys(path)
But it doesn't do anything. Also I'm getting not any errors.
So, here's a second method, which may work:
<div class="ProfileAvatarEditing-buttonContainer">
<button class="ProfileAvatarEditing-button u-boxShadowInsetUserColorHover" type="button" tabindex="2">
<div class="ProfileAvatarEditing-addAvatarHelp">
<span class="Icon Icon--cameraPlus"></span>
<p>Dodaj zdjęcie profilowe</p>
</div>
<div class="ProfileAvatarEditing-changeAvatarHelp">
<span class="Icon Icon--camera"></span>
<p>Zmień zdjęcie profilowe</p>
</div>
<div class="ProfileAvatarEditing-dropAvatarHelp">
<span class="Icon Icon--cameraPlus"></span>
<p>Upuść zdięcie profilowe tutaj</p>
</div>
</button>
Here user can drap and drop file. I've found this question: Selenium: Drag and Drop from file system to webdriver? however I still don't know how can I use it in this situation.
So the question is how to send file path to the input to trigger file upload. In this case when you choose a file from file dialog or drag and drop it you'll see confirm window with preview on your photo. So then all what's left to do is to click confirm. But I don't know how to send it in the first place.
Any help will be appreciated.
edit:
I've found a solution (my own answer below):
fileInput = driver.find_element_by_xpath('//*[#id="photo-choose-existing"]/div/div/label/input')
fileInput.send_keys(path)
but there's one more problem: photo is uploaded but file dialog still opens - I don't know how to close it. I tried accesing it:
dialog = driver.switch_to.active_element['value']
but I don't know how to close it.
Strangely enough I found send_keys do indeed work. When I inspected html code in different browser it wasn't "media_empty" anymore, but a different name ("media[]" or something similar). Instead I've used xpath and I was stunned that it actually worked:
fileInput = driver.find_element_by_xpath('//*[#id="photo-choose-existing"]/div/div/label/input')
fileInput.send_keys(path)
try using below code:
fileInput = driver.find_element_by_css_selector("div.image-selector label.t1-label input")
driver.execute_script("arguments[0].setAttribute('value', 'YOUR_PATH_HERE')",fileInput)
Assuming that element is present on page if not explicitly wait for element to exist on page.
then try this:
driver.execute_script("document.getElementById('ID_HERE').setAttribute('value', 'PATH_HERE')");
hope this will help you!

Splinter Python Script Button Click

I am trying to write a code which lets me select the gender of my choice (let's use female as an example). The element as below. Please note that the ID keep changes so I cannot use css selector with the ID.
Please advise which method to use in selenium.
Thanks!
<div id="557f72b0-c612-428a-a77e-eb0841869ddb" class="nike-unite-gender-buttons gender nike-unite-component">
<div class="shim"></div>
<div class="error"></div>
<input type="hidden" id="40d664f0-e498-4fa2-8a6f-7d9fc75cfe01" value="" name="gender" data-componentname="gender">
<ul data-componentname="gender">
<li id="222f5bc2-171e-450e-8182-8e15c8d9f47b" class="">
<input type="button">
<span>Male</span>
</li>
<li id="6c6098bb-fc9f-497e-8551-0ae6bb8a235c" class="">
<input type="button">
<span>Female</span>
<</li>
</ul>
<div class="tip">Please select a gender.</div>
</div>
First, locate the gender container by the class names:
gender_container = browser.find_by_css('.nike-unite-gender-buttons.gender').first
Then, locate the button by the following text inside the span element:
female = gender_container.find_by_xpath('.//li[span = "Female"]/input').first
female.click()
Or, you may try finding the element by text directly:
browser.find_by_text('Female').first.click()

Categories

Resources