Trigger page load blocking explicitly in Selenium Webdriver - selenium

I understand that the top level webdriver API doesn't provide access to the page load event handler, but is there any way (including sending a command directly to the server through the REST interface) to make a call directly to the selenium server to force the page load block behavior? I know about the wait for element hack, but I'd rather go straight to the source if at all possible. The specific problem I'm having is a page that makes a JS call when a button is clicked that displays a modal dialog on the page while some backend processes happen, then forwards the browser to a new page once the backend work is complete. Since the click action doesn't directly trigger the new page, selenium doesn't block on the event (and I wouldn't want it to in all cases anyway).
I've looked through the Command class for any promising looking commands, but didn't see anything. I found http://code.google.com/p/selenium/wiki/JsonWireProtocol but it didn't help either...

Thats a tricky one.
Accessing the http status in selenium/webdriver is not very handy.
I would recommend a pragmatic way. IMO the wait for element approach is not a hack, its the proper way to do it. In your case I would wait for selenium.getLocation() or webdriver.getCurrentUrl() contains an expected value.
Something like this:
webDriverWait.until(new Function<WebDriver, WebElement>() {
#Override
public WebElement apply(WebDriver driver) {
//TODO: pass expected url as parameter
boolean expectedUrl = driver.getCurrentUrl().contains("your redirect url");
if (expectedUrl) {
//If not null is returned, we have found something and waitUntil stops
return new RemoteWebElement();
}
//try again
return null;
}
});

Related

Selenium Send keys intermittently skips over text fields

I am writing automation tests that send keys to every text box on a form (about 5 fields) and then a submit button becomes enabled and clicked. I find that the test frequently fails as only the last field is populated and the button never becomes enabled.
It seems like the method to send keys may be executing too fast for the page to be populated. So far I have attempted to click on each field before sending keys (as well as waiting for the elements to exist) and this doesn't seem to help.
I have also tried to verify the page is fully loaded by waiting for every element and button to exist on the page before proceeding.
The browser I am testing against is chrome. (Version 79.0.3945.130)
The selenium web-driver is 3.11.2
The chrome driver is up to date with chrome
private IWebElement FirstNameInput => Webdriver.FindElement(By.Id("first-name-input"));
// The remaining input fields
public void VerifyPageIsFullyLoaded()
{
// Wait until all elements exist
}
public void EnterFormDetails(FormDetail formDetail)
{
WebDriver.WaitUntilElementExists(FirstNameInput);
FirstNameInput.Click();
FirstNameInput.SendKeys(formDetail.FirstName);
WebDriver.WaitUntilElementExists(LastNameInput);
LastNameInput.Click();
LastNameInput.SendKeys(formDetail.LastName);
WebDriver.WaitUntilElementExists(DateOfBirthInput);
DateOfBirthInput.Click();
DateOfBirthInput.SendKeys(formDetail.DateOfBirth);
WebDriver.WaitUntilElementIsClickable(SubmitButton);
SubmitButton.Click();
}
Update:
Just tried the latest stable release of selenium web driver (3.141.0) and found that it is still not as reliable.
JavascriptExecutor javascript = (JavascriptExecutor)webdriver;
javascript.executeScript("document.getElementById('FirstNameInput').value='test123'");
javascript.executeScript("document.getElementById('LastNameInput').value='test123'");
javascript.executeScript("document.getElementById('DateOfBirthInput').value='test123'");
SubmitButton.Click();
and if the submit button is in form tag then you can use submit() method.

Selenium Page Objects: Why should I return this?

Reading SeleniumHQ's pageobject documentation they specify examples of returning "this" from methods that do not navigate to other pages. My question is why?
I thought maybe the state of the page object could be a reason, however the page itself (the actual UI page) may change state or refresh but the page object itself would not. Page Factory with its #FindBy annotations already ensure that each WebElement will be found every time it is called, so the state of the elements doesn't seem to be relevant this case.
Consider their example
public LoginPage typeUsername(String username) {
driver.findElement(usernameLocator).sendKeys(username);
return this;
}
public LoginPage typePassword(String password) {
driver.findElement(passwordLocator).sendKeys(password);
return this;
}
public HomePage submitLogin() {
driver.findElement(loginButtonLocator).submit();
return new HomePage(driver);
}
now assume we have create the page object create as page. If you didn't return anything your code would like
page.typeUsername("tarun");
page.typePassword("lalwani");
HomePage newPage = page.submitLogin()
But when you return this, it allows you to do method chaining. So I can use it like below
HomePage newPage = page.typeUsername("tarun").typePassword("lalwani").submitLogin()
As you can see it will save you some coding effort and much more elegant with IDE intellisense
It allows method chaining, as demonstrated in Tarun's answer, but it also captures flow. If logging in from the Login Page routes you to the Home Page, then your login method would return a Home Page page object. If that flow ever changed, you would update your login method to return some other page object and it would cause errors in the IDE everywhere that the flow would fail. It helps you find the places you need to fix faster.
Having said that, I don't return page objects in my methods. I'm not a big fan of method chaining for page objects. I think it obscures the test flow because you can lose track of which page you are on by chaining too many methods together.
By returning page objects, you also have to write extra methods for error cases, etc. You can see this in their example. There is a submitLogin() method that returns a Home Page and a submitLoginExpectingFailure() that returns a Login Page and so on. For me, I haven't found the benefits to outweigh the extra code and difficulty reading the test flow.

