Selenium/Python - Element not reachable by keyboard - selenium

I am trying to fill in a form automatically. I have recorded a script with Selenium.
One of the field to populate is the zip code. When I start typing the code, a new window opens to suggest appropriate option (javascript autofill)
I need to select the first item the ul (cf. html below)
I am quite new to Selenium and though I have been reading the Selenium/html documentation I am totally stuck for almost 1 month on this...
Many thanks in advance for your support
My code is as follows and I received the error message "Element is not reachable by keyboard"
elem = driver.find_element_by_id("location_p")
elem.send_keys("75")
first_option = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, "selected")))
first_option.send_keys(Keys.RETURN)
**HTML**
<div id="localisation_left">
<div class="line toDisable">
<label for="location_p" class="label">Ville ou code postal *</label>
<div class="field-wrapper location-container">
<div class="inputWrapper">
<i id="browserGeoloc" class="icon-geoloc icon-2x blue"></i>
<div class="loaderGif-small hidden"></div>
<input class="nude" name="location_p" id="location_p" autocomplete="off" value="Paris 75010" type="text">
<input name="zipcode" value="" type="hidden">
<input name="city" value="" type="hidden">
<script type="text/javascript">
var numberOfLocation = 1, numberOfAuthorizedLocation = 1;
var cityNewadMultipleLocation = new MultipleLocationNewad('input[name="location_p"]', numberOfLocation, numberOfAuthorizedLocation);
cityNewadMultipleLocation.cityAndZipcodeAreSelected = true;
</script>
<input name="region" value="" type="hidden">
<input name="dpt_code" value="" type="hidden">
</div>
<ul class="location-list visible" style="top: 43px;">
<li data-region="12" data-dpt-code="75" class="selected">
<span class="city" title="Paris">Paris</span> <span class="zipcode">75011</span>
</li>
<li data-region="12" data-dpt-code="75">
<span class="city" title="Paris">Paris</span> <span class="zipcode">75015</span>
</li>
<li data-region="12" data-dpt-code="75">
<span class="city" title="Paris">Paris</span> <span class="zipcode">75009</span>
</li>
<li data-region="12" data-dpt-code="75">
<span class="city" title="Paris">Paris</span> <span class="zipcode">75010</span>
</li>
<li data-region="12" data-dpt-code="75">
<span class="city" title="Paris">Paris</span> <span class="zipcode">75017</span>
</li>

You can click on the first option, instead of pressing Enter key
elem = driver.find_element_by_id("location_p")
elem.send_keys("75")
condition = EC.visibility_of_element_located((By.CSS,
"label[for='location_p'] + div ul.location-list > li"))
first_option = WebDriverWait(driver, 15).until(condition)
first_option.click()

I had a similar issue, and the above solution did not work for me (it would throw an invalid syntax error).
I first used the find_element_by_css_selector function, which selects the first occurrence of the element with given attributes. This did not work.
Then I used the find_elements_by_css_selector (notice the s), which returns a list of the elements with given attributes. There were two elements in that list. Of course the first one (with index [0]) was not accessible by keyboard: this is equivalent of doing (1) above. But the second element (with index [1]) was accessible by keyboard.
Problem solved.

Try selecting by using Xpath below
elem = driver.find_element_by_id("location_p") elem.send_keys("75")
first_option = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.Xpath,
".//*[#id='localisation_left']/div/div/ul/li[1]")))
first_option.click()

If anyone faces Element not reachable by keyboard issue, one can also seek below approach:
input_xpath = '//input[#type="file"][#name="files[]"][#class="class_name"]'
input_element = self.driver.find_element_by_xpath(input_xpath)
## to make element visible:
driver.execute_script('arguments[0].style = ""; arguments[0].style.display = "block"; arguments[0].style.visibility = "visible";',
input_element)
input_element.send_keys('~\Desktop\Release2.pdf')

Related

How to select the first option in a radio button group with selenium when its ID changes with every new page load

