mirror of
https://github.com/nasa/openmct.git
synced 2024-12-28 17:08:51 +00:00
Merge branch 'master' of https://github.com/nasa/openmctweb into open72
Conflicts: platform/commonUI/general/res/css/theme-espresso.css
This commit is contained in:
commit
dcfcfa74bb
@ -28,6 +28,7 @@
|
|||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
"test": "karma start --single-run",
|
"test": "karma start --single-run",
|
||||||
"jshint": "jshint platform example || exit 0",
|
"jshint": "jshint platform example || exit 0",
|
||||||
|
"watch": "karma start",
|
||||||
"jsdoc": "jsdoc -c jsdoc.json -r -d target/docs/api",
|
"jsdoc": "jsdoc -c jsdoc.json -r -d target/docs/api",
|
||||||
"otherdoc": "node docs/gendocs.js --in docs/src --out target/docs",
|
"otherdoc": "node docs/gendocs.js --in docs/src --out target/docs",
|
||||||
"docs": "npm run jsdoc ; npm run otherdoc"
|
"docs": "npm run jsdoc ; npm run otherdoc"
|
||||||
|
@ -69,8 +69,8 @@
|
|||||||
{
|
{
|
||||||
"key": "grid-item",
|
"key": "grid-item",
|
||||||
"templateUrl": "templates/items/grid-item.html",
|
"templateUrl": "templates/items/grid-item.html",
|
||||||
"uses": [ "type", "action" ],
|
"uses": [ "type", "action", "location" ],
|
||||||
"gestures": [ "info","menu" ]
|
"gestures": [ "info", "menu" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "object-header",
|
"key": "object-header",
|
||||||
@ -88,12 +88,12 @@
|
|||||||
{
|
{
|
||||||
"key": "navigationService",
|
"key": "navigationService",
|
||||||
"implementation": "navigation/NavigationService.js"
|
"implementation": "navigation/NavigationService.js"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "creationService",
|
"key": "creationService",
|
||||||
"implementation": "creation/CreationService.js",
|
"implementation": "creation/CreationService.js",
|
||||||
"depends": [ "persistenceService", "$q", "$log" ]
|
"depends": [ "persistenceService", "$q", "$log" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
{
|
{
|
||||||
|
@ -27,12 +27,18 @@
|
|||||||
<mct-include key="_checkbox"></mct-include>
|
<mct-include key="_checkbox"></mct-include>
|
||||||
</div>
|
</div>
|
||||||
<div class='right abs'>
|
<div class='right abs'>
|
||||||
<div class='ui-symbol icon alert hidden' onclick="alert('Not yet functional. When this is visible, it means that this object needs to be updated. Clicking will allow that action via a dialog.');">!</div>
|
<div class='ui-symbol icon l-icon-alert'></div>
|
||||||
<div class='ui-symbol icon profile' title="Shared">P</div>
|
<div class='ui-symbol icon profile' title="Shared">P</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='item-main abs'>
|
<div class='item-main abs'>
|
||||||
<div class='ui-symbol icon lg abs item-type'>{{type.getGlyph()}}</div>
|
<div class='ui-symbol icon lg item-type'>
|
||||||
|
{{type.getGlyph()}}
|
||||||
|
<span
|
||||||
|
class="ui-symbol icon l-icon-link" title="This object is a link"
|
||||||
|
ng-show="location.isLink()"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
<div class='ui-symbol icon abs item-open'>}</div>
|
<div class='ui-symbol icon abs item-open'>}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='bottom-bar bar abs'>
|
<div class='bottom-bar bar abs'>
|
||||||
@ -44,4 +50,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,6 +93,12 @@ define(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the location of an object relative to it's parent.
|
||||||
|
function addLocationToModel(modelId, model, parent) {
|
||||||
|
model.location = parent.getId();
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new domain object with the provided model as a
|
// Create a new domain object with the provided model as a
|
||||||
// member of the specified parent's composition
|
// member of the specified parent's composition
|
||||||
function createObject(model, parent) {
|
function createObject(model, parent) {
|
||||||
@ -112,6 +118,7 @@ define(
|
|||||||
return $q.when(
|
return $q.when(
|
||||||
uuid()
|
uuid()
|
||||||
).then(function (id) {
|
).then(function (id) {
|
||||||
|
model = addLocationToModel(id, model, parent);
|
||||||
return doPersist(persistence.getSpace(), id, model);
|
return doPersist(persistence.getSpace(), id, model);
|
||||||
}).then(function (id) {
|
}).then(function (id) {
|
||||||
return addToComposition(id, parent, persistence);
|
return addToComposition(id, parent, persistence);
|
||||||
|
@ -38,6 +38,7 @@ define(
|
|||||||
mockMutationCapability,
|
mockMutationCapability,
|
||||||
mockPersistenceCapability,
|
mockPersistenceCapability,
|
||||||
mockCompositionCapability,
|
mockCompositionCapability,
|
||||||
|
mockContextCapability,
|
||||||
mockCapabilities,
|
mockCapabilities,
|
||||||
creationService;
|
creationService;
|
||||||
|
|
||||||
@ -87,10 +88,15 @@ define(
|
|||||||
"composition",
|
"composition",
|
||||||
["invoke"]
|
["invoke"]
|
||||||
);
|
);
|
||||||
|
mockContextCapability = jasmine.createSpyObj(
|
||||||
|
"context",
|
||||||
|
["getPath"]
|
||||||
|
);
|
||||||
mockCapabilities = {
|
mockCapabilities = {
|
||||||
mutation: mockMutationCapability,
|
mutation: mockMutationCapability,
|
||||||
persistence: mockPersistenceCapability,
|
persistence: mockPersistenceCapability,
|
||||||
composition: mockCompositionCapability
|
composition: mockCompositionCapability,
|
||||||
|
context: mockContextCapability
|
||||||
};
|
};
|
||||||
|
|
||||||
mockPersistenceService.createObject.andReturn(
|
mockPersistenceService.createObject.andReturn(
|
||||||
@ -103,6 +109,7 @@ define(
|
|||||||
mockParentObject.useCapability.andCallFake(function (key, value) {
|
mockParentObject.useCapability.andCallFake(function (key, value) {
|
||||||
return mockCapabilities[key].invoke(value);
|
return mockCapabilities[key].invoke(value);
|
||||||
});
|
});
|
||||||
|
mockParentObject.getId.andReturn('parentId');
|
||||||
|
|
||||||
mockPersistenceCapability.persist.andReturn(
|
mockPersistenceCapability.persist.andReturn(
|
||||||
mockPromise(true)
|
mockPromise(true)
|
||||||
@ -194,7 +201,16 @@ define(
|
|||||||
expect(mockLog.error).toHaveBeenCalled();
|
expect(mockLog.error).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("stores location on new domainObjects", function () {
|
||||||
|
var model = { name: "my model" },
|
||||||
|
objectPromise = creationService.createObject(
|
||||||
|
model,
|
||||||
|
mockParentObject
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(model.location).toBe('parentId');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -196,7 +196,7 @@
|
|||||||
{
|
{
|
||||||
"key": "label",
|
"key": "label",
|
||||||
"templateUrl": "templates/label.html",
|
"templateUrl": "templates/label.html",
|
||||||
"uses": [ "type" ],
|
"uses": [ "type", "location" ],
|
||||||
"gestures": [ "drag", "menu", "info" ]
|
"gestures": [ "drag", "menu", "info" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -172,11 +172,11 @@ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
|
|||||||
/*********************************************** FORM ELEMENTS */
|
/*********************************************** FORM ELEMENTS */
|
||||||
/*
|
/*
|
||||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||||
$c: $baseColor;
|
$c: $baseColor;
|
||||||
color: $c;
|
color: $c;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: lighten($c, $ltGamma);
|
color: lighten($c, $ltGamma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -1049,27 +1049,27 @@ mct-container {
|
|||||||
|
|
||||||
/*.s-limit-upr,
|
/*.s-limit-upr,
|
||||||
.s-limit-lwr {
|
.s-limit-lwr {
|
||||||
$a: 0.5;
|
$a: 0.5;
|
||||||
$l: 30%;
|
$l: 30%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
&:before {
|
&:before {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-family: symbolsfont;
|
font-family: symbolsfont;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
font-style: normal !important;
|
font-style: normal !important;
|
||||||
margin-right: $interiorMarginSm;
|
margin-right: $interiorMarginSm;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.s-limit-upr {
|
.s-limit-upr {
|
||||||
&.s-limit-yellow { @include limit($colorLimitYellow, "\0000ed"); }
|
&.s-limit-yellow { @include limit($colorLimitYellow, "\0000ed"); }
|
||||||
&.s-limit-red { @include limit($colorLimitRed, "\0000eb"); }
|
&.s-limit-red { @include limit($colorLimitRed, "\0000eb"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.s-limit-lwr {
|
.s-limit-lwr {
|
||||||
&.s-limit-yellow { @include limit($colorLimitYellow, "\0000ec"); }
|
&.s-limit-yellow { @include limit($colorLimitYellow, "\0000ec"); }
|
||||||
&.s-limit-red { @include limit($colorLimitRed, "\0000ee"); }
|
&.s-limit-red { @include limit($colorLimitRed, "\0000ee"); }
|
||||||
}*/
|
}*/
|
||||||
/* line 35, ../sass/_limits.scss */
|
/* line 35, ../sass/_limits.scss */
|
||||||
[class*="s-limit"] {
|
[class*="s-limit"] {
|
||||||
@ -1772,11 +1772,11 @@ table {
|
|||||||
/* line 132, ../sass/controls/_buttons.scss */
|
/* line 132, ../sass/controls/_buttons.scss */
|
||||||
.icon-btn.pause-play,
|
.icon-btn.pause-play,
|
||||||
.s-icon-btn.pause-play {
|
.s-icon-btn.pause-play {
|
||||||
/* &.paused {
|
/* &.paused {
|
||||||
.icon {
|
.icon {
|
||||||
@include pulse(500ms);
|
@include pulse(500ms);
|
||||||
}
|
}
|
||||||
}*/ }
|
}*/ }
|
||||||
/* line 138, ../sass/controls/_buttons.scss */
|
/* line 138, ../sass/controls/_buttons.scss */
|
||||||
.icon-btn.pause-play .icon:before,
|
.icon-btn.pause-play .icon:before,
|
||||||
.s-icon-btn.pause-play .icon:before {
|
.s-icon-btn.pause-play .icon:before {
|
||||||
@ -1899,32 +1899,32 @@ a.l-btn span {
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*.control {
|
/*.control {
|
||||||
// UNUSED?
|
// UNUSED?
|
||||||
&.view-control {
|
&.view-control {
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: -1px 5px 1px 2px;
|
margin: -1px 5px 1px 2px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
&.triangle-down {
|
&.triangle-down {
|
||||||
margin: 2px 2px -2px 0px;
|
margin: 2px 2px -2px 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle {
|
.toggle {
|
||||||
@include border-radius(3px);
|
@include border-radius(3px);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 1px 6px 4px 4px;
|
padding: 1px 6px 4px 4px;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(white, 0.1);
|
background: rgba(white, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
/* line 51, ../sass/controls/_controls.scss */
|
/* line 51, ../sass/controls/_controls.scss */
|
||||||
.accordion {
|
.accordion {
|
||||||
@ -2161,23 +2161,23 @@ label.checkbox.custom {
|
|||||||
border-top: 1px solid #575757;
|
border-top: 1px solid #575757;
|
||||||
color: #999;
|
color: #999;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
/* height: $h;
|
/* height: $h;
|
||||||
line-height: $h;
|
line-height: $h;
|
||||||
&.dropdown {
|
&.dropdown {
|
||||||
padding-left: $p;
|
padding-left: $p;
|
||||||
padding-right: $p;
|
padding-right: $p;
|
||||||
}*/
|
}*/
|
||||||
/* &.context-available {
|
/* &.context-available {
|
||||||
// An element like the invoke-menu triangle;
|
// An element like the invoke-menu triangle;
|
||||||
// Indicates that this element has a dropdown menu available;
|
// Indicates that this element has a dropdown menu available;
|
||||||
// Currently unused
|
// Currently unused
|
||||||
$c: $colorKey;
|
$c: $colorKey;
|
||||||
color: $c;
|
color: $c;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: lighten($c, 10%);
|
color: lighten($c, 10%);
|
||||||
}
|
}
|
||||||
}*/ }
|
}*/ }
|
||||||
/* line 162, ../sass/_mixins.scss */
|
/* line 162, ../sass/_mixins.scss */
|
||||||
.btn-menu:not(.disabled):hover {
|
.btn-menu:not(.disabled):hover {
|
||||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||||
@ -2566,7 +2566,7 @@ label.checkbox.custom {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-top: 1px solid #737373;
|
border-top: 1px solid #737373;
|
||||||
color: #d9d9d9;
|
color: #d9d9d9;
|
||||||
line-height: 1.4rem;
|
line-height: 1.5rem;
|
||||||
padding: 3px 10px 3px 30px;
|
padding: 3px 10px 3px 30px;
|
||||||
white-space: nowrap; }
|
white-space: nowrap; }
|
||||||
/* line 46, ../sass/controls/_menus.scss */
|
/* line 46, ../sass/controls/_menus.scss */
|
||||||
|
@ -124,8 +124,8 @@ ul.tree {
|
|||||||
transition: background-color 0.25s;
|
transition: background-color 0.25s;
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
height: 1.4rem;
|
height: 1.5rem;
|
||||||
line-height: 1.4rem;
|
line-height: 1.5rem;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
position: relative; }
|
position: relative; }
|
||||||
/* line 39, ../sass/tree/_tree.scss */
|
/* line 39, ../sass/tree/_tree.scss */
|
||||||
|
@ -146,7 +146,7 @@ $controlDisabledOpacity: 0.3;
|
|||||||
$formLabelW: 20%;
|
$formLabelW: 20%;
|
||||||
$formInputH: 22px;
|
$formInputH: 22px;
|
||||||
$formRowCtrlsH: 14px;
|
$formRowCtrlsH: 14px;
|
||||||
$menuLineH: 1.4rem;
|
$menuLineH: 1.5rem;
|
||||||
$scrollbarTrackSize: 10px;
|
$scrollbarTrackSize: 10px;
|
||||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
||||||
$btnStdH: 25px;
|
$btnStdH: 25px;
|
||||||
|
@ -22,7 +22,13 @@
|
|||||||
<span class="label s-label">
|
<span class="label s-label">
|
||||||
<span class='ui-symbol icon type-icon'>
|
<span class='ui-symbol icon type-icon'>
|
||||||
{{type.getGlyph()}}
|
{{type.getGlyph()}}
|
||||||
<span class='ui-symbol icon alert hidden'>!</span>
|
<span
|
||||||
|
class='ui-symbol icon l-icon-link'
|
||||||
|
ng-show="location.isLink()"
|
||||||
|
></span>
|
||||||
|
<span class='ui-symbol icon l-icon-alert'></span>
|
||||||
|
</span>
|
||||||
|
<span class='title-label'>
|
||||||
|
{{model.name}}
|
||||||
</span>
|
</span>
|
||||||
<span class='title-label'>{{model.name}}</span>
|
|
||||||
</span>
|
</span>
|
||||||
|
@ -22,29 +22,29 @@
|
|||||||
<span ng-controller="ToggleController as toggle">
|
<span ng-controller="ToggleController as toggle">
|
||||||
<span ng-controller="TreeNodeController as treeNode">
|
<span ng-controller="TreeNodeController as treeNode">
|
||||||
<span
|
<span
|
||||||
class="tree-item menus-to-left"
|
class="tree-item menus-to-left"
|
||||||
ng-class="{selected: treeNode.isSelected()}"
|
ng-class="{selected: treeNode.isSelected()}"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class='ui-symbol view-control'
|
class='ui-symbol view-control'
|
||||||
ng-click="toggle.toggle(); treeNode.trackExpansion()"
|
ng-click="toggle.toggle(); treeNode.trackExpansion()"
|
||||||
ng-if="model.composition !== undefined"
|
ng-if="model.composition !== undefined"
|
||||||
>
|
>
|
||||||
{{toggle.isActive() ? "v" : ">"}}
|
{{toggle.isActive() ? "v" : ">"}}
|
||||||
</span>
|
</span>
|
||||||
<mct-representation
|
<mct-representation
|
||||||
key="'label'"
|
key="'label'"
|
||||||
mct-object="domainObject"
|
mct-object="domainObject"
|
||||||
ng-model="ngModel"
|
ng-model="ngModel"
|
||||||
ng-click="ngModel.selectedObject = domainObject"
|
ng-click="ngModel.selectedObject = domainObject"
|
||||||
>
|
>
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="tree-item-subtree"
|
class="tree-item-subtree"
|
||||||
ng-show="toggle.isActive()"
|
ng-show="toggle.isActive()"
|
||||||
ng-if="model.composition !== undefined"
|
ng-if="model.composition !== undefined"
|
||||||
>
|
>
|
||||||
|
|
||||||
<mct-representation key="'subtree'"
|
<mct-representation key="'subtree'"
|
||||||
ng-model="ngModel"
|
ng-model="ngModel"
|
||||||
|
@ -42,8 +42,12 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function RootModelProvider(roots, $q, $log) {
|
function RootModelProvider(roots, $q, $log) {
|
||||||
// Pull out identifiers to used as ROOT's
|
// Pull out identifiers to used as ROOT's, while setting locations.
|
||||||
var ids = roots.map(function (root) { return root.id; }),
|
var ids = roots.map(function (root) {
|
||||||
|
if (!root.model) { root.model = {}; }
|
||||||
|
root.model.location = 'ROOT';
|
||||||
|
return root.id;
|
||||||
|
}),
|
||||||
baseProvider = new StaticModelProvider(roots, $q, $log);
|
baseProvider = new StaticModelProvider(roots, $q, $log);
|
||||||
|
|
||||||
function addRoot(models) {
|
function addRoot(models) {
|
||||||
@ -77,4 +81,4 @@ define(
|
|||||||
|
|
||||||
return RootModelProvider;
|
return RootModelProvider;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -79,6 +79,12 @@ define(
|
|||||||
expect(captured.b.someProperty).toEqual("Some Value B");
|
expect(captured.b.someProperty).toEqual("Some Value B");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("provides models with a location", function () {
|
||||||
|
provider.getModels(["a", "b"]).then(capture);
|
||||||
|
expect(captured.a.location).toBe('ROOT');
|
||||||
|
expect(captured.b.location).toBe('ROOT');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it("does not provide models which are not in extension declarations", function () {
|
it("does not provide models which are not in extension declarations", function () {
|
||||||
provider.getModels(["c"]).then(capture);
|
provider.getModels(["c"]).then(capture);
|
||||||
@ -96,4 +102,4 @@ define(
|
|||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -37,6 +37,12 @@
|
|||||||
"controllers": [
|
"controllers": [
|
||||||
],
|
],
|
||||||
"capabilities": [
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"key": "location",
|
||||||
|
"name": "Location Capability",
|
||||||
|
"description": "Provides a capability for retrieving the location of an object based upon it's context.",
|
||||||
|
"implementation": "capabilities/LocationCapability"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"services": [
|
"services": [
|
||||||
{
|
{
|
||||||
@ -44,7 +50,7 @@
|
|||||||
"name": "Move Service",
|
"name": "Move Service",
|
||||||
"description": "Provides a service for moving objects",
|
"description": "Provides a service for moving objects",
|
||||||
"implementation": "services/MoveService.js",
|
"implementation": "services/MoveService.js",
|
||||||
"depends": ["policyService", "linkService"]
|
"depends": ["policyService", "linkService", "$q"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "linkService",
|
"key": "linkService",
|
||||||
|
87
platform/entanglement/src/capabilities/LocationCapability.js
Normal file
87
platform/entanglement/src/capabilities/LocationCapability.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location capability allows a domain object to know its current
|
||||||
|
* parent, and also know its original parent. When a domain object's
|
||||||
|
* current parent is its original parent, the object is considered an
|
||||||
|
* original, otherwise it's a link.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function LocationCapability(domainObject) {
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the primary location (the parent id) of the current domain
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param {String} location the primary location to persist.
|
||||||
|
* @returns {Promise} a promise that is resolved when the operation
|
||||||
|
* completes.
|
||||||
|
*/
|
||||||
|
LocationCapability.prototype.setPrimaryLocation = function (location) {
|
||||||
|
var capability = this;
|
||||||
|
return this.domainObject.useCapability(
|
||||||
|
'mutation',
|
||||||
|
function (model) {
|
||||||
|
model.location = location;
|
||||||
|
}
|
||||||
|
).then(function () {
|
||||||
|
return capability.domainObject
|
||||||
|
.getCapability('persistence')
|
||||||
|
.persist();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the contextual location of the current domain object. Only
|
||||||
|
* valid for domain objects that have a context capability.
|
||||||
|
*
|
||||||
|
* @returns {String} the contextual location of the object; the id of
|
||||||
|
* its parent.
|
||||||
|
*/
|
||||||
|
LocationCapability.prototype.getContextualLocation = function () {
|
||||||
|
var context = this.domainObject.getCapability("context");
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.getParent().getId();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the domainObject is a link, false if it's an
|
||||||
|
* original.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
LocationCapability.prototype.isLink = function () {
|
||||||
|
var model = this.domainObject.getModel();
|
||||||
|
|
||||||
|
return model.location !== this.getContextualLocation();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the domainObject is an original, false if it's a
|
||||||
|
* link.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
LocationCapability.prototype.isOriginal = function () {
|
||||||
|
return !this.isLink();
|
||||||
|
};
|
||||||
|
|
||||||
|
function createLocationCapability(domainObject) {
|
||||||
|
return new LocationCapability(domainObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createLocationCapability;
|
||||||
|
}
|
||||||
|
);
|
@ -66,6 +66,17 @@ define(
|
|||||||
}
|
}
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
return parentObject.getCapability('persistence').persist();
|
return parentObject.getCapability('persistence').persist();
|
||||||
|
}).then(function getObjectWithNewContext() {
|
||||||
|
return parentObject
|
||||||
|
.useCapability('composition')
|
||||||
|
.then(function (children) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < children.length; i += 1) {
|
||||||
|
if (children[i].getId() === object.getId()) {
|
||||||
|
return children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,13 +25,13 @@
|
|||||||
define(
|
define(
|
||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MoveService provides an interface for moving objects from one
|
* MoveService provides an interface for moving objects from one
|
||||||
* location to another. It also provides a method for determining if
|
* location to another. It also provides a method for determining if
|
||||||
* an object can be copied to a specific location.
|
* an object can be copied to a specific location.
|
||||||
*/
|
*/
|
||||||
function MoveService(policyService, linkService) {
|
function MoveService(policyService, linkService, $q) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Returns `true` if `object` can be moved into
|
* Returns `true` if `object` can be moved into
|
||||||
@ -69,6 +69,25 @@ define(
|
|||||||
perform: function (object, parentObject) {
|
perform: function (object, parentObject) {
|
||||||
return linkService
|
return linkService
|
||||||
.perform(object, parentObject)
|
.perform(object, parentObject)
|
||||||
|
.then(function (objectInNewContext) {
|
||||||
|
var newLocationCapability = objectInNewContext
|
||||||
|
.getCapability('location'),
|
||||||
|
oldLocationCapability = object
|
||||||
|
.getCapability('location');
|
||||||
|
if (!newLocationCapability ||
|
||||||
|
!oldLocationCapability) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (oldLocationCapability.isOriginal()) {
|
||||||
|
return newLocationCapability.setPrimaryLocation(
|
||||||
|
newLocationCapability
|
||||||
|
.getContextualLocation()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return object
|
return object
|
||||||
.getCapability('action')
|
.getCapability('action')
|
||||||
|
78
platform/entanglement/test/ControlledPromise.js
Normal file
78
platform/entanglement/test/ControlledPromise.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*global define,spyOn */
|
||||||
|
|
||||||
|
define(
|
||||||
|
function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An instrumented promise implementation for better control of promises
|
||||||
|
* during tests.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function ControlledPromise() {
|
||||||
|
this.resolveHandlers = [];
|
||||||
|
this.rejectHandlers = [];
|
||||||
|
spyOn(this, 'then').andCallThrough();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the promise, passing the supplied value to all resolve
|
||||||
|
* handlers.
|
||||||
|
*/
|
||||||
|
ControlledPromise.prototype.resolve = function(value) {
|
||||||
|
this.resolveHandlers.forEach(function(handler) {
|
||||||
|
handler(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject the promise, passing the supplied value to all rejection
|
||||||
|
* handlers.
|
||||||
|
*/
|
||||||
|
ControlledPromise.prototype.reject = function(value) {
|
||||||
|
this.rejectHandlers.forEach(function(handler) {
|
||||||
|
handler(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard promise.then, returns a promise that support chaining.
|
||||||
|
* TODO: Need to support resolve/reject handlers that return promises.
|
||||||
|
*/
|
||||||
|
ControlledPromise.prototype.then = function (onResolve, onReject) {
|
||||||
|
var returnPromise = new ControlledPromise();
|
||||||
|
|
||||||
|
if (onResolve) {
|
||||||
|
this.resolveHandlers.push(function(resolveWith) {
|
||||||
|
var chainResult = onResolve(resolveWith);
|
||||||
|
if (chainResult && chainResult.then) {
|
||||||
|
// chainResult is a promise, resolve when it resolves.
|
||||||
|
chainResult.then(function(pipedResult) {
|
||||||
|
return returnPromise.resolve(pipedResult);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
returnPromise.resolve(chainResult);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onReject) {
|
||||||
|
this.rejectHandlers.push(function(rejectWith) {
|
||||||
|
var chainResult = onReject(rejectWith);
|
||||||
|
if (chainResult && chainResult.then) {
|
||||||
|
chainResult.then(function(pipedResult) {
|
||||||
|
returnPromise.reject(pipedResult);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
returnPromise.reject(chainResult);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
return ControlledPromise;
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,94 @@
|
|||||||
|
/*global define,describe,it,expect,beforeEach,jasmine */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../../src/capabilities/LocationCapability',
|
||||||
|
'../DomainObjectFactory',
|
||||||
|
'../ControlledPromise'
|
||||||
|
],
|
||||||
|
function (LocationCapability, domainObjectFactory, ControlledPromise) {
|
||||||
|
|
||||||
|
describe("LocationCapability", function () {
|
||||||
|
|
||||||
|
describe("instantiated with domain object", function () {
|
||||||
|
var locationCapability,
|
||||||
|
persistencePromise,
|
||||||
|
mutationPromise,
|
||||||
|
domainObject;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
domainObject = domainObjectFactory({
|
||||||
|
capabilities: {
|
||||||
|
context: {
|
||||||
|
getParent: function() {
|
||||||
|
return domainObjectFactory({id: 'root'});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence: jasmine.createSpyObj(
|
||||||
|
'persistenceCapability',
|
||||||
|
['persist']
|
||||||
|
),
|
||||||
|
mutation: jasmine.createSpyObj(
|
||||||
|
'mutationCapability',
|
||||||
|
['invoke']
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
persistencePromise = new ControlledPromise();
|
||||||
|
domainObject.capabilities.persistence.persist.andReturn(
|
||||||
|
persistencePromise
|
||||||
|
);
|
||||||
|
|
||||||
|
mutationPromise = new ControlledPromise();
|
||||||
|
domainObject.capabilities.mutation.invoke.andCallFake(
|
||||||
|
function (mutator) {
|
||||||
|
return mutationPromise.then(function () {
|
||||||
|
mutator(domainObject.model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
locationCapability = new LocationCapability(domainObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns contextual location", function () {
|
||||||
|
expect(locationCapability.getContextualLocation())
|
||||||
|
.toBe('root');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("knows when the object is an original", function () {
|
||||||
|
domainObject.model.location = 'root';
|
||||||
|
expect(locationCapability.isOriginal()).toBe(true);
|
||||||
|
expect(locationCapability.isLink()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("knows when the object is a link.", function () {
|
||||||
|
domainObject.model.location = 'different-root';
|
||||||
|
expect(locationCapability.isLink()).toBe(true);
|
||||||
|
expect(locationCapability.isOriginal()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can persist location", function () {
|
||||||
|
var persistResult = locationCapability
|
||||||
|
.setPrimaryLocation('root'),
|
||||||
|
whenComplete = jasmine.createSpy('whenComplete');
|
||||||
|
|
||||||
|
persistResult.then(whenComplete);
|
||||||
|
|
||||||
|
expect(domainObject.model.location).not.toBeDefined();
|
||||||
|
mutationPromise.resolve();
|
||||||
|
expect(domainObject.model.location).toBe('root');
|
||||||
|
|
||||||
|
expect(whenComplete).not.toHaveBeenCalled();
|
||||||
|
expect(domainObject.capabilities.persistence.persist)
|
||||||
|
.toHaveBeenCalled();
|
||||||
|
|
||||||
|
persistencePromise.resolve();
|
||||||
|
expect(whenComplete).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -25,9 +25,10 @@
|
|||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'../../src/services/LinkService',
|
'../../src/services/LinkService',
|
||||||
'../DomainObjectFactory'
|
'../DomainObjectFactory',
|
||||||
|
'../ControlledPromise'
|
||||||
],
|
],
|
||||||
function (LinkService, domainObjectFactory) {
|
function (LinkService, domainObjectFactory, ControlledPromise) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe("LinkService", function () {
|
describe("LinkService", function () {
|
||||||
@ -50,7 +51,6 @@ define(
|
|||||||
validate;
|
validate;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
|
||||||
object = domainObjectFactory({
|
object = domainObjectFactory({
|
||||||
name: 'object'
|
name: 'object'
|
||||||
});
|
});
|
||||||
@ -118,20 +118,29 @@ define(
|
|||||||
describe("perform", function () {
|
describe("perform", function () {
|
||||||
|
|
||||||
var object,
|
var object,
|
||||||
|
linkedObject,
|
||||||
parentModel,
|
parentModel,
|
||||||
parentObject,
|
parentObject,
|
||||||
mutationPromise,
|
mutationPromise,
|
||||||
|
compositionPromise,
|
||||||
|
persistencePromise,
|
||||||
|
compositionCapability,
|
||||||
persistenceCapability;
|
persistenceCapability;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mutationPromise = jasmine.createSpyObj(
|
mutationPromise = new ControlledPromise();
|
||||||
'promise',
|
compositionPromise = new ControlledPromise();
|
||||||
['then']
|
persistencePromise = new ControlledPromise();
|
||||||
);
|
|
||||||
persistenceCapability = jasmine.createSpyObj(
|
persistenceCapability = jasmine.createSpyObj(
|
||||||
'persistenceCapability',
|
'persistenceCapability',
|
||||||
['persist']
|
['persist']
|
||||||
);
|
);
|
||||||
|
persistenceCapability.persist.andReturn(persistencePromise);
|
||||||
|
compositionCapability = jasmine.createSpyObj(
|
||||||
|
'compositionCapability',
|
||||||
|
['invoke']
|
||||||
|
);
|
||||||
|
compositionCapability.invoke.andReturn(compositionPromise);
|
||||||
parentModel = {
|
parentModel = {
|
||||||
composition: []
|
composition: []
|
||||||
};
|
};
|
||||||
@ -145,7 +154,8 @@ define(
|
|||||||
return mutationPromise;
|
return mutationPromise;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
persistence: persistenceCapability
|
persistence: persistenceCapability,
|
||||||
|
composition: compositionCapability
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -154,7 +164,11 @@ define(
|
|||||||
id: 'xyz'
|
id: 'xyz'
|
||||||
});
|
});
|
||||||
|
|
||||||
parentObject.getCapability.andReturn(persistenceCapability);
|
linkedObject = domainObjectFactory({
|
||||||
|
name: 'object-link',
|
||||||
|
id: 'xyz'
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -171,12 +185,23 @@ define(
|
|||||||
it("persists parent", function () {
|
it("persists parent", function () {
|
||||||
linkService.perform(object, parentObject);
|
linkService.perform(object, parentObject);
|
||||||
expect(mutationPromise.then).toHaveBeenCalled();
|
expect(mutationPromise.then).toHaveBeenCalled();
|
||||||
mutationPromise.then.calls[0].args[0]();
|
mutationPromise.resolve();
|
||||||
expect(parentObject.getCapability)
|
expect(parentObject.getCapability)
|
||||||
.toHaveBeenCalledWith('persistence');
|
.toHaveBeenCalledWith('persistence');
|
||||||
|
|
||||||
expect(persistenceCapability.persist).toHaveBeenCalled();
|
expect(persistenceCapability.persist).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns object representing new link", function () {
|
||||||
|
var returnPromise, whenComplete;
|
||||||
|
returnPromise = linkService.perform(object, parentObject);
|
||||||
|
whenComplete = jasmine.createSpy('whenComplete');
|
||||||
|
returnPromise.then(whenComplete);
|
||||||
|
|
||||||
|
mutationPromise.resolve();
|
||||||
|
persistencePromise.resolve();
|
||||||
|
compositionPromise.resolve([linkedObject]);
|
||||||
|
expect(whenComplete).toHaveBeenCalledWith(linkedObject);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,10 @@
|
|||||||
/*global define,jasmine */
|
/*global define,jasmine */
|
||||||
|
|
||||||
define(
|
define(
|
||||||
function () {
|
[
|
||||||
|
'../ControlledPromise'
|
||||||
|
],
|
||||||
|
function (ControlledPromise) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +50,7 @@ define(
|
|||||||
* var whenLinked = jasmine.createSpy('whenLinked');
|
* var whenLinked = jasmine.createSpy('whenLinked');
|
||||||
* linkService.perform(object, parentObject).then(whenLinked);
|
* linkService.perform(object, parentObject).then(whenLinked);
|
||||||
* expect(whenLinked).not.toHaveBeenCalled();
|
* expect(whenLinked).not.toHaveBeenCalled();
|
||||||
* linkService.perform.mostRecentCall.resolve('someArg');
|
* linkService.perform.mostRecentCall.promise.resolve('someArg');
|
||||||
* expect(whenLinked).toHaveBeenCalledWith('someArg');
|
* expect(whenLinked).toHaveBeenCalledWith('someArg');
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@ -62,33 +65,19 @@ define(
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockLinkService.perform.andCallFake(function () {
|
mockLinkService.perform.andCallFake(function (object, newParent) {
|
||||||
var performPromise,
|
var performPromise = new ControlledPromise();
|
||||||
callExtensions,
|
|
||||||
spy;
|
|
||||||
|
|
||||||
performPromise = jasmine.createSpyObj(
|
this.perform.mostRecentCall.promise = performPromise;
|
||||||
'performPromise',
|
this.perform.calls[this.perform.calls.length - 1].promise =
|
||||||
['then']
|
performPromise;
|
||||||
);
|
|
||||||
|
|
||||||
callExtensions = {
|
return performPromise.then(function (overrideObject) {
|
||||||
promise: performPromise,
|
if (overrideObject) {
|
||||||
resolve: function (resolveWith) {
|
return overrideObject;
|
||||||
performPromise.then.calls.forEach(function (call) {
|
|
||||||
call.args[0](resolveWith);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
return object;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -25,9 +25,15 @@ define(
|
|||||||
[
|
[
|
||||||
'../../src/services/MoveService',
|
'../../src/services/MoveService',
|
||||||
'../services/MockLinkService',
|
'../services/MockLinkService',
|
||||||
'../DomainObjectFactory'
|
'../DomainObjectFactory',
|
||||||
|
'../ControlledPromise'
|
||||||
],
|
],
|
||||||
function (MoveService, MockLinkService, domainObjectFactory) {
|
function (
|
||||||
|
MoveService,
|
||||||
|
MockLinkService,
|
||||||
|
domainObjectFactory,
|
||||||
|
ControlledPromise
|
||||||
|
) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe("MoveService", function () {
|
describe("MoveService", function () {
|
||||||
@ -140,8 +146,11 @@ define(
|
|||||||
describe("perform", function () {
|
describe("perform", function () {
|
||||||
|
|
||||||
var object,
|
var object,
|
||||||
parentObject,
|
newParent,
|
||||||
actionCapability;
|
actionCapability,
|
||||||
|
locationCapability,
|
||||||
|
locationPromise,
|
||||||
|
moveResult;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
actionCapability = jasmine.createSpyObj(
|
actionCapability = jasmine.createSpyObj(
|
||||||
@ -149,24 +158,34 @@ define(
|
|||||||
['perform']
|
['perform']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
locationCapability = jasmine.createSpyObj(
|
||||||
|
'locationCapability',
|
||||||
|
[
|
||||||
|
'isOriginal',
|
||||||
|
'setPrimaryLocation',
|
||||||
|
'getContextualLocation'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
locationPromise = new ControlledPromise();
|
||||||
|
locationCapability.setPrimaryLocation
|
||||||
|
.andReturn(locationPromise);
|
||||||
|
|
||||||
object = domainObjectFactory({
|
object = domainObjectFactory({
|
||||||
name: 'object',
|
name: 'object',
|
||||||
capabilities: {
|
capabilities: {
|
||||||
action: actionCapability
|
action: actionCapability,
|
||||||
|
location: locationCapability
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
parentObject = domainObjectFactory({
|
moveResult = moveService.perform(object, newParent);
|
||||||
name: 'parentObject'
|
|
||||||
});
|
|
||||||
|
|
||||||
moveService.perform(object, parentObject);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("links object to parentObject", function () {
|
it("links object to newParent", function () {
|
||||||
expect(linkService.perform).toHaveBeenCalledWith(
|
expect(linkService.perform).toHaveBeenCalledWith(
|
||||||
object,
|
object,
|
||||||
parentObject
|
newParent
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -175,12 +194,48 @@ define(
|
|||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("removes object when link is completed", function () {
|
describe("when moving an original", function () {
|
||||||
linkService.perform.mostRecentCall.resolve();
|
beforeEach(function () {
|
||||||
expect(object.getCapability)
|
locationCapability.getContextualLocation
|
||||||
.toHaveBeenCalledWith('action');
|
.andReturn('new-location');
|
||||||
expect(actionCapability.perform)
|
locationCapability.isOriginal.andReturn(true);
|
||||||
.toHaveBeenCalledWith('remove');
|
linkService.perform.mostRecentCall.promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("updates location", function () {
|
||||||
|
expect(locationCapability.setPrimaryLocation)
|
||||||
|
.toHaveBeenCalledWith('new-location');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("after location update", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
locationPromise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes object from parent", function () {
|
||||||
|
expect(actionCapability.perform)
|
||||||
|
.toHaveBeenCalledWith('remove');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when moving a link", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
locationCapability.isOriginal.andReturn(false);
|
||||||
|
linkService.perform.mostRecentCall.promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not update location", function () {
|
||||||
|
expect(locationCapability.setPrimaryLocation)
|
||||||
|
.not
|
||||||
|
.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes object from parent", function () {
|
||||||
|
expect(actionCapability.perform)
|
||||||
|
.toHaveBeenCalledWith('remove');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
"services/CopyService",
|
"services/CopyService",
|
||||||
"services/LinkService",
|
"services/LinkService",
|
||||||
"services/MoveService",
|
"services/MoveService",
|
||||||
"services/LocationService"
|
"services/LocationService",
|
||||||
|
"capabilities/LocationCapability"
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user