mirror of
https://github.com/nasa/openmct.git
synced 2025-06-13 12:48:14 +00:00
Merge pull request #6 from nasa/open-1167
Review and Integrate open-1167, entanglement actions
This commit is contained in:
@ -16,6 +16,7 @@
|
|||||||
"platform/forms",
|
"platform/forms",
|
||||||
"platform/persistence/queue",
|
"platform/persistence/queue",
|
||||||
"platform/policy",
|
"platform/policy",
|
||||||
|
"platform/entanglement",
|
||||||
|
|
||||||
"example/persistence",
|
"example/persistence",
|
||||||
"example/generator"
|
"example/generator"
|
||||||
|
@ -77,7 +77,19 @@ define(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parentPersistence.persist();
|
return parentPersistence.persist().then(function () {
|
||||||
|
// Locate and return new Object in context of parent.
|
||||||
|
return parent
|
||||||
|
.useCapability('composition')
|
||||||
|
.then(function (children) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < children.length; i += 1) {
|
||||||
|
if (children[i].getId() === id) {
|
||||||
|
return children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,4 +138,4 @@ define(
|
|||||||
|
|
||||||
return CreationService;
|
return CreationService;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -34,8 +34,10 @@ define(
|
|||||||
mockQ,
|
mockQ,
|
||||||
mockLog,
|
mockLog,
|
||||||
mockParentObject,
|
mockParentObject,
|
||||||
|
mockNewObject,
|
||||||
mockMutationCapability,
|
mockMutationCapability,
|
||||||
mockPersistenceCapability,
|
mockPersistenceCapability,
|
||||||
|
mockCompositionCapability,
|
||||||
mockCapabilities,
|
mockCapabilities,
|
||||||
creationService;
|
creationService;
|
||||||
|
|
||||||
@ -69,6 +71,10 @@ define(
|
|||||||
"parentObject",
|
"parentObject",
|
||||||
[ "getId", "getCapability", "useCapability" ]
|
[ "getId", "getCapability", "useCapability" ]
|
||||||
);
|
);
|
||||||
|
mockNewObject = jasmine.createSpyObj(
|
||||||
|
"newObject",
|
||||||
|
[ "getId" ]
|
||||||
|
);
|
||||||
mockMutationCapability = jasmine.createSpyObj(
|
mockMutationCapability = jasmine.createSpyObj(
|
||||||
"mutation",
|
"mutation",
|
||||||
[ "invoke" ]
|
[ "invoke" ]
|
||||||
@ -77,9 +83,14 @@ define(
|
|||||||
"persistence",
|
"persistence",
|
||||||
[ "persist", "getSpace" ]
|
[ "persist", "getSpace" ]
|
||||||
);
|
);
|
||||||
|
mockCompositionCapability = jasmine.createSpyObj(
|
||||||
|
"composition",
|
||||||
|
["invoke"]
|
||||||
|
);
|
||||||
mockCapabilities = {
|
mockCapabilities = {
|
||||||
mutation: mockMutationCapability,
|
mutation: mockMutationCapability,
|
||||||
persistence: mockPersistenceCapability
|
persistence: mockPersistenceCapability,
|
||||||
|
composition: mockCompositionCapability
|
||||||
};
|
};
|
||||||
|
|
||||||
mockPersistenceService.createObject.andReturn(
|
mockPersistenceService.createObject.andReturn(
|
||||||
@ -93,8 +104,15 @@ define(
|
|||||||
return mockCapabilities[key].invoke(value);
|
return mockCapabilities[key].invoke(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mockPersistenceCapability.persist.andReturn(
|
||||||
|
mockPromise(true)
|
||||||
|
);
|
||||||
|
|
||||||
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
||||||
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
||||||
|
mockCompositionCapability.invoke.andReturn(
|
||||||
|
mockPromise([mockNewObject])
|
||||||
|
);
|
||||||
|
|
||||||
creationService = new CreationService(
|
creationService = new CreationService(
|
||||||
mockPersistenceService,
|
mockPersistenceService,
|
||||||
|
24
platform/entanglement/README.md
Normal file
24
platform/entanglement/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Entanglement
|
||||||
|
|
||||||
|
Entanglement is the process of moving, copying, and linking domain objects
|
||||||
|
in such a way that their relationships are impossible to discern.
|
||||||
|
|
||||||
|
This bundle provides move, copy, and link functionality. Acheiving a state of
|
||||||
|
entanglement is left up to the end user.
|
||||||
|
|
||||||
|
|
||||||
|
## Services implement logic
|
||||||
|
|
||||||
|
Each method (move, copy, link) is implemented as a service, and each service
|
||||||
|
provides two functions: `validate` and `perform`.
|
||||||
|
|
||||||
|
`validate(object, parentCandidate)` returns true if the `object` can be
|
||||||
|
move/copy/linked into the `parentCandidate`'s composition.
|
||||||
|
|
||||||
|
`perform(object, parentObject)` move/copy/links the `object` into the
|
||||||
|
`parentObject`'s composition.
|
||||||
|
|
||||||
|
## Actions implement user interactions
|
||||||
|
|
||||||
|
Actions are used to expose move/copy/link to the user. They prompt for input
|
||||||
|
where necessary, and complete the actions.
|
75
platform/entanglement/bundle.json
Normal file
75
platform/entanglement/bundle.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "Entanglement",
|
||||||
|
"description": "Tools to assist you in entangling the world of WARP.",
|
||||||
|
"configuration": {},
|
||||||
|
"extensions": {
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"key": "move",
|
||||||
|
"name": "Move",
|
||||||
|
"description": "Move object to another location.",
|
||||||
|
"glyph": "f",
|
||||||
|
"category": "contextual",
|
||||||
|
"implementation": "actions/MoveAction.js",
|
||||||
|
"depends": ["locationService", "moveService"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "copy",
|
||||||
|
"name": "Duplicate",
|
||||||
|
"description": "Duplicate object to another location.",
|
||||||
|
"glyph": "+",
|
||||||
|
"category": "contextual",
|
||||||
|
"implementation": "actions/CopyAction.js",
|
||||||
|
"depends": ["locationService", "copyService"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "link",
|
||||||
|
"name": "Create Link",
|
||||||
|
"description": "Create Link to object in another location.",
|
||||||
|
"glyph": "\u00E8",
|
||||||
|
"category": "contextual",
|
||||||
|
"implementation": "actions/LinkAction.js",
|
||||||
|
"depends": ["locationService", "linkService"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": [
|
||||||
|
],
|
||||||
|
"controllers": [
|
||||||
|
],
|
||||||
|
"capabilities": [
|
||||||
|
],
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"key": "moveService",
|
||||||
|
"name": "Move Service",
|
||||||
|
"description": "Provides a service for moving objects",
|
||||||
|
"implementation": "services/MoveService.js",
|
||||||
|
"depends": ["policyService", "linkService"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "linkService",
|
||||||
|
"name": "Link Service",
|
||||||
|
"description": "Provides a service for linking objects",
|
||||||
|
"implementation": "services/LinkService.js",
|
||||||
|
"depends": ["policyService"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "copyService",
|
||||||
|
"name": "Copy Service",
|
||||||
|
"description": "Provides a service for copying objects",
|
||||||
|
"implementation": "services/CopyService.js",
|
||||||
|
"depends": ["$q", "creationService", "policyService"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "locationService",
|
||||||
|
"name": "Location Service",
|
||||||
|
"description": "Provides a service for prompting a user for locations.",
|
||||||
|
"implementation": "services/LocationService.js",
|
||||||
|
"depends": ["dialogService"]
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
92
platform/entanglement/src/actions/CopyAction.js
Normal file
92
platform/entanglement/src/actions/CopyAction.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CopyAction is available from context menus and allows a user to
|
||||||
|
* deep copy an object to another location of their choosing.
|
||||||
|
*
|
||||||
|
* @implements Action
|
||||||
|
*/
|
||||||
|
function CopyAction(locationService, copyService, context) {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
newParent,
|
||||||
|
currentParent;
|
||||||
|
|
||||||
|
if (context.selectedObject) {
|
||||||
|
newParent = context.domainObject;
|
||||||
|
object = context.selectedObject;
|
||||||
|
} else {
|
||||||
|
object = context.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentParent = object
|
||||||
|
.getCapability('context')
|
||||||
|
.getParent();
|
||||||
|
|
||||||
|
return {
|
||||||
|
perform: function () {
|
||||||
|
|
||||||
|
if (newParent) {
|
||||||
|
return copyService
|
||||||
|
.perform(object, newParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation;
|
||||||
|
|
||||||
|
dialogTitle = [
|
||||||
|
"Duplicate ",
|
||||||
|
object.getModel().name,
|
||||||
|
" to a location"
|
||||||
|
].join("");
|
||||||
|
|
||||||
|
label = "Duplicate To";
|
||||||
|
|
||||||
|
validateLocation = function (newParent) {
|
||||||
|
return copyService
|
||||||
|
.validate(object, newParent);
|
||||||
|
};
|
||||||
|
|
||||||
|
return locationService.getLocationFromUser(
|
||||||
|
dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation,
|
||||||
|
currentParent
|
||||||
|
).then(function (newParent) {
|
||||||
|
return copyService
|
||||||
|
.perform(object, newParent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CopyAction;
|
||||||
|
}
|
||||||
|
);
|
89
platform/entanglement/src/actions/LinkAction.js
Normal file
89
platform/entanglement/src/actions/LinkAction.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LinkAction is available from context menus and allows a user to
|
||||||
|
* link an object to another location of their choosing.
|
||||||
|
*
|
||||||
|
* @implements Action
|
||||||
|
*/
|
||||||
|
function LinkAction(locationService, linkService, context) {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
newParent,
|
||||||
|
currentParent;
|
||||||
|
|
||||||
|
if (context.selectedObject) {
|
||||||
|
newParent = context.domainObject;
|
||||||
|
object = context.selectedObject;
|
||||||
|
} else {
|
||||||
|
object = context.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentParent = object
|
||||||
|
.getCapability('context')
|
||||||
|
.getParent();
|
||||||
|
|
||||||
|
return {
|
||||||
|
perform: function () {
|
||||||
|
if (newParent) {
|
||||||
|
return linkService
|
||||||
|
.perform(object, newParent);
|
||||||
|
}
|
||||||
|
var dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation;
|
||||||
|
|
||||||
|
dialogTitle = [
|
||||||
|
"Link ",
|
||||||
|
object.getModel().name,
|
||||||
|
" to a new location"
|
||||||
|
].join("");
|
||||||
|
|
||||||
|
label = "Link To";
|
||||||
|
|
||||||
|
validateLocation = function (newParent) {
|
||||||
|
return linkService
|
||||||
|
.validate(object, newParent);
|
||||||
|
};
|
||||||
|
|
||||||
|
return locationService.getLocationFromUser(
|
||||||
|
dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation,
|
||||||
|
currentParent
|
||||||
|
).then(function (newParent) {
|
||||||
|
return linkService
|
||||||
|
.perform(object, newParent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return LinkAction;
|
||||||
|
}
|
||||||
|
);
|
90
platform/entanglement/src/actions/MoveAction.js
Normal file
90
platform/entanglement/src/actions/MoveAction.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MoveAction is available from context menus and allows a user to
|
||||||
|
* move an object to another location of their choosing.
|
||||||
|
*
|
||||||
|
* @implements Action
|
||||||
|
*/
|
||||||
|
function MoveAction(locationService, moveService, context) {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
newParent,
|
||||||
|
currentParent;
|
||||||
|
|
||||||
|
if (context.selectedObject) {
|
||||||
|
newParent = context.domainObject;
|
||||||
|
object = context.selectedObject;
|
||||||
|
} else {
|
||||||
|
object = context.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentParent = object
|
||||||
|
.getCapability('context')
|
||||||
|
.getParent();
|
||||||
|
|
||||||
|
return {
|
||||||
|
perform: function () {
|
||||||
|
if (newParent) {
|
||||||
|
return moveService
|
||||||
|
.perform(object, newParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation;
|
||||||
|
|
||||||
|
dialogTitle = [
|
||||||
|
"Move ",
|
||||||
|
object.getModel().name,
|
||||||
|
" to a new location"
|
||||||
|
].join("");
|
||||||
|
|
||||||
|
label = "Move To";
|
||||||
|
|
||||||
|
validateLocation = function (newParent) {
|
||||||
|
return moveService
|
||||||
|
.validate(object, newParent);
|
||||||
|
};
|
||||||
|
|
||||||
|
return locationService.getLocationFromUser(
|
||||||
|
dialogTitle,
|
||||||
|
label,
|
||||||
|
validateLocation,
|
||||||
|
currentParent
|
||||||
|
).then(function (newParent) {
|
||||||
|
return moveService
|
||||||
|
.perform(object, newParent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MoveAction;
|
||||||
|
}
|
||||||
|
);
|
106
platform/entanglement/src/services/CopyService.js
Normal file
106
platform/entanglement/src/services/CopyService.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CopyService provides an interface for deep copying objects from one
|
||||||
|
* location to another. It also provides a method for determining if
|
||||||
|
* an object can be copied to a specific location.
|
||||||
|
*/
|
||||||
|
function CopyService($q, creationService, policyService) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* duplicateObject duplicates a `domainObject` into the composition
|
||||||
|
* of `parent`, and then duplicates the composition of
|
||||||
|
* `domainObject` into the new object.
|
||||||
|
*
|
||||||
|
* This function is a recursive deep copy.
|
||||||
|
*
|
||||||
|
* @param {DomainObject} domainObject - the domain object to
|
||||||
|
* duplicate.
|
||||||
|
* @param {DomainObject} parent - the parent domain object to
|
||||||
|
* create the duplicate in.
|
||||||
|
* @returns {Promise} A promise that is fulfilled when the
|
||||||
|
* duplicate operation has completed.
|
||||||
|
*/
|
||||||
|
function duplicateObject(domainObject, parent) {
|
||||||
|
var model = JSON.parse(JSON.stringify(domainObject.getModel()));
|
||||||
|
if (domainObject.hasCapability('composition')) {
|
||||||
|
model.composition = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return creationService
|
||||||
|
.createObject(model, parent)
|
||||||
|
.then(function (newObject) {
|
||||||
|
if (!domainObject.hasCapability('composition')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domainObject
|
||||||
|
.useCapability('composition')
|
||||||
|
.then(function (composees) {
|
||||||
|
// Duplicate composition serially to prevent
|
||||||
|
// write conflicts.
|
||||||
|
return composees.reduce(function (promise, composee) {
|
||||||
|
return promise.then(function () {
|
||||||
|
return duplicateObject(composee, newObject);
|
||||||
|
});
|
||||||
|
}, $q.when(undefined));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Returns true if `object` can be copied into
|
||||||
|
* `parentCandidate`'s composition.
|
||||||
|
*/
|
||||||
|
validate: function (object, parentCandidate) {
|
||||||
|
if (!parentCandidate || !parentCandidate.getId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getId() === object.getId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return policyService.allow(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.getCapability('type'),
|
||||||
|
object.getCapability('type')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Wrapper, @see {@link duplicateObject} for implementation.
|
||||||
|
*/
|
||||||
|
perform: function (object, parentObject) {
|
||||||
|
return duplicateObject(object, parentObject);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CopyService;
|
||||||
|
}
|
||||||
|
);
|
76
platform/entanglement/src/services/LinkService.js
Normal file
76
platform/entanglement/src/services/LinkService.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LinkService provides an interface for linking objects to additional
|
||||||
|
* locations. It also provides a method for determining if an object
|
||||||
|
* can be copied to a specific location.
|
||||||
|
*/
|
||||||
|
function LinkService(policyService) {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Returns `true` if `object` can be linked into
|
||||||
|
* `parentCandidate`'s composition.
|
||||||
|
*/
|
||||||
|
validate: function (object, parentCandidate) {
|
||||||
|
if (!parentCandidate || !parentCandidate.getId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getId() === object.getId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return policyService.allow(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.getCapability('type'),
|
||||||
|
object.getCapability('type')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Link `object` into `parentObject`'s composition.
|
||||||
|
*
|
||||||
|
* @returns {Promise} A promise that is fulfilled when the
|
||||||
|
* linking operation has completed.
|
||||||
|
*/
|
||||||
|
perform: function (object, parentObject) {
|
||||||
|
return parentObject.useCapability('mutation', function (model) {
|
||||||
|
if (model.composition.indexOf(object.getId()) === -1) {
|
||||||
|
model.composition.push(object.getId());
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
return parentObject.getCapability('persistence').persist();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return LinkService;
|
||||||
|
}
|
||||||
|
);
|
83
platform/entanglement/src/services/LocationService.js
Normal file
83
platform/entanglement/src/services/LocationService.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LocationService allows for easily prompting the user for a
|
||||||
|
* location in the root tree.
|
||||||
|
*/
|
||||||
|
function LocationService(dialogService) {
|
||||||
|
return {
|
||||||
|
/** Prompt the user to select a location. Returns a promise
|
||||||
|
* that is resolved with a domainObject representing the
|
||||||
|
* location selected by the user.
|
||||||
|
*
|
||||||
|
* @param {string} title - title of location dialog
|
||||||
|
* @param {string} label - label for location input field
|
||||||
|
* @param {function} validate - function that validates
|
||||||
|
* selections.
|
||||||
|
* @param {domainObject} initialLocation - tree location to
|
||||||
|
* display at start
|
||||||
|
* @returns {Promise} promise for a domain object.
|
||||||
|
*/
|
||||||
|
getLocationFromUser: function (title, label, validate, initialLocation) {
|
||||||
|
var formStructure,
|
||||||
|
formState;
|
||||||
|
|
||||||
|
formStructure = {
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
name: 'Location',
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
name: label,
|
||||||
|
control: "locator",
|
||||||
|
validate: validate,
|
||||||
|
key: 'location'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: title
|
||||||
|
};
|
||||||
|
|
||||||
|
formState = {
|
||||||
|
location: initialLocation
|
||||||
|
};
|
||||||
|
|
||||||
|
return dialogService
|
||||||
|
.getUserInput(formStructure, formState)
|
||||||
|
.then(function (formState) {
|
||||||
|
return formState.location;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return LocationService;
|
||||||
|
}
|
||||||
|
);
|
83
platform/entanglement/src/services/MoveService.js
Normal file
83
platform/entanglement/src/services/MoveService.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MoveService provides an interface for moving objects from one
|
||||||
|
* location to another. It also provides a method for determining if
|
||||||
|
* an object can be copied to a specific location.
|
||||||
|
*/
|
||||||
|
function MoveService(policyService, linkService) {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Returns `true` if `object` can be moved into
|
||||||
|
* `parentCandidate`'s composition.
|
||||||
|
*/
|
||||||
|
validate: function (object, parentCandidate) {
|
||||||
|
var currentParent = object
|
||||||
|
.getCapability('context')
|
||||||
|
.getParent();
|
||||||
|
|
||||||
|
if (!parentCandidate || !parentCandidate.getId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getId() === currentParent.getId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getId() === object.getId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return policyService.allow(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.getCapability('type'),
|
||||||
|
object.getCapability('type')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Move `object` into `parentObject`'s composition.
|
||||||
|
*
|
||||||
|
* @returns {Promise} A promise that is fulfilled when the
|
||||||
|
* move operation has completed.
|
||||||
|
*/
|
||||||
|
perform: function (object, parentObject) {
|
||||||
|
return linkService
|
||||||
|
.perform(object, parentObject)
|
||||||
|
.then(function () {
|
||||||
|
return object
|
||||||
|
.getCapability('action')
|
||||||
|
.perform('remove');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MoveService;
|
||||||
|
}
|
||||||
|
);
|
158
platform/entanglement/test/DomainObjectFactory.js
Normal file
158
platform/entanglement/test/DomainObjectFactory.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define, jasmine, */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef DomainObjectConfig
|
||||||
|
* @type {object}
|
||||||
|
* @property {string} [name] a name for the underlying jasmine spy
|
||||||
|
* object mockDomainObject. Used as
|
||||||
|
* @property {string} [id] initial id value for the domainOBject.
|
||||||
|
* @property {object} [model] initial values for the object's model.
|
||||||
|
* @property {object} [capabilities] an object containing
|
||||||
|
* capability definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var configObjectProps = ['model', 'capabilities'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function for ensuring an object is an instance of a
|
||||||
|
* DomainObjectConfig.
|
||||||
|
*/
|
||||||
|
function ensureValidConfigObject(config) {
|
||||||
|
if (!config || !config.hasOwnProperty) {
|
||||||
|
config = {};
|
||||||
|
}
|
||||||
|
if (!config.name) {
|
||||||
|
config.name = 'domainObject';
|
||||||
|
}
|
||||||
|
configObjectProps.forEach(function (prop) {
|
||||||
|
if (!config[prop] || !config[prop].hasOwnProperty) {
|
||||||
|
config[prop] = {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a factory function which takes a `config` object and returns
|
||||||
|
* a mock domainObject. The config object is an easy way to provide
|
||||||
|
* initial properties for the domainObject-- they can be changed at any
|
||||||
|
* time by directly modifying the domainObject's properties.
|
||||||
|
*
|
||||||
|
* @param {Object} [config] initial configuration for a domain object.
|
||||||
|
* @returns {Object} mockDomainObject
|
||||||
|
*/
|
||||||
|
function domainObjectFactory(config) {
|
||||||
|
config = ensureValidConfigObject(config);
|
||||||
|
|
||||||
|
var domainObject = jasmine.createSpyObj(config.name, [
|
||||||
|
'getId',
|
||||||
|
'getModel',
|
||||||
|
'getCapability',
|
||||||
|
'hasCapability',
|
||||||
|
'useCapability'
|
||||||
|
]);
|
||||||
|
|
||||||
|
domainObject.model = JSON.parse(JSON.stringify(config.model));
|
||||||
|
domainObject.capabilities = config.capabilities;
|
||||||
|
domainObject.id = config.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getId: Returns `domainObject.id`.
|
||||||
|
*
|
||||||
|
* @returns {string} id
|
||||||
|
*/
|
||||||
|
domainObject.getId.andCallFake(function () {
|
||||||
|
return domainObject.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getModel: Returns `domainObject.model`.
|
||||||
|
*
|
||||||
|
* @returns {object} model
|
||||||
|
*/
|
||||||
|
domainObject.getModel.andCallFake(function () {
|
||||||
|
return domainObject.model;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getCapability: returns a `capability` object defined in
|
||||||
|
* domainObject.capabilities. Returns undefined if capability
|
||||||
|
* does not exist.
|
||||||
|
*
|
||||||
|
* @param {string} capability name of the capability to return.
|
||||||
|
* @returns {*} capability object
|
||||||
|
*/
|
||||||
|
domainObject.getCapability.andCallFake(function (capability) {
|
||||||
|
if (config.capabilities.hasOwnProperty(capability)) {
|
||||||
|
return config.capabilities[capability];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hasCapability: return true if domainObject.capabilities has a
|
||||||
|
* property named `capability`, otherwise returns false.
|
||||||
|
*
|
||||||
|
* @param {string} capability name of the capability to test for
|
||||||
|
* existence of.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
domainObject.hasCapability.andCallFake(function (capability) {
|
||||||
|
return config.capabilities.hasOwnProperty(capability);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* useCapability: find a capability in domainObject.capabilities
|
||||||
|
* and call that capabilities' invoke method. If the capability
|
||||||
|
* does not have an invoke method, will throw an error.
|
||||||
|
*
|
||||||
|
* @param {string} capability name of a capability to invoke.
|
||||||
|
* @param {...*} params to pass to the capability's `invoke` method.
|
||||||
|
* @returns {*} result whatever was returned by `invoke`.
|
||||||
|
*/
|
||||||
|
domainObject.useCapability.andCallFake(function (capability) {
|
||||||
|
if (config.capabilities.hasOwnProperty(capability)) {
|
||||||
|
if (!config.capabilities[capability].invoke) {
|
||||||
|
throw new Error(
|
||||||
|
capability + ' missing invoke function.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var passThroughArgs = [].slice.call(arguments, 1);
|
||||||
|
return config
|
||||||
|
.capabilities[capability]
|
||||||
|
.invoke
|
||||||
|
.apply(null, passThroughArgs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domainObjectFactory;
|
||||||
|
}
|
||||||
|
);
|
174
platform/entanglement/test/actions/CopyActionSpec.js
Normal file
174
platform/entanglement/test/actions/CopyActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/actions/CopyAction',
|
||||||
|
'../services/MockCopyService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (CopyAction, MockCopyService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("Copy Action", function () {
|
||||||
|
|
||||||
|
var copyAction,
|
||||||
|
locationService,
|
||||||
|
locationServicePromise,
|
||||||
|
copyService,
|
||||||
|
context,
|
||||||
|
selectedObject,
|
||||||
|
selectedObjectContextCapability,
|
||||||
|
currentParent,
|
||||||
|
newParent;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||||
|
'selectedObjectContextCapability',
|
||||||
|
[
|
||||||
|
'getParent'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
selectedObject = domainObjectFactory({
|
||||||
|
name: 'selectedObject',
|
||||||
|
model: {
|
||||||
|
name: 'selectedObject'
|
||||||
|
},
|
||||||
|
capabilities: {
|
||||||
|
context: selectedObjectContextCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentParent = domainObjectFactory({
|
||||||
|
name: 'currentParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
selectedObjectContextCapability
|
||||||
|
.getParent
|
||||||
|
.andReturn(currentParent);
|
||||||
|
|
||||||
|
newParent = domainObjectFactory({
|
||||||
|
name: 'newParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
locationService = jasmine.createSpyObj(
|
||||||
|
'locationService',
|
||||||
|
[
|
||||||
|
'getLocationFromUser'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationServicePromise = jasmine.createSpyObj(
|
||||||
|
'locationServicePromise',
|
||||||
|
[
|
||||||
|
'then'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationService
|
||||||
|
.getLocationFromUser
|
||||||
|
.andReturn(locationServicePromise);
|
||||||
|
|
||||||
|
copyService = new MockCopyService();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("with context from context-action", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
domainObject: selectedObject
|
||||||
|
};
|
||||||
|
|
||||||
|
copyAction = new CopyAction(
|
||||||
|
locationService,
|
||||||
|
copyService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(copyAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when performed it", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
copyAction.perform();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("prompts for location", function () {
|
||||||
|
expect(locationService.getLocationFromUser)
|
||||||
|
.toHaveBeenCalledWith(
|
||||||
|
"Duplicate selectedObject to a location",
|
||||||
|
"Duplicate To",
|
||||||
|
jasmine.any(Function),
|
||||||
|
currentParent
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("waits for location from user", function () {
|
||||||
|
expect(locationServicePromise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("copys object to selected location", function () {
|
||||||
|
locationServicePromise
|
||||||
|
.then
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0](newParent);
|
||||||
|
|
||||||
|
expect(copyService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("with context from drag-drop", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
selectedObject: selectedObject,
|
||||||
|
domainObject: newParent
|
||||||
|
};
|
||||||
|
|
||||||
|
copyAction = new CopyAction(
|
||||||
|
locationService,
|
||||||
|
copyService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(copyAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("performs copy immediately", function () {
|
||||||
|
copyAction.perform();
|
||||||
|
expect(copyService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
174
platform/entanglement/test/actions/LinkActionSpec.js
Normal file
174
platform/entanglement/test/actions/LinkActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/actions/LinkAction',
|
||||||
|
'../services/MockLinkService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (LinkAction, MockLinkService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("Link Action", function () {
|
||||||
|
|
||||||
|
var linkAction,
|
||||||
|
locationService,
|
||||||
|
locationServicePromise,
|
||||||
|
linkService,
|
||||||
|
context,
|
||||||
|
selectedObject,
|
||||||
|
selectedObjectContextCapability,
|
||||||
|
currentParent,
|
||||||
|
newParent;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||||
|
'selectedObjectContextCapability',
|
||||||
|
[
|
||||||
|
'getParent'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
selectedObject = domainObjectFactory({
|
||||||
|
name: 'selectedObject',
|
||||||
|
model: {
|
||||||
|
name: 'selectedObject'
|
||||||
|
},
|
||||||
|
capabilities: {
|
||||||
|
context: selectedObjectContextCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentParent = domainObjectFactory({
|
||||||
|
name: 'currentParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
selectedObjectContextCapability
|
||||||
|
.getParent
|
||||||
|
.andReturn(currentParent);
|
||||||
|
|
||||||
|
newParent = domainObjectFactory({
|
||||||
|
name: 'newParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
locationService = jasmine.createSpyObj(
|
||||||
|
'locationService',
|
||||||
|
[
|
||||||
|
'getLocationFromUser'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationServicePromise = jasmine.createSpyObj(
|
||||||
|
'locationServicePromise',
|
||||||
|
[
|
||||||
|
'then'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationService
|
||||||
|
.getLocationFromUser
|
||||||
|
.andReturn(locationServicePromise);
|
||||||
|
|
||||||
|
linkService = new MockLinkService();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("with context from context-action", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
domainObject: selectedObject
|
||||||
|
};
|
||||||
|
|
||||||
|
linkAction = new LinkAction(
|
||||||
|
locationService,
|
||||||
|
linkService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(linkAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when performed it", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
linkAction.perform();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("prompts for location", function () {
|
||||||
|
expect(locationService.getLocationFromUser)
|
||||||
|
.toHaveBeenCalledWith(
|
||||||
|
"Link selectedObject to a new location",
|
||||||
|
"Link To",
|
||||||
|
jasmine.any(Function),
|
||||||
|
currentParent
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("waits for location from user", function () {
|
||||||
|
expect(locationServicePromise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("links object to selected location", function () {
|
||||||
|
locationServicePromise
|
||||||
|
.then
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0](newParent);
|
||||||
|
|
||||||
|
expect(linkService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("with context from drag-drop", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
selectedObject: selectedObject,
|
||||||
|
domainObject: newParent
|
||||||
|
};
|
||||||
|
|
||||||
|
linkAction = new LinkAction(
|
||||||
|
locationService,
|
||||||
|
linkService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(linkAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("performs link immediately", function () {
|
||||||
|
linkAction.perform();
|
||||||
|
expect(linkService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
174
platform/entanglement/test/actions/MoveActionSpec.js
Normal file
174
platform/entanglement/test/actions/MoveActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/actions/MoveAction',
|
||||||
|
'../services/MockMoveService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (MoveAction, MockMoveService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("Move Action", function () {
|
||||||
|
|
||||||
|
var moveAction,
|
||||||
|
locationService,
|
||||||
|
locationServicePromise,
|
||||||
|
moveService,
|
||||||
|
context,
|
||||||
|
selectedObject,
|
||||||
|
selectedObjectContextCapability,
|
||||||
|
currentParent,
|
||||||
|
newParent;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||||
|
'selectedObjectContextCapability',
|
||||||
|
[
|
||||||
|
'getParent'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
selectedObject = domainObjectFactory({
|
||||||
|
name: 'selectedObject',
|
||||||
|
model: {
|
||||||
|
name: 'selectedObject'
|
||||||
|
},
|
||||||
|
capabilities: {
|
||||||
|
context: selectedObjectContextCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentParent = domainObjectFactory({
|
||||||
|
name: 'currentParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
selectedObjectContextCapability
|
||||||
|
.getParent
|
||||||
|
.andReturn(currentParent);
|
||||||
|
|
||||||
|
newParent = domainObjectFactory({
|
||||||
|
name: 'newParent'
|
||||||
|
});
|
||||||
|
|
||||||
|
locationService = jasmine.createSpyObj(
|
||||||
|
'locationService',
|
||||||
|
[
|
||||||
|
'getLocationFromUser'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationServicePromise = jasmine.createSpyObj(
|
||||||
|
'locationServicePromise',
|
||||||
|
[
|
||||||
|
'then'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationService
|
||||||
|
.getLocationFromUser
|
||||||
|
.andReturn(locationServicePromise);
|
||||||
|
|
||||||
|
moveService = new MockMoveService();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("with context from context-action", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
domainObject: selectedObject
|
||||||
|
};
|
||||||
|
|
||||||
|
moveAction = new MoveAction(
|
||||||
|
locationService,
|
||||||
|
moveService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(moveAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when performed it", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
moveAction.perform();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("prompts for location", function () {
|
||||||
|
expect(locationService.getLocationFromUser)
|
||||||
|
.toHaveBeenCalledWith(
|
||||||
|
"Move selectedObject to a new location",
|
||||||
|
"Move To",
|
||||||
|
jasmine.any(Function),
|
||||||
|
currentParent
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("waits for location from user", function () {
|
||||||
|
expect(locationServicePromise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("moves object to selected location", function () {
|
||||||
|
locationServicePromise
|
||||||
|
.then
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0](newParent);
|
||||||
|
|
||||||
|
expect(moveService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("with context from drag-drop", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
context = {
|
||||||
|
selectedObject: selectedObject,
|
||||||
|
domainObject: newParent
|
||||||
|
};
|
||||||
|
|
||||||
|
moveAction = new MoveAction(
|
||||||
|
locationService,
|
||||||
|
moveService,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes happily", function () {
|
||||||
|
expect(moveAction).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("performs move immediately", function () {
|
||||||
|
moveAction.perform();
|
||||||
|
expect(moveService.perform)
|
||||||
|
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
272
platform/entanglement/test/services/CopyServiceSpec.js
Normal file
272
platform/entanglement/test/services/CopyServiceSpec.js
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect,spyOn */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/services/CopyService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (CopyService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function synchronousPromise(value) {
|
||||||
|
var promise = {
|
||||||
|
then: function (callback) {
|
||||||
|
return synchronousPromise(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(promise, 'then').andCallThrough();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("CopyService", function () {
|
||||||
|
describe("validate", function () {
|
||||||
|
|
||||||
|
var policyService,
|
||||||
|
copyService,
|
||||||
|
object,
|
||||||
|
parentCandidate,
|
||||||
|
validate;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
policyService = jasmine.createSpyObj(
|
||||||
|
'policyService',
|
||||||
|
['allow']
|
||||||
|
);
|
||||||
|
copyService = new CopyService(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
policyService
|
||||||
|
);
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
capabilities: {
|
||||||
|
type: { type: 'object' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
parentCandidate = domainObjectFactory({
|
||||||
|
name: 'parentCandidate',
|
||||||
|
capabilities: {
|
||||||
|
type: { type: 'parentCandidate' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
validate = function () {
|
||||||
|
return copyService.validate(object, parentCandidate);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow invalid parentCandidate", function () {
|
||||||
|
parentCandidate = undefined;
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
parentCandidate = {};
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow copying into source object", function () {
|
||||||
|
object.id = parentCandidate.id = 'abc';
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("defers to policyService", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
object.id = 'a';
|
||||||
|
parentCandidate.id = 'b';
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls policy service with correct args", function () {
|
||||||
|
validate();
|
||||||
|
expect(policyService.allow).toHaveBeenCalledWith(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.capabilities.type,
|
||||||
|
object.capabilities.type
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns false", function () {
|
||||||
|
policyService.allow.andReturn(false);
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns true", function () {
|
||||||
|
policyService.allow.andReturn(true);
|
||||||
|
expect(validate()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("perform", function () {
|
||||||
|
|
||||||
|
var mockQ,
|
||||||
|
creationService,
|
||||||
|
createObjectPromise,
|
||||||
|
copyService,
|
||||||
|
object,
|
||||||
|
newParent,
|
||||||
|
copyResult,
|
||||||
|
copyFinished;
|
||||||
|
|
||||||
|
describe("on domain object without composition", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
id: 'abc',
|
||||||
|
model: {
|
||||||
|
name: 'some object'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newParent = domainObjectFactory({
|
||||||
|
name: 'newParent',
|
||||||
|
id: '456',
|
||||||
|
model: {
|
||||||
|
composition: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
creationService = jasmine.createSpyObj(
|
||||||
|
'creationService',
|
||||||
|
['createObject']
|
||||||
|
);
|
||||||
|
createObjectPromise = synchronousPromise(undefined);
|
||||||
|
creationService.createObject.andReturn(createObjectPromise);
|
||||||
|
copyService = new CopyService(null, creationService);
|
||||||
|
copyResult = copyService.perform(object, newParent);
|
||||||
|
copyFinished = jasmine.createSpy('copyFinished');
|
||||||
|
copyResult.then(copyFinished);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses creation service", function () {
|
||||||
|
expect(creationService.createObject)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Object), newParent);
|
||||||
|
|
||||||
|
expect(createObjectPromise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deep clones object model", function () {
|
||||||
|
var newModel = creationService
|
||||||
|
.createObject
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0];
|
||||||
|
|
||||||
|
expect(newModel).toEqual(object.model);
|
||||||
|
expect(newModel).not.toBe(object.model);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a promise", function () {
|
||||||
|
expect(copyResult).toBeDefined();
|
||||||
|
expect(copyFinished).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("on domainObject with composition", function () {
|
||||||
|
var childObject,
|
||||||
|
compositionCapability,
|
||||||
|
compositionPromise;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockQ = jasmine.createSpyObj('mockQ', ['when']);
|
||||||
|
mockQ.when.andCallFake(synchronousPromise);
|
||||||
|
childObject = domainObjectFactory({
|
||||||
|
name: 'childObject',
|
||||||
|
id: 'def',
|
||||||
|
model: {
|
||||||
|
name: 'a child object'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
compositionCapability = jasmine.createSpyObj(
|
||||||
|
'compositionCapability',
|
||||||
|
['invoke']
|
||||||
|
);
|
||||||
|
compositionPromise = jasmine.createSpyObj(
|
||||||
|
'compositionPromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
compositionCapability
|
||||||
|
.invoke
|
||||||
|
.andReturn(compositionPromise);
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
id: 'abc',
|
||||||
|
model: {
|
||||||
|
name: 'some object',
|
||||||
|
composition: ['def']
|
||||||
|
},
|
||||||
|
capabilities: {
|
||||||
|
composition: compositionCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newParent = domainObjectFactory({
|
||||||
|
name: 'newParent',
|
||||||
|
id: '456',
|
||||||
|
model: {
|
||||||
|
composition: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
creationService = jasmine.createSpyObj(
|
||||||
|
'creationService',
|
||||||
|
['createObject']
|
||||||
|
);
|
||||||
|
createObjectPromise = synchronousPromise(undefined);
|
||||||
|
creationService.createObject.andReturn(createObjectPromise);
|
||||||
|
copyService = new CopyService(mockQ, creationService);
|
||||||
|
copyResult = copyService.perform(object, newParent);
|
||||||
|
copyFinished = jasmine.createSpy('copyFinished');
|
||||||
|
copyResult.then(copyFinished);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses creation service", function () {
|
||||||
|
expect(creationService.createObject)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Object), newParent);
|
||||||
|
|
||||||
|
expect(createObjectPromise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clears model composition", function () {
|
||||||
|
var newModel = creationService
|
||||||
|
.createObject
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0];
|
||||||
|
|
||||||
|
expect(newModel.composition.length).toBe(0);
|
||||||
|
expect(newModel.name).toBe('some object');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("recursively clones it's children", function () {
|
||||||
|
expect(creationService.createObject.calls.length).toBe(1);
|
||||||
|
expect(compositionCapability.invoke).toHaveBeenCalled();
|
||||||
|
compositionPromise.then.mostRecentCall.args[0]([childObject]);
|
||||||
|
expect(creationService.createObject.calls.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a promise", function () {
|
||||||
|
expect(copyResult.then).toBeDefined();
|
||||||
|
expect(copyFinished).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
183
platform/entanglement/test/services/LinkServiceSpec.js
Normal file
183
platform/entanglement/test/services/LinkServiceSpec.js
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/services/LinkService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (LinkService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("LinkService", function () {
|
||||||
|
|
||||||
|
var linkService,
|
||||||
|
mockPolicyService;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockPolicyService = jasmine.createSpyObj(
|
||||||
|
'policyService',
|
||||||
|
['allow']
|
||||||
|
);
|
||||||
|
linkService = new LinkService(mockPolicyService);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("validate", function () {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
parentCandidate,
|
||||||
|
validate;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object'
|
||||||
|
});
|
||||||
|
parentCandidate = domainObjectFactory({
|
||||||
|
name: 'parentCandidate'
|
||||||
|
});
|
||||||
|
validate = function () {
|
||||||
|
return linkService.validate(object, parentCandidate);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow invalid parentCandidate", function () {
|
||||||
|
parentCandidate = undefined;
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
parentCandidate = {};
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow parent to be object", function () {
|
||||||
|
parentCandidate.id = object.id = 'abc';
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow parent that contains object", function () {
|
||||||
|
object.id = 'abc';
|
||||||
|
parentCandidate.id = 'xyz';
|
||||||
|
parentCandidate.model.composition = ['abc'];
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("defers to policyService", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
object.id = 'abc';
|
||||||
|
object.capabilities.type = { type: 'object' };
|
||||||
|
parentCandidate.id = 'xyz';
|
||||||
|
parentCandidate.capabilities.type = {
|
||||||
|
type: 'parentCandidate'
|
||||||
|
};
|
||||||
|
parentCandidate.model.composition = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls policy service with correct args", function () {
|
||||||
|
validate();
|
||||||
|
expect(mockPolicyService.allow).toHaveBeenCalledWith(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.capabilities.type,
|
||||||
|
object.capabilities.type
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns false", function () {
|
||||||
|
mockPolicyService.allow.andReturn(true);
|
||||||
|
expect(validate()).toBe(true);
|
||||||
|
expect(mockPolicyService.allow).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns true", function () {
|
||||||
|
mockPolicyService.allow.andReturn(false);
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
expect(mockPolicyService.allow).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("perform", function () {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
parentModel,
|
||||||
|
parentObject,
|
||||||
|
mutationPromise,
|
||||||
|
persistenceCapability;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mutationPromise = jasmine.createSpyObj(
|
||||||
|
'promise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
persistenceCapability = jasmine.createSpyObj(
|
||||||
|
'persistenceCapability',
|
||||||
|
['persist']
|
||||||
|
);
|
||||||
|
parentModel = {
|
||||||
|
composition: []
|
||||||
|
};
|
||||||
|
parentObject = domainObjectFactory({
|
||||||
|
name: 'parentObject',
|
||||||
|
model: parentModel,
|
||||||
|
capabilities: {
|
||||||
|
mutation: {
|
||||||
|
invoke: function (mutator) {
|
||||||
|
mutator(parentModel);
|
||||||
|
return mutationPromise;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence: persistenceCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
id: 'xyz'
|
||||||
|
});
|
||||||
|
|
||||||
|
parentObject.getCapability.andReturn(persistenceCapability);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("modifies parent model composition", function () {
|
||||||
|
expect(parentModel.composition.length).toBe(0);
|
||||||
|
linkService.perform(object, parentObject);
|
||||||
|
expect(parentObject.useCapability).toHaveBeenCalledWith(
|
||||||
|
'mutation',
|
||||||
|
jasmine.any(Function)
|
||||||
|
);
|
||||||
|
expect(parentModel.composition).toContain('xyz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("persists parent", function () {
|
||||||
|
linkService.perform(object, parentObject);
|
||||||
|
expect(mutationPromise.then).toHaveBeenCalled();
|
||||||
|
mutationPromise.then.calls[0].args[0]();
|
||||||
|
expect(parentObject.getCapability)
|
||||||
|
.toHaveBeenCalledWith('persistence');
|
||||||
|
|
||||||
|
expect(persistenceCapability.persist).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
151
platform/entanglement/test/services/LocationServiceSpec.js
Normal file
151
platform/entanglement/test/services/LocationServiceSpec.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/services/LocationService'
|
||||||
|
],
|
||||||
|
function (LocationService) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("LocationService", function () {
|
||||||
|
var dialogService,
|
||||||
|
locationService,
|
||||||
|
dialogServicePromise,
|
||||||
|
chainedPromise;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
dialogService = jasmine.createSpyObj(
|
||||||
|
'dialogService',
|
||||||
|
['getUserInput']
|
||||||
|
);
|
||||||
|
dialogServicePromise = jasmine.createSpyObj(
|
||||||
|
'dialogServicePromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
chainedPromise = jasmine.createSpyObj(
|
||||||
|
'chainedPromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
dialogServicePromise.then.andReturn(chainedPromise);
|
||||||
|
dialogService.getUserInput.andReturn(dialogServicePromise);
|
||||||
|
locationService = new LocationService(dialogService);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getLocationFromUser", function () {
|
||||||
|
var title,
|
||||||
|
label,
|
||||||
|
validate,
|
||||||
|
initialLocation,
|
||||||
|
locationResult,
|
||||||
|
formStructure,
|
||||||
|
formState;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
title = "Get a location to do something";
|
||||||
|
label = "a location";
|
||||||
|
validate = function () { return true; };
|
||||||
|
initialLocation = { key: "a key" };
|
||||||
|
locationResult = locationService.getLocationFromUser(
|
||||||
|
title,
|
||||||
|
label,
|
||||||
|
validate,
|
||||||
|
initialLocation
|
||||||
|
);
|
||||||
|
formStructure = dialogService
|
||||||
|
.getUserInput
|
||||||
|
.mostRecentCall
|
||||||
|
.args[0];
|
||||||
|
formState = dialogService
|
||||||
|
.getUserInput
|
||||||
|
.mostRecentCall
|
||||||
|
.args[1];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls through to dialogService", function () {
|
||||||
|
expect(dialogService.getUserInput).toHaveBeenCalledWith(
|
||||||
|
jasmine.any(Object),
|
||||||
|
jasmine.any(Object)
|
||||||
|
);
|
||||||
|
expect(formStructure.name).toBe(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a promise", function () {
|
||||||
|
expect(locationResult.then).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formStructure", function () {
|
||||||
|
var locationSection,
|
||||||
|
inputRow;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
locationSection = formStructure.sections[0];
|
||||||
|
inputRow = locationSection.rows[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has a location section", function () {
|
||||||
|
expect(locationSection).toBeDefined();
|
||||||
|
expect(locationSection.name).toBe('Location');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has a input row", function () {
|
||||||
|
expect(inputRow.control).toBe('locator');
|
||||||
|
expect(inputRow.key).toBe('location');
|
||||||
|
expect(inputRow.name).toBe(label);
|
||||||
|
expect(inputRow.validate).toBe(validate);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formState", function () {
|
||||||
|
it("has an initial location", function () {
|
||||||
|
expect(formState.location).toBe(initialLocation);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("resolution of dialog service promise", function () {
|
||||||
|
var resolution,
|
||||||
|
resolver,
|
||||||
|
dialogResult,
|
||||||
|
selectedLocation;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
resolver =
|
||||||
|
dialogServicePromise.then.mostRecentCall.args[0];
|
||||||
|
|
||||||
|
selectedLocation = { key: "i'm a location key" };
|
||||||
|
dialogResult = {
|
||||||
|
location: selectedLocation
|
||||||
|
};
|
||||||
|
|
||||||
|
resolution = resolver(dialogResult);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns selectedLocation", function () {
|
||||||
|
expect(resolution).toBe(selectedLocation);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
99
platform/entanglement/test/services/MockCopyService.js
Normal file
99
platform/entanglement/test/services/MockCopyService.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,jasmine */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MockCopyService provides the same interface as the copyService,
|
||||||
|
* returning promises where it would normally do so. At it's core,
|
||||||
|
* it is a jasmine spy object, but it also tracks the promises it
|
||||||
|
* returns and provides shortcut methods for resolving those promises
|
||||||
|
* synchronously.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* var copyService = new MockCopyService();
|
||||||
|
*
|
||||||
|
* // validate is a standard jasmine spy.
|
||||||
|
* copyService.validate.andReturn(true);
|
||||||
|
* var isValid = copyService.validate(object, parentCandidate);
|
||||||
|
* expect(isValid).toBe(true);
|
||||||
|
*
|
||||||
|
* // perform returns promises and tracks them.
|
||||||
|
* var whenCopied = jasmine.createSpy('whenCopied');
|
||||||
|
* copyService.perform(object, parentObject).then(whenCopied);
|
||||||
|
* expect(whenCopied).not.toHaveBeenCalled();
|
||||||
|
* copyService.perform.mostRecentCall.resolve('someArg');
|
||||||
|
* expect(whenCopied).toHaveBeenCalledWith('someArg');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function MockCopyService() {
|
||||||
|
// track most recent call of a function,
|
||||||
|
// perform automatically returns
|
||||||
|
var mockCopyService = jasmine.createSpyObj(
|
||||||
|
'MockCopyService',
|
||||||
|
[
|
||||||
|
'validate',
|
||||||
|
'perform'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
mockCopyService.perform.andCallFake(function () {
|
||||||
|
var performPromise,
|
||||||
|
callExtensions,
|
||||||
|
spy;
|
||||||
|
|
||||||
|
performPromise = jasmine.createSpyObj(
|
||||||
|
'performPromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
|
||||||
|
callExtensions = {
|
||||||
|
promise: performPromise,
|
||||||
|
resolve: function (resolveWith) {
|
||||||
|
performPromise.then.calls.forEach(function (call) {
|
||||||
|
call.args[0](resolveWith);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spy = this.perform;
|
||||||
|
|
||||||
|
Object.keys(callExtensions).forEach(function (key) {
|
||||||
|
spy.mostRecentCall[key] = callExtensions[key];
|
||||||
|
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return performPromise;
|
||||||
|
});
|
||||||
|
|
||||||
|
return mockCopyService;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MockCopyService;
|
||||||
|
}
|
||||||
|
);
|
99
platform/entanglement/test/services/MockLinkService.js
Normal file
99
platform/entanglement/test/services/MockLinkService.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,jasmine */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MockLinkService provides the same interface as the linkService,
|
||||||
|
* returning promises where it would normally do so. At it's core,
|
||||||
|
* it is a jasmine spy object, but it also tracks the promises it
|
||||||
|
* returns and provides shortcut methods for resolving those promises
|
||||||
|
* synchronously.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* var linkService = new MockLinkService();
|
||||||
|
*
|
||||||
|
* // validate is a standard jasmine spy.
|
||||||
|
* linkService.validate.andReturn(true);
|
||||||
|
* var isValid = linkService.validate(object, parentObject);
|
||||||
|
* expect(isValid).toBe(true);
|
||||||
|
*
|
||||||
|
* // perform returns promises and tracks them.
|
||||||
|
* var whenLinked = jasmine.createSpy('whenLinked');
|
||||||
|
* linkService.perform(object, parentObject).then(whenLinked);
|
||||||
|
* expect(whenLinked).not.toHaveBeenCalled();
|
||||||
|
* linkService.perform.mostRecentCall.resolve('someArg');
|
||||||
|
* expect(whenLinked).toHaveBeenCalledWith('someArg');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function MockLinkService() {
|
||||||
|
// track most recent call of a function,
|
||||||
|
// perform automatically returns
|
||||||
|
var mockLinkService = jasmine.createSpyObj(
|
||||||
|
'MockLinkService',
|
||||||
|
[
|
||||||
|
'validate',
|
||||||
|
'perform'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
mockLinkService.perform.andCallFake(function () {
|
||||||
|
var performPromise,
|
||||||
|
callExtensions,
|
||||||
|
spy;
|
||||||
|
|
||||||
|
performPromise = jasmine.createSpyObj(
|
||||||
|
'performPromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
|
||||||
|
callExtensions = {
|
||||||
|
promise: performPromise,
|
||||||
|
resolve: function (resolveWith) {
|
||||||
|
performPromise.then.calls.forEach(function (call) {
|
||||||
|
call.args[0](resolveWith);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spy = this.perform;
|
||||||
|
|
||||||
|
Object.keys(callExtensions).forEach(function (key) {
|
||||||
|
spy.mostRecentCall[key] = callExtensions[key];
|
||||||
|
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return performPromise;
|
||||||
|
});
|
||||||
|
|
||||||
|
return mockLinkService;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MockLinkService;
|
||||||
|
}
|
||||||
|
);
|
99
platform/entanglement/test/services/MockMoveService.js
Normal file
99
platform/entanglement/test/services/MockMoveService.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,jasmine */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MockMoveService provides the same interface as the moveService,
|
||||||
|
* returning promises where it would normally do so. At it's core,
|
||||||
|
* it is a jasmine spy object, but it also tracks the promises it
|
||||||
|
* returns and provides shortcut methods for resolving those promises
|
||||||
|
* synchronously.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* ```javascript
|
||||||
|
* var moveService = new MockMoveService();
|
||||||
|
*
|
||||||
|
* // validate is a standard jasmine spy.
|
||||||
|
* moveService.validate.andReturn(true);
|
||||||
|
* var isValid = moveService.validate(object, parentCandidate);
|
||||||
|
* expect(isValid).toBe(true);
|
||||||
|
*
|
||||||
|
* // perform returns promises and tracks them.
|
||||||
|
* var whenCopied = jasmine.createSpy('whenCopied');
|
||||||
|
* moveService.perform(object, parentObject).then(whenCopied);
|
||||||
|
* expect(whenCopied).not.toHaveBeenCalled();
|
||||||
|
* moveService.perform.mostRecentCall.resolve('someArg');
|
||||||
|
* expect(whenCopied).toHaveBeenCalledWith('someArg');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function MockMoveService() {
|
||||||
|
// track most recent call of a function,
|
||||||
|
// perform automatically returns
|
||||||
|
var mockMoveService = jasmine.createSpyObj(
|
||||||
|
'MockMoveService',
|
||||||
|
[
|
||||||
|
'validate',
|
||||||
|
'perform'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
mockMoveService.perform.andCallFake(function () {
|
||||||
|
var performPromise,
|
||||||
|
callExtensions,
|
||||||
|
spy;
|
||||||
|
|
||||||
|
performPromise = jasmine.createSpyObj(
|
||||||
|
'performPromise',
|
||||||
|
['then']
|
||||||
|
);
|
||||||
|
|
||||||
|
callExtensions = {
|
||||||
|
promise: performPromise,
|
||||||
|
resolve: function (resolveWith) {
|
||||||
|
performPromise.then.calls.forEach(function (call) {
|
||||||
|
call.args[0](resolveWith);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spy = this.perform;
|
||||||
|
|
||||||
|
Object.keys(callExtensions).forEach(function (key) {
|
||||||
|
spy.mostRecentCall[key] = callExtensions[key];
|
||||||
|
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return performPromise;
|
||||||
|
});
|
||||||
|
|
||||||
|
return mockMoveService;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MockMoveService;
|
||||||
|
}
|
||||||
|
);
|
189
platform/entanglement/test/services/MoveServiceSpec.js
Normal file
189
platform/entanglement/test/services/MoveServiceSpec.js
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is 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.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*global define,describe,beforeEach,it,jasmine,expect */
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/services/MoveService',
|
||||||
|
'../services/MockLinkService',
|
||||||
|
'../DomainObjectFactory'
|
||||||
|
],
|
||||||
|
function (MoveService, MockLinkService, domainObjectFactory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("MoveService", function () {
|
||||||
|
|
||||||
|
var moveService,
|
||||||
|
policyService,
|
||||||
|
linkService;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
policyService = jasmine.createSpyObj(
|
||||||
|
'policyService',
|
||||||
|
['allow']
|
||||||
|
);
|
||||||
|
linkService = new MockLinkService();
|
||||||
|
moveService = new MoveService(policyService, linkService);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("validate", function () {
|
||||||
|
var object,
|
||||||
|
objectContextCapability,
|
||||||
|
currentParent,
|
||||||
|
parentCandidate,
|
||||||
|
validate;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
|
||||||
|
objectContextCapability = jasmine.createSpyObj(
|
||||||
|
'objectContextCapability',
|
||||||
|
[
|
||||||
|
'getParent'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
id: 'a',
|
||||||
|
capabilities: {
|
||||||
|
context: objectContextCapability,
|
||||||
|
type: { type: 'object' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentParent = domainObjectFactory({
|
||||||
|
name: 'currentParent',
|
||||||
|
id: 'b'
|
||||||
|
});
|
||||||
|
|
||||||
|
objectContextCapability.getParent.andReturn(currentParent);
|
||||||
|
|
||||||
|
parentCandidate = domainObjectFactory({
|
||||||
|
name: 'parentCandidate',
|
||||||
|
model: { composition: [] },
|
||||||
|
id: 'c',
|
||||||
|
capabilities: {
|
||||||
|
type: { type: 'parentCandidate' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validate = function () {
|
||||||
|
return moveService.validate(object, parentCandidate);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow an invalid parent", function () {
|
||||||
|
parentCandidate = undefined;
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
parentCandidate = {};
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow moving to current parent", function () {
|
||||||
|
parentCandidate.id = currentParent.id = 'xyz';
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow moving to self", function () {
|
||||||
|
object.id = parentCandidate.id = 'xyz';
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not allow moving to the same location", function () {
|
||||||
|
object.id = 'abc';
|
||||||
|
parentCandidate.model.composition = ['abc'];
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("defers to policyService", function () {
|
||||||
|
|
||||||
|
it("calls policy service with correct args", function () {
|
||||||
|
validate();
|
||||||
|
expect(policyService.allow).toHaveBeenCalledWith(
|
||||||
|
"composition",
|
||||||
|
parentCandidate.capabilities.type,
|
||||||
|
object.capabilities.type
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns false", function () {
|
||||||
|
policyService.allow.andReturn(false);
|
||||||
|
expect(validate()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns true", function () {
|
||||||
|
policyService.allow.andReturn(true);
|
||||||
|
expect(validate()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("perform", function () {
|
||||||
|
|
||||||
|
var object,
|
||||||
|
parentObject,
|
||||||
|
actionCapability;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
actionCapability = jasmine.createSpyObj(
|
||||||
|
'actionCapability',
|
||||||
|
['perform']
|
||||||
|
);
|
||||||
|
|
||||||
|
object = domainObjectFactory({
|
||||||
|
name: 'object',
|
||||||
|
capabilities: {
|
||||||
|
action: actionCapability
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
parentObject = domainObjectFactory({
|
||||||
|
name: 'parentObject'
|
||||||
|
});
|
||||||
|
|
||||||
|
moveService.perform(object, parentObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("links object to parentObject", function () {
|
||||||
|
expect(linkService.perform).toHaveBeenCalledWith(
|
||||||
|
object,
|
||||||
|
parentObject
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("waits for result of link", function () {
|
||||||
|
expect(linkService.perform.mostRecentCall.promise.then)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes object when link is completed", function () {
|
||||||
|
linkService.perform.mostRecentCall.resolve();
|
||||||
|
expect(object.getCapability)
|
||||||
|
.toHaveBeenCalledWith('action');
|
||||||
|
expect(actionCapability.perform)
|
||||||
|
.toHaveBeenCalledWith('remove');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
9
platform/entanglement/test/suite.json
Normal file
9
platform/entanglement/test/suite.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[
|
||||||
|
"actions/CopyAction",
|
||||||
|
"actions/LinkAction",
|
||||||
|
"actions/MoveAction",
|
||||||
|
"services/CopyService",
|
||||||
|
"services/LinkService",
|
||||||
|
"services/MoveService",
|
||||||
|
"services/LocationService"
|
||||||
|
]
|
Reference in New Issue
Block a user