How to handle pagination in selenium Webdriver - java

This is my code when I run it goes to the 2nd page and stop it not looping all pages and search the required element. It should look for particular text in a page and click on the link of it.
if (driver.getTitle().contains("Article properties")) {
WebElement assigninitial = driver.findElement(By.partialLinkText("Assign reviewer for initial review"));
assigninitial.click();
} else {
//pagination code
//driver.findElement(By.xpath("/html/body/app/main/app-mytasks/div[1]/section/div/pagination/ul/li[3]/a")).click();
#SuppressWarnings("unchecked")
ArrayList<WebElement> pagination = (ArrayList<WebElement>) driver.findElements(By.xpath("/html/body/app/main/app-mytasks/div[1]/section/div/pagination/ul/li[5]/a"));
// checkif pagination link exists
if ((pagination).size() > 0) {
//System.out.print("pagination exists");
// click on pagination link
for (int i = 0; i < pagination.size(); i++) {
pagination.get(i).click();
if (driver.getPageSource().contains("Article properties")) {
WebElement assigninitial = driver.findElement(By.partialLinkText("Assign reviewer for initial review"));
assigninitial.click();
}
}
} else {
System.out.print("pagination not exists");
}
}

public void pagination_check() throws InterruptedException {
loader_wait(5); //wait until 'loader' loading
List<WebElement> pagination = driver.findElements(By.xpath("//page-navigation/div/div/span/a"));
Thread.sleep(5000);
if (pagination.size() > 0) {
System.out.println("pagination exists and size=>"+pagination.size());
int page_no=pagination.size();
for (int i = 2; i <= pagination.size(); i++) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView();", driver.findElement(By.xpath("//page-navigation/div/div/span"))); //for
scroller move
js.executeScript("arguments[0].click();", driver.findElement(By.xpath("//page-navigation/div/div/span/a["+i+"]")));
loader_wait(5); //wait
}
} else {
System.out.println("no pagination");
}
}

Related

Dynamic Web Table : incorrect count of rows in table

