Merge pull request #8 from ediardo/JSUnitTestsBase
Add JavaScript unit tests code base
This commit is contained in:
commit
f63308d60f
|
@ -0,0 +1,51 @@
|
|||
# Set up globals
|
||||
globals:
|
||||
angular: false
|
||||
|
||||
extends: openstack
|
||||
|
||||
# Most environment options are not explicitly enabled or disabled, only
|
||||
# included here for completeness' sake. They are commented out, because the
|
||||
# global updates.py script would otherwise override them during a global
|
||||
# requirements synchronization.
|
||||
#
|
||||
# Individual projects should choose which platforms they deploy to.
|
||||
|
||||
env:
|
||||
# browser global variables.
|
||||
browser: true
|
||||
|
||||
# Adds all of the Jasmine testing global variables for version 1.3 and 2.0.
|
||||
jasmine: true
|
||||
|
||||
|
||||
# Below we adjust rules specific to horizon's usage of openstack's linting
|
||||
# rules, and its own plugin inclusions.
|
||||
rules:
|
||||
#############################################################################
|
||||
# Disabled Rules from eslint-config-openstack
|
||||
#############################################################################
|
||||
valid-jsdoc: [1, {
|
||||
requireParamDescription: false
|
||||
}]
|
||||
no-undefined: 1
|
||||
brace-style: 1
|
||||
no-extra-parens: 1
|
||||
callback-return: 1
|
||||
block-scoped-var: 1
|
||||
quote-props: 0
|
||||
space-in-parens: 1
|
||||
no-use-before-define: 1
|
||||
no-unneeded-ternary: 1
|
||||
|
||||
#############################################################################
|
||||
# Angular Plugin Customization
|
||||
#############################################################################
|
||||
|
||||
angular/controller-as-vm:
|
||||
- 1
|
||||
- "ctrl"
|
||||
|
||||
# Remove after migrating to angular 1.4 or later.
|
||||
angular/no-cookiestore:
|
||||
- 1
|
|
@ -6,6 +6,7 @@ dist
|
|||
ChangeLog
|
||||
AUTHORS
|
||||
craton_ui.egg-info/*
|
||||
node_modules/*
|
||||
.cache
|
||||
.testrepository
|
||||
.tox
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
Craton UI for Horizon Dashboard
|
||||
===============================
|
||||
|
||||
Test
|
||||
____
|
||||
|
||||
* Python tests: `./run_test.sh`
|
||||
* JS tests:
|
||||
1. `npm install` (first do `./run_tests.sh` to create virtual environment)
|
||||
2. `npm run lint` for eslint
|
||||
3. `npm run test` for JS unit tests
|
||||
|
||||
Install
|
||||
-------
|
||||
|
|
|
@ -14,13 +14,28 @@
|
|||
|
||||
|
||||
from cratonclient.v1 import client as craton_client
|
||||
from cratonclient import session as craton_session
|
||||
|
||||
from horizon.utils.memoized import memoized # noqa
|
||||
from horizon.utils.memoized import memoized_with_request # noqa
|
||||
|
||||
from openstack_dashboard.api import base
|
||||
from six.moves.urllib import request
|
||||
|
||||
|
||||
def cratonclient():
|
||||
url = base.url_for(request, 'craton')
|
||||
c = craton_client.Client(session=request.session, url=url)
|
||||
def get_auth_params_from_request(request):
|
||||
return(
|
||||
request.user.username,
|
||||
request.user.token.id,
|
||||
request.user.tenant_id,
|
||||
base.url_for(request, 'craton')
|
||||
)
|
||||
|
||||
|
||||
@memoized_with_request(get_auth_params_from_request)
|
||||
def cratonclient(request_auth_params):
|
||||
username, token, project_id, url = request_auth_params
|
||||
session = craton_session.Session(username=username, token=token)
|
||||
c = craton_client.Client(session=session, url=url)
|
||||
return c
|
||||
|
||||
|
||||
|
@ -52,6 +67,7 @@ def region_delete(request, **kwargs):
|
|||
pass
|
||||
|
||||
|
||||
@memoized
|
||||
def region_list(request, **kwargs):
|
||||
return cratonclient(request).regions.list(**kwargs)
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class Regions(generic.View):
|
|||
@rest_utils.ajax()
|
||||
def get(self, request, **kwargs):
|
||||
"""Get all Regions."""
|
||||
regions = craton.region_list(request)
|
||||
regions = craton.region_list(request, **kwargs)
|
||||
return {'items': regions}
|
||||
|
||||
@rest_utils.ajax()
|
||||
|
|
|
@ -18,25 +18,41 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name
|
||||
* @description
|
||||
* @ngdoc service
|
||||
* @name cratonAPI
|
||||
* @param {Object} apiService
|
||||
* @param {Object} toastService
|
||||
* @description provides direct pass through craton with NO abstraction
|
||||
* @returns {Object} the service
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.app.core.openstack-service-api')
|
||||
.factory('horizon.app.core.openstack-service-api.craton', CratonAPI);
|
||||
.factory('horizon.app.core.openstack-service-api.craton', cratonAPI);
|
||||
|
||||
CratonAPI.$inject = [
|
||||
cratonAPI.$inject = [
|
||||
'horizon.framework.util.http.service',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
function CratonAPI(apiService, toastService) {
|
||||
function cratonAPI(apiService, toastService) {
|
||||
var service = {
|
||||
|
||||
getRegions: getRegions
|
||||
};
|
||||
|
||||
/**
|
||||
* @name getRegions
|
||||
* @description Gets a list of regions
|
||||
*
|
||||
* @returns {Object} an object with 'items'
|
||||
*/
|
||||
function getRegions() {
|
||||
return apiService.get('api/craton/regions')
|
||||
.error(function error() {
|
||||
toastService.add('error', gettext("Unable to get the Craton regions listing"));
|
||||
});
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* 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('Craton API', function() {
|
||||
var testCall, service;
|
||||
var apiService = {};
|
||||
var toastService = {};
|
||||
|
||||
beforeEach(
|
||||
module('horizon.mock.openstack-service-api',
|
||||
function($provide, initServices) {
|
||||
testCall = initServices($provide, apiService, toastService);
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(['horizon.app.core.openstack-service-api.craton', function(cratonAPI) {
|
||||
service = cratonAPI;
|
||||
}]));
|
||||
|
||||
it('defines the service', function() {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
var tests = [
|
||||
{
|
||||
func: "getRegions",
|
||||
method: "get",
|
||||
path: "api/craton/regions",
|
||||
error: "Unable to get the Craton regions listing"
|
||||
}
|
||||
];
|
||||
|
||||
// Iterate through the defined tests and apply as Jasmine specs.
|
||||
angular.forEach(tests, function(params) {
|
||||
it('defines the ' + params.func + ' call properly', function test() {
|
||||
var callParams = [apiService, service, toastService, params];
|
||||
testCall.apply(this, callParams);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* 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';
|
||||
|
||||
//TODO: ADD Tests!!
|
||||
|
||||
})();
|
|
@ -38,32 +38,32 @@
|
|||
var basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/fleet_management/';
|
||||
$provide.constant('horizon.dashboard.project.fleet_management.basePath', basePath);
|
||||
|
||||
var regions = '/project/regions',
|
||||
taskflows = '/project/fleet/taskflows',
|
||||
alerts = '/project/fleet/alerts',
|
||||
auditor = '/project/fleet/auditor',
|
||||
reporting = '/project/fleet/reporting',
|
||||
inventory = '/project/fleet/inventory';
|
||||
var regions = '/project/regions';
|
||||
var taskflows = '/project/fleet/taskflows';
|
||||
var alerts = '/project/fleet/alerts';
|
||||
var auditor = '/project/fleet/auditor';
|
||||
var reporting = '/project/fleet/reporting';
|
||||
var inventory = '/project/fleet/inventory';
|
||||
|
||||
$routeProvider
|
||||
.when(regions, {
|
||||
templateUrl: basePath + 'regions/index.html'
|
||||
}).
|
||||
when(taskflows, {
|
||||
})
|
||||
.when(taskflows, {
|
||||
templateUrl: basePath + 'taskflows/index.html'
|
||||
}).
|
||||
when(alerts, {
|
||||
})
|
||||
.when(alerts, {
|
||||
templateUrl: basePath + 'alerts/index.html'
|
||||
}).
|
||||
when(auditor, {
|
||||
})
|
||||
.when(auditor, {
|
||||
templateUrl: basePath + 'auditor/index.html'
|
||||
}).
|
||||
when(reporting, {
|
||||
})
|
||||
.when(reporting, {
|
||||
templateUrl: basePath + 'reporting/index.html'
|
||||
}).
|
||||
when(inventory, {
|
||||
})
|
||||
.when(inventory, {
|
||||
templateUrl: basePath + 'inventory/index.html'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* 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';
|
||||
|
||||
//TODO: ADD TESTS!!
|
||||
|
||||
})();
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* 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';
|
||||
|
||||
// TODO: ADD TESTS!!
|
||||
|
||||
})();
|
|
@ -0,0 +1,190 @@
|
|||
/**
|
||||
*
|
||||
* 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) {
|
||||
var xstaticPath;
|
||||
var horizonPath;
|
||||
var openstackDashboardPath;
|
||||
var horizonRoot;
|
||||
var basePaths = [
|
||||
'./.venv',
|
||||
'./.tox/py27'
|
||||
];
|
||||
|
||||
for (var i = 0; i < basePaths.length; i++) {
|
||||
var basePath = path.resolve(basePaths[i]);
|
||||
|
||||
if (fs.existsSync(basePath)) {
|
||||
xstaticPath = basePath + '/lib/python2.7/site-packages/xstatic/pkg/';
|
||||
horizonRoot = basePath + '/src/horizon/';
|
||||
horizonPath = basePath + '/src/horizon/horizon/';
|
||||
openstackDashboardPath = basePath + '/src/horizon/openstack_dashboard/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xstaticPath) {
|
||||
console.error('xStatic libraries not found, please set up venv');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
config.set({
|
||||
preprocessors: {
|
||||
// Used to collect templates for preprocessing.
|
||||
// NOTE: the templates must also be listed in the files section below.
|
||||
'./**/*.html': ['ng-html2js'],
|
||||
// Used to indicate files requiring coverage reports.
|
||||
'./craton_dashboard/static/**/!(*.spec).js': ['coverage']
|
||||
},
|
||||
|
||||
// Sets up module to process templates.
|
||||
ngHtml2JsPreprocessor: {
|
||||
moduleName: 'templates',
|
||||
cacheIdFromPath: function(filepath) {
|
||||
// This function takes the raw provided path from the file searches
|
||||
// below (in the files: pattern list), applies the filter from the
|
||||
// preprocessor above (basically, finds the html files), then uses
|
||||
// this function to translate the relative file path into a path
|
||||
// that matches what would actually be called in production.
|
||||
//
|
||||
// e.g.
|
||||
// dashboards/project/static/dashboard/project/workflow/launch-instance/configuration/load-edit.html
|
||||
// becomes:
|
||||
// /static/dashboard/project/workflow/launch-instance/configuration/load-edit.html
|
||||
// We can't just use stripPrefix because there are a couple of
|
||||
// prefixes that need to be altered (and may be more).
|
||||
return filepath.replace(/^dashboards\/[^\/]+/, '')
|
||||
.replace(/^static\/app/, '/static/app');
|
||||
},
|
||||
},
|
||||
|
||||
// This establishes the base for most referenced paths as being relative
|
||||
// to this file, i.e. ./craton_dashboard.
|
||||
basePath: '.',
|
||||
|
||||
// Contains both source and test files.
|
||||
files: [
|
||||
|
||||
// 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',
|
||||
|
||||
/**
|
||||
* Include framework source code from horizon and openstack_dashboard
|
||||
* that we need.
|
||||
* Otherwise, karma will not be able to find them when testing.
|
||||
* These files should be mocked in the foreseeable future.
|
||||
* These are located within the project's ./.venv/horizon directory.
|
||||
*/
|
||||
|
||||
// Getting horizon's test-shim.js for gettext modules and others
|
||||
horizonRoot + 'test-shim.js',
|
||||
|
||||
horizonPath + 'static/horizon/js/horizon.js',
|
||||
horizonPath + 'static/framework/**/*.module.js',
|
||||
horizonPath + 'static/framework/**/!(*.spec|*.mock).js',
|
||||
openstackDashboardPath + 'static/app/**/*.module.js',
|
||||
openstackDashboardPath + 'static/app/**/!(*.spec|*.mock).js',
|
||||
openstackDashboardPath + 'static/app/**/*.mock.js',
|
||||
openstackDashboardPath + 'dashboards/**/static/**/**/*.module.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.
|
||||
*/
|
||||
'./craton_dashboard/static/app/core/**/*.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.
|
||||
*/
|
||||
'./craton_dashboard/static/app/core/**/!(*.spec|*.mock).js',
|
||||
|
||||
/**
|
||||
* Then, list files for mocks with `mock.js` extension. The order
|
||||
* among them should not be significant.
|
||||
*/
|
||||
'./craton_dashboard/static/app/core/**/*.mock.js',
|
||||
|
||||
/**
|
||||
* Finally, list files for spec with `spec.js` extension. The order
|
||||
* among them should not be significant.
|
||||
*/
|
||||
'./craton_dashboard/static/app/core/**/*.spec.js',
|
||||
|
||||
/**
|
||||
* Angular external templates
|
||||
*/
|
||||
'./craton_dashboard/static/app/core/**/*.html'
|
||||
],
|
||||
|
||||
autoWatch: true,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers: ['Chrome'],
|
||||
|
||||
browserNoActivityTimeout: 60000,
|
||||
|
||||
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/craton_dashboard'
|
||||
},
|
||||
|
||||
// Coverage threshold values.
|
||||
thresholdReporter: {
|
||||
statements: 1, // target 100
|
||||
branches: 1, // target 100
|
||||
functions: 1, // target 100
|
||||
lines: 1 // target 100
|
||||
}
|
||||
});
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"name": "craton-dashboard",
|
||||
"description": "OpenStack Craton Dashboard - Angular",
|
||||
"repository": "none",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
"eslint": "1.10.3",
|
||||
"eslint-config-openstack": "1.2.4",
|
||||
"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 .venv ]; then tox -epy27 --notest; fi",
|
||||
"test": "karma start ./karma.conf.js --single-run",
|
||||
"lint": "eslint --no-color craton_dashboard/static",
|
||||
"lintq": "eslint --quiet craton_dashboard/static"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular": "1.5.8"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue