'waitForPageToLoad'/'waitForElementPresent' - how use in Selenium2? (C#) - c#

Guys, I have problem with waitForPageToLoad condtion. I'm using C# with Nunit, and I don't know exactly what I should use instead of 'waitForPageToLoad'/'waitForElementPresent'. Maybe someone knows how I can use 'waitForPageToLoad'/'waitForElementPresent' in Selenium 2?

I use FindElement() for something on the new page. Wrap in in a loop that will keep trying until the element is found, with a maximum wait.
// pseudocode WebElement wait_for_element(By locator)
while (!timeout) {
try {
return driver.FindElement(locator);
} catch (Exception) {
Thread.sleep(1000);
}
// check for timeout here
}
throw new NoSuchElementException("Timeout waiting for "+locator);

ISelenium selenium = new DefaultSelenium( "localhost", 4444, "*chrome", "
http://localhost/UrlOfAppToTest/" );
selenium.WaitForPageToLoad( "30000" );
Is that what you're looking for?

You could use a explicit wait method to wait for your action/page to load.
With that you can specify a condition to be met, and when it is met your test will continue.
See link for more details:
Selenium HQ, explicit wait

Related

How can I use Selenium 'Until' function without throwing an Exception?

I am trying to create a test script using selenium that might interact with an element but if the element is not there it will not. I need to add that the element might take some time to appear. The issue is that if I use FindElement I get an exception. If I use FindElements it take too long. So, I tried to used "until" function which work well to wait until the element to appear... but if it doesn't appear it throws an exception I want to avoid that.
I know I can use a try catch.But, is there any better way to do this?
I curently have this:
IWebElement button;
try{
string x = "search query";
button = this.WaitDriver.Until(d => d.FindElement(By.XPath(x)));
}catch{
button = null;
}
If you want to test for existence without a try-catch then you would have to use .FindElements(). It shouldn't take any longer than .FindElement() using the same wait but the wait will time out if the element doesn't exist... which is a pain. One way to get around this is to do something like the below. It's basically what you had with a few tweaks.
public bool ElementExists(By locator)
{
try
{
new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(locator));
return true;
}
catch (Exception e) when (e is NoSuchElementException || e is WebDriverTimeoutException)
{
return false;
}
}
I prefer checking for existence rather returning a null because then you have to check for null also. By putting this in a function, you can call it whenever and your tests stay cleaner. You would use it like
By locator = By.Id("someId");
if (ElementExists(locator))
{
IWebElement e = driver.FindElement(locator);
// do something with e
}

C# selenium Webdriver how to get the current timeout time

I want to create the equivalent of a wait for element present command with custom timeout time
public static void WaitForElementPresent(string Xpath, int WaitTime, int OriginalWaitTime)
{
try
{
SeleniumBrowser.driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(WaitTime));
SeleniumBrowser.driver.FindElements(By.XPath(Xpath));
SeleniumBrowser.driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(OriginalWaitTime));
}
catch (Exception)
{
throw new Exception("Could not find the" + Xpath + "Xpath after" + DefaultWaitTime + "second");
}
}
So far my code looks like this however instead of setting a hard coded integer at the end id rather get the previous timeout time registered as an integer mid test from some obscure function and call it so to reset the timeout to its previous time.
You should avoid those Implicit time outs as much as possible and stick to explicit waiting. Explicit waiting is not Thread.Sleep(time) but explicitly waiting for your element.
A huge lesson came in realizing how Implicit and Explicit waiting work. One thing to note is that C# will look for the Element immediately and when it is not found will crash with a "No Such Element" exception. If you mix implicit and explicit waiting together you will be stuck waiting until the Implicit wait time completes even if the element has been found. Not good and caused huge time issues for tests.
I would not recommend using XPath unless needed, however, you should use one of the following ways to wait. This is mostly handled with Selenium code already.
I personally extended Selenium to do the following call with set Page Objects
Expected Condition way:
public static void WaitForElement(this IWebElement element, IWebDriver
driver, int waitTime)
{
try{
var wait = new WebDriverWait(driver, timeSpan.FromSeconds(waitTime));
wait.Until(ExpectedConditions.ElementToBeClickable(element));
Logging.Information(elementText + " is clickable");
}
catch (NoSuchElementException)
{
throw new Exception("Could not find the" + Xpath + "Xpath after" + DefaultWaitTime + "second");
}
}
}
This would look like this with a mapped page object:
SaveButton.WaitForElement(driver);
I also extended selenium to use the same waiting for unmapped Page Objects.
You could do something similar with Extending the Driver class as well to match what you are currently doing.
public static void WaitForLocator(this IWebDriver driver, By by, int waitTime)
{
Logging.Action("Using locator: " + by + " to find element");
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime));
wait.Until(ExpectedConditions.ElementToBeClickable(by)); //There are several Expected conditions
Logging.Information("Found element with locator: " + by);
}
This would look like this with your current example
driver.WaitForLocator(By.XPath('your XPath');
This method will also allow you to use CSS selectors, Ids, etc by changing your By type.
The other way to explicitly wait for elements is using
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
var saveButton = wait.Until(x => driver.FindElements(By.XPath(Xpath));
Not sure you if meant to use driver.FindElements or driver.FindElement since the name of the method is WaitForElementPresent but you used driver.FindElements. Find elements returns a list of elements not just the element you were looking for.
Hope this helps.

Selenium with C# - Driver gets killed when object is not present on the page

We are using Selenium with C#. We have a driver script where we instantiate the driver and then we call a testscript (automated functional testcase flow). Everything works well when the object is present on the page. We are facing issue of driver getting killed when we try and verify that certain object is not present, below is the code
Driver Script Code
//driver = new RemoteWebDriver(new Uri(uri), capabilites,TimeSpan.FromSeconds(120));
Test Script Code
public class GraphNew
{
public Boolean testGraphNew(IWebDriver driver, Logger OneLogger)
{
try
{ //Navigate to a page
try
{
driver.FindElement(By.XPath("//a[contains(text(),'Add New Claim')]")).Click();
}
catch
{
OneLogger.Log("Element is not prsent")
}
}
}
catch(Exception e)
{
OneLogger.LogException(e);
return false;
}
}
The problem is when the object is not identified (as it is not present) in the inner try, rather than going to the inner catch block, the execution proceeds to outer catch and shows exception as -
{"The HTTP request to the remote WebDriver server for URL
http://localhost:4449/wd/hub/session/35c483a6-6871-425a-a936-aeebb0742fd2/element
timed out after 120 seconds."}
and driver gets killed.
Can anyone please suggest, if we are missing something or what should be the idle way to code so that once the object is not identified, driver does not get killed and execution continues for the remaining code.
You can do something like below ...
The code is in java but it is very similar/near to C#
You can check first whether your element is present or not in your HTML DOM to prevent from error/failer of script. like below:-
(I am replacing size to lenght in below code as lenght is using in C# to determine the size of array)
if (driver.findElements("YOUR LOCATOR").Length() != 0) {
driver.findElement(YOUR LOCATOR).click();
System.out.println("element exists");
}
else{
System.out.println("element is not exists");
}
You can also use isDisplayed() method of selenium, it will return boolean value. true if element exist on DOM.
Boolean result = driver.findElement(By.xpath("//a[contains(text(),'Add New Claim')]")).isDisplayed();
if(result==true)
{
System.out.println("element exists");
}else{
System.out.println("element is not exists");
}
Refer below link if you want to know more about isDisplayed() method
http://www.softwaretestinghelp.com/webdriver-commands-selenium-tutorial-14/
Hope it will help you :)

Selenium c# custom expected conditions for innerText

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.

How to override Selenium Webdriver FindElement and add a wait to it?

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();

Categories

Resources