I have code that reads the rows from a web table that consists of multiple pages and prints them. On the last page there are only 2 rows, but the code counts 10 instead (10 is the max rows on a page). When I run it in debug mode and step through, it correctly counts 2 rows. I have no idea why this is happening and would like some help on this.
Here is the web table : https://demo.opencart.com/admin/index.php?route=sale/order&user_token=cf5c87b778476447f8451877fae6af2f
Here is where the rows are counted in my code:
//get number of rows
int rows = driver.findElements(By.xpath("//table[#class='table table-bordered table-hover']//tbody/tr")).size();
System.out.println("No of Rows: "+rows);
Here is all my code:
package mypackage;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.github.bonigarcia.wdm.WebDriverManager;
public class DynamicWebTable {
static WebDriver driver;
public static void main(String[] args) throws InterruptedException {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.get("https://demo.opencart.com/admin/");
driver.manage().window().maximize();
WebElement username = driver.findElement(By.id("input-username"));
username.clear();
username.sendKeys("demo");
WebElement password = driver.findElement(By.id("input-password"));
password.clear();
password.sendKeys("demo");
driver.findElement(By.xpath("//button[normalize-space()='Login']")).click();
//Close popup
if(driver.findElement(By.xpath("//div[#class='modal-content']")).isDisplayed()) {
driver.findElement(By.xpath("//button[#class='btn-close']")).click();
}
driver.findElement(By.xpath("//a[normalize-space()='Sales']")).click();
driver.findElement(By.xpath("//a[normalize-space()='Orders']")).click();
//get total no of pages
String textWithTotalPages = driver.findElement(By.xpath("//div[#class='col-sm-6 text-end']")).getText();
int pages = getNumberOfPages(textWithTotalPages);
System.out.println(pages);
//go through each page
for(int p = 1; p <= pages; p++) {
System.out.println("Page no: "+p);
**//get number of rows
int rows = driver.findElements(By.xpath("//table[#class='table table-bordered table-hover']//tbody/tr")).size();
System.out.println("No of Rows: "+rows);**
//read rows from page
for(int r=1; r<=rows; r++) {
String orderId = retryingFindClick(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[2]"));
String store = retryingFindClick(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[3]"));
String customer = retryingFindClick(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[4]"));
String status = retryingFindClick(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr[\"+r+\"]//td[5]"));
System.out.println(orderId+ " "+store+" "+customer+" "+status);
}
//stop when finished with the last page
if(p == pages) {
break;
}
//click next page
String nextPage = Integer.toString(p + 1);
// try {
// driver.findElement(By.xpath("//ul[#class='pagination']//li//a[text()='"+nextPage+"']")).click();
// }catch(ElementClickInterceptedException e) {}
JavascriptExecutor js= (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0,document.body.scrollHeight)");
Thread.sleep(2000);
driver.findElement(By.xpath("//ul[#class='pagination']//li//a[text()='"+nextPage+"']")).click();
//waitAndLocate(By.xpath("//ul[#class='pagination']//li//a[text()='"+nextPage+"']")).click();
System.out.println("Clicked page: "+nextPage);
}
driver.quit();
}
//extract number of pages from String
public static int getNumberOfPages(String text){
return Integer.valueOf(text.substring(text.indexOf("(")+1, text.indexOf("Pages")-1));
}
public static String retryingFindClick(By by) {
//boolean result = false;
String s = null;
int attempts = 0;
while(attempts < 2) {
try {
s = driver.findElement(by).getText();
//result = true;
break;
} catch(StaleElementReferenceException e) {
}
attempts++;
}
return s;
}
public static WebElement waitAndLocate(By by) {
return new WebDriverWait(driver, Duration.ofSeconds(2))
.until(driver -> driver.findElement(by));
}
}
I rewrote your code to simplify things.
I think your main issue was that the script was not waiting properly so when it printed the number of rows for the last page, it was actually printing them for the previous page. The way to prevent this is to use ExpectedConditions.stalenessOf(). This takes an existing element on the page and then waits for it to go stale (no longer on the page). I added this at the bottom of every loop to make sure when the > button is clicked to go to the next page, the script pauses until the next page is loaded.
I added waits, where needed
Instead of getting a count of pages, just loop until there's no > (Next) button
Instead of getting a count of rows, just loop through all rows
I changed the URL to navigate straight to the sale/order page to save time
I removed the implicit wait since you shouldn't mix implicit and explicit waits according to the docs
Removed all support methods since they were no longer needed
With all these changes, the code is much shorter, simpler, and works successfully.
public static void main(String[] args) throws InterruptedException {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
String url = "https://demo.opencart.com/admin/index.php?route=sale/order";
driver.get(url);
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("input-username"))).sendKeys("demo");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("input-password"))).sendKeys("demo");
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("i.fa-key"))).click();
// loop until last page is reached
while (true) {
for (WebElement row : wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("table tr")))) {
String orderId = row.findElement(By.xpath("./td[2]")).getText();
String store = row.findElement(By.xpath("./td[3]")).getText();
String customer = row.findElement(By.xpath("./td[4]")).getText();
String status = row.findElement(By.xpath("./td[5]")).getText();
System.out.println(orderId + " " + store + " " + customer + " " + status);
}
List<WebElement> nextButton = driver.findElements(By.xpath("//a[text()='>']"));
if (nextButton.isEmpty()) {
break;
} else {
nextButton.get(0).click();
wait.until(ExpectedConditions.stalenessOf(nextButton.get(0)));
}
}
}

Using Selenium Java I want to automate a table that contains a price list and a price calculator

Problem: Using Selenium Java I want to automate a table that contains a price list and a price calculator
Another little problem: I can't click on the "Analysis" (Filter) button, because I have to double-click, which I could do in this case
What I want: I'm trying to find a method so that when I run the program, the program will click on another analysis (on another + button) Now with the help of a selector, I can only click on the first (+). But I want each time, the program to test, randomly other analyzes (other buttons +).
What I do
#FindBy(xpath = "//*[#id='footable_501']/thead/tr[2]/th[1]")
WebElement analizaSort;
#FindBy(xpath = "//*[#id='footable_501']/thead/tr[2]/th[2]")
WebElement pretSort;
#FindBy(xpath = "//*[#id='calculator']/div[1]/div[2]/div[2]")
WebElement total;
public void checkCalculator()
{
add.click();
add2.click();
}
public void checkFilter()
{
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,500)"); //Scroll vertically down by 1000 pixels
analizaSort.click();
analizaSort.click();
pretSort.click();
}
Link: https://www.poliana.ro/analize-preturi/
I've added below the code to click on a random analyze and to calculate the total:
#FindBy(css = "th.footable-sortable[class*='pret']") // css locator is faster than xpath
WebElement pretSort;
#FindBy(css = "th.footable-sortable[class*='analiza']")
WebElement analizaSort;
#FindBy(css = "tr[class*='row'] td[class*='pret']")
List<WebElement> analyzePriceList;
#FindBy(css = "#calculator .total .right")
WebElement total;
public void checkCalculator() {
int elementListSize = analyzePriceList.size();
assertTrue("No analyze was found in the table", elementListSize != 0); // replace here with the specific of your testing framework
int elementIndex = getRandomNumber(elementListSize - 1);
scrollElementToTheMiddle(analyzePriceList.get(elementIndex));
int expectedTotal = getTextAsInt(analyzePriceList.get(elementIndex));
analyzePriceList.get(elementIndex).click();
String totalAsString = total.getText().replace("lei", "");
int actualTotal = getInt(totalAsString);
assertEquals(expectedTotal, actualTotal);
}
public void checkFilter() {
scrollElementToTheMiddle(analizaSort);
analizaSort.click();
analizaSort.click(); // if you need double click, please see the below method
pretSort.click();
}
private void doubleClick(WebElement element) {
Actions act = new Actions(driver);
act.doubleClick(element).build().perform();
}
private int getTextAsInt(WebElement element) {
String text = element.getText();
return getInt(text);
}
private int getInt(String text) {
assertTrue("The " + text + " text was expected to be numeric", isNumeric(text)); // replace here with the specific of your testing framework
return Integer.parseInt(text);
}
private boolean isNumeric(String possibleNumberAsString) {
Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?\n");
if (possibleNumberAsString == null) {
return false;
}
return pattern.matcher(possibleNumberAsString.trim()).matches();
}
private int getRandomNumber(int maximum) {
return ThreadLocalRandom.current().nextInt(0, maximum);
}
private void scrollElementToTheMiddle(WebElement element) {
String scrollElementIntoMiddle = "var viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);"
+ "var elementTop = arguments[0].getBoundingClientRect().top;"
+ "window.scrollBy(0, elementTop-(viewPortHeight/2));";
((JavascriptExecutor) driver).executeScript(scrollElementIntoMiddle, element);
}

Selenium :Unable to click the same Close button on overlay when 2nd product is added to cart.For 1st item,able to click Close button perfectly

