mirror of
https://github.com/nasa/openmct.git
synced 2025-05-05 10:13:07 +00:00
* feat(eslint): sort import rule * chore(deps): pin dep * refactor: sort imports --------- Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
603 lines
16 KiB
JavaScript
603 lines
16 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT, Copyright (c) 2014-2023, 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 BarGraph from './BarGraphPlot.vue';
|
|
import EventEmitter from 'EventEmitter';
|
|
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
|
import Vue from 'vue';
|
|
|
|
import { BAR_GRAPH_KEY, BAR_GRAPH_VIEW } from './BarGraphConstants';
|
|
import BarGraphPlugin from './plugin';
|
|
|
|
describe('the plugin', function () {
|
|
let element;
|
|
let child;
|
|
let openmct;
|
|
let telemetryPromise;
|
|
let telemetryPromiseResolve;
|
|
let mockObjectPath;
|
|
|
|
beforeEach((done) => {
|
|
mockObjectPath = [
|
|
{
|
|
name: 'mock folder',
|
|
type: 'fake-folder',
|
|
identifier: {
|
|
key: 'mock-folder',
|
|
namespace: ''
|
|
}
|
|
},
|
|
{
|
|
name: 'mock parent folder',
|
|
type: 'time-strip',
|
|
identifier: {
|
|
key: 'mock-parent-folder',
|
|
namespace: ''
|
|
}
|
|
}
|
|
];
|
|
const testTelemetry = [
|
|
{
|
|
utc: 1,
|
|
'some-key': ['1.3222'],
|
|
'some-other-key': [1]
|
|
},
|
|
{
|
|
utc: 2,
|
|
'some-key': ['2.555'],
|
|
'some-other-key': [2]
|
|
},
|
|
{
|
|
utc: 3,
|
|
'some-key': ['3.888'],
|
|
'some-other-key': [3]
|
|
}
|
|
];
|
|
|
|
openmct = createOpenMct();
|
|
|
|
telemetryPromise = new Promise((resolve) => {
|
|
telemetryPromiseResolve = resolve;
|
|
});
|
|
|
|
spyOn(openmct.telemetry, 'request').and.callFake(() => {
|
|
telemetryPromiseResolve(testTelemetry);
|
|
|
|
return telemetryPromise;
|
|
});
|
|
|
|
openmct.install(new BarGraphPlugin());
|
|
|
|
element = document.createElement('div');
|
|
element.style.width = '640px';
|
|
element.style.height = '480px';
|
|
child = document.createElement('div');
|
|
child.style.width = '640px';
|
|
child.style.height = '480px';
|
|
element.appendChild(child);
|
|
document.body.appendChild(element);
|
|
|
|
spyOn(window, 'ResizeObserver').and.returnValue({
|
|
observe() {},
|
|
unobserve() {},
|
|
disconnect() {}
|
|
});
|
|
|
|
openmct.time.timeSystem('utc', {
|
|
start: 0,
|
|
end: 4
|
|
});
|
|
|
|
openmct.types.addType('test-object', {
|
|
creatable: true
|
|
});
|
|
|
|
openmct.on('start', done);
|
|
openmct.startHeadless();
|
|
});
|
|
|
|
afterEach((done) => {
|
|
openmct.time.timeSystem('utc', {
|
|
start: 0,
|
|
end: 1
|
|
});
|
|
resetApplicationState(openmct).then(done).catch(done);
|
|
});
|
|
|
|
describe('The bar graph view', () => {
|
|
let barGraphObject;
|
|
// eslint-disable-next-line no-unused-vars
|
|
let mockComposition;
|
|
|
|
beforeEach(async () => {
|
|
barGraphObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'test-plot'
|
|
},
|
|
configuration: {
|
|
barStyles: {
|
|
series: {}
|
|
},
|
|
axes: {},
|
|
useInterpolation: 'linear',
|
|
useBar: true
|
|
},
|
|
type: 'telemetry.plot.bar-graph',
|
|
name: 'Test Bar Graph'
|
|
};
|
|
|
|
mockComposition = new EventEmitter();
|
|
mockComposition.load = () => {
|
|
return [];
|
|
};
|
|
|
|
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
|
|
|
await Vue.nextTick();
|
|
});
|
|
|
|
it('provides a bar graph view', () => {
|
|
const applicableViews = openmct.objectViews.get(barGraphObject, mockObjectPath);
|
|
const plotViewProvider = applicableViews.find(
|
|
(viewProvider) => viewProvider.key === BAR_GRAPH_VIEW
|
|
);
|
|
expect(plotViewProvider).toBeDefined();
|
|
});
|
|
|
|
xit('Renders plotly bar graph', () => {
|
|
let barChartElement = element.querySelectorAll('.plotly');
|
|
expect(barChartElement.length).toBe(1);
|
|
});
|
|
|
|
it('Handles dots in telemetry id', () => {
|
|
const dotFullTelemetryObject = {
|
|
identifier: {
|
|
namespace: 'someNamespace',
|
|
key: '~OpenMCT~outer.test-object.foo.bar'
|
|
},
|
|
type: 'test-dotful-object',
|
|
name: 'A Dotful Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'utc',
|
|
format: 'utc',
|
|
name: 'Time',
|
|
hints: {
|
|
domain: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-key.foo.name.45',
|
|
name: 'Some dotful attribute',
|
|
hints: {
|
|
range: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-other-key.bar.344.rad',
|
|
name: 'Another dotful attribute',
|
|
hints: {
|
|
range: 2
|
|
}
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
const applicableViews = openmct.objectViews.get(barGraphObject, mockObjectPath);
|
|
const plotViewProvider = applicableViews.find(
|
|
(viewProvider) => viewProvider.key === BAR_GRAPH_VIEW
|
|
);
|
|
const barGraphView = plotViewProvider.view(barGraphObject, [barGraphObject]);
|
|
barGraphView.show(child, true);
|
|
mockComposition.emit('add', dotFullTelemetryObject);
|
|
expect(
|
|
barGraphObject.configuration.barStyles.series[
|
|
'someNamespace:~OpenMCT~outer.test-object.foo.bar'
|
|
].name
|
|
).toEqual('A Dotful Object');
|
|
barGraphView.destroy();
|
|
});
|
|
});
|
|
|
|
xdescribe('The spectral plot view for telemetry objects with array values', () => {
|
|
let barGraphObject;
|
|
// eslint-disable-next-line no-unused-vars
|
|
let mockComposition;
|
|
|
|
beforeEach(async () => {
|
|
barGraphObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'test-plot'
|
|
},
|
|
configuration: {
|
|
barStyles: {
|
|
series: {}
|
|
},
|
|
axes: {
|
|
xKey: 'some-key',
|
|
yKey: 'some-other-key'
|
|
},
|
|
useInterpolation: 'linear',
|
|
useBar: false
|
|
},
|
|
type: 'telemetry.plot.bar-graph',
|
|
name: 'Test Bar Graph'
|
|
};
|
|
|
|
mockComposition = new EventEmitter();
|
|
mockComposition.load = () => {
|
|
return [];
|
|
};
|
|
|
|
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
|
|
|
await Vue.nextTick();
|
|
});
|
|
|
|
it('Renders spectral plots', () => {
|
|
const dotFullTelemetryObject = {
|
|
identifier: {
|
|
namespace: 'someNamespace',
|
|
key: '~OpenMCT~outer.test-object.foo.bar'
|
|
},
|
|
type: 'test-dotful-object',
|
|
name: 'A Dotful Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'utc',
|
|
format: 'utc',
|
|
name: 'Time',
|
|
hints: {
|
|
domain: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-key',
|
|
name: 'Some attribute',
|
|
formatString: '%0.2f[]',
|
|
hints: {
|
|
range: 1
|
|
},
|
|
source: 'some-key'
|
|
},
|
|
{
|
|
key: 'some-other-key',
|
|
name: 'Another attribute',
|
|
format: 'number[]',
|
|
hints: {
|
|
range: 2
|
|
},
|
|
source: 'some-other-key'
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
const applicableViews = openmct.objectViews.get(barGraphObject, mockObjectPath);
|
|
const plotViewProvider = applicableViews.find(
|
|
(viewProvider) => viewProvider.key === BAR_GRAPH_VIEW
|
|
);
|
|
const barGraphView = plotViewProvider.view(barGraphObject, [barGraphObject]);
|
|
barGraphView.show(child, true);
|
|
mockComposition.emit('add', dotFullTelemetryObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
const plotElement = element.querySelector('.cartesianlayer .scatterlayer .trace .lines');
|
|
expect(plotElement).not.toBeNull();
|
|
barGraphView.destroy();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('the bar graph objects', () => {
|
|
const mockObject = {
|
|
name: 'A very nice bar graph',
|
|
key: BAR_GRAPH_KEY,
|
|
creatable: true
|
|
};
|
|
|
|
it('defines a bar graph object type with the correct key', () => {
|
|
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
|
expect(objectDef.key).toEqual(mockObject.key);
|
|
});
|
|
|
|
it('is creatable', () => {
|
|
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
|
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
|
});
|
|
});
|
|
|
|
describe('The bar graph composition policy', () => {
|
|
it('allows composition for telemetry that contain at least one range', () => {
|
|
const parent = {
|
|
composition: [],
|
|
configuration: {},
|
|
name: 'Some Bar Graph',
|
|
type: 'telemetry.plot.bar-graph',
|
|
location: 'mine',
|
|
modified: 1631005183584,
|
|
persisted: 1631005183502,
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9'
|
|
}
|
|
};
|
|
const testTelemetryObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'test-object'
|
|
},
|
|
type: 'test-object',
|
|
name: 'Test Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'some-key',
|
|
source: 'some-key',
|
|
name: 'Some attribute',
|
|
format: 'enum',
|
|
enumerations: [
|
|
{
|
|
value: 0,
|
|
string: 'OFF'
|
|
},
|
|
{
|
|
value: 1,
|
|
string: 'ON'
|
|
}
|
|
],
|
|
hints: {
|
|
range: 1
|
|
}
|
|
}
|
|
]
|
|
}
|
|
};
|
|
const composition = openmct.composition.get(parent);
|
|
expect(() => {
|
|
composition.add(testTelemetryObject);
|
|
}).not.toThrow();
|
|
expect(parent.composition.length).toBe(1);
|
|
});
|
|
|
|
it("disallows composition for telemetry that don't contain any range hints", () => {
|
|
const parent = {
|
|
composition: [],
|
|
configuration: {},
|
|
name: 'Some Bar Graph',
|
|
type: 'telemetry.plot.bar-graph',
|
|
location: 'mine',
|
|
modified: 1631005183584,
|
|
persisted: 1631005183502,
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9'
|
|
}
|
|
};
|
|
const testTelemetryObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'test-object'
|
|
},
|
|
type: 'test-object',
|
|
name: 'Test Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'some-key',
|
|
name: 'Some attribute'
|
|
},
|
|
{
|
|
key: 'some-other-key',
|
|
name: 'Another attribute'
|
|
}
|
|
]
|
|
}
|
|
};
|
|
const composition = openmct.composition.get(parent);
|
|
expect(() => {
|
|
composition.add(testTelemetryObject);
|
|
}).toThrow();
|
|
expect(parent.composition.length).toBe(0);
|
|
});
|
|
it('disallows composition for condition sets', () => {
|
|
const parent = {
|
|
composition: [],
|
|
configuration: {},
|
|
name: 'Some Bar Graph',
|
|
type: 'telemetry.plot.bar-graph',
|
|
location: 'mine',
|
|
modified: 1631005183584,
|
|
persisted: 1631005183502,
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'b78e7e23-f2b8-4776-b1f0-3ff778f5c8a9'
|
|
}
|
|
};
|
|
const testTelemetryObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: 'test-object'
|
|
},
|
|
type: 'conditionSet',
|
|
name: 'Test Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'some-key',
|
|
name: 'Some attribute',
|
|
format: 'enum',
|
|
hints: {
|
|
domain: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-other-key',
|
|
name: 'Another attribute',
|
|
hints: {
|
|
range: 1
|
|
}
|
|
}
|
|
]
|
|
}
|
|
};
|
|
const composition = openmct.composition.get(parent);
|
|
expect(() => {
|
|
composition.add(testTelemetryObject);
|
|
}).toThrow();
|
|
expect(parent.composition.length).toBe(0);
|
|
});
|
|
});
|
|
describe('the inspector view', () => {
|
|
let mockComposition;
|
|
let testDomainObject;
|
|
let selection;
|
|
let plotInspectorView;
|
|
let viewContainer;
|
|
let optionsElement;
|
|
beforeEach(async () => {
|
|
testDomainObject = {
|
|
identifier: {
|
|
namespace: '',
|
|
key: '~Some~foo.bar'
|
|
},
|
|
type: 'test-object',
|
|
name: 'Test Object',
|
|
telemetry: {
|
|
values: [
|
|
{
|
|
key: 'utc',
|
|
format: 'utc',
|
|
name: 'Time',
|
|
hints: {
|
|
domain: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-key',
|
|
name: 'Some attribute',
|
|
hints: {
|
|
range: 1
|
|
}
|
|
},
|
|
{
|
|
key: 'some-other-key',
|
|
name: 'Another attribute',
|
|
hints: {
|
|
range: 2
|
|
}
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
selection = [
|
|
[
|
|
{
|
|
context: {
|
|
item: {
|
|
id: 'test-object',
|
|
identifier: {
|
|
key: 'test-object',
|
|
namespace: ''
|
|
},
|
|
type: 'telemetry.plot.bar-graph',
|
|
configuration: {
|
|
barStyles: {
|
|
series: {
|
|
'~Some~foo.bar': {
|
|
name: 'A telemetry object',
|
|
type: 'some-type',
|
|
isAlias: true
|
|
}
|
|
}
|
|
},
|
|
axes: {},
|
|
useInterpolation: 'linear',
|
|
useBar: true
|
|
},
|
|
composition: [
|
|
{
|
|
identifier: {
|
|
key: '~Some~foo.bar'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
context: {
|
|
item: {
|
|
type: 'time-strip',
|
|
identifier: {
|
|
key: 'some-other-key',
|
|
namespace: ''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
];
|
|
|
|
mockComposition = new EventEmitter();
|
|
mockComposition.load = () => {
|
|
mockComposition.emit('add', testDomainObject);
|
|
|
|
return [testDomainObject];
|
|
};
|
|
|
|
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
|
|
|
viewContainer = document.createElement('div');
|
|
child.append(viewContainer);
|
|
|
|
const applicableViews = openmct.inspectorViews.get(selection);
|
|
plotInspectorView = applicableViews.filter(
|
|
(view) => view.name === 'Bar Graph Configuration'
|
|
)[0];
|
|
plotInspectorView.show(viewContainer);
|
|
|
|
await Vue.nextTick();
|
|
optionsElement = element.querySelector('.c-bar-graph-options');
|
|
});
|
|
|
|
afterEach(() => {
|
|
plotInspectorView.destroy();
|
|
});
|
|
|
|
it('it renders the options', () => {
|
|
expect(optionsElement).toBeDefined();
|
|
});
|
|
|
|
it('shows the name', () => {
|
|
const seriesEl = optionsElement.querySelector('.c-object-label__name');
|
|
expect(seriesEl.innerHTML).toEqual('A telemetry object');
|
|
});
|
|
});
|
|
});
|