Selenium / C# WebDriverWait Not Waiting - c#

I have a website with a jQuery slide down at the top with a list of all the languages I want to use: http://testing.bestshippers.com/net/index.aspx, the slider is "language selection" button at the top.
I can click it, but I get and error when trying to click on the elements inside of the slide down. I believe it is because I need to pause for a few seconds before I try to select them. Could be wrong? I'm relatively new, but I have read all kinds of things about the WebDriverWait and changing focus.
//check spanish
driver.FindElement(By.XPath("//*[#id='openCloseWrap']/img")).Click();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(100));
driver.FindElement(By.Id("ButtonSPFlag")).Click();
String check = driver.FindElement(By.XPath("html/body/form/div[5]/div/div[1]/div/p")).Text;
Console.Out.WriteLine(check);
The above code clicks on the openCloseWrap (Language Selection Button) and then I am trying to pause for seconds (100) and then trying to click on the SP flag to change the language.
Anyone able to provide any assistance with why my wait will not pause?

You are initiating the Wait, but not waiting for anything. You probably want to do something similar to:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(100));
// wait.Until(By.Id("ButtonSPFlag"));
IWebElement element = wait.Until(driver => driver.FindElement(By.Id("ButtonSPFlag")));
element.Click();
Alternatively you can set implicit wait, but I would go with the first one.
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

I would upvote you both, but I don't have enough rep points yet.
I worked on this for 4 days, issue seems to be with the way that the language bar is displayed. I can't seem to reference anything whether by CSS, XPath or naming. I'm going to keep moving on my project for now. I can check to make sure it exists, and that passes (see below) but the actual interaction fails for some reason. I am going to keep working and I will revisit. Thank you both for your time and effort!
DoesElementExistX(driver, sw, "//*[#id='openCloseWrap']/img");
DoesElementExistX(driver, sw, "//*[#id='ButtonUSFlag']");
DoesElementExistX(driver, sw, "//*[#id='ButtoFRFlag']");
DoesElementExistX(driver, sw, "//*[#id='ImageButton1']");
DoesElementExistX(driver, sw, "//*[#id='ButtonDEFlag']");
DoesElementExistX(driver, sw, "//*[#id='ButtonITFlag']");
DoesElementExistX(driver, sw, "//*[#id='ButtonSPFlag']");
#region[DoesElementExistX]
public static void DoesElementExistX(IWebDriver driver, StreamWriter sw, String id)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(2));
try
{
wait.Until(ExpectedConditions.ElementExists(By.XPath(id)));
}
catch (WebDriverTimeoutException)
{
sw.WriteLine("FAILED - " + id);
}
}
#endregion

I looked into this some more.
You're trying to click on the Language element by id. This is a problem, because Selenium will click in the center of the element (unless otherwise told differently), and the center of the element is to the left of the Language area.
I think this will accomplish what you need:
driver.FindElement(By.CssSelector(".topMenuAction")).Click();
driver.FindElement(By.Id("ButtonSPFlag")).Click();
String Check = driver.FindElement(By.CssSelector("#loginBoxInner>p")).Text;
You may need to add a Sleep(), or use WebDriverWait().

Could it be that the language selection bar is always in the DOM, and that when you click "expand" it is simply showing the html rather than creating or injecting it?
If so, then your "wait" will return straight away because you are saying "wait until the element" is in the HTML, and in your case, it is always there.
You need to make your waiting smarter such as "wait until displayed" or perhaps even "wait until displayed and stationary" as you also need to wait for the animation to finish

Related

Selenium can not proceed as chrome Does not loads UI

Sometimes, Selenium C# launches chrome as well as the website, but is unable to interact with it.
On close inspection, I noticed that it was because chrome was not in focus and was not loading the UI.
As soon as I focused the chrome, I would see a white screen for half a second, and then UI appeared. And as soon as UI appeared, the test started running well.
I feel like chrome can not get enough system resources without the background. Any help would be appreciated. I never faced the issue in selenium-python.
Website is - web.whatsapp.com
It look like you are not giving enough time for page to load. You can use any of the below wait technique.
Explicit Wait in Selenium C#
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
String ele_xpath = "<xpath of element>"
WebDriverWait wait = new WebDriverWait(driver,30);
IWebElement welcomeMessage =
wait.until(ExpectedConditions.visibilityOfElementLocated(By.XPath(ele_xpath)));
// Here I have assumed first page is having a welcome message, you can use any element present on your page. Your script will wait up to 30 sec for element to appear before it will throw timeoutexception
implicit wait in Selenium C#
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
//Above will make script to wait for each element up to 30 sec
waiting in C#:
You can ask your script to wait for a defined millisecond before executing next line of code:
Thread.Sleep(6000);
# It will for 6 sec
Fluent Wait in Selenium C#
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS) // this defines the total amount of time to wait for
.pollingEvery(2, SECONDS) // this defines the polling frequency
.ignoring(NoSuchElementException.class); // this defines the exception to ignore
WebElement welcomeMessage= fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) //in this method defined your own subjected conditions for which we need to wait for
{ return driver.findElement(By.xpath("//*[contains(text(),'Welcome')]"));
}});
Note : You can use any of the above wait method. However each of them have their own advantage/ disadvantage. Please read more about them and difference at below link:
https://www.lambdatest.com/blog/selenium-waits-implicit-explicit-fluent-and-sleep/
Please try the following - it will force focus on Chrome (from the information provided I can assume there a JS event which blocks the page loading or trigger onfocus event).
var driver = new ChromeDriver();
driver.Manage().Window.Maximize(); // will focus or at least bring to front
// other things to try - switch
driver.SwitchTo().DefaultContent();
driver.SwitchTo().ActiveElement();
// other things to try - JavaScript
((IJavaScriptExecutor)driver).ExecuteScript("document.querySelector('body').focus();")

