Unable to print the Text associated with the li tag - selenium

I have a Google Search bar with a drop down and the options are under a UL and the actual ones under the li. I am unable to retrieve the data field of the li, while I am able to retrieve the count. Have tried with the List elements and looping thru it ,but no luck. The drop with all the Options is Not visible.
I have to print the Titles associated with the li using Selenium Web driver.
Below is what I tried:
ul class=classname> xxx – GSA 2 days ago
wb.findElement(By.xpath("<>")).click();
List items = html_list.findElements(By.tagName("li")); System.out.println("The size of the elements is " + items.size()); for(WebElement item : items) { html_list.sendKeys( Keys.DOWN ); //simulate visual movement
wb.manage().timeouts().implicitlyWait(1000, TimeUnit.SECONDS); System.out.println(item.getText());
}

Hypohesis #1: You don't wait for the page to load after the click on line 1. The li elements are in the DOM but they are not completely loaded. You could test the hypothesis by introducing a delay between line 1 and line 2. I have code that I use to wait for page loads but the specifics depend on the JavaScript framework (e.g. jQuery, AngularJs), on the loading spinner implementation and browser readystate. My readystate logic looks like this:
/**
* Wait for browser readystate to be complete. But don't wait forever.
*
* #param webDriver
*/
public void waitForBrowserReadystateComplete(WebDriver webDriver) {
for (int a=0; a<20; a++) {
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
if (javascriptExecutor.executeScript("return document.readyState")
.toString().equals("complete")) {
break;
}
sleepResponsibly(500);
}
}
public void sleepResponsibly(int timeMillisecond){
try{
Thread.sleep(timeMillisecond);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
}
Hypthosis #2: The text nodes are complex. I have experienced a failure in method getText() to return text when the text nodes code complex formatting. I got around this by invoking the following instead:
public static String getTextFromElementsTextNodes(WebDriver webDriver, WebElement element) throws IllegalArgumentException {
String text = "";
if (webDriver instanceof JavascriptExecutor) {
text = (String)((JavascriptExecutor) webDriver).executeScript(
"var nodes = arguments[0].childNodes;" +
"var text = '';" +
"for (var i = 0; i < nodes.length; i++) {" +
" if (nodes[i].nodeType == Node.TEXT_NODE) {" +
" text += nodes[i].textContent;" +
" }" +
"}" +
"return text;"
, element);
} else {
throw new IllegalArgumentException("driver is not an instance of JavascriptExecutor");
}
return text;
}
A caveat is that getTextFromElementsTextNodes() may return non-ASCII charcters so I do the following:
System.out.println(getTextFromElementsTextNodes(wb,item).replaceAll("[^\\x00-\\x7F]", " "));

I could finally able to retrieve the options under the li. This is what I did and it worked
for(WebElement MyListOptions: listOfLiTags) {
String myoptions=serchOptions.getAttribute("<<The actual attribute value which is storing my options>>");
System.out.println("THE List Options are" + txt3);
}

Related

Find element locator on IE webddriver (Any driver actually)

This post is to share a solution I've built to help find elements on webdrivers using System.in, since there are no (at least that I'm aware of) extensions to find locators on IE.
This solution is not ideal and may present issues, however, you can easily implement navigations and it gives you a quick response/highlight the elements.
Package:
package locator;
Imports:
import org.openqa.selenium.*;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
Class:
public class LocatorHelper {
private static WebDriver driver = null;
public static void main(String[] args) {
createIE();
driver.get("http://www.google.com.br/");
JavascriptExecutor js = (JavascriptExecutor) driver;
Scanner scan = new Scanner(System.in);
String mainXpath = "";
String lastXpath = "";
while (!mainXpath.equals("exit")) {
System.out.println("Type an xpath: ");
lastXpath = mainXpath;
mainXpath = scan.nextLine();
if (lastXpath.length() > 0) {
List<WebElement> elements = getElements(lastXpath, true);
if (elements != null) {
for (WebElement element : elements) {
js.executeScript("arguments[0].style.border='1px solid orange'", element);
}
}
}
List<WebElement> elements = getElements(mainXpath);
if (elements != null) {
for (WebElement element : elements) {
js.executeScript("arguments[0].style.border='3px solid red'", element);
}
}
System.out.println("---------------------------------------------------------------------------------------------------");
}
}
private static List<WebElement> getElements(String xpath, boolean... disableLog) {
List<WebElement> elements = null;
try {
elements = driver.findElements(By.xpath(xpath));
int count = elements.size();
if (disableLog.length == 0) {
if (count > 1) {
System.out.println("The xpath '" + xpath + "' returned " + count + " elements");
} else if (count == 1) {
System.out.println("The xpath '" + xpath + "' returned one element");
} else {
System.out.println("The xpath '" + xpath + "' returned no elements");
}
}
} catch (InvalidSelectorException e) {
if (disableLog.length == 0) {
System.out.println("The xpath '" + xpath + "' is not valid");
}
}
return elements;
}
private static void createIE() {
//your driver locator
System.setProperty("webdriver.ie.driver", "src/main/resources/drivers/IEDriverServerNew.exe");
DesiredCapabilities caps = DesiredCapabilities.internetExplorer();
caps.setCapability("ignoreZoomSetting", true);
caps.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
caps.setCapability(InternetExplorerDriver.ELEMENT_SCROLL_BEHAVIOR, true);
DesiredCapabilities.internetExplorer().setCapability("ignoreProtectedModeSettings", true);
caps.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
caps.setCapability(CapabilityType.SUPPORTS_JAVASCRIPT, true);
caps.setJavascriptEnabled(true);
driver = new InternetExplorerDriver(caps);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
}
In this image, the locator found a single element
Example of a single element located
In this image, the locator found 20 elements
Example of 20 elements found
As you type the locators on the terminal, it will highlight the current elements in red and all previous elements found will be highlighted in orange with a thinner line.
Example of input
Hope it helps

Get dropdown values using actions class

After moving to the value which is present in dropdown, i want to get it using actions class. Below is the code i have written. i am trying to print the dropdown values. HTML tag for dropdown is input(for select i have code). Please help me
public static void caseSearch()
{
try
{
Actions a=new Actions(driver);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
logger.info("clicking on cases tab :: ");
driver.findElement(By.xpath(loader.getProperty(Constants.CaseTab))).click();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
WebElement ele=driver.findElement(By.xpath(loader.getProperty(Constants.CaseSearch)));
ele.click();
for(int i=0;i<=20;i++)
{
//i want to print the first value of dropdown in console
a.sendKeys(Keys.DOWN,Keys.DOWN,Keys.DOWN).build().perform();
String value=ele.getText();
System.out.println("value is = "+value);
a.sendKeys(Keys.DOWN,Keys.DOWN).build().perform();
Thread.sleep(3000);
a.sendKeys(Keys.ENTER).build().perform();
}
}
catch(Exception e)
{
logger.info("case search method is not executed :: " +e);
}
}
I think you forgot to get the value from the dropdown box.
You need to use the Select Class to get it.
Actions key = new Actions(browser);
WebElement dropdownElement = this.browser.findElement(By.xpath("YOUR DROPDOWN ELEMENT"));
Select dropOptions = new Select(dropdownElement);
int elements = dropOptions.getOptions().size();
for (int i = 0; i < elements; i++) {
dropdownElement.click();
if (i > 0) {
Thread.sleep(1000L);
key.sendKeys(Keys.DOWN).build().perform();
Thread.sleep(1000L);
key.sendKeys(Keys.ENTER).build().perform();
}
else {
Thread.sleep(1000L);
ActionPerformers.sendActionKey(browser, Keys.ENTER);
}
System.out.println("ELEMENT " + i + " -> " + dropOptions.getFirstSelectedOption().getText()); //Here you will get the selected Value...
}
This is only an exemple, I hope it suits you.

Can we retrieve text/drag n drop elements using JavascriptExecutor similarly we are doing with gettext/Actions in Selenium

In below code if the my div containing the attribute as text then only it will return the text. I am new/curious to find new way to use JavascriptExecutor instead of selenium as they are much faster than selenium
WebElement gettexxxt= driver.findElement(By.id("loginButton"));
JavascriptExecutor executor1 = (JavascriptExecutor) driver;
String text = (String) executor1.executeScript("return arguments[0].text;", gettexxxt));
System.out.println(text);
Right now I am retrieving the text as below using JavascriptExecutor
WebElement Rent_rentc =(WebElement) ((JavascriptExecutor) driver).executeScript("return document.getElementById('loginButton');");
System.out.println(Rent_rentc.getText());
Is there any way to get text using JavascriptExecutor except above solution?
Note:- I am editing this question as I got the answer of how to gettext from JavascriptExecutor by referring Vicky answer in this page. Please refer from here to answer my next problem that how we can perform drag and drop using JavascriptExecutor.
I am facing error in below code, Error :- No match found
driver.get("https://jqueryui.com/droppable/");
WebElement iframe=driver.findElement(By.xpath(".//*[#id='content']/iframe"));
driver.switchTo().frame(iframe);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
try{
String filePath = "./dnd.js-master//dnd.js";
String source = "div[id='draggable']";
String target = "div[id='droppable']";
StringBuffer buffer = new StringBuffer();
String line;
BufferedReader br = new BufferedReader(new FileReader(filePath));
while((line = br.readLine())!=null)
buffer.append(line);
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcherSource = pattern.matcher(source);
Matcher matcherTarget = pattern.matcher(target);
String cssSource = "#" + matcherSource.group(1);
String cssTarget = "#" + matcherTarget.group(1);
String javaScript = buffer.toString();
javaScript = javaScript + "$('" + cssSource + "').simulateDragDrop({ dropTarget: '" + cssTarget + "'});";
((JavascriptExecutor)driver).executeScript(javaScript);
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
Another code error :- expected expression, got '.'
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://jqueryui.com/droppable/");
String line = null;
String source = ".//*[#id='draggable']";
String target = ".//*[#id='droppable']";
try{
BufferedReader br = new BufferedReader(new FileReader("./dnd.js-master//Drag.js"));
StringBuffer buffer = new StringBuffer();
while((line = br.readLine())!=null)
buffer.append(line);
String javaScript = buffer.toString();
Thread.sleep(5000);//you can remove it added just to show you that drag and drop appeared as it is too fast
String java_Script = javaScript + "$("+source+").simulateDragDrop({ dropTarget: "+target+"});";
((JavascriptExecutor)driver).executeScript(java_Script);
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
}
Use the below Javascript to get the text of the Element
String Rent_rentc =(String) ((JavascriptExecutor) driver).executeScript("return document.getElementById('loginButton').getElementsByTagName('div')[0].innerHTML;");
Also, I want to know can we perform drag and drop using
JavascriptExecutor
A working example using the above javascript library is already posted in stackoverflow
Note:- I am editing this question as I got the answer of how to
gettext from JavascriptExecutor by referring Vicky answer in this
page. Please refer from here to answer my next problem that how we can
perform drag and drop using JavascriptExecutor.
I am facing error in below code, Error :- No match found
EDIT :
(function ($) {
$.fn.simulateDragDrop = function (options) {
return this.each(function () {
new $.simulateDragDrop(this, options);
});
};
$.simulateDragDrop = function (elem, options) {
this.options = options;
this.simulateEvent(elem, options);
};
$.extend($.simulateDragDrop.prototype, {
simulateEvent: function (elem, options) {
/*Simulating drag start*/
var type = 'dragstart';
var event = this.createEvent(type);
this.dispatchEvent(elem, type, event);
/*Simulating drop*/
type = 'drop';
var dropEvent = this.createEvent(type, {});
dropEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent($(options.dropTarget)[0], type, dropEvent);
/*Simulating drag end*/
type = 'dragend';
var dragEndEvent = this.createEvent(type, {});
dragEndEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent(elem, type, dragEndEvent);
},
createEvent: function (type) {
var event = document.createEvent("CustomEvent");
event.initCustomEvent(type, true, true, null);
event.dataTransfer = {
data: {
},
setData: function (type, val) {
this.data[type] = val;
},
getData: function (type) {
return this.data[type];
}
};
return event;
},
dispatchEvent: function (elem, type, event) {
if (elem.dispatchEvent) {
elem.dispatchEvent(event);
} else if (elem.fireEvent) {
elem.fireEvent("on" + type, event);
}
}
});
})(jQuery);
save the above jquery to a file ex:Drag.js
driver.get("http://the-internet.herokuapp.com/drag_and_drop");
String line = null;
BufferedReader br = new BufferedReader(new FileReader("/path/Drag.js"));
StringBuffer buffer = new StringBuffer();
while((line = br.readLine())!=null)
buffer.append(line);
String javaScript = buffer.toString();
Thread.sleep(5000);//you can remove it added just to show you that drag and drop appeared as it is too fast
String java_Script = javaScript + "$('#column-a').simulateDragDrop({ dropTarget: '#column-b'});";
((JavascriptExecutor)driver).executeScript(java_Script);
}
please explain how it will work with the same div contain the or child
div will contains many similar attribute like div
<button id="loginButton">Submit<button>
document.getElementById('loginButton') //will find the first element with id loginButton
<a id="loginButton" class="initial" href="javascript:void(0)" onclick="pageController.submitForm(); return false;"><div>Login </div></a> <div>Login </div>
document.getElementById('loginButton').getElementsByTagName('div')[0]; //will find the first element with id loginButton and then first div child inside it
<a id="loginButton" class="initial" href="javascript:void(0)" onclick="pageController.submitForm(); return false;"><div>Login </div><div>Register</div></a>
document.getElementById('loginButton').getElementsByTagName('div')[1]; //will find the first element with id loginButton and then second div child inside it
<a id="loginButton" class="initial" href="javascript:void(0)" onclick="pageController.submitForm(); return false;"><div><div>Register</div></div></a>
document.getElementById('loginButton').getElementsByTagName('div')[0].getElementsByTagName('div')[0].innerHTML;//will find the first element with id loginButton and then first div child inside it and then locate the first div child inside it
//you can also use other attributes like document.getElementsByClassName
Can you please provide me some links also where from I can refer/learn
the formatting of the JavascriptExecutor
W3schools
Hope this helps you.Kindly get back if it is not working

