I am trying to do a wait for element to be visible before I try to click it. My tests fail with NoSuchElementException if I don't wait. Right now I am doing a wait by text but I want to be able to wait for the accessibilityId. I noticed that accessibilityId is not an option in By. How do I handle it?
_driver = new AndroidDriver<IWebElement>(new Uri("http://127.0.0.1:4723/wd/hub"),capability);
var wait = new WebDriverWait(_driver,new TimeSpan(0,0,0,15));
wait.Until(ExpectedConditions.ElementIsVisible(
By.XPath("//android.widget.TextView[#text='Bypass Sign In (Testing Only)']")));
_driver.FindElementByXPath("//android.widget.TextView[#text='Bypass Sign In (Testing Only)']").Click();;
Update: I noticed that there is a MobileBy class with a By strategy for Accessibility Id however when I try to implement the wait with it my test fails immediately with a NoSuchElementException. Once I have waited long enough using the xpath and then do a click by _driver.FindByAccessibilityId it seems to recognize that button and click on it.
Failing Code below.
'var wait = new WebDriverWait(_driver, new TimeSpan(0, 0, 0, 45));
wait.Until(ExpectedConditions.ElementIsVisible(MobileBy.AccessibilityId("Button_SignIn")));
_driver.FindElementByAccessibilityId("Button_SignIn").Click();'
Working Code
`var wait = new WebDriverWait(_driver, new TimeSpan(0, 0, 0, 45));
wait.Until(ExpectedConditions.ElementIsVisible(
By.XPath("//android.widget.TextView[#text='Bypass Sign In (Testing Only)']")));
_driver.FindElementByAccessibilityId("Button_SignIn").Click();`
I just figured out that there is a MobileBy class in C# that has the AccessibilityId locator available as a By type but it didn't really do what I was expecting it to
Related
I want to start my Selenium script on a login page, wait for 30 seconds so I can manually resolve a captcha, and once the login is successful, start the actual work automation work.
I'm using the code below, and it works ok up to the line where it enter the email.
I supposed that this code will wait in a sort of pooling until it sees the H4 element with certain text in it (login successful), but it throws an exception when the element is not found.
IWebDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
driver.Navigate().GoToUrl("URL");
var loginEmail = driver.FindElement(By.Id("LOGINTextBTTN"));
loginEmail.SendKeys("myEmail"); //this line works
IWebElement firstResult = wait.Until(ExpectedConditions.ElementExists(By.XPath(#"//h4[text()='H4 Text']"))); //this lines fails with an exception
Console.WriteLine(firstResult.GetAttribute("textContent"));
Write the code
driver.manage().timeouts().implicitlyWait(60,TimeUnit.SECONDS) ; // Wait for 60 Sec.
WebElement firstResult = wait.Until(ExpectedConditions.ElementExists(By.XPath(#"//h4[text()='H4 Text']")));
Or
You can use Fluentwait
Wait wait = new FluentWait(driver).withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
I had to deal with this a while back. The way I solved was with sleep:
time.sleep(seconds need to solve) #for me it was around 60ish seconds
Probably something like:
import code
code.interact(local=dict(globals(), **locals()))
Then Ctrl+D out after you solve the captcha
We have some UI tests written in selenium running with Browserstack on TeamCity.
These tests randomly fail because (in my opinion) the wait.Untils are not working correctly as the error always is 'could not click element ... because element would receive the click. As you can see in the code i apply multiple waits and still it randomly ignores them.
driver.FindElement(By.XPath("//input[#value='Login']")).Click();
//wait for the page to be loaded, check the title and open a booking
wait.Until(ExpectedConditions.ElementExists(By.LinkText("To be completed")));
wait.Until(ExpectedConditions.ElementToBeClickable(By.LinkText("To be completed")));
Assert.AreEqual("Booking Overview", driver.Title);
wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//button")));
wait.Until(ExpectedConditions.ElementToBeClickable(By.LinkText("To be completed")));
driver.FindElement(By.LinkText("To be completed")).Click();
//wait for step 2 to load
wait.Until(ExpectedConditions.ElementExists(By.XPath("//div[#id='WiredWizardsteps']/div[2]/div/form/div/div[2]/label/span")));
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div[#id='WiredWizardsteps']/div[2]/div/form/div/div[2]/label/span")));
//verify we are at step 2
var step2 = driver.FindElement(By.XPath("//ul[contains(#class, 'steps')]/li[contains(#class, 'active')]"));
Assert.AreEqual("2", step2.GetAttribute("data-target"));
//click the radiobutton with a movetoelement
var option = driver.FindElement(By.XPath("//div[#id='WiredWizardsteps']/div[2]/div/form/div/div[2]/label/span"));
new Actions(driver).MoveToElement(option).Click().Perform();
//retry programmatically
driver.FindElement(By.XPath("//div[#id='WiredWizardsteps']/div[2]/div/form/div/div[2]/label/span")).Click();
//wait for the textbox to appear
wait.Until(ExpectedConditions.ElementToBeClickable(By.Name("commodityNonOperative")));
anybody has a suggestion or had the same problems please let me know.
I am using FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to catch printing events. However I have noticed that FindNextPrinterChangeNotification does not reliably returns all the events. I have found a guy with the same problem in this article.
Basically, when I debug my program, or put Sleep command like his suggestion when processing an event, FindNextPrinterChangeNotificationskips a lot of events. Also, most of the time I get a lot of SPOOLING status events but miss the DELETED status event (sometimes I get it, but most of the time I cannot), even though I already push the jobs to a Queue for later processing.
Does anyone have this problem too? Also, I am trying the Microsoft PDF Printer, The NumberOfPages increases as the SPOOLING events come, but the NumberOfPagesPrinted does not. Is it intended?
EDIT After some investigation, the events are not actually gone. If I call another print job, the previous events are fired (including the DELETING/DELETED status of previous print job). Can you please suggest what is the problem?
Here's the code for calling FindFirstPrinterChangeNotification:
//We got a valid Printer handle. Let us register for change notification....
_changeHandle = FindFirstPrinterChangeNotification(_printerHandle, (int)PRINTER_CHANGES.PRINTER_CHANGE_JOB, 0, _notifyOptions);
// We have successfully registered for change notification. Let us capture the handle...
_mrEvent.SafeWaitHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(_changeHandle, true);
//Now, let us wait for change notification from the printer queue....
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);
And this is for the FindNextPrinterChangeNotification:
_notifyOptions.Count = 1;
_notifyOptions.dwFlags = PRINTER_NOTIFY_OPTIONS_REFRESH;
int pdwChange = 0;
IntPtr pNotifyInfo = IntPtr.Zero;
bool bResult = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions, out pNotifyInfo);
I had the same issue then I tried:
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);
with:
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, false);
(false arg in the end)
and seems to work now
I searched on uncountable webpages, and did not get a good answer to my question. I'm on Selenium 2.30 using C#.
I tried
if (browser.FindElement(By.XPath("xpath")).Displayed)
I tried
if (browser.FindElements(By.XPath("xpath")).Count !=0)
And also
IWebElement element = browser.FindElement(By.XPath("xpath"));
if (element.Displayed == true)
They only work when the element exist, but if not, it will pull out the exception. But that's not necessary an exception, I have something in else{} statement to handle it, I don't want the webdriver just stop me at the first point.
What I'm doing right now is
IWebElement element = null;
try
{
element = browser.FindElement(By.XPath("xpath"));
}
catch
{
}
if (element != null)
This way works so far, but I don't think this is the best solution. I appreciate if someone can show me a better way.
The way you are doing it is acceptable, but at times you will be trying to run this after performing a prior action (eg. navigating to a page) and it is usually best to give a timeout value and utilise the following WebDriverWait method:
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 0, timeout));
element = _wait.Until(x => x.FindElement(By.XPath(searchAttribute.attributeValue)));
This allows you to wait until the element exists on the page up to the timeout value (I use 5 seconds on the application I test). However, simple you can just use your code of if(element == null) then it is was not found. If you use the WebDriverWait, you will have to catch the exception if you do not want it to throw after the timeout.
I am using Selenium 2.20 WebDriver to create and manage a firefox browser with C#. To visit a page, i use the following code, setting the driver timeouts before visiting the URL:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5)); // Set implicit wait timeouts to 5 secs
driver.Manage().Timeouts().SetScriptTimeout(new TimeSpan(0, 0, 0, 5)); // Set script timeouts to 5 secs
driver.Navigate().GoToUrl(myUrl); // Goto page url
The problem is that sometimes pages take forever to load, and it appears that the default timeout for a page to load using the selenium WebDriver is 30 seconds, which is too long. And i don't believe the timeouts i am setting apply to the loading of a page using the GoToUrl() method.
So I am trying to figure out how to set a timeout for a page to load, however, i cannot find any property or method that actually works. The default 30 second timeout also seems to apply to when i click an element.
Is there a way to set the page load timeout to a specific value so that when i call the GoToUrl() method it will only wait my specified time before continuing?
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);
Note: driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(5)) is now deprecated.
In case this helps anyone still looking for the answer to this, the C# WebDriver API now contains the appropriate method.
driver.Manage().Timeouts().SetPageLoadTimeout(timespan)
With this you should be able to declare a wait explicitly.
WebDriverWait wait = new WebDriverWait(browser, new TimeSpan(time in seconds));
wait.until(Your condition)
you could also change the implicit wait time
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
I think that is the syntax in C#. (not to sure)
In ruby it is
#driver.manage.timeouts.implicit_wait = 30
#wait = Selenium::WebDriver::Wait.new(:timeout => 30)
i found the solution this this issue. When creating a new FirefoxDriver, there are overloads in the constructor that allow you to specify a command timeout which is the maximum time to wait for each command, and it seems to be working when calling the GoToUrl() method:
driver = new FirefoxDriver(new FirefoxBinary(), profile, new TimeSpan(0, 0, 0, timeoutSeconds));
link to FirefoxDriver constructor documentation for reference:
http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/html/M_OpenQA_Selenium_Firefox_FirefoxDriver__ctor_2.htm
Hope this helps someone else who runs into this problem.
We brazilians have a word for crappy workarounds "Gambiarra"... Well... at least they do the job...
Here is mine:
var url = "www.your.url.here"
try {
DRIVER.Navigate().GoToUrl(url);
} catch {
// Here you can freely use the Selenium's By class:
WaitElement(By.Id("element_id_or_class_or_whatever_to_be_waited"), 60);
}
// rest of your application
What my WaitElement(By, int) does:
/// <summary>
/// Waits until an element of the type <paramref name="element"/> to show in the screen.
/// </summary>
/// <param name="element">Element to be waited for.</param>
/// <param name="timeout">How long (in seconds) it should be waited for.</param>
/// <returns>
/// False: Never found the element.
/// True: Element found.
/// </returns>
private bool WaitElement(By element, int timeout)
{
try {
Console.WriteLine($" - Waiting for the element {element.ToString()}");
int timesToWait = timeout * 4; // Times to wait for 1/4 of a second.
int waitedTimes = 0; // Times waited.
// This setup timesout at 7 seconds. you can change the code to pass the
do {
waitedTimes++;
if (waitedTimes >= timesToWait) {
Console.WriteLine($" -- Element not found within (" +
$"{(timesToWait * 0.25)} seconds). Canceling section...");
return false;
}
Thread.Sleep(250);
} while (!ExistsElement(element));
Console.WriteLine($" -- Element found. Continuing...");
// Thread.Sleep(1000); // may apply here
return true;
} catch { throw; }
}
After this, you can play with timeout...
Make By the things you notice that loads last in the page (like javascript elements and captchas) remembering: it will start working the // rest of your application before the page fully loads, therefore may be nice to put a Thread.Sleep(1000) at the end just to be sure...
Also notice that this method will be called AFTER the 60 seconds standard timeout from Selenium's DRIVER.Navigate().GoToUrl(url);
Not the best, but... as I said: A good gambiarra gets the job done...
Page load timeouts are not implemented in the .NET bindings yet. Hopefully they will be soon.
As of 2018:
Besides these:
driver.Manage().Timeouts().ImplicitWait.Add(System.TimeSpan.FromSeconds(5));
driver.Manage().Timeouts().PageLoad.Add(System.TimeSpan.FromSeconds(5));
driver.Manage().Timeouts().AsynchronousJavaScript.Add(timespan));
wait for searching for an item, loading a page, and waiting for script respectively.
There is:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
For anyone who wants the opposite effect: setting timeout longer than 60s.
You need both use:
new FirefoxDriver(FirefoxDriverService.CreateDefaultService(), new FirefoxOptions(), TimeSpan.FromSeconds(120))
and
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(120);
The new FirefoxDriver(binary, profile, timeSpan) has been obsolete.
driver.Manage().Timeouts().SetPageLoadTimeout(timespan)
does not work.
This works. Use a property setter syntax.
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(15);