Selenium waitForCondition - ajax

I am doing Selenium testing for the first time. On the homepage, I call some AJAX, and i want Selenium to wait for the element to load finish. I not sure it works, but i just type selenium and the waitForCondition are able to choose.
I not matter what I choose it always return "false". I do not now if the waitForCondition even work?
How can I test if it works?
And what am I doing wrong in this codes?
selenium.waitForCondition("//input[#name='Report'", "3000");
selenium.waitForCondition("//*[#id='MyTable']", "3000");
selenium.waitForCondition("css=.someClass2", "3000");
If I implement by own class - it return "true"
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
isElementPresent(By.xpath("//*[#id='MyTable']")) - return "true"

waitForCondition is for Javascript calls only, not for waiting for elements to load.
What you have in isElementPresent is fine. I would combine it with explicit waits to be a bit more accurate about when an element is actually loaded and present on the screen:
http://seleniumhq.org/docs/04_webdriver_advanced.html

C#
You can do it like this:
First of all you can set timeout value for the condition.
Then you can use the condition.
var Wait = new WebDriverWait(GlobalDriver, TimeSpan.FromMinutes(1));
Wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(By.XPath("xPath"))));
OR
Wait.Until(driver => driver.FindElement(By.XPath("xPath")));
Thats all.

You can do it like this :
selenium.waitForCondition("selenium.isElementPresent(\"//input[#name='Report']\")", "30000");
This will wait for the element to be loaded till 30 seconds.

Hope this works for you
new WebDriverWait(driver, 30).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (Boolean) js.executeScript("return jQuery.active == 0");
}
});
This will check if the jQuery library has any active AJAX requests for 30 seconds.

Aaran referred you to the correct documentation for Selenium WebDriver waits.
You can see that they also write about ExpectedConditions class. This contains several helpful implementation of ExpectedCondition classes, such at the "is element present one", which is ExpectedConditions.presenceOfElementLocated .
Here is an example of using it:
WebDriver driver = new ChromeDriver();
driver.get("http://www.degraeve.com/reference/simple-ajax-example.php");
driver.findElement(By.name("word")).sendKeys("bird is the word");;
driver.findElement(By.cssSelector("input[type='button']")).click();
WebDriverWait driverWait = new WebDriverWait(driver, 10);
WebElement dynamicElement = driverWait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#result p")));
System.out.println(dynamicElement.getText());
If you find it too verbose, why won't you just refactor it and extract a function which will accept the element locator and the webdriver, and returns you the element?
DriverWait.until() accepting an ExpectedCondition instance is like a way of passing a predicate function, just doing it through a class, or in the documentation example an anonymous nested class, since under Java you can't send a function.
The ExpectedCondition "function" you pass also returns a value, which can be useful in case you're waiting for a condition on some element (or some other value from the WebDriver), so returning it will save you an extra call.

Try this once:
await().atMost(10, SECONDS).until(() -> driver.findElements(By.id("elementId")).size() >1);

Related

I want to use assertion for the checkbox

I want to use assertion for this checkbox. It depends on duration. If it's checked duration = forever, if not = a month.
cy.wrap(cy.get('span.ant-checkbox').should('have.class','ant-checkbox-checked')).then((a) => {
if a == true {
cy.log('Forever')
}
})
A few thoughts:
You don't need to cy.wrap() your entire statement. cy.wrap() would primarily be used to wrap a JQuery yielded from cy.get() or a similar command, and insert it back into the Cypress command chain.
Your assertion that the element has a certain class will fail and stop your test before even getting to the .then() part of the command if the element does not have the ant-checkbox-checked class.
Instead, if we get the element, we can use JQuery functions (in this case, .hasClass())to determine if it has the class we want.
cy.get('span.ant-checkbox').then(($el) => {
// cy.get yields a JQuery<HTMLElement>
if ($el.hasClass('ant-checkbox-checked')) {
cy.log('Forever');
} else {
cy.log('A month');
}
});

Elegant Protractor Logging on browser.wait()

