"Implicit wait" waiting for element to clickable, displayed or visible - java

There have been questions on the difference between implicit and explicit wait in Selenium WebDriver.
What is difference between Implicit wait Vs. Explicit wait in selenium webdriver?
When to use explicit wait vs implicit wait in Selenium Webdriver?
On SeleniumHq also:
Implicit Waits
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.
But not clear what kind of wait is this, I mean would it wait till isDispalyed, isVisible or isClickable

I believe the implicit wait does not care about any of those properties (isDisplayed, isVisible or isClickable). It just waits the time you set up and checks regularly whether the element you try to select is available in your DOM. If it is not found it will lauch a timeout error.

I believe narko is right and here's some code that I think proves it.
By hiddenLocator = By.id("csi");
FirefoxDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement hiddenEle = driver.findElement(hiddenLocator);
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.presenceOfElementLocated(hiddenLocator));
System.out.println("done");
I went to google.com and found an element that was hidden
<textarea name="csi" id="csi" style="display:none"></textarea>
I set the implicit wait to 30s, set up a WebDriverWait for 30s, and then waited for the element to be present. From the presenceOfElementLocated() source
An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
If implicit wait was waiting for anything other than just the presence of the element in the DOM, it would have waited for 30s... but it finished as soon as the page was loaded in the browser.
I did some research to better understand what these different functions are doing and how they are truly different. Here's what I found...
WebElement has three methods related to this question: isDisplayed(), isEnabled(), and isSelected(). From the docs...
isDisplayed() Is this element displayed or not? This method avoids the
problem of having to parse an element's "style" attribute.
isEnabled() Is the element currently enabled or not? This will
generally return true for everything but disabled input elements.
isSelected() Determine whether or not this element is selected or not.
ExpectedConditions also comes into play here with several methods. I'll just look briefly at elementToBeClickable(). From the docs...
elementToBeClickable An expectation for checking an element is visible
and enabled such that you can click it.
If you look at the source, the description is accurate. You can look at the source for the other methods, etc. if you want more info but I think this is enough to answer your question.

Related

Selenium : Element is found when using Thread.sleep(), but not Implicit/Explicit waits

I read about how beneficial in using Implicit/Explicit waits, and decided to abandon Thread.sleep() in my code. However, the result is opposite. Using Thread.sleep(), I can actually locate the element, while Implicit/Explicit waits result in the ElementClickInterceptedException: element click intercepted: [duplicate] error for the same element.
The element I am trying to simulate a click on is an "I AGREE" button located in a dialog box. The following is the DOM for the button which I am trying to click.
And the following is the code to simulate the click.
Using Implicit Wait
driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Result : ElementClickInterceptedException: element click intercepted: [duplicate] error
Using Explicit Wait
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement I_Agree;
I_Agree = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[1]/div/div/div[4]/a")));
I_Agree.click();
Result : ElementClickInterceptedException: element click intercepted: [duplicate] error
Using Thread.sleep()
Thread.sleep(20000);
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Result : Element is found and click can be executed.
Hope to have advice on any mistakes I may have done.
implicitlyWait waits for the element existence.
So in case of
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a")).click();
Selenium will try clicking that element immediately after the goal element appears.
In many cases the element can still be not clickable so utilizing the implicitlyWait may often cause exceptions.
Using ExpectedConditions.visibilityOfElementLocated will mostly work better, but still there are several situations this will not work.
In some cases the goal element can be out of the visible screen. In this case you will have to scroll to the goal element in order to bring it into the visible screen and then click it properly.
In some other cases during the page rendering Selenium will indicate element as visible and clickable while actually some other element may be overlapping on the goal element so clicking on it will cause the wrong element accepting the click. However if you give some more wait the page rendering process will complete and now you can click the goal element properly.
This is seems to be your case.
In most cases the overlapping element will be some kind of spinner element.
If so you should add the ExpectedConditions.invisibilityOfElementLocated condition to wait until the spinner / other overlapping element is disappeared.
To give more precise answer we need to see the specific site you are working on and the actual test flow you are doing.
You can see more about the ElementClickInterceptedException here, here, here and at more resources.
UPD
From your comments I see you did not actually understand. Both implicitly and explicitly waits are pooling the DOM to find element matching the passed condition. In both cases at the moment the condition is met Selenium will immediately stop waiting and polling, it will return an element (or Boolean true in some cases) and continue to the next command.
Implicitly wait is waiting for element presence. So in many cases the element itself is still not finally rendered and may still not be clickable or visible but it is already present, so in your case
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[4]/a"))
may return the element that is still not ready to be clicked on.
This is why it is preferred to use explicit waits like ExpectedConditions.visibilityOfElementLocated since in this case Selenium will wait polling the DOM until it finds the desired element to be visible, this is much more mature state of the element on the page and it can normally be clicked on this point.
However, sometimes it can be some spinner etc. on that element. This is some external problem. So in this case we need to add ExpectedConditions.invisibilityOfElementLocated to wait until that spinner is disappeared.
There are more cases explicit wait will not be enough to be applied on the element itself. Sometimes you will have to scroll the desired element into the view, sometimes you will even need to use JavaScript click etc.