How to handle cases where Selenium click action succeeds, but nothing happens

I am using Selenium to test the user interface of a website. 95% of the time, things work fine. I find my elements, execute my clicks, and check the results. Unfortunately, maybe 5% of the time, I'll find the element, verify that it is clickable, run the click event with no error... but nothing actually changes.
Here's an example bit of code:
WebDriverWait waitForTimeout = new WebDriverWait(Driver, TimeSpan.FromSeconds(60));
IWebElement selectMaskButton = waitForTimeout.Until(ExpectedConditions.ElementToBeClickable(By.Id("mask_expander")));
Thread.Sleep(250); // A slight delay ensures that the button really is clickable
selectMaskButton.ClickAndWait(Driver);
I have that sleep statement in there because this is a case where, frequently, that click event goes awry. The quarter second wait works most of the time, but not always. For this case, I could probably surround it with custom code to pause, and then click again if the specified follow-up element doesn't work out, but that's clunky and involves a different target for everywhere that I click on things. And adding delays everywhere is less than optimal too because it leads to a bunch of fixed delays that just keep getting incremented as people run into issues.
I don't know that it's entirely a matter of going too fast because I've had the occasional case where I set a debug statement on a Click command, run the test in debug, and waited a few seconds before executing the Click, and still it doesn't work. As a tester, I don't have access to some of the inner code, so I don't know exactly what gets executed inside the click, and the developers I've spoken to are basically telling me that it works fine when they manually click on it, so they don't see the problem.
Is there a generic way to handle clicking on an element and ensuring that the action actually fires?
Additional code for helper function ClickAndWait:
public static void WaitUntilPageLoads(this IWebDriver driver)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(d => ((RemoteWebDriver)d).ExecuteScript("return document.readyState").Equals("complete"));
Thread.Sleep(500);
}
public static void ClickAndWait(this IWebElement element, IWebDriver driver)
{
element.Click();
driver.WaitUntilPageLoads();
}
In this case, ClickAndWait actually isn't useful because the page is changing dynamically rather than all at once, so the page claims to be loaded right away. I had just forgotten to replace the call.

