Selenium Web driver: How to get preceding element from a nested span text using Java code? - selenium-webdriver

I have a web page with below HTML format. This is just a sample and a part of code.
<div id="content">
........... Many other tags go in here......
<div id="1234"> // This id number is not constant and so cant hard code in xpath
<img class="float-right ng-scope" width="85" data-ng-click="highlightItem()" data-ng if="showThumbnail" ng-src="/server/image" src="/server/image">
<p>
<span data-ng-transclude="" data-ng-class="{ selected: isActive }">
<span class="ng-scope">My sample text</span>
<br class="ng-scope">
</span>
</p>
</div>
</div>
I have the text "My sample text" as my input. (There are many such div blocks and each has different span text). With this, I need to find the img element and click on it. I tried the below code : (referenceText variable = "My sample text")
String xPath = "//div[#id='content']//span[contains(text(),'" + referenceText + "')]";
// Get element of the text i.e get span element
WebElement element = getWebElementByXpath(getWebDriver(), xPath); // Gets span element
// Works fine !
// Get its parent element which is again another span
WebElement parentElement = getParentElement(element, xPath); // Gets next level span
// Works fine !
// Get its parent element p
WebElement grandParentElement = getParentElement(parentElement, xPath);
// Does not get its parent element 'p' instead return span element again
// Get preceding element for p which is img element
grandParentElement.findElement(By.xpath("./preceding-sibling::img")).click();
// Does not work as element p is not obtained.
getParentElement method is as below:
public static WebElement getParentElement(WebElement element, String xPath){
return element.findElement(By.xpath((xPath + "/..")));
}
Problem : I am able to get the span element and its parent span element but unable to get the p element and its sibling element img. I want to get img element using the span element. Any help on this would be great ! Thanks in advance.

Try the below XPAth for the image tag having "My sample text" as span value.
//div[#id='content']//div[.//span[span='My sample text']]/img
Refer http://www.xpathtester.com/xpath/b1d50008dd4be8ab7545548c4b8238f5

Simple open browser and check unique css locator, then check if that locator works for U in java code.

Try this xpath for getting grandparent 'p' from the 'span', with text "My sample text":
//span[.='My sample text']/../..
Try this xpath for getting the sibling 'img' of grandparent 'p', from the 'span' with text "My sample text":
//span[.='My sample text']/../../preceding-sibling::img

Try out with:
//span[.='My sample text']/ancestor::div/img

Thanks all for your help ! The below Xpath worked fine for me.
String xPath = "//div/p/span/span[contains(text(),'My Sample Text')]/../../..//img"

Related

Selenium can't find elements until I inspect the page

I have quite a weird problem.
There's a website that has the following two buttons (I can see them when I inspect the page):
button 1
<ul class=" _3dEhb">
<li class = " LH76I">
<a class="-na14 _81NM2" href="/preview/">
<span class="g47FY 10XF41"</span>" preview"
<li class = " LH76I">
<a class="-na14 _81NM2" href="/launch/">
<span class="g47FY 10XF41"</span>" launch"
I'm using the python selenium code
buttons = driver.find_element_by_class_name('LH76I')
if I run it without inspecting the webpage, this code gives me an empty list.
However, if I debug and I inspect the webpage, the same code gives me 2 items in the list.
What am I doing wrong?
Thanks
You should use driver.find_elements_by_class_name instead because you are trying to get a list of elements with same identifier. Try the following code:
buttons = driver.find_elements_by_class_name('LH76I')
Then, if you want to click or something, you would do:
buttons[0].click()
EDIT - You can try the way the list items are generally extracted:
main_list = driver.find_element_by_class_name('_3dEhb') //gets the main ul element
List<WebElement> list_items = main_list.findElements(By.tagName("li"));
for x in range(0, len(list_items)):
{
// whatever you want to do with the item
}

How to find the anchor text from Web Element located using CSS Locator?

I have a list of anchors in HTML page with id, href, etc attributes.
<a id="vRecords534534_link" onclick="theEvent=event;openModal(this.href, {width: 640});return false;" href="https://example/sourceDetailAction.do?NoticeId=534615198&webFlow=gcaMain">SIXER</a>
<a id="vRecords64353_link" onclick="theEvent=event;openModal(this.href, {width: 640});return false;" href="https://example/sourceDetailAction.do?NoticeId=534615198&webFlow=gcaMain">CROSS</a>
and so on. Look at the id attribute having starting and ending text.
I used CSS Locator to do this:
#FindBy(how=How.CSS, using="a[id^='vRecords'][id$='link']")
protected List<WebElement> vRecordsList;
public void getVendorRecordList(){
System.out.println(vRecordsList.size());
for(WebElement s : vRecordsList){
System.out.println("Record List ::"+s.getAttribute("value"));
}
}
From the above code, I am able to find all the ids stars-with with vRecords and ends-with link.
Problem : From this, i want to get the anchor value for each link like "SIXER", "CROSS" from the anchor links above.
If any other approach is feasible, then also revert.
getAttribute basically use for getting the element attribute property. But here you want to get the text inside a. So achieving this there is a method getText() Provided by selenium as below :-
for(WebElement s : vRecordsList){
System.out.println("Record List ::"+s.getText());
}
Edited :- If unfortunately getText() does not work here try using getAttribute("innerHTML") as below :-
for(WebElement s : vRecordsList){
System.out.println("Record List ::"+s.getAttribute("innerHTML"));
}
Or using getAttribute("textContent") as below :-
for(WebElement s : vRecordsList){
System.out.println("Record List ::"+s.getAttribute("textContent"));
}
Hope it helps..:)

