[Import/Export] Adds Import and Export functionality
Added context actions for importing and exporting JSON representations of domain objects. Added FileInputService for triggering file picker and retrieving uploaded data. Also added a File Input form control for integration with MCTForms.
This commit is contained in:
240
platform/import-export/test/actions/ImportAsJSONActionSpec.js
Normal file
240
platform/import-export/test/actions/ImportAsJSONActionSpec.js
Normal file
@@ -0,0 +1,240 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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/ImportAsJSONAction",
|
||||
"../../../entanglement/test/DomainObjectFactory"
|
||||
],
|
||||
function (ImportAsJSONAction, domainObjectFactory) {
|
||||
|
||||
describe("The import JSON action", function () {
|
||||
|
||||
var context = {};
|
||||
var action,
|
||||
exportService,
|
||||
identifierService,
|
||||
dialogService,
|
||||
openmct,
|
||||
mockDialog,
|
||||
compositionCapability,
|
||||
mockInstantiate,
|
||||
uniqueId,
|
||||
newObjects;
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
uniqueId = 0;
|
||||
newObjects = [];
|
||||
openmct = {
|
||||
$injector: jasmine.createSpyObj('$injector', ['get'])
|
||||
};
|
||||
mockInstantiate = jasmine.createSpy('instantiate').andCallFake(
|
||||
function (model, id) {
|
||||
var config = {
|
||||
"model": model,
|
||||
"id": id,
|
||||
"capabilities": {}
|
||||
};
|
||||
var locationCapability = {
|
||||
setPrimaryLocation: jasmine.createSpy
|
||||
('setPrimaryLocation').andCallFake(
|
||||
function (newLocation) {
|
||||
config.model.location = newLocation;
|
||||
}
|
||||
)
|
||||
};
|
||||
config.capabilities.location = locationCapability;
|
||||
if (model.composition) {
|
||||
var compCapability =
|
||||
jasmine.createSpy('compCapability')
|
||||
.andReturn(model.composition);
|
||||
compCapability.add = jasmine.createSpy('add')
|
||||
.andCallFake(function (newObj) {
|
||||
config.model.composition.push(newObj.getId());
|
||||
});
|
||||
config.capabilities.composition = compCapability;
|
||||
}
|
||||
newObjects.push(domainObjectFactory(config));
|
||||
return domainObjectFactory(config);
|
||||
});
|
||||
openmct.$injector.get.andReturn(mockInstantiate);
|
||||
dialogService = jasmine.createSpyObj('dialogService',
|
||||
[
|
||||
'getUserInput',
|
||||
'showBlockingMessage'
|
||||
]
|
||||
);
|
||||
identifierService = jasmine.createSpyObj('identifierService',
|
||||
[
|
||||
'generate'
|
||||
]
|
||||
);
|
||||
identifierService.generate.andCallFake(function () {
|
||||
uniqueId++;
|
||||
return uniqueId;
|
||||
});
|
||||
compositionCapability = jasmine.createSpy('compositionCapability');
|
||||
mockDialog = jasmine.createSpyObj("dialog", ["dismiss"]);
|
||||
dialogService.showBlockingMessage.andReturn(mockDialog);
|
||||
|
||||
action = new ImportAsJSONAction(exportService, identifierService,
|
||||
dialogService, openmct, context);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
|
||||
it("only applies to objects with composition capability", function () {
|
||||
var compDomainObject = domainObjectFactory({
|
||||
name: 'compObject',
|
||||
model: { name: 'compObject'},
|
||||
capabilities: {"composition": compositionCapability}
|
||||
});
|
||||
var noCompDomainObject = domainObjectFactory();
|
||||
|
||||
context.domainObject = compDomainObject;
|
||||
expect(ImportAsJSONAction.appliesTo(context)).toBe(true);
|
||||
context.domainObject = noCompDomainObject;
|
||||
expect(ImportAsJSONAction.appliesTo(context)).toBe(false);
|
||||
});
|
||||
|
||||
it("displays error dialog on invalid file choice", function () {
|
||||
dialogService.getUserInput.andReturn(Promise.resolve(
|
||||
{
|
||||
selectFile: {
|
||||
body: JSON.stringify({badKey: "INVALID"}),
|
||||
name: "fileName"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var init = false;
|
||||
runs(function () {
|
||||
action.perform();
|
||||
setTimeout(function () {
|
||||
init = true;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return init;
|
||||
}, "Promise containing file data should have resolved");
|
||||
|
||||
runs(function () {
|
||||
expect(dialogService.getUserInput).toHaveBeenCalled();
|
||||
expect(dialogService.showBlockingMessage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("can import self-containing objects", function () {
|
||||
dialogService.getUserInput.andReturn(Promise.resolve(
|
||||
{
|
||||
selectFile: {
|
||||
body: JSON.stringify({
|
||||
"openmct": {
|
||||
"infiniteParent": {
|
||||
"composition": ["infinteChild"],
|
||||
"name": "1",
|
||||
"type": "folder",
|
||||
"modified": 1503598129176,
|
||||
"location": "mine",
|
||||
"persisted": 1503598129176
|
||||
},
|
||||
"infinteChild": {
|
||||
"composition": ["infiniteParent"],
|
||||
"name": "2",
|
||||
"type": "folder",
|
||||
"modified": 1503598132428,
|
||||
"location": "infiniteParent",
|
||||
"persisted": 1503598132428
|
||||
}
|
||||
},
|
||||
"rootId": "infiniteParent"
|
||||
}),
|
||||
name: "fileName"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var init = false;
|
||||
runs(function () {
|
||||
action.perform();
|
||||
setTimeout(function () {
|
||||
init = true;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return init;
|
||||
}, "Promise containing file data should have resolved");
|
||||
|
||||
runs(function () {
|
||||
expect(mockInstantiate.calls.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
it("assigns new ids to each imported object", function () {
|
||||
dialogService.getUserInput.andReturn(Promise.resolve(
|
||||
{
|
||||
selectFile: {
|
||||
body: JSON.stringify({
|
||||
"openmct": {
|
||||
"cce9f107-5060-4f55-8151-a00120f4222f": {
|
||||
"composition": [],
|
||||
"name": "test",
|
||||
"type": "folder",
|
||||
"modified": 1503596596639,
|
||||
"location": "mine",
|
||||
"persisted": 1503596596639
|
||||
}
|
||||
},
|
||||
"rootId": "cce9f107-5060-4f55-8151-a00120f4222f"
|
||||
}),
|
||||
name: "fileName"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var init = false;
|
||||
runs(function () {
|
||||
action.perform();
|
||||
setTimeout(function () {
|
||||
init = true;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
waitsFor(function () {
|
||||
return init;
|
||||
}, "Promise containing file data should have resolved");
|
||||
|
||||
runs(function () {
|
||||
expect(mockInstantiate.calls.length).toEqual(1);
|
||||
expect(newObjects[0].getId()).toBe('1');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user