//Main Class TestNg class
public class XCartCheckout extends TestBase {
public static WebDriver driver;
StoreHomePage ohome;
// ArrayList<String> productname = new ArrayList<String>();
#Test(dataProvider = "DataFromExcel", priority = 1)
// public void Ad`enter code here`dToCartTest(productname) throws InterruptedException {
public void AddToCartTest(String[][] productname) throws InterruptedException {
int b = 0;
ArrayList < String > arrlist = new ArrayList < String > ();
boolean t = true;
System.out.println("length =" + productname.length);
System.out.println("arraylist values are");
for (int i = 0; i < productname.length; i++) {
for (int j = 0; j < productname[i].length; j++) {
// System.out.println("productname=" + productname[i][j]);
arrlist.add(productname[i][j]);
// System.out.println("b=" + b+ "productname="+productname[i][j]);
// b++;
}
}
for (int k = 0; k < arrlist.size(); k++) {
System.out.println(arrlist.get(k));
}
driver.get("");
driver.manage().window().maximize();
ohome = new StoreHomePage(driver);
ohome.movingBanners();
boolean sortstatus = ohome.selectSortOrder();
b = Boolean.compare(sortstatus, t);
if (sortstatus == t) {
for (int l = 0; l < arrlist.size(); l++) {
String cartmsg = ohome.addToCart(arrlist.get(l));
Assert.assertEquals(cartmsg, "You have just added");
System.out.println("Product added to cart");
}
}
}
//Add to Cart Method in my subclass:
public String addToCart(String prodnamefrmexcel) {
String successmsg = null;
i++;
try {
WebElement prodname = driver.findElement(By.xpath("//h5/a[contains(text(),'" + prodnamefrmexcel + "')]"));
WebElement addtocartbtn = driver.findElement(By.xpath("//h5/a[contains(text(),'" + prodnamefrmexcel +
" ')]//parent::h5//following-sibling::div//span[text()='Add to cart']"));
Actions action = new Actions(driver);
Action action1 = action.moveToElement(prodname).moveToElement(addtocartbtn).build();
action1.perform();
addtocartbtn.click();
Thread.sleep(4000);
successmsg = driver.findElement(By.xpath("(//span[text()='You have just added'])['" + i + "']"))
.getAttribute("innerText");
System.out.println(successmsg);
Thread.sleep(3000);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("(//span[text()='You have just added'])['" + i + "']//following-sibling::button"))).click();
} catch (Exception e) {
e.printStackTrace();
}
return successmsg;
}
}
I am trying to add 2 items to cart.While adding each item,an overlay with close button is displayed.I am trying to click Close button after adding each item.After adding 1st item,I am able to click Close button.But after adding 2nd item,unable to click close button.
The following is the error received:
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for element to be clickable: By.xpath: (//span[text()='You have just added'])['2']//following-sibling::button (tried for 30 second(s) with 500 milliseconds interval)
Screenshots containing the webpage and html elements are attached.
web-page-1
web-page-2
Try to click with JsExecutor:
element = driver.findElement(By.xpath("your_xpath"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", element);

Is there any way to solve sorting web element ? I am getting difficulties while sorting using drag and drop function

Is there any way to solve sorting web element ? I am getting difficulties while sorting using drag and drop function. My drag and drop is not working, i think my logic is good, but while running code nothing happening...
public void sortable() { // loop for drag and drop is not working...
try {
driver.get("http://jqueryui.com/");
myLibrary.clickButton(By.partialLinkText("Sortable"));
WebElement iframe = driver.findElement(By.xpath("//*[#id='content']/iframe"));
driver.switchTo().frame(iframe);
String temp = "";
Thread.sleep(10 * 1000); //manual work to disorder sortable list prior to start for loop.
Actions action = new Actions(driver);
int i = 1, j = 1;
for (i = 1; i < 8; i = i + 1) {
WebElement sourceText = driver.findElement(By.cssSelector("#sortable > li:nth-child(" + i + ")"));
WebElement dragElement = driver
.findElement(By.cssSelector("#sortable > li:nth-child(" + i + ") > span"));
while (true) {
temp = "Item" + " " + j;
if (temp == sourceText.getText()) {
WebElement targetElement = driver
.findElement(By.cssSelector("#sortable > li:nth-child(" + j + ")"));
action.moveToElement(dragElement).dragAndDrop(dragElement, targetElement).build().perform();
Thread.sleep(1 * 1000);
break;
} else {
if (j == 8) {
break;
} else {
j++;
}
}
}
}
Thread.sleep(5 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
Building upon what #JeffC posted as an answer, here's another variant of the same that uses some of the built in capabilities of Java.
We basically use the List.sort() and a Comparator to get this done.
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class SorterSample {
private RemoteWebDriver driver;
#BeforeClass
public void setup() {
driver = new ChromeDriver();
}
#AfterClass
public void cleanup() {
if (driver != null) {
driver.quit();
}
}
#Test
public void testMethod() {
String url = "http://jqueryui.com/sortable/";
driver.get(url);
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe.demo-frame")));
List<WebElement> items = driver.findElements(By.cssSelector("#sortable > li"));
items.sort(
(o1, o2) -> {
int compareValue = o1.getText().compareTo(o2.getText());
if (compareValue < 0) {
new Actions(driver).dragAndDrop(o1, o2).perform();
}
return compareValue;
});
}
}
This was a fun little exercise...
Rather than trying to invent your own sorting code, you should use an established sorting algorithm. I chose bubble sort but you can pick any one you want. If you are just sorting a few items, this should work just fine. It runs in just a few seconds.
The main code
String url = "http://jqueryui.com/sortable/";
driver.get(url);
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe.demo-frame")));
List<WebElement> items = driver.findElements(By.cssSelector("#sortable > li"));
bubbleSort(items);
The bubble sort method
static void bubbleSort(List<WebElement> items)
{
int n = items.size();
boolean swapped;
for (int i = 0; i < n - 1; i++)
{
swapped = false;
for (int j = 0; j < n - i - 1; j++)
{
int compare = items.get(j).getText().compareTo(items.get(j + 1).getText());
if (compare < 0)
{
swap(items.get(j + 1), items.get(j));
swapped = true;
}
}
// break if no elements were swapped
if (swapped == false)
{
break;
}
}
}
and finally the support method to swap items
public static void swap(WebElement source, WebElement target)
{
new Actions(driver).dragAndDrop(source, target).perform();
}
I just ran this code a few times and it's working just fine. It sorts the items in reverse order (so you don't have to mix them up manually). This is not the most efficient way to do this but I wanted to be able to watch the bubble sort work so you see each swap. If you want this to go faster, you can pull the text from the items, sort that list and then line up the elements with their sorted text so you only have to do n swaps.

Java Selenium Element is not currently interactable and may not be manipulated

This is my code:
click(By.id("job-description-help"), MOUSE_LEFT, 2);
click(By.id("job-description-help"), MOUSE_LEFT, 2);
click(By.id("title"), MOUSE_LEFT, 2);
sendKeys(By.id("title"), "ttttt", true, 4);
click(By.xpath(".//*[#id='editor']/span[5]/a[1]"), MOUSE_LEFT, 7);
public void click(By locator, int mouseButton, String combinedControlKeys, int timeoutInSeconds) throws Exception {
Boolean success = false;
long timeoutInMillies = timeoutInSeconds * 1000;
WebElement elm = null;
// indicate whether the element is an <option> tag on Firefox browser
Boolean isOptionTagOnFireFox = false;
// time spent counters
long timeSpentInMillis = 0;
// try to click on the element until wait timout reached
while ((success == false) && (timeSpentInMillis <= timeoutInMillies)) {
try {
// find the element and calculate time spent
long startFinding = System.currentTimeMillis();
elm = findElement(locator, 1);
timeSpentInMillis += System.currentTimeMillis() - startFinding;
if (elm != null) {
// get tag name of the element
String tag = elm.getTagName();
// check whether the element is <option> tag on Firefox browser
isOptionTagOnFireFox = isFirefoxDriver && (0 == elm.getTagName().compareToIgnoreCase("option"));
// press control keys (Ctrl, Alt, Shift, Meta), if any
pressControlKeys(combinedControlKeys);
if (mouseButton == MOUSE_LEFT) {
// click on the element
elm.click();
}
else if (mouseButton == MOUSE_RIGHT) {
Actions action = new Actions(driver);
action.contextClick(elm);
action.build().perform();
}
// release control keys (Ctrl, Alt, Shift, Meta)
releaseControlKeys(combinedControlKeys);
// successfully clicked on element, turn on the flag to escape the loop
success = true;
}
} catch (Exception e) {
releaseControlKeys(combinedControlKeys);
// probably the element is not present yet or it is non-clickable
System.out.println(e.getMessage());
// if element is found and we reached to the timeout, try to click on it with JavaScript
if ((elm != null) && (timeSpentInMillis > timeoutInMillies)) {
// press control keys (Ctrl, Alt, Shift, Meta), if any
pressControlKeys(combinedControlKeys);
JavascriptExecutor js = (JavascriptExecutor) this.driver;
js.executeScript("arguments[0].click();", elm);
releaseControlKeys(combinedControlKeys);
// successfully clicked on element, turn on the flag to escape the loop
success = true;
}
}
}
if (success) {
// if element is <option> tag on Firefox browser,
// perform a workaround to support MOUSE_LEFT
if (isOptionTagOnFireFox)
{
robot.keyPress(KeyEvent.VK_ENTER);
robot.delay(300);
robot.keyRelease(KeyEvent.VK_ENTER);
}
}
else { // failed
if (elm == null) {
throw new NoSuchElementException("Element not found.");
} else {
throw new Exception("Failed to click on the element");
}
}
}
public void sendKeys(By locator, String keys, boolean clearTextBeforeSendingKeys, int timeoutInSeconds) throws Exception {
WebElement elm = findElement(locator, timeoutInSeconds);
if (clearTextBeforeSendingKeys) elm.clear();
elm.sendKeys(keys);
}
The error
invalid element state: Element is not currently interactable and may not be manipulated
start at
sendKeys(By.id("title"), "ttttt", true, 4);
I'm using Eclipse and ChromeDriver 2.27
Not sure why but the input field is visible. Can't move forward because of error. Any Idea how to solve this error?

Categories