For some time now, our team has been using the Protractor/Jasmine combo in order to do E2E testing and it has worked out great for us.
Recently, I've been assigned the task of improving the logging and have noticed 2 areas in our code where the logging could be improved.
One of these areas is with using browser.wait(). We're currently using the method in the form of browser.wait(condition, timeOut) and excluding the third parameter which is a message to be written to the console in case of a failure.
I decided to comb the code and insert a message into each of these methods and the result has been OK. Although the code works, I'm wondering if there is a more elegant way of doing this.
I'm currently saving the XPath of whatever element I'm waiting on and then if that fails, displaying a message in the form: getWait() timeout due to <element_name> { XPath = <element_XPath> } being not visible or enabled such that you can click it. The pattern changes if we're using isPresent(), elementToBeClickable(), visibilityOf(), etc.
Is there a way of getting the current context of the code I'm executing when browser.wait() is executed? Can I instead display the element or more information on what caused the timeOut?
Let me know if I can clarify further. Thanks
Even I came faced the same problem when using browser.wait where it won't show any detailed log on time out. So what I have done is, I created a wrapper class for waitHandling and added failure messages based on the wait type. Kindly have a look at below code.
var browserWaitHandler = function () {
var expectedConditions = protractor.ExpectedConditions;
var defaultWaitTime = 5000;
this.waitForElementPresent = function (_element,customWaitTime) {
return browserWait(expectedConditions.presenceOf(_element),customWaitTime,"Wait timeout after waiting for element to be Present with locator "+_element.locator().toString());
};
this.waitForElementVisible = function (_element,customWaitTime) {
return browserWait(expectedConditions.visibilityOf(_element),customWaitTime,"Wait timeout after waiting for element to be Visible with locator "+_element.locator().toString());
};
this.waitForElementClickable = function (_element,customWaitTime) {
return browserWait(expectedConditions.elementToBeClickable(_element),customWaitTime,"Wait timeout after waiting for element to be clickable with locator "+_element.locator().toString())
};
this.waitForElementContainsText = function (_element,expectedText,customWaitTime) {
return browserWait(expectedConditions.textToBePresentInElement(_element,expectedText),customWaitTime,"Wait timeout after waiting for element to Contain text as "+expectedText+" with locator "+_element.locator().toString())
};
var browserWait = function (waitCondition,customWaitTime,timeoutMessage) {
return browser.wait(waitCondition,customWaitTime | defaultWaitTime,timeoutMessage);
};
};
And also in protractor we have a method called locator() which can be used with ElementFinder and ElementArrayFinder objects to get the locator that is used to find the element.Refer below example code,
var loginButton = element(by.buttonText("Login"));
console.log("Locator used for login button is:"+loginButton.locator().toString());
*OUTPUT:*
Locator used for login button is:by.buttonText("Login")

Firefox Selenium test freezes sometimes

I am using Selenium 2.46 and Firefox 31. Whenever my test gets to a point that an web-element does not exist (or an exception is thrown) my test freezes, but it does not happen when I use Chrome. Just to let you know I have already used different versions of selenium-java and Firefox. Please find the code below:
List<WebElement> divs = driverChrome.findElements(By.tagName("div"));
int i = 0;
while (true) {
boolean breakIt = true;
System.out
.println("Waiting for map to load completely, thanks for your patience.");
for (WebElement weDiv : divs) {
try {
if (weDiv.getText().equals("Loading")) {
Thread.sleep(2000);
breakIt = false;
break;
}
} catch (Exception e) {
}
}
if (breakIt) {
break;
}
driverChrome.manage().timeouts()
.implicitlyWait(5, TimeUnit.SECONDS);
divs = driverChrome.findElements(By.tagName("div"));
}
I am using this code to wait till a map is completely loaded
The most probable reason for your test to freeze is the while(true) loop. If the text "Loading" does not show up, there still can be an (invisible) element with that text.
Anyway, I would never use a wait mechanism without timeout. And I would always try to use methods provided by the framework.
WebDriver offers explicit and implicit wait mechanisms. This one-liner could replace your whole listing (waits for up to 60s, polling every two seconds):
new WebDriverWait(driver, 60000L, 2000L).until(ExpectedConditions.invisibilityOfElementWithText(By.tagName("div"), "Loading"));
Hope it helps. If not, check out other methods of ExpectedConditions or implement your own ExpectedCondition.

