From ae54dd1b5ead9da70ef760faa1f4a238f2531386 Mon Sep 17 00:00:00 2001 From: Anusree Date: Wed, 23 Aug 2017 18:29:50 +0530 Subject: [PATCH] AngularJS unittest with Jasmine and Karma Change-Id: I3e42eac041d346851d51228f5e1185d8464325e9 Co-Authored-By: Saju Madhavan Closes-Bug: 1670102 Implements: blueprint angularjs-unittest-with-jasmine-and-karma --- .gitignore | 2 + README.rst | 17 +++ .../actions/actions.module.spec.js | 49 ++++++ karma.conf.js | 141 ++++++++++++++++++ package.json | 26 ++++ test-shim.js | 110 ++++++++++++++ 6 files changed, 345 insertions(+) create mode 100644 designatedashboard/static/designatedashboard/resources/os-designate-zone/actions/actions.module.spec.js create mode 100644 karma.conf.js create mode 100644 package.json create mode 100644 test-shim.js diff --git a/.gitignore b/.gitignore index 9069827..aea1652 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ functionaltests/.testrepository/ *.ipynb /.ipynb_checkpoints/* releasenotes/build +node_modules +npm-debug.log diff --git a/README.rst b/README.rst index c3ea888..4c030ee 100644 --- a/README.rst +++ b/README.rst @@ -60,3 +60,20 @@ Howto addresses instead of a free form text field:: DESIGNATE = { 'records_use_fips': True } + + +Test +---- + +* How to run JS tests: + + * Install npm and nodejs=4.8.4 + + $ ``sudo apt-get install npm`` + $ ``curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -`` + $ ``sudo apt-get install -y nodejs`` + + 1. ``npm install`` (to create virtual environment and install all dependencies in package.json) + 2. ``npm run lint`` for eslint + 3. ``npm run test`` for JS unit tests + diff --git a/designatedashboard/static/designatedashboard/resources/os-designate-zone/actions/actions.module.spec.js b/designatedashboard/static/designatedashboard/resources/os-designate-zone/actions/actions.module.spec.js new file mode 100644 index 0000000..f4bcda2 --- /dev/null +++ b/designatedashboard/static/designatedashboard/resources/os-designate-zone/actions/actions.module.spec.js @@ -0,0 +1,49 @@ +/** + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +(function() { + 'use strict'; + + describe('zone actions module', function() { + var registry; + beforeEach(module('designatedashboard')); + + beforeEach(inject(function($injector) { + registry = $injector.get('horizon.framework.conf.resource-type-registry.service'); + })); + + it('registers Create Zone as a global action', function() { + var actions = registry.getResourceType('OS::Designate::Zone').globalActions; + expect(actionHasId(actions, 'create')).toBe(true); + }); + + it('registers Update Zone as a item action', function() { + var actions = registry.getResourceType('OS::Designate::Zone').itemActions; + expect(actionHasId(actions, 'update')).toBe(true); + }); + + function actionHasId(list, value) { + return list.filter(matchesId).length === 1; + + function matchesId(action) { + if (action.id === value) { + return true; + } + } + } + + }); + +})(); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..f437037 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,141 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var fs = require('fs'); +var path = require('path'); + +module.exports = function (config) { + // This tox venv is setup in the post-install npm step + var toxPath = '.tox/py27/lib/python2.7/site-packages/'; + var xstaticPath = toxPath + 'xstatic/pkg/'; + + config.set({ + preprocessors: { + // Used to collect templates for preprocessing. + // NOTE: the templates must also be listed in the files section below. + './static/**/*.html': ['ng-html2js'] + }, + + // Sets up module to process templates. + ngHtml2JsPreprocessor: { + prependPrefix: '/', + moduleName: 'templates' + }, + + basePath: './', + + // Contains both source and test files. + files: [ + /* + * shim, partly stolen from /i18n/js/horizon/ + * Contains expected items not provided elsewhere (dynamically by + * Django or via jasmine template. + */ + './test-shim.js', + + // from jasmine.html + xstaticPath + 'jquery/data/jquery.js', + xstaticPath + 'angular/data/angular.js', + xstaticPath + 'angular/data/angular-route.js', + xstaticPath + 'angular/data/angular-mocks.js', + xstaticPath + 'angular/data/angular-cookies.js', + xstaticPath + 'angular_bootstrap/data/angular-bootstrap.js', + xstaticPath + 'angular_gettext/data/angular-gettext.js', + xstaticPath + 'angular_fileupload/data/ng-file-upload-all.js', + xstaticPath + 'angular/data/angular-sanitize.js', + xstaticPath + 'd3/data/d3.js', + xstaticPath + 'rickshaw/data/rickshaw.js', + xstaticPath + 'angular_smart_table/data/smart-table.js', + xstaticPath + 'angular_lrdragndrop/data/lrdragndrop.js', + xstaticPath + 'spin/data/spin.js', + xstaticPath + 'spin/data/spin.jquery.js', + xstaticPath + 'tv4/data/tv4.js', + xstaticPath + 'objectpath/data/ObjectPath.js', + xstaticPath + 'angular_schema_form/data/schema-form.js', + + // TODO: These should be mocked. + toxPath + '/horizon/static/horizon/js/horizon.js', + + /** + * Include framework source code from horizon that we need. + * Otherwise, karma will not be able to find them when testing. + * These files should be mocked in the foreseeable future. + */ + toxPath + 'horizon/static/framework/**/*.module.js', + toxPath + 'horizon/static/framework/**/!(*.spec|*.mock).js', + toxPath + 'openstack_dashboard/static/**/*.module.js', + toxPath + 'openstack_dashboard/static/**/!(*.spec|*.mock).js', + toxPath + 'openstack_dashboard/dashboards/**/static/**/*.module.js', + toxPath + 'openstack_dashboard/dashboards/**/static/**/!(*.spec|*.mock).js', + + /** + * First, list all the files that defines application's angular modules. + * Those files have extension of `.module.js`. The order among them is + * not significant. + */ + './designatedashboard/static/**/*.module.js', + + /** + * Followed by other JavaScript files that defines angular providers + * on the modules defined in files listed above. And they are not mock + * files or spec files defined below. The order among them is not + * significant. + */ + './designatedashboard/static/**/!(*.spec|*.mock).js', + + /** + * Then, list files for mocks with `mock.js` extension. The order + * among them should not be significant. + */ + toxPath + 'openstack_dashboard/static/**/*.mock.js', + //'./static/**/*.mock.js', + + /** + * Finally, list files for spec with `spec.js` extension. The order + * among them should not be significant. + */ + './designatedashboard/static/**/*.spec.js', + + /** + * Angular external templates + */ + './designatedashboard/static/**/*.html', + + ], + + autoWatch: true, + + frameworks: ['jasmine'], + + browsers: ['Chrome'], + + phantomjsLauncher: { + // Have phantomjs exit if a ResourceError is encountered + // (useful if karma exits without killing phantom) + exitOnResourceError: true + }, + + reporters: ['progress'], + + plugins: [ + 'karma-chrome-launcher', + 'karma-jasmine', + 'karma-ng-html2js-preprocessor' + ] + + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..6ee7760 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "version": "0.0.0", + "private": true, + "name": "designate-dashboard", + "description": "Designate Dashboard", + "repository": "none", + "license": "Apache 2.0", + "devDependencies": { + "eslint": "1.10.3", + "eslint-config-openstack": "1.2.4", + "jasmine-core": "2.4.1", + "karma": "1.1.2", + "karma-chrome-launcher": "1.0.1", + "karma-cli": "1.0.1", + "karma-jasmine": "1.0.2", + "karma-ng-html2js-preprocessor": "1.0.0" + }, + "scripts": { + "postinstall": "if [ ! -d .venv ]; then tox -epy27 --notest; fi", + "lint": "eslint --no-color designatedashboard/static", + "lintq": "eslint --quiet designatedashboard/static", + "test": "karma start karma.conf.js --single-run" + }, + "dependencies": {} +} + diff --git a/test-shim.js b/test-shim.js new file mode 100644 index 0000000..176b1c3 --- /dev/null +++ b/test-shim.js @@ -0,0 +1,110 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +/* + * Shim for Javascript unit tests; supplying expected global features. + * This should be removed from the codebase once i18n services are provided. + * Taken from default i18n file provided by Django. + */ + +var horizonPlugInModules = []; + + +(function (globals) { + + var django = globals.django || (globals.django = {}); + + + django.pluralidx = function (count) { return (count == 1) ? 0 : 1; }; + + /* gettext identity library */ + + django.gettext = function (msgid) { return msgid; }; + django.ngettext = function (singular, plural, count) { return (count == 1) ? singular : plural; }; + django.gettext_noop = function (msgid) { return msgid; }; + django.pgettext = function (context, msgid) { return msgid; }; + django.npgettext = function (context, singular, plural, count) { return (count == 1) ? singular : plural; }; + + + django.interpolate = function (fmt, obj, named) { + if (named) { + return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); + } else { + return fmt.replace(/%s/g, function(match){return String(obj.shift())}); + } + }; + + + /* formatting library */ + + django.formats = { + "DATETIME_FORMAT": "N j, Y, P", + "DATETIME_INPUT_FORMATS": [ + "%Y-%m-%d %H:%M:%S", + "%Y-%m-%d %H:%M:%S.%f", + "%Y-%m-%d %H:%M", + "%Y-%m-%d", + "%m/%d/%Y %H:%M:%S", + "%m/%d/%Y %H:%M:%S.%f", + "%m/%d/%Y %H:%M", + "%m/%d/%Y", + "%m/%d/%y %H:%M:%S", + "%m/%d/%y %H:%M:%S.%f", + "%m/%d/%y %H:%M", + "%m/%d/%y" + ], + "DATE_FORMAT": "N j, Y", + "DATE_INPUT_FORMATS": [ + "%Y-%m-%d", + "%m/%d/%Y", + "%m/%d/%y" + ], + "DECIMAL_SEPARATOR": ".", + "FIRST_DAY_OF_WEEK": "0", + "MONTH_DAY_FORMAT": "F j", + "NUMBER_GROUPING": "3", + "SHORT_DATETIME_FORMAT": "m/d/Y P", + "SHORT_DATE_FORMAT": "m/d/Y", + "THOUSAND_SEPARATOR": ",", + "TIME_FORMAT": "P", + "TIME_INPUT_FORMATS": [ + "%H:%M:%S", + "%H:%M:%S.%f", + "%H:%M" + ], + "YEAR_MONTH_FORMAT": "F Y" + }; + + django.get_format = function (format_type) { + var value = django.formats[format_type]; + if (typeof(value) == 'undefined') { + return format_type; + } else { + return value; + } + }; + + /* add to global namespace */ + globals.pluralidx = django.pluralidx; + globals.gettext = django.gettext; + globals.ngettext = django.ngettext; + globals.gettext_noop = django.gettext_noop; + globals.pgettext = django.pgettext; + globals.npgettext = django.npgettext; + globals.interpolate = django.interpolate; + globals.get_format = django.get_format; + globals.STATIC_URL = '/static/'; + globals.WEBROOT = '/'; + +}(this));