How to set value to input field - selenium

Can you please suggest me how can I set value
<input type="text" name="loginAccountName" maxlength="100" value="" id="loginAccountName" class="ui-input-text ui-body-c">
I have tried using CSS
driver.findElement(By.cssSelector("input[class=textbox ui-input-text ui-body-c]")).sendKeys("qwqweq");
But it is not working.

To locate the element, you have tried:
By.cssSelector("input[class=textbox ui-input-text ui-body-c]")
While working with cssSelector we have a much convinient way to specify them. Additionally, you need to drop the textbox class as it is not a part of the node attributes. Your effective cssSelector could have been:
By.cssSelector("input.ui-input-text.ui-body-c")
But the above mentioned cssSelector may not identify an unique element. Instead we will use the id or the name locator which remains unique through out the DOM tree as follows:
Using id:
By.cssSelector("input#loginAccountName").sendKeys("qwqweq");
Using name:
By.cssSelector("input[name=loginAccountName]").sendKeys("qwqweq");

Related

FInd sibling using XPath

How to find sibling element text using xpath
<label>
<span>some span</span>
</label>
<label>
Second Label
</label>
//label[normalize-space(text()) = 'some span']/following-sibling::label/text()
In Python we would do something like this :
driver.find_element(By.XPATH, "//label[//text()[normalize-space() = 'some span']]/following-sibling::label").text
basically Python Selenium bindings provide a text method for web element. getText() for Java.
Now if you want to heavily dependent on XPATH then you can try below XPATH :
//span[contains(text(),'some span')]/../following-sibling::label
or probably
//span[contains(text(),'some span')]/../following-sibling::label[contains(text(),'Second Label')]
I would use:
//label[span[text()='some span']]/following-sibling::label/text()
or if you only want to find that if it is actually the first following-element:(i.e: you don't want to find that label if there is a input in between)
//label[span[text()='some span']]/following-sibling::*[1][self::label]/text()
or if you only want to find that the first following label(if there even more following label-elements):
//label[span[text()='some span']]/following-sibling::label[1]/text()

XPath : Pass attribute value down the path

I am wondering if below is achievable using xpath
Given:
<label for="pt1:sc">Select Country</label>
<select id="pt1:sc">....</select>
Requirement:
I want to find select element using single xpath expression like below,
bcs ids are dynamic and always available in attribute 'for'.
//label[text()='Select Country']/#for//*[#id=#for]
Can we pass attribute value(here for attribute of label) in xpath, further down the path to find element.
Please do not suggest alternative using siblings, child, id or selenium get-attribute etc.
Thanks,
You can use something like this to select an element with an attribute value which refers to another attribute located in another element :
//*[#id=//label[text()='Select Country']/#for]
I'm not sure how it's going to work with your actual html, but it works on the example in the question:
//label[text()='Select Country'][#for=//select/#id]

How to match xpath for id element that changes each time page loads?

I have these 2 xpath that are different each time I load a webpage.
The xpaths were recorded by Selenium-IDE and always have mainForm_view within the id string and the text before and after this always changes.
xpath=//input[#id='abc_hyd_wuu2_8333nd_mainForm_view_jjd_uueue2_jjd_11_jkdhd']
xpath=//div[#id='abc_hyd_wuu2_8333nd_mainForm_view_kcjjcs_sjsjs_jjdj_994_kkk']/div/div[2]/div/div/div/a[1]/h2
I've tried to locate the id like below but doesn't work.
xpath=//input[contains(#id,'mainForm_view')]
xpath=//div[contains(#id,'mainForm_view')]
Which would be the correct way to do it?
Thanks in advance.
UPDATE
I've tried with CSS selector like below but it seems is taking another id that is within an input element
document.querySelector("input[id*='mainForm_view']").id
Examining the html code I see that the id I need is related with a unique class. The code is like below:
<div class="Class_p2">
<div class="Class_p3" style="...">
<input name="8333nd$mainForm$view$jjd$uueue2" type="text" class="class a1 n1-Control" value="xyz" id="8333nd_mainForm_view_jjd_uueue2" disabled="disabled" style="..">
</div>
<input name="8333nd$mainForm$view$ttyi" type="text" disabled="disabled">
</div>
I've tried the following Javascript code in Chrome console but it doesn't work
document.getElementsByClassName("class a1 n1-Control").id
How would be to get the id=8333nd_mainForm_view_jjd_uueue2 that is related with Class=class a1 n1-Control?
UPDATE2
I was finally able to do it with
document.getElementsByClassName("class a1 n1-Control")[0].id
Thanks for all the help and time.
You can write css selector as :
input[id*='mainForm_view']
for div it'd be :
div[id*='mainForm_view']
Asterisk is to match the sub string part.
Note that if any id contains mainForm_view that will also be selected, so better to check in developers tool before proceeding.
You can try finding some other element for which xpath/css locator remains same and then try to reach to this element by traversing from there. You can use parent, ancestor, preceding-sibling, following-sibling keywords in order to traverse. Hope it helps :)

