Selenium not inputting the whole text into a text box - selenium

I am using Selenium to clear out the existing Shipping Address fields of a Salesforce Account object and to assign new values. I am coding in C# and running on Visual Studio 2019.
I am getting cases where the textboxes are not getting fully populated.
My code is below.
private string shippingStreet = "56789 Liberty Street"; // 80 character limit
private string shippingCity = "Toronto"; // 40 character limit
private string shippingState = "ON"; // 80 character limit
private string shippingZip = "87654"; // 20 character limit
private string shippingCountry = "Canada"; // 80 character limit
IWebElement shStreet = driver.FindElement(By.XPath("//textarea[#placeholder='Shipping Street']"));
shStreet.Clear();
shStreet.SendKeys(shippingStreet);
IWebElement shCity = driver.FindElement(By.XPath("//input[#placeholder='Shipping City']"));
shCity.Clear();
shCity.SendKeys(shippingCity);
IWebElement shState = driver.FindElement(By.XPath("//input[#placeholder='Shipping State/Province']"));
shState.Clear();
shState.SendKeys(shippingState);
IWebElement shZip = driver.FindElement(By.XPath("//input[#placeholder='Shipping Zip/Postal Code']"));
shZip.Clear();
shZip.SendKeys(shippingZip);
IWebElement shCountry = driver.FindElement(By.XPath("//input[#placeholder='Shipping Country']"));
shCountry.Clear();
shCountry.SendKeys(shippingCountry);
Please see the screenshot.
I fix this issue by adding an extra space after city, state, zip code, and country but I was wondering if there is a better solution.

You can try this method:
Just call it and add the xpath: WaitForElementDisplayed_byXPathTime("//myPath");
WaitForElementDisplayed_byXPathTime
public static void WaitForElementDisplayed_byXPathTime(string value)
{
var wait = new WebDriverWait(Driver, new TimeSpan(0, 0, 30));
wait.Until(webDriver => webDriver.FindElement(By.XPath(value)).Displayed);
}
The other thing I have done on these is create a new type method for individual characters like you would on mobile. This just slows it down a bit.
public static void TypeCharsIndividually(IWebElement element, string expectedValue)
{
//use your code for element displayed and element enabled
element.Click();
element.Clear();
foreach (char c in expectedValue)
{
element.SendKeys(c.ToString());
Thread.Sleep(100);
}
}
java click
public static void ClickJava(IWebElement element)
{
IJavaScriptExecutor executor = driver IJavaScriptExecutor;
executor.ExecuteScript("arguments[0].click();", element);
}
WaitForElement
public static bool WaitForElementDisplayed_byXPath(string path)
{
var result = true;
try { _wait.Until(webDriver => driver.FindElement(By.XPath(path)).Displayed); }
catch (StaleElementReferenceException) { WaitForElementDisplayed_byXPath(path); }
catch (NoSuchElementException) { WaitForElementDisplayed_byXPath(path); }
catch (WebDriverTimeoutException) { result = false; }
return result;
}

This is a Salesforce issue. I see the problem even when i am manually updating a shipping address field and I tab to another field.

Related

Why my selenium function say no Element found