Chaining an element using css containing text and accessing an associated field

I need to access the input field in the below html. The way the page is setup I need to chain using the 'Address Line 1' text and then sending text to the input field. The input field id changes and so doesn't the layout of the fields depending on user preference. I am struggling. If you need some more information feel free to ask I did not want to overload with too much information.
<td class="labelCol requiredInput">
<label for="00N36000000xina"><span class="assistiveText">*</span>Address Line 1</label>
</td>
<td class="dataCol col02">
<div class="requiredInput">
<div class="requiredBlock"></div>
<input id="00N36000000xina" maxlength="255" name="00N36000000xina" size="20" tabindex="4" type="text">
</div>
</td>
I have accessed like this:
element(by.css('div.pbSubsection:nth-child(3) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > input'))
However depending on where the user puts the fields it can move around. So what I was hoping was to be able to access the label\ and use that to pinpoint its input field.
I don't know protractor but I cobbled together some code that hopefully will work or be close and I'll give you the thought process and some info and hopefully you can use it to fix my code, if needed, and solve the problem.
Start by finding an element by XPath, "//label[text()='Address Line 1']". This searches for a LABEL tag that contains "Address Line 1". Once you find that element, get the label attribute. From your HTML, this label is the id for the INPUT element you want. Now use the id to find the element and do with it what you want.
id = element(by.xpath("//label[text()='Address Line 1']")).getAttribute("label")
input = element(by.id(id))
input.sendkeys("some text")
Haven't tested this myself, but you could try something like this:
// $ is shorthand for element(by.css())
$('div.assistiveText').getAttribute('for').then(function (val) {
// locate the <input> by the value of the attribute on <label>
element(by.id(val)).sendKeys('abc'); // replace sendKeys with your intended function
});
Or if that first locator on the label isn't specific enough, swap out $('div.assistiveText') for element(by.cssContainingText('Address Line 1'))
I tried it for other attributes (I don't have a for attribute anywhere in my app) and it seemed to work for me.
Try this:
List<WebElement> elementList = driver.findElements(By.cssSelector("tbody > tr"));
for (WebElement element : elementList) {
if(element.findElement(By.cssSelector("td.labelCol > label")).getText().equalsIgnoreCase("Address Line 1")) {
element.findElement(By.cssSelector("input[type='text']")).sendKeys("textToInput");
}
}

How to type in text box in selenium?

I used sendKeys method, first time when I ran my script it worked but from second time it is not working. Script is finding the element but not entering in text box.
Please suggest if there is any other way to enter text in text box. and why it is not working.
Here is my code:
System.out.println(driver.findElements(By.xpath("//*[#id='logcomments']")).size());
driver.findElement(By.xpath("//*[#id='logcomments']")).sendKeys("Log_Testing"); // textBox
driver.findElement(By.xpath("//*[#id='postLog']/img")).click(); //enter button
HTML code :
<div style="position:relative;top:40px;">
<div>
<span id="actualcommentCount">1</span>
<span> Comments </span>
</div>
<div>
<textarea id="logcomments" type="text" style="resize:none; width:80%;" placeholder="Comments"> </textarea>
<span id="postLog">
<img style="cursor:pointer;width:45px;color:#337ab7;float: right;margin-top:-5px; margin-right:10px;font-size:30px;" src="images/poll_fly.png">
</span>
</div>
</div>
Can you share the HTML of the page?
You could try :-
driver.findElement(By.id("logcomments")).sendKeys("Some Text");
What error are you getting when you run the test?
You should try as below :-
WebElement el = driver.findElement(By.id("logcomments"));
el.click();
el.sendKeys("Log_Testing");
driver.findElement(By.xpath("//*[#id='postLog']/img")).click();
Note :- You need to focus on text area before set value so need to use el.click() to focus on text area because when you try to .sendKeys() it goes to set value but due to focus is not on text area it could not be set.
Hope it will help you..:)
If you want to type on keyboard then you need to use robot class as below. But ensure you have already clicked on textbox before you start typing.
typeKeysStringUsingRobotClass("hey123");
}
public void typeKeysStringUsingRobotClass(String text){
String[] arr = text.split("");
for(int i=0; i<arr.length; i++)
keyPressUsingRobotClass(arr[i]);
}
public void keyPressUsingRobotClass(String key){
Robot rb = new Robot();
if(key.equalsIgnoreCase("A")){ rb.keyPress(KeyEvent.VK_A); rb.keyRelease(KeyEvent.VK_A);
if(key.equalsIgnoreCase("B")){ rb.keyPress(KeyEvent.VK_B); rb.keyRelease(KeyEvent.VK_B);
.
.
.
if(key.equalsIgnoreCase("0")){ rb.keyPress(KeyEvent.VK_0); rb.keyRelease(KeyEvent.VK_0);
}
My suggestion is to try with javaScript executed to add text to the text box.
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("document.getElementById('logcomments').value='Yourvalue is here'");
And also, plz post if there is an exception or error is there. Without that, it is hard to find a solution.

Getting text of element without including text of sub-element with jsoup

I'm using jsoup to parse HTML. There are list items that look like this:
<li><span class="chk">X</span>Category Name</li>
I want to get the text of the li NOT including the text of the span. So I want to get "Category Name" without the "X". (If I invoke the text() method on the li element, I get "XCategory Name".) How can I exclude the sub-span?
ownText() method will help you here.
Document document = Jsoup.parse("<ul><li><span class=\"chk\">X</span>Home</li><li><spanclass=\"chk\">X</span>Category Name</li></ul>");
Elements elems = document.select("li");
for(Element elem : elems){
System.out.println(elem.ownText());
}

Resources