1

I'm automating this website But facing the issue with ExplicitWaitConditions to manage the time.

Scenario is When i click on Login link or Submit button after send username, It shows a loader during the process, once process has completed the loader get removed from DOM.

I have used condition for invisibilityOfElementLocated like below

new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));

But this can't predict correct time it taking more time (not exectly 60 sec but around 15-20 or may be 30 sec.) then allow to execute next command.

The same line i have to put before 4 commands to do complete login process. So it seems to consumed around 90 second to do login.

If i do not use Explicitwait or remove Impliciwait wait then script failed all time as loader get click instead of some other element.

The code i tried so far :

WebDriver driver = new FirefoxDriver();

System.out.println("Browser Opened");
driver.manage().window().maximize();
driver.get("https://www.rcontacts.in");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);    
System.out.println("URL Opened");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
driver.findElement(By.cssSelector(".ng-scope>a span[translate='login.register']")).click();
System.out.println("Register Link Clicked");
driver.findElement(By.name("userId")).sendKeys("9422307801");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
driver.findElement(By.xpath("//button[@type='submit']")).click();
System.out.println("Mobile number entered");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));

Is there any solution that as soon as loader get removed it start performing actions ?

OR is there any way that I can wait until loader element get removed from DOM. Once removed then i can continue the further actions ?.

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
NarendraR
  • 7,577
  • 10
  • 44
  • 82
  • Try `Wait wait = new FluentWait(driver).withTimeout(60, SECONDS).pollingEvery(5, SECONDS)` with less polling time and see if that helps and change `driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);` to `driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);` – Tarun Lalwani Sep 11 '17 at 09:39
  • "It seems to consumed" or it did actually consume that much just waiting for event that's already happened? You said nothing about how long that loading bar actually stays on the screen. For all I know, you already have the good solution. – M. Prokhorov Sep 11 '17 at 09:45
  • 1
    @TarunLalwani, default polling time is 500 millis, which is already good enough for most applications. There's no point in changing it, especially to higher number. – M. Prokhorov Sep 11 '17 at 09:47
  • @TarunLalwani, Still same scenario. I really don't know why does it takes so much time. is implicit and explicit both causing conflict ? – NarendraR Sep 11 '17 at 10:48
  • @M.Prokhorov, yes you are right. it is waiting for loader to be invisible even its already not there. – NarendraR Sep 11 '17 at 10:51
  • Don't mix implicit waits with `WebDriverWait`. That's simply [asking for trouble](https://stackoverflow.com/questions/15164742/combining-implicit-wait-and-explicit-wait-together-results-in-unexpected-wait-ti/15174978#15174978) – JimEvans Sep 11 '17 at 12:28
  • @JimEvans, If i do not use implicit Wait, then my script fails for the other elements which require some time to get into DOM – NarendraR Sep 11 '17 at 12:31

2 Answers2

1

First and foremost, you have induced implicitlyWait() as follows:

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

As well as WebDriverWait() as follows:

new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));

As per the documentation of Explicit and Implicit Waits it is clearly mentioned that:

Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

Again, it seems changing the ExpectedConditions clause from invisibilityOfElementLocated(By.id("loading-bar") to elementToBeClickable(By.xpath("//span[contains(text(),'Register')]") gives me a success rate of 80%. Here is the effective code block on my Windows 8 box:

System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver(); 
driver.get("https://www.rcontacts.in");
System.out.println("URL Opened");
WebDriverWait wait = new WebDriverWait (driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//span[contains(text(),'Register')]")));
driver.findElement(By.xpath("//span[contains(text(),'Register')]")).click();
System.out.println("Register Link clicked");

Note: Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully to ensure that no dangling instance of geckodriver is present (through Task Manager) while you initiate the execution.

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • @DebhanjanB, Thanks for reply. Still it cause failure. I have 5 steps to do for login 1. Click login link 2. enter mobile no 3. click submit 4. enter password 5. click submit . and it shows loader for each step. i have tried you solution to wait for next element clickable rather then invisibility of loader. but it cause failure – NarendraR Sep 11 '17 at 11:54
  • I'm using chrome 45 for with selenium 2.53.1 so no concern with geckodriver – NarendraR Sep 11 '17 at 11:55
1

According to the docs,

WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times.

That's likely the cause of your issues. It's recommended to not use implicit waits. I would remove them and then add explicit waits as needed and see how that goes.

I took your code and rewrote it (below) and it's working every time for me.

String url = "https://www.rcontacts.in";
driver.navigate().to(url);
waitForLoader();
driver.findElement(By.cssSelector("span[translate='login.register']")).click();
waitForLoader();
driver.findElement(By.cssSelector("input[name='userId']")).sendKeys("9422307801");
driver.findElement(By.cssSelector("button[translate='common.btns.next']")).click();

The issue I was having at times was that many times the script was jumping ahead. I added code to waitForLoader() to wait for the loader to appear (be visible) and then disappear (be invisible). Once I did that, it worked 100% of the time.

public static void waitForLoader()
{
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.id("loading-bar")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
}
JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thanks but it also doesn't seems to work. now it will throw me TimeOutException for visibility of loader – NarendraR Sep 12 '17 at 07:46
  • I'm not sure what you changed. I ran the code I posted above 10 times and it worked 10 times, no issues. – JeffC Sep 12 '17 at 13:32
  • You may be correct. It run fine till click submit but if i try to do complete login e.g. enter password and submit. in that case it fails. even i have used same approach as you mentioned. – NarendraR Sep 13 '17 at 04:14