Unable to locate the login box by type attribute or xpath

HTML looks like following
<input class="text-input text-input-md" dir="auto" ng-reflect-klass="text-input" ng-reflect-ng-class="text-input-md" type="email" aria-labelledby="lbl-14" autocomplete="off" autocorrect="off" placeholder="" ng-reflect-type="email">
the code fails to find login box...tried by attribute
var email_xpath = "//*[type='email']"
then xpath
var email_xpath = "/html/body/ion-app/ng-component/ion-split-pane/ion-nav/page-login/ion-content/div[2]/ion-list/ion-item[1]/div[1]/div/ion-input/input"
var email = webDriver.findElement(By.xpath(email_xpath))
but still unable to get the element....
===============Updated===============
most of the solutions posted below works with selenium firefox driver. The issue was really with htmlunit driver that i was using in scala. Probably it cannot handle javascript properly. I changed it with firefox driver and your solutions works well. The application being tested is an Ionic app (angular), hence i will have to look for another headless solution later.
//*[type='email'] is not correct XPath. Try below instead:
//*[#type='email']
Note that type='email' predicate means child node with string value 'email':
<input>
<type>email</type>
</input>
While #type='email' means attribute type with value "email"
The previous answer is correct but You can try this also //input[#type='email']
The generic syntax is something like as mentioned below for xpath
// - means relative xpath, can be present anywhere inside DOM
tagName - means html tags like td,tr,span,br,input etc
#- denotes start of attribute name present inside html tag
value - actual attribute value present inside DOM
//tagName[#attribute='value']
You can use any XPath, as some are already mentioned by #Andersson and #zsbappa
some others are
//input[#class='text-input text-input-md' and #type='email']
//input[contains(#type,'email')]
Since you are using WATIR, you don't have to write xpath, write the below code, it would work.
b.text_field(type: "email").set "abc#gmail.com"

Is it okay to use such xpath to find web elements?

Consider this xpath which should always return one element.
//div[#id='MyDiv123']/div[contains(#class, 'super')]
Assume that we won't add anymore divs whose class is super. Given that info, I don't think that it is a good idea to use /div[contains(#class, 'super')]because the xpath will break if div[contains(#class, 'super')] is placed inside another element.
Shouldn't we be using //div[contains(#class, 'super')] instead ?
I don't like using XPaths for locators that can be written as a CSS selector. I think it's much simpler as
#MyDiv123 > div.super
or just
div.super
if it's unique on the page.
XPath contains() is a string match. All the elements below will match your XPath locator but none of them will match the CSS selectors above.
<div class="super-duper" ...>
<div class="superior" ...>
<div class="abcsuperdef" ...>
... you get the idea...
There is no defined Best Practices while writing xpaths. It all boils down to how effective xpath can be written.
I don't see any issue with the xpath as :
//div[#id='MyDiv123']/div[contains(#class, 'super')]
Of-coarse there ca be some improvements as follows :
As an enduser you won't be sure how the class attribute super impacts the HTML or which elements have this attribute. So in that case to identify the WebElement uniquely it would be wise to include the ancestor <div> tag with id as MyDiv123.
But it doesn't looks like the classname super can be dynamic. Hence you can avoid the keyword contains within the xpath and rewrite it as :
//div[#id='MyDiv123']/div[#class='super']