(C# Selenium) How to wait until an element is present?

I am completely new to Selenium, started using it yesterday and I am pretty much done with the first part of my project and I really love the way its going.
Altho I am having one problem, currently I am using Thread.Sleep for pauses until elements get present. There are some animations going on or just slow loading at times, how can I make it wait until the element is present and then interact with it?
For example:
LoginPageElements loginPage = new LoginPageElements();
loginPage.continueLink.Click();
Thread.Sleep(5000); //here it has to wait until the next page loads
ClickDailyBonusPopUp();
Driver.driver.Navigate().GoToUrl(.....);
Thread.Sleep(2000); //here it has to wait until a login form pops up
LoginFormElements loginForm = new LoginFormElements();
loginForm.userPasswordLogin.Click();
Thread.Sleep(2000); //here it has to wait until a different login form pops up
You need to use WebDriverWait class. Here is really good solution for your problem.
If your application uses jQuery, I would make use of Selenium's IJavaScriptExecutor to do something like this:
public void WaitForAjax()
{
if ((bool)((IJavaScriptExecutor)WebDriver).("return window.jQuery != undefined"))
{
while (true)
{
var ajaxIsComplete = (bool)((IJavaScriptExecutor)WebDriver).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
}
(More on jQuery.active here.)
The main idea is to find some condition or element to poll for/wait on that is always present when the page isn't ready.

How to wait for element to load in selenium webdriver?

I am new to selenium webdriver and am testing one application. In my application, I have to test about linking Facebook Account. Whenever I click on link the pop up will be displayed where I have to enter credentials. I am able to link sometimes and sometimes the test fails. I know the reason because it takes time to load pop up window and next command is executed so it is not able to find the element. I have used Thread.Sleep but I want to use implicit wait or explicit wait which is always a good practice rather than Thread.Sleep. How to use implicit wait and where to use that command exactly? Please advice. Thanks.
public void SocialFaceBook()
{
string currentWindow = driver.CurrentWindowHandle;
PopupWindowFinder finder = new PopupWindowFinder(driver);
string facebookWindow = finder.Click(driver.FindElement(By.XPath("//div[#id='panelFacebook']/div[2]/div[3]/div[3]/a")));
// Switch To FaceBook Window
driver.SwitchTo().Window(facebookWindow);
System.Threading.Thread.Sleep(3000);
// Link
// Email Address
IWebElement faceBookLinkEmail = driver.FindElement(By.Id("email"));
faceBookLinkEmail.SendKeys(SocialFaceBookEmail);
// Password
IWebElement faceBookLinkPass = driver.FindElement(By.Id("pass"));
faceBookLinkPass.SendKeys(SocialFaceBookPass);
// Log In Button
IWebElement faceBookLinkLogin = driver.FindElement(By.XPath("//input[#id='u_0_1']"));
faceBookLinkLogin.Click();
// Switch To Main Window
driver.SwitchTo().Window(currentWindow);
System.Threading.Thread.Sleep(3000);
// Sync
IWebElement faceBookSync = driver.FindElement(By.XPath("//div[#id='panelFacebook']/div[2]/div[3]/div[2]/a"));
faceBookSync.Click();
// Unlink
IWebElement faceBookUnLink = driver.FindElement(By.XPath("//div[#id='panelFacebook']/div[2]/div[3]/div[1]/a"));
faceBookUnLink.Click();
}
Sometimes it is not able to find the log in details as pop up is not loaded properly and sometimes it is not able to find sync button as facebook account takes time to link. Please advice.
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("locator")));
It will wait for the element to be located for a maximum of 30 seconds if the element is found before that it will execute....
I had to change some small things from #Vicky's answer but this is what I got as a method I could call.
public static void WaitForElementLoad(By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(timeoutInSeconds));
wait.Until(ExpectedConditions.ElementIsVisible(by));
}
}
and I call it like this:
MyClass.WaitForElementLoad(By.CssSelector("div#div1 div strong a"), 10);
I used to write a function to detect an element exists every second. if find continue, otherwise threw timeout error. but in that function i still use Thread.Sleep.
Expect other good solution.
I use ExpectedCondition.visibilityOf(element) instead of thread sleeps
Implicit wait -- max waiting time to identify object, it will identify the object for every 500 ms. if it fails to identify the object with in maximum time it will throw nosuchelement exception.
Explicit wait -- used for ajax page loads for the same purpose.
maximum waiting time is same as thread.sleep
Wrote a method for a project:
public static void WaitForElementPresentBy(By by)
{
try
{
Wait.Until(ExpectedConditions.ElementIsVisible(by));
}
catch (TimeoutException te)
{
Assert.Fail("The element with selector {0} didn't appear. The exception was:\n {1}", by, te.ToString());
}
}
Wait should have already been defined.

Selenium Webdriver c# without waiting for page to load

I have the following scenario:
I want to navigate to a page. Then click a button as soon as it appears(not wait for page to load ). I don't want to wait for the initial page to load as it takes a long time. My program currently is stuck until the page loads and then clicks the button.
I basically want to navigate to link and then have no wait for page and continue with my code.
Is there anyway round this?
With the latest version of the .NET bindings, you can set a page load timeout. However, there are some caveats you'll need to be aware of. First, this hasn't been implemented by all browsers. It should work for IE and Firefox, if memory serves. Secondly, you'll need to catch an exception to make that work properly, but it can be done.
// WARNING! Completely untested code written without
// the benefit of an IDE!
IWebDriver driver = new InternetExplorerDriver();
driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(1));
try
{
driver.Url = "http://your.long.loading.page.com";
}
catch (TimeoutException)
{
// NOTE: In 2.26 or later, this will be WebDriverTimeoutException
}
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("yourId"));
}
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) =>
{
return d.FindElement(By.Id("someDynamicElement"));
});
It does exactly what you want. It queries the page to find the element, catches exceptions if no element found and returns an element when found.
After that, you can manipulate the button ignoring the fact that page can be not loaded
http://seleniumhq.org/docs/04_webdriver_advanced.html
Short answer: No.
Long answer: Selenium is by default trying to simulate the real user - I know that it kinda sucks, especially at a times you need to test a deploy after deploy after deploy...
But: If real user has to wait for button to appear, then the program has to do it also...
BTW: If the button really appears among first on the page, you can try this:
search for the button by ID, xpath ... the way you do it
Catch exception (I am Java guy, so dont ask me how)
If there was error, wait short time (e.g. 200 milliseconds) and then go to 1
If not, click the button
The cycle should end also if certain amount of time passes (10s) and if so, throw exception
As stated above: Language of my choice is Java. There I can do that. But I dont know how to write that in C#

Categories

Resources