Adding tests for Copy Action

This commit is contained in:
Henry 2015-11-04 17:39:44 -08:00 committed by Andrew Henry
parent 5e1b0f38b7
commit 7d1a1acc11
5 changed files with 109 additions and 410 deletions

View File

@ -26,20 +26,6 @@ define(
function (AbstractComposeAction) {
"use strict";
/*
function CopyAction(locationService, copyService, context) {
return new AbstractComposeAction (
locationService,
copyService,
context,
"Duplicate",
"to a location"
);
}
return CopyAction;
*/
/**
* The CopyAction is available from context menus and allows a user to
* deep copy an object to another location of their choosing.
@ -50,6 +36,8 @@ define(
*/
function CopyAction($log, locationService, copyService, dialogService,
notificationService, context) {
this.dialog = undefined;
this.notification = undefined;
this.dialogService = dialogService;
this.notificationService = notificationService;
this.$log = $log;
@ -58,58 +46,61 @@ define(
context, "Duplicate", "to a location");
}
/**
* Updates user about progress of copy. Should not be invoked by
* client code under any circumstances.
*
* @private
* @param phase
* @param totalObjects
* @param processed
*/
CopyAction.prototype.progress = function(phase, totalObjects, processed){
/*
Copy has two distinct phases. In the first phase a copy plan is
made in memory. During this phase of execution, the user is
shown a blocking 'modal' dialog.
In the second phase, the copying is taking place, and the user
is shown non-invasive banner notifications at the bottom of the screen.
*/
if (phase.toLowerCase() === 'preparing' && !this.dialog){
this.dialog = self.dialogService.showBlockingMessage({
title: "Preparing to copy objects",
unknownProgress: true,
severity: "info",
});
} else if (phase.toLowerCase() === "copying") {
self.dialogService.dismiss();
if (!notification) {
this.notification = self.notificationService
.notify({
title: "Copying objects",
unknownProgress: false,
severity: "info"
});
}
this.notification.model.progress = (processed / totalObjects) * 100;
this.notification.model.title = ["Copied ", processed, "of ",
totalObjects, "objects"].join(" ");
}
}
/**
* Executes the CopyAction. The CopyAction uses the default behaviour of
* the AbstractComposeAction, but extends it to support notification
* updates of progress on copy.
*/
CopyAction.prototype.perform = function() {
var self = this,
notification,
dialog,
notificationModel = {
title: "Copying objects",
unknownProgress: false,
severity: "info",
};
/*
Show banner notification of copy progress.
*/
function progress(phase, totalObjects, processed){
/*
Copy has two distinct phases. In the first phase a copy plan is
made in memory. During this phase of execution, the user is
shown a blocking 'modal' dialog.
In the second phase, the copying is taking place, and the user
is shown non-invasive banner notifications at the bottom of the screen.
*/
if (phase.toLowerCase() === 'preparing' && !dialog){
dialog = self.dialogService.showBlockingMessage({
title: "Preparing to copy objects",
unknownProgress: true,
severity: "info",
});
} else if (phase.toLowerCase() === "copying") {
self.dialogService.dismiss();
if (!notification) {
notification = self.notificationService
.notify(notificationModel);
}
notificationModel.progress = (processed / totalObjects) * 100;
notificationModel.title = ["Copied ", processed, "of ",
totalObjects, "objects"].join(" ");
}
}
var self = this;
AbstractComposeAction.prototype.perform.call(this)
return AbstractComposeAction.prototype.perform.call(this)
.then(
function(){
notification.dismiss();
function success(){
self.notification.dismiss();
self.notificationService.info("Copying complete.");
},
function(error){
function error(error){
self.$log.error("Error copying objects. ", error);
//Show more general error message
self.notificationService.notify({
@ -119,10 +110,11 @@ define(
});
},
function(notification){
progress(notification.phase, notification.totalObjects, notification.processed);
})
};
function notification(notification){
this.progress(notification.phase, notification.totalObjects, notification.processed);
}
);
};
return CopyAction;
}
);

View File

@ -41,7 +41,12 @@ define(
selectedObject,
selectedObjectContextCapability,
currentParent,
newParent;
newParent,
notificationService,
notification,
dialogService,
mockLog,
abstractComposePromise;
beforeEach(function () {
selectedObjectContextCapability = jasmine.createSpyObj(
@ -87,10 +92,47 @@ define(
]
);
abstractComposePromise = jasmine.createSpyObj(
'abstractComposePromise',
[
'then'
]
);
abstractComposePromise.then.andCallFake(function(success, error, notify){
notify({phase: "copying", totalObjects: 10, processed: 10});
success();
}
)
locationServicePromise.then.andCallFake(function(callback){
callback(newParent);
return abstractComposePromise;
});
locationService
.getLocationFromUser
.andReturn(locationServicePromise);
dialogService = jasmine.createSpyObj('dialogService',
['showBlockingMessage']
);
dialogService.showBlockingMessage.andReturn();
notification = jasmine.createSpyObj('notification',
['dismiss', 'model']
);
notification.dismiss.andReturn();
notificationService = jasmine.createSpyObj('notificationService',
['notify']
);
notificationService.notify.andReturn(notification);
mockLog = jasmine.createSpyObj('log', ['error']);
mockLog.error.andReturn();
copyService = new MockCopyService();
});
@ -102,8 +144,11 @@ define(
};
copyAction = new CopyAction(
mockLog,
locationService,
copyService,
dialogService,
notificationService,
context
);
});
@ -114,6 +159,7 @@ define(
describe("when performed it", function () {
beforeEach(function () {
spyOn(copyAction, 'progress').andCallThrough();
copyAction.perform();
});
@ -132,7 +178,7 @@ define(
.toHaveBeenCalledWith(jasmine.any(Function));
});
it("copys object to selected location", function () {
it("copies object to selected location", function () {
locationServicePromise
.then
.mostRecentCall
@ -141,6 +187,11 @@ define(
expect(copyService.perform)
.toHaveBeenCalledWith(selectedObject, newParent);
});
it("notifies the user of progress", function(){
expect(copyAction.progress.calls.length).toBeGreaterThan(0)
});
});
});
@ -152,8 +203,11 @@ define(
};
copyAction = new CopyAction(
mockLog,
locationService,
copyService,
dialogService,
notificationService,
context
);
});

View File

@ -1,174 +0,0 @@
/*****************************************************************************
* 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);
});
});
});
}
);

View File

@ -1,174 +0,0 @@
/*****************************************************************************
* 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);
});
});
});
}
);

View File

@ -1,5 +1,6 @@
[
"actions/AbstractComposeAction",
"actions/CopyAction",
"services/CopyService",
"services/LinkService",
"services/MoveService",