OpenQA.Selenium.NoSuchElementException was unhandled by user code in c# selenium - c#

I want to wait my selenium programe for max 30 seconds (GlobalVar.timetomaximumwait) with explicit wait.But when ever its unable to locate the element its pausing at wait.until(...) line and displaying OpenQA.Selenium.NoSuchElementException was unhandled by user code
If i press continue or press F10 its trying again to find the element and continuing the same for my defined time spam.
Not able to understand why the programme paused and the error message is coming in between.
I am using VS2010, c#, selenium 2.45,Ie 9
Any kind of help is much appreciated .
public string SetValueInTextBox(string InputData, string xPathVal)
{
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(GlobalVar.timetomaximumwait));
wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.XPath(xPathVal));
});
IWebElement TargetElement = driver.FindElement(By.XPath(xPathVal));
// IWebElement TargetElement = driver.FindElement(By.XPath(xPathVal));
elementHighlight(TargetElement);
TargetElement.Clear();
TargetElement.SendKeys(InputData);
//driver.FindElement(By.XPath(xPathVal)).SendKeys(InputData);
return "Pass";
}
catch (Exception e)
{
return "Fail";
}
finally
{
// string SSName = "temp.jpg";
TakeScreenshot("SetValueInTextBox");
}
}

The problem lies here:
wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.XPath(xPathVal));
});
You need to handle the exception that gets thrown when the element is not found.
wait.Until<IWebElement>((d) =>
{
try
{
return d.FindElement(By.XPath(xPathVal));
}
catch(NoSuchElementException e)
{
return null;
}
});
I would suggest adding in some logging into the catch block, so you know every time the driver fails to find the element.

Related

Using WebDriverWait to wait if value changes after some time

I'm using WebDriverWait to get the value of a WebElement after some time, but if it doesn't change, I don't want it to fail, just get the current value and keep going with the execution.
I'm running a process in a Web that has a "process completed" label that I use to check if it finished. On the same screen there is an "elapsed time" for the process that I need to read to report how much time it took to run the process.
The issue is that there is a backend process running even after the "process completed" label appeared, and the time gets updated. I can't know how much time this "backend update" will take, and I don't know if in happy runs it can appear before mentioned label, for the moment, from my tests it goes from 10 to 40 seconds (60 to be sure).
We have a Waits class for this kind of stuff, but we didn't have a method for this text change validation, so I came up with this:
private static WebDriverWait _customWait(int value) => new WebDriverWait(
clock,
Driver.Instance,
TimeSpan.FromSeconds(value),
TimeSpan.FromMilliseconds(Settings.Timeouts.SleepIntervalInMillis));
public static void WaitForTextElementToChange(Func<IWebDriver, IWebElement> elementFinder, IWebDriver driver, int time)
{
string oldValue = elementFinder.Invoke(driver).Read();
_customWait(time).Until(drv =>
{
try
{
return !elementFinder.Invoke(driver).Read().Contains(oldValue);
}
catch (NotFoundException)
{
return true;
}
catch (StaleElementReferenceException)
{
return true;
}
});
}
This works. And I remark it because I don't fully understand yet the syntax and logic behind that Until method, I know that it gives a WebDriverTimeoutException and I left it that way to be an additional method for the framework.
So, if the value changes it gets out and keeps running lovely, but in this particular case, if it doesn't change, I don't need it to throw that exception so I called it within a try/catch.
Waits.WaitForProcessToFinish(drv => processCompleteLabel); //<- context code
try
{
//If value changes before 60 secs everything is fine
Waits.WaitForTextElementToChange(drv => timeElement, someDriverObject, 60);
//60 is a hardcoded int value just for testing
}
catch (WebDriverTimeoutException)
{
//But if it doesn't change just do nothing
}
string timeElapsed = timeElement.Read(); //<- context code
My question is, would it be ok to leave it that way?
What would you do instead?
Based on what I see in the source I don't think there is a way around this with how Until works.
The Until method executes a method passed to it in a loop until either a bool or object is returned or the timeout occurs.
public virtual TResult Until<TResult>(Func<T, TResult> condition)
{
if (condition == null)
{
throw new ArgumentNullException("condition", "condition cannot be null");
}
var resultType = typeof(TResult);
if ((resultType.IsValueType && resultType != typeof(bool)) || !typeof(object).IsAssignableFrom(resultType))
{
throw new ArgumentException("Can only wait on an object or boolean response, tried to use type: " + resultType.ToString(), "condition");
}
Exception lastException = null;
var endTime = this.clock.LaterBy(this.timeout);
while (true)
{
try
{
var result = condition(this.input);
if (resultType == typeof(bool))
{
var boolResult = result as bool?;
if (boolResult.HasValue && boolResult.Value)
{
return result;
}
}
else
{
if (result != null)
{
return result;
}
}
}
catch (Exception ex)
{
if (!this.IsIgnoredException(ex))
{
throw;
}
lastException = ex;
}
// Check the timeout after evaluating the function to ensure conditions
// with a zero timeout can succeed.
if (!this.clock.IsNowBefore(endTime))
{
string timeoutMessage = string.Format(CultureInfo.InvariantCulture, "Timed out after {0} seconds", this.timeout.TotalSeconds);
if (!string.IsNullOrEmpty(this.message))
{
timeoutMessage += ": " + this.message;
}
this.ThrowTimeoutException(timeoutMessage, lastException);
}
Thread.Sleep(this.sleepInterval);
}
}
What you're doing works, But I would suggest having your own timeout loop without using Wait.Until() since it's core function is to throw an exception if there is an issue.

