Webdriver - issues with fluent wait and IE - java

I am using Java and webdriver to automate a test. This test is for 2 dropdowns, and has drilldown functionality. So, the first dropdown contains a list of options, and the second one will be populated differently based on what the user selects in the first. I am trying to test selecting all the different options in the first dropdown, and verifying that the correct options are available in the second dropdown. For example, the first dropdown could have choices A and B. If I select A, the second dropdown will have choices 1, 2, and 3. If I select B, the second dropdown will have choices 8, 9, and 10.
I was having an issue when changing the values in the first dropdown. When I selected A, webdriver would try to check to see if 1, 2, and 3 were available in the 2nd dropdown before it was loaded. This was causing my tests to fail.
To resolve this issue, I added a fluent wait for the second dropdown. So, if I chose either A or B in the first dropdown, it would wait until the 2nd dropdown loaded before checking the available options. This solution worked great for testing in chrome and firefox. However, it does not help when using IE10. When I run the test in IE10, it is still trying to check the values of the second dropdown before they are loaded, which causes my test to fail.
Has anyone come across issues with fluent wait when using IE. The only way I have been able to get it to work in IE, is to add a sleep line. if I use something like sleep(2000), it seemed to work. However, that could still cause my tests to fail if the web page were running slow and took longer to load.
Here is the code I am using for fluent wait. I am selecting a value from the first dropdown. Then I use smartSleep to wait for the 2nd dropdown, and then check the values in that dropdown. Please let me know if more information is needed to help understand the issue I am having.
public void smartSleep(String selector){
//log.info("INFO: waiting for the selector to appear");
fluentWaitPresent(selector);
log.info("INFO: Smart Sleep waited for: " +selector);
}

