Selenium - C# - Webdriver - Unable to find element - c#

Using selenium in C# I am trying to open a browser, navigate to Google and find the text search field.
I try the below
IWebDriver driver = new InternetExplorerDriver(#"C:\");
driver.Navigate().GoToUrl("www.google.com");
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
IWebElement password = driver.FindElement(By.Id("gbqfq"));
but get the following error -
Unable to find element with id == gbqfq

This looks like a copy of this question that has already been answered.
I can show you what I've done, which seems to work well for me:
public static IWebElement WaitForElementToAppear(IWebDriver driver, int waitTime, By waitingElement)
{
IWebElement wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime)).Until(ExpectedConditions.ElementExists(waitingElement));
return wait;
}
This should wait waitTime amount of time until either the element is found or not. I've run into a lot of issues with dynamic pages not loading the elements I need right away and the WebDriver trying to find the elements faster than the page can load them, and this is my solution to it. Hope it helps!

You can try using a spin wait
int timeout =0;
while (driver.FindElements(By.id("gbqfq")).Count == 0 && timeout <500){
Thread.sleep(1);
timeout++;
}
IWebElement password = driver.FindElement(By.Id("gbqfq"));
this should help make sure that the element has actually had time to appear.
also note, the "gbqfq" id is kinda a smell. I might try something more meaningful to match on than that id.

Related

Headless Browser C# and Alternatives

