how to resolve race conditions in webdriver - angularjs

I have an app that uses a mixture of angular and asp.net. My issue is that the home page is redirected by setting window.location and then the required data and page is requested form the server.
Previously this was not the case and all routing was done via the angular app. However due to requirements the applications routing had to be changed to what it is now.
Now because the application requires a server side request/response (I believe) this is causing a race condition in my tests as I only receive the expected result once in every 5 tests.
At present I am not able to provide code to explain my situation. However, I will be albe to provide some code in a edit later today.
The only code I can provide for now would be the test that is being run. Although I do not believe this would help without the code running the application.

Recent frameworks have this feature where it sets the document.readState of browser to complete and the content is loaded afterwards. Due to this the test may fails as we will be expecting an element to be present.
For such conditions you have to use explicit wait for the element to be present for which you want to take an action after the page is loaded or changed.

Here is an example how we wait for elements in our project (The application is also angularjs, we use Java for webdriver):
In our Webdriver implementation we added:
private WebDriverWait iWait(int timeoutInSeconds) {
return new WebDriverWait(webDriver, timeoutInSeconds);
}
we want to wait for an element to be visible ("Visibility means that the element is not only displayed but also has a height and width that is greater than 0"):
public void waitForElementToAppear(By by, int timeoutInSeconds) {
iWait(timeoutInSeconds).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.visibilityOfElementLocated(by));
}
the ExpectedConditions class provides many other out of the box condition, here are some:
elementToBeClickable
textToBePresentInElement
titleContains
elementSelectionStateToBe
for more, please look at the ExpectedConditions Javadoc
if you need to create your own conditions, you can use ExoectedCondition (no 's') class
ExpectedCondition Javadoc

Related

Why explicit wait is waiting for entire wait time even though element is visible/clickable before the wait time is over

I have given a wait time for 60 sec, and i am using wait until element to be clickable/visible but script is waiting for whole 30 secs even though the element is visible on UI and also clickable?
I tried using latest selenium version, tried using different waits also using different locators. but it did not work
The reasons could be in:
The element belongs to iframe so you need to switch to the iframe prior to attempting locating anything inside it
The element belongs to Shadow DOM so you need to locate ShadowRoot object, cast it to the WebElement and find the sub-element you want to click
Your locator is not correct, try getting the page source and saving it to a file. Once done use your favourite browser developer tools to locate the elemen
The syntax of your Explicit Wait is not correct. Check out Explicit Waits and How to use Selenium to test web applications using AJAX technology for code examples
Going forward consider adding page source and your code to your question as the chance you will get the comprehensive answer will be much higher, otherwise we have to go for "blind shots"

Cakephp 3 process code after page response

One of the requirements of the project I am working on is that I log the connections made to the site, due to the amount of processing being done to get as much information as possible I would like to process this after the page has been sent back to the user.
At the moment I am running my code in the afterFilter of my appController:
public function afterFilter(Event $event){
$log_request = new RequestsController;
$log_request->log_request();
}
I am attempting to run this in afterRender of my appController:
public function afterRender(Event $event, $viewFile){
$log_request = new RequestsController;
$log_request->log_request();
}
But I can not seem to get the code to execute or if it does then I do not know how to find out what the error being thrown is.
If somebody can point me towards an example of this being done or a concurrent method of doing this (it needs to be logged within a second of the request) I would appreciate it.
$log_request = new RequestsController; you don't instantiate controllers inside controllers. You want to learn the MVC design pattern first when using a MVC based framework or you'll end up with a non maintainable piece of horrible spaghetti code. I recommend you to do the blog tutorial to get a basic understanding.
If somebody can point me towards an example of this being done or a concurrent method of doing this (it needs to be logged within a second of the request) I would appreciate it.
Read this chapter: CakePHP Logging Taken from there:
Logging data in CakePHP is easy - the log() function is provided by the LogTrait, which is the common ancestor for many CakePHP classes. If the context is a CakePHP class (Controller, Component, View,...), you can log your data. You can also use Log::write() directly.
Add the log trait to the AppController, pass the request to the log() method and configure the logging to log these requests to whatever you prefer either in afterRender() or if you want to do it really late, do it in __destruct().

Random Popups While Automating the Webpage

I was attending an interview and he gave me the following scenarios . If I could get an hint as I could not answer the questions.
Assume that there is an application and popups keep coming up all the time. These are not times, its just random. You never know when they are going to come. How to deal with it?
Assume that the script you wrote is fine. But due to network issues the objects in the page are really slow to load or the page itself is taking long time. How do you deal with such a scenario?
Assume that I have 5-6 pages in the application. In all the pages we have certain text fields. In page 1 and Page 5 there is an object which is a text box. I see that what ever whatever identification method (css, xpath, id etc) you take, the values are same. That is duplicates. How do you deal with this scenario?
What is the basic purpose of "data provider" annotation in TestNG. In genral, what is the purpose of testng annotations?
Thanks.
Assume that the script you wrote is fine. But due to network issues the objects in the page are really slow to load or the page itself is taking long time.
How do you deal with such a scenario. In such situation, You should Wait property of Selenium. Implicit Wait or Explicit wait.
Implicit Wait -- Used for setting Timeout for Webpage loading
Driverobject.manage().timeouts().PageLoadtimeOut(units,TimeUnit.SECONDS);
Explicit Wait-- Used for setting Timeout for particular
Webelement FirefoxDriver f = new FirefoxDriver();
WebDriverWait ww = new WebDriverWait(f,Units);
ww.until(ExpectedConditions.CONDITION);
For second question, Anubhav has answered it.
For third, even if elements are same for the page1 and page5, they can be differentiated. First, switch to page to, whose text field you want to interact with, and then interact with that text field.
For forth, dataprovider is an annotation in TestNG using which you can do data driven testing and using TestNG annotations, you can manage test execution flow of your tests. For more details of dataprovider and TestNG annotation, please go here
For third, If you open 5-6 the pages in different tabs of single browser you will get such a duplication problem. That time only one page is visible to the end user. So we can differentiate that element by visibility and can interact with that element using webdriver
List<WebElement> el=driver.findElements(By.xpath("xpath of that text element"));//you can use other than xpath too to identify the elements
for(int i=0;i<el.size();i++)
{
if(el.get(i).isDisplayed())
el.get(i).sendKeys("text you want to send");//any other action you want to perform
break;
}