I am writing a test automation solution with Selenium in Java.
I want to select to first option in a radio button group on my page.
The HTML id and content of these options are dynamically generated.
The options belong to a radio button group with data-cy=tv-select and name=selectTv.
How can I select the first option in this radio button group?
EDIT This is the html code:
<section _ngcontent-hqh-c168="">
<span _ngcontent-hqh-c168="">
<vi-select-tv _ngcontent-hqh-c168="" _nghost-hqh-c167="">
<mat-radio-group _ngcontent-hqh-c167="" role="radiogroup" name="selectTv" data-cy="tv-select"
class="mat-radio-group tvken-select ng-pristine ng-valid ng-star-inserted ng-touched">
<mat-radio-button _ngcontent-hqh-c167="" class="mat-radio-button mat-accent ng-star-inserted" id="mat-radio-8">
<label class="mat-radio-label" for="mat-radio-8-input">
<span class="mat-radio-container">
<span class="mat-radio-outer-circle"></span>
<span class="mat-radio-inner-circle">
</span>
<input type="radio"
class="mat-radio-input cdk-visually-hidden"
id="mat-radio-8-input"
tabindex="0"
name="selectTv"
value="NIEUW_a11fd55d-5792-4f19-8764-ccb188d20591">
<span mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator">
<span class="mat-ripple-element mat-radio-persistent-ripple">
</span>
</span>
</span>
<span class="mat-radio-label-content">
<span style="display: none;"> </span>tv 1: 02-10-2021 13:20 tot 02-10-2021 15:20</span>
</label>
</mat-radio-button>
<mat-radio-button _ngcontent-hqh-c167="" class="mat-radio-button mat-accent ng-star-inserted mat-radio-checked"
id="mat-radio-9">
<label class="mat-radio-label" for="mat-radio-9-input">
<span class="mat-radio-container">
<span class="mat-radio-outer-circle"></span>
<span class="mat-radio-inner-circle"></span>
<input type="radio"
class="mat-radio-input cdk-visually-hidden"
id="mat-radio-9-input"
tabindex="0"
name="selectTv"
value="new">
<span mat-ripple="" class="mat-ripple mat-radio-ripple mat-focus-indicator">
<span class="mat-ripple-element mat-radio-persistent-ripple"></span>
</span>
</span>
<span class="mat-radio-label-content">
<span style="display: none;"> </span>NEW</span></label>
</mat-radio-button>
</mat-radio-group>
</vi-select-tv>
</span>
</section>
I am interested in the radio button with ID mat-radio-8-input, but that ID changes with every new test run.
This is how I identify my radio button group:
#FindBy(how = CSS, using = "mat-radio-group[data-cy='tv-select']")
private List<WebElement> tv;
How can I select the first option of this group?
You can do this:
#FindBy(how = CSS, using = "mat-radio-group[data-cy='tv-select'] mat-radio-button")
private List<WebElement> radioBtns;
To get first item:
WebElement firstRadioBtn = radioBtns.get(0);
You can do this simply by executing a JS code on the page. Just inspect the target page to find a unique selector for the radio button and set selector.checked = true; using js...
For example, if my radio button have id mat-radio-9, I can use js code :- document.getElementById("mat-radio-9").checked = true;
Check Out These Questions :- Executing js code Check a radio button in js

How can I find the exact value using xpath in selenium webdriver for text that contains ?