Does selenium / webdriver with protractor wait for async activity in a describe block before continuing?

I have code in a desribe block but some of my set up code is outside of the block. That's the code that sets up elements.
When my code executes it runs fine but then I see the browser go to another page before parts of my test have completed. With a different page on the browser then it looks for elements and throws an exception when they are not there.
So how can I handle this problem of the browser going to another page before tests are completed?
As per my understanding of the question you want to be on the same page and don't want to move to the new page which loads when you click on to a link/button. If this is the case then to be on the same page you cane use.
Use this command -String oldwindow=window.getWindowHandle();
window.switchTo().window(oldwindow);
Use this command just below the button code which throws a new window. I am a java programer thats why the code written is in java.
getWindowHandle Methods stores the url of current window in oldwindow string and by using window.switchTo().window(oldwindow) it won't move to new window because you are passing oldwindow as argument for the command.
For more go through the Webdriver documentation by clicking this link

How to autorefresh chromeDriver with Selenium?

Previously I have been using chrome Auto Refresh plug in. However, now my code has multiple ChromeDriver instances opening and closing and I cannot use Auto Refresh. Also, it is quite a hassle to install Auto Refresh on new computers.
Is there any way to refresh driver (simulate F5 say every 15 seconds if driver does not change remains motionless) with Selenium similar to Google Auto Refresh?
refresh is a built in command.
driver = webdriver.Chrome()
driver.get("http://www.google.com")
driver.refresh()
If you don't have the chrome driver it can be found here:
https://code.google.com/p/chromedriver/downloads/list
Put the binary in the same folder as the python script you're writing. (Or add it to the path or whatever, more information here: https://code.google.com/p/selenium/wiki/ChromeDriver)
edit:
If you want to refresh ever 10 seconds or something, just wrap the refresh line with a loop and a delay. For example:
import time
while(True):
driver.refresh()
time.sleep(refresh_time_in_seconds)
If you only want to refresh if the page hasn't changed in the meantime, keep track of the page that you're on. driver.current_url is the url of the current page. So putting it all together it would be:
import time
refresh_time_in_seconds = 15
driver = webdriver.Chrome()
driver.get("http://www.google.com")
url = driver.current_url
while(True):
if url == driver.current_url:
driver.refresh()
url = driver.current_url
time.sleep(refresh_time_in_seconds)
Well there are two ways of doing this.
1. We can use refresh method
driver.get("some website url");
driver.navigate().refresh();
We can use actions class and mimic F5 press
Actions act = new Actions(driver);
act.SendKeys(Keys.F5).perform();
If you write unit tests that must be run like if you had to open/refresh a new browser session each time, you can use a method with before annotations:
#Before
public void refreshPage() {
driver.navigate().refresh();
}
If all tests are individually successful (green) but fail all together, the reason might also been that you need to wait for some resources to be available on the page, so you also need to handle it, setting the timeout like this:
public WebElement getSaveButton() {
return findDynamicElementByXPath(By.xpath("//*[#id=\"form:btnSave\"]"), 320);
}
320 is a long time, but you must make sure that you give enough time to get all that it takes to test.

How to avoid waiting for request in background with selenium web driver?

I just started using Selenium Web Driver to test an online banking transaction application.
I love it, but there is something that annoy me. Let say i access the login screen with this code:
driver.get("https://webdev.myurl:18113/");
WebElement element = driver.findElement(By.name("username"));
element.sendKeys("xxxx");
element.submit();
the browser start and the page load and display. But it look like the page try loading element from an external site and the findElement (2nd line) wait for these request to complete!
Is there a way to bypass this beahvior?
I tried this too :
WebElement element = (new WebDriverWait(driver, 10)).until(new ExpectedCondition<WebElement>() {
#Override
public WebElement apply(WebDriver d) {
return d.findElement(By.name("username"));
}
});
But it does not help since this line seems to execute only when the page is totally loaded.
EDIT: I spoke with one of the guy here.. and he told me ipinvite.iperceptions.com is not called by our app.!!! and in fact when i load the site in FF, i don't see this call?!
Does Selenium web driver call this site : ipinvite.iperceptions.com?
Anyone have the same issue?
You can try setting implicitly wait time and page load time to 0. Google "selenium implicitly wait time" and "selenium page load time."
Time outs on get function have not been implemented yet.
When creating a new FirefoxDriver, there are overloads in the constructor that allow you to specify a command timeout which is the maximum time to wait for each command.
You could refer to the answer on this post
ok, i found the problem. I commented out the setPreference to my FirefoxProfile that was setting the proxy parameters. I noticed i did not need them anyway. And now there is no more call to this wierd ipinvite.iperception.com!
Thanks for the time you took to reply
Regards