Xpath for Submit button with precedence nodes select file and * - selenium

Query 1:
I would request you to please help me on getting xpath for submit button. Absolute path starts with Select file and *.
<div id="bg">
<label id="label" style=" font-family: Segoe UI;color:#2e2e2e; font-size:12px; float:left; padding-top:8px;">
Select File <span id="spanhide" class="red">*</span></label>
<div style="margin-left:105px;"><input type="file" name="filUploadIcon" id="filUploadIcon" class="txt-box" onchange="FileUpload_OnChange(this,event);" style="width:180px;">
<input type="submit" name="btnUploadcancel" value="" onclick="return check();" id="btnUploadcancel" title="Upload" class="upload_pop"></div>
<input name="textFileName" type="text" id="textFileName" style="display:none;">
<input type="hidden" name="hdnframeID" id="hdnframeID">
<input type="hidden" name="hdnlbl" id="hdnlbl">
</div>
Query 2:
How to write xpath to skip few nodes in between. Please help. Also let me know adding // or * in between to skip nodes.
Ex: Above HTML
//*div[#id="bg"]/skip elements before input type submit node/input [#type="submit"]

Use the below xpath to target the precedence nodes that include the label with the string "Select File" and the embedded span that contains '*'.
//div[contains(#id, 'bg')]/label[contains(text(), 'Select File')]/span[contains(text(), '*')]
Then add on the below line to return to the parent node label to the span tag.
/parent::label
Then add on the below to get to the sibling div tag of the label tag, which contains the input tag with a type of submit.
/following-sibling::div/input[#type='submit']
So the xpath in its entirety should look like this:
//div[contains(#id, 'bg')]/label[contains(text(), 'Select File')]/span[contains(text(), '*')]/parent::label/following-sibling::div/input[#type='submit']

You can use below xpath.
//div[#id='bg']//input[#name='btnUploadcancel']
Strongly suggest to go through this to learn more on xpath 1.0 which will answer all your questions in OP.

Related

only first word from radio button selection is being returned

To get the selected option from a radio button form, I'm looking at request.vars to get the value. Following is the controller code:
def get_results():
test = request.vars['QuestionOne']
for topic in session.selectedtopics:
test = test + request.vars[topic]
return locals()
And now the code for the view:
{{extend 'layout.html'}}
<P>Please select the options that most closely approximates the actual scenario.
<br>
<form action="{{=URL('get_results')}}" method="post">
{{nameTopic =""}}
{{session.selectedtopics = list()}}
{{for topic in topics:}}
{{if nameTopic <> topic.topic.replace(" ", "_"):}}
<br><h2>{{=topic.topic}}</h2>
{{nameTopic = topic.topic.replace(" ", "_")}}
{{session.selectedtopics.append(nameTopic)}}
{{pass}}
<p><input type="radio" name={{=nameTopic}} value={{=topic.param}}>{{=topic.param}}</p>
{{pass}}
<br>
<input type="submit">
</form>
Here is the problem: I don't know the reason, but it is getting only the first word of the selected option in the radio form. For example, the option selected is "It is normal", but the var is returning only "It". Any idea why it is happening?
Thank in advance.
You need to quote the HTML attribute values:
<input type="radio" name="{{=nameTopic}}" value="{{=topic.param}}">
Without the quotes, you'll end up with final HTML like:
<input type="radio" name=some_topic value=It is normal>
The browser will interpret the value to be "It", with "is" and "normal" being invalid HTML attributes.

How to find Label of a input field

Looking for a generic way to find text before an input field to know what to fill in the field. Using xpath, css selector or any other way possible.
<div>
<span>Full Name</span>
<input name="xddadN">
</div>
<div>
<span>Email</span>
<input name="xedadN">
</div>
Or
<div>
<div><label>Full Name</label></div>
<div><input name="xddadN"></div>
<div><label>Email</label></div>
<div><input name="xedadN"></
</div>
Or
<div>
<label>Full Name<br>
<span><input name="xddadN"></span>
</label>
</div>
<div>
<label>Full Name<br>
<span><input name="xddadN"></span>
</label>
</div>
You can try below XPath expression to get preceding text node:
//input/preceding::*[1]
or more specific for Full Name
//input[#name="xddadN"]/preceding::*[1]
and Email:
//input[#name="xedadN"]/preceding::*[1]
For full name use this Xpath : //input[#name='xddadN']/preceding-sibling::span
code :
String fullName = driver.findElement(By.Xpath(//input[#name='xddadN']/preceding-sibling::span)).getText();
String Email = driver.findElement(By.Xpath(//input[#name='xedadN']/preceding-sibling::span)).getText();
You haven't mentioned any Selenium Language Binding Art so I will be using Java for the example.
First the Answer
Yes, you can use a generic way to find text before an input field as follows :
As per the HTML :
<div>
<span>Full Name</span>
<input name="xddadN">
</div>
<div>
<span>Email</span>
<input name="xedadN">
</div>
To retrieve the text Full Name from the <span> tag with respect to the <input> tag you can use :
String myText = driver.findElement(By.xpath("//input[#name='xddadN']//preceding::*[1]")).getAttribute("innerHTML");
Now the Pitfall
Without any visibility to your usecase in my opinion the generic way would be a pitfall which will induce much chaos and uncertanity for the following reasons :
As per the xpath we are straightway jumping into the previous element, a small change in the HTML DOM (e.g. inclusion of a <span> tag) will make your Testcases to Fail.
In general, while constructing a Locator Strategy through css-selectors or xpath it will be benificial to include the <tagName> to optimize the element search process. If <tagName> are not included your Tests will require more time to locate the elements and perform action on them. In this process you are compromising some of the advantages of Test Automation.
Conclusion
Hence as a conclusion as per the Best Practices always include the <tagName> while constructing a Locator Strategy through css-selectors or xpath.

How to 'click' a radio button -> xPath needed

I need to check one of three radio buttons. I tried this code:
//input[#type='radio']/following-sibling::*[contains(., 'Inne akcje')]
but I think it's wrong way.
<label class="HoldersInLineLabel">Rodzaj akcji</label>
<input type="radio" ng-model="holdersModel.OperationType" class="prettifiedIeCheckbox ng-valid ng-dirty" value="P" name="01H">
"Przekazanie"
<input type="radio" ng-model="holdersModel.OperationType" value="D" class="prettifiedIeCheckbox ng-valid ng-dirty" name="01I">
"Dekretacja"
<input type="radio" ng-model="holdersModel.OperationType" value="O" class="prettifiedIeCheckbox ng-valid ng-dirty" name="01J">
"Inne akcje"
<span class="k-widget k-dropdown k-header ng-pristine ng-valid" unselectable="on" role="listbox" aria-haspopup="true" aria-expanded="false"...></span>
The following XPath expression will get just the input element you want:
//input[#type='radio'][following-sibling::text()[position()=1][contains(., 'Inne akcje')]]
That returns this element:
<input type="radio" ng-model="holdersModel.OperationType" value="O"
class="prettifiedIeCheckbox ng-valid ng-dirty" name="01J" />
The key differences from your original XPath expression are:
Don’t use the syntax input[#type='radio']/following-sibling…; instead use //input[#type='radio'][following-sibling….
Don’t use following-sibling::*; instead use following-sibling::text() (because in this context * means “any element“; so if you want that text node instead, you have to explicitly indicate it by using text() instead)
Do use [position()=1] in following-sibling::*[position()=1] to indicate that you want the first following sibling.
Xpath seems to get more complicated and would be hard to maintain in long term in this case. Names seem to be unique for these radio buttons. Are they not static? If they are, then you can just use name as selector. If you really want to use xpath, then try something concise like
.//input[contains(#name, '01J') and text() = 'Inne akcje']
I agree with nilesh about XPath. Here's how I would do this using CSS Selectors.
WebElement przekazanie = driver.findElement(By.cssSelector("input[value='P']"));
WebElement dekretacja = driver.findElement(By.cssSelector("input[value='D']"));
WebElement inneAkcje = driver.findElement(By.cssSelector("input[value='O']"));
// pick the one you want to click and .click() it
przekazanie.click();

Read the label of a Radio Button and confirm the value with Selenium

So as the title suggests. I am looking to confirm that the value of the Radio button is correct.
The HTML is as follows:
<input type="radio" value="Coach" name="servClass" checked="">
<font face="Arial, Helvetica, sans-serif">
Economy class
<br>
<input type="radio" value="Business" name="servClass">
Business class
<br>
<input type="radio" value="First" name="servClass">
First class
</font>
The selenium bit is as follows:
String expectedServiceClass = "First class";
String actualServiceClass = driver.findElement(By.cssSelector("input[value='First']")).getText();
if (actualserviceClass.equals(expectedServiceClass)){
System.out.println("Correct Wording");
}else{
System.out.println("Oops: somethings not right with the wording");
//close Firefox
driver.close();
// exit the program explicitly
System.exit(0);
}
But when this is executed, the actualServiceClass variable doesn't contain any values i.e. null therefore the "if statement" will always print "Oops: somethings not right with the wording"
Any help???
With the current HTML code, you won't be able to confirm the value of label of Radio button as Radio button is implemented as Input tag, that is a self-closing tag and hence getText() on input will always return null. You will need a container tag like div to include the Input tag(radio button) and the label. Refer: Self-closed versus Container Tags
The problem is not with the Selenium Code, its actually due to the improper HTML snippet. Changing the HTML as below can solve this:
<font face="Arial, Helvetica, sans-serif">
<div>
<input type="radio" value="Coach" name="servClass" checked="">
Economy class
<br>
</div>
<div>
<input type="radio" value="Business" name="servClass">
Business class
<br>
</div>
<div>
<input type="radio" value="First" name="servClass">
First class
</div>
After this, just changing the Css Selector or XPath to find the div will give you value of label of Radio Button. Css Selector can be div>input[value='First']. Let me know if you are able to solve the problem.
I agree with #Manu the HTML snippet is poor but you can use javascript childNodes to get the text from the nodes
The childNodes property returns a collection of a node's child nodes, as a NodeList object.
The nodes in the collection are sorted as they appear in the source code and can be accessed by index numbers. The index starts at 0.
Use executescript to execute JavaScript in the context of the currently selected frame or window
Below is an example in java
Don't forget to add return since you need to return the value to the caller
WebElement element = driver.findElement(By.xpath("//input[#value='Coach']/following-sibling::font"));
String node_text=(String)((JavascriptExecutor)driver).executeScript("return arguments[0].childNodes[0].nodeValue",element);
System.out.println(node_text.trim());
Try the above script it will return "Economy class"
In the above script we use childnode property to get all the childnodes of
font tag <font face="Arial, Helvetica, sans-serif">
similarly you can get the other text nodes by replacing childnode index
childNodes[4]----->"Business class"
childNodes[8]------>"First class"
I tried the above code it was working fine
Hope this helps you...kindly get back if you have any queries

want to gettext from span

I want to get text "Entered code is already exists" using selenium webdriver , I tried using id="code_error" but no use
HTML code is as follows :
<div class="leftsection">
<div class="form-element">
<fieldset>
<label><span class="required">*</span>Code:</label>
<input type="text" maxlength="6" value="" id="code" name="code" style="border: 1px solid rgb(178, 178, 178);">
</fieldset>
<span role="alert" class="errormsg" id="code_error">Entered Code already exists</span>
</div>
i used xpath , id, cssselecor but it returns NULL.
Have a look at the below code..works perfectly
options=driver.find_elements_by_class_name("errormsg")
for i in options:
print i.text
when selenium can parse JavaScript, you can use this:
var text = document.getElementById('sbucode_error').innerHTML;
Please use Selenium Ide to check whether id=code_error selector pointing to your element then use the below mentioned code to get text from that.
driver.findElement(By.id("code_error")).getText();
String text = driver.findElementById("code_error").getText(); should do the trick for you :)