I'm having an issue selecting the exact text 'Section' from the code using xpath.
** To be clear I require the exact text selection to be made from the innerText or innerHTML of the element if that is possible, not the id. **
I'm able to use the contains text function, but that results in other partial matches that contain 'Section' being returned/highlighted as well:
//div[#aria-hidden='false']//ul/li[contains(text(),'Section')]
I've tried using the following methods, but I don't know if I've got the syntax correct, as nothing is returned/highlighted:
//div[#aria-hidden='false']//ul/li[text()='Section')]
//div[#aria-hidden='false']//ul/li[.='Section']
//div[#aria-hidden='false']//ul/li[normalize-space(.)='Section']
This is what is shown when inspecting the Section node:
<li id="GOS--/40" class="nodecollapsed item parent-node xh-highlight" style="" xpath="1">
Section <span class="child-count"></span>
</li>
This is what is shown in the element properties:
id: "GOS--/40"
innerHTML: "↵ Section <span class="child-count"></span>↵ "
innerText: " Section "
Here is the xml which shows the other partial matches that are returned:
<div class="selection-list-dialog modal-dialog Dialog">
<div class="modal-content">
<div class="modal-header SectionHeader">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<span class="modal-title" data-lang="StandardItems">Standard Items</span>
</div>
<div class="modal-body selection-list-container" style="margin-top: 30px" id="base">
<div>
<span data-lang="SelectItemInstructions">Select the items you are interested in from the list.</span>
</div>
<br/>
<div class="pull-left selection-tree-container">
<h4 class="selection-list-title">
<span data-lang="Available">Available</span>
</h4>
<ul class="selection-list selection-tree-list">
<li id="CS--/14" class="nodecollapsed item parent-node">
Country Section <span class="child-count"></span>
</li>
<li id="Sec1--/23" class="nodecollapsed item parent-node">
Section 1 <span class="child-count"></span>
</li>
<li id="Sec2--/24" class="nodecollapsed item parent-node">
Section 2 <span class="child-count"></span>
</li>
<li id="GOS--/40" class="nodecollapsed item parent-node">
Section <span class="child-count"></span>
</li>
<li id="RS--/43" class="nodecollapsed item parent-node">
Regional Section <span class="child-count"></span>
</li>
This was a tough one. The problem is that you have a number of similar options all containing "Section" in some flavor and it's hard to distinguish them apart. What adds to this is that each one contains a non-breaking space which means that normalize-space() won't work (directly) either.
But... I found that the below XPath will work.
//li[normalize-space()='Section\u00a0']
normalize-space() removes whitespace (but not &nbsp) so you have to add it in there with \u00a0. I've tested this locally and it's working.
Try following xpath see if it helps.
//li[starts-with(#id,'GOS')][#class='nodecollapsed item parent-node xh-highlight']
OR
//li[#class='nodecollapsed item parent-node xh-highlight'][#xpath='1']
you can try the below XPath to find a section node
Try if it helps
//li[#id='GOS--/40'][contains(text(),'Section')]
Let me throw my hat into the ring....
//li[(normalize-space(text()) = 'Section')]
Here is the method that will fetch the text from the parent only. (exclude the text in the child(ren))
In Python:
def get_pure_element_text(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()
This method will iterate all the firstChild (direct children) and extract all text from all the text nodes.
In this context If you want to retrieve the text of li which have the id GOS--/40 then use the method as below.
element = driver.find_element_by_xpath("//li[#id='GOS--/40']")
print(get_pure_element_text(element))
Sharing this method, at least might help the others (if not the OP in this context).
C# implementation:(not tested)
string get_pure_text(IWebDriver driver, IWebElement element){
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
return (string)js.ExecuteScript(""""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element");
Usage:
string output = get_pure_text(driver,element)

Unable to find element using protactor which have same classes

I have one check box and two links with same classes & same Div.During the automation testing using protractor, i want to click on check box but it click on Links.
i am writing this code but its not working, please provide a solution.
Code:
element(by.id('Remember')).click();
[1
please find HTMl code:-
<div class="input-field">
<div class="pas_rembr">
<input name="remember" id="Remember" class="css-checkbox ng-dirty ng-valid-parse ng-touched ng-not-empty ng-valid ng-valid-required" ng-model="rememberMe" type="checkbox" ng-required="true" required="required">
<!-- <label for="Remember" class="css-label">I agree with the <a class="text_link" target="_blank" ng-href="{{baseUrl}}terms-conditions">Terms & Conditions</a>.</label> -->
<label for="Remember" class="css-label">I have read and I agree with <a class="text_link" target="_blank" ng-href="/lmd/terms-conditions" href="/lmd/terms-conditions">Terms and Conditions</a> and the <a class="text_link" target="_blank" ng-href="/lmd/privacy" href="/lmd/privacy">Privacy Policy</a> of this site.</label>
</div>
<span class="errorForm ng-hide" ng-show="(memberForm.remember.$dirty || submitted) && ((memberForm.remember.$error.required))">
<span class="errorForm ng-scope ng-hide" ng-show="memberForm.remember.$error.required" translate="TERAMS_CONDITION_IS_REQUIRED">Terms and condition is required</span>
</span>
</div>
Try this:-
var el = element(by.css('label[for="Remember"]'));
browser.actions().mouseMove(el, {x: 20, y: 3}).click().perform();
For your tests, the CSS selector would be
element = $$('label.css-label > a:nth-child(2)');
This should be able to click on the second a child of the label element.

Element should have been "select" but was "span" in selenium

Toggle button is present in an web application similar to
http://www.dhtmlgoodies.com/index.html?whichScript=on-off-switch
Search for "option two" in the above link.
Html code of the button is like this when turned Off
<div class="field-block button-height">
<label style="width:175px" class="label" for="input-2"><b>Case Association</b><sup>*</sup>
<span id="reqCaseAssociationTD" style="display: none;">
required</span>
</label>
<p style="margin:0px" class="field switch">
<label style="margin:0 0 4px" class="cb-enable"><span>On</span></label>
<label style="margin:0 0 4px" class="cb-disable selected"><span>Off</span></label>
<input type="checkbox" class="checkbox" id="caseAssociation">
</p>
<span style="margin-top:8px;margin-left:2px" data-tooltip="Simulataneous post from the same user (Twitter and Facebook) would get associated with the previous open case of the user." class="helpText showToolTip"></span>
</div>
Html code of the button is like this when turned ON
<div class="field-block button-height">
<label style="width:175px" class="label" for="input-2"><b>Case Association</b><sup>*</sup>
<span id="reqCaseAssociationTD" style="display: none;">
required</span>
</label>
<p style="margin:0px" class="field switch">
<label style="margin:0 0 4px" class="cb-enable selected"><span>On</span></label>
<label style="margin:0 0 4px" class="cb-disable"><span>Off</span></label>
<input type="checkbox" class="checkbox" id="caseAssociation" checked="checked">
</p>
<span style="margin-top:8px;margin-left:2px" data-tooltip="Simulataneous post from the same user (Twitter and Facebook) would get associated with the previous open case of the user." class="helpText showToolTip"></span>
</div>
Used the following identifiers
//Case Association Turned On
#FindAll(#FindBy(how = How.CSS, using = "a.cb-enable.selected"))
public List<WebElement> caseAssociationIsON;
//Case Association Turned OFF
#FindAll(#FindBy(how = How.CSS, using = "a.cb-disable.selected"))
public List<WebElement> caseAssociationIsOFF;
While running using the selenium getting the error
org.openqa.selenium.support.ui.UnexpectedTagNameException: Element
should have been "select" but was "span"
How do fix this. If more details are needed, please suggest.
I don't see any element that would match your selector, you should use label instead of a, like:
label.cb-enable.selected
and
label.cb-disable.selected
or use a selector based on input. a means link and you don't have any.
In case you still have the error what happens is that you must add an specific route:
In my case:
enter image description here
This is the resultant code:
enter image description here

Handle on-off switch with Selenium / java

I can neither recognize the on-off switch nor get its current value (On / Off).
Please help to have a look
try using xpath = "//span[#class='onoffswitch-inner' and contains(#id,'aui')]" but it doesn't help to recognize this button
"id" is a dynamic one, it will be changed once loading the page
Code:
<li id="aui_3_4_0_1_1099">
<div id="aui_3_4_0_1_1098" class="onoffswitch">
<input id="notificationActive" class="onoffswitch-checkbox" type="checkbox" autocomplete="off" checked="checked" name="notificationActive"></input>
<label id="aui_3_4_0_1_1097" class="onoffswitch-label" for="notificationActive">
<span id="aui_3_4_0_1_1096" class="onoffswitch-inner">
::before
::after
</span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</li>
Thanks,