currently I have the following code using selenium and phantomjs in c#:
public class Driver
{
static void Main()
{
using (var driver = new PhantomJSDriver())
{
driver.Navigate().GoToUrl("https://www.website.com/");
driver.Navigate().GoToUrl("https://www.website.com/productpage/");
driver.ExecuteScript("document.getElementById('pdp_selectedSize').value = '10.0'"); //FindElementById("pdp_selectedSize").SendKeys("10.0");
driver.ExecuteScript("document.getElementById('product_form').submit()");
driver.Navigate().GoToUrl("http://www.website/cart/");
Screenshot sh = driver.GetScreenshot();
sh.SaveAsFile(#"C:\temp\test.jpg", ImageFormat.Png);
}
}
}
My objective is to be able to add a product to my cart and then checkout automatically. The screenshot is just included to test whether the code was successfully working. My first issue is that I often get an error that it cannot find the element with product id "pdp_selectedSize". I'm assuming this is because the the webdriver hasn't loaded the page yet, so I'm looking for a way to keep checking until it finds it without having to set a specific timeout.
I'm also looking for faster alternatives to use instead of a headless browser. I used a headless browser instead of http requests because I need certain cookies to be able to checkout on the page, and these cookies are set through javascript within the page. If anyone has a reccommendation for a faster method, it would be greatly appreciated, thanks!
For your first question, it would behoove you to look into using ExpectedConditions' which is part of theWebDriverWaitclass inSelenium`. The following code sample was taken from here and only serves as a reference point.
using (IWebDriver driver = new FirefoxDriver())
{
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>(d =>
d.FindElement(By.Id("someDynamicElement")));
}
More on WebDriverWaits here.
As to your second question, that is a really subjective thing, in my opinion. Headless Browsers aren't necessarily any faster or slower than a real browser. See this article.

Selenium C# Webdriver: I am getting error: 'iWebDriver' does not contain definition for 'WaitforElement'

I am new to Selenium and C#... I am in middle of a selenium application development using C#. I have a drop down menu on a webpage. I want selenium to click on the exact name after clicking the drop down menu. So I did something like this:
C#/NUnit code:
driver.FindElement(By.LinkText("z")).Click;
driver.WaitForElement(By.LinkText("xxxxx"));
driver.FindElement(By.LinkText("xxxxx")).Click();
but when I build my code I get the following error:
'iWebDriver' does not contain definition for 'WaitforElement'
Okay, I can offer you an example, but I don't know c#, But I can give you the example from Ruby Selenium Binding.
driver.manage.timeouts.implicit_wait=20
driver.find_element(:link_text,"z").click;
driver.find_element(:link_text,"xxxxx").click
Since I have given the implicit wait 20, whenever it finds the element via find_element function, it waits for 20 minutes, So your external wait statement is not necessary .
The C# code might be(I don't know C#, I took it from the net and placing it here)
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.FindElement(By.LinkText("z")).Click;
driver.FindElement(By.LinkText("xxxxx")).Click();
It doesn't work the way you shown.
The next code is an example how you should write it:
WebDriverWait watiDriver = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
IWebElement element = watiDriver.Until(x => Driver.FindElement(By.CssSelector("")));
Where Driver is your instance of a webdriver.
If you want to use it as you shown then you need to add an extension method to the webdriver class. To do this, just create a new static class (with any name) and insert the next code into it:
public static IWebElement WaitForElement(this IWebDriver driver, By how)
{
webDriverWait watiDriver = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
return watiDriver.Until(x => Driver.FindElement(FindElement(how));
}

Ocasional InvalidElementStateException or ElementNotVisibleException when calling SendKeys on input

I have this code:
IWebDriver driver = new FirefoxDriver();
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
//Go to the powerbi site
driver.Navigate().GoToUrl("https://powerbi.microsoft.com/en-us/");
//Go to the page with login form
driver.FindElement(By.XPath("html/body/div[2]/header/nav/div/ul[3]/li[1]/a")).Click();
//Fill in email field
driver.FindElement(By.XPath("//*[#id='cred_userid_inputtext']")).SendKeys("example#gmail.com");
When I launch this code on my computer everything works fine without errors. But when I launch this code on my boss's computer, sometimes it works and sometimes it doesn't.
When an error occurs, it's always on the last line of code. I don't remember exactly which error it is: InvalidElementStateException (when the target element is not enabled) or ElementNotVisibleException (when the target element is not visible).
I suppose the whole thing lies on the Click() method. The documentation says:
Click this element. If the click causes a new page to load, the Click() method will attempt to block until the page has loaded.
I don't quite understand how it attempts to block.
Seems like your input isn't always ready immediately after you click the button.
You should wait for it before sending the keys:
Try this instead of your last line:
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,5));
var input = wait.Until(ElementIsClickable(By.XPath("//*[#id='cred_userid_inputtext']")));
input.SendKeys("example#gmail.com");
In order to do that check, you should create a ElementIsClickable function, which returns a delegate, just as this answer shows:
public static Func<IWebDriver, IWebElement> ElementIsClickable(By locator)
{
return driver =>
{
var element = driver.FindElement(locator);
return (element != null && element.Displayed && element.Enabled) ? element : null;
};
}
Also, keep in mind that for using the WebDriverWait class you might need to import the Selenium.WebDriver and Selenium.Support packages into your project, just as this answer suggests.
It's coming occasional because sometimes it takes time to load element from DOM and which cause exception like InvalidElementStateException or ElementNotVisibleException.
I ran your snippets code.
It runs fine, try to separate action and find element.
WebElement element = driver.findElement(By.xpath(".//xyz"/);
element.sendkeys("data");
This could work.

Selenium is telling me the ID doesn't exist

When I run the following program it runs absolutely fine, until I get to filling out the form on the webclip section. Once it gets there it says the id "txtTemplateName" can't be found. I copied and pasted that name directly from Inspecting the element. It isn't that i'm not giving it enough time to load either, I've given it a full 5 seconds in the past just to make sure, and still nothing.
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System.Diagnostics;
using System.Linq;
namespace Build1Evan
{
class Program
{
static void Main(string[] args)
{
IWebDriver driver1 = new FirefoxDriver();
driver1.Navigate().GoToUrl("URL");
Process.Start(#FILE"); // This is just an Auto IT Script to get me by a login window
bool loginCheck1 = driver1.FindElements(By.Id("btnLoginAgain")).Count() > 0;
if (loginCheck1 == true)
{
driver1.FindElement(By.Id("btnLoginAgain")).Click();
}
System.Threading.Thread.Sleep(500);
driver1.FindElement(By.LinkText("Configuration")).Click();
System.Threading.Thread.Sleep(500);
driver1.FindElement(By.LinkText("Payloads")).Click();
System.Threading.Thread.Sleep(500);
driver1.FindElement(By.PartialLinkText("WebClip")).Click();
// BELOW IS WHERE I ENCOUNTER THE ISSUE
System.Threading.Thread.Sleep(500);
driver1.FindElement(By.Id("txtTemplateName")).SendKeys("TESTING");
}
}
}
I also encounter the error when I try selecting any other element in the form, rather it be a button or another text field.
EDIT: PHOTO AS ASKED
EDIT 2: PHOTO 2 Also just a FYI i have had no problems using Selenium IDE, it is easily able to select the element and fill it in.
According to your screenshot, I think your app embed the form by using <object id="panelcontentobject" data="....
In case the form is really inside object tag, you have to create a WebElement of the object tag then use JavaScriptExecutor to retrieve attribute or interact with the form.
For example,
IWebElement objectTag= driver.FindElement(By.Id("panelcontentobject"));
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
js.ExecuteScript("return (arguments[0].contentDocument.getElementById('txtTemplateName')).click()",objectTag);
Please see Examples from http://aksahu.blogspot.com/2015/05/dealing-with-object-tags-in-selenium-webdriver.html?m=1
The form is probably inside iframe, you need to switch to it before you can perform actions on elements inside it:
IWebElement frame = driver.FindElement(By.Id(frameId));
driver.SwitchTo().Frame(frame);
You can also use explicit wait to make sure the element you want is visible and you can interact with it:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("txtTemplateName"))).SendKeys("TESTING");

Selenium C# RemoteWebDriver not finding XPath Elements

I'm using Selenium 2.25.1 API, and I'm trying to be able to find the elements using RemoteWebDriver(). Except when I try, it just fails to find the element. I've tried several different combinations with no luck and have been looking this up for a few days now.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement WaitForPage = wait.Until<IWebElement>((d) =>
{
return driver.FindElement(By.XPath((String)data));
});
Is my code where it fails. Basically the data variable is an object grabbed from my database. I converted it, and going though the code it comes out perfectly fine. How the difference is, when I used just the browser (i.e. firefox, IE) it works just fine with no errors. But when I use it with RemoteWebDriver(), it throws InvalidOperationException and throws a popup saying it was unable to find the element. (Server did not provide any stacktrace information).
This is usually what I use
IWebDriver driver = new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub"), IEcapa);
When that is used, it just fails everytime.
Any ideas? I am completely puzzled. Anything is welcome and thanks in advance!
I would suggest using an implicit wait instead of an WebDriverWait statement.
WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
IWebElement WaitForPage = driver.FindElement(By.XPath((String)data));
And make sure that the xpath you are getting from the data variable is valid. If possible post an some xpath you get from the database.

Categories

Resources