Bring the auto Sync magic of Protractor to Selenium with Java
|Its quite sometime, I have been working with Protractor, an awesome framework for e2e automated testing of AngularJS applications. There are some facts about Protractor which make it stand out in the crowd , when looking for an automated testing solution for AngularJS applications. Among those remarkable features , one is automatic synchronisation.
What it means is, we need not to write additional wait statements in our code for page loading or any XHR request to complete. There is no need of Implicit or Explicit waits at all. Just write the code without bothering about loaders or any such page loading indicators.
How Protractor does it ?
For every command we write , for example click, enter something to text field etc , Protractor calls one function which is responsible to make sure that all the angular calls are finished/done in the browser before performing that command/user event. That method is – waitForAngular. We can call this method explicitly using the ‘browser’ object.
‘waitForAngular’ method holds the JS snippet , which gets executed with the browser and confirms that everything is finished loading.
What is inside ‘waitForAngular’ function?
Well, here is the snippet:
/** * Wait until Angular has finished rendering and has * no outstanding $http calls before continuing. * * Asynchronous. * * @param {string} rootSelector The selector housing an ng-app * @param {function(string)} callback callback. If a failure occurs, it will * be passed as a parameter. */ functions.waitForAngular = function (rootSelector, callback) { var el = document.querySelector(rootSelector); try { if (!window.angular) { throw new Error('angular could not be found on the window'); } if (angular.getTestability) { angular.getTestability(el). whenStable(callback); } else { if (!angular.element(el). injector()) { throw new Error('root element (' + rootSelector + ') has no injector.' + ' this may mean it is not inside ng-app.'); } angular.element(el).injector() .get('$browser'). notifyWhenNoOutstandingRequest s(callback); } } catch (err) { callback(err.message); } };
This is a Javascript snippet which gets executed against the application under test in the browser. As the application under test already holds references/links to the Angular library , so all the dependencies of the objects mentioned in the above method are resolved from the application dependencies.
How to achieve it using Selenium Java bindings?
As the concept behind the auto synchronisation is to execute the above JS against the application under test on browser, so we would be needing JavascriptExecutor for the same. So we are going to execute the same JS snippet (inside waitForAngular function) using JavascriptExecutor.
Here is the code snippet in Java :
/** * Waits for the Angular calls to finish with browser * This method is helpful for auto synchronization * * @return Pass/Fail * @author Abhishek Swain */ public static String waitForAngular(){ try{ driver.manage().timeouts().setScriptTimeout(60, TimeUnit.SECONDS); driver.executeAsyncScript("var callback=arguments[arguments. length-1];"+" if (!window.angular) { throw new Error('angular could not be found on the window');}if (angular.getTestability) {angular.getTestability( angular.element(document.body) ).whenStable(callback); } else { if (!angular.element(angular. element(document.body)). injector()) { throw new Error('root element (' + 'body' + ') has no injector.' +' this may mean it is not inside ng-app.'); }}"+"angular.element(document. body).injector().get('$ browser'). notifyWhenNoOutstandingRequest s(callback);"); return"Pass:"; } catch(Throwable e){ System.err.println(e. getMessage()); return"Fail:"+e.getMessage(); } }
2. Root element is set to ‘document.body’, if required this can also be modified/parameterised , incase root element of the application is other than <body>, which means that AngularJS has been used in other sections/tags , but not body.
This could be helpful for people using Selenium but not Protractor to test applications built with AngularJS.
Happy Testing 🙂
- Bring the auto Sync magic of Protractor to Selenium with Java - October 23, 2015
- Restarting Appium Server could improve various server freezing issues and may improve execution time - January 20, 2015
- Appium with iOS 8 and XCode 6 : What’s new? - November 5, 2014
- REST API automation testing using Apache HttpClient – The Approach - October 3, 2014
- An Overview of mobile application : Moving forward to automation - October 1, 2014
- An introduction to REST - September 29, 2014
- Run ChromeDriver with Chrome Driver Service to reduce script execution time significantly - September 26, 2014
- Selenium WebDriver – Get Cookies from an existing session and add those to a newly instantiated WebDriver browser instance. - September 26, 2014
- Simulate Copy Paste action using Java Robot and Clipboard class - September 26, 2014
- Android : How to test if Android Application has memory leaks - August 11, 2014
-
Suresh Vemuri
-
radhika viswanath