I found the best solution for IE10 is to wait for the page to load. I was previously waiting for an element to appear on the page, but sometimes IE wouldn't find the element even though it was displayed. Below is the wait method I am using, which has been working for all versions of IE
public boolean waitForPageLoaded(RCLocationExecutor driver) throws Exception {
String fluentWaitTimeout = customParameters.get(CustomParameterNames.FLUENT_WAIT_TIMEOUT);
log.info("INFO: setting the fluent wait timeout at: "+fluentWaitTimeout);
Wait<RCLocationExecutor> wait = new FluentWait<RCLocationExecutor>(driver)
.withTimeout(Long.valueOf(fluentWaitTimeout), TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(ElementNotFoundException.class);
return wait.until(new Function<RCLocationExecutor, Boolean>(){
public Boolean apply(RCLocationExecutor driver){
return driver.executeScript("return document.readyState").equals("complete");
}});
}

Related

How to wait for WebElement on a web page, which appers sometimes in random places while test execution?

I wrote an automated selenium based tests for a web application and they run perfectly with fast internet connection, but unpredictable behavior with less good connection.
Web application was build so, that if duration of response on a request< of some action at the web page, is bigger than 250ms, then appers loader-wrapper element, that prevents any kind of action from user, until response ends. Loader-wrapper can apper at any request in any place of test execution, so i cant use explicit waits of selenium, because i dont know when and where it will appear. As a result i receive an exception:
org.openqa.selenium.WebDriverException: Element is not clickable at point (411, 675). Other element would receive the click:(.show-component .loader-wrapper)
Is there any way to set a "global wait", which will stop test execution if loader-wrapper appered and will wait until it ends, and then test execution will continue? Or any another idea.
I kind of like your idea of the annotation, but not sure how to implement it.
Another possible approach is to write your own ExpectedCondition "loaderWrapperDisappeared" (or something like that), which would wait for the loader wrapper to be gone, and return the target WebElement so that you could chain a click to it.
You would then use it like this;
(new WebDriverWait(targetWebElement, 50))
.until(ExpectedConditions.loaderWrapperDisappeared(By.id("your div id"))).click();
(pardon the syntax it that's wrong...I haven't written java in a few years)
In case of web driver, you can have to use like this.
WebElement webElement = (new WebDriverWait(driver, 50))
.until(ExpectedConditions.elementToBeClickable(By.id("your div id")));
Here 50 refers to 50 seconds.
For more details, refer below the link.
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html#WebDriverWait-org.openqa.selenium.WebDriver-long-
If I understand correctly you are looking for invisibilityOfElementLocated.
You can add it as a decorator to your steps...
Hope this helps!

given a webelement, does clicking it cause a page reload?

What I'm doing
I've been making a utility method to help me find and properly wait for Webelements in Selenium. so far its going well and I have a way to try all kinds of different locators, wait till a webelement is found and then wait untill the webelement is displayed/enabled all with timeouts and nice things like that.
Whats the problem then?
The problem is that I sometimes need to find Webelements after pages reload. I've read up on available solutions to the 'staleness' problem and I know how to solve it (using the old webelement I just found and clicked on I'll wait till it's stale before I search again) BUT I don't want to manually have to check wether a given webelement causes a page to reload. I've tried looking in the Webelement and Expected conditions class to see if there is any method that returns true if a given webelement causes a page reload. I've tried searching about it here and on google and gotten nothing useful. I wanted to know if its possible to have something like this:
Boolean causesPageReload = webElement.causesPageReload;
With some imaginary method named causesPageReload that determines wether a webelement causes a page reload when it is clicked on, submitted to, ect. I know that some webelements just cause javascript to run on the page and others reload the page but If i could programatically determine if it reloads the page I could just say:
if (causesPageReload){
wait.until(ExpectedConditions.stalenessOf("insert old webelement here"));
}
And solve the problem. Is there anything in the underlying HTML, javascript or maybe something already built in that could provide this information? Sure I can manually go through the steps myself and see which webelements under test actually cause a page refresh, but that is subject to change, prone to human error and also time consuming.
Possible alternatives?
Alternatively I could just do my staleness check with a timeout of ten seconds and then if it reloads the page thats fine but if it doesn't it allows 10 seconds for the javascript or whatever to finish what it's doing. (I was also kinda wondering If I needed to wait for non page reloading webelement clicks as well but that seems harder due to javascript and entails a different question) I don't know if I would need to wait if the page isn't going to reload. even if I knew that I did need to wait in the non reload case, I wouldn't know how to. My current waits just wait for the webelement to be found, displayed and enabled so if clicking on it causes something important (that I need to wait for) but doesn't change those things, I'd need something else but that requires another question to be more in depth.
Tl:Dr
I just need to know if I can find out which webelements cause pages to reload programatically and if I can't then is there any need to wait for the non reloading ones (no need to go all in depth about the second case just tell me how to ask that as a second question later)?
Update
I've tried multithreading this and so far I've gotten something that can (in a timely manner) decide wether a given element when clicked changes in the DOM or doesn't. This covers most page reloading cases but might lead to a false positive since I'm pretty sure there are other instances where Element references go stale that don't involve the page reloading. I think the root cause of the problem is there is no data/flag/hook to grab onto to really tell. I suppose a better hook would lead to a better solution but I have no idea what that hook would be. On the bright side I did learn/become familiar with alot of multithreading which is good because its an area I've been weak in. I'm going to try to research the javascript thats been mentioned in answers and see If i can't combine that with my multithread approach. Once I have a good hook all I'd need to change is an ExpectedConditions call on a WebDriverwait waiting object.
Update 2
I found this website:
https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Which details "load" and "DOMcontentloaded" events. Two things in javascript that fire when pages are loaded/reloaded. I have already created a thread application with ExpectedConditions like so:
WebDriverWait wait = new WebDriverWait(driver,timeoutSeconds);
try{
wait.until(ExpectedConditions.stalenessOf(webElement));
}
catch (TimeoutException e){
}
Thus I'm pretty sure I can modify the wait.until line to check for a javascript event firing with a timeout using a Java to Javascript interface. To use the two langauges together I was led to this question:
How can I use JavaScript in Java?
In order to obatin knowledge on how that basically works. I'm going to try to implement this using Nashorn or maybe some other interface depending on whats the best.
What this potentially means
While this doesn't determine for us wether a given webelement causes page reloading BEFORE actually "trying" it, it does determine it just by "trying" the webelement. And, because I used a thread off of main, my check for "no it didn't reload the page" is effectively just the timeout condition which can be configured as needed. I don't think its possible to determine if a Webelement causes a page reload without actually trying it, but at least we can try it, determine if it reloads within a timeout period and then we will know we will have waited sufficiently long enough to not get any stale reference exceptions when searching for the same or a next element if we at least know that the next element we're looking for exists on the new page (assuming that once we execute the method to try to locate it, it waits for said element to be displayed and selectable but I've already done that). This also allows us to determine if a given webelement was deleted from the page by "trying it" because if we combine the javascript pageload call with the stalereference check I already have, then we can use the condition of "the JS load event didn't fire (page static) BUT stalereference excpetion was thrown (DOM element changed)" as the check for "this element was deleted/changed signifigantly but page wasn't reloaded", Which is quite useful information. Additioanlly since these elements can now be grouped into three categories:
Doesn't get deleted, can reference again
Deleted but page static
Deleted but page changes
We can store the results beforehand and (as long as the locators remain intact) we can more easily know wether we must wait or not after clicking the webelement. We could even go further and if we know we have the 2nd case, we could retry locating the element and see if it's locators change or not when we click it since I think stalereference exceptions can be thrown without requiring all the locators to change. How useful this is? I'm not sure but I think its pretty useful stuff but somehow I don't think I'm the first one to try/find a solution for this. I will post an answer when I successfully implement and test this but it will be awhile because I need to learn some basic Javascript and then how to integrate that with my java.
There isn't any way to programatically find out if the click will cause a reload.
You need each case separately, for this you can create main click() method with overload (or not) and call the appropriate one in each case
public void clickOnElement(WebElement element, boolean waitForStaleness) {
element.click();
if (waitForStaleness) {
wait.until(ExpectedConditions.stalenessOf(element));
}
}
public void clickOnElement(WebElement element) {
clickOnElement(element, false);
}
You can use
WaitElement(pBy, pWait);
end if you need if element is visible for continue you can add is_displayed()
finaly is not working you use a java wait :
Thread.sleep(second)
or
TimeUnit.SECONDS.sleep(second);

Selenium needs a sleep before going to the next page

I am currently learning Selenium, and I learned a lot. One thing the community said; is that you need avoiding thread.sleep as much as possible. Selenium uses implicit and explicit waits in replace. Yes, I understand that concept.
Recently I cam across a problem. This is that without a certain action; going from the login page to another page, without the use of a Thread.sleep(1000). Selenium seems too crash: that it can't find a certain element. I find this behaviour strange. So I was thinking that this conflict occurs, because of the login page that firstly wants to redirects to the main page of the website and without the Thread.sleep(1000); it wants to go to the second page but the login page refuses it because it want's to go first to the main page. With that being said is that why Selenium crashes or do you guys see and strange use of code in the example below?
// Currently on a webpage
WebElement ui_login_button = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("account-login-button")));
ui_login_button.click();
//After the click it logs in and redirects to a webpage
Thread.sleep(1000); // why sleep here? (without this Selenium crashes)
// Go to second page and perform actions
waitForLoad(driver);
driver.navigate().to(URL + "/mymp/verkopen/index.html");
/* -------------------------------------------------------------------
public void waitForLoad(WebDriver driver) {
ExpectedCondition<Boolean> pageLoadCondition = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
//WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(pageLoadCondition);
}
Sorry for the explanation, I tried my best to be clear. English is not my native language. Thanks for your help.
Kind regargds.
As per your question and the updated comments It raises an exception that it can't find the element on the webpage, it is very much possible. Additionally when you mention putting a sleep in between is not an elegant solution to fix, that's pretty correct as inducing Thread.sleep(1000); degrades the overall Test Execution Performance.
Now, what I observed in your commented code block to compare document.readyState to complete was a wiser step. But sometime it may happen that, though Web Browser will send document.readyState as complete to Selenium, due to presence of JavaScript and AJAX Calls the elements with whom we want to interact may not be Visible, Clickable or Interactable which in-turn may raise associated Exception.
So, the solution would be inducing ExplicitWait i.e. WebDriverWait. We will induce ExplicitWait for the element with which we want to interact, with proper ExpectedConditions set. You can find documentation about ExplicitWait here.
An Example:
If you want to wait for a button to be clickable the expected code block may be in the following format along with the imports:
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
// Go to second page and wait for the element
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.id("id_of_the_element")));
//perform actions
driver.navigate().to(URL + "/mymp/verkopen/index.html");
I am guessing that the exception is raised after you've navigated to URL + "/mymp/verkopen/index.html" and started to take some action.
I am speculating that the main issue here is that your waitForLoad() method is not waiting for some Javascript, or other background task, to complete on the page that Login goes to first. So when you navigate to the next page, something is not yet completed, leaving your user authentication in a bad state. Perhaps you need to wait for some AJAX to complete after login before proceeding with your further navigation? Or it would be better to click on a link on that page to trigger the navigation to your target page (as a real user would), rather than directly entering the URL? You might find it helpful to discuss the actual behavior of the web application with developers.
As DebanjanB has pointed out, once you are on your target page you can then use WebDriverWait for the elements on the page where you are taking actions.

How to wait until my browser will get into time out using selenium

So i have perform some times tests using Selenium:
My page have simple Drop Down List and from this Element i am selecting different value and wait until the next page will load and calculate the time that this operation took and again try to load different value from this Drop Down List.
So in some values this took a loot of time (because the page need to load many thing) so in this case sometimes this lead into white screen and in this case i want to specify that this is TimeOut so my question is how to recognise that this white screen appears when i cannot expect to any WebElement on this white screen.
You can waitForCondition to wait until a particular javascript condition is true. There's also other waitForX convenience methods.
https://www.neustar.biz/blog/selenium-tips-wait-with-waitforcondition
Note: If using jQuery you can wait for "jQuery.active == 0"
wait for an ajax call to complete with Selenium 2 web driver

webdriver sendKeys doesn't wait for page to load

I have an issue with selenium webdriver and i would be very grateful if anyone can help me
Environment:
selenium-server-standalone-2.31.0.jar / selenium-server-standalone-2.35.0.jar
IEDriverServer.exe (tried version 2.28 - 2.35)
Sample code:
WebElement href = this.findElement(By.xpath("//A"));
href.sendKeys(Keys.ENTER);
href.click();
Problem: A fix to any of this would help me
href.sendKeys() successfully simulates user click, but does not wait for page to load
href.click() fails to simulate user click, but successfully wait for page to load
I have search for the source code of .click() method to try to manually create a waitForPageToLoad function, but i haven't been able to find it.
I know i am not giving to much information because the application I am running the test against is internal, so I cant share a link for debugging. But any idea or previous experience with similar problems that could help me figure out what is going on would be appreciate it.
Right now, I have to do both sendKeys and click to achieve the expected results.
Whenever you do .click() on a button or link an internal method something like "waitTillPageLoads()" is called and hence webdriver waits until the next page is loaded completely.
I have experienced a scenario where it waited for almost 10-15 minutes for the page to load because web app was too slow. Wierd it sounds i know.
however sendKeys() doesn't wait. Because sendkeys is not used for clicking purpose rather it used for entering keys.
I guess there must be some strong reason for you to do
href.sendKeys(Keys.ENTER);
And if you still want to go with this approach you can implicitly you can wait for element of next page using implicit wait
WebDriverWait wait = new WebDriverWait(webDriver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath")));
Please note :
You quotation
href.click() fails to simulate user click, but successfully wait for page to load
Can be because you have not set your browser level to 100%.
Please Check my answer at Unable to run Selenium script on IE
What you can do here is after sendKeys operation, put several waits for elements which are on the resulting page using WebDriverWait. This will serve your purpose.

Categories

Resources