I'm new to Selenium webdriver. I came across a requirement where I have to run my test which clicks on all links with in a section. Can someone help me with the Java code for this. Attached a image which shows firebug properties of that particular section.
I have tried the below code but it returns me a null list.
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://dev.www.tycois.com/");
driver.manage().window().maximize();
List<WebElement> allElements = driver.findElements(By.xpath("html/body/div[10]/div/div[1]/div[3]/ul[1]/li[5]"));
System.out.println(allElements);
for (WebElement element: allElements) {
System.out.println(element.getText());
element.click();
}
}
Thanks in advance.
The details aren't clear but it looks like you are trying to print the links in the INDUSTRIES section of the footer. If that's true, this should work.
driver.get("https://dev.www.tycois.com/");
WebElement industries = driver.findElement(By.cssSelector("div.columns.three.alpha > ul"));
List<WebElement> links = industries.findElements(By.tagName("li"));
for (int i = 1; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
You can't click the links in this loop because once you click the first one, you will no longer be on the page. I would suggest that you store the URLs from each link in an array and then driver.get(url) for each one. Or you could store the expected URLs in an array and compare the URLs from the links to the expected URLs and not have to navigate at all. The choice is up to you...
The solution from JeffC works with the tweak detailed below -
driver.get("https://dev.www.tycois.com/");
WebElement industries =
driver.findElement(By.cssSelector("div.columns.three.alpha > ul"));
List<WebElement> links = industries.findElements(By.tagName("li"));
for (int i = 0; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
The alternate answer above, which I cannot comment on because I'm new to the site had
for(int i=1; i < links.size(); i++)
However this misses off the first element in the list. The suggested fix to use -
for(int i=1; i <= links.size(); i++)
will cause an IndexOutOfBoundsException.
To fix, simply set your iterator to start at 0 instead of 1
You could use like for example:
driver.findElements(By.xpath("//li[contains(#class,'managed-services')]/ul/li/a"));
It is usually bad idea to use XPath attached to root of html i.e Absolute xpath, you should always try to use the shortest selectors possible i.e Relative xpath.
Also remember that if links are hidden, you need to trigger action, which enables them - like open menu for instance.
You can try with the below code.
Just change the xpath according to your application.
List<WebElement> liElements = driver.findElements(By.xpath(".//*[#id='fk-mainhead-id']/div[2]/div/div/ul/li"));
System.out.println(liElements);
for(int i=1; i <= liElements.size(); i++)
{
WebElement linkElement = driver.findElement(By.xpath(".//*[#id='fk-mainhead-id']/div[2]/div/div/ul/li[" + i + "]/a"));
System.out.println(linkElement.getText());
}
WebElement industries = driver.findElement(obj.getElement("history_list"));
List<WebElement> links = industries.findElements(By.tagName("li"));
boolean a = false;
Thread.sleep(10000);
for (WebElement option : links) {
System.out.println("value =" + option.getText());
String s = option.getText();
if (s.equals(new_site_name)) {
a = true;
break;
} else {
continue;
}
}
Related
I am trying to get correct page number for Seattle which is 7 and then click on every pages from 1 to 7. I have 2 problems see the parts with asterisk ** below:
1) I am not sure how to write the xpath so that I get 7 instead of 11
2) The while loop is an infinite loop
public class Job {
public static WebDriver driver;
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Users\\Shahriar\\Downloads\\chromedriver_win32\\chromedriver.exe");
driver= new ChromeDriver();
driver.get("https://web.expeditors.com/careers/#/listTop");
driver.manage().window().maximize();
//Disable the cookie notification at bottom
driver.findElement(By.xpath("//a[#id='hs-eu-decline-button']")).click();
// Find more cities and scroll down
driver.findElement(By.xpath("//a[#id='moreCity']")).click();
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollBy(0,5500)", "");
//Locate US-Seattle and click and verify
driver.findElement(By.xpath("//label[#class='ng-binding']//input[#id='us~Seattle']")).click();
String state=driver.findElement(By.xpath("//a[contains(text(),'United States - Seattle')]")).getText();
Assert.assertEquals(state, "United States - Seattle");
**//Number of search pages found should be 7
List<WebElement> resultPages=driver.findElements(By.xpath("//a[#href='#listTop']"));
Assert.assertEquals(7, resultPages.size());**
**//Go to each page by clicking on page number at bottom
int count=0;
WebElement next_button=driver.findElement(By.xpath("//a[#ng-click='setCurrent(pagination.current + 1)']"));
while (resultPages.size()!=0){
next_button.click();
count++;
System.out.println("Current page is "+ count);
}**
//driver.close();
}
}
I could use some help. Thanks in advance for your time.
Here is the logic that you need.
//Number of search pages found should be 7
List<WebElement> resultPages=driver.findElements(By.xpath("//a[#href='#listTop' and #ng-click='setCurrent(pageNumber)']"));
Assert.assertEquals(7, resultPages.size());
for (int i = 1; i <= resultPages.size(); i++) {
driver.findElement(By.xpath("(//a[#href='#listTop' and #ng-click='setCurrent(pageNumber)'])[" + i +"]")).click();
System.out.println(driver.findElement(By.xpath("(//a[#href='#listTop' and #ng-click='setCurrent(pageNumber)'])[" + i +"]")).getText());
}
Your while loop is counting pages, but the condition itself appears to be static (I can't tell without the actual page). You probably want something more like
int count=0;
WebElement next_button=driver.findElement(By.xpath("//a[#ng-click='setCurrent(pagination.current + 1)']"));
while (next_button != null){
next_button.click();
count++;
System.out.println("Current page is "+ count);
next_button=driver.findElement(By.xpath("//a[#ng-click='setCurrent(pagination.current + 1)']"));
}
As for your 7 vs 11 result pages, again it's hard to tell without the HTML, but your XPath search is for By.xpath("//a[#href='#listTop']") so I'd check and see what's in your HTML with listTop. Perhaps other elements are somehow using that anchor tag?
Please refer the below code, this code will fetch all the orderID from findtable method and it passes all of the orderID to clickonIndividualOrderID method
so the cursor moves to each orderid and it clicks on it, a new page will come and it fetch the status and clicks on done and it comes back to old page now if we try to select next orderID, it will throw the exeception
Could you please suggest some approaches to resolve this issue
Thanks in advance
List<WebElement> orderID = new ArrayList<WebElement>();
List<WebElement> statusID = new ArrayList<WebElement>();
public void OrderandReleases()
{
orderID = outboxpage.findtable(orderID);
util.pause("1");
statusID = outboxpage.findordernumber(statusID, orderID);
}
public List<WebElement> findOrderID(List<WebElement> orderID) {
WebElement table = driver.findElement(By.id("_kod7c3"));
List<WebElement> allRows = table.findElements(By.tagName("tr"));
//And iterate over them, getting the cells
for (int i = 1; i < allRows.size(); i++) {
List<WebElement> alltd = allRows.get(i).findElements(By.tagName("td"));
for (int j = 0; j < alltd.size(); j++) {
if (j == 1) {
orderID.add(alltd.get(j));
continue;
}
}
}
return orderID;
}
public List<WebElement> clickonIndividualOrderID(List<WebElement>
statusID,List<WebElement> orderID){
for (int i = 0; i < orderID.size(); i++) {
WebElement table = driver.findElement(By.id("_kod7c3"));
if (table.isDisplayed()) {
System.out.println("Clicking on
order="+orderID.get(i).getText()); -> //first time it will run fine , second time when it loops back it will thow the execption StaleElementReferenceException here
orderID.get(i).click(); -> //it is clicking on a order link and it will take me to next page
driver.findElement(By.id("_jxndro")).click();
WebElement table2 = driver.findElement(By.xpath("//*
[#id=\"_mfb\"]"));
List<WebElement> allRows2 =
table2.findElements(By.tagName("tr"));
String col = "";
for (int j = 1; j < allRows2.size(); j++) {
List<WebElement> alltd2 =
allRows2.get(j).findElements(By.tagName("td"));
int flag = 0;
for (int k = 0; k < alltd2.size(); k++) {
col = alltd2.get(k).getText().toString().trim();
System.out.println(col);
if (col.equals("Failed")||col.contains("FE-")) {
statusID.add(alltd2.get(++k));
driver.findElement(By.id("_uvsub")).click(); --> // it will take me back to the first page
flag =1;
break;
}
}
if(flag==1)
break;
}
}
}
return statusID;
}
Whenever you find a specific exception from any third party code, you should look for information in the official documentation of said code if available. You can find information about the "StaleElementReferenceException" here
In said page you will find this
The most frequent cause of this is that page that the element was part of has been refreshed, or the user has navigated away to another page.
You're navigating to another page, so all the references will be lost. The driver do not have the knowledge that its the same page, with the same objects.
You need to look for a different way to keep track of which links you already clicked, or open the links in a new tab/window, to do whatever you need to, and then dispose the tab/window instead of navigating back.
The official documentation for StaleElementReferenceException says:
Indicates that a reference to an element is now "stale" --- the element no longer appears on the DOM of the page.
If you are navigating back and forth between pages, as you are doing, then this is the expected behaviour.
The normal way to approach this is to not keep track of the WebElements outside of the loop, but find them inside the loop during each iteration. Something like this:
// this will not change, but you need to adjust for your case!
By pageLocator = By.tagName("a");
int pageCount = driver.findElements(pageLocator).size();
for (int i = 0; i < pageCount; i++) {
WebElement pageLink = driver.findElements(pageLocator).get(i);
pageLink.click();
// at this point pageLink is gone stale!
// do some stuff
driver.navigate().back();
}
I want to print and then click on list of all items like home top stories, latest news, opinion etc each and every category as you can see in image but did get success please help..
List<WebElement> list=driver.findElements(By.id("com.readwhere.whitelabel.prabhatkhabar:id/left_drawer_list"));
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).getText()+"\n");
}
Most probably you are trying to find the list with wrong id. If in this window only category names are present as text, try find with texts.
After trying findElements with valid id, you need to click each category and then return to window containing the list again. Try this way:
// Trying to find the list with texts
List<WebElement> list = driver.findElements(By.className("android.widget.TextView"));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getText() + "\n");
list.get(i).click(); // clicking on each category
// navigate back to previous window
}
For navigating back, you can use this code:
driver.navigate().back();
try with the below code:
List<WebElement> listForSize =driver.findElements(By.id("com.readwhere.whitelabel.prabhatkhabar:id/left_drawer_list"));
int size = listForSize.size();
for (int i=0; i< size;i++)
{
//this is taken again because you are navigate back again
List<WebElement> list = driver.findElements(By.id("com.readwhere.whitelabel.prabhatkhabar:id/left_drawer_list"));
System.out.println(list.get(i).getText() + "\n");
list.get(i).click();
driver.navigate().back();
Thread.sleep(2000);//avoid this kind of waiting. wait using until
}
let me know if any error occurs.
I am writing in java a method using selenium that will clear a form entry, that is, several boxes may have text in them. My method will click a "clear search form" and then wait for all the boxes to be clear. I tried the following:
WebDriverWait wt = new WebDriverWait(driver, 30);
click("Clear Search Form", clearSearchForm);
for (int ind = 0; ind < boxes.size(); ind++) {
wt.until(ExpectedConditions.textToBePresentInElementValue(boxes.get(ind), ""));
}
however, it looks like the Expected Conditions waits for the text to contain "" rather than to equal "", so any text will contain "". I forgot to put in the clearSearchForm click, and the method succeeded anyway even though the text boxes were not clear, since they all contained "".
I tried to find an ExpectedConditions for the value to be equal to "" and not contain it but I could not.
I have seen people rewrite a wait method so they could customize it to what they want. When I searched with google I could not find examples, though I am sure there are examples, as I have seen them before. I just can't find them now. Can anyone direct me to such an example (or just type one)?
Thanks
Here is a possible solution
public static ExpectedCondition<WebElement> textInValue(final WebElement el) {
return new ExpectedCondition<WebElement>() {
#Override
public WebElement apply(WebDriver driver) {
return el.getAttribute("value").equals("") ? el : null;
}
}
}
And use it like this
for (int ind = 0; ind < boxes.size(); ind++) {
try {
wt.until(textInValue(boxes.get(ind)));
}
catch (TimeoutException e) {
// print message
}
}
I have written below code for Checking list Web Elements, but below code is running but for only 1st item its no looping to end of loop.
List <WebElement> listofItems = wd.findElements(By.xpath("//*[starts-with(#id,'result_')]//div//div[1]//div//a//img"));
for (int i=1; i<=listofItems.size(); i++)
{
listofItems.get(i).click();
wd.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
System.out.println(i);
System.out.println("pass");
wd.navigate().back();
}
#Saifur has explained nicely regarding the issue. So, I will just put the code that will see you through
List <WebElement> listofItems = wd.findElements(By.xpath("//*[starts-with(#id,'result_')]//div//div[1]//div//a//img"));
WebDriverWait wait = new WebDriverWait(wd, 20); //Wait time of 20 seconds
for (int i=1; i<=listofItems.size(); i++)
{
/*Getting the list of items again so that when the page is
navigated back to, then the list of items will be refreshed
again */
listofItems = wd.findElements(By.xpath("//*[starts-with(#id,'result_')]//div//div[1]//div//a//img"));
//Waiting for the element to be visible
//Used (i-1) because the list's item start with 0th index, like in an array
wait.until(ExpectedConditions.visibilityOf(listofItems.get(i-1)));
//Clicking on the first element
listofItems.get(i-1).click();
wd.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
System.out.print(i + " element clicked\t--");
System.out.println("pass");
wd.navigate().back();
}
So, above I have just tweaked your code a bit and have the relevant comments where changes are made and why. Hope this works out for you. :)
The possible issue with this is the DOM refresh. You cannot find a list and click through the elements back and forth and reference to the same list since the DOM has refreshed after first click. The best solution of that problem is to find the element on the fly. Plus, implicit wait is firm for that driver instance once you set that. So, you do not have to set the wait for each element look up. Instead set it where you instantiate the driver.(possibly). However, I think the explicit wait is a best fit here.
By byXpath = By.xpath("//*[starts-with(#id,'result_')]//div//div[1]//div//a//img");
List <WebElement> listofItems = wd.findElements(byXpath);
for (int i=1; i<=listofItems.size(); i++)
{
//I would suggest you to see if you can improve the selector though
By by= By.xpath("//*[starts-with(#id,'result_')]//div//div[1]//div//a//img[" + i + "]");
WebElement myDynamicElement = (new wd(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(by));
System.out.println(i);
myDynamicElement.click();
wd.navigate().back();
}