the html
<span id="banner">Rolling in 10.00...</span>
my code
public void waitroller()
{
Console.WriteLine("waiting roller");
WebDriverWait wait = new WebDriverWait(PropertiesCollection.driver, TimeSpan.FromDays(2));
wait.Until<IWebElement>((d) =>
{
IWebElement element = PropertiesCollection.driver.FindElement(By.Id("banner"));
if (element.Text == "Rolling in 20.00...")
{
return element;
}
return null;
});
}
OR
public void waitroller()
{
new WebDriverWait(PropertiesCollection.driver, TimeSpan.FromMinutes(1.5)).Until(ExpectedConditions.TextToBePresentInElementLocated(By.Id("banner") , "Rolling in 20.00..."));
}
I'm stuck with this innertext because the innertext in the html is always changing and i want to make a webdriverwait that waits until the innertext in the span banner is "Rolling in 20.00" . Is there any way to make custom expected conditions because I am not understand custom expected condition.
what i need is something like this
new WebDriverWait(PropertiesCollection.driver, TimeSpan.FromMinutes(1.5)).Until(ExpectedConditions.TextToBePresentInElement(PropertiesCollection.driver.FindElement(By.Id("banner"), "Rolling in 20.00...");
but this is not work because i think the id="banner" is innerText
there is one way that work but can't work for long because i think it is the wrong way of doing it . i loop the element banner many times and check if the innerText is equals to "Rolling in 20.00..." but have error also
public void waitroller()
{
Console.WriteLine("waiting roller");
WebDriverWait wait = new WebDriverWait(PropertiesCollection.driver, TimeSpan.FromDays(2));
IWebElement bannerElement = PropertiesCollection.driver.FindElement(By.Id("banner"));
wait.Until((d) =>{ return bannerElement.Text.Contains("Rolling in 20.00"); });
}
I don't know what you mean by "innertext", but with Selenium's WebDriverWait you can wait for whatever you want. You don't have to use the ExpectedConditions, they're only for programmers' comfort.
Example:
new WebDriverWait(...).Until(driver => driver.FindElement(...).Text.Equals(...));
On the other hand, your problem might be a completely different one. Is your "roller" a countdown where the text changes very fast? In this case you might never reach the expected condition. I think Selenium checks the expected conditions every 500 milliseconds, so it doesn't even notice when "Rolling in 20.00" is displayed for just let's say 50 millisecods and then has already changed to "Rolling in 19.95" when Selenium checks for the next time.
Related
I have setup a class with properties get value from WebDriver.FindElements().
public IList<IWebElement> ListObjectElements
{
get
{
var container = WebDriver.FindElement(By.Id("objects"));
return container.FindElements(By.XPath("//*[contains(#id, 'id_')]"));
}
}
I also implemented test case to test Add New function.
All steps ran success. When I tried to get the return of new list after Add New, it missed 1 item.
I set a break point to watch value. The property ListObjectElements has 10 items, but the return newList only has 9.
var newList = clientpage.ListObjectElements;
return newList;
If I add a Thread.Sleep(), the return newList has 10 items same as the property ListObjectElements.
How could I get the exactly results without using Thread.Sleep()?
Thanks in advance for you help.
It sounds like the site you're automating adds the elements representing the objects dynamically to the DOM, and that your code is then losing the race condition that you execute FindElements before the elements are actually added to the DOM. You'll need to implement some sort of wait in your code. You might be able to leverage the WebDriverWait construct, the .NET implementation of which is available in the WebDriver.Support assembly. The construct could be used in a manner similar to the following:
// Assumes 'driver' is a valid IWebDriver instance.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until<bool>((d) =>
{
return clientPage.ListObjectElements.Count > 9;
});
Putting this in a more concrete context in your test case would look something like this, depending on your architecture and desires:
// Assume that the element you click on to add a new element
// is stored in the variable 'element', and your IWebDriver
// variable is 'driver'.
int originalCount = clientPage.ListObjectElements.Count;
element.Click();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
wait.Until<bool>((d) =>
{
return clientPage.ListObjectElements.Count > originalCount;
});
return clientPage.ListObjectElements;
I'm using Selenium Webdriver with C# and I'm wondering if there's a way to override the FindElement method? What I'd like to do - if possible - is to add an extra parameter and code to the method that would force it to wait for the element to be visible before proceeding.
For example, it would then be something like this:
Driver.FindElement(By.Id("orion.dialog.box.ok"), 60).Click();
This would wait up to 60 seconds for the element to appear and be available to click.
Any ideas how to do this?
Thanks,
John
You could use ImplicitWait for this. You can create a new user defined function to accept the By object and the timeout seconds and have the function return the IWebElement, something like below:
IWebElement elem = MyOwnGetElement(By.id("test"),60);
The above function might have the below code, where time_out_sec is the function parameter.
WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(time_out_sec));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));
I would suggest you add it as an extension method. Pseudo code:
public static IWebElement WaitForAndFindElement(this IWebDriver driver, By by)
{
// do a wait
// something like...
WebDriverWait wait = new WebDriverWait(TimeSpan.FromSeconds(60)); // hard code it here if you want to avoid each calling method passing in a value
return wait.Until(webDriver =>
{
if (webDriver.FindElement(by).Displayed)
{
return webDriver.FindElement(by);
}
return null; // returning null with force the wait class to iterate around again.
});
}
Just to state, an implicit wait is going to be part one of your solution. It will cause Selenium to wait up to 60 seconds for an element to be present in DOM but being visible is something entirely different.
.Displayed will handle that, and it must be handled within a WebDriverWait.
I am coding with Selenium for 6+ months and I had the same problem as yours. I have created this extension method and it works for me every time.
What the code does is:
During 20 seconds, it checks each 500ms, whether or not the element is present on the page. If after 20 seconds, it's not found, it will throw an exception.
This will help you make a dynamic wait.
public static class SeleniumExtensionMethods {
public static WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
public static void SafeClick(this IWebElement webElement) {
try {
wait.Until(ExpectedConditions.ElementToBeClickable(webElement)).Click();
} catch (TargetInvocationException ex) {
Console.WriteLine(ex.InnerException);
}
}
and then use it like this:
IWebElement x = driver.FindElement(By.Id("username"));
x.SafeClick();
I am looking for a way to check that the page was loaded using Selenium. So basically does the url point to a correct address (in chrome the browser shows something like this) :
I am using the following code:
var driver = new FirefoxDriver();
driver.Url = "SomeUrl";
Currently I am comparing the title to "SomeUrl is not available" and if it matches I mark that the page has failed to load.
But is there a better way?
I would suggest, if you know what control ID/or link or/Class is going to appear on your page. Then wait for that element to appear on screen for a defined period of time.
I that element appears then your next line of code will be executed
Here is the simple version of m method. You can make it more dynamic based on your need.
/// <summary>
/// WaitForElementOnPage() method waits a passed number of seconds for the existence
/// of a passed IWebElement object. If the object is found the method return an IWebElement of the object
/// If the object is not found in the passed number of seconds, the method returns a null IWebElement
/// </summary>
public IWebElement WaitForElementOnPage(string controlID, int waitTime)
{
IWebElement element = null;
IWebElement elementFound = null;
try
{
WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(waitTime));
Thread.Sleep(3000);
elementFound = wait.Until<IWebElement>((d) =>
{
element = d.FindElement(By.Id(controlID));
break;
return element;
});
}
catch (Exception ex)
{
Log.Error(ex);
elementFound = null;
}
return elementFound ;
}
I personally try to locate body or frameset element on the page.
Based on my experience while using selenium with chromedriver, page content sometimes doesn't show up and I need to run webdriver.refresh() 1-2 times. It doesn't happen all the time, but I run big amount of chrome instances on one machine and this approach was the most effective for now to avoid this.
So I try to locate body or frameset elements and reload few times before I give up.
The advantage of this solution is also the fact that it will also work in case Chrome changes its messages in the future. It will also work with other browsers.
I am really sorry if this question has already been asked/answered. but I could not find it.
Please excuse my ignorance as I am new to WebDriver.
When the page is initially loads, it displays a LOADING DIV untill all the data is loaded. How can I wait until this div is hidden before I proceed with other actions on page elements?
I am trying to know as follows:
public static void waitForPageLoad(string ID, IWebDriver driver)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id(ID));
});
}
I pass the Id of SOME OTHER ELEMENT to this function which I will use when the LOADING DIV disappears. It returns the wrong result as the element by ID is actually present/loaded but is behind the grey DIV that shows "Loading... Please wait" message. So this does not work. I would like to know when that LOADING div disappears.
Any help is greatly appreciated.
By waiting on a bool value instead of IWebElement, the .NET WebDriverWait class will wait until a value of true is returned. Given that, how about trying something like the following:
public static void WaitForElementToNotExist(string ID, IWebDriver driver)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until<bool>((d) =>
{
try
{
// If the find succeeds, the element exists, and
// we want the element to *not* exist, so we want
// to return true when the find throws an exception.
IWebElement element = d.FindElement(By.Id(ID));
return false;
}
catch (NoSuchElementException)
{
return true;
}
});
}
Note that this is the appropriate pattern if the element you're looking for is actually removed from the DOM. If, on the other hand, the "waiting" element is always present in the DOM, but just made visible/invisible as required by the JavaScript framework your app is using, then the code is a little simpler, and looks something like this:
public static void WaitForElementInvisible(string ID, IWebDriver driver)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until<bool>((d) =>
{
try
{
IWebElement element = d.FindElement(By.Id(ID));
return !element.Displayed;
}
catch (NoSuchElementException)
{
// If the find fails, the element exists, and
// by definition, cannot then be visible.
return true;
}
});
}
I am using selenium 2 and a chrome driver and cannot seem to get the explicit wait to work no matter what I do. I am trying to click on an element which generates some data dynamically via ajax (no reloads) and then search for an element when it becomes present on the page.
This is my code
leagueNameItem.Click();
IList<IWebElement> outerTables_forEachLeague = new List<IWebElement>();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
outerTables_forEachLeague = wait.Until<IList<IWebElement>>((d) =>
{
return d.FindElements(By.ClassName("boxVerde"));
});
The element is not found (and it is on the page for sure). The wait function does not actually 'wait' for the 10 seconds as specified ut just returns nothing. Any ideas pls?
The problem is that FindElements returns immediately, and returns a valid empty list object if the elements aren't found. You have two choices. You can use a single FindElement in your wait, which throws an exception if the element doesn't exist. The WebDriverWait object will catch that exception and retry until the element can be found.
However, since you want to return a list from your wait, you'll need to be a little more clever, which leads to your second option. Change your wait to look something like this:
leagueNameItem.Click();
IList<IWebElement> outerTables_forEachLeague = new List<IWebElement>();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
outerTables_forEachLeague = wait.Until<IList<IWebElement>>((d) =>
{
var elements = d.FindElements(By.ClassName("boxVerde"));
if (elements.Count == 0)
{
return null;
}
return elements;
});