Java Selenium stale element reference, using AjaxLocatorFactory

I have a super-class Component, inside this class I store common ways to access elements attached to the component.
In the Component constructor, I initElements with the pagefactory
PageFactory.initElements(new AjaxElementLocatorFactory(root,10), this);
As I understand it, this will automatically keep element reference fresh, as long as the elements are annotated by the #FindBy annotation.
I have a specialized Component called SearchResultRow which extends Component.
In this component, I have all the WebElements related to a row in the search result.
What I want to do is to get the first search result and click on it. This is my code for that.
public void clickOnFirstResult() {
WebElement firstUser = wait.until(ExpectedConditions.elementToBeClickable(searchResultRoot.findElement(By.cssSelector("tbody > tr:nth-child(1)"))));
new SearchResultRow(firstUser).clickOn(SearchModel.NAME);
}
Here I wait for the element to become clickable, because it's a dynamic element that is not covered by the #FindBy annotation.
SearchModel.NAME refers to a WebElement annotated by #FindBy in the SearchResultRow component. Yet this method sometimes 10-15 % gives the error
stale element reference: element is not attached to the page document
Root cause
Stale element reference refers to web elements that were obtained before a page refresh but attempted to be used (i.e. calling click() method after said refresh.)
Solution
Wait.... Which are the best ways to wait for page reloads? One way is to use Implicit Waits. One very common way to implicitly wait some amount of time:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
This is how it is done in Selenium Java, but there should be an equivalent method for whichever version of Selenium you are using. The question now is, what does this do? This is the way to tell the web driver to wait the given amount of time BEFORE attempting to obtain a web element. When the implicit wait time is set, it will remain set for the duration of your test session. Therefore, this is typically done at the very beginning before any tests begin to execute. More specifically, you should do it immediately after getting the web driver instance.
That said, this should not be enough. For example, what if the component become stale after initial load of a page? For that, you should use ExpectedConditions class and set an explicit wait for some condition to occur:
WebDriverWait wait = new WebDriverWait(driver, 10); // timeout of 10 seconds and polling the default value of 500 ms, or...
WebDriverWait wait = new WebDriverWait(driver, 10, 100); // timeout of 10 seconds and polling every 100 ms
Then use wait object to set your expected condition and obtain the required web element
WebElement element = wait.until(...);
You will need to pass the appropriate ExpectedConditions to the above method. Common ones to be used to avoid staleness:
WebElement element = wait.until(ExpectedConditions.elementSelectionStateToBe(...));
WebElement element = wait.until(ExpectedConditions.refreshed(...));
Lastly, you will check to see what the state of the element is before interacting with it. For example:
WebElement newElement = wait.until(ExpectedConditions.elementToBeClickable(element));
newElement.click();
In this case, element and newElement are the same object so using just wait.until(ExpectedConditions.elementToBeClickable(element)); should be enough before calling element.click(). By this point, you have established that the element is not stale and it is visible and enabled; and therefore, safe to be clicked (for instance).
It's caused by dynamic DOM.
wait.until(ExpectedConditions.elementToBeClickable(searchResultRoot.findElement(By.cssSelector("tbody > tr:nth-child(1)")))); ends when the element is found and clickable. However this occurs during the process of DOM building, so when you trying to click on this element it may disappear / change so the element you are referencing to is no more exists.
The simplest way to work with dynamic DOM pages is each time the DOM / page is reloaded / rebuilt is to give some enough delay time and only after that to deal with it's elements.
You already asked similar question and I already answered you there.

How to wait HTML element appear globally with Selenide?

We have many e2e test written by Selenide.
To avoid failing test in test server, I would like selenide to wait for html element appearing.
I know some scripts like wait.until(...) for this. But, I don't want to fix all test code.
Is there any global switch or setting for Selenide ? ( in detail, I hope the option making cssselector waiting )
My question is resolved by this post
Implicit Wait is the way to configure the WebDriver instance to poll the HTML DOM (DOM Tree)
for a configured amount of time when it tries to find an element
or find a group/collection of elements if they are not immediately available.
As per the current W3C specification the default time is configured to 0.
We can configure the time for the Implicit Wait any where within our script/program and can reconfigure it as per our necessity.
Once we set Implicit Wait it will be valid for the lifetime of the WebDriver instance.
I think implicit wait time is almost the global switch I expected.
Before performing any action, selenide provides methods to look up for Conditions.
$("By Locator").shouldBe(Condition."Desired Condition").
I might be late for this question. But for anyone who still needs help in selenide wait, my answer might still be helpful.
For selenium if you have wait method like:
element = (new WebDriverWait(driver, <timeOutForElement>))
.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(<cssSelector>)));
You can perform the same in Selenide with element = $(<cssSelector>).should(exist);
For
element = (new WebDriverWait(driver, <timeOutForElement>))
.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(<cssSelector>)));
We just go with element = $(<cssSelector>).shouldBe(visible);
Reference Page Here.

