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.
Related
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));
}
I wrote this code in C# and it's not working for me.
Second url is still opening in the first tab, although I switched tabs and updated handle.
// open first page in first tab
string firstPageUrl = "http://google.com";
driver.Navigate().GoToUrl(firstPageUrl);
// getting handle to first tab
string firstTabHandle = driver.CurrentWindowHandle;
// open new tab
Actions action = new Actions(driver);
action.SendKeys(OpenQA.Selenium.Keys.Control + "t").Build().Perform();
string secondTabHandle = driver.CurrentWindowHandle;
// open second page in second tab
driver.SwitchTo().Window(secondTabHandle);
string secondPageUrl = "http://bbc.com";
driver.Navigate().GoToUrl(secondPageUrl); // FAILED, page is opened in first tab -.-
Thread.Sleep(2000); // slow down a bit to see tab change
// swtich to first tab
action.SendKeys(OpenQA.Selenium.Keys.Control + "1").Build().Perform();
driver.SwitchTo().Window(firstTabHandle);
Thread.Sleep(1000);
action.SendKeys(OpenQA.Selenium.Keys.Control + "2").Build().Perform();
I'm using latest Chrome driver.
Any ideas?
EDIT:
This is not duplicate. I am not opening links here, I want to navigate to URL I've provided. Also, I am using CurrentWindowHandle as suggested, but it is not working for me.
string secondTabHandle = driver.CurrentWindowHandle; is still returning the first tab, even if the second tab cover the first one. Try this
string firstTabHandle = driver.getWindowHandle();
Actions action = new Actions(driver);
action.SendKeys(OpenQA.Selenium.Keys.Control + "t").Build().Perform();
// switch to the new tab
for (String handle : driver.getWindowHandles()) {
if (!handle.equals(firstTabHandle))
{
driver.switchTo().window(handle);
}
}
// close the second tab and switch back to the first tab
driver.close();
driver.switchTo().window(firstTabHandle);
Not entirely sure if this is related to your problem (but I think it might be):
I've found, with selenium, that a better alternative to using Thread.Sleep() is using:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
where first argument is the selenium driver you're using, and the second argument is how long you want to wait before giving up (the timeout)
You can then call:
wait.Until(condition);
where condition is what you want to wait for. There is a selenium class that provides various useful conditions called ExpectedConditions, for example:
ExpectedConditions.ElementToBeClickable(By by)
which would wait for a particular clickable element to be ready to click.
In fact, I've found that any time the content of the page changes, it's a good idea to wait for the element you're using next like this.
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");
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.
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.