Merge "Unit test framework for Ironic-UI API service"
This commit is contained in:
commit
911671d540
@ -58,6 +58,7 @@
|
||||
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/angular_fileupload/data/ng-file-upload-all.js',
|
||||
toxPath + 'xstatic/pkg/spin/data/spin.js',
|
||||
toxPath + 'xstatic/pkg/spin/data/spin.jquery.js',
|
||||
toxPath + 'xstatic/pkg/tv4/data/tv4.js',
|
||||
|
@ -116,70 +116,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Check whether a group contains required properties
|
||||
*
|
||||
* @param {DriverProperty[]} group - Property group
|
||||
* @return {boolean} Return true if the group contains required
|
||||
* properties, false otherwise
|
||||
*/
|
||||
function driverPropertyGroupHasRequired(group) {
|
||||
var hasRequired = false;
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
if (group[i].required) {
|
||||
hasRequired = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Convert array of driver property groups to a string
|
||||
*
|
||||
* @param {array[]} groups - Array for driver property groups
|
||||
* @return {string} Output string
|
||||
*/
|
||||
function driverPropertyGroupsToString(groups) {
|
||||
var output = [];
|
||||
angular.forEach(groups, function(group) {
|
||||
var groupStr = [];
|
||||
angular.forEach(group, function(property) {
|
||||
groupStr.push(property.name);
|
||||
});
|
||||
groupStr = groupStr.join(", ");
|
||||
output.push(['[', groupStr, ']'].join(""));
|
||||
});
|
||||
output = output.join(", ");
|
||||
return ['[', output, ']'].join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Comaprison function used to sort driver property groups
|
||||
*
|
||||
* @param {DriverProperty[]} group1 - First group
|
||||
* @param {DriverProperty[]} group2 - Second group
|
||||
* @return {integer} Return:
|
||||
* < 0 if group1 should precede group2 in an ascending ordering
|
||||
* > 0 if group2 should precede group1
|
||||
* 0 if group1 and group2 are considered equal from ordering perpsective
|
||||
*/
|
||||
function compareDriverPropertyGroups(group1, group2) {
|
||||
var group1HasRequired = driverPropertyGroupHasRequired(group1);
|
||||
var group2HasRequired = driverPropertyGroupHasRequired(group2);
|
||||
|
||||
if (group1HasRequired === group2HasRequired) {
|
||||
if (group1.length === group2.length) {
|
||||
return group1[0].name.localeCompare(group2[0].name);
|
||||
} else {
|
||||
return group1.length - group2.length;
|
||||
}
|
||||
} else {
|
||||
return group1HasRequired ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Order driver properties in the form using the following
|
||||
* rules:
|
||||
@ -190,7 +126,7 @@
|
||||
* (2) Required properties with no dependents should be located at the
|
||||
* top of the form
|
||||
*
|
||||
* @return {void}
|
||||
* @return {[]} Ordered list of groups of strongly related properties
|
||||
*/
|
||||
ctrl._sortDriverProperties = function() {
|
||||
// Build dependency graph between driver properties
|
||||
@ -235,10 +171,10 @@
|
||||
components.push(component);
|
||||
},
|
||||
groups);
|
||||
groups.sort(compareDriverPropertyGroups);
|
||||
groups.sort(baseNodeService.compareDriverPropertyGroups);
|
||||
|
||||
$log.debug("Found the following property groups: " +
|
||||
driverPropertyGroupsToString(groups));
|
||||
baseNodeService.driverPropertyGroupsToString(groups));
|
||||
return groups;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* 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('horizon.dashboard.admin.ironic.base-node', function () {
|
||||
var ironicBackendMockService, uibModalInstance;
|
||||
var ctrl = {};
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
uibModalInstance = {
|
||||
dismiss: jasmine.createSpy()
|
||||
};
|
||||
$provide.value('$uibModalInstance', uibModalInstance);
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.toast.service',
|
||||
{});
|
||||
}));
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicBackendMockService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.backend-mock.service');
|
||||
ironicBackendMockService.init();
|
||||
|
||||
var controller = $injector.get('$controller');
|
||||
controller('BaseNodeController', {ctrl: ctrl});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
ironicBackendMockService.postTest();
|
||||
});
|
||||
|
||||
it('controller should be defined', function () {
|
||||
expect(ctrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('base construction', function () {
|
||||
expect(ctrl.drivers).toBeNull();
|
||||
expect(ctrl.images).toBeNull();
|
||||
expect(ctrl.loadingDriverProperties).toBe(false);
|
||||
expect(ctrl.driverProperties).toBeNull();
|
||||
expect(ctrl.driverPropertyGroups).toBeNull();
|
||||
expect(ctrl.modalTitle).toBeDefined();
|
||||
angular.forEach(ctrl.propertyCollections, function(collection) {
|
||||
expect(Object.getOwnPropertyNames(collection).sort()).toEqual(
|
||||
PROPERTY_COLLECTION_PROPERTIES.sort());
|
||||
});
|
||||
expect(ctrl.propertyCollections)
|
||||
.toContain(jasmine.objectContaining({id: "properties"}));
|
||||
expect(ctrl.propertyCollections)
|
||||
.toContain(jasmine.objectContaining({id: "extra"}));
|
||||
expect(ctrl.node).toEqual({
|
||||
name: null,
|
||||
driver: null,
|
||||
driver_info: {},
|
||||
properties: {},
|
||||
extra: {},
|
||||
network_interface: null});
|
||||
expect(Object.getOwnPropertyNames(ctrl).sort()).toEqual(
|
||||
BASE_NODE_CONTROLLER_PROPERTIES.sort());
|
||||
});
|
||||
|
||||
it('_loadDrivers', function () {
|
||||
ctrl._loadDrivers();
|
||||
ironicBackendMockService.flush();
|
||||
expect(ctrl.drivers).toEqual(ironicBackendMockService.getDrivers());
|
||||
});
|
||||
|
||||
it('_getImages', function () {
|
||||
ctrl._getImages();
|
||||
ironicBackendMockService.flush();
|
||||
expect(ctrl.images).toEqual(ironicBackendMockService.getImages());
|
||||
});
|
||||
|
||||
it('cancel', function () {
|
||||
ctrl.cancel();
|
||||
expect(uibModalInstance.dismiss).toHaveBeenCalledWith('cancel');
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -64,7 +64,10 @@
|
||||
var service = {
|
||||
DriverProperty: DriverProperty,
|
||||
PostfixExpr: PostfixExpr,
|
||||
Graph: Graph
|
||||
Graph: Graph,
|
||||
driverPropertyGroupHasRequired: driverPropertyGroupHasRequired,
|
||||
driverPropertyGroupsToString: driverPropertyGroupsToString,
|
||||
compareDriverPropertyGroups: compareDriverPropertyGroups
|
||||
};
|
||||
|
||||
var VALID_ADDRESS_HOSTNAME_REGEX = new RegExp(VALID_IPV4_ADDRESS + "|" +
|
||||
@ -669,6 +672,70 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Check whether a group contains required properties
|
||||
*
|
||||
* @param {DriverProperty[]} group - Property group
|
||||
* @return {boolean} Return true if the group contains required
|
||||
* properties, false otherwise
|
||||
*/
|
||||
function driverPropertyGroupHasRequired(group) {
|
||||
var hasRequired = false;
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
if (group[i].required) {
|
||||
hasRequired = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Convert array of driver property groups to a string
|
||||
*
|
||||
* @param {array[]} groups - Array of driver property groups
|
||||
* @return {string} Output string
|
||||
*/
|
||||
function driverPropertyGroupsToString(groups) {
|
||||
var output = [];
|
||||
angular.forEach(groups, function(group) {
|
||||
var groupStr = [];
|
||||
angular.forEach(group, function(property) {
|
||||
groupStr.push(property.name);
|
||||
});
|
||||
groupStr = groupStr.join(", ");
|
||||
output.push(['[', groupStr, ']'].join(""));
|
||||
});
|
||||
output = output.join(", ");
|
||||
return ['[', output, ']'].join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Comaprison function used to sort driver property groups
|
||||
*
|
||||
* @param {DriverProperty[]} group1 - First group
|
||||
* @param {DriverProperty[]} group2 - Second group
|
||||
* @return {integer} Return:
|
||||
* < 0 if group1 should precede group2 in an ascending ordering
|
||||
* > 0 if group2 should precede group1
|
||||
* 0 if group1 and group2 are considered equal from ordering perpsective
|
||||
*/
|
||||
function compareDriverPropertyGroups(group1, group2) {
|
||||
var group1HasRequired = driverPropertyGroupHasRequired(group1);
|
||||
var group2HasRequired = driverPropertyGroupHasRequired(group2);
|
||||
|
||||
if (group1HasRequired === group2HasRequired) {
|
||||
if (group1.length === group2.length) {
|
||||
return group1[0].name.localeCompare(group2[0].name);
|
||||
} else {
|
||||
return group1.length - group2.length;
|
||||
}
|
||||
} else {
|
||||
return group1HasRequired ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
})();
|
||||
|
@ -224,5 +224,47 @@
|
||||
expect(ret[1]).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DriverPropertyGroup', function() {
|
||||
it('driverPropertyGroupHasRequired', function () {
|
||||
var dp1 = new service.DriverProperty("dp-1", " Required.", []);
|
||||
var dp2 = new service.DriverProperty("dp-2", " ", []);
|
||||
|
||||
expect(service.driverPropertyGroupHasRequired).toBeDefined();
|
||||
expect(service.driverPropertyGroupHasRequired([])).toBe(false);
|
||||
expect(service.driverPropertyGroupHasRequired([dp1])).toBe(true);
|
||||
expect(service.driverPropertyGroupHasRequired([dp2])).toBe(false);
|
||||
expect(service.driverPropertyGroupHasRequired([dp1, dp2])).toBe(true);
|
||||
});
|
||||
|
||||
it('driverPropertyGroupsToString', function () {
|
||||
var dp1 = new service.DriverProperty("dp-1", " Required.", []);
|
||||
var dp2 = new service.DriverProperty("dp-2", " ", []);
|
||||
|
||||
expect(service.driverPropertyGroupsToString).toBeDefined();
|
||||
expect(service.driverPropertyGroupsToString([])).toBe("[]");
|
||||
expect(service.driverPropertyGroupsToString([[dp1]]))
|
||||
.toBe("[[dp-1]]");
|
||||
expect(service.driverPropertyGroupsToString([[dp1], [dp2]]))
|
||||
.toBe("[[dp-1], [dp-2]]");
|
||||
});
|
||||
|
||||
it('compareDriverPropertyGroups', function () {
|
||||
var dp1 = new service.DriverProperty("dp-1", " Required.", []);
|
||||
var dp2 = new service.DriverProperty("dp-2", " ", []);
|
||||
|
||||
expect(service.compareDriverPropertyGroups).toBeDefined();
|
||||
expect(service.compareDriverPropertyGroups([dp1], [dp1])).toBe(0);
|
||||
expect(service.compareDriverPropertyGroups([dp1], [dp2])).toBe(-1);
|
||||
expect(service.compareDriverPropertyGroups([dp2], [dp1])).toBe(1);
|
||||
// smaller group precedes larger group
|
||||
expect(service.compareDriverPropertyGroups([dp1], [dp1, dp2]))
|
||||
.toBe(-1);
|
||||
// group order decided on lexographic comparison of names of first
|
||||
// property
|
||||
expect(service.compareDriverPropertyGroups([dp2, dp1], [dp1, dp2]))
|
||||
.toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Cray Inc.
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -67,6 +67,8 @@
|
||||
|
||||
ctrl.node[instanceInfoId] = {};
|
||||
|
||||
ctrl.node[instanceInfoId] = {};
|
||||
|
||||
init(node);
|
||||
|
||||
function init(node) {
|
||||
@ -112,7 +114,7 @@
|
||||
* @param {object} targetNode - Target node
|
||||
* @return {object[]} Array of patch instructions
|
||||
*/
|
||||
function buildPatch(sourceNode, targetNode) {
|
||||
ctrl.buildPatch = function(sourceNode, targetNode) {
|
||||
var patcher = new updatePatchService.UpdatePatch();
|
||||
var PatchItem = function PatchItem(id, path) {
|
||||
this.id = id;
|
||||
@ -132,7 +134,7 @@
|
||||
});
|
||||
|
||||
return patcher.getPatch();
|
||||
}
|
||||
};
|
||||
|
||||
ctrl.submit = function() {
|
||||
angular.forEach(ctrl.driverProperties, function(property, name) {
|
||||
@ -153,7 +155,7 @@
|
||||
$log.info("Updating node " + JSON.stringify(ctrl.baseNode));
|
||||
$log.info("to " + JSON.stringify(ctrl.node));
|
||||
|
||||
var patch = buildPatch(ctrl.baseNode, ctrl.node);
|
||||
var patch = ctrl.buildPatch(ctrl.baseNode, ctrl.node);
|
||||
$log.info("patch = " + JSON.stringify(patch.patch));
|
||||
if (patch.status === updatePatchService.UpdatePatch.status.OK) {
|
||||
ironic.updateNode(ctrl.baseNode.uuid, patch.patch).then(function(node) {
|
||||
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2015 Hewlett Packard Enterprise Development Company LP
|
||||
* Copyright 2016 Cray Inc.
|
||||
*
|
||||
* 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('horizon.dashboard.admin.ironic.edit-node', function () {
|
||||
var ironicBackendMockService, ctrl, editNode, updatePatchService;
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModalInstance', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.toast.service',
|
||||
{});
|
||||
}));
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicBackendMockService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.backend-mock.service');
|
||||
ironicBackendMockService.init();
|
||||
|
||||
updatePatchService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.update-patch.service');
|
||||
|
||||
var ironicAPI =
|
||||
$injector.get('horizon.app.core.openstack-service-api.ironic');
|
||||
ironicAPI.createNode(
|
||||
{driver: ironicBackendMockService.params.defaultDriver})
|
||||
.then(function(response) {
|
||||
editNode = response.data;
|
||||
var controller = $injector.get('$controller');
|
||||
ctrl = controller('EditNodeController', {node: editNode});
|
||||
});
|
||||
ironicBackendMockService.flush();
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
ironicBackendMockService.postTest();
|
||||
});
|
||||
|
||||
it('controller should be defined', function () {
|
||||
expect(ctrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('controller base construction', function () {
|
||||
expect(ctrl.baseNode).toEqual(
|
||||
ironicBackendMockService.getNode(editNode.uuid));
|
||||
expect(ctrl.propertyCollections)
|
||||
.toContain(jasmine.objectContaining({id: "instance_info"}));
|
||||
angular.forEach(ctrl.propertyCollections, function(collection) {
|
||||
expect(Object.getOwnPropertyNames(collection).sort()).toEqual(
|
||||
PROPERTY_COLLECTION_PROPERTIES.sort());
|
||||
});
|
||||
expect(ctrl.node.name).toEqual(editNode.name);
|
||||
expect(ctrl.node.network_interface).toEqual(editNode.network_interface);
|
||||
expect(ctrl.node.properties).toEqual(editNode.properties);
|
||||
expect(ctrl.node.extra).toEqual(editNode.extra);
|
||||
expect(ctrl.node.instance_info).toEqual(editNode.instance_info);
|
||||
expect(ctrl.node.uuid).toEqual(editNode.uuid);
|
||||
var properties = angular.copy(BASE_NODE_CONTROLLER_PROPERTIES);
|
||||
properties.push('baseNode',
|
||||
'buildPatch',
|
||||
'selectedDriver',
|
||||
'submit');
|
||||
|
||||
expect(Object.getOwnPropertyNames(ctrl).sort()).toEqual(
|
||||
properties.sort());
|
||||
});
|
||||
|
||||
it('buildPatch', function () {
|
||||
var patch = ctrl.buildPatch(editNode, editNode);
|
||||
expect(patch.patch).toEqual([]);
|
||||
expect(patch.status).toEqual(updatePatchService.UpdatePatch.status.OK);
|
||||
});
|
||||
});
|
||||
})();
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* 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('horizon.dashboard.admin.ironic.enroll-node', function () {
|
||||
var ironicBackendMockService, rootScope, ironicEvents, uibModalInstance;
|
||||
var ctrl = {};
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
uibModalInstance = {
|
||||
close: jasmine.createSpy()
|
||||
};
|
||||
$provide.value('$uibModalInstance', uibModalInstance);
|
||||
}));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.toast.service',
|
||||
{});
|
||||
}));
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
rootScope = $injector.get('$rootScope');
|
||||
ironicEvents = $injector.get('horizon.dashboard.admin.ironic.events');
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicBackendMockService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.backend-mock.service');
|
||||
ironicBackendMockService.init();
|
||||
|
||||
var controller = $injector.get('$controller');
|
||||
ctrl = controller('EnrollNodeController');
|
||||
ironicBackendMockService.flush();
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
ironicBackendMockService.postTest();
|
||||
});
|
||||
|
||||
it('controller should be defined', function () {
|
||||
expect(ctrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('base construction', function () {
|
||||
var properties = angular.copy(BASE_NODE_CONTROLLER_PROPERTIES);
|
||||
properties.push('submit');
|
||||
expect(Object.getOwnPropertyNames(ctrl).sort()).toEqual(
|
||||
properties.sort());
|
||||
});
|
||||
|
||||
it('submit - success', function () {
|
||||
spyOn(rootScope, '$emit');
|
||||
var nodeName = "node_" + Date.now();
|
||||
ctrl.node.name = nodeName;
|
||||
ctrl.node.driver = ironicBackendMockService.params.defaultDriver;
|
||||
ctrl.submit();
|
||||
ironicBackendMockService.flush();
|
||||
expect(rootScope.$emit)
|
||||
.toHaveBeenCalledWith(ironicEvents.ENROLL_NODE_SUCCESS);
|
||||
expect(uibModalInstance.close)
|
||||
.toHaveBeenCalledWith(ironicBackendMockService.getNode(nodeName));
|
||||
});
|
||||
});
|
||||
})();
|
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* © Copyright 2015,2016 Hewlett Packard Enterprise Development Company LP
|
||||
* © Copyright 2016 Cray Inc.
|
||||
*
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* @description Service that provides a mock for the Ironic backend.
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.admin.ironic')
|
||||
.factory('horizon.dashboard.admin.ironic.backend-mock.service',
|
||||
ironicBackendMockService);
|
||||
|
||||
ironicBackendMockService.$inject = [
|
||||
'$httpBackend',
|
||||
'horizon.framework.util.uuid.service'
|
||||
];
|
||||
|
||||
function ironicBackendMockService($httpBackend, uuidService) {
|
||||
// Default node object.
|
||||
var defaultNode = {
|
||||
chassis_uuid: null,
|
||||
clean_step: {},
|
||||
console_enabled: false,
|
||||
driver: undefined,
|
||||
driver_info: {},
|
||||
driver_internal_info: {},
|
||||
extra: {},
|
||||
inspection_finished_at: null,
|
||||
inspection_started_at: null,
|
||||
instance_info: {},
|
||||
instance_uuid: null,
|
||||
last_error: null,
|
||||
maintenance: false,
|
||||
maintenance_reason: null,
|
||||
name: null,
|
||||
network_interface: "flat",
|
||||
power_state: null,
|
||||
properties: {},
|
||||
provision_state: "enroll",
|
||||
provision_updated_at: null,
|
||||
raid_config: {},
|
||||
reservation: null,
|
||||
resource_class: null,
|
||||
target_power_state: null,
|
||||
target_provision_state: null,
|
||||
target_raid_config: {},
|
||||
updated_at: null,
|
||||
uuid: undefined
|
||||
};
|
||||
|
||||
// Value of the next available system port
|
||||
var nextAvailableSystemPort = 1024;
|
||||
|
||||
// Additional service parameters
|
||||
var params = {
|
||||
// Currently, all nodes have the same boot device.
|
||||
bootDevice: {boot_device: 'pxe', persistent: true},
|
||||
// Console info
|
||||
consoleType: "shellinabox",
|
||||
consoleUrl: "http://localhost:",
|
||||
defaultDriver: "agent_ipmitool"
|
||||
};
|
||||
|
||||
// List of supported drivers
|
||||
var drivers = [{name: params.defaultDriver}];
|
||||
|
||||
// List of images
|
||||
var images = [];
|
||||
|
||||
var service = {
|
||||
params: params,
|
||||
init: init,
|
||||
flush: flush,
|
||||
postTest: postTest,
|
||||
getNode: getNode,
|
||||
nodeGetConsoleUrl: nodeGetConsoleUrl,
|
||||
getDrivers: getDrivers,
|
||||
getImages: getImages
|
||||
};
|
||||
|
||||
// Dictionary of active nodes indexed by node-id (uuid and name)
|
||||
var nodes = {};
|
||||
|
||||
return service;
|
||||
|
||||
/**
|
||||
* @description Get and reserve the next available system port.
|
||||
*
|
||||
* @return {int} Port number.
|
||||
*/
|
||||
function getNextAvailableSystemPort() {
|
||||
return nextAvailableSystemPort++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Create a backend managed node.
|
||||
*
|
||||
* @param {object} params - Dictionary of parameters that define
|
||||
* the node to be created.
|
||||
* @return {object | null} Node object, or null if the nde could
|
||||
* not be created.
|
||||
*/
|
||||
function createNode(params) {
|
||||
var node = null;
|
||||
|
||||
if (angular.isDefined(params.driver)) {
|
||||
node = angular.copy(defaultNode);
|
||||
angular.forEach(params, function(value, key) {
|
||||
node[key] = value;
|
||||
});
|
||||
|
||||
if (angular.isUndefined(node.uuid)) {
|
||||
node.uuid = uuidService.generate();
|
||||
}
|
||||
|
||||
var backendNode = {
|
||||
base: node,
|
||||
consolePort: getNextAvailableSystemPort()
|
||||
};
|
||||
|
||||
nodes[node.uuid] = backendNode;
|
||||
|
||||
if (node.name !== null) {
|
||||
nodes[node.name] = backendNode;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* description Get a specified node.
|
||||
*
|
||||
* @param {string} nodeId - Uuid or name of the requested node.
|
||||
* @return {object} Base node object.
|
||||
*/
|
||||
function getNode(nodeId) {
|
||||
return angular.isDefined(nodes[nodeId]) ? nodes[nodeId].base : undefined;
|
||||
}
|
||||
|
||||
/*
|
||||
* @description Get the console-url for a specified node.
|
||||
*
|
||||
* @param {string} nodeId - Uuid or name of the node.
|
||||
* @return {string} Console url if the console is enabled, null otherwise.
|
||||
*/
|
||||
function nodeGetConsoleUrl(nodeId) {
|
||||
return nodes[nodeId].base.console_enabled
|
||||
? service.params.consoleUrl + nodes[nodeId].consolePort
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Initialize the Backend-Mock service.
|
||||
* Create the handlers that intercept http requests.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function init() {
|
||||
// Create node
|
||||
$httpBackend.whenPOST(/\/api\/ironic\/nodes\/$/)
|
||||
.respond(function(method, url, data) {
|
||||
var node = createNode(JSON.parse(data).node);
|
||||
return [node ? 200 : 400, node];
|
||||
});
|
||||
|
||||
// Delete node
|
||||
$httpBackend.whenDELETE(/\/api\/ironic\/nodes\/$/)
|
||||
.respond(function(method, url, data) {
|
||||
var nodeId = JSON.parse(data).node;
|
||||
var status = 400;
|
||||
if (angular.isDefined(nodes[nodeId])) {
|
||||
var node = nodes[nodeId].base;
|
||||
if (node.name !== null) {
|
||||
delete nodes[node.name];
|
||||
delete nodes[node.uuid];
|
||||
} else {
|
||||
delete nodes[nodeId];
|
||||
}
|
||||
status = 204;
|
||||
}
|
||||
return [status, ""];
|
||||
});
|
||||
|
||||
function _addItem(node, path, value) {
|
||||
var parts = path.substring(1).split("/");
|
||||
var leaf = parts.pop();
|
||||
var obj = node;
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
if (angular.isUndefined(obj[part])) {
|
||||
obj[part] = {};
|
||||
}
|
||||
obj = obj[part];
|
||||
}
|
||||
obj[leaf] = value;
|
||||
}
|
||||
|
||||
function _removeItem(node, path) {
|
||||
var parts = path.substring(1).split("/");
|
||||
var leaf = parts.pop();
|
||||
var obj = node;
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
obj = obj[parts[i]];
|
||||
}
|
||||
delete obj[leaf];
|
||||
}
|
||||
|
||||
function _replaceItem(node, path, value) {
|
||||
if (path === "/name" &&
|
||||
node.name !== null) {
|
||||
delete nodes[name];
|
||||
if (value !== null) {
|
||||
nodes[value] = node;
|
||||
}
|
||||
}
|
||||
|
||||
var parts = path.substring(1).split("/");
|
||||
var leaf = parts.pop();
|
||||
var obj = node;
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
obj = obj[parts[i]];
|
||||
}
|
||||
obj[leaf] = value;
|
||||
}
|
||||
|
||||
// Update node
|
||||
$httpBackend.whenPATCH(/\/api\/ironic\/nodes\/([^\/]+)$/,
|
||||
undefined,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(function(method, url, data, headers, params) {
|
||||
var status = 400;
|
||||
var node = service.getNode(params.nodeId);
|
||||
if (angular.isDefined(node)) {
|
||||
var patch = JSON.parse(data).patch;
|
||||
angular.forEach(patch, function(operation) {
|
||||
switch (operation.op) {
|
||||
case "add":
|
||||
_addItem(node, operation.path, operation.value);
|
||||
break;
|
||||
case "remove":
|
||||
_removeItem(node, operation.path);
|
||||
break;
|
||||
case "replace":
|
||||
_replaceItem(node, operation.path, operation.value);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
status = 200;
|
||||
}
|
||||
return [status, node];
|
||||
});
|
||||
|
||||
// Get node
|
||||
$httpBackend.whenGET(/\/api\/ironic\/nodes\/([^\/]+)$/,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(function(method, url, data, headers, params) {
|
||||
if (angular.isDefined(nodes[params.nodeId])) {
|
||||
return [200, nodes[params.nodeId].base];
|
||||
} else {
|
||||
return [400, null];
|
||||
}
|
||||
});
|
||||
|
||||
// Get console
|
||||
$httpBackend.whenGET(/\/api\/ironic\/nodes\/(.+)\/states\/console/,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(function(method, url, data, headers, params) {
|
||||
var node = nodes[params.nodeId];
|
||||
var consoleEnabled = node.base.console_enabled;
|
||||
var consoleInfo = consoleEnabled
|
||||
? {console_type: service.params.consoleType,
|
||||
url: service.params.consoleUrl + node.consolePort}
|
||||
: null;
|
||||
|
||||
var info = {
|
||||
console_enabled: consoleEnabled,
|
||||
console_info: consoleInfo};
|
||||
return [200, info];
|
||||
});
|
||||
|
||||
// Set console
|
||||
$httpBackend.whenPUT(/\/api\/ironic\/nodes\/(.+)\/states\/console/,
|
||||
undefined,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(function(method, url, data, headers, params) {
|
||||
data = JSON.parse(data);
|
||||
nodes[params.nodeId].base.console_enabled = data.enabled;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
// Get the ports belonging to a specified node
|
||||
$httpBackend.whenGET(/\/api\/ironic\/ports/)
|
||||
.respond(200, []);
|
||||
|
||||
// Get boot device
|
||||
$httpBackend.whenGET(/\/api\/ironic\/nodes\/([^\/]+)\/boot_device$/,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(200, service.params.bootDevice);
|
||||
|
||||
// Validate the interfaces associated with a specified node
|
||||
$httpBackend.whenGET(/\/api\/ironic\/nodes\/([^\/]+)\/validate$/,
|
||||
undefined,
|
||||
['nodeId'])
|
||||
.respond(200, []);
|
||||
|
||||
// Get the currently available drivers
|
||||
$httpBackend.whenGET(/\/api\/ironic\/drivers\/$/)
|
||||
.respond(200, {drivers: drivers});
|
||||
|
||||
// Get driver properties
|
||||
$httpBackend.whenGET(/\/api\/ironic\/drivers\/([^\/]+)\/properties$/,
|
||||
undefined,
|
||||
['driverName'])
|
||||
.respond(200, []);
|
||||
|
||||
// Get glance images
|
||||
$httpBackend.whenGET(/\/api\/glance\/images/)
|
||||
.respond(200, {items: images});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the list of supported drivers
|
||||
*
|
||||
* @return {[]} Array of driver objects
|
||||
*/
|
||||
function getDrivers() {
|
||||
return drivers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the list of images
|
||||
*
|
||||
* @return {[]} Array of image objects
|
||||
*/
|
||||
function getImages() {
|
||||
return images;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Flush pending requests
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function flush() {
|
||||
$httpBackend.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Post test verifications.
|
||||
* This function should be called after completion of a unit test.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function postTest() {
|
||||
$httpBackend.verifyNoOutstandingExpectation();
|
||||
$httpBackend.verifyNoOutstandingRequest();
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
322
ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js
Normal file
322
ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js
Normal file
@ -0,0 +1,322 @@
|
||||
/**
|
||||
* Copyright 2016 Cray Inc
|
||||
*
|
||||
* 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";
|
||||
|
||||
var IRONIC_API_PROPERTIES = [
|
||||
'createNode',
|
||||
'createPort',
|
||||
'deleteNode',
|
||||
'deletePort',
|
||||
'getDrivers',
|
||||
'getDriverProperties',
|
||||
'getNode',
|
||||
'getNodes',
|
||||
'getPortsWithNode',
|
||||
'getBootDevice',
|
||||
'nodeGetConsole',
|
||||
'nodeSetConsoleMode',
|
||||
'nodeSetPowerState',
|
||||
'nodeSetMaintenance',
|
||||
'setNodeProvisionState',
|
||||
'updateNode',
|
||||
'updatePort',
|
||||
'validateNode'
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Unit tests for the Ironic-UI API service
|
||||
*/
|
||||
|
||||
describe(
|
||||
'horizon.dashboard.admin.ironic.service',
|
||||
|
||||
function() {
|
||||
// Name of default driver used to create nodes.
|
||||
var ironicAPI, ironicBackendMockService, defaultDriver;
|
||||
|
||||
/**
|
||||
* @description Create a node.
|
||||
*
|
||||
* @param {object} params - Dictionary of parameters that define the node.
|
||||
* @return {promise} - Promise containing the newly created node.
|
||||
*/
|
||||
function createNode(params) {
|
||||
return ironicAPI.createNode(params)
|
||||
.then(function(response) {
|
||||
return response.data; // node
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Fail the current test
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function failTest() {
|
||||
fail();
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.toast.service', {
|
||||
add: function() {}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicBackendMockService =
|
||||
$injector.get('horizon.dashboard.admin.ironic.backend-mock.service');
|
||||
ironicBackendMockService.init();
|
||||
defaultDriver = ironicBackendMockService.params.defaultDriver;
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
ironicAPI =
|
||||
$injector.get('horizon.app.core.openstack-service-api.ironic');
|
||||
}));
|
||||
|
||||
it('defines the ironicAPI', function() {
|
||||
expect(ironicAPI).toBeDefined();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
ironicBackendMockService.postTest();
|
||||
});
|
||||
|
||||
describe('ironicAPI', function() {
|
||||
it('service API', function() {
|
||||
expect(Object.getOwnPropertyNames(ironicAPI).sort())
|
||||
.toEqual(IRONIC_API_PROPERTIES.sort());
|
||||
});
|
||||
|
||||
it('getDrivers', function() {
|
||||
ironicAPI.getDrivers()
|
||||
.then(function(drivers) {
|
||||
expect(drivers.length).toBeGreaterThan(0);
|
||||
angular.forEach(drivers, function(driver) {
|
||||
expect(driver.name).toBeDefined();
|
||||
});
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('createNode - Minimal input data', function() {
|
||||
createNode({driver: defaultDriver})
|
||||
.then(function(node) {
|
||||
expect(node.driver).toEqual(defaultDriver);
|
||||
expect(node).toEqual(ironicBackendMockService.getNode(node.uuid));
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('createNode - Missing input data', function() {
|
||||
createNode({})
|
||||
.then(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('getNode', function() {
|
||||
createNode({driver: defaultDriver})
|
||||
.then(function(node1) {
|
||||
ironicAPI.getNode(node1.uuid).then(function(node2) {
|
||||
expect(node2).toEqual(node1);
|
||||
});
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('deleteNode', function() {
|
||||
createNode({driver: defaultDriver})
|
||||
.then(function(node) {
|
||||
return ironicAPI.deleteNode(node.uuid).then(function() {
|
||||
return node;
|
||||
});
|
||||
})
|
||||
.then(function(node) {
|
||||
expect(
|
||||
ironicBackendMockService.getNode(node.uuid)).toBe(undefined);
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('deleteNode - nonexistent node', function() {
|
||||
ironicAPI.deleteNode(0)
|
||||
.then(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('updateNode - resource_class', function() {
|
||||
createNode({driver: defaultDriver})
|
||||
.then(function(node) {
|
||||
return ironicAPI.updateNode(
|
||||
node.uuid,
|
||||
[{op: "replace",
|
||||
path: "/resource_class",
|
||||
value: "some-resource-class"}]).then(
|
||||
function(node) {
|
||||
return node;
|
||||
});
|
||||
})
|
||||
.then(function(node) {
|
||||
expect(node.resource_class).toEqual("some-resource-class");
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('nodeGetConsole - console enabled', function() {
|
||||
createNode({driver: defaultDriver,
|
||||
console_enabled: true})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(true);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.nodeGetConsole(node.uuid).then(
|
||||
function(consoleData) {
|
||||
return {node: node, consoleData: consoleData};
|
||||
});
|
||||
})
|
||||
.then(function(data) {
|
||||
expect(data.consoleData.console_enabled).toEqual(true);
|
||||
expect(data.consoleData.console_info.console_type)
|
||||
.toEqual(ironicBackendMockService.params.consoleType);
|
||||
expect(data.consoleData.console_info.url)
|
||||
.toEqual(ironicBackendMockService.nodeGetConsoleUrl(
|
||||
data.node.uuid));
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('nodeGetConsole - console not enabled', function() {
|
||||
createNode({driver: defaultDriver,
|
||||
console_enabled: false})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.nodeGetConsole(node.uuid);
|
||||
})
|
||||
.then(function(consoleData) {
|
||||
expect(consoleData).toEqual(
|
||||
{console_enabled: false,
|
||||
console_info: null});
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('nodeSetConsoleMode - Toggle console mode', function() {
|
||||
createNode({driver: defaultDriver,
|
||||
console_enabled: false})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
ironicAPI.nodeSetConsoleMode(node.uuid, true);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.getNode(node.uuid);
|
||||
})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(true);
|
||||
return node;
|
||||
})
|
||||
// Toggle back
|
||||
.then(function(node) {
|
||||
ironicAPI.nodeSetConsoleMode(node.uuid, false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.getNode(node.uuid);
|
||||
})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
})
|
||||
.catch(failTest);
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('nodeSetConsoleMode - Redundant console set', function() {
|
||||
createNode({driver: defaultDriver,
|
||||
console_enabled: false})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
ironicAPI.nodeSetConsoleMode(node.uuid, false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.getNode(node.uuid);
|
||||
})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
});
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
|
||||
it('getBootDevice', function() {
|
||||
createNode({driver: defaultDriver})
|
||||
.then(function(node) {
|
||||
expect(node.console_enabled).toEqual(false);
|
||||
return node;
|
||||
})
|
||||
.then(function(node) {
|
||||
return ironicAPI.getBootDevice(node.uuid)
|
||||
.then(function(bootDevice) {
|
||||
return bootDevice;
|
||||
});
|
||||
})
|
||||
.then(function(bootDevice) {
|
||||
expect(bootDevice).toEqual(
|
||||
ironicBackendMockService.params.bootDevice);
|
||||
});
|
||||
|
||||
ironicBackendMockService.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
52
ironic_ui/static/dashboard/admin/ironic/test-data.spec.js
Normal file
52
ironic_ui/static/dashboard/admin/ironic/test-data.spec.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2017 Cray Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
@description Global data used by unit tests.
|
||||
*/
|
||||
|
||||
/* exported BASE_NODE_CONTROLLER_PROPERTIES */
|
||||
|
||||
var BASE_NODE_CONTROLLER_PROPERTIES = [
|
||||
'_getImages',
|
||||
'_loadDrivers',
|
||||
'_sortDriverProperties',
|
||||
'cancel',
|
||||
'collectionCheckPropertyUnique',
|
||||
'collectionDeleteProperty',
|
||||
'driverProperties',
|
||||
'driverPropertyGroups',
|
||||
'drivers',
|
||||
'images',
|
||||
'isDriverPropertyActive',
|
||||
'loadDriverProperties',
|
||||
'loadingDriverProperties',
|
||||
'modalTitle',
|
||||
'node',
|
||||
'propertyCollections',
|
||||
'readyToSubmit',
|
||||
'submitButtonTitle',
|
||||
'validHostNameRegex'];
|
||||
|
||||
/* exported PROPERTY_COLLECTION_PROPERTIES */
|
||||
|
||||
var PROPERTY_COLLECTION_PROPERTIES = [
|
||||
'id',
|
||||
'formId',
|
||||
'title',
|
||||
'addPrompt',
|
||||
'placeholder'
|
||||
];
|
14
releasenotes/notes/unit-test-framework-f61ad7926413bf91.yaml
Normal file
14
releasenotes/notes/unit-test-framework-f61ad7926413bf91.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A backend mock has been added that enables better unit testing of the
|
||||
Ironic API service and other Ironic-UI components. The mock utilizes
|
||||
Angular $httpbackend handlers to intercept requests targeted at the
|
||||
Ironic-UI server-side REST endpoints, and returns simulated responses.
|
||||
- |
|
||||
A number of unit tests have been developed that illustrate the use
|
||||
of the backend mock.
|
||||
- |
|
||||
Although the backend mock is a work in progress, enough
|
||||
functionality already exists to support test development for
|
||||
the current set of in-progress features.
|
Loading…
x
Reference in New Issue
Block a user