How to initialize another WebElement inside the method in Java with Selenium - java

I'm a bit concerned with the minor problem that I'm facing. I have a test case where I need to pick up any value from the drop down. After selection entire web page reloads and I have 2 options. If warning message appears, I need to click on drop down again and choose another value. If warning message doesn't appear, just click on "Continue" button. All my values inside the drop down have the same id which only differs in ending:
uxMiniFinderVoyageSelect_chzn_o_1
uxMiniFinderVoyageSelect_chzn_o_2
uxMiniFinderVoyageSelect_chzn_o_3
uxMiniFinderVoyageSelect_chzn_o_4
till 30. What I did I called Random class where I set up variable from 1 - 30
Random random = new Random();
int x = random.nextInt(30) + 1;
Now I look for my element this way
WebElement valueFromDropDown = driver.findElement(By.id("uxMiniFinderVoyageSelect_chzn_o_" + x));
But if warning message appears and I need to click on another value, my code picks up the same value over and over. The question is how to correctly and with less code writing click on another element in drop down? The full class looks like this
public class SomeClassName{
Random random = new Random();
int x = random.nextInt(30) + 1;
#FindBy(xpath = "someXpathExpression") private WebElement dropDown;
#FindBy(xpath = "someXpathExpression") private WebElement warningMessage;
#FindBy(xpath = "someXpathExpression") private WebElement continueButton;
public void fillForm() throws Exception{
WebElement valueFromDropDown = driver.findElement(By.id("uxMiniFinderVoyageSelect_chzn_o_" + x));
dropDown.click();
valueFromDropDown.click();
if(user will see that warningMessage suddenly apppears){
dropDown.click();
valueFromDropDown.click(); -> this is where I want to click on another value
}else{
contunieButton.click();

Introduce a method to return drop down webelement randomly like below
public WebElement getDropDownValueRandomly() {
Random random = new Random();
int x = random.nextInt(30) + 1;
WebElement valueFromDropDown = driver.findElement(By.id("uxMiniFinderVoyageSelect_chzn_o_" + x));
return valueFromDropDown;
}
Your Class will be like :
public class SomeClassName{
#FindBy(xpath = "someXpathExpression") private WebElement dropDown;
#FindBy(xpath = "someXpathExpression") private WebElement warningMessage;
#FindBy(xpath = "someXpathExpression") private WebElement continueButton;
public void fillForm() throws Exception{
WebElement valueFromDropDown = getDropDownValueRandomly();
dropDown.click();
valueFromDropDown.click();
if(user will see that warningMessage suddenly apppears){
dropDown.click();
getDropDownValueRandomly().click(); -> this is where I want to click on another value
}else{
contunieButton.click();
}
}
public WebElement getDropDownValueRandomly() {
Random random = new Random();
int x = random.nextInt(30) + 1;
WebElement valueFromDropDown = driver.findElement(By.id("uxMiniFinderVoyageSelect_chzn_o_" + x));
return valueFromDropDown;
}
}
Hope this helps

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)));
}
}
}

Selenium Java can't always click the same place

I am trying to automate with Java. What I need to do is to choose a random product from the product list and then press the "add to favorite" button on the top left of that product. However, whenever I try to run this test, sometimes it adds the product to the favourite, and sometimes instead of pressing the favorite button, it presses on the product and the test results in an error.
The url I'm trying to pick a random product and add to favourite: https://www.turkcell.com.tr/pasaj/cep-telefonu
mycode:
//Add 3 random items
for (int i = 0; i < 3; i++) {
Random random = new Random();
int productOrder = driver.findElements(By.xpath("//*[contains(#class, 'm-grid-col-4 product')]")).size();
int randomNum = random.nextInt(productOrder)+1;
TimeUnit.SECONDS.sleep(2);
System.out.println(randomNum + "th product selected");
TimeUnit.SECONDS.sleep(2);
//int newRandom = randomNum+1;
TimeUnit.SECONDS.sleep(2);
WebElement randomFavoriteClick = driver.findElement(By.xpath("(//*[#class='m-grid-col-4 product'])["+randomNum+"]/a/div[1]/span"));
js.executeScript("arguments[0].scrollIntoView();", randomFavoriteClick);
TimeUnit.SECONDS.sleep(5);
randomFavoriteClick.click();
TimeUnit.SECONDS.sleep(3);
I tried changing the Xpaths but nothing changed.
To confirm exactly where I want to click, I added "actions" to the project and moved my cursor over the element before clicking with the MoveToElement function and it works for now.
Actions actions = new Actions(driver);
for (int i = 0; i < 3; i++) {
Random random = new Random();
int productOrder = driver.findElements(By.xpath("//*[contains(#class, 'm-grid-col-4 product')]")).size();
int randomNum = random.nextInt(productOrder)+1;
TimeUnit.SECONDS.sleep(2);
System.out.println(randomNum + "th product selected");
TimeUnit.SECONDS.sleep(2);
//int newRandom = randomNum+1;
TimeUnit.SECONDS.sleep(2);
WebElement randomFavoriteClick = driver.findElement(By.xpath("(//*[#class='m-grid-col-4 product'])["+randomNum+"]/a/div[1]/span"));
actions.moveToElement(randomFavoriteClick);
TimeUnit.SECONDS.sleep(2);
js.executeScript("arguments[0].scrollIntoView();", randomFavoriteClick);
TimeUnit.SECONDS.sleep(4);
randomFavoriteClick.click();
TimeUnit.SECONDS.sleep(4);
}

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);
}

