How to wait HTML element appear globally with Selenide? - java

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.

Related

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 create wait in selenium that waits for a web element to finish refreshing

I'm fairly new to Selenium and I'm writing a test for a web app using it. In doing this, I'm using assertions to make sure the web app is working correctly. For a few of these assertions, I'm asserting on a web element that has a numeric value in which the expected number is known. The problem is when a change is made that changes this numeric value the change happens gradually based on how fast the internet connection is. Up to this point have resorted to using sleep's to wait for the element to finish refreshing before I use assertions but I would like to make it so this wait is no longer than the time it takes for the element to stop refreshing and thus not have to include sleep's that are either too short or too long.
You should try this:
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(<specific locator of element>));
Sleep is not a good option because you wait always expected the amount of time.
In the approach presented above you always wait for the visibility of a specific element. When an element is visible your test steps will go forward. There is no extra wait time which you got with implicit sleep
Avoid using sleep and replace it with an implicit wait or use expected condition if applicable. below is c# code for it
int time =10; // set maximum time required for operation
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(time));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath(""))); //replace "" with your desired xpath
The above code will wait for max 10 seconds for an element to be visible. but if it appears earlier then it will jump to next process so you need not have to wait for a specific time. Also, there are other expected conditions available like ElementExists, ElementToBeClickable etc. I will leave it to you to explore the appropriate option for yourself
if you wan t to use implicit wait specifically use below code
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(50));

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

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.

Selenium - wait for page to render dynamic page

I have a Dynamic web page that refreshes and loads new data. I am using Selenium and I need to wait till the page has finished rendering before I can continue checking the page. I have seen many posts about waiting for the page to load or using explicit waits (implicit wait could solve the problem but is very unelegant and not fast enough). The problem with using explicit waits is not having any info on what will come up after the refresh. I have seen some solutions talking about waiting for all the connections to the server to end but that will not promise me that the actual UI has finished rendering.
What I need is a way to know if a page has finished to render (not load!!)
First of all you DO KNOW what sctructure will come after the page will load. You don't know what tags were not on the page, but you know what DOM will look like. That's why usually it's worst practice to test with page text, but a good one to have a website tested by DOM only. So, depending on what structure appears on the page you will need to have explicit ways waiting for specific tags will appear on the page.
One more solution (but as I told it's not really the best practice) is to wait for document.readystate is "complete". This state will not help in every situation, but if you have something still loading on the page, in more then half cases it will not return complete. So, you should have some kind of implicit state that is executing:
string readyState = javascript.ExecuteScript("if (document.readyState) return document.readyState;").ToString();
and then checking:
readyState.ToLower() == "complete";
btw if you will use protractor as an angular js application test executor, it's waiting for angular page loaded by default, or in some difficult situations you can use:
browser.waitForAngular();
OR do something in a callback
button.click().then(function() {
// go next step
});
I have had similar problem with the product I am testing. I had to create special functions for click,click_checkbox,sendKeys and getText for example. These include try catch methods for cathcing NoSuchElement StaleElementReference exceptions. Also it retries if the actions fail, like sending the wrong text.
document.readyState
This isnt enough for you. It only waits for the DOM to load. WHen the HTML tag are loaded, it returns "complete". So you have to wait for each individual item.
This works for me well with dynamically rendered websites - I do not have a time constraint in getting the data as it would run in background for me, if efficiency is an issue may be this is not the solution for you (50s is a huge time for any website to load after the ready state is completed) :
Wait for complete page to load
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
Make another implicit wait with a dummy condition which would always fail
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true
}
catch (TimeoutException te) {
}
Finally, instead of getting the html source - which would in most of one page applications would give you a different result , pull the outerhtml of the first html tag
String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;";
content = ((JavascriptExecutor) driver).executeScript(script).toString();

Webelement.click in selenium

I am using selenium to do the UI automation for a web application.
1) My doubt is
when i use the click() method like, right_btn.click() whether it just clicks the right_btn and comes out or it just waits for the underlying actions to be completed before it moves out???
bcoz i read this
When i googled for WebElement.click() http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebElement.html it says like, it gets blocked whenever the click() involves opening a new page but here it doesnt opens a new page rather it involves in service call.
2) What i actually want to know?
I want to know this actually to calculate the latency involved in carrying out each actions in the UI. Is there any way to calculate the latency for each UI actions, just like we can see the latency time when we use inspect element in chrome. Thanks in advance.
In java, you can make a Date a = new date() object with the current time, just before your right_btn.click() and then wait for the resulting page to open, (if in a new tab/window - switch to it) and then find some element on that page
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("someid")));
After that returns the element, make another Date b = new Date()
The latency is the difference in milliseconds int millis = b-a;
Yes, a small part of that total time is Selenium searching for the 2nd element, but I'm afraid this might be the best you can do with java/selenium for your purpose.
I am not too sure if I understood your question exactly
How to calculate Latency is hard , but for intercepting calls you can use browserMobProxy in your code and check if particular call is complete and move on

Categories