How to replace Wait instant of Thread.sleep() in my automation test script

I am a new bee for the automation and I have used the JUnit to develop the automation test script on using selenium webdriver on here my requirements
I have developed the automation test script. For some actions on my code, I want some time to execute the next command like find the element and load the pages so I use the Thread.sleep(). So now I found the info about using the Thread.sleep is a not good for the making test script
So my question is Can anyone say then how I give the dynamic wait time to my code My code is as below,
System.setProperty("webdriver.chrome.driver", "//path of the chrome driver");
driver = new ChromeDriver();
driver.get("https://url for my org");
Thread.sleep(5000); //to load the login page of my Org
driver.findElement(By.xpath("my login xpath")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("my login xpath")).sendKeys("username");
Thread.sleep(2000);
driver.findElement(By.xpath("my password xpath")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("my password xpath")).sendKeys("my password");
driver.findElement(By.xpath("login button")).click();
Thread.sleep(6000); //for giving the time to login Org
I have used the different type of the wait time on my code as per my requirement.
If I go to the wait Class Can I able to achieve the same Wait time on
there?
My question is different for the getting the explicit wait is provide the constant wait time to the different places like if we define the followingly,
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath")));
element.click();
//for another wait
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath")));
element.sendKeys("something"); //Here it's wait time(10 seconds) is same to the after the click action wait time.
So Why I am waiting the same time for all my wait section without need? if having another way please let me know?
If I am wrong please correct me.
Thanks.
Firstly, I would very much like to advice you to use pageobjects or something like it. This is going to get you to maintenance-hell. Having said that, to solve your problem, you can use the implicit or explicit wait, whichever works best for you.
If you want to use the implicit wait, when initializing your driver, use:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
If you want to use explicit wait, use this example and make it your own:
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element =
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("xpath")));
element.click();
In both examples, the driver will wait for a max of 10 seconds.
If you want to know the difference between the 2, check out the link and see what suits you best
http://toolsqa.com/selenium-webdriver/implicit-explicit-n-fluent-wait/
You should avoid using implicit wait due to the advice of Selenium contributors. You should also avoid mixing implicit and explicit waits as stated in the Selenium docs:
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times.
You should instead use explicit waits, e.g. WebDriverWait. You shouldn't need a wait between entering data into fields. My general approach is to wait for a specific element to be visible on the page that indicates that a page is finished loading. You will want to pick one of the last elements to load on the page in the case where you have a long loading/dynamic section. After that element is loaded, you are free to enter text, etc. on the page at will. The only time you should need to wait again on the same page is if you trigger some dynamic behavior such as clicking a link that refreshes part of the page, making a selection from a dropdown that triggers a reload of another dropdown, etc.
Your code should look more like
driver.get("https://url for my org");
driver.findElement(By.xpath("my login xpath")).sendKeys("username");
driver.findElement(By.xpath("my password xpath")).sendKeys("my password");
driver.findElement(By.xpath("login button")).click();
// wait for element on newly loaded page and continue
You don't need a wait after navigating to a URL. Selenium will wait for the browser readyState to be complete.
You don't need to click in an element before using .sendKeys().
You don't (generally) need a wait between entering data into fields.
You should add implicit wait in your program as shown below
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://url for my org");
Here Implicit waits are basically your way of telling WebDriver that it should wait 10 seconds(as mentioned in code) in cases if specified element not available on the UI (DOM), i.e. before throwing exception it will wait for 10 seconds.
Once you added implicit wait, remove all Thread.sleep(1000). It is not good practice to write Thread.sleep(1000) after every statement.
Or you can use explicit wait like
// Create object of WebDriverWait class
WebDriverWait wait=new WebDriverWait(driver,20);
// Wait till the element is not visible
WebElement element=wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("ur xpath here")));
boolean status = element.isDisplayed();
//Then perform other action on element
This waits up to 20 seconds before throwing a TimeoutException or if it finds the element will return it in 0 - 20 seconds. WebDriverWait by default calls the ExpectedCondition every 500 milliseconds until it returns successfully. A successful return is for ExpectedCondition type is Boolean return true or not null return value for all other ExpectedCondition types.

Selenium Subselect waiting in java

I have 3 select menus depending on each other. Selenium enables you to select a value of a select item but since the menus depend on each other there is a small waiting time between each one. You can have a thread sleeping for one second the time it loads but I want to know how to make the waiting dynamic. The WebDriverWait enables you to wait for an element but not a value of the element.
The secret to dynamic waits is the ExpectedConditions class. Used properly, you can get WebDriverWait to work with quite a large variety of conditions.
Without seeing the HTML of your page, I suspect you're going to need something like:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions
.textToBePresentInElementLocated(By.id("the-element's-id", "Value you are looking for");
You don't have to use id if it's not convenient: any of the usual locators like xpath and css will work too.

Categories