My two scenarios -
1) First
@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 45) # Time greater than implicit
@wait.until {@driver.find_element(:tag_name => "body").text.include?("hey")}
Which gives the driver 45 seconds to search for the text(which is expected)
2) Second
@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 5) # Time less than implicit
@wait.until {@driver.find_element(:tag_name => "body").text.include?("hey")}
This now gives the driver 30 seconds to search for the text(not expected)
Is there a way to make selenium wait only for the explicit
wait time and not for the greater of the two?
Note - Not declaring the implicit wait time is not an option, cause I cannot afford to let selenium hang each time the driver is unable to find something.
Using Selenium version 30, windows, ff
Don't mix implicit and explicit waits. Part of the problem is that implicit waits are often (but may not always be!) implemented on the "remote" side of the WebDriver system. That means they're "baked in" to IEDriverServer.exe, chromedriver.exe, the WebDriver Firefox extension that gets installed into the anonymous Firefox profile, and the Java remote WebDriver server (selenium-server-standalone.jar). Explicit waits are implemented exclusively in the "local" language bindings. Things get much more complicated when using RemoteWebDriver, because you could be using both the local and remote sides of the system multiple times.
This is how that would work: local code -> Java remote server -> local Java language bindings on the remote server -> "remote" component like the Firefox extension, chromedriver.exe or IEDriverServer.exe. It's even more complex in the grid case, since there could be other hops in between.
Thus, when you try to mix implicit and explicit waits, you've strayed into "undefined behavior". You might be able to figure out what the rules of that behavior are, but they'll be subject to change as the implementation details of the drivers change. So don't do it.
You shouldn't be experiencing "hangs" when an element can't be found if you're not using implicit waits. The driver should throw a NoSuchElement exception immediately.
The best practice is to set implicitlyWait() at the beginning of each test, and use WebDriverWait() for waiting an element, or AJAX element to load.
However, implicitlyWait() and WebDriverWait() do not work well together in the same test.
You would have to nullify implicitlyWait() before calling WebDriverWait because implicitlyWait() also sets the "driver.findElement()" wait time.
Whenever you are using WebDriverWait() with implicitlyWait() already set some initial value, follow the steps -
- nullifying implicitlyWait()
- executing WebDriverWait (), and return element
- reset implicitlyWait() again
Example Java code -
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait()
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS);