Setup JavaScript test environment

This patch sets up JavaScript test environment.
npm run test

Change-Id: Ia2b1568fb73bbedd4fd0c2f30a35c2e27a329c92
This commit is contained in:
Beth Elwell 2017-04-05 16:58:10 +01:00 committed by Julia Kreger
parent 2db9dfc3dd
commit c8b900873b
6 changed files with 288 additions and 12 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@
*.egg-info *.egg-info
dist dist
build build
cover
.eggs .eggs
eggs eggs
parts parts

View File

@ -88,8 +88,11 @@ After this, you can run ./stack.sh from the devstack directory.
The Ironic Bare Metal Provisioning plugin should now be visible in the Horizon The Ironic Bare Metal Provisioning plugin should now be visible in the Horizon
navigation. navigation.
6. Run JavaScript unit tests by visiting 6. Run JavaScript unit tests by either:
http://localhost:8000/jasmine/?spec=horizon.dashboard.admin.ironic in your
Running the tests locally with npm run test.
Visiting http://localhost:8000/jasmine/?spec=horizon.dashboard.admin.ironic in your
browser. browser.
Uninstallation Uninstallation

153
ironic_ui/karma.conf.js Normal file
View File

@ -0,0 +1,153 @@
/*
* 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';
module.exports = function (config) {
// This tox venv is setup in the post-install npm step
var toxPath = '../.tox/py27/lib/python2.7/site-packages/';
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'],
// Used to indicate files requiring coverage reports.
'./static/**/!(*.spec).js': ['coverage']
},
// 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
toxPath + 'xstatic/pkg/jquery/data/jquery.js',
toxPath + 'xstatic/pkg/angular/data/angular.js',
toxPath + 'xstatic/pkg/angular/data/angular-route.js',
toxPath + 'xstatic/pkg/angular/data/angular-mocks.js',
toxPath + 'xstatic/pkg/angular/data/angular-cookies.js',
toxPath + 'xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js',
toxPath + 'xstatic/pkg/angular_gettext/data/angular-gettext.js',
toxPath + 'xstatic/pkg/angular/data/angular-sanitize.js',
toxPath + 'xstatic/pkg/d3/data/d3.js',
toxPath + 'xstatic/pkg/rickshaw/data/rickshaw.js',
toxPath + 'xstatic/pkg/angular_smart_table/data/smart-table.js',
toxPath + 'xstatic/pkg/angular_lrdragndrop/data/lrdragndrop.js',
toxPath + 'xstatic/pkg/spin/data/spin.js',
toxPath + 'xstatic/pkg/spin/data/spin.jquery.js',
toxPath + 'xstatic/pkg/tv4/data/tv4.js',
toxPath + 'xstatic/pkg/objectpath/data/ObjectPath.js',
toxPath + 'xstatic/pkg/angular_schema_form/data/schema-form.js',
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.
*/
'./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.
*/
'./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',
/**
* Finally, list files for spec with `spec.js` extension. The order
* among them should not be significant.
*/
'./static/**/*.spec.js',
/**
* Angular external templates
*/
'./static/**/*.html'
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
browserNoActivityTimeout: 60000,
phantomjsLauncher: {
// Have phantomjs exit if a ResourceError is encountered
// (useful if karma exits without killing phantom)
exitOnResourceError: true
},
reporters: ['progress', 'coverage', 'threshold'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-ng-html2js-preprocessor',
'karma-coverage',
'karma-threshold-reporter'
],
// Places coverage report in HTML format in the subdirectory below.
coverageReporter: {
type: 'html',
dir: '../cover/karma/'
},
// Coverage threshold values.
thresholdReporter: {
statements: 10, // target 100
branches: 0, // target 100
functions: 10, // target 100
lines: 10 // target 100
}
});
};
}());

View File

@ -2,9 +2,6 @@
"name": "ironic-ui", "name": "ironic-ui",
"version": "1.0.0", "version": "1.0.0",
"description": "Horizon plugin for OpenStack Ironic.", "description": "Horizon plugin for OpenStack Ironic.",
"scripts": {
"lint": "eslint ./"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://git.openstack.org/openstack/ironic-ui" "url": "git://git.openstack.org/openstack/ironic-ui"
@ -12,8 +9,23 @@
"author": "Openstack <openstack-dev@lists.openstack.org>", "author": "Openstack <openstack-dev@lists.openstack.org>",
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"eslint": "^1.10.3", "eslint": "1.10.3",
"eslint-config-openstack": "^1.2.4", "eslint-config-openstack": "1.2.4",
"eslint-plugin-angular": "1.0.0" "eslint-plugin-angular": "1.0.1",
} "jasmine-core": "2.4.1",
"karma": "1.1.2",
"karma-chrome-launcher": "1.0.1",
"karma-cli": "1.0.1",
"karma-coverage": "1.1.1",
"karma-jasmine": "1.0.2",
"karma-ng-html2js-preprocessor": "1.0.0",
"karma-threshold-reporter": "0.1.15"
},
"scripts": {
"postinstall": "if [ ! -d .tox ] || [ ! -d .tox/py27 ]; then tox -epy27 --notest; fi",
"test": "karma start ironic_ui/karma.conf.js --single-run",
"lint": "eslint --no-color ironic_ui/static",
"lintq": "eslint --quiet ironic_ui/static"
},
"dependencies": {}
} }

View File

@ -2,9 +2,6 @@
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
# Require Horizon
-e git://github.com/openstack/horizon.git#egg=horizon
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0
@ -19,3 +16,5 @@ testtools>=1.4.0 # MIT
sphinx!=1.6.1,>=1.5.1 # BSD sphinx!=1.6.1,>=1.5.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0 oslosphinx>=4.7.0 # Apache-2.0
reno>=1.8.0 # Apache-2.0 reno>=1.8.0 # Apache-2.0
# Include horizon as test requirement
http://tarballs.openstack.org/horizon/horizon-master.tar.gz#egg=horizon

108
test-shim.js Normal file
View File

@ -0,0 +1,108 @@
/*
* 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));