Alternate for thread.sleep(9000) in every line in selenium - java

I have been using thread.sleep(9000) almost after every line of code in selenium which is making me wait for long.Can anybody suggest me an alternate way to reduce this.As my application is taking time load a page it needs to wait until a particular page is loaded to perform any action.
WebElement un = driver.findElement(By.id("login_username_id"));
un.sendKeys(username);
WebElement pwd = driver.findElement(By.id("login_password_id"));
pwd.sendKeys(password);
try {
Thread.sleep(25000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
driver.findElement(By.id("login_submit_id")).click();
try {
Thread.sleep(9000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I want to reduce the usage of thread.sleep after every line and use one common function so that it waits whenever required.

use the below example:
public class Main{
static WebDriver driver = new FirefoxDriver();
public static void main(String [] args) throws InterruptedException{
WebElement un = driver.findElement(By.id("login_username_id"));
un.sendKeys(username);
WebElement pwd = driver.findElement(By.id("login_password_id"));
pwd.sendKeys(password);
waitForElement(By.id("ur id"),60);
driver.findElement(By.id("login_submit_id")).click();
waitForElement(By.id("ur id"),60);
}
/**
* wait until expected element is visible
*
* #param expectedElement element to be expected
* #param timeout Maximum timeout time
*/
public static void waitForElement(By expectedElement, int timeout) {
try {
WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.visibilityOfElementLocated(expectedElement));
} catch (Exception e) {
e.printStackTrace();
//System.out.println("print ur message here");
}
}
}
if u have any confusion, let me know.

Hi please use universal wait in your script i.e implicit wait
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
above line tell selenium to wait for maximum of 10 seconds for each and every webelement before throwing any error (note you can increase or decrease seconds it depends upon you)
explicit wait : when you want to wait for a specific webelement (use this when you think a particular element takes more then usual time to load then only)
WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.visibilityOfElementLocated(your element));

You can put assertion saying that "Whether particular element displayed or not" so that web driver will spend time to search that element which will create delay in execution.
Ex: A page may contain some button make it as target and tell web driver to find it.

Related

Selenium wait for specific XHR request to be complete

Hi i am working on a selenium project and the top difficulty that i am having was waiting for XHR request to be completed. What i am currently doing is i wait for a request to be made using following expected condition,
public ExpectedCondition<Boolean> jQueryExpect (int expectedActive) {
ExpectedCondition<Boolean> jQLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver dr) {
try {
logger.log(Level.INFO,"Checking number of jQueries Active");
Long active = (Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active");
logger.log(Level.INFO,"jQuery''s active: {0}",active);
return (active >= expectedActive);
}
catch (Exception e) {
logger.log(Level.WARNING,"Error executing script in jQueryLoad method");
// no jQuery present
return true;
}
}
};
return jQLoad;
}
And then i wait for the jQuery to load using this expected condition
public ExpectedCondition<Boolean> jQueryLoad (int expectedActive) {
ExpectedCondition<Boolean> jQLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver dr) {
try {
logger.log(Level.INFO,"Checking number of jQueries Active");
Long active = (Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active");
logger.log(Level.INFO,"jQuery''s active: {0}",active);
return (active <= expectedActive);
}
catch (Exception e) {
logger.log(Level.WARNING,"Error executing script in jQueryLoad method");
// no jQuery present
return true;
}
}
};
return jQLoad;
}
This method is working pretty solid for now since i know how many requests to expect. But as you have already noticed it can easily break in future as number of requests made are changed for some reason.
I been looking at cypress documentation and found this. According to cypress documentation this waits for the specified requests to be made.
cy.wait(['#getUsers', '#getActivities', '#getComments']).then((xhrs) => {
// xhrs will now be an array of matching XHR's
// xhrs[0] <-- getUsers
// xhrs[1] <-- getActivities
// xhrs[2] <-- getComments
})
Is there any such method available in Selenium? or Is there any way this can be implemented? So far from what i have googled i got nothing. So any help will be appreciated.
You can locate Element and wait for element
There are Implicit and Explicit waits in selenium.
You can use either
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
or
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
More information: on this answer

How to control loading in Selenium WebDriver?