How to handle multiple jQuery popup with selenium webdriver

I am working on java with selenium webdriver 2.39, we have application where multiple 'processing' popup is display for 2-5 sec and closed automatically, that is depend on data. Now, the question is how to handle this popup, this popup are jQuery popup. My script can only work further once all this three popup gets open and process data and get closed automatically. However, I can not use wait time as this script is used for load testing using JMeter, hence the process time may take more or less than 5 sec., Is there any way we can know if the popup exist or not on screen? I have used below given sample code but it returns only parent window and it does not identify jQuery popup, using below given code I can get if popup exist or not, but only if it is not jQuery popup. Can anyone help me?
public void FocusOnWindow() throws Exception{
int i=0;
do {
handles=driver.getWindowHandles();//get all windows
iterator = handles.iterator();
if(iterator.hasNext()){
subWindowHandler = iterator.next();
if(subWindowHandler==null){
i=0;
}else if(subWindowHandler!=null){
if(subWindowHandler!=parentWindowHandler){
popup = true;
i=2;
}
}
}
}while(i<2);
if(popup){
do{
handles=driver.getWindowHandles();
iterator = handles.iterator();
Thread.sleep(500);
if(iterator.hasNext()){
subWindowHandler = iterator.next();
if(subWindowHandler!=parentWindowHandler){
if(subWindowHandler==null){
String source = driver.getPageSource();
if(source==null){
i=2;
}
}
}else {
i=0;
}
//System.out.println("No any other popup.");
}
}while (i<2);
}
}
First of all, I'll strongly suggest not to put hard wait at all.
If you are aware of any of the element which is unique and part of post processing pop up screen (i.e. resulted user screen) then make use of selenium waitForElement() API function which intelligently wait for element to appear and once appeared performs further actions.
Take a look at this link which explains the advantages of using it.
And with Java bindings for selenium in place, You can use something like this -
WebDriverWait wait = new WebDriverWait(driver, /*seconds=*/3);
elementOfPage = wait.until(presenceOfElementLocated(By.id("id_of_element")));
Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
return new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
public boolean runScript(){
JavascriptExecutor js = (JavascriptExecutor) driver;
return (Boolean) js.executeScript("return jQuery.active==0;");
}
public void FocusOnWindow() throws Exception{
int i=0;
do {
if(!runScript()){
System.out.println("Popup exists");
i++;
}else{
i=5000;
System.out.println("Popup does not exists");
}
}while(i<5000);
}

