{"id":13776322,"url":"https://github.com/MarketSquare/robotframework-angularjs","last_synced_at":"2025-05-11T10:30:55.833Z","repository":{"id":32344276,"uuid":"35919838","full_name":"MarketSquare/robotframework-angularjs","owner":"MarketSquare","description":"An AngularJS and Angular extension to Robotframework's SeleniumLibrary","archived":false,"fork":false,"pushed_at":"2024-02-23T04:32:56.000Z","size":189,"stargazers_count":34,"open_issues_count":4,"forks_count":20,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-12T11:02:38.391Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MarketSquare.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGES.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-05-20T02:01:22.000Z","updated_at":"2022-06-09T19:39:57.000Z","dependencies_parsed_at":"2024-06-19T09:26:43.899Z","dependency_job_id":null,"html_url":"https://github.com/MarketSquare/robotframework-angularjs","commit_stats":{"total_commits":94,"total_committers":7,"mean_commits":"13.428571428571429","dds":"0.14893617021276595","last_synced_commit":"3b3ee14e6f2433e08c2cab5647ea18ea5f4febbf"},"previous_names":["selenium2library/robotframework-angularjs"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarketSquare%2Frobotframework-angularjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarketSquare%2Frobotframework-angularjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarketSquare%2Frobotframework-angularjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarketSquare%2Frobotframework-angularjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MarketSquare","download_url":"https://codeload.github.com/MarketSquare/robotframework-angularjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253551508,"owners_count":21926308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:22.870Z","updated_at":"2025-05-11T10:30:55.447Z","avatar_url":"https://github.com/MarketSquare.png","language":"Python","funding_links":[],"categories":["Libraries"],"sub_categories":["Frameworks"],"readme":"AngularJSLibrary - robotframework-angularjs\n===========================================\nAn AngularJS and Angular extension to Robotframework's SeleniumLibrary.\nAngularJSLibrary primarily provides functionality to deal with **waiting** and\nthus timing issue when testing Angular based websites. The library does this by\nproviding first an implicit wait and, subsequently, an explicit keyword for\nwaiting on angular.\n\nAbout this library\n------------------\nThe AngularJSLibrary, despite the name including JS, supports testing against\nboth Angular 2.0+ (known as simply Angular) and Angular 1.0 (also known as\nAngular JS).\n\nThis library is considered mature and feature complete. Ongoing support is\nprovided through the Robot Framework community Slack. Thus it may appear\nto be abandoned or neglected for which it is not.\n\n**Please carefully read through this README in its entirety**. It covers how\nto configure and import the library into your test scripts, use and understand\nits key functionality, as well as troubleshooting and debugging information.\n\nInstallation\n------------\nTo install **AngularJSLibrary**, run:\n\n.. code:: bash\n\n    pip install robotframework-angularjs\n\n\nAlternatively, to install from source:\n\n.. code:: bash\n\n    python setup.py install\n\n\nIdentifying the Angular root element\n------------------------------------\nPrior to importing the library, one must identify the Angular root element or root\ncomponent. For more information about \n\nHere are a few examples of Angular sites and their corresponding root elements or\ncomponents. The first example is from the `AngularJS.org PhoneCat tutorial \u003chttp://angular.github.io/angular-phonecat/step-14/app\u003e`_.\nThe base html code is\n\n.. code::  html\n\n    \u003chtml lang=\"en\" ng-app=\"phonecatApp\"\u003e\n      \u003chead\u003e\n        \u003c!-- ... --\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n    \n        \u003cdiv class=\"view-container\"\u003e\n          \u003cdiv ng-view class=\"view-frame\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n    \n      \u003c/body\u003e\n    \u003c/html\u003e\n\nIn the PhoneCat tutorial the html element with the ng-app attribute is the root\nelement. Thus for this website the root selector would be :code:`[ng-app]`. The\nnext example is the `Getting started with Angular tutorial \u003chttps://angular.io/start\u003e`_\non angular.io site. It's main html looks like\n\n.. code::  html\n\n    \u003c!DOCTYPE html\u003e\n    \u003chtml lang=\"en\"\u003e\n      \u003chead\u003e\n        \u003c!-- ... --\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        \u003capp-root\u003e\u003c/app-root\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n\nHere the root component is the app-root element and thus the root selector for\nthis website would be :code:`app-root`. The last example is the `example tab of\nthe Dialog UI component \u003chttps://material.angular.io/cdk/dialog/examples\u003e`_\nwithin the Angular.io Component Dev Kit (CDK).\n\n.. code::  html\n\n    \u003c!DOCTYPE html\u003e\u003chtml lang=\"en-US\"\u003e\u003chead\u003e\n    \u003c!-- ... --\u003e\n    \u003c/head\u003e\n    \n\n    \u003cbody class=\"docs-app-background\"\u003e\n      \u003cmaterial-docs-app\u003e\u003c/material-docs-app\u003e\n      \u003c!-- ... --\u003e\n    \n    \u003c/body\u003e\u003c/html\u003e\n\nThe root component for the Dialog component example page is the material-docs-app\nelement. The root selector will be :code:`material-docs-app`.\n\nNow we will use the root selector when we import the library.\n\nImporting the library\n---------------------\nThe proper name for importing the library is :code:`AngularJSLibrary`. You will\nneed to include the SeleniumLibrary **before** you import the AngularJSLibrary.\nThe first of two library options is `root_selector`. So using our first example,\nthe PhoneCat tutorial from AngularJS.org above, our import may look like,\n\n.. code::  robotframework\n\n    *** Settings ***\n    Library    SeleniumLibrary\n    Library    AngularJSLibrary    root_selector=[ng-app]\n    \n    *** Test Cases ***\n    Search Through The Phone Catalog For Samsung Phones\n        Open Browser  http://angular.github.io/angular-phonecat/step-14/app  Chrome\n        Input Text  //input  Samsung\n        Click Link  Samsung Galaxy Tab™\n        Element Text Should Be    css:phone-detail h1    Samsung Galaxy Tab™\n\nAs the default value for the root_selector argument is :code:`[ng-app]`, for\nthe PhoneCat tutorial we did not need to specify the root_selector and could\nhave written the Library import as\n\n.. code::  robotframework\n\n    *** Settings ***\n    Library    SeleniumLibrary\n    Library    AngularJSLibrary\n    \n    *** Test Cases ***\n    Search Through The Phone Catalog For Samsung Phones\n        Open Browser  http://angular.github.io/angular-phonecat/step-14/app  Chrome\n        Input Text  //input  Samsung\n        Click Link  Samsung Galaxy Tab™\n        Element Text Should Be    css:phone-detail h1    Samsung Galaxy Tab™\n\n*If you get an \"Unable to find root selector ...\" error* then you should re-check\nyour root_selector. Note that unlike locators used with the SeleniumLibrary the\nroot_selector **should not** contain the css locator prefix.\n\nThe second library option, ignore_implicit_angular_wait, is a flag which when\nset to True the AngularJS Library will not wait for Angular $timeouts nor\n$http calls to complete when finding elements by locator. The default value is\nFalse.\n\n*If the application under test starts on a non angular page,* for example a\nlogin page that is not angular which leads into an angular app, then one should\nstart with the implicit angular wait turned off. For example,\n\n.. code::  robotframework\n\n    *** Settings ***\n    Library    SeleniumLibrary\n    Library    AngularJSLibrary    ignore_implicit_angular_wait=True\n    \n    *** Test Cases ***\n    Login Into Non Angular Page\n        # ...\n\nUsage of the Waiting functionality\n----------------------------------\nThe AngularJS Library provides two types of waiting: a built-in implicit wait\nthat automatically waits when using a locator strategy and then an explicit\nkeyword that one calls out or writes into their script. In the tutorial and\nexamples above the scripts there aren't any expicit wait calls. Here instead\nthe script is relying on the implicit wait which by default is turned on.\nThis means as soon as you import the library you will have waiting enabled.\n\nThis can be demostrated by importing the library with the implicit wait turned\noff and using instead the library's explicit `Wait For Angular` keyword.\n\n.. code::  robotframework\n\n    *** Settings ***\n    Library    SeleniumLibrary\n    Library    AngularJSLibrary    ignore_implicit_angular_wait=True\n    \n    *** Test Cases ***\n    Search Through The Phone Catalog For Samsung Phones\n        Open Browser  http://angular.github.io/angular-phonecat/step-14/app  Chrome\n        Wait For Angular\n        Input Text  //input  Samsung\n        Wait For Angular\n        Click Link  Samsung Galaxy Tab™\n        Wait For Angular\n        Element Text Should Be    css:phone-detail h1    Samsung Galaxy Tab™\n\nWith the implicit wait functionality it is expected that most of the situations\nwhere waiting is needed will be handled \"automatically\" by this \"hidden\" implicit\nwait. Thus if one examined your test case they would not see many, if any,\n`Wait For Angular` keywords but instead would see actions keywords with no\n\"waiting\" keywords in between actions. There are times, though, when one needs to\nexplicitly call out to wait for angular. For example when using a SeleniumLibrary\nkeyword that does not use a locator strategy, like :code:`Alert Should Be Present`\nand :code:`Page should contain`, or if you use webelement.\n\nIn addition to the option to turn off the implicit wait on library import, you\nmay turn it off using the :code:`Set Ignore Implicit Angular Wait` keyword with\nan argument of :code:`${True}`. \n\n\nUnderstanding and verifying the angular waits\n---------------------------------------------\nAlthough the waits seem like \"Magic\" they are not. Let's look into how the\nwaits are implimented and work to gain insight as to how they work. The waits,\nboth the implicit and explicit, poll what I call the \"angular queue\".\nTechnically it is checking that angular has \"finished rendering and has no\noutstanding $http or $timeout calls\". It does this by checking the\n`notifyWhenNoOutstandingRequests` function for AngularJS applications. For\nAngular applications the library is checking the `isStable` function on the\nAngular Testibility service.\n\nThis can be seen within the log file by setting the loglevel to DEBUG or TRACE.\nRerunning the PhoneCat demo (:code:`robot --loglevel DEBUG demo_phonecat.robot`)\none should see in the log file\n\n.. code::  robotframework\n\n    20:01:04.658\tINFO\tTyping text 'Samsung' into text field '//input'.\t\n    20:01:04.658\tDEBUG\tPOST http://localhost:50271/session/f75e7aaf5a00c717ae5e4af34a6ce516540611dae4b7f6079ce1a753c308cde2/execute/sync {\"script\": \"...snip...\"]}\t\n    20:01:04.661\tDEBUG\thttp://localhost:50271 \"POST /session/f75e7aaf5a00c717ae5e4af34a6ce516540611dae4b7f6079ce1a753c308cde2/execute/sync HTTP/1.1\" 200 14\t\n    20:01:04.661\tDEBUG\tRemote response: status=200 | data={\"value\":true} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})\t\n    20:01:04.661\tDEBUG\tFinished Request\t\n\nFor space reasons I snipped out the core script on the POST execute/sync line.\nOne should see these lines repeated several times over. This is the polling the\nlibrary is doing to see if the application is ready to test. It will repeat\nthis query till either it returns true or it will repeat till the \"give up\"\ntimeout. If it gives up, it will silently and gracefully fail continuing onto\nthe actions it was waiting to perform. It is important for the user of this\nlibrary to see and understand, at a basic level, this functionality. As the\nprimary usage are these implicit, and thus hidden, waits it is key to see how\nto check the library is operating properly and when it is waiting.\n\n*When using the AngularJS Library, if all waits timeout then the AngularJS\nLibrary may not wait properly with that application under test.* This,\nrecalling all previously outlined information, is telling you that the\nAngular app is constantly busy. This can happen depending on how the angular\napplication is designed. It may also affect only a portion of the application\nso it is important to test out various parts of the application.\n\nFurther debugging techniques\n----------------------------\nIn addition to using the AngularJS Library, one can use the Browser's DevTools\nas a way to test out and demonstrate the core operation of the library against\nan application. To be clear, this is not library code but similar Javascript\ncode which one uses outside of robot to exhibit, to a dev team for example,\nwhat the library is seeing when it querys the application. When viewing the\napplication under test open the DevTools, preferably under Chrome, and on the\nConsole tab type the following,\n\nIf the application is built with AngularJS or Angular 1.x then the script is\n\n.. code::  javascript\n\n    var callback = function () {console.log('*')}\n    var el = document.querySelector('[ng-app]');\n    var h = setInterval(function w4ng() {\n        console.log('.');\n        try {\n            angular.element(el).injector().get('$browser').\n                notifyWhenNoOutstandingRequests(callback);\n        } catch (err) {\n          console.log(err.message);\n          callback(err.message);\n        }\n      }, 10);\n\nFor Angular v2+ then the script is\n\n.. code::  javascript\n\n    var callback = function () {console.log('*')}\n    var el = document.querySelector('material-docs-app');\n    var h = setInterval(function w4ng() {\n        console.log('.');\n        try {\n            var readyToTest = window.getAngularTestability(el).isStable();\n        } catch (err) {\n          console.log(err.message);\n          callback(err.message);\n        }\n        if (!readyToTest) {\n          callback()\n        } else {\n          console.log('.');\n        }\n      }, 10);\n\nThis will display a :code:`.` when \"stable\". Otherwise it will show a :code:`*`\nwhen \"busy\". To shut down the javascript interval and stop this script type on\nthe console prompt :code:`clearInterval(h);`. [Chrome Browser is preferred\nbecause repeated output within its DevTools console will be displayed as a\nsingle line with a count versus a new line for each output making it much\neasier to see and read.] I have personally used this myself both in developing\nthis library as well as demonstrating to various Angular developers how a\ndesign/implementation is blocking testability.\n\nAdditional Angular Specific Locator Strategies\n-------------------------------------------------\n**Note: It is no longer recommended to use these angular specific locator\nstrategies. Although functional, the SeleniumLibrary locator strategies are more\nthan sufficient and in most cases easier to use then these strategies. For backward\ncompatablity reasons these will be left in but it is strongly recommended not to\nuse.**\n\nThe library provides three new locator strategies, including ``binding``,\n``model``, and ``repeater``.\n\nFor example, you can look for an Angular ng-binding using\n\n.. code::  robotframework\n\n    Get Text  binding={{greeting}}\n\n\nor by using partial match\n\n.. code::  robotframework\n\n    Get Text  binding=greet\n\n\nor by simply using the binding {{…}} notation\n\n.. code::  robotframework\n\n    Get Text  {{greeting}}\n\n\nOne can also find elements  by model\n\n.. code::  robotframework\n\n    Input Text  model=aboutbox  Something else to write about\n\n    \n.. role:: rf(code)\n   :language: robotframework\n\nFinally there is the strategy of find by repeat. This takes the general form of :rf:`repeater=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; using :rf:`repeater=baz in days@row[0]@column=b` is the same as :rf:`repeater=baz in days@column=b @row[0]`.\n\n\nGetting Help\n------------\nIf you need help with AngularJSLibrary, SeleniumLibrary, or Robot Framework usage, please reach out within the Robot Framework community `Slack \u003chttps://slack.robotframework.org/\u003e`_.\n\n    \nKeyword Documentation\n---------------------\nThe keyword documentation can be found on the `Github project page \u003chttps://marketsquare.github.io/robotframework-angularjs/\u003e`_.\n\n\nTesting\n-------\nFor information on how we test the AngularJSLibrary see the `Testing.rst \u003chttps://github.com/Selenium2Library/robotframework-angularjs/blob/master/TESTING.rst\u003e`_ file.\n\n\nReferences\n----------\n\n`SeleniumLibrary \u003chttps://github.com/robotframework/SeleniumLibrary\u003e`_: Web testing library for Robot Framework\n\n`Protractor \u003chttp://www.protractortest.org\u003e`_: E2E test framework for Angular apps\n\n`isStable reference \u003chttps://angular.io/api/core/ApplicationRef#is-stable-examples\u003e`_\n\n`Angular Testability service \u003chttps://angular.io/api/core/Testability\u003e`_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMarketSquare%2Frobotframework-angularjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMarketSquare%2Frobotframework-angularjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMarketSquare%2Frobotframework-angularjs/lists"}