When i try to run my scripts and call this method, when i enter URL into address bar, loading starts and loading take much time,
but sometime when refresh page page proper loaded on the spot so please help me out.
How can i handle this issue in automation.
public static MainPage LaunchBrowserAndLogin(String currentScriptName, String LoginUser) throws Throwable {
try {
killprocess();
LaunchBrowser();
String siteUrl = null;
if (excelSiteURL != null) {
if (excelSiteURL.equalsIgnoreCase("")) {
siteUrl = CONFIG.getProperty("siteName");
}else{
if (excelSiteURL.contains("SiteName")) {
siteUrl=excelSiteURL;
}
}
} else {
siteUrl = CONFIG.getProperty("SiteName");
}
driver.get("https://QA.YYYY.com/ABC9/#/login");
System.out.println("URL for Login: "+siteUrl);
CheckErrorPageNotFound();
driver.manage().timeouts().pageLoadTimeout(Long.parseLong(CONFIG.getProperty("pageLoadTime")), TimeUnit.SECONDS);
enterUserID(currentScriptName, LoginUser);
enterPasswd(currentScriptName);
MandatoryFieldSkipErrMsg("~~~~~~ Mandatory Field is skipped, Getting Error: ");
ClickLoginButton();
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
}catch(){
DesireScreenshot("AfterClickOnLoginButton");
String stackTrace = Throwables.getStackTraceAsString(t);
String errorMsg = t.getMessage();
errorMsg = "\n\n\n\n Login failed.See screenshot 'LoginFailed' \n\n\n\n" + errorMsg + stackTrace;
Exception c = new Exception(errorMsg);
ErrorUtil.addVerificationFailure(c);
killprocess();
IsBrowserPresentAlready = false;
throw new Exception(errorMsg);
}
return new MainPage(driver);
}
First you need to check whether page is fully loaded or not in that case we will use the below code.
new WebDriverWait(driver, 5).until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
Then as per your question I believe that some web elements are not properly getting loaded. So what you can do add one more explicit wait and put that wait inside try catch block as shown below.
try
{
new WebDriverWait(driver, 5).until(ExpectedConditions.visibilityOfElementLocated(By.id("Abhishek")));
System.out.println("Completed");
}
catch( TimeoutException e)
{
System.out.println("Reloading");
driver.navigate().refresh();
}
If it is unable to find that element then in the catch block it will refresh the page and in this way you can proceed further.
Note: I could have written the script for you but application url is invalid.

Can't find an element by name using chrome driver in selenium?