Selenium WebDriver generates StaleElementReferenceExeption on getText() on table elements

The current environment:
Selenium Server version 2.37.0
RemoteWebDriver running on Firefox
no Ajax / asynchronously loaded content
My tests are attempting to validate the content of each cell of an HTML table. Before accessing any table element an explicit wait verifies that the <tbody> element exists
ExpectedCondition<WebElement> recruitTableIsPresent = ExpectedConditions.presenceOfElementLocated(By.id("newRecruitFieldAgentWidget:newRecruitDataTable_data"));
new WebDriverWait(driver, 5).until(recruitTableIsPresent);
Once the table is verified to exist, data is pulled out by row and column
private Stats[] parseStats() {
String xpath = "//tbody[#id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]";
Stats[] stats = new Stats[3];
for (int i = 0; i < stats.length; i++) {
String inProgresOrders = cellContent(xpath, i, 1);
String maxCapacity = cellContent(xpath, i, 2);
String allocationRatio = cellContent(xpath, i, 3);
Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio);
}
return stats;
}
private String cellContent(String xpathTemplate, int row, int cell) {
String xpath = String.format(xpathTemplate, row + 1, cell + 1);
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
WebElement elementByXPath = driver.findElementByXPath(xpath);
return elementByXPath.getText();
}
I don't see any race conditions, since the table content is populated with the page, and not in an asynchronous call. Additionally, I have seen other answers that suggest invoking findElement() via the driver instance will refresh the cache. Lastly, the explicit wait before accessing the element should ensure that the <TD> tag is present.
What could be causing the getText() method return the following exception:
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
It's worthwhile to note that the failure is intermittent. Some executions fail while other passes through the same code pass. The table cell causing the failure are also not consistent.
There is a solution to this using Html-Agility-Pack.
This will work only if you want to read the data from that page.
This goes likes this
//Convert the pageContent into documentNode.
void _getHtmlNode(IWebDriver driver){
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(driver.PageSource);
return htmlDocument.DocumentNode;
}
private Stats[] parseStats(){
String xpath = "//tbody[#id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]";
Stats[] stats = new Stats[3];
for (int i = 0; i < stats.Length; i++) {
String inProgresOrders = cellContent(xpath, i, 1);
String maxCapacity = cellContent(xpath, i, 2);
String allocationRatio = cellContent(xpath, i, 3);
Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio);
}
return stats;
}
private String cellContent(String xpathTemplate, int row, int cell) {
String xpath = String.format(xpathTemplate, row + 1, cell + 1);
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
var documentNode = _getHtmlNode(driver);
var elementByXPath = documentNode.SelectSingleNode(xpath);
return elementByXPath.InnerText;
}
now read any data.
Some tips for using htmlNode.
1. Similar to driver.FindElement: document.SelectSingleNode
2. Similar to driver.FindElements: document.SelectNodes
3. Similar to driver.Text: document.InnerText.
For more search regarding HtmlNode.
Turns out there was a race condition as I've already mentioned. Since jQuery is available via PrimeFaces there is a very handy solution mentioned in a few other posts. I implemented the following method to wait for any asynchronous requests to return before parsing page elements
public static void waitForPageLoad(JavascriptExecutor jsContext) {
while (getActiveConnections(jsContext) > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
private static long getActiveConnections(JavascriptExecutor jsContext) {
return (Long) jsContext.executeScript("return (window.jQuery || { active : 0 }).active");
}
Each built in driver implementation implements the JavascriptExecutor interface, so the calling code is very straightforward:
WebDriver driver = new FirefoxDriver();
waitForPageLoad((JavascriptExecutor) driver);