EDIT: I have narrowed the problem to its possible source see Update 2 and you can skip the intro.
My issue is that selenium "thinks" it has clicked a link when the link click was never actually executed. The problem is due to a timing issue for InternetExplorer as Firefox doesn't seem to have this same issue (at least as often).
The issue occurs when I am on a particular page, open a popupdialog widget on that page, than close it and than try to continue to navigate.
Sample code:
//Already navigated to Myphotospage.
Account.MyPhotosPage.isLoaded();//Just to show its been loaded not required code.
Account.MyPhotosPage.ButtonUploadPhoto.click(); //Shows widget to user
Account.MyPhotosPage.DialogUploadPhoto.File.setText(Directory)//Do stuff...
Account.MyPhotosPage.DialogUploadPhoto.ButtonOK.click(); //Close dialog
Assert.IsTrue(Account.MyPhotosPage.isLoaded()); //Check that the page is still loaded
Account.MyPhotosPage.Menu.MyContacts.click(); //Navigate to a new page.
//FAILS THIS NEXT LINE SINCE PREVIOUS CLICK DID NOT ACTUALLY CLICK Though
//Selenium acts as if it did.
Assert.IsTrue(Account.MyContactsPage.isLoaded()); //Checks that new page is laoded
The main page contains dynamic images which means user can upload as many as they want so the elements id can dynamically change. The dialog uploads a new image to the page. I think this contributes to the slower loading/unloading times.
Currently I wait between each IWebElement reference using WebDriverWait timeout of 10 seconds:
_WAIT.Until(ExpectedConditions.ElementIsVisible); //PDEUDO Code. My code is slightly different.
Here is how the current execution behaves.
- It navigates to page.
- It popups the dialog
- It closes Dialog
- It immediately states the page is loaded though the "widget" could still actually be open or unloading itself. This can be seen with Console.WriteLines being written to output before the widget has fully closed.
- It thinks the page is loaded.
- It waits for IWebElement to be visible and executes the click command when visible before widget is unloaded or page is actually fully rendered. (Account.MyPhotosPage.Menu.MyContacts.click())
Because it thinks the element is visible and clicks it early, it doesn't actually navigate to the new page. Though selenium thinks it clicked the element successfully.
If I add a thread wait it fixes the problem.
...
Account.MyPhotosPage.DialogUploadPhoto.ButtonOK.click(); //Close dialog
Thread.Sleep(5 seconds);
...
Account.MyPhotosPage.Menu.MyContacts.click()//Navigate to new page
Summary: The dialog box makes selenium think the backpage isLoaded or that an element was clicked even though it was not registered. So selenium C# code acts as if the element was clicked on the main page while the widget still has focus or unloading (closing).
So increasing wait times does not fix the issue as it thinks the elements ARE visible and were clicked even though the browser did not register it. But by adding the System wait it has more time to load the page (or unload the widget) allowing the functions to work.
Design Notes: If you are interested this may help clarify my design approach.
I go into more detail in a response on this post: https://sqa.stackexchange.com/a/13579/11972
In short I define the main page as follows.
public MyDialog;
public MyPhotosPage()
{
PageFactory.InitElements(_DRIVER, this);
MyDialog = new MyDialog(); //PageFactory is executed in the constructor for the dialog page object.
}
Browser: InternetExplorer 11 FireFox seems to work more frequently.
Goal: I would like it to fully load without adding System waits. Any ideas? I prefer using some type of explicit waits. Have not tried using Driver implicit waits.
UPDATE Updated for more information.
My current wait strategy.
while (ignoredException)
{
try
{
PageObject._WAIT.Until(d => visibility(element));
ignoredException = false;
}
catch (StaleElementReferenceException)
{
//Ignored Exception
}
catch (NoSuchElementException)
{
//Ignored Exception
}
catch (WebDriverTimeoutException e)
{
//Timeout Exception
throw new UnabletoFindElementException(e.Message + " Element Locator: " + tag + " >>>>>>>> " + e.InnerException);
}
catch
{
//Unexpected exception
//Rethrow same exception.
throw;
}
My visibility method was adapted from ExpectedConditions.ElementIsVisible (cs file)
try
{
//Checks that the element is in the DOM by accessing its attributes.
iwe.GetAttribute("");
//checks that the element is visible. An element can be visible but not currently in the DOM (such as popup dialogs) which is why I added trying to access the IWebElement.
if (iwe.Displayed)
{
return iwe;
}
return null;
}
// It internally Throws a NoSuchElementException if the element does not exist. Return null to the user for the Wait.Until() function.
catch (NoSuchElementException)
{
return null;
}
The issue I am having the click method actually "passes" the wait function even though it has not actually been clicked so the browser recognizes it. this same issue can be seen manually when you try to click a link before the page is fully loaded. Sometimes it will not register that mouseclick because internet is going slow. (At least I have seen this in the past).
Update 2: Issue identified I have narrowed the problem further.
I get random errors like Nullreference or StaleElementException (element no longer exists). What is happening is in the widget when I click submit, it begins unloading the dialog and refocuses on the main page. I noticed it does a quick refresh of the page.
So I would begin my code and it would "access" the page elements and randomly fail on different lines of code when the page begins the refresh. So the WaitForElement method passes but than fails later during the refresh since the elements no longer exist in the DOM for a short period.
I guess my only way to fix this is to add System waits (which I hate) as I don't want my test cases to handle this error on the front. To give the page enough time to refresh.
This could explain why the link "clikc" doesnt work as it has not refreshed its state so it ignores it until after the refresh.