Selenium wait until expected conditions - java

I'm trying to search for something, after clicking the search button, the button going into an loading animation. If there is a result, it goes to the next page, if there is no result, a yellow box appears. How can I write this line new WebDriverWait(driver, 1).until? I'm thinking until the title change or the yellow box appears. But I'm not sure how can I code that.
This is what I got so far
new WebDriverWait(driver, 1).until(driver.getTitle().contains("Overview") || !driver.findElements(By
.xpath("/html/body/div[2]/div/div[3]/div/div[1]/div/div/div[2]/div[2]/div/div[1]/div/div/div/span"));
.isEmpty())

Use org.openqa.selenium.support.ui.ExpectedConditions
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public WebDriverWait waitSec(WebDriver driver, int sec) {
return new WebDriverWait(driver, sec);
}
public WebElement clickableByXpath(String xpath, int sec) {
WebElement element = waitSec(driver, sec).until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
return element;
}
public WebElement clickableById(String id, int sec) {
WebElement element = waitSec(driver, sec).until(ExpectedConditions.elementToBeClickable(By.id(id)));
return element;
}
public WebElement visibleById(String id, int sec) {
WebElement element = waitSec(driver, sec).until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
return element;
}
public WebElement visibleByXpath(String xpath, int sec) {
WebElement element = waitSec(driver, sec).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
return element;
}
// custom ExpectedCondition
public ExpectedCondition<Boolean> elementNotVisible(String xpath) {
return ExpectedConditions.not(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
}
See https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

Related

ElementClickInterceptedException error that I cannot resolve

I am getting the following error:
ElementClickInterceptedException: element click intercepted: Element is not clickable at point (288, 833)
When I manually scroll down the page to view the element, selenium finds it and clicks on it, but only if I help it by scrolling down. I have tried different methods to resolve this that I have commented out in the code, but it is still not resolved? How do I resolve this error?
package mypackage;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.github.bonigarcia.wdm.WebDriverManager;
public class DynamicWebTable {
public static void main(String[] args) throws InterruptedException {
WebDriverManager.chromedriver().setup();
WebDriver 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);
//
for(int p = 1; p <= 2; p++) {
WebElement active_page = driver.findElement(By.xpath("//ul[#class='pagination']//li//span"));
System.out.println("Active Page: "+active_page.getText());
Thread.sleep(3000);
//new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.elementToBeClickable(active_page)).click();
active_page.click();
//Actions actions = new Actions(driver);
//actions.moveToElement(active_page).click().perform();
//JavascriptExecutor e = (JavascriptExecutor)driver;
//e.executeScript("arguments[0].click();", active_page);
//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 each page
for(int r=1; r<=rows; r++) {
String orderId = driver.findElement(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[2]")).getText();
String store = driver.findElement(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[3]")).getText();
String customer = driver.findElement(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[4]")).getText();
String status = driver.findElement(By.xpath("//table[#class='table table-bordered table-hover']//tbody//tr["+r+"]//td[5]")).getText();
System.out.println(orderId+ " "+store+" "+customer+" "+status);
}
//click next page
String nextPage = Integer.toString(p + 1);
driver.findElement(By.xpath("//ul[#class='pagination']//li//a[text()='"+nextPage+"']")).click();
}
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));
}
}
You have to close this pop updriver.findElement(By.xpath("//button[#class='btn-close']")).click
before you execute
driver.findElement(By.xpath("//a[normalize-space()='Sales']")).click();
This will resolve the problem for you. I have tried in WATIR, it's working for me.
Okay, So try writing this code in try catch block.
try{
activePage.click();
}catch(ElementClickInterceptedException e){
}
or scroll down the page and issue the click, it works too
JavascriptExecutor js= (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0,document.body.scrollHeight)");
Thread.sleep(2000);
activePage.click();
Try the below code, I made 2 changes to your code:
Using JavascriptExecutor, scroll down to the bottom of the page and then perform active_page.click()
In the second iteration since the DOM structure changes,active_page.click() won't work(you may get Stale element reference, Element is not attached to the page document exception), so you need to assign the web element once again
Good luck.
for(int p = 1; p <= 2; p++) {
WebElement active_page = driver.findElement(By.xpath("//ul[#class='pagination']//li//span"));
System.out.println("Active Page: "+active_page.getText());
Thread.sleep(3000);
//below 2 lines will scroll to the bottom of the page
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,document.body.scrollHeight)");
Thread.sleep(3000);
//assigning web element to active_page once again as the DOM structure has changed
active_page = driver.findElement(By.xpath("//ul[#class='pagination']//li//span"));
active_page.click();

Unable to locate any date from return date calendar in Make My Trip website through selenium and Java

Here i am trying to select return date 12 of April month. i tried with different customized xpath and css but unable to locate the element:
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Make_my_trip {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "F:\\Selenium\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://www.makemytrip.com/");
// Selecting Return date
driver.findElement(By.id("hp-widget__return")).click();
//WebDriverWait ws = new WebDriverWait(driver, 10);
//ws.until(ExpectedConditions.presenceOfElementLocated(By.id("dp1551508380301")));
Thread.sleep(2000);;
while (!driver.findElement(By.xpath("//span[#class ='ui-datepicker-month']")).getText().contains("April")) {
System.out.println("Return date selected ");
driver.findElement(By.xpath(
"div[#id='dp1551508898872']//span[#class='ui-icon ui-icon-circle-triangle-e'][contains(text(),'Next')"))
.click();
}
List<WebElement> returndate = driver.findElements(By.xpath("//a[#class ='ui-state-default']"));
int count = returndate.size();
for (int j = 0; j < count; j++) {
String returndatetext = driver.findElements(By.xpath("//a[#class ='ui-state-default']")).get(i).getText();
if (returndatetext.equalsIgnoreCase("12")) {
driver.findElements(By.xpath("//a[#class ='ui-state-default']")).get(i).click();
break;
}
}
}
PS :
If we use explicitly wait getting "org.openqa.selenium.InvalidSelectorException" Error so as of now use Thread.sleep(1000).
If we use Xpath //div[#class='ui-datepicker-group ui-datepicker-group-last']/div/a/span[contains(text(),'Next' )][1] getting
org.openqa.selenium.ElementNotVisibleException: element not visible
"Element not visible". I had this error too. It's mean your searchable element isn't visible in the current snapshot. You should focus on that element or scroll down till element appear in the snapshot

