openmct/src/plugins/charts/bar/pluginSpec.js
Even Stensberg c27ad469f6
feat(eslint): sort import rule (#6939)
* feat(eslint): sort import rule

* chore(deps): pin dep

* refactor: sort imports

---------

Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
2023-08-31 13:40:00 -07:00

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');
});
});
});