java-selenium
Hi,
I am recently working with selenium-java for project automation.
I found that in a lot of codes are using this method.
waitForAngularRequestsToFinish();
I don't know exactly why is this in the main function.
And in the next example is my code, cause I don't know what is the benefit of using at the beginning and at the end this method.
Example of this code:
public void ActualizarEstadoDeFinalizacion(String caso) {
waitForAngularRequestsToFinish();
JavascriptExecutor js = (JavascriptExecutor) getDriver();
js.executeScript("window.scrollBy(850)");
WebElement htmlScrollProblemaDeCierre = findBy(String.format("//*[#title='%s']//ancestor::div[#class='oneWorkspaceTabWrapper']//span/span[contains(.,'Estado de finalizaciĆ³n')]//following::a[1]/parent::div/parent::div/parent::Div/parent::div",caso));
htmlScrollProblemaDeCierre.click();
waitForAngularRequestsToFinish();
}
The author of the code has created a function called waitForAngularRequestsToFinish().
This is a way to wait for all the pending requests to load...
Generally, it will be implemented with JavaScript... You can see it in paul-hammant's ngWebDriver.
If you want you can implement it yourself:
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("var injector = window.angular.element('body').injector(); var $http = injector.get('$http'); return ($http.pendingRequests.length === 0);")
The benefit of using it at the beginning and at the end of the method is to ensure that the page you come to and the page you lead to are fully loaded.
Hope this helps you!
This method waitForAngularRequestsToFinish(); is used to wait for the elements or request in Angular application. This method will wait until all the request has been completed. This is mostly used in Angular application. For more check its documentation in the given link.
https://github.com/paul-hammant/ngWebDriver
Related
I have a problem with the automation of PayPal sandbox by Selenium Python.
Generally, I wrote explicit waits for each action method like send_keys(), or click() into the button, but they just don't work. I tried almost all explicit waits that are available.
I tried to adapt method which will be waiting until Angular script will be fully loaded, but it totally doesn't work because of this app based on Angular v.1., by executing javascript.
For example:
while self.context.browser.execute_script(
"return angular.element(document).injector().get('$http').pendingRequests.length === 0"):
sleep(0.5)
The only method which works are static python sleep, which is totally inappropriate! But when I add 2 seconds of sleep between every first action on the page, the test passing without any problems, while I trying to replace sleep by for example WebDriverWait(self.context.browser, timeout=15).until(EC.visibility_of_all_elements_located) , the test stop when all elements are visible on the page.
Can someone handle this?
My code witch sleeps between each page objects:
context.pages.base_page.asert_if_url_contain_text("sandbox.paypal.com")
context.pages.paypal_login_page.login_to_pp_as(**testPP)
sleep(2)
context.pages.choose_payment_page.pp_payment_method("paypal")
sleep(2)
context.pages.pay_now_page.click_pay_now()
sleep(2)
context.pages.finish_payment_page.click_return_to_seller()
sleep(5)
context.pages.base_page.open()
Example method witch explicit wait:
def click_pay_now(self):
WebDriverWait(self.context.browser, timeout=15).until(EC.visibility_of_all_elements_located)
self.pay_now_button.is_element_visible()
self.pay_now_button.click()
visibility_of_all_elements_located() will return a list, instead you need to use visibility_of_element_located() which will return a WebElement.
Ideally, if your usecase is to invoke click() then you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(self.context.browser, timeout=15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css"))).click()
Using XPATH:
WebDriverWait(self.context.browser, timeout=15).until(EC.element_to_be_clickable((By.XPATH, "element_xpath"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a relevant detailed discussion in:
Do we have any generic function to check if page has completely loaded in Selenium
Selenium wait sometime not works well with AngularJs or reactJs based app that's why protractor is best tools for AngularJs or reactJs based app. Although I hope If you can try below solution it can work as it based on Javascript.
A function will check page is fully loaded or not.
def page_has_loaded():
page_state = browser.execute_script(
'return document.readyState;'
)
return page_state == 'complete'
Then use wait with combination of very small sleeping time that can be less as soon as page will be loaded.
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 2:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception(
'Timeout waiting for {}'.format(condition_function.**name**)
)
And you can call it as mentioned below:
wait_for(page_has_loaded)
I have an element on a web page that is updated by AJAX almost immeditely after page load. I know what I expect the change to be and want Selenium to wait for the change and capture it. I am trying to use an explicit wait for this. However, I am getting a timeoutException as Selenium is not detecting the change.
I know I am properly selecting the element and value as I have used print statements. I've solved the issue using
Java Thead.sleep(1000)
and then using
driver.findElement(By.id("balance-sms")).getText()
but this is not an acceptable solution.
private void modalSend(String newBalence){
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(modalSendButton)); //this wait works fine
modalSendButton.click(); //this results in a page refresh
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.id("balance-sms")),newBalence));
//continue...
}
Try the locator using xpath and visibilityOfElementLocated with a few modifications :
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='balance-sms' and contains(text(),'" +newBalence +"')]")));
//continue...
Try with fluent wait like below instead of Thread.sleep
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);
Using selenium 3.141.5 (Latest) and java 8. Now I have a situation where I need to wait for particular element on webpage to get loaded before I execute next line. I am trying to use ExpectedConditions java class but unable to import this. In the javadoc of selenium I can find ExpectedConditions and ExpectedCondition. [PSB]
static ExpectedCondition<WebElement> presenceOfElementLocated(By locator)
An expectation for checking that an element is present on the DOM of a page.
I am not using any maven or any other tool. it is just eclipse, java and selenium.
Image from my local eclipse
Please help for the same. I just want to wait for particular element to get loaded before I execute my next line of code with latest selenium and java. Thanks in advance! :) I hope I have tried to explain well if not then sorry
I'm using ExpectedConditions:
// modified wait method
public WebDriverWait wait_sec(WebDriver driver, int sec) {return new WebDriverWait(driver, sec);}
// example of usage one of ExpectedConditions
driver.get(url_portal);
WebElement fld_pwd = wait_sec(driver, 60).until(ExpectedConditions.elementToBeClickable(By.name("password")));
fld_pwd.click();
fld_pwd.sendKeys(sec_var.getPwd());
// example of negative usage
wait_sec(driver, 300).until(ExpectedConditions.not(ExpectedConditions.urlContains("#")));
Exploring ExpectedConditions was trully essential for my tests.
I switched to selenium 3.11 and now everything is working as expected!. There I can use ExpectedConditions
Thanks
I'm using webdriver(java) for a unique test where a page reloads itself when you log on, I've been unable to wait for the element to load because it is already there before the reload. So far the only way I've been able to get it to work is to use a thread.sleep, is there a way to listen for a page refresh?
One way to solve this is, to get a reference to the element you need, that appears both on the login-page and the reloaded page.
Then you can use the ExpectedConditions.stalenessOf to occur, and then you can be sure, that the element is removed from the DOM and a new element is created. Well, the last part is not guaranteed by this method, but at least you know that the old element is gone.
The code could look something like this:
WebElement elementOldPage = driver.findElement(By.id("yourid"));
... do login etc ...
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.stalenessOf(elementOldPage));
WebElement elementNewPage = driver.findElement(By.id("yourid"));
Building upon the accepted answer from Kim Schiller one might be interested in the following piece of code. It is surely not perfect due to the sleeps, so be free to suggest improvements to make it more bulletproof. Also note I'm no expert with selenium.
The if branch waits for the top level node in the html to go stale in case of a page reload. The else branch simply waits until the drivers url matches the request url in case we load a different page.
def safe_page_load(url):
if driver.current_url == url:
tmp = driver.find_element_by_xpath('/html')
driver.get(url)
WebDriverWait(driver, 2).until(ExpectedConditions.staleness_of(tmp))
else:
driver.get(url)
while(driver.current_url) != url:
sleep(0.3)
sleep(0.3)
Happy if I could help someone.
I have been running into intermittent errors with some java selenium-rc tests which I think are related to a page which has an ajax poll and automatically refreshes when some condition is reached on the server. In this scenario, I have no way of asking selenium to wait for the page to load, and so I run into a bunch of random "Couldn't access document.body" errors.
So, is there some way I can cause selenium to gracefully handle this situation? If not, is there some way I could detect whether the user is selenium from the page's javascript, and disable the automatic refresh?
If it helps at all, the javascript code in the page looks something like...
var ajax = new Ajax(url, {
update: state,
method: 'get',
onComplete: function(message) {
if (some_condition) {
window.location.replace(unescape(window.location));
}
}
});
One solution might be to always use a waitForCondition using isElementPresent before attempting to interact with the application under test. You could put the following method in a superclass to keep your tests more readable. Alternatively you could create helper methods for common Selenium commands that perform this wait.
/** Waits for an element to be present */
public static void waitForElementToBePresent(String locator) {
session().waitForCondition("var value = selenium.isElementPresent('" + locator.replace("'", "\\'") + "'); value == true", "60000");
}
You may also want to wait for the element to be visible, as waiting for it to just be present isn't always enough (imagine a textbox that is always present but hidden until a certain condition). You can combine this with the above method:
/** Waits for an element to be visible */
public static void waitForElementToBeVisible(String locator) {
waitForElementToBePresent(locator);
session().waitForCondition("var value = selenium.isVisible('" + locator.replace("'", "\\'") + "'); value == true", TIMEOUT);
}
Incidentally, the WebDriver (Selenium 2) team are working on having implicit waits, specifically to address AJAX issues where elements are not present immediately.
My solution was to disable the refresh in javascript by wrapping it in something like the following...
var isSeleniumActive = parent.seleniumAlert;
if (isSeleniumActive) {
alert("Selenium");
} else {
alert("Not selenium");
}
I'm not sure if the seleniumAlert function here is likely to sick around forever, so be aware if you're taking this that you may be relying on internal selenium implementation details of selenium.
There i was facing the same problem and i use a single line of code and it helps.
i was getting the error about the page is getting auto refresh
plus this warning:
-1490472087141 Marionette WARN Using deprecated data structure for setting timeouts
all i use is
Thread.sleep(2000)
and it worked for me.
I think that you can pause, or use a click and wait. There are a few good articles on the google. Good luck.
Edit for your comment:
How about the waitFor command?