IF ELSE condition with Selenium (C#) when an element is not present

I am using Selenium with C# on NUNit framework and I am trying to put an Conditional statement looking for an element (banner to be specific). I already have a piece of code to click that banner and go forward in my test flow.
Now, I am after a condition that IF that banner is not present THEN user should have to perform additional steps to set the banner and proceed.
So, I want my IF to check not present condition to execute that piece of code otherwise will skip it.
var banner = FindElement(By.Id("bannerId"));
IF ( checking if above element not present)
{ execute set of steps to set the banner }
ELSE
{
WebDriverWait wait2 = new WebDriverWait(driver, TimeSpan.FromSeconds(40));
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("bannerId")));
banner.Click();
Thread.Sleep(2000);
}
I hope I was able to explain my problem and will appreciate any help.
try this code :
public bool IsElementVisible(IWebElement element)
{
return element.Displayed && element.Enabled;
}
IF(IsElementVisible(banner) == false)
{ execute set of steps to set the banner }
You could use the try and catch,
try
{
var banner = FindElement(By.Id("bannerId"));
IF ( checking if above element not present)
{ execute set of steps to set the banner }
ELSE
{
WebDriverWait wait2 = new WebDriverWait(driver, TimeSpan.FromSeconds(40));
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("bannerId")));
banner.Click();
Thread.Sleep(2000);
}
}
catch(Exception ex)
{
//check what will be the return message from ex.Message
//and from here you could add a logic what would be your next step.
}
I have validated your code. I can see some mistakes. Please find the suggestions below:
The line of your code :
var banner = FindElement(By.Id("bannerId")); will throw a "NoSuchElementException" and the if statement on the next line will not be executed. Hence, the simplest option will be to use try and catch where you are finding the element and skip the if block.
Your code snippet can be:
try
{
var banner = FindElement(By.Id("bannerId"));
WebDriverWait wait2 = new WebDriverWait(driver,
TimeSpan.FromSeconds(40));
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("bannerId")));
banner.Click();
Thread.Sleep(2000);
}
catch (NoSuchElementException ex)
{
//Give the appropriate message
}
If you want to follow the approach you have mentioned in your code then please try the code snippet below. You will have to store the elements in the List and check the list size. If the size of the list is not zero, then you can click the banner else display the appropriate message.
Second code snippet:
IList<IWebElement> banner = driver.FindElements(By.Id("bannerId"));
IF ( list size is zero)
{ execute set of steps to set the banner }
ELSE
{
WebDriverWait wait2 = new WebDriverWait(driver,
TimeSpan.FromSeconds(40));
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("bannerId")));
//Click on the first element of the list
}
Use FindElements instead, it will prevent the exception and you can check the size of the returned collection to check if the banner exists
IList<IWebElement> elements = driver.FindElements(By.Id("bannerId")).ToList();
if(elements.Count == 0)
{
do something
}
else
{
//do something with the banner at elements[0]
wait2.Until(ExpectedConditions.ElementToBeClickable(elements[0])).Click();
}

Exception: "Timed Out After xx seconds" on wait.until Selenium WebDriver C#

