Package: robotframework-angularjs
An AngularJS and Angular extension to Robotframework’s SeleniumLibrary.
AngularJSLibrary primarily provides functionality to deal withwaitingand
thus timing issue when testing Angular based websites. The library does this by
providing first an implicit wait and, subsequently, an explicit keyword for
waiting on angular.About this libraryThe AngularJSLibrary, despite the name including JS, supports testing against
both Angular 2.0+ (known as simply Angular) and Angular 1.0 (also known as
Angular JS).This library is considered mature and feature complete. Ongoing support is
provided through the Robot Framework community Slack. Thus it may appear
to be abandoned or neglected for which it is not.Please carefully read through this README in its entirety. It covers how
to configure and import the library into your test scripts, use and understand
its key functionality, as well as troubleshooting and debugging information.InstallationTo installAngularJSLibrary, run:pipinstallrobotframework-angularjsAlternatively, to install from source:pythonsetup.pyinstallIdentifying the Angular root elementPrior to importing the library, one must identify the Angular root element or root
component. For more information aboutHere are a few examples of Angular sites and their corresponding root elements or
components. The first example is from theAngularJS.org PhoneCat tutorial.
The base html code is<htmllang="en"ng-app="phonecatApp"><head><!-- ... --></head><body><divclass="view-container"><divng-viewclass="view-frame"></div></div></body></html>In the PhoneCat tutorial the html element with the ng-app attribute is the root
element. Thus for this website the root selector would be[ng-app]. The
next example is theGetting started with Angular tutorialon angular.io site. It’s main html looks like<!DOCTYPE html><htmllang="en"><head><!-- ... --></head><body><app-root></app-root></body></html>Here the root component is the app-root element and thus the root selector for
this website would beapp-root. The last example is theexample tab of
the Dialog UI componentwithin the Angular.io Component Dev Kit (CDK).<!DOCTYPE html><htmllang="en-US"><head><!-- ... --></head><bodyclass="docs-app-background"><material-docs-app></material-docs-app><!-- ... --></body></html>The root component for the Dialog component example page is the material-docs-app
element. The root selector will bematerial-docs-app.Now we will use the root selector when we import the library.Importing the libraryThe proper name for importing the library isAngularJSLibrary. You will
need to include the SeleniumLibrarybeforeyou import the AngularJSLibrary.
The first of two library options isroot_selector. So using our first example,
the PhoneCat tutorial from AngularJS.org above, our import may look like,*** Settings ***LibrarySeleniumLibraryLibraryAngularJSLibraryroot_selector=[ng-app]*** Test Cases ***Search Through The Phone Catalog For Samsung PhonesOpen Browserhttp://angular.github.io/angular-phonecat/step-14/appChromeInput Text//inputSamsungClick LinkSamsung Galaxy Tab™Element Text Should Becss:phone-detail h1Samsung Galaxy Tab™As the default value for the root_selector argument is[ng-app], for
the PhoneCat tutorial we did not need to specify the root_selector and could
have written the Library import as*** Settings ***LibrarySeleniumLibraryLibraryAngularJSLibrary*** Test Cases ***Search Through The Phone Catalog For Samsung PhonesOpen Browserhttp://angular.github.io/angular-phonecat/step-14/appChromeInput Text//inputSamsungClick LinkSamsung Galaxy Tab™Element Text Should Becss:phone-detail h1Samsung Galaxy Tab™If you get an “Unable to find root selector …” errorthen you should re-check
your root_selector. Note that unlike locators used with the SeleniumLibrary the
root_selectorshould notcontain the css locator prefix.The second library option, ignore_implicit_angular_wait, is a flag which when
set to True the AngularJS Library will not wait for Angular $timeouts nor
$http calls to complete when finding elements by locator. The default value is
False.If the application under test starts on a non angular page,for example a
login page that is not angular which leads into an angular app, then one should
start with the implicit angular wait turned off. For example,*** Settings ***LibrarySeleniumLibraryLibraryAngularJSLibraryignore_implicit_angular_wait=True*** Test Cases ***Login Into Non Angular Page# ...Usage of the Waiting functionalityThe AngularJS Library provides two types of waiting: a built-in implicit wait
that automatically waits when using a locator strategy and then an explicit
keyword that one calls out or writes into their script. In the tutorial and
examples above the scripts there aren’t any expicit wait calls. Here instead
the script is relying on the implicit wait which by default is turned on.
This means as soon as you import the library you will have waiting enabled.This can be demostrated by importing the library with the implicit wait turned
off and using instead the library’s explicitWait For Angularkeyword.*** Settings ***LibrarySeleniumLibraryLibraryAngularJSLibraryignore_implicit_angular_wait=True*** Test Cases ***Search Through The Phone Catalog For Samsung PhonesOpen Browserhttp://angular.github.io/angular-phonecat/step-14/appChromeWait For AngularInput Text//inputSamsungWait For AngularClick LinkSamsung Galaxy Tab™Wait For AngularElement Text Should Becss:phone-detail h1Samsung Galaxy Tab™With the implicit wait functionality it is expected that most of the situations
where waiting is needed will be handled “automatically” by this “hidden” implicit
wait. Thus if one examined your test case they would not see many, if any,Wait For Angularkeywords but instead would see actions keywords with no
“waiting” keywords in between actions. There are times, though, when one needs to
explicitly call out to wait for angular. For example when using a SeleniumLibrary
keyword that does not use a locator strategy, likeAlert Should Be PresentandPage should contain, or if you use webelement.In addition to the option to turn off the implicit wait on library import, you
may turn it off using theSet Ignore Implicit Angular Waitkeyword with
an argument of${True}.Understanding and verifying the angular waitsAlthough the waits seem like “Magic” they are not. Let’s look into how the
waits are implimented and work to gain insight as to how they work. The waits,
both the implicit and explicit, poll what I call the “angular queue”.
Technically it is checking that angular has “finished rendering and has no
outstanding $http or $timeout calls”. It does this by checking thenotifyWhenNoOutstandingRequestsfunction for AngularJS applications. For
Angular applications the library is checking theisStablefunction on the
Angular Testibility service.This can be seen within the log file by setting the loglevel to DEBUG or TRACE.
Rerunning the PhoneCat demo (robot --loglevel DEBUG demo_phonecat.robot)
one should see in the log file20:01:04.658INFOTyping text 'Samsung' into text field '//input'.20:01:04.658DEBUGPOST http://localhost:50271/session/f75e7aaf5a00c717ae5e4af34a6ce516540611dae4b7f6079ce1a753c308cde2/execute/sync {"script": "...snip..."]}20:01:04.661DEBUGhttp://localhost:50271 "POST /session/f75e7aaf5a00c717ae5e4af34a6ce516540611dae4b7f6079ce1a753c308cde2/execute/sync HTTP/1.1" 200 1420:01:04.661DEBUGRemote response: status=200 | data={"value":true} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})20:01:04.661DEBUGFinished RequestFor space reasons I snipped out the core script on the POST execute/sync line.
One should see these lines repeated several times over. This is the polling the
library is doing to see if the application is ready to test. It will repeat
this query till either it returns true or it will repeat till the “give up”
timeout. If it gives up, it will silently and gracefully fail continuing onto
the actions it was waiting to perform. It is important for the user of this
library to see and understand, at a basic level, this functionality. As the
primary usage are these implicit, and thus hidden, waits it is key to see how
to check the library is operating properly and when it is waiting.When using the AngularJS Library, if all waits timeout then the AngularJS
Library may not wait properly with that application under test.This,
recalling all previously outlined information, is telling you that the
Angular app is constantly busy. This can happen depending on how the angular
application is designed. It may also affect only a portion of the application
so it is important to test out various parts of the application.Further debugging techniquesIn addition to using the AngularJS Library, one can use the Browser’s DevTools
as a way to test out and demonstrate the core operation of the library against
an application. To be clear, this is not library code but similar Javascript
code which one uses outside of robot to exhibit, to a dev team for example,
what the library is seeing when it querys the application. When viewing the
application under test open the DevTools, preferably under Chrome, and on the
Console tab type the following,If the application is built with AngularJS or Angular 1.x then the script isvarcallback=function(){console.log('*')}varel=document.querySelector('[ng-app]');varh=setInterval(functionw4ng(){console.log('.');try{angular.element(el).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);}catch(err){console.log(err.message);callback(err.message);}},10);For Angular v2+ then the script isvarcallback=function(){console.log('*')}varel=document.querySelector('material-docs-app');varh=setInterval(functionw4ng(){console.log('.');try{varreadyToTest=window.getAngularTestability(el).isStable();}catch(err){console.log(err.message);callback(err.message);}if(!readyToTest){callback()}else{console.log('.');}},10);This will display a.when “stable”. Otherwise it will show a*when “busy”. To shut down the javascript interval and stop this script type on
the console promptclearInterval(h);. [Chrome Browser is preferred
because repeated output within its DevTools console will be displayed as a
single line with a count versus a new line for each output making it much
easier to see and read.] I have personally used this myself both in developing
this library as well as demonstrating to various Angular developers how a
design/implementation is blocking testability.Additional Angular Specific Locator StrategiesNote: It is no longer recommended to use these angular specific locator
strategies. Although functional, the SeleniumLibrary locator strategies are more
than sufficient and in most cases easier to use then these strategies. For backward
compatablity reasons these will be left in but it is strongly recommended not to
use.The library provides three new locator strategies, includingbinding,model, andrepeater.For example, you can look for an Angular ng-binding usingGet Textbinding={{greeting}}or by using partial matchGet Textbinding=greetor by simply using the binding {{…}} notationGet Text{{greeting}}One can also find elements  by modelInput Textmodel=aboutboxSomething else to write aboutFinally there is the strategy of find by repeat. This takes the general form ofrepeater=some ngRepeat directive@row[n]@column={{ngBinding}}. Here we specify the directive as well as the row, an zero-based index, and the column, an ngBinding. Using this full format will return, if exists the element matching the directive, row and column binding.  One does not need to specify the row and column but can specify either both, one or the other or neither. In such cases the locator may return  list  of elements or even a list of list of elements. Also the ordering of row and column does not matter; usingrepeater=baz in days@row[0]@column=bis the same asrepeater=baz in days@column=b @row[0].Getting HelpIf you need help with AngularJSLibrary, SeleniumLibrary, or Robot Framework usage, please reach out within the Robot Framework communitySlack.Keyword DocumentationThe keyword documentation can be found on theGithub project page.TestingFor information on how we test the AngularJSLibrary see theTesting.rstfile.ReferencesSeleniumLibrary: Web testing library for Robot FrameworkProtractor: E2E test framework for Angular appsisStable referenceAngular Testability service