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();
}
Related
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
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");
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
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.
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;
}