Legacy dialogservice form fix (#4564)

* Replace all remaining usage of the legacy dialogService under /src/ #4551
* fixed DefaultRootNamePlugin tests
* fix importFromJSONAction tests
This commit is contained in:
Nikhil 2021-12-13 12:42:47 -08:00 committed by GitHub
parent a0b02c9684
commit 82ea23e20c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 198 additions and 385 deletions

View File

@ -1,58 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, 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([
'objectUtils'
], function (objectUtils) {
function ActionDialogDecorator(mct, actionService) {
this.mct = mct;
this.actionService = actionService;
}
ActionDialogDecorator.prototype.getActions = function (context) {
const mct = this.mct;
return this.actionService.getActions(context).map(function (action) {
if (action.dialogService) {
const domainObject = objectUtils.toNewFormat(
context.domainObject.getModel(),
objectUtils.parseKeyString(context.domainObject.getId())
);
const providers = mct.propertyEditors.get(domainObject, mct.router.path);
if (providers.length > 0) {
action.dialogService = Object.create(action.dialogService);
action.dialogService.getUserInput = function (form) {
return new mct.Dialog(
providers[0].view(context.domainObject),
form.title
).show();
};
}
}
return action;
});
};
return ActionDialogDecorator;
});

View File

@ -21,7 +21,6 @@
*****************************************************************************/
define([
'./actions/ActionDialogDecorator',
'./capabilities/AdapterCapability',
'./directives/MCTView',
'./services/Instantiate',
@ -36,7 +35,6 @@ define([
'./actions/LegacyActionAdapter',
'./services/LegacyPersistenceAdapter'
], function (
ActionDialogDecorator,
AdapterCapability,
MCTView,
Instantiate,
@ -89,12 +87,6 @@ define([
"$injector"
]
},
{
type: "decorator",
provides: "actionService",
implementation: ActionDialogDecorator,
depends: ["openmct"]
},
{
provides: "objectService",
type: "decorator",

View File

@ -4,12 +4,12 @@
* 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.
* '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
* 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.
@ -24,76 +24,54 @@ import {
resetApplicationState
} from 'utils/testing';
xdescribe("the plugin", () => {
let openmct;
let compositionAPI;
let newFolderAction;
let mockObjectPath;
let mockDialogService;
let mockComposition;
let mockPromise;
let newFolderName = 'New Folder';
const OLD_ROOT_NAME = 'Open MCT';
const NEW_ROOT_NAME = 'not_a_root';
beforeEach((done) => {
openmct = createOpenMct();
openmct.on('start', done);
openmct.startHeadless();
newFolderAction = openmct.contextMenu._allActions.filter(action => {
return action.key === 'newFolder';
})[0];
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('installs the new folder action', () => {
expect(newFolderAction).toBeDefined();
});
describe('when invoked', () => {
let openmct;
describe('the DefaultRootNamePlugin', () => {
describe('without DefaultRootNamePlugin', () => {
beforeEach((done) => {
compositionAPI = openmct.composition;
mockObjectPath = [{
name: 'mock folder',
type: 'folder',
identifier: {
key: 'mock-folder',
namespace: ''
}
}];
mockPromise = {
then: (callback) => {
callback({name: newFolderName});
openmct = createOpenMct();
openmct.on('start', done);
openmct.startHeadless();
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('does not changes root name', (done) => {
openmct.objects.getRoot()
.then(object => {
expect(object.name).toEqual(OLD_ROOT_NAME);
done();
}
};
});
});
});
mockDialogService = jasmine.createSpyObj('dialogService', ['getUserInput']);
mockComposition = jasmine.createSpyObj('composition', ['add']);
describe('with DefaultRootNamePlugin', () => {
beforeEach((done) => {
openmct = createOpenMct();
mockDialogService.getUserInput.and.returnValue(mockPromise);
spyOn(openmct.$injector, 'get').and.returnValue(mockDialogService);
spyOn(compositionAPI, 'get').and.returnValue(mockComposition);
spyOn(openmct.objects, 'mutate');
newFolderAction.invoke(mockObjectPath);
openmct.install(openmct.plugins.DefaultRootName(NEW_ROOT_NAME));
openmct.on('start', done);
openmct.startHeadless();
});
it('gets user input for folder name', () => {
expect(mockDialogService.getUserInput).toHaveBeenCalled();
afterEach(() => {
return resetApplicationState(openmct);
});
it('creates a new folder object', () => {
expect(openmct.objects.mutate).toHaveBeenCalled();
});
it('changes root name', (done) => {
openmct.objects.getRoot()
.then(object => {
expect(object.name).toEqual(NEW_ROOT_NAME);
it('adds new folder object to parent composition', () => {
expect(mockComposition.add).toHaveBeenCalled();
done();
});
});
});
});

View File

@ -116,7 +116,7 @@ export default function DisplayLayoutPlugin(options) {
}
});
openmct.types.addType('layout', DisplayLayoutType());
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct, options));
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct));
openmct.inspectorViews.addProvider(new AlphaNumericFormatViewProvider(openmct, options));
openmct.composition.addPolicy((parent, child) => {
if (parent.type === 'layout' && child.type === 'folder') {

View File

@ -214,8 +214,8 @@ export default class ImportAsJSONAction {
]
};
this.openmct.forms.showForm(formStructure).
then(changes => {
this.openmct.forms.showForm(formStructure)
.then(changes => {
let onSave = this.onSave.bind(this);
onSave(domainObject, changes);
});

View File

@ -1,249 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, 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 () {
let context = {};
let action;
let exportService;
let identifierService;
let dialogService;
let openmct;
let mockDialog;
let compositionCapability;
let mockInstantiate;
let uniqueId;
let newObjects;
beforeEach(function () {
uniqueId = 0;
newObjects = [];
openmct = {
$injector: jasmine.createSpyObj('$injector', ['get']),
objects: {
makeKeyString: function (identifier) {
return identifier.key;
},
isPersistable: jasmine.createSpy('isPersistable')
}
};
openmct.objects.isPersistable.and.returnValue(true);
mockInstantiate = jasmine.createSpy('instantiate').and.callFake(
function (model, id) {
let config = {
"model": model,
"id": id,
"capabilities": {}
};
let locationCapability = {
setPrimaryLocation: jasmine.createSpy('setPrimaryLocation')
.and
.callFake(function (newLocation) {
config.model.location = newLocation;
})
};
config.capabilities.location = locationCapability;
if (model.composition) {
let compCapability =
jasmine.createSpy('compCapability')
.and.returnValue(model.composition);
compCapability.add = jasmine.createSpy('add')
.and.callFake(function (newObj) {
config.model.composition.push(newObj.getId());
});
config.capabilities.composition = compCapability;
}
newObjects.push(domainObjectFactory(config));
return domainObjectFactory(config);
});
openmct.$injector.get.and.returnValue(mockInstantiate);
dialogService = jasmine.createSpyObj('dialogService',
[
'getUserInput',
'showBlockingMessage'
]
);
identifierService = jasmine.createSpyObj('identifierService',
[
'generate'
]
);
identifierService.generate.and.callFake(function () {
uniqueId++;
return uniqueId;
});
compositionCapability = jasmine.createSpy('compositionCapability');
mockDialog = jasmine.createSpyObj("dialog", ["dismiss"]);
dialogService.showBlockingMessage.and.returnValue(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 () {
let compDomainObject = domainObjectFactory({
name: 'compObject',
model: { name: 'compObject'},
capabilities: {"composition": compositionCapability}
});
let noCompDomainObject = domainObjectFactory();
context.domainObject = compDomainObject;
expect(ImportAsJSONAction.appliesTo(context, undefined, openmct)).toBe(true);
context.domainObject = noCompDomainObject;
expect(ImportAsJSONAction.appliesTo(context, undefined, openmct)).toBe(false);
});
it("checks object persistability", function () {
const compDomainObject = domainObjectFactory({
name: 'compObject',
model: { name: 'compObject'},
capabilities: {"composition": compositionCapability}
});
context.domainObject = compDomainObject;
ImportAsJSONAction.appliesTo(context, undefined, openmct);
expect(openmct.objects.isPersistable).toHaveBeenCalled();
});
it("displays error dialog on invalid file choice", function () {
dialogService.getUserInput.and.returnValue(Promise.resolve(
{
selectFile: {
body: JSON.stringify({badKey: "INVALID"}),
name: "fileName"
}
})
);
action.perform();
return new Promise(function (resolve, reject) {
setTimeout(resolve, 100);
}).then(function () {
expect(dialogService.getUserInput).toHaveBeenCalled();
expect(dialogService.showBlockingMessage).toHaveBeenCalled();
});
});
xit("can import self-containing objects", function () {
let compDomainObject = domainObjectFactory({
name: 'compObject',
model: { name: 'compObject'},
capabilities: {"composition": compositionCapability}
});
context.domainObject = compDomainObject;
dialogService.getUserInput.and.returnValue(Promise.resolve(
{
selectFile: {
body: JSON.stringify({
"openmct": {
"infiniteParent": {
"composition": [{
key: "infinteChild",
namespace: ""
}],
"name": "1",
"type": "folder",
"modified": 1503598129176,
"location": "mine",
"persisted": 1503598129176
},
"infinteChild": {
"composition": [{
key: "infinteParent",
namespace: ""
}],
"name": "2",
"type": "folder",
"modified": 1503598132428,
"location": "infiniteParent",
"persisted": 1503598132428
}
},
"rootId": "infiniteParent"
}),
name: "fileName"
}
})
);
action.perform();
return new Promise(function (resolve, reject) {
setTimeout(resolve, 100);
}).then(function () {
expect(mockInstantiate.calls.count()).toEqual(2);
});
});
xit("assigns new ids to each imported object", function () {
dialogService.getUserInput.and.returnValue(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"
}
})
);
action.perform();
return new Promise(function (resolve, reject) {
setTimeout(resolve, 100);
}).then(function () {
expect(mockInstantiate.calls.count()).toEqual(1);
expect(newObjects[0].getId()).toBe('1');
});
});
});
}
);

View File

@ -0,0 +1,129 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, 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.
*****************************************************************************/
import ImportFromJSONAction from './ImportFromJSONAction';
import {
createOpenMct,
resetApplicationState
} from 'utils/testing';
let openmct;
let importFromJSONAction;
describe("The import JSON action", function () {
beforeEach((done) => {
openmct = createOpenMct();
openmct.on('start', done);
openmct.startHeadless();
importFromJSONAction = new ImportFromJSONAction(openmct);
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('has import as JSON action', () => {
expect(importFromJSONAction.key).toBe('import.JSON');
});
it('applies to return true for objects with composition', function () {
const domainObject = {
composition: [],
name: 'Unnamed Folder',
type: 'folder',
location: '9f6c9dae-51c3-401d-92f1-c812de942922',
modified: 1637021471624,
persisted: 1637021471624,
id: '84438cda-a071-48d1-b9bf-d77bd53e59ba',
identifier: {
namespace: '',
key: '84438cda-a071-48d1-b9bf-d77bd53e59ba'
}
};
const objectPath = [
domainObject
];
spyOn(openmct.composition, 'get').and.returnValue(true);
expect(importFromJSONAction.appliesTo(objectPath)).toBe(true);
});
it('applies to return false for objects without composition', function () {
const domainObject = {
telemetry: {
period: 10,
amplitude: 1,
offset: 0,
dataRateInHz: 1,
phase: 0,
randomness: 0
},
name: 'Unnamed Sine Wave Generator',
type: 'generator',
location: '84438cda-a071-48d1-b9bf-d77bd53e59ba',
modified: 1637021471172,
identifier: {
namespace: '',
key: 'c102b6e1-3c81-4618-926a-56cc310925f6'
},
persisted: 1637021471172
};
const objectPath = [
domainObject
];
spyOn(openmct.composition, 'get').and.returnValue(false);
expect(importFromJSONAction.appliesTo(objectPath)).toBe(false);
});
it('calls showForm on invoke ', function () {
const domainObject = {
composition: [],
name: 'Unnamed Folder',
type: 'folder',
location: '9f6c9dae-51c3-401d-92f1-c812de942922',
modified: 1637021471624,
persisted: 1637021471624,
id: '84438cda-a071-48d1-b9bf-d77bd53e59ba',
identifier: {
namespace: '',
key: '84438cda-a071-48d1-b9bf-d77bd53e59ba'
}
};
const objectPath = [
domainObject
];
spyOn(openmct.forms, 'showForm').and.returnValue(Promise.resolve({}));
importFromJSONAction.invoke(objectPath);
expect(openmct.forms.showForm).toHaveBeenCalled();
});
});

View File

@ -36,15 +36,36 @@ export default {
},
methods: {
onClick(event) {
if ((this.options.isEditing === undefined || this.options.isEditing) && this.options.dialog) {
this.openmct.$injector.get('dialogService')
.getUserInput(this.options.dialog, this.options.value)
.then(value => {
this.$emit('change', {...value}, this.options);
const self = this;
if ((self.options.isEditing === undefined || self.options.isEditing) && self.options.dialog) {
this.updateFormStructure();
self.openmct.forms.showForm(self.options.dialog)
.then(changes => {
self.$emit('change', {...changes}, self.options);
})
.catch(e => {
// canceled, do nothing
});
}
this.$emit('click', this.options);
self.$emit('click', self.options);
},
updateFormStructure() {
if (!this.options.value) {
return;
}
Object.entries(this.options.value).forEach(([key, value]) => {
this.options.dialog.sections.forEach(section => {
section.rows.forEach(row => {
if (row.key === key) {
row.value = value;
}
});
});
});
}
}
};