Why if i use same code of affordabilityErrorVerify() in mortgageCalculator() function its working fine but when i use that code in affordabilityErrorVerify() [ same as i posted here ] it says : --> org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#ifrm_13536"}
its weird for me can someone help me how i can make it work
public class test1 extends base {
public WebDriver driver;
public static Logger log =LogManager.getLogger(base.class.getName());
#BeforeTest
public void initialize() throws IOException {
driver = initializeDriver(); // initialize the browser driver based on data.properties file browser value
}
#Test(dataProvider = "dataDriven")
public void mortgageCalculator(String amount, String year, String Frequency, String type, String product,
String term, String rate) throws IOException, InterruptedException {
driver.get(prop.getProperty("url")); // read the data.properties file for get the value of url
driver.manage().window().maximize();
LandingPage l = new LandingPage(driver); // created object for Landing page to access page element
Actions actions = new Actions(driver);
WebElement mainMenu = l.menuBar();
actions.moveToElement(mainMenu);
WebElement subMenu = l.clickLink();
actions.moveToElement(subMenu);
actions.click().build().perform();
// Explicit wait because calculator is in frame and it loads after some time
// so wait until frame is visible
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(#class,'col-12 col-md-9 side-content')]")));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,500)");
// switch to frame elements
driver.switchTo().frame(l.switchToFrame());
Thread.sleep(3000);
l.productTabClick().click(); // click on product tab
Thread.sleep(3000);
WebElement money = l.mortgageAmount();
money.click();
money.sendKeys(Keys.CONTROL + "a");
money.sendKeys(Keys.DELETE);
money.sendKeys(amount);
WebElement period = l.mortgageYear();
period.click();
period.sendKeys(Keys.CONTROL + "a");
period.sendKeys(Keys.DELETE);
period.sendKeys(year);
Select s = new Select(l.paymentFrequency());
s.selectByValue(Frequency);
// if data provider send Fixed it will click on fixed radio button otherwise click on variable
if (type == "Fixed") {
l.paymentType().click();
} else {
l.paymentType().click();
}
Select ss = new Select(l.paymentProduct());
ss.selectByValue(product);
Thread.sleep(3000);
driver.switchTo().defaultContent();
js.executeScript("window.scrollBy(0,300)");
driver.switchTo().frame(l.switchToFrame());
Thread.sleep(3000);
WebElement inputOwnRateTerm = l.paymentTerm();
inputOwnRateTerm.click();
inputOwnRateTerm.sendKeys(Keys.CONTROL + "a");
inputOwnRateTerm.sendKeys(Keys.DELETE);
l.paymentTerm().sendKeys(term);
WebElement inputOwnRateValue = l.paymentRate();
inputOwnRateValue.click();
inputOwnRateValue.sendKeys(Keys.CONTROL + "a");
inputOwnRateValue.sendKeys(Keys.DELETE);
l.paymentRate().sendKeys(rate);
inputOwnRateValue.sendKeys(Keys.ENTER);
Thread.sleep(3000);
String actualPayment = l.monthlyPayment().getText();
String actualIOT = l.interestOverTerm().getText();
String actualInterestOverTerm = actualIOT.substring(0, actualIOT.length()-1);
//double actualInterestOverTerm = Math.round(actualIOT)* 10.0) / 10.0;
//System.out.print(actualPayment); // uncomment to see what Mortgage Payment amount function is returning for given data
//System.out.print(actualInterestOverTerm);
//System.out.print(actualIOT);
String totalAmount = amount;
int arg1 = Integer.parseInt(totalAmount);
String mortgageRate = rate;
double arg2 = Double.parseDouble(mortgageRate);
String totalYear = year;
int arg3 = Integer.parseInt(totalYear);
// to find out total Interest over term months based on year
String iot = term;
int iot1 = Integer.parseInt(iot);
int arg4 = iot1 * 12;
// Pass all 4 argument into mortgage calculator to assert actual and expected result
calculator c = new calculator();
double[] expected = c.mortgageCalculator(arg1, arg2, arg3, arg4);
//System.out.println("Mortgage Payment :" + expected[0]); // giving back Mortgage Payment amount from custom function
//System.out.println("Interest over term :" + expected[1]); // giving back Interest over term amount from custom function
NumberFormat defaultFormat = NumberFormat.getCurrencyInstance(); // converting numbers into money format [number format]
String act = defaultFormat.format(expected[1]);
String expectedInterestOverTerm = act.substring(0, act.length()-1);
//***********************
// ActualPayment = Getting value from https://www.coastcapitalsavings.com/calculators/mortgage-calculator
// Expected[0] = Getting value from calculator() function which is mortgageCalculator logic file
//***********************
Assert.assertEquals(actualPayment,defaultFormat.format(expected[0])); // Assertion to find out both values are same
Assert.assertEquals(actualInterestOverTerm,expectedInterestOverTerm); // Assertion to find out both values are same
log.info("*************Expected****************");
log.info("Mortgage Payment :" + expected[0]);
log.info("Interest Over Term :" + expectedInterestOverTerm);
log.info("**************Actual*****************");
log.info("Mortgage Payment :" + actualPayment);
log.info("Interest Over Term :" + actualInterestOverTerm);
log.info("_______________________________________");
}
#Test
public void affordabilityErrorVerify() throws InterruptedException
{
LandingPage l = new LandingPage(driver); // created object for Landing page to access page element
JavascriptExecutor js = (JavascriptExecutor) driver;
Thread.sleep(3000);
driver.switchTo().defaultContent();
js.executeScript("window.scrollBy(0,-500)");
Thread.sleep(3000);
driver.switchTo().frame(l.switchToFrame());
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(#class,'col-12 col-md-9 side-content')]")));
Thread.sleep(3000);
l.affordabilityTabClick().click(); // click on affordability tab
Thread.sleep(3000);
driver.findElement(By.cssSelector("slider-control:nth-child(3) > #slider-container #name")).click();
driver.findElement(By.cssSelector("slider-control:nth-child(3) > #slider-container #name")).sendKeys("10000");
driver.findElement(By.cssSelector("slider-control:nth-child(3) > #slider-container #name")).sendKeys(Keys.ENTER);
}
By looking at your code, I have a probable solution to your problem.
There is no priority defined for tests. So in TestNG, if priority is not defined, the test will get executed in alphabetical order. In this case, affordabilityErrorVerify() test will execute first and then mortgageCalculator().
If I observe affordabilityErrorVerify(), there is no method to open URL like driver.get(url) so no page will get open and it will cause NoSuchElementException
A possible answer can be assigned priority to tests
#Test (priority=1, dataProvider = "dataDriven")
public void mortgageCalculator(String amount, String year, String Frequency, String type, String product,
String term, String rate) throws IOException, InterruptedException {
//code
}
#Test (priority=2)
public void affordabilityErrorVerify() throws InterruptedException
{
//code
}
In this as well you have to make sure actions on second test are continuing on same page where test1 ends.
Modify your tests and actions considering flow of test and it will work
Happy coding~

How to pass multiple locators in Selenium webdriver to fetch an element on a page

Hi can anyone pls solve this. When i write a code to automate sometimes the elements are not identified and sometimes its not found even they are present, means even if the id is present it says element not found error. So I a trying to create a method where i would pass all the dom objects i find like Ex :
public static void Click(WebDriver driver, String name,Sting linktext,Sting id,Sting Xpath,String css)
{
driver.findElement(new ByAll(By.name(name),
By.linkText(linktext),
By.id(id),
By.xpath(xpath),
By.cssSelector(css))).click();
}
And i would pass what ever value i find in source page like sometimes it will have oly id or it ll have oly link text Ex:(when i import this method in other class)
Click(Webdriver driver, "username",null,"","//[fas].user");
is this the correct way to pass the arguments. can i pass like null and "" (blank). Pls help this would become a one simple effective framework for me.
you can use this 2 methods
public static WebElement findElement(WebDriver driver, By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.presenceOfElementLocated(selector));
return findElement(driver, selector);
}
public static WebElement findElementSafe(WebDriver driver, By selector, long timeOutInSeconds) {
try {
return findElement(driver, selector, timeOutInSeconds);
} catch (TimeoutException e) {
return null;
}
}
public static void waitForElementToAppear(WebDriver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
try {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
} catch (TimeoutException e) {
throw new IllegalStateException(timeOutMessage);
}
}
----------------
public static void click(WebDriver driver , By ... selector ){
for (By byPath : selector) {
WebElement element = findElementSafe(driver, byPath, 1);
if(element != null){
element.click();
}
}
}

Selenium WebDriver generates StaleElementReferenceExeption on getText() on table elements

The current environment:
Selenium Server version 2.37.0
RemoteWebDriver running on Firefox
no Ajax / asynchronously loaded content
My tests are attempting to validate the content of each cell of an HTML table. Before accessing any table element an explicit wait verifies that the <tbody> element exists
ExpectedCondition<WebElement> recruitTableIsPresent = ExpectedConditions.presenceOfElementLocated(By.id("newRecruitFieldAgentWidget:newRecruitDataTable_data"));
new WebDriverWait(driver, 5).until(recruitTableIsPresent);
Once the table is verified to exist, data is pulled out by row and column
private Stats[] parseStats() {
String xpath = "//tbody[#id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]";
Stats[] stats = new Stats[3];
for (int i = 0; i < stats.length; i++) {
String inProgresOrders = cellContent(xpath, i, 1);
String maxCapacity = cellContent(xpath, i, 2);
String allocationRatio = cellContent(xpath, i, 3);
Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio);
}
return stats;
}
private String cellContent(String xpathTemplate, int row, int cell) {
String xpath = String.format(xpathTemplate, row + 1, cell + 1);
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
WebElement elementByXPath = driver.findElementByXPath(xpath);
return elementByXPath.getText();
}
I don't see any race conditions, since the table content is populated with the page, and not in an asynchronous call. Additionally, I have seen other answers that suggest invoking findElement() via the driver instance will refresh the cache. Lastly, the explicit wait before accessing the element should ensure that the <TD> tag is present.
What could be causing the getText() method return the following exception:
org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
It's worthwhile to note that the failure is intermittent. Some executions fail while other passes through the same code pass. The table cell causing the failure are also not consistent.
There is a solution to this using Html-Agility-Pack.
This will work only if you want to read the data from that page.
This goes likes this
//Convert the pageContent into documentNode.
void _getHtmlNode(IWebDriver driver){
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(driver.PageSource);
return htmlDocument.DocumentNode;
}
private Stats[] parseStats(){
String xpath = "//tbody[#id='regionalFieldAgentWidget:regionalDataTable_data']/tr[%d]/td[%d]";
Stats[] stats = new Stats[3];
for (int i = 0; i < stats.Length; i++) {
String inProgresOrders = cellContent(xpath, i, 1);
String maxCapacity = cellContent(xpath, i, 2);
String allocationRatio = cellContent(xpath, i, 3);
Stats[i] = new Stats(inProgressORders, maxCapacity, allocationRatio);
}
return stats;
}
private String cellContent(String xpathTemplate, int row, int cell) {
String xpath = String.format(xpathTemplate, row + 1, cell + 1);
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
var documentNode = _getHtmlNode(driver);
var elementByXPath = documentNode.SelectSingleNode(xpath);
return elementByXPath.InnerText;
}
now read any data.
Some tips for using htmlNode.
1. Similar to driver.FindElement: document.SelectSingleNode
2. Similar to driver.FindElements: document.SelectNodes
3. Similar to driver.Text: document.InnerText.
For more search regarding HtmlNode.
Turns out there was a race condition as I've already mentioned. Since jQuery is available via PrimeFaces there is a very handy solution mentioned in a few other posts. I implemented the following method to wait for any asynchronous requests to return before parsing page elements
public static void waitForPageLoad(JavascriptExecutor jsContext) {
while (getActiveConnections(jsContext) > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
private static long getActiveConnections(JavascriptExecutor jsContext) {
return (Long) jsContext.executeScript("return (window.jQuery || { active : 0 }).active");
}
Each built in driver implementation implements the JavascriptExecutor interface, so the calling code is very straightforward:
WebDriver driver = new FirefoxDriver();
waitForPageLoad((JavascriptExecutor) driver);

Selenium wait until document is ready

Can anyone let me how can I make selenium wait until the time the page loads completely? I want something generic, I know I can configure WebDriverWait and call something like 'find' to make it wait but I don't go that far. I just need to test that the page loads successfully and move on to next page to test.
I found something in .net but couldn't make it work in java ...
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
Any thoughts anyone?
Your suggested solution only waits for DOM readyState to signal complete. But Selenium by default tries to wait for those (and a little bit more) on page loads via the driver.get() and element.click() methods. They are already blocking, they wait for the page to fully load and those should be working ok.
Problem, obviously, are redirects via AJAX requests and running scripts - those can't be caught by Selenium, it doesn't wait for them to finish. Also, you can't reliably catch them via readyState - it waits for a bit, which can be useful, but it will signal complete long before all the AJAX content is downloaded.
There is no general solution that would work everywhere and for everyone, that's why it's hard and everyone uses something a little bit different.
The general rule is to rely on WebDriver to do his part, then use implicit waits, then use explicit waits for elements you want to assert on the page, but there's a lot more techniques that can be done. You should pick the one (or a combination of several of them) that works best in your case, on your tested page.
See my two answers regarding this for more information:
How I can check whether page is loaded completely or not in web driver
Selenium Webdriver : Wait for complex page with javascript to load
Try this code:
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
The above code will wait up to 10 seconds for page loading. If the page loading exceeds the time it will throw the TimeoutException. You catch the exception and do your needs. I am not sure whether it quits the page loading after the exception thrown. i didn't try this code yet. Want to just try it.
This is an implicit wait. If you set this once it will have the scope until the Web Driver instance destroy.
See the documentation for WebDriver.Timeouts for more info.
This is a working Java version of the example you gave :
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}
Example For c#:
public static void WaitForLoad(IWebDriver driver, int timeoutSec = 15)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}
Example for PHP:
final public function waitUntilDomReadyState(RemoteWebDriver $webDriver): void
{
$webDriver->wait()->until(function () {
return $webDriver->executeScript('return document.readyState') === 'complete';
});
}
Here's my attempt at a completely generic solution, in Python:
First, a generic "wait" function (use a WebDriverWait if you like, I find them ugly):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
Next, the solution relies on the fact that selenium records an (internal) id-number for all elements on a page, including the top-level <html> element. When a page refreshes or loads, it gets a new html element with a new ID.
So, assuming you want to click on a link with text "my link" for example:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
For more Pythonic, reusable, generic helper, you can make a context manager:
from contextlib import contextmanager
#contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
And then you can use it on pretty much any selenium interaction:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
I reckon that's bulletproof! What do you think?
More info in a blog post about it here.
I had a similar problem. I needed to wait until my document was ready but also until all Ajax calls had finished. The second condition proved to be difficult to detect. In the end I checked for active Ajax calls and it worked.
Javascript:
return (document.readyState == 'complete' && jQuery.active == 0)
Full C# method:
private void WaitUntilDocumentIsReady(TimeSpan timeout)
{
var javaScriptExecutor = WebDriver as IJavaScriptExecutor;
var wait = new WebDriverWait(WebDriver, timeout);
// Check if document is ready
Func<IWebDriver, bool> readyCondition = webDriver => javaScriptExecutor
.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
wait.Until(readyCondition);
}
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
For C# NUnit, you need to convert WebDriver to JSExecuter and then execute the script to check if document.ready state is complete or not. Check below code for reference:
public static void WaitForLoad(IWebDriver driver)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
int timeoutSec = 15;
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}
This will wait until the condition is satisfied or timeout.
For initial page load I have noticed that "Maximizing" the browser window practically waits until page load is completed (including sources)
Replace:
AppDriver.Navigate().GoToUrl(url);
With:
public void OpenURL(IWebDriver AppDriver, string Url)
{
try
{
AppDriver.Navigate().GoToUrl(Url);
AppDriver.Manage().Window.Maximize();
AppDriver.SwitchTo().ActiveElement();
}
catch (Exception e)
{
Console.WriteLine("ERR: {0}; {1}", e.TargetSite, e.Message);
throw;
}
}
than use:
OpenURL(myDriver, myUrl);
This will load the page, wait until completed, maximize and focus on it. I don't know why its like this but it works.
If you want to wait for page load after click on next or any other page navigation trigger other then "Navigate()", Ben Dyer's answer (in this thread) will do the work.
In Nodejs you can get it via promises...
If you write this code, you can be sure that the page is fully loaded when you get to the then...
driver.get('www.sidanmor.com').then(()=> {
// here the page is fully loaded!!!
// do your stuff...
}).catch(console.log.bind(console));
If you write this code, you will navigate, and selenium will wait 3 seconds...
driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...
From Selenium documentation:
this.get( url ) → Thenable
Schedules a command to navigate to the given URL.
Returns a promise that will be resolved when the document has finished loading.
Selenium Documentation (Nodejs)
Have a look at tapestry web-framework. You can download source code there.
The idea is to signalize that page is ready by html attribute of body. You can use this idea ignore complicated sue cases.
<html>
<head>
</head>
<body data-page-initialized="false">
<p>Write you page here</p>
<script>
$(document).ready(function () {
$(document.body).attr('data-page-initialized', 'true');
});
</script>
</body>
</html>
And then create extension of Selenium webdriver (according to tapestry framework)
public static void WaitForPageToLoad(this IWebDriver driver, int timeout = 15000)
{
//wait a bit for the page to start loading
Thread.Sleep(100);
//// In a limited number of cases, a "page" is an container error page or raw HTML content
// that does not include the body element and data-page-initialized element. In those cases,
// there will never be page initialization in the Tapestry sense and we return immediately.
if (!driver.ElementIsDisplayed("/html/body[#data-page-initialized]"))
{
return;
}
Stopwatch stopwatch = Stopwatch.StartNew();
int sleepTime = 20;
while(true)
{
if (driver.ElementIsDisplayed("/html/body[#data-page-initialized='true']"))
{
return;
}
if (stopwatch.ElapsedMilliseconds > 30000)
{
throw new Exception("Page did not finish initializing after 30 seconds.");
}
Thread.Sleep(sleepTime);
sleepTime *= 2; // geometric row of sleep time
}
}
Use extension ElementIsDisplayed written by Alister Scott.
public static bool ElementIsDisplayed(this IWebDriver driver, string xpath)
{
try
{
return driver.FindElement(By.XPath(xpath)).Displayed;
}
catch(NoSuchElementException)
{
return false;
}
}
And finally create test:
driver.Url = this.GetAbsoluteUrl("/Account/Login");
driver.WaitForPageToLoad();
Ben Dryer's answer didn't compile on my machine ("The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").
Working Java 8 version:
Predicate<WebDriver> pageLoaded = wd -> ((JavascriptExecutor) wd).executeScript(
"return document.readyState").equals("complete");
new FluentWait<WebDriver>(driver).until(pageLoaded);
Java 7 version:
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
new FluentWait<WebDriver>(driver).until(pageLoaded);
I tried this code and it works for me. I call this function every time I move to another page
public static void waitForPageToBeReady()
{
JavascriptExecutor js = (JavascriptExecutor)driver;
//This loop will rotate for 100 times to check If page Is ready after every 1 second.
//You can replace your if you wants to Increase or decrease wait time.
for (int i=0; i<400; i++)
{
try
{
Thread.sleep(1000);
}catch (InterruptedException e) {}
//To check page ready state.
if (js.executeScript("return document.readyState").toString().equals("complete"))
{
break;
}
}
}
The wait for the document.ready event is not the entire fix to this problem, because this code is still in a race condition: Sometimes this code is fired before the click event is processed so this directly returns, since the browser hasn't started loading the new page yet.
After some searching I found a post on Obay the testing goat, which has a solution for this problem. The c# code for that solution is something like this:
IWebElement page = null;
...
public void WaitForPageLoad()
{
if (page != null)
{
var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
}
var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
page = driver.FindElement(By.TagName("html"));
}
`
I fire this method directly after the driver.navigate.gotourl, so that it gets a reference of the page as soon as possible. Have fun with it!
normaly when selenium open a new page from a click or submit or get methods, it will wait untell the page is loaded but the probleme is when the page have a xhr call (ajax) he will never wait of the xhr to be loaded, so creating a new methode to monitor a xhr and wait for them it will be the good.
public boolean waitForJSandJQueryToLoad() {
WebDriverWait wait = new WebDriverWait(webDriver, 30);
// wait for jQuery to load
ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
try {
Long r = (Long)((JavascriptExecutor)driver).executeScript("return $.active");
return r == 0;
} catch (Exception e) {
LOG.info("no jquery present");
return true;
}
}
};
// wait for Javascript to load
ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState")
.toString().equals("complete");
}
};
return wait.until(jQueryLoad) && wait.until(jsLoad);
}
if $.active == 0 so the is no active xhrs call (that work only with jQuery).
for javascript ajax call you have to create a variable in your project and simulate it.
You can write some logic to handle this. I have write a method that will return the WebElement and this method will be called three times or you can increase the time and add a null check for WebElement Here is an example
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.crowdanalytix.com/#home");
WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
int i = 1;
while (webElement == null && i < 4) {
webElement = getWebElement(driver, "homessssssssssss");
System.out.println("calling");
i++;
}
System.out.println(webElement.getTagName());
System.out.println("End");
driver.close();
}
public static WebElement getWebElement(WebDriver driver, String id) {
WebElement myDynamicElement = null;
try {
myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By
.id(id)));
return myDynamicElement;
} catch (TimeoutException ex) {
return null;
}
}
I executed a javascript code to check if the document is ready. Saved me a lot of time debugging selenium tests for sites that has client side rendering.
public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
Thread.sleep(100)
def ready = isDOMReady(driver);
if (ready) {
break;
}
}
}
public static boolean isDOMReady(WebDriver driver){
return driver.executeScript("return document.readyState");
}
public boolean waitForElement(String zoneName, String element, int index, int timeout) {
WebDriverWait wait = new WebDriverWait(appiumDriver, timeout/1000);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element)));
return true;
}
Like Rubanov wrote for C#, i write it for Java, and it is:
public void waitForPageLoaded() {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return (((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete")&&((Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")));
}
};
try {
Thread.sleep(100);
WebDriverWait waitForLoad = new WebDriverWait(driver, 30);
waitForLoad.until(expectation);
} catch (Throwable error) {
Assert.fail("Timeout waiting for Page Load Request to complete.");
}
}
In Java it will like below :-
private static boolean isloadComplete(WebDriver driver)
{
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
|| ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
The following code should probably work:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));
If you have a slow page or network connection, chances are that none of the above will work. I have tried them all and the only thing that worked for me is to wait for the last visible element on that page. Take for example the Bing webpage. They have placed a CAMERA icon (search by image button) next to the main search button that is visible only after the complete page has loaded. If everyone did that, then all we have to do is use an explicit wait like in the examples above.
public void waitForPageToLoad()
{
(new WebDriverWait(driver, DEFAULT_WAIT_TIME)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return (((org.openqa.selenium.JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"));
}
});//Here DEFAULT_WAIT_TIME is a integer correspond to wait time in seconds
Here's something similar, in Ruby:
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { #driver.execute_script('return document.readyState').eql?('complete') }
You can have the thread sleep till the page is reloaded. This is not the best solution, because you need to have an estimate of how long does the page take to load.
driver.get(homeUrl);
Thread.sleep(5000);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(userName);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(passWord);
driver.findElement(By.xpath("Your_Xpath_here")).click();
I Checked page load complete, work in Selenium 3.14.0
public static void UntilPageLoadComplete(IWebDriver driver, long timeoutInSeconds)
{
Until(driver, (d) =>
{
Boolean isPageLoaded = (Boolean)((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete");
if (!isPageLoaded) Console.WriteLine("Document is loading");
return isPageLoaded;
}, timeoutInSeconds);
}
public static void Until(IWebDriver driver, Func<IWebDriver, Boolean> waitCondition, long timeoutInSeconds)
{
WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
webDriverWait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
try
{
webDriverWait.Until(waitCondition);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
For the people who need to wait for a specific element to show up. (used c#)
public static void WaitForElement(IWebDriver driver, By element)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
wait.Until(ExpectedConditions.ElementIsVisible(element));
}
Then if you want to wait for example if an class="error-message" exists in the DOM you simply do:
WaitForElement(driver, By.ClassName("error-message"));
For id, it will then be
WaitForElement(driver, By.Id("yourid"));
Are you using Angular? If you are it is possible that the webdriver doesn't recognize that the async calls have finished.
I recommend looking at Paul Hammants ngWebDriver.
The method waitForAngularRequestsToFinish() could come in handy.

How to deal with ModalDialog using selenium webdriver?

I am unable to switch to Modal Dialog of given example
http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/showModalDialog2.htm
I don't know how to get element on modal Dialog
Use
following methods to switch to modelframe
driver.switchTo().frame("ModelFrameTitle");
or
driver.switchTo().activeElement()
Hope this will work
What you are using is not a model dialog, it is a separate window.
Use this code:
private static Object firstHandle;
private static Object lastHandle;
public static void switchToWindowsPopup() {
Set<String> handles = DriverManager.getCurrent().getWindowHandles();
Iterator<String> itr = handles.iterator();
firstHandle = itr.next();
lastHandle = firstHandle;
while (itr.hasNext()) {
lastHandle = itr.next();
}
DriverManager.getCurrent().switchTo().window(lastHandle.toString());
}
public static void switchToMainWindow() {
DriverManager.getCurrent().switchTo().window(firstHandle.toString());
Try the below code. It is working in IE but not in FF22. If Modal dialog found is printed in Console, then Modal dialog is identified and switched.
public class ModalDialog {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
WebDriver driver = new InternetExplorerDriver();
//WebDriver driver = new FirefoxDriver();
driver.get("http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/showModalDialog2.htm");
String parent = driver.getWindowHandle();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement push_to_create = wait.until(ExpectedConditions
.elementToBeClickable(By
.cssSelector("input[value='Push To Create']")));
push_to_create.click();
waitForWindow(driver);
switchToModalDialog(driver, parent);
}
public static void waitForWindow(WebDriver driver)
throws InterruptedException {
//wait until number of window handles become 2 or until 6 seconds are completed.
int timecount = 1;
do {
driver.getWindowHandles();
Thread.sleep(200);
timecount++;
if (timecount > 30) {
break;
}
} while (driver.getWindowHandles().size() != 2);
}
public static void switchToModalDialog(WebDriver driver, String parent) {
//Switch to Modal dialog
if (driver.getWindowHandles().size() == 2) {
for (String window : driver.getWindowHandles()) {
if (!window.equals(parent)) {
driver.switchTo().window(window);
System.out.println("Modal dialog found");
break;
}
}
}
}
}
Solution in R (RSelenium):
I had a popup dialog (which is dynamically generated) and hence undetectable in the original page source code
Here are methods which worked for me:
Method 1: Simulating Pressing keys for Tabs and switching to that modal dialog
My current key is focussed on a dropdown button behind the modal dialog box
remDr$sendKeysToActiveElement(list(key = "tab"))
Sys.sleep(5)
remDr$sendKeysToActiveElement(list(key = "enter"))
Sys.sleep(15)
Method 2: Bring focus to the frame(or iframe) if you can locate it
date_filter_frame <- remDr$findElement(using = "tag name", 'iframe')
date_filter_frame$highlightElement()
Sys.sleep(5)
remDr$switchToFrame(date_filter_frame)
Sys.sleep(2)
Now you can search for elements in the frame. Remember to put adequate Sys.sleep in between commands for elements to load properly (just in case)
date_filter_element <- remDr$findElement(using = "xpath", paste0("//*[contains(text(), 'Week to Date')]"))
date_filter_element$highlightElement()
Try this code, include your object names & variable to work.
Set<String> windowids = driver.getWindowHandles();
Iterator<String> iter= windowids.iterator();
for (int i = 1; i < sh.getRows(); i++)
{
while(iter.hasNext())
{
System.out.println("Main Window ID :"+iter.next());
}
driver.findElement(By.id("lgnLogin_UserName")).clear();
driver.findElement(By.id("lgnLogin_UserName")).sendKeys(sh.getCell(0,
i).getContents());
driver.findElement(By.id("lgnLogin_Password")).clear();
driver.findElement(By.id("lgnLogin_Password")).sendKeys(sh.getCell(1,
i).getContents());
driver.findElement(By.id("lgnLogin_LoginButton")).click();
Thread.sleep(5000L);
windowids = driver.getWindowHandles();
iter= windowids.iterator();
String main_windowID=iter.next();
String tabbed_windowID=iter.next();
System.out.println("Main Window ID :"+main_windowID);
//switch over to pop-up window
Thread.sleep(1000);
driver.switchTo().window(tabbed_windowID);
System.out.println("Pop-up window Title : "+driver.getTitle());
I have tried it, it works for you.
String mainWinHander = webDriver.getWindowHandle();
// code for clicking button to open new window is ommited
//Now the window opened. So here reture the handle with size = 2
Set<String> handles = webDriver.getWindowHandles();
for(String handle : handles)
{
if(!mainWinHander.equals(handle))
{
// Here will block for ever. No exception and timeout!
WebDriver popup = webDriver.switchTo().window(handle);
// do something with popup
popup.close();
}
}
Assuming the expectation is just going to be two windows popping up (one of the parent and one for the popup) then just wait for two windows to come up, find the other window handle and switch to it.
WebElement link = // element that will showModalDialog()
// Click on the link, but don't wait for the document to finish
final JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript(
"var el=arguments[0]; setTimeout(function() { el.click(); }, 100);",
link);
// wait for there to be two windows and choose the one that is
// not the original window
final String parentWindowHandle = driver.getWindowHandle();
new WebDriverWait(driver, 60, 1000)
.until(new Function<WebDriver, Boolean>() {
#Override
public Boolean apply(final WebDriver driver) {
final String[] windowHandles =
driver.getWindowHandles().toArray(new String[0]);
if (windowHandles.length != 2) {
return false;
}
if (windowHandles[0].equals(parentWindowHandle)) {
driver.switchTo().window(windowHandles[1]);
} else {
driver.switchTo().window(windowHandles[0]);
}
return true;
}
});
Nope, Model window needs to be handle by javaScriptExecutor,Because majorly model window made up of window model,
This will works once model appeared then control take a place into model and click the expected element.
have to import javascriptexector
like below,
Javascriptexecutor js =(Javascriptexecutor).driver;
js.executescript(**<element to be clicked>**);
P.S. 1 adding my 2 cents even though the question is too old
public void PressEnterKey()
{
var simulator = new InputSimulator();
simulator.Keyboard.KeyPress(VirtualKeyCode.RETURN);
}
you can create a method like the above and call it where it is required.
P.S. 2 - you can change the keyboard inputs as well (like up arrow, down arrow, page down etc)