I have my simple selenium program that validate if the value search box in the google is equal to hello world but i got this error:
Exception in thread "main"
org.openqa.selenium.NoSuchElementException: no such element: Unable to
locate element: {"method":"name","selector":"q"}....
Here's my complete code
public class SimpleSelenium {
WebDriver driver = null;
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowserInChrome();
ss.getPage();
ss.listenForHelloWorld();
ss.quitPage();
}
private void openBrowserInChrome(){
System.setProperty("webdriver.chrome.driver", "C:/chromedriver.exe");
driver = new ChromeDriver();
}
private void quitPage() {
driver.quit();
}
private void getPage() {
driver.get("http://www.google.com");
}
private void listenForHelloWorld() {
WebElement searchField = driver.findElement(By.name("q"));
int count = 1;
while (count++ < 20) {
if (searchField.getAttribute("value").equalsIgnoreCase("hello world")) {
break;
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Do you wait until the page is ready and element displayed?
I've often got this error when the page is still loading. You could add something like
(MochaJS example, pretty much the same API for JAVA tests)
test.it('should check the field existence', function (done) {
let field_by = By.id(ID_OF_THE_FIELD);
driver.wait(until.elementLocated(field_by,
driver.wait(until.elementIsVisible(driver.findElement(field_by)), TIME_TO_WAIT_MS);
done();
});
You wait until the element is visible. If it failed, the timeout of TIME_TO_WAIT_MS will be raised.
The google search bar will never have "hello world" in it because you haven't typed it in?
Also the search field value doesn't seem to update when you type in a search (if you inspect the element using the Console).
If your just learning I would just write a test like this and the click the search button, then confirm the "hello world" text in the search results:
WebElement searchField = driver.findElement(By.name("q"))
searchField.sendKeys("Hello World")
//Add code to click search button
//Add code to assert results on next page
Also I would completely change your listenForHelloWorld() method and use the built in WebDriver ExpectedConditions:
new WebDriverWait(driver, 10)
.until(ExpectedConditions.textToBePresentInElement(searchField, "Hello World"))

Click loop until the (button) element found for multiple buttons in java

I want to click the 'Followed' button until it found in the web page.
I've below code:
#Test
public void testCar() throws Exception
{
driver.get("https://-----/login/");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys("user");
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys("password");
driver.findElement(By.xpath("//button[#type='submit']")).click();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.findElement(By.xpath("//span[text()='Followed']")).click();
}
How can I do this? if not found the element then click next page & find the button again.
here is the next button HTML:
<span>Next Page</span>
Please help.
Just put a loop around with try catch
try {
while (true)
{
driver.findElement(By.xpath("//span[text()='Followed']")).click();
}
} catch (ElementNotFoundException ex) {
driver.findElement(By.xpath("//span[text()='Next Page']")).click()
}
If the element is found it will be clicked, if not then a element not found exception will be thrown and that time you can click on the Next page button
Check the condition weather Followed button available or not for that you have to use List to get followed webelements Like :
Boolean buttonNotFound = true;
while(buttonNotFound)
{
List<WebElement> follow = driver.findElements(By.xpath("//span[text()='Followed']"));
if(follow.size()!=0)
{
follow.get(0).click();
buttonNotFound=false;
}
else
{
driver.findElement(By.xpath("//span[text()='Next Page']")).click();
}
}
NOTE : Don't write ImplicitWait again and again, If you have mentioned at one place right below the get() then it is applicable for whole script. If some element require some more time to interact then use ExplicitWait.

Selenium: Waiting for an element do disappear

I posed with a difficult task. I am fairly new to selenium and still working through the functionalities of waiting for elements and alike.
I have to manipulate some data on a website and then proceed to another. Problem: the manipulation invokes a script that makes a little "Saving..." label appear while the manipulated data is being processed in the background. I have to wait until I can proceed to the next website.
So here it is:
How do i wait for and element to DISAPPEAR? Thing is: It is always present in the DOM but only made visible by some script (I suppose, see image below).
This is what I tried but it just doesn't work - there is no waiting, selenium just proceeds to the next step (and gets stuck with an alert asking me if I want to leave or stay on the page because of the "saving...").
private By savingLableLocator = By.id("lblOrderHeaderSaving");
public boolean waitForSavingDone(By webelementLocator, Integer seconds){
WebDriverWait wait = new WebDriverWait(driver, seconds);
Boolean element = wait.until(ExpectedConditions.invisibilityOfElementLocated(webelementLocator));
return element;
}
UPDATE / SOLUTION:
I came up ith the following solution: I built my own method. Basically it checks in a loop for the CssValue to change.
the loops checks for a certain amount of time for the CSSVALUE "display" to go from "block" to another state.
public void waitForSavingOrderHeaderDone(Integer _seconds){
WebElement savingLbl = driver.findElement(By.id("lblOrderHeaderSaving"));
for (int second = 0;; second++) {
if (second >= _seconds)
System.out.println("Waiting for changes to be saved...");
try {
if (!("block".equals(savingLbl.getCssValue("display"))))
break;
} catch (Exception e) {
}
}
You can wait for a WebElement to throw a StaleElementReferenceException like this:
public void waitForInvisibility(WebElement webElement, int maxSeconds) {
Long startTime = System.currentTimeMillis();
try {
while (System.currentTimeMillis() - startTime < maxSeconds * 1000 && webElement.isDisplayed()) {}
} catch (StaleElementReferenceException e) {
return;
}
}
So you would pass in the WebElement you want to wait for, and the max amount of seconds you want to wait.
Webdriver has built in waiting functionality you just need to build in the condition to wait for.
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.findElements(By.id("lblOrderHeaderSaving")).size() == 0);
}
});
I'm not sure, but you can try something like this :)
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //time in second
WebElement we = driver.findElement(By.id("lblOrderHeaderSaving"));
assertEquals("none", we.getCssValue("display"));
This works with selenium 2.4.0. you have to use the invisibility mehtod to find it.
final public static boolean waitForElToBeRemove(WebDriver driver, final By by) {
try {
driver.manage().timeouts()
.implicitlyWait(0, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(UITestBase.driver,
DEFAULT_TIMEOUT);
boolean present = wait
.ignoring(StaleElementReferenceException.class)
.ignoring(NoSuchElementException.class)
.until(ExpectedConditions.invisibilityOfElementLocated(by));
return present;
} catch (Exception e) {
return false;
} finally {
driver.manage().timeouts()
.implicitlyWait(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
}
}
I used following C# code to handle this, you may convert it to Java
public bool WaitForElementDisapper(By element)
{
try
{
while (true)
{
try
{
if (driver.FindElement(element).Displayed)
Thread.Sleep(2000);
}
catch (NoSuchElementException)
{
break;
}
}
return true;
}
catch (Exception e)
{
logger.Error(e.Message);
return false;
}
}
You can also try waiting for the ajax calls to complete. I've used this to check when the page load is complete and all the elements are visible.
Here's the code - https://stackoverflow.com/a/46640938/4418897
You could use XPath and WebDriverWait to check whether display: none is present in the style attribute of an element. Here is an example:
// Specify the time in seconds the driver should wait while searching for an element which is not present yet.
int WAITING_TIME = 10;
// Use the driver for the browser you want to use.
ChromeDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, WAITING_TIME);
// Replace ELEMENT_ID with the ID of the element which should disappear.
// Waits unit style="display: none;" is present in the element, which means the element is not visible anymore.
driver.wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id='ELEMENT_ID'][contains(#style, 'display: block')]")));
Try using invisibilityOfElementLocated method.
You can reference example here How to wait until an element no longer exists in Selenium?
enter image description hereI created my own method for element disappearing from dom....
In Conditions class (In .m2\repository\org\seleniumhq\selenium\selenium-support\3.141.59\selenium-support-3.141.59.jar!\org\openqa\selenium\support\ui\ExpectedConditions.class)
we can see that 'isInvisible' method with 'isDisplayed' method,,, i wrote the same with 'isEnabled'
public static ExpectedCondition<Boolean> invisibilityOf(final WebElement element) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
return isRemovedFromDom(element);
}
#Override
public String toString() {
return "invisibility of " + element;
}
};
}
private static boolean isRemovedFromDom(final WebElement element) {
try {
return !element.isEnabled();
} catch (StaleElementReferenceException ignored) {
return true;
}
}

Categories