wait.until(ExpectedConditions.visibilityOf(userName)) is not working

In the below code on 33rd line getting below error message near wait.until
Multiple markers at this line
- The type com.google.common.base.Function cannot be resolved. It is indirectly referenced from required .class files
- The method until(Function) in the type FluentWait is not applicable for the
arguments (ExpectedCondition)
package MPA;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class LoginhelperClass {
WebDriver driver;
#FindBy(xpath = "//input[#ng-model='login.username']")
private WebElement userName;
#FindBy(xpath = "//input[#type='password']")
private WebElement Password;
#FindBy(xpath = "//input[#type='submit' and #value='Sign In']")
private WebElement SignIn;
#FindBy(xpath = "//span[#class='icon-avatar-round']")
private WebElement Avatar;
public LoginhelperClass(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void logIn(String uName, String Pswd) throws InterruptedException {
WebDriverWait wait=new WebDriverWait(driver,7);
wait.until(ExpectedConditions.visibilityOf(userName));
userName.sendKeys(uName);
Password.sendKeys(Pswd);
SignIn.click();
try {
Thread.sleep(4000);
if (Avatar.isDisplayed()) {
System.out.println("Login Successfull: " + uName);
} else {
System.out.println("Login failure check the credentials: " + uName);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
package MPA;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class LoginhelperClass {
WebDriver driver;
#FindBy(xpath = "//input[#ng-model='login.username']")
private WebElement userName;
#FindBy(xpath = "//input[#type='password']")
private WebElement Password;
#FindBy(xpath = "//input[#type='submit' and #value='Sign In']")
private WebElement SignIn;
#FindBy(xpath = "//span[#class='icon-avatar-round']")
private WebElement Avatar;
public LoginhelperClass(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void logIn(String uName, String Pswd) throws InterruptedException {
WebDriverWait wait=new WebDriverWait(driver,7);
wait.until(ExpectedConditions.visibilityOf(userName));
userName.sendKeys(uName);
Password.sendKeys(Pswd);
SignIn.click();
try {
Thread.sleep(4000);
if (Avatar.isDisplayed()) {
System.out.println("Login Successfull: " + uName);
} else {
System.out.println("Login failure check the credentials: " + uName);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
The error which you are seeing is as follows :
Multiple markers at this line - The type com.google.common.base.Function cannot be resolved. It is indirectly referenced from required .class files - The method until(Function) in the type FluentWait is not applicable for the arguments (ExpectedCondition)
Let us analyze what is happening in our code.
In the Page Object you have defined an WebElement as :
#FindBy(xpath = "//input[#ng-model='login.username']")
private WebElement userName;
Moving ahead you have tried to use the WebElement within the method :
public void logIn(String uName, String Pswd) throws InterruptedException {
WebDriverWait wait=new WebDriverWait(driver,7);
wait.until(ExpectedConditions.visibilityOf(userName));
//
}
So basically here we were trying to wait for the visibility of an Indirectly Referenced Angular WebElement userName which is dependent on the attribute ng-model. In such circumstances we can never be sure that when the WebElement will be referenced within a method userName will mandatory reference to a not NULL value. It may be NULL as well.
Now let us have a look at the Method Defination of visibilityOf, it is defined as :
visibilityOf(WebElement element)
An expectation for checking that an element, known to be present on the DOM of a page, is visible.
So clearly, visibilityOf method expects a Direct Reference of the WebElement. Hence in absence of a definite value (not NULL) of userName, WebDriverWait which is a variant of FluentWait shows the error.
Play with conditions with By/WebElement:
ExpectedConditions.presenceOfAllElementsLocatedBy(By)
ExpectedConditions.elementExists(By)
ExpectedConditions.elementIsVisible(By)
ExpectedConditions.elementToBeClickable(By/WebElement)
ExpectedConditions.visibilityOfAllElementsLocatedBy(By)

how to locate an element of a page after new data loaded on the same page in selenium webdriver

I am trying to copy the table data of the html page which is loaded on the same page after clicking on the 'Get Table' button on the previous page. However, as the page url is not changing I am getting exception of 'No such element' when trying to locate new elements on newly loaded page. Following is the code I tried:
package com.test.selenium;
import java.util.List;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import junit.framework.Test;
import junit.framework.TestSuite;
public class Example1{
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "D:\\Java Stuff\\Selenium Tutorial\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.oanda.com/currency/table");
WebElement date = driver.findElement(By.name("date"));
date.sendKeys("12/04/10");
WebElement date_frmt = driver.findElement(By.name("date_fmt"));
date_frmt.sendKeys("yy/mm/dd");
WebElement curr = driver.findElement(By.name("exch"));
curr.sendKeys("US Dollar.USD");
Select sel = new Select(driver.findElement(By.name("Currency")));
sel.deselectAll();
List lsize = sel.getOptions();
int count = lsize.size();
for(int j=0;j<count;j++)
{
String lvalue = sel.getOptions().get(j).getText();
sel.selectByVisibleText(lvalue);
}
WebElement crr = driver.findElement(By.name("dest"));
crr.click();
driver.getCurrentUrl();
String table = driver.findElement(By.id("converter_table")).getText();
System.out.println(table);
}
}
According to exception it seems that element not exists on the page, or smth wrong with you xpath. Why you use xpath?! Try css selectors (they are more powerful and stable) =) e.g.
driver.findElement(By.css("#converter_table"));
P.S. if you want to verify that your selector is correct (no matter xpath or css) use dev console in browser (e.g. for css enter $("#converter_table") in console, and if element exists (and this id has no type in the name) then you'll see what this selector will return)). For xpath use $x("xpath")
UPDATE:
Simple solution i think is to add some method which will wait for element, some period of time. Below sample code in C# (test with wait method)
private IWebDriver driver;
[SetUp]
public void SetUp()
{
// Here i just create browser as you (firefox, chrome etc);
driver = CreateBrowser("http://www.oanda.com/currency/table");
}
[TearDown]
public void TearDown()
{
driver.Dispose();
}
[Test]
public void PortTest()
{
var dateElement = driver.FindElement(By.Name("date"));
dateElement.SendKeys("12/04/10");
var dateFrmt = driver.FindElement(By.Name("date_fmt"));
dateFrmt.SendKeys("yy/mm/dd");
var curr = driver.FindElement(By.Name("exch"));
curr.SendKeys("US Dollar.USD");
var crr = driver.FindElement(By.Name("dest"));
crr.Click();
WaitUntilLoad();
var table = driver.FindElement(By.Id("converter_table"));
Console.Write("the text is " + table.Text);
}
public void WaitUntilLoad()
{
int repetitionCount = 0;
bool isLoaded = false;
while (!isLoaded)
{
var table = driver.FindElements(By.Id("converter_table")).Count;
if (table > 0 )
isLoaded = true;
Thread.Sleep(250);
repetitionCount++;
Console.WriteLine("Searching again for element");
if (repetitionCount > 25) break;
}
}
you get NoSuchElement because your xpath seems wrong
try
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.xpath(".//*[#id='content_section']/table")));
String table = driver.findElement(By.xpath(".//*[#id='content_section']/table")).getText();

Selenium WebDriver - getCssValue() method

I am doing a exercise to use cssGetValue method to retrieve the value from a particular web element's CSS property.
I have 2 questions:
why the cssGetValue method returned value 13px, which web element does the method actually referenced.
1a. I want to get CSS property for section labeled as "By ID". how should I modify my code so I can get CSS property value for id="by-id" section?
I used driver.close() method, but it won't close the browser after the script finished. Please explain to me why driver.close() method didn't work in this case.
Here is my code fragment:
package wd_findElementBy;
import java.util.List;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class SearchWebElements
{
WebDriver driver = new FirefoxDriver();
private String baseUrl= "http://docs.seleniumhq.org/docs/03_webdriver.jsp#introducing-the-selenium-webdriver-api-by-example";
#Test
public void findElements(){
driver.get(baseUrl);
try{
List<WebElement> elements = driver.findElements(By.id("by-id"));
System.out.println("number of elements: " + elements.size());
for(WebElement ele : elements){
System.out.println(ele.getTagName());
System.out.println("get the text for web element with id='by-id' ");
System.out.println("------------------------------------------------------------");
System.out.println(ele.getText());
System.out.println("------------------------------------------------------------");
System.out.println(ele.getAttribute("id"));
System.out.println(ele.getCssValue("font-size"));
}
}
finally{
//driver.close();
driver.quit();
}
}
}
Yes, all correct.
Here's a screenshot of where to find font-size through Firebug.
Since the ids are supposed to be unique (at least for this page), you don't need findElements to find a list of elements with id by-id and loop through, instead, you use findElement to get the element directly.
try{
WebElement byId = driver.findElement(By.id("by-id"));
System.out.println(byId.getTagName());
System.out.println("get the text for web element with id='by-id' ");
System.out.println("------------------------------------------------------------");
System.out.println(byId.getText());
System.out.println("------------------------------------------------------------");
System.out.println(byId.getAttribute("id"));
System.out.println(byId.getCssValue("font-size"));
}
}
For getting CSS value:
driver.findElement(By.id("by-id")).getCssValue("font-size");//similarly you can use other CSS property such as background-color, font-family etc.
For quit/close the browser after finishing the execution of script:
driver.quit();
public class GetCssValues {
public WebDriver driver;
private By bySearchButton = By.name("btnK");
#BeforeClass
public void setUp() {
driver = new FirefoxDriver();
driver.get("http://www.google.com");
}
#Test(priority=1)
public void getCssValue_ButtonColor() {
WebElement googleSearchBtn = driver.findElement(bySearchButton);
System.out.println("Color of a button before mouse hover: " + googleSearchBtn.getCssValue("color"));
Actions action = new Actions(driver);
action.moveToElement(googleSearchBtn).perform();
System.out.println("Color of a button after mouse hover : " + googleSearchBtn.getCssValue("color"));
}
#Test(priority=2)
public void getCssValue_ButtonFontSize() {
WebElement googleSearchBtn = driver.findElement(bySearchButton);
System.out.println("Font Size of a button " + googleSearchBtn.getCssValue("font-size"));
}
#Test(priority=3)
public void getCssValue_ButtonFontWeight(){
WebElement googleSearchBtn = driver.findElement(bySearchButton);
System.out.println("Font Weight of a button " +getFontWeight(googleSearchBtn) );
}
public String getFontWeight(WebElement element) {
//Output will return as 400 for font-weight : normal, and 700 for font-weight : bold
return element.getCssValue("font-weight");
}
#AfterClass
public void tearDown() {
driver.quit();
}
}
output:
Color of a button before mouse hover: rgba(68, 68, 68, 1)
Color of a button after mouse hover : rgba(34, 34, 34, 1)
Font Size of a button 11px
Font Weight of a button 700
The value is correct. You need access computed section in dev-tools
Add the property name in the getCssValue to get the info regarding same
Some Examples are :-
System.out.println("font-size = "+ele.getCssValue("font-size"));
System.out.println("background = "+ele.getCssValue("background"));
System.out.println("line-height = "+ele.getCssValue("line-height"));
System.out.println("color = "+ele.getCssValue("color"));
System.out.println("font-family = "+ele.getCssValue("font-family"));
Refer:-

Categories