How do I reliably check the current page after navigation in Selenium WebDriver?

In my web tests using Selenium WebDriver and IEDriverServer.exe 2.32.3.0, I need to check the title of the current page after navigating to a certain URL. Here's the code:
_webDriver.Navigate().GoToUrl("...");
Assert.That(_webDriver.Title, Is.EqualTo("..."));
This sometimes works, but sporadically breaks - the title is not as expected (but still the one from the page before).
I've read on StackOverflow (C# Webdriver - Page Title assert fails before page loads) that IWebDriver.Title property does not auto-wait for navigation to complete (why doesn't it?), but instead you need to manually wait using the WebDriverWait API.
I implemented manual waiting for the title:
var wait = new WebDriverWait(_webDriver, TimeSpan.FromSeconds (3.0));
wait.Until(d => d.Title == expectedTitle);
However, this sometimes waits for 3 seconds, then throws a WebDriverTimeoutException. The build agent running the code is quite fast and the web site I'm testing is trivial (just starting development), so I'm quite sure that it can't really take 3 seconds to navigate. I noticed that on the other StackOverflow question, the original poster also got the WebDriverTimeoutException and just caught and ignored it.
I found that solution a little flaky, so I tried a different workaround. I gave the <title> attribute an ID in my HTML and used IWebDriver.FindElement, which is supposed to wait for the page to complete:
Assert.That(_webDriver.FindElement(By.Id(ViewIDs.Shared._Layout.Title)).Text, Is.EqualTo(page.ExpectedTitle));
At first, that seemed to work. However, it doesn't reliably, it sometimes throws:
OpenQA.Selenium.NoSuchElementException : Unable to find element with id == _Layout-title
at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Remote.RemoteWebDriver.FindElement(String mechanism, String value)
at OpenQA.Selenium.By.FindElement(ISearchContext context)
at ...
(I also tried upgrading to WebDriver/IEDriverServer 2.33.0.0; but in that version, the text of the <title> tag is always empty...)
Hence my question. How do I reliably check the current page after navigation in Selenium WebDriver? Is there a good pattern that works?
I just solved it with stuff I derived from something I found on CodeProject:
private void WaitUntilLoaded()
{
var wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(%));
wait.Until(x =>
{
return ((IJavaScriptExecutor)this.driver)
.ExecuteScript("return document.readyState").Equals("complete");
});
}
According to w3schools it works for most popular browsers.
As I presently test on Firefox I ended up on Mozilla's own page about how to recognise a page as loaded. IMHO read worth to avoid dragons.
That gave me
wait.Until(p => p.FindElement(
By.Id("somethingThatIsDisplayedWhenMyAsyncronousStuffIsFinished")
).Displayed);
which saved my day.
I have run into very similar issues. I still have not been able to tell why but often if you try to use an element without doing a isElementPresent check it will fail occasionally. My solution is mildly "expensive" but I have not found a reliable alternative as yet.
My example is in java, shouldn't be hard to translate but I don't have the libraries.
waitForElement("_Layout-title", 45);
then continue with your code
Assert.That(_webDriver.FindElement(By.Id(ViewIDs.Shared._Layout.Title)).Text, Is.EqualTo(page.ExpectedTitle));
This tries a set number of times, in this case 45, to find the element. Once id=_Layout-title is present it will continue to the next line of code and do the assert. While it isn't perfect, it did make my test much more stable.

How to get latest object in PageFactory without/with doing InitElements?

I am using PageFactory model in selenium framework (WebDriver, Java).
Test: Create an entity in application and wait until it will get complete ( To verify state of entity (completed/in-process) , I have to verify status image in-front of created entity).
Issues/Queries:
** How should I wait for specific status should get change from In-process to Complete? (As whole page is not getting refresh after completion, only that image is getting refresh – AJAX/JSON Call)
***How should I get latest page objects using PageFactory? I have tried using PageFactory.InitElements(driver, classname.class), but it’s not working.
**Is any way, we can refresh only PageFactory Cache? Like SilkTest having ‘BrowserPage.FlushCache()’?
The WebElements defined with the #FindBy annotation are effectively proxies. Every time you perform an action with the WebElement it uses the locator in the #FindBy annotation to find that element on the page again.
PageFactory.InitElements(driver, classname.class) just sets up these proxies, it doesn't actually find the elements so you don't need to keep calling it again and again.
You can cache individual WebElements by using the #CacheLookup annotation, if you use this the WebElement will be lazily evaluated the first time that you utilise it, but from that point onwards it will not be looked up again (which means you could start getting StaleElementExceptions if the element changes).
The latest information is kept in the Selenium Wiki:
http://code.google.com/p/selenium/wiki/PageFactory

Resources