org.openqa.selenium.TimeoutException: Expected condition failed: waiting for element to be clickable [duplicate]

This question already has answers here:
Element MyElement is not clickable at point (x, y)... Other element would receive the click
(5 answers)
Selenium Web Driver & Java. Element is not clickable at point (x, y). Other element would receive the click
(9 answers)
Closed 2 years ago.
I created test for clicking all menu items and subitems on the page. It fails on clicking second item's subitem:
org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element <a class="side-bar-third__link" href="/radiology/kt/golova/">...</a> is not clickable at point (456, 824). Other element would receive the click: <div class="monitoring_link">...</div>
#Test
public void clickAllMenuItemsTest() {
System.setProperty("webdriver.chrome.driver", "libs/chromedriver/chromedriver.exe");
List<String> links = new ArrayList<>();
driver = new ChromeDriver();
driver.get("https://www.invitro.ru/radiology/");
JavascriptExecutor jsExecutor = driver;
WebDriverWait wait = new WebDriverWait(driver, 10);
final By locator = By.cssSelector("a.side-bar-second__link");
final By locatorActiveItem = By.cssSelector(".side-bar-second__items.side-bar__items--active");
final By locatorSubItems = By.cssSelector(" a.side-bar-third__link");
wait.until(ExpectedConditions.elementToBeClickable(locator));
int numberOfElementsFound = getNumberOfElementsFound(locator);
for (int pos = 0; pos < numberOfElementsFound; pos++) {
wait.until(ExpectedConditions.elementToBeClickable(locator));
final WebElement elementClickable = getElementWithIndex(locator, pos);
jsExecutor.executeScript("arguments[0].scrollIntoView(true);", elementClickable);
elementClickable.click();
wait.until(ExpectedConditions.elementToBeClickable(locatorActiveItem));
int numberOfSubElementsFound = getNumberOfElementsFound(locatorActiveItem, locatorSubItems);
for (int subPos = 0; subPos < numberOfSubElementsFound; subPos++) {
wait.until(ExpectedConditions.elementToBeClickable(locatorSubItems));
final WebElement subElementClickable = driver.findElement(locatorActiveItem).findElements(locatorSubItems).get(subPos);
jsExecutor.executeScript("arguments[0].scrollIntoView(true);", subElementClickable);
//fails here:
subElementClickable.click();
}
}
driver.quit();
}
private WebElement getElementWithIndex(By locatorActiveItem, By locatorSubItems, int index) {
return driver.findElement(locatorActiveItem).findElements(locatorSubItems).get(index);
}
private int getNumberOfElementsFound(By locatorActiveItem, By locatorSubItems) {
return driver.findElement(locatorActiveItem).findElements(locatorSubItems).size();
}
public int getNumberOfElementsFound(By by) {
return driver.findElements(by).size();
}
public WebElement getElementWithIndex(By by, int index) {
return driver.findElements(by).get(index);
}
What is could be wrong?

Android + Appium: Scroll inside ListView to specific position and click on it

can someone please help me with this.
Task: Open ListView element in Android App, scroll to specific position and click on it. If element wasn't found, than scroll to the bottom of the list and stop to search and drop the test with exception.
//Yes, I have been looking for a solution on other questions, but I can't combine then to use in my case.
What did i get:
1) Test swipes inside ListView to specific position and clicks on it;
2) Test stacks in loop in the bottom of ListView.
Questions:
1) How to stop test with exception if specific position wasn't found when the bottom of ListView was reached?
2) Swipe looks like incorrect solution and seems there must be used another solution, or no?
code:
public void scrollToElementFromList (String keyword_locator){
// keyword_locator = (By.xpath("//*[#resource-id = 'android:id/text1'][#text = 'Spain']"))
boolean token = false;
while(!token) {
if (this.isElementPresent(keyword_locator)){
waitForElementAndClick(keyword_locator,"Cannot click selected element",3);
token = true;
} else {
TouchAction action = new TouchAction(driver);
WebElement element = driver.findElement(By.xpath("//android.widget.ListView"));
int middleX = element.getLocation().getX() + element.getSize().getWidth() / 2;
int upperY = element.getLocation().getY();
int lowerY = upperY + element.getSize().getHeight() - 50;
action.press(middleX, lowerY).waitAction(1200).moveTo(middleX, upperY).release().perform();
continue;
}
}
}
answer:
public void scrollToElementFromList (String locator, String keyword_locator, int max_swipes){
By by = this.getLocatorByString(locator);
boolean element_found = false;
int already_swiped = 0;
while(!element_found) {
if (this.isElementPresent(keyword_locator)){
waitForElementAndClick(keyword_locator,"Cannot click selected element",3);
element_found = true;
} else if (already_swiped > max_swipes){
throw new AssertionError("Cannot find element by swiping up.");
}
else {
TouchAction action = new TouchAction(driver);
WebElement element = driver.findElement(by);
int middleX = element.getLocation().getX() + element.getSize().getWidth() / 2;
int upperY = element.getLocation().getY();
int lowerY = upperY + element.getSize().getHeight() - 50;
action.press(middleX, lowerY).waitAction(1200).moveTo(middleX, upperY).release().perform();
++already_swiped;
continue;
}
}
}

Categories