mirror of
https://github.com/nasa/openmct.git
synced 2025-02-20 17:33:23 +00:00
Merge branch 'BogdanAlexandru-mct588comm'
This commit is contained in:
commit
c179d9e759
@ -64,7 +64,7 @@ define(
|
||||
var editing = currentObject.hasCapability('editor') &&
|
||||
currentObject.getCapability('editor').isEditContextRoot();
|
||||
|
||||
return self.$q.when(editing && currentObject.getCapability("editor").cancel());
|
||||
return self.$q.when(editing && currentObject.getCapability("editor").finish());
|
||||
}
|
||||
|
||||
function navigate() {
|
||||
|
@ -61,7 +61,7 @@ define(
|
||||
|
||||
capabilities.editor = jasmine.createSpyObj("editorCapability", [
|
||||
"isEditContextRoot",
|
||||
"cancel"
|
||||
"finish"
|
||||
]);
|
||||
|
||||
mockNavigatedObject.getCapability.andCallFake(function (capability) {
|
||||
@ -148,9 +148,9 @@ define(
|
||||
capabilities.editor.isEditContextRoot.andReturn(true);
|
||||
});
|
||||
|
||||
it("cancels editing if in edit mode", function () {
|
||||
it("finishes editing if in edit mode", function () {
|
||||
action.perform();
|
||||
expect(capabilities.editor.cancel)
|
||||
expect(capabilities.editor.finish)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -31,6 +31,7 @@ define([
|
||||
"./src/actions/PropertiesAction",
|
||||
"./src/actions/RemoveAction",
|
||||
"./src/actions/SaveAction",
|
||||
"./src/actions/SaveAndStopEditingAction",
|
||||
"./src/actions/SaveAsAction",
|
||||
"./src/actions/CancelAction",
|
||||
"./src/policies/EditActionPolicy",
|
||||
@ -70,6 +71,7 @@ define([
|
||||
PropertiesAction,
|
||||
RemoveAction,
|
||||
SaveAction,
|
||||
SaveAndStopEditingAction,
|
||||
SaveAsAction,
|
||||
CancelAction,
|
||||
EditActionPolicy,
|
||||
@ -203,20 +205,30 @@ define([
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save",
|
||||
"category": "conclude-editing",
|
||||
"implementation": SaveAction,
|
||||
"name": "Save",
|
||||
"key": "save-and-stop-editing",
|
||||
"category": "save",
|
||||
"implementation": SaveAndStopEditingAction,
|
||||
"name": "Save and Finish Editing",
|
||||
"cssclass": "icon-save labeled",
|
||||
"description": "Save changes made to these objects.",
|
||||
"depends": [
|
||||
"dialogService"
|
||||
],
|
||||
"priority": "mandatory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save",
|
||||
"category": "conclude-editing",
|
||||
"category": "save",
|
||||
"implementation": SaveAction,
|
||||
"name": "Save and Continue Editing",
|
||||
"cssclass": "icon-save labeled",
|
||||
"description": "Save changes made to these objects.",
|
||||
"depends": [
|
||||
"dialogService"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save-as",
|
||||
"category": "save",
|
||||
"implementation": SaveAsAction,
|
||||
"name": "Save As...",
|
||||
"cssclass": "icon-save labeled",
|
||||
@ -225,7 +237,6 @@ define([
|
||||
"$injector",
|
||||
"policyService",
|
||||
"dialogService",
|
||||
"creationService",
|
||||
"copyService"
|
||||
],
|
||||
"priority": "mandatory"
|
||||
|
@ -20,11 +20,32 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="EditActionController">
|
||||
<span ng-repeat="currentAction in editActions">
|
||||
<!-- If there's a single save action show a button, otherwise show a dropdown with all save actions. -->
|
||||
<span ng-if="saveActions.length === 1">
|
||||
<mct-control key="'button'"
|
||||
structure="{
|
||||
text: saveActions[0].getMetadata().name,
|
||||
click: saveActions[0].perform,
|
||||
cssclass: 'major ' + saveActions[0].getMetadata().cssclass
|
||||
}">
|
||||
</mct-control>
|
||||
</span>
|
||||
|
||||
<span ng-if="saveActions.length > 1">
|
||||
<mct-control key="'menu-button'"
|
||||
structure="{
|
||||
options: saveActionsAsMenuOptions,
|
||||
click: saveActionMenuClickHandler,
|
||||
cssclass: 'btn-bar right icon-save no-label major'
|
||||
}">
|
||||
</mct-control>
|
||||
</span>
|
||||
|
||||
<span ng-repeat="currentAction in otherEditActions">
|
||||
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
||||
title='{{currentAction.getMetadata().name}}'
|
||||
ng-click="currentAction.perform()"
|
||||
ng-class="{ major: $index === 0 }">
|
||||
ng-class="{ major: $index === 0 && saveActions.length === 0 }">
|
||||
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
||||
</a>
|
||||
</span>
|
||||
|
@ -62,7 +62,7 @@ define(
|
||||
}
|
||||
|
||||
function cancel(allowed) {
|
||||
return allowed && domainObject.getCapability("editor").cancel();
|
||||
return allowed && domainObject.getCapability("editor").finish();
|
||||
}
|
||||
|
||||
//Do navigation first in order to trigger unsaved changes dialog
|
||||
|
@ -25,9 +25,8 @@ define(
|
||||
function (SaveInProgressDialog) {
|
||||
|
||||
/**
|
||||
* The "Save" action; the action triggered by clicking Save from
|
||||
* Edit Mode. Exits the editing user interface and invokes object
|
||||
* capabilities to persist the changes that have been made.
|
||||
* The "Save" action; it invokes object capabilities to persist
|
||||
* the changes that have been made.
|
||||
* @constructor
|
||||
* @implements {Action}
|
||||
* @memberof platform/commonUI/edit
|
||||
@ -41,7 +40,7 @@ define(
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes and conclude editing.
|
||||
* Save changes.
|
||||
*
|
||||
* @returns {Promise} a promise that will be fulfilled when
|
||||
* cancellation has completed
|
||||
@ -51,40 +50,22 @@ define(
|
||||
var domainObject = this.domainObject,
|
||||
dialog = new SaveInProgressDialog(this.dialogService);
|
||||
|
||||
function resolveWith(object) {
|
||||
return function () {
|
||||
return object;
|
||||
};
|
||||
}
|
||||
|
||||
// Invoke any save behavior introduced by the editor capability;
|
||||
// this is introduced by EditableDomainObject which is
|
||||
// used to insulate underlying objects from changes made
|
||||
// during editing.
|
||||
function doSave() {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(domainObject));
|
||||
return domainObject.getCapability("editor").save();
|
||||
}
|
||||
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browse UI.)
|
||||
function returnToBrowse(object) {
|
||||
if (object) {
|
||||
object.getCapability("action").perform("navigate");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
function hideBlockingDialog(object) {
|
||||
function hideBlockingDialog() {
|
||||
dialog.hide();
|
||||
return object;
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
|
||||
return doSave()
|
||||
.then(hideBlockingDialog)
|
||||
.then(returnToBrowse)
|
||||
.catch(hideBlockingDialog);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT 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 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["./SaveAction"],
|
||||
function (SaveAction) {
|
||||
|
||||
/**
|
||||
* The "Save and Stop Editing" action performs a [Save action]{@link SaveAction}
|
||||
* on the object under edit followed by exiting the edit user interface.
|
||||
* @constructor
|
||||
* @implements {Action}
|
||||
* @memberof platform/commonUI/edit
|
||||
*/
|
||||
function SaveAndStopEditingAction(
|
||||
dialogService,
|
||||
context
|
||||
) {
|
||||
this.context = context;
|
||||
this.domainObject = (context || {}).domainObject;
|
||||
this.dialogService = dialogService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a save operation and exit edit mode.
|
||||
*
|
||||
* @returns {Promise} a promise that will be fulfilled when
|
||||
* cancellation has completed
|
||||
* @memberof platform/commonUI/edit.SaveAndStopEditingAction#
|
||||
*/
|
||||
SaveAndStopEditingAction.prototype.perform = function () {
|
||||
var domainObject = this.domainObject,
|
||||
saveAction = new SaveAction(this.dialogService, this.context);
|
||||
|
||||
function closeEditor() {
|
||||
return domainObject.getCapability("editor").finish();
|
||||
}
|
||||
|
||||
return saveAction.perform()
|
||||
.then(closeEditor)
|
||||
.catch(closeEditor);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this action is applicable in a given context.
|
||||
* This will ensure that a domain object is present in the context,
|
||||
* and that this domain object is in Edit mode.
|
||||
* @returns true if applicable
|
||||
*/
|
||||
SaveAndStopEditingAction.appliesTo = SaveAction.appliesTo;
|
||||
|
||||
return SaveAndStopEditingAction;
|
||||
}
|
||||
);
|
@ -42,7 +42,6 @@ define([
|
||||
$injector,
|
||||
policyService,
|
||||
dialogService,
|
||||
creationService,
|
||||
copyService,
|
||||
context
|
||||
) {
|
||||
@ -52,7 +51,6 @@ define([
|
||||
};
|
||||
this.policyService = policyService;
|
||||
this.dialogService = dialogService;
|
||||
this.creationService = creationService;
|
||||
this.copyService = copyService;
|
||||
}
|
||||
|
||||
@ -166,11 +164,16 @@ define([
|
||||
.then(resolveWith(object));
|
||||
}
|
||||
|
||||
function commitEditingAfterClone(clonedObject) {
|
||||
function saveAfterClone(clonedObject) {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(clonedObject));
|
||||
}
|
||||
|
||||
function finishEditing(clonedObject) {
|
||||
return domainObject.getCapability("editor").finish()
|
||||
.then(resolveWith(clonedObject));
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
hideBlockingDialog();
|
||||
return false;
|
||||
@ -182,7 +185,8 @@ define([
|
||||
.then(getParent)
|
||||
.then(cloneIntoParent)
|
||||
.then(undirtyOriginals)
|
||||
.then(commitEditingAfterClone)
|
||||
.then(saveAfterClone)
|
||||
.then(finishEditing)
|
||||
.then(hideBlockingDialog)
|
||||
.catch(onFailure);
|
||||
};
|
||||
|
@ -28,8 +28,8 @@ define(
|
||||
* A capability that implements an editing 'session' for a domain
|
||||
* object. An editing session is initiated via a call to .edit().
|
||||
* Once initiated, any persist operations will be queued pending a
|
||||
* subsequent call to [.save()](@link #save) or [.cancel()](@link
|
||||
* #cancel).
|
||||
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
||||
* #finish).
|
||||
* @param transactionService
|
||||
* @param domainObject
|
||||
* @constructor
|
||||
@ -45,7 +45,7 @@ define(
|
||||
/**
|
||||
* Initiate an editing session. This will start a transaction during
|
||||
* which any persist operations will be deferred until either save()
|
||||
* or cancel() are called.
|
||||
* or finish() are called.
|
||||
*/
|
||||
EditorCapability.prototype.edit = function () {
|
||||
this.transactionService.startTransaction();
|
||||
@ -81,25 +81,25 @@ define(
|
||||
};
|
||||
|
||||
/**
|
||||
* Save any changes from this editing session. This will flush all
|
||||
* pending persists and end the current transaction
|
||||
* Save any unsaved changes from this editing session. This will
|
||||
* end the current transaction and continue with a new one.
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.save = function () {
|
||||
var domainObject = this.domainObject;
|
||||
return this.transactionService.commit().then(function () {
|
||||
domainObject.getCapability('status').set('editing', false);
|
||||
var transactionService = this.transactionService;
|
||||
return transactionService.commit().then(function () {
|
||||
transactionService.startTransaction();
|
||||
});
|
||||
};
|
||||
|
||||
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
||||
|
||||
/**
|
||||
* Cancel the current editing session. This will discard any pending
|
||||
* Finish the current editing session. This will discard any pending
|
||||
* persist operations
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.cancel = function () {
|
||||
EditorCapability.prototype.finish = function () {
|
||||
var domainObject = this.domainObject;
|
||||
return this.transactionService.cancel().then(function () {
|
||||
domainObject.getCapability("status").set("editing", false);
|
||||
|
@ -27,7 +27,8 @@ define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
var ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
||||
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||
|
||||
/**
|
||||
* Controller which supplies action instances for Save/Cancel.
|
||||
@ -35,11 +36,30 @@ define(
|
||||
* @constructor
|
||||
*/
|
||||
function EditActionController($scope) {
|
||||
// Maintain all "conclude-editing" actions in the present
|
||||
// context.
|
||||
|
||||
function actionToMenuOption(action) {
|
||||
return {
|
||||
key: action,
|
||||
name: action.getMetadata().name,
|
||||
cssclass: action.getMetadata().cssclass
|
||||
};
|
||||
}
|
||||
|
||||
// Maintain all "conclude-editing" and "save" actions in the
|
||||
// present context.
|
||||
function updateActions() {
|
||||
$scope.editActions = $scope.action ?
|
||||
$scope.action.getActions(ACTION_CONTEXT) :
|
||||
$scope.saveActions = $scope.action ?
|
||||
$scope.action.getActions(SAVE_ACTION_CONTEXT) :
|
||||
[];
|
||||
|
||||
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
||||
|
||||
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
||||
clickedAction.perform();
|
||||
};
|
||||
|
||||
$scope.otherEditActions = $scope.action ?
|
||||
$scope.action.getActions(OTHERS_ACTION_CONTEXT) :
|
||||
[];
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,17 @@ define(
|
||||
editAction,
|
||||
editorCapability;
|
||||
|
||||
function closeEditor() {
|
||||
return editorCapability.finish();
|
||||
}
|
||||
|
||||
function onSave() {
|
||||
return editorCapability.save();
|
||||
return editorCapability.save()
|
||||
.then(closeEditor);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
return editorCapability.cancel();
|
||||
return closeEditor();
|
||||
}
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
@ -85,9 +90,9 @@ define(
|
||||
if (editAction) {
|
||||
return editAction.perform();
|
||||
} else if (editorCapability) {
|
||||
//otherwise, use the save action
|
||||
//otherwise, use the save as action
|
||||
editorCapability.edit();
|
||||
return newObject.getCapability("action").perform("save").then(onSave, onCancel);
|
||||
return newObject.getCapability("action").perform("save-as").then(onSave, onCancel);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +63,7 @@ define(
|
||||
|
||||
capabilities.editor = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
capabilities.action = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
@ -105,7 +105,7 @@ define(
|
||||
return !!capabilities[name];
|
||||
});
|
||||
|
||||
capabilities.editor.cancel.andReturn(mockPromise(true));
|
||||
capabilities.editor.finish.andReturn(mockPromise(true));
|
||||
|
||||
action = new CancelAction(actionContext);
|
||||
|
||||
@ -130,8 +130,8 @@ define(
|
||||
capabilities.action.perform.andReturn(mockPromise(true));
|
||||
action.perform();
|
||||
|
||||
// Should have called cancel
|
||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
||||
// Should have called finish
|
||||
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||
|
||||
// Definitely shouldn't call save!
|
||||
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||
|
@ -58,7 +58,7 @@ define(
|
||||
);
|
||||
mockEditor = jasmine.createSpyObj(
|
||||
"editorCapability",
|
||||
["edit", "isEditContextRoot", "cancel"]
|
||||
["edit", "isEditContextRoot"]
|
||||
);
|
||||
|
||||
capabilities = {
|
||||
|
@ -56,7 +56,7 @@ define(
|
||||
);
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "isEditContextRoot"]
|
||||
);
|
||||
mockActionCapability = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
@ -105,12 +105,6 @@ define(
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("navigates to the object after saving",
|
||||
function () {
|
||||
action.perform();
|
||||
expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate");
|
||||
});
|
||||
|
||||
describe("a blocking dialog", function () {
|
||||
var mockDialogHandle;
|
||||
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT 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 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["../../src/actions/SaveAndStopEditingAction"],
|
||||
function (SaveAndStopEditingAction) {
|
||||
|
||||
describe("The Save and Stop Editing action", function () {
|
||||
|
||||
// Some mocks appear unused because the
|
||||
// underlying SaveAction that this action
|
||||
// depends on is not mocked, so we mock some
|
||||
// of SaveAction's own dependencies to make
|
||||
// it run.
|
||||
var mockDomainObject,
|
||||
mockEditorCapability,
|
||||
actionContext,
|
||||
dialogService,
|
||||
mockActionCapability,
|
||||
capabilities = {},
|
||||
action;
|
||||
|
||||
function mockPromise(value) {
|
||||
return {
|
||||
then: function (callback) {
|
||||
return mockPromise(callback(value));
|
||||
},
|
||||
catch: function (callback) {
|
||||
return mockPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[
|
||||
"getCapability",
|
||||
"hasCapability",
|
||||
"getModel",
|
||||
"getOriginalObject"
|
||||
]
|
||||
);
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
mockActionCapability = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
["perform"]
|
||||
);
|
||||
capabilities.editor = mockEditorCapability;
|
||||
capabilities.action = mockActionCapability;
|
||||
|
||||
actionContext = {
|
||||
domainObject: mockDomainObject
|
||||
};
|
||||
dialogService = jasmine.createSpyObj(
|
||||
"dialogService",
|
||||
["showBlockingMessage"]
|
||||
);
|
||||
|
||||
mockDomainObject.hasCapability.andReturn(true);
|
||||
mockDomainObject.getCapability.andCallFake(function (capability) {
|
||||
return capabilities[capability];
|
||||
});
|
||||
mockDomainObject.getModel.andReturn({ persisted: 0 });
|
||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||
|
||||
action = new SaveAndStopEditingAction(dialogService, actionContext);
|
||||
});
|
||||
|
||||
|
||||
it("only applies to domain object with an editor capability", function () {
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true);
|
||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||
|
||||
mockDomainObject.hasCapability.andReturn(false);
|
||||
mockDomainObject.getCapability.andReturn(undefined);
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("only applies to domain object that has already been persisted", function () {
|
||||
mockDomainObject.getModel.andReturn({ persisted: undefined });
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("does not close the editor before completing the save", function () {
|
||||
mockEditorCapability.save.andReturn(new Promise(function () {
|
||||
}));
|
||||
action.perform();
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("closes the editor after saving", function () {
|
||||
action.perform();
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global describe,it,expect,beforeEach,jasmine*/
|
||||
/*global describe,it,expect,beforeEach,jasmine,runs,waitsFor,spyOn*/
|
||||
|
||||
define(
|
||||
["../../src/actions/SaveAsAction"],
|
||||
@ -33,7 +33,6 @@ define(
|
||||
mockDialogService,
|
||||
mockCopyService,
|
||||
mockParent,
|
||||
mockUrlService,
|
||||
actionContext,
|
||||
capabilities = {},
|
||||
action;
|
||||
@ -78,10 +77,10 @@ define(
|
||||
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
mockEditorCapability.cancel.andReturn(mockPromise(undefined));
|
||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||
mockEditorCapability.finish.andReturn(mockPromise(true));
|
||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||
capabilities.editor = mockEditorCapability;
|
||||
|
||||
@ -113,16 +112,11 @@ define(
|
||||
]
|
||||
);
|
||||
|
||||
mockUrlService = jasmine.createSpyObj(
|
||||
"urlService",
|
||||
["urlForLocation"]
|
||||
);
|
||||
|
||||
actionContext = {
|
||||
domainObject: mockDomainObject
|
||||
};
|
||||
|
||||
action = new SaveAsAction(undefined, undefined, mockDialogService, undefined, mockCopyService, actionContext);
|
||||
action = new SaveAsAction(undefined, undefined, mockDialogService, mockCopyService, actionContext);
|
||||
|
||||
spyOn(action, "getObjectService");
|
||||
action.getObjectService.andReturn(mockObjectService);
|
||||
@ -156,6 +150,28 @@ define(
|
||||
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("uses the editor capability to save the object", function () {
|
||||
mockEditorCapability.save.andReturn(new Promise(function () {}));
|
||||
runs(function () {
|
||||
action.perform();
|
||||
});
|
||||
waitsFor(function () {
|
||||
return mockEditorCapability.save.calls.length > 0;
|
||||
}, "perform() should call EditorCapability.save");
|
||||
runs(function () {
|
||||
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the editor capability to finish editing the object", function () {
|
||||
runs(function () {
|
||||
action.perform();
|
||||
});
|
||||
waitsFor(function () {
|
||||
return mockEditorCapability.finish.calls.length > 0;
|
||||
}, "perform() should call EditorCapability.finish");
|
||||
});
|
||||
|
||||
it("returns to browse after save", function () {
|
||||
spyOn(action, "save");
|
||||
action.save.andReturn(mockPromise(mockDomainObject));
|
||||
|
@ -134,15 +134,15 @@ define(
|
||||
it("commits the transaction", function () {
|
||||
expect(mockTransactionService.commit).toHaveBeenCalled();
|
||||
});
|
||||
it("resets the edit state", function () {
|
||||
expect(mockStatusCapability.set).toHaveBeenCalledWith('editing', false);
|
||||
it("begins a new transaction", function () {
|
||||
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("cancel", function () {
|
||||
describe("finish", function () {
|
||||
beforeEach(function () {
|
||||
capability.edit();
|
||||
capability.cancel();
|
||||
capability.finish();
|
||||
});
|
||||
it("cancels the transaction", function () {
|
||||
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
||||
@ -158,7 +158,7 @@ define(
|
||||
beforeEach(function () {
|
||||
mockDomainObject.getModel.andReturn(model);
|
||||
capability.edit();
|
||||
capability.cancel();
|
||||
capability.finish();
|
||||
});
|
||||
it("returns true if the object has been modified since it" +
|
||||
" was last persisted", function () {
|
||||
|
@ -19,22 +19,51 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/EditActionController"],
|
||||
function (EditActionController) {
|
||||
|
||||
describe("The Edit Action controller", function () {
|
||||
var mockSaveActionMetadata = {
|
||||
name: "mocked-save-action",
|
||||
cssclass: "mocked-save-action-css"
|
||||
};
|
||||
|
||||
function fakeGetActions(actionContext) {
|
||||
if (actionContext.category === "save") {
|
||||
var mockedSaveActions = [
|
||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"]),
|
||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
|
||||
];
|
||||
mockedSaveActions.forEach(function (action) {
|
||||
action.getMetadata.andReturn(mockSaveActionMetadata);
|
||||
});
|
||||
return mockedSaveActions;
|
||||
} else if (actionContext.category === "conclude-editing") {
|
||||
return ["a", "b", "c"];
|
||||
} else {
|
||||
throw "EditActionController uses a context that's not covered by tests.";
|
||||
}
|
||||
}
|
||||
|
||||
var mockScope,
|
||||
mockActions,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||
mockActions.getActions.andCallFake(fakeGetActions);
|
||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||
mockScope.action = mockActions;
|
||||
controller = new EditActionController(mockScope);
|
||||
});
|
||||
|
||||
function makeControllerUpdateActions() {
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
}
|
||||
|
||||
it("watches scope that may change applicable actions", function () {
|
||||
// The action capability
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
@ -43,16 +72,34 @@ define(
|
||||
);
|
||||
});
|
||||
|
||||
it("populates the scope with grouped and ungrouped actions", function () {
|
||||
mockScope.action = mockActions;
|
||||
it("populates the scope with 'save' actions", function () {
|
||||
makeControllerUpdateActions();
|
||||
expect(mockScope.saveActions.length).toEqual(2);
|
||||
});
|
||||
|
||||
mockActions.getActions.andReturn(["a", "b", "c"]);
|
||||
it("converts 'save' actions to their menu counterparts", function () {
|
||||
makeControllerUpdateActions();
|
||||
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
||||
|
||||
// Call the watch
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
expect(menuOptions.length).toEqual(2);
|
||||
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
||||
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
||||
menuOptions.forEach(function (option) {
|
||||
expect(option.name).toEqual(mockSaveActionMetadata.name);
|
||||
expect(option.cssclass).toEqual(mockSaveActionMetadata.cssclass);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have grouped and ungrouped actions in scope now
|
||||
expect(mockScope.editActions.length).toEqual(3);
|
||||
it("uses a click handler to perform the clicked action", function () {
|
||||
makeControllerUpdateActions();
|
||||
var sampleSaveAction = mockScope.saveActions[0];
|
||||
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
||||
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("populates the scope with other editing actions", function () {
|
||||
makeControllerUpdateActions();
|
||||
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ define(
|
||||
[
|
||||
"edit",
|
||||
"save",
|
||||
"cancel"
|
||||
"finish"
|
||||
]
|
||||
);
|
||||
|
||||
@ -142,6 +142,7 @@ define(
|
||||
});
|
||||
|
||||
describe("the perform function", function () {
|
||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||
beforeEach(function () {
|
||||
capabilities.action.getActions.andReturn([mockEditAction]);
|
||||
});
|
||||
@ -156,19 +157,20 @@ define(
|
||||
expect(mockEditAction.perform).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses the save action if object does not have an edit action" +
|
||||
it("uses the save-as action if object does not have an edit action" +
|
||||
" available", function () {
|
||||
capabilities.action.getActions.andReturn([]);
|
||||
capabilities.action.perform.andReturn(mockPromise(undefined));
|
||||
capabilities.editor.save.andReturn(promise);
|
||||
action.perform();
|
||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save");
|
||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
|
||||
});
|
||||
|
||||
describe("uses to editor capability", function () {
|
||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||
beforeEach(function () {
|
||||
capabilities.action.getActions.andReturn([]);
|
||||
capabilities.action.perform.andReturn(promise);
|
||||
capabilities.editor.save.andReturn(promise);
|
||||
});
|
||||
|
||||
it("to save the edit if user saves dialog", function () {
|
||||
@ -178,10 +180,10 @@ define(
|
||||
expect(capabilities.editor.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("to cancel the edit if user cancels dialog", function () {
|
||||
it("to finish the edit if user cancels dialog", function () {
|
||||
action.perform();
|
||||
promise.then.mostRecentCall.args[1]();
|
||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
||||
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user