I am trying to write following code but I am getting NoSuchElementException. I see that the explicit wait is not getting applied.
WebDriver driver = WebDriverManager.chromedriver().create();
driver.manage().window().maximize();
driver.get("abc");
driver.findElement(By.id("-signin-username")).sendKeys("pratik.p#feg.com");
driver.findElement(By.id("-signin-password")).sendKeys("abcdf");
driver.findElement(By.id("-signin-submit")).click();
// wait(100);
waitForElementToLoad(driver, driver.findElement(By.cssSelector("portal-application[title='AW Acc']")), 100);
Below is the 'Explicit Wait' method.
public static void waitForElementToLoad(WebDriver driver, WebElement element,int seconds) {
WebDriverWait wait = new WebDriverWait(driver, seconds);
wait.until(ExpectedConditions.visibilityOf(element));
}
Using forced wait Thread.sleep() the code works but I don't want any forced wait in the code as it slows down the execution. Can anyone help? I am getting this in the console:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"portal-application[title='AW Acc']"}
(Session info: chrome=102.0.5005.115)
Try:
...
driver.findElement(By.id("-signin-submit")).click();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("portal-application[title='AW Acc']")));
You catch exception because webdriver tries to find element before checking it's visibility. So what it does is:
Find element by css selector portal-application[title='AW Acc']
Wait for element to be visible (it's height and width more than 0)
and it fails on step 1 because element is not in the DOM yet.
If it doesn't work, then try Fluent Waits:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(10))
.ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.cssSelector("portal-application[title='AW Acc']"));
}
});
Also, just in case you decide you want it, there is a dirty way that works in any case:
public static WebElement findMyElement(WebDriver driver, By by, int timeoutSeconds) throws Exception {
long timeout = System.currentTimeMillis() + (timeoutSeconds * 1000);
while (true) {
try {
return driver.findElement(by);
} catch (NoSuchElementException nEx) {
Thread.sleep(50);
if (System.currentTimeMillis() > timeout) {
throw new RuntimeException("Still can't find the element..");
}
}
}
}
...
WebElement element = findMyElement(driver, By.cssSelector("portal-application[title='AW Acc']"), 20);
Related
I am using Fluent wait and I see that the return value of function is WebElement. However, I want to retun true or false based on the element's presence. How can I do it? I refer this page - https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/FluentWait.html
Code snipppet is here -
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
I tried changing to below, but it gives me error -
The method until(Function) in the type
Wait is not applicable for the arguments (new
Function(){})
Here is what I changed -
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(retryCount, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
Boolean foo = wait.until(new Function<WebElement, Boolean>() {
public Boolean apply(WebElement by) {
return true;
}
});
I am using Guava version 23.0, Selenium 3.0, Java 1.8.*
If only element visibility matters then try with following : -
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.withTimeout(Duration.ofSeconds(20));
wait.pollingEvery(Duration.ofSeconds(5));
wait.ignoring(NoSuchElementException.class);
boolean status = wait.until(new Function<WebDriver, Boolean>() {
public Boolean apply(WebDriver driver) {
return driver.findElement(By.name("q")).isDisplayed();
}
});
findelements() is one easier way to check element presence
if(driver.findelements(By.id("foo")).size()>0) {
//true
}
I am getting some good handson on my Java ans Selenium. When I use the same "Input_Search_Box" Webelement to perform click method it throws a nullpointer exception. I have googled and tried few work around like adding Thread, adding Explicit wait but still no clue where i miss. Any suggestion would be greatly appreciated.
Here is my Code:
public class Testclass {
WebElement Input_Search_Box;
WebDriver driver;
#Test
public void openBrowser() throws Exception{
System.setProperty("webdriver.chrome.driver","E:\\Ecilpse\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://en.wikipedia.org/wiki/Main_Page");
driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
driver.manage().window().maximize();
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("window.scrollBy(0,500)");
WebElement Click_Create_Book = driver.findElement(By.xpath(".//*[#id='coll-create_a_book']/a"));
Click_Create_Book.click();
WebElement Start_Book_Creator_Btn = driver.findElement(By.xpath(".//*[#id='mw-content-text']/form/div/div[1]/button"));
Start_Book_Creator_Btn.click();
Input_Search_Box = driver.findElement(By.xpath(".//*[#id='searchInput']"));
Input_Search_Box.click();
Input_Search_Box.sendKeys("Selenium",Keys.ENTER);
for(int i =0;i<=8;i++){
try{
if(driver.findElement(By.xpath(".//*[#id='siteNotice']/div[2]/div[2]/div")).isDisplayed())
break;
}
catch(Exception e){
jse.executeScript("window.scrollBy(0,2500)");
}
}
for(int j=0;j<=5;j++){
if(driver.findElement(By.id("coll-add_article")).isDisplayed()) {
System.out.println("If Executed");
break;
}else
{
WebElement Book_Remove = driver.findElement(By.xpath(".//*[#id='coll-remove_article']"));
Book_Remove.click();
}
}
WebElement Add_This_Book = driver.findElement(By.xpath(".//*[#id='coll-add_article']"));
Add_This_Book.click();
Thread.sleep(3000);
for(int k =0;k<=6;k++){
jse.executeScript("window.scrollBy(0,-2500)");
Thread.sleep(3000);
}
Thread.sleep(4000);
System.out.println("Sctipr on hold for 4k seconds");
//Here is the Nullpointer error occuring
Input_Search_Box.click();
Input_SearchBox.sendKeys("JSCRIPT",Keys.ENTER);
}
}
If the page has changed/reloaded then you need to use find again.
Sometimes on user actions the page can trigger calls that can change the page that can change the state of the page and the current found objects are lost this can results in a stale element exception or null exception.
I am unable to click on the "Login" button provided in the header I am new to selenium, here is the code snippet
public class Muft_Mashwara_login {
public WebDriver driver= null;
#BeforeMethod
public void startBrowser () {
driver= new FirefoxDriver();
driver.get("http://sqa.muftmashwara.be.vteamslabs.com/home");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
}
#Test
public void Click()throws InterruptedException {
//Thread.sleep(3000);
driver.findElement(By.xpath(".//*[#id='header2']/nav/div/ul/li/a")).click();
WebElement loginTxt = driver.findElement(By.xpath("html/body/main/div/section/article[2]/div/div/form[1]/div[1]/div/input"));
loginTxt.sendKeys("test#test.com");
}
#AfterMethod
public void Close() {
driver.close();
}
}
It only works if I uncomment "Thread.sleep". I don't know how to implement dynamic wait in this case.
Should work with something like this:
WebDriverWait webDriverWait = new WebDriverWait(driver, 5); // Wait up to five seconds.
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath(".//*[#id='header2']/nav/div/ul/li/a"))).click();
// Or perhaps:
//webDriverWait.until(ExpectedConditions.elementToBeClickable(
// By.xpath("//xpath"))).click();
You may also want to add this one before clicking, as the loading overlay interferes with clicking for some versions of webdriver.
wait.until(ExpectedConditions.invisibilityOfElementLocated(
By.xpath("//div[#id='cover']")));
I think the webdriverwait is not working correctly for this scenario so Thread.sleep will do.
Try this code, it ran sucessfully at my end.
And always Use Css before you think of XPath.
Css are faster than Xpath.
#Test
public void test() throws InterruptedException, AWTException{
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://sqa.muftmashwara.be.vteamslabs.com/home");
Thread.sleep(10000L);
driver.findElement(By.cssSelector(".fa.fa-lock")).click();
}
use the below code:
public class Muft_Mashwara_login {
public WebDriver driver= null;
#BeforeMethod
public void startBrowser () {
driver= new FirefoxDriver();
driver.get("http://sqa.muftmashwara.be.vteamslabs.com/home");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
}
#Test
public void Click()throws InterruptedException {
//use javascript click here
WebElement elem = driver.findElement(By.cssSelector("li>a[href='/login']"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", elem);
WebElement loginTxt = driver.findElement(By.cssSelector("div.form-group.ng-invalid>input[name='username']"));
loginTxt.click();
loginTxt.sendKeys("test#test.com");
}
#AfterMethod
public void Close() {
driver.close();
}
}
but if u want to learn how to use dynamic wait,see the below example:
WebDriverWait webDriverWait = new WebDriverWait(driver, 20);
webDriverWait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("ue selector")));
//u can use by xpath or class or name here also
// this will until the element is visible to the page
I'm writing some automated tests for using the selenium chrome driver. I trying to write a reusable method that will explicitly wait for elements to appear and then call this method in other classes. Seems pretty straight forward but its not doing what I want it do. Here is the method that I have.
public String waitForElement(String item) {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(
ExpectedConditions.elementToBeClickable(By.id(item)));
return item;
}
Then I call the method and pass it a parameter like this:
waitForElement("new-message-button");
That doesn't seem to become working, can someone give some insight?
You can use Explicit wait or Fluent Wait
Example of Explicit Wait -
WebDriverWait wait = new WebDriverWait(WebDriverRefrence,20);
WebElement aboutMe;
aboutMe= wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("about_me")));
Example of Fluent Wait -
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(20, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement aboutMe= wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("about_me"));
}
});
Check this TUTORIAL for more details.
public static void clickOn(WebDriver driver, WebElement locator, int timeout)
{
new WebDriverWait(driver,timeout).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(locator));
locator.click();
}
Call the above method in the main method then we will get explicitly wait functionality.
Your problem is that you passed String to method parameter:
public String waitForElement(String item) {
You have to pass your WebElement, something like:
public boolean visibilityOfElementWait(WebElement webElement) {
if (webElement != null) {
try {
WebDriverWait wait = new WebDriverWait(Driver.getCurrentDriver(), 20);
wait.until(ExpectedConditions.visibilityOf(wrappedElement));
highlightElement(webElement);
return true;
} catch (Exception e) {
return false;
}
} else
Logger.logError("PageElement " + webElement.getText() + " not exist");
return false;
}
public void highlightElement(WebElement element) {
if (!Config.getProperty(Config.BROWSER).equalsIgnoreCase("ANDROIDHYBRID")) {
String bg = element.getCssValue("backgroundColor");
for (int i = 0; i < 4; i++) {
Driver.getDefault()
.executeScript("arguments[0].style.backgroundColor = 'red'", element);
Driver.getDefault()
.executeScript("arguments[0].style.backgroundColor = '" + bg + "'", element);
}
// String highlightElementScript = "arguments[0].style.backgroundColor = 'red';";
// Driver.getDefault().executeScript(highlightElementScript, element);
}
}
We can develop implicit wait on our own.
Use this code; it should also work the same as implicit wait.
//=== Start of Implicit Wait Statement ===
public void implicit_Wait_ID(String str) throws Exception{
for(int i=0;i<60;i++){
try{
driver.findElement(By.id(str)).isDisplayed();
break;
}catch(Exception e){Thread.sleep(2000);
}
}
}
//=== End of Implicit Wait Statement ===
Use this method by passing the ID value:
public void loginGmail() throws Exception
{
driver.findElement(By.id("Email")).sendKeys("Mail ID");
driver.findElement(By.id("next")).click();
implicit_Wait_ID("Passwd");
driver.findElement(By.id("Passwd")).sendKeys("Pwd value");
driver.findElement(By.id("signIn")).click();
}
If it is Xpath, LinkText, just create one of the above methods for all locator types and reuse it n number of times in your script.
Just use this method.I hope it will work perfectly.
public void waitForElement(String item) {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("item")));
}
Then call the method :
waitForElement("new-message-button");
I wrote an explicit wait for my selenium test in the following manner:
I declared my WebElement to be found with an #FindBy annotation added referencing the Id as follows:
#FindBy(how = How.ID, using = "home")
private WebElement home;
Then my method that waits for an element to load was written as follows:
public WebElement isElementLoaded(WebElement elementToBeLoaded) {
WebDriverWait wait = new WebDriverWait(driver, 15);
WebElement element = wait.until(ExpectedConditions.visibilityOf(elementToBeLoaded));
return element;
}
This allowed me to reference any element I was waiting for by name that I had annotated with a find by, regardless of the #FindBy method used.
I built a package using Selenium and waiting was one of the biggest issues I had. In the end, the methods as you described above wouldn't work. I had to resort to doing a simple implicit wait for any dynamic elements, as described below
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
Code:
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
src
Hope that helps.
I'm getting an "Unable to locate element" exception while running the below code. My expected output is First Page of GoogleResults.
public static void main(String[] args) {
WebDriver driver;
driver = new FirefoxDriver();
driver.get("http://www.google.com");
driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
WebElement oSearchField = driver.findElement(By.name("q"));
oSearchField.sendKeys("Selenium");
WebElement oButton = driver.findElement(By.name("btnG"));
oButton.click();
//String oNext = "//td[#class='b navend']/a[#id='pnnext']";
WebElement oPrevious;
oPrevious = driver.findElement(By.xpath("//td[#class='b navend']/a[#id='pnprev']"));
if (!oPrevious.isDisplayed()){
System.out.println("First Page of GoogleResults");
}
}
If I run the above code I get "Unable to Locate Element Exception". I know the Previous Button Element is not in the first page of the Google Search Results page, but I want to suppress the exception and get the output of the next step if condition.
Logical mistake -
oPrevious = driver.findElement(By.xpath("//td[#class='b navend']/a[#id='pnprev']"));
will fail or give error if WebDriver can't locate the element.
Try using something like -
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
You can pass the xpath to the function like
boolean x = isElementPresent(By.xpath("//td[#class='b navend']/a[#id='pnprev']"));
if (!x){
System.out.println("First Page of GoogleResults");
}