I'm trying to figure out how it's possible to wait for a condition in order to login into a web page with Selenium Driver. However it is not as straightforward as it may seem. I'm working around with Thread.Sleep(3000); but I'm sure there should be a better solution. So, my code works as follows:
Load page with firefox driver.
Execute a javascript snnipet to change language (I need to wait for this in order to login).
IJavaScriptExecutor executor = (IJavaScriptExecutor)firefox;
executor.ExecuteScript("arguments[0].click();", idioma_español);
Above instruction leads to a page reload.
Next instruction is intented to wait for page to be reloaded
WebDriverWait wait = new WebDriverWait(newDriver,TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.TextToBePresentInElementValue(element,textToAppear));
Continue to login.
However, when I run the code, it throws the following exception:
Looking closer into de output, I found this:
I tried with different expected conditions such as: TextToBePresentInElement,ElementExists; but it throws the same exception.
I also tried with ExecuteAsyncScript("arguments[0].click();", idioma_español); method, but it throws "Document was unloaded " exception.
It looks like the text element has been replaced, so the element was stale. I think you can solve it by fetch the new element every time. See code below:
public bool WaitForTextToAppear(IWebDriver driver, By elementLocator, string textToAppear, int timeoutInSec=10)
{
IWait<IWebDriver> wait = new DefaultWait<IWebDriver>(driver);
wait.Timeout = TimeSpan.FromSeconds(timeoutInSec);
wait.PollingInterval = TimeSpan.FromMilliseconds(300);
try
{
wait.Until(d => IsTextPresentedIn(d, elementLocator, textToAppear));
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
return false;
}
}
private bool IsTextPresentedIn(IWebDriver driver, By elementLocator, string textToAppear)
{
try
{
var elements = driver.FindElements(elementLocator);
if (elements.Count>0 && elements[0].Text.Equals(textToAppear, StringComparison.OrdinalIgnoreCase))
return true;
}
catch
{
return false;
}
return false;
}
// using the web driver extension.
bool textAppeared = WaitForTextToAppear(driver, By.CssSelector("selector-of-the-text-element"), "HERE IS THE EXPECTED TEXT");

How to refresh page when element isn't displayed

I am trying to refresh the page when an element I am trying to find isnt displayed I have written this code but instead of just skipping the if statement the test just fails
while (true)
{
if (Driver.Instance.FindElement(By.LinkText("Leather Utility Vest")).Displayed)
{
var clickButton = Driver.Instance.FindElement(By.LinkText("Leather Utility Vest"));
clickButton.Click();
break;
}
Driver.Instance.Navigate().Refresh();
}
I just used this code instead
while (true)
{
try
{
var clickButton = Driver.Instance.FindElement(By.LinkText("Leather Utility Vest"));
clickButton.Click();
break;
}
catch(Exception)
{
Driver.Instance.Navigate().Refresh();
}
}
This catches the error that the element wasn't found which was why the test was failing and runs the catch block which refreshes the webpage

.NET Selenium NoSuchElementException; WebDriverWait.Until() doesn't work

We have a .NET 4.5, MVC, C# project. We're using Selenium for UI tests, and the tests keep intermittently failing on lines that we have wait.Until(). One such example is:
NoSuchElementException was unhandled by user code
An exception of type 'OpenQA.Selenium.NoSuchElementException' occurred in WebDriver.dll but was not handled in user code
Additional information: Unable to locate element: {"method":"css selector","selector":"#assessment-472 .status-PushedToSEAS"}
It's thrown right here:
Thread.Sleep(600);
wait.Until(drv => drv.FindElement(By.CssSelector("#" + assessmentQueueId + " .status-PushedToSEAS")));
I can see that the browser opens, I see it get to that point, and I can inspect element to see that the element exists. Its id is exactly correct.
We have this problem A LOT and so far the solution has been to throw Thread.Sleep(600) (or some similar time) in front of it. The whole point of wait.Until() is to not have to do that, and this is making our test suites get very long. Also, as you can see in the example above, sometimes we have the problem even after putting a Thread.Sleep() in front of it and we have to extend the time.
Why is .NET Selenium's WebDriver.Until() not working, and is there a different way to do the same thing without just waiting a set period of time? Again, the problem is intermittent, meaning that it only happens sometimes, and it could happen at any number of wait.Until() statements, not just the one shown!
Edit:
This is a class variable.
private WebDriverWait wait;
It is instantiated like this:
this.wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
I decided to just not use WebDriverWait.Until(), and use implicit waits on the main driver instead:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
I give full credit to this answer on a different question for giving me the idea.
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
try
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
catch
{
throw;
}
}
or if you are having
NoSuchElementException
try this code
try
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds)).Until(ExpectedConditions.ElementIsVisible(by));
}
return driver.FindElement(by);
}
catch(Exception e)
{
throw;
}

Categories