How can I write a wait_for_ajax call in selenium where the web page uses XMLHttpRequest based AJAX calls?

I have a select box which calls a XMLHttpRequest based AJAX call to populate another select box.
I want selenium to wait till the select box is populated. I have to wait for XMLHttpRequest's readyState variable to have value 4 which means data populated.
In Java: You could wait for the readyState change like this:
int tryCount = 0;
boolean desiredResponseReceived = false;
while (desiredResponseReceived == false && tryCount < 20) {
String readyState = (String) js.executeScript("return xhr.readyState;");
if (readyState.equals("4")) {
desiredResponseReceived = true;
}
else {
Thread.sleep(250);
tryCount++;
}
}
if (desiredResponseReceived == false) {
driver.quit();
}
One problem with looking for the ready state is, the page could be making more than one XMLHttpRequest. And you won't know which one is which. Even if you check for it immediately after clicking the relevant button (for example) even that could fire off multiple requests. And there's no telling which would return first.
Another option in your case might be to instead wait for the options in the select box to change. So in the code above, you might replace
String readyState = (String) js.executeScript("return xhr.readyState;");
if (readyState.equals("4")) {
with
List<WebElement> options = driver.findElements(By.tagName("option"));
if (options.size() > 1) {
Or if you don't know what minimum number of options to expect, you could test that an option with a particular attribute is in the List. Or something like that.

jQuery.ajax(): discard slow requests

I've build a livesearch with the jQuery.ajax() method. On every keyup events it receives new result data from the server.
The problem is, when I'm typing very fast, e.g. "foobar" and the GET request of "fooba" requires more time than the "foobar" request, the results of "fooba" are shown.
To handle this with the timeout parameter is impossible, I think.
Has anyone an idea how to solve this?
You can store and .abort() the last request when starting a new one, like this:
var curSearch;
$("#myInput").keyup(function() {
if(curSearch) curSearch.abort(); //cancel previous search
curSearch = $.ajax({ ...ajax options... }); //start a new one, save a reference
});
The $.ajax() method returns the XmlHttpRequest object, so just hang onto it, and when you start the next search, abort the previous one.
Assign a unique, incrementing ID to each request, and only show them in incrementing order. Something like this:
var counter = 0, lastCounter = 0;
function doAjax() {
++counter;
jQuery.ajax(url, function (result) {
if (counter < lastCounter)
return;
lastCounter = counter;
processResult(result);
});
}
You should only start the search when the user hasn't typed anything for a while (500ms or so). This would prevent the problem you're having.
An excellent jQuery plugin which does just that is delayedObserver:
http://code.google.com/p/jquery-utils/wiki/DelayedObserver
Make it so each cancels the last. That might be too much cancellation, but when typing slows, it will trigger.
That seems like an intense amount of traffic to send an ajax request for every KeyUp event. You should wait for the user to stop typing - presumably that they are done, for at least a few 100 milliseconds.
What I would do is this:
var ajaxTimeout;
function doAjax() {
//Your actual ajax request code
}
function keyUpHandler() {
if (ajaxTimeout !== undefined)
clearTimeout(ajaxTimeout);
ajaxTimeout = setTimeout(doAjax, 200);
}
You may have to play with the actual timeout time, but this way works very well and does not require any other plugins.
Edit:
If you need to pass in parameters, create an inline function (closure).
...
var fun = function() { doAjax(params...) };
ajaxTimeout = setTimeout(fun, 200);
You will want some kind of an ajax queue such as:
http://plugins.jquery.com/project/ajaxqueue
or http://www.protofunc.com/scripts/jquery/ajaxManager/
EDIT:Another option, study the Autocomplete plug-in code and emulate that.(there are several Autocomplete as well as the one in jquery UI
OR just implement the Autocomplete if that serves your needs

Resources