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

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;
}

Related

Selenium FindElements() times out. Get around unpredictable loading icons

I've searched quite a bit on this topic on the stack and other places.
When I run driver.FindElements(By.myselector) my browser waits 60 seconds to time out. Instead of returning an empty list as described by the documentation
( https://www.selenium.dev/documentation/en/getting_started_with_webdriver/locating_elements/ ). It seems to be a great solution to work around an element possibly being in the DOM.
I need to check for the possible existence of loading icons/gifs. When the icons are present I need to wait until they are gone. When the icons are not there I need the method to fail to find MUCH faster than 60 seconds so I can let the script continue to test. The loading icon's appearance is not always predictable.
Is there a way to
Make an individual operation fail quickly?
Get FindElements() to return an empty list instead of failing after 60 seconds?
Get around unpredictable DOM blocking loading icons another way?
Examples of code I have tried:
Find if any elements are returned. Originally had a loop to keep checking if empty. If not Thread.Sleep() then reassign and check for existence again. Waits 60 seconds to fail.
public static IWebElement FindElementIfExists(ChromeDriver _driver, By by)
{
ReadOnlyCollection<IWebElement> elements = _driver.FindElements(by);
return (elements.Count >= 1) ? elements[0] : null;
}
This code works when the loading icon shows up, but Selenium waits 60 seconds and fails on
OpenQA.Selenium.WebDriverException: 'The HTTP request to the remote WebDriver server for URL timeout after 60 seconds when the icon is
not in the DOM.
public static bool isElementDisplayed(ChromeDriver _driver, By aSelector)
{
try
{
// WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(4));
wait.Until(ExpectedConditions.ElementIsVisible(aSelector));
return _driver.FindElement(aSelector).Displayed;
}
catch (Exception ex)
{
if (ex is NoSuchElementException || ex is StaleElementReferenceException || ex is TimeoutException)
{
return false;
}
else
{
throw ex;
}
}
}
public static void WaitForElementToBeGone(ChromeDriver _driver, By aSelector, int timeout)
{
if (isElementDisplayed(_driver, aSelector))
{
new WebDriverWait(_driver, TimeSpan.FromSeconds(timeout)).Until(ExpectedConditions.StalenessOf(_driver.FindElement(aSelector)));
}
}
Thanks again

Assert element not exist without exception

I am trying to make an if statement so I can use my code in multiple situations.
When i try to assert displayed or enable I get in some situations an exception Iwebelement could not be found.
I want to make a statement that if element exist 'x' should happen and when element does not exist 'y' should happen.
As mentioned I tried Displayed, Enabled. I also tried asserFalse but that also didnt gave me the required result.
It was asked for code but I only need a if statement that let something true if element exist otherwise should skip it. When I do
if (element.Displayed)
{
}
But in some cases I get an exception and I dont want the exception
is this in a TestNG or JUnit test?
I would usually handle this in a normal case inside the if statement:
pseudocode:
if(exists(x)){
assertTrue(....);
}
else{
assertFalse(....);
}
Search for multiple elements and even if one exists (>0), then return true, otherwise, non of the elements with a specific By exist.
bool ElementExists()
{
return driver.FindElements(By.Id("your locator")).Count > 0;
}
Then just do
bool ElementExists(By locator)
{
TimeSpan originalWait = driver.Manage().Timeouts().ImplicitWait;
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(0);
bool exists = driver.FindElements(locator).Count > 0;
driver.Manage().Timeouts().ImplicitWait = originalWait;
return exists;
}
if(ElementExists(By.Id("your locator")))
{
//Do Stuff
}
else
{
//Do Stuff when element does not exist
}
Edit: Also reduce your implicit wait to 0 seconds so you don't wait long for your bool to return (the webdriver will wait for the element to appear as long as you told).
Your approach will work only when the element is displayed or exists , if not it will throw the exception and you are not handling that, so the script is failing for you.
You can create a method like below by handling the exception(I have written it in java , please make the required changes).
public static Boolean isElementDisplayed(WebDriver driver, By element) {
try {
driver.findElement(element).isDisplayed();
System.out.println("Element is displayed");
return true;
} catch (NoSuchElementException | ElementNotVisibleException e) {
System.out.println("Element not displayed");
return false;
}
}
And you can use the above method in you test cases 'n' number times like this.
if(isElementDisplayed(driver, By.xpath("locator")){
//do what you have to do if element is exists
}else{
//do what you have to do if element is not exists
}
Hope this will solve your problem

Try block do not handle scenario when element not found

I used below code and found that TRY block is not working for the situation when element is not present :
try
{
var actual = new WebDriverWait(m_WebDriver, TimeSpan
.FromSeconds(5))
.Until(ExpectedConditions
.ElementIsVisible(By.XPath(XpathUnderTest)))
.Displayed;
return actual;
}
catch (Exception ex)
{
return false;
}
I have a use-case where presence of Webelement is depend on other conditions so it is not present or visible all the time on webpage. If element is present then it's working and if element is not present then Try catch is not able to handle the scenario using you above code.
I also tried : bool isPresent = Driver.Findelements.(xpath).Count() > 0; // list
but it is not working as well if element is not present
As per your code block it's the right behavior as WebDriverWait with ElementIsVisible is correct.
As per the documentation, ExpectedConditions with ElementIsVisible will return the IWebElement once it is located and visible. In case the ExpectedConditions fails a Boolean value is returned back.
As in your try block you are defining :
var actual;
And trying to :
return actual;
So, irespective of the return from ExpectedConditions with ElementIsVisible your try block returns False Positive.
Solution :
WebDriverWait with ExpectedConditions must be implemented outside any Try-Catch block. Next steps can be decided with respect to the return type.

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

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

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.

Categories