mirror of
https://github.com/nasa/openmct.git
synced 2025-02-22 10:11:06 +00:00
Lad testing (#3045)
* Added tests for LAD Tables and LAD Table Sets Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
This commit is contained in:
parent
67ebcf4749
commit
055cf2b118
39
src/plugins/LADTable/LADTableCompositionPolicy.js
Normal file
39
src/plugins/LADTable/LADTableCompositionPolicy.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2020, 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
export default class LADTableCompositionPolicy {
|
||||||
|
|
||||||
|
constructor(openmct) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
return this.allow.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
allow(parent, child) {
|
||||||
|
if(parent.type === 'LadTable') {
|
||||||
|
return this.openmct.telemetry.isTelemetryObject(child);
|
||||||
|
} else if(parent.type === 'LadTableSet') {
|
||||||
|
return child.type === 'LadTable';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -19,53 +19,46 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
import LadTableSet from './components/LadTableSet.vue';
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
define([
|
export default function LADTableSetViewProvider(openmct) {
|
||||||
'./components/LadTableSet.vue',
|
return {
|
||||||
'vue'
|
key: 'LadTableSet',
|
||||||
], function (
|
name: 'LAD Table Set',
|
||||||
LadTableSet,
|
cssClass: 'icon-tabular-lad-set',
|
||||||
Vue
|
canView: function (domainObject) {
|
||||||
) {
|
return domainObject.type === 'LadTableSet';
|
||||||
function LADTableSetViewProvider(openmct) {
|
},
|
||||||
return {
|
canEdit: function (domainObject) {
|
||||||
key: 'LadTableSet',
|
return domainObject.type === 'LadTableSet';
|
||||||
name: 'LAD Table Set',
|
},
|
||||||
cssClass: 'icon-tabular-lad-set',
|
view: function (domainObject, objectPath) {
|
||||||
canView: function (domainObject) {
|
let component;
|
||||||
return domainObject.type === 'LadTableSet';
|
|
||||||
},
|
|
||||||
canEdit: function (domainObject) {
|
|
||||||
return domainObject.type === 'LadTableSet';
|
|
||||||
},
|
|
||||||
view: function (domainObject, objectPath) {
|
|
||||||
let component;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
el: element,
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
LadTableSet: LadTableSet.default
|
LadTableSet: LadTableSet
|
||||||
},
|
},
|
||||||
provide: {
|
provide: {
|
||||||
openmct,
|
openmct,
|
||||||
domainObject,
|
domainObject,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
template: '<lad-table-set></lad-table-set>'
|
template: '<lad-table-set></lad-table-set>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
destroy: function (element) {
|
destroy: function (element) {
|
||||||
component.$destroy();
|
component.$destroy();
|
||||||
component = undefined;
|
component = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
priority: function () {
|
priority: function () {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return LADTableSetViewProvider;
|
|
||||||
});
|
|
||||||
|
@ -19,53 +19,46 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
import LadTable from './components/LADTable.vue';
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
define([
|
export default function LADTableViewProvider(openmct) {
|
||||||
'./components/LADTable.vue',
|
return {
|
||||||
'vue'
|
key: 'LadTable',
|
||||||
], function (
|
name: 'LAD Table',
|
||||||
LadTableComponent,
|
cssClass: 'icon-tabular-lad',
|
||||||
Vue
|
canView: function (domainObject) {
|
||||||
) {
|
return domainObject.type === 'LadTable';
|
||||||
function LADTableViewProvider(openmct) {
|
},
|
||||||
return {
|
canEdit: function (domainObject) {
|
||||||
key: 'LadTable',
|
return domainObject.type === 'LadTable';
|
||||||
name: 'LAD Table',
|
},
|
||||||
cssClass: 'icon-tabular-lad',
|
view: function (domainObject, objectPath) {
|
||||||
canView: function (domainObject) {
|
let component;
|
||||||
return domainObject.type === 'LadTable';
|
|
||||||
},
|
|
||||||
canEdit: function (domainObject) {
|
|
||||||
return domainObject.type === 'LadTable';
|
|
||||||
},
|
|
||||||
view: function (domainObject, objectPath) {
|
|
||||||
let component;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
show: function (element) {
|
show: function (element) {
|
||||||
component = new Vue({
|
component = new Vue({
|
||||||
el: element,
|
el: element,
|
||||||
components: {
|
components: {
|
||||||
LadTableComponent: LadTableComponent.default
|
LadTableComponent: LadTable
|
||||||
},
|
},
|
||||||
provide: {
|
provide: {
|
||||||
openmct,
|
openmct,
|
||||||
domainObject,
|
domainObject,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
template: '<lad-table-component></lad-table-component>'
|
template: '<lad-table-component></lad-table-component>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
destroy: function (element) {
|
destroy: function (element) {
|
||||||
component.$destroy();
|
component.$destroy();
|
||||||
component = undefined;
|
component = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
priority: function () {
|
priority: function () {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return LADTableViewProvider;
|
|
||||||
});
|
|
||||||
|
@ -22,10 +22,16 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<tr @contextmenu.prevent="showContextMenu">
|
<tr
|
||||||
<td>{{ name }}</td>
|
class="js-lad-table__body__row"
|
||||||
<td>{{ formattedTimestamp }}</td>
|
@contextmenu.prevent="showContextMenu"
|
||||||
<td :class="valueClass">{{ value }}</td>
|
>
|
||||||
|
<td class="js-first-data">{{ name }}</td>
|
||||||
|
<td class="js-second-data">{{ formattedTimestamp }}</td>
|
||||||
|
<td
|
||||||
|
class="js-third-data"
|
||||||
|
:class="valueClass"
|
||||||
|
>{{ value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -88,4 +88,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
>
|
>
|
||||||
<tr
|
<tr
|
||||||
:key="primary.key"
|
:key="primary.key"
|
||||||
class="c-table__group-header"
|
class="c-table__group-header js-lad-table-set__table-headers"
|
||||||
>
|
>
|
||||||
<td colspan="10">
|
<td colspan="10">
|
||||||
{{ primary.domainObject.name }}
|
{{ primary.domainObject.name }}
|
||||||
|
@ -19,38 +19,36 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
import LADTableViewProvider from './LADTableViewProvider';
|
||||||
|
import LADTableSetViewProvider from './LADTableSetViewProvider';
|
||||||
|
import LADTableCompositionPolicy from './LADTableCompositionPolicy';
|
||||||
|
|
||||||
define([
|
export default function plugin() {
|
||||||
'./LADTableViewProvider',
|
return function install(openmct) {
|
||||||
'./LADTableSetViewProvider'
|
|
||||||
], function (
|
|
||||||
LADTableViewProvider,
|
|
||||||
LADTableSetViewProvider
|
|
||||||
) {
|
|
||||||
return function plugin() {
|
|
||||||
return function install(openmct) {
|
|
||||||
openmct.objectViews.addProvider(new LADTableViewProvider(openmct));
|
|
||||||
openmct.objectViews.addProvider(new LADTableSetViewProvider(openmct));
|
|
||||||
|
|
||||||
openmct.types.addType('LadTable', {
|
openmct.objectViews.addProvider(new LADTableViewProvider(openmct));
|
||||||
name: "LAD Table",
|
openmct.objectViews.addProvider(new LADTableSetViewProvider(openmct));
|
||||||
creatable: true,
|
|
||||||
description: "A Latest Available Data tabular view in which each row displays the values for one or more contained telemetry objects.",
|
|
||||||
cssClass: 'icon-tabular-lad',
|
|
||||||
initialize(domainObject) {
|
|
||||||
domainObject.composition = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.types.addType('LadTableSet', {
|
openmct.types.addType('LadTable', {
|
||||||
name: "LAD Table Set",
|
name: "LAD Table",
|
||||||
creatable: true,
|
creatable: true,
|
||||||
description: "A Latest Available Data tabular view in which each row displays the values for one or more contained telemetry objects.",
|
description: "A Latest Available Data tabular view in which each row displays the values for one or more contained telemetry objects.",
|
||||||
cssClass: 'icon-tabular-lad-set',
|
cssClass: 'icon-tabular-lad',
|
||||||
initialize(domainObject) {
|
initialize(domainObject) {
|
||||||
domainObject.composition = [];
|
domainObject.composition = [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
openmct.types.addType('LadTableSet', {
|
||||||
|
name: "LAD Table Set",
|
||||||
|
creatable: true,
|
||||||
|
description: "A Latest Available Data tabular view in which each row displays the values for one or more contained telemetry objects.",
|
||||||
|
cssClass: 'icon-tabular-lad-set',
|
||||||
|
initialize(domainObject) {
|
||||||
|
domainObject.composition = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
openmct.composition.addPolicy(new LADTableCompositionPolicy(openmct));
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
365
src/plugins/LADTable/pluginSpec.js
Normal file
365
src/plugins/LADTable/pluginSpec.js
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, 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 LadPlugin from './plugin.js';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import {
|
||||||
|
createOpenMct,
|
||||||
|
getMockObjects,
|
||||||
|
getMockTelemetry,
|
||||||
|
getLatestTelemetry,
|
||||||
|
resetApplicationState
|
||||||
|
} from 'utils/testing';
|
||||||
|
|
||||||
|
const TABLE_BODY_ROWS = '.js-lad-table__body__row';
|
||||||
|
const TABLE_BODY_FIRST_ROW = TABLE_BODY_ROWS + ':first-child';
|
||||||
|
const TABLE_BODY_FIRST_ROW_FIRST_DATA = TABLE_BODY_FIRST_ROW + ' .js-first-data';
|
||||||
|
const TABLE_BODY_FIRST_ROW_SECOND_DATA = TABLE_BODY_FIRST_ROW + ' .js-second-data';
|
||||||
|
const TABLE_BODY_FIRST_ROW_THIRD_DATA = TABLE_BODY_FIRST_ROW + ' .js-third-data';
|
||||||
|
const LAD_SET_TABLE_HEADERS = '.js-lad-table-set__table-headers';
|
||||||
|
|
||||||
|
function utcTimeFormat(value) {
|
||||||
|
return new Date(value).toISOString().replace('T', ' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("The LAD Table", () => {
|
||||||
|
const ladTableKey = 'LadTable';
|
||||||
|
|
||||||
|
let openmct,
|
||||||
|
ladPlugin,
|
||||||
|
parent,
|
||||||
|
child,
|
||||||
|
telemetryCount = 3,
|
||||||
|
timeFormat = 'utc',
|
||||||
|
mockTelemetry = getMockTelemetry({ count: telemetryCount, format: timeFormat }),
|
||||||
|
mockObj = getMockObjects({
|
||||||
|
objectKeyStrings: ['ladTable', 'telemetry'],
|
||||||
|
format: timeFormat
|
||||||
|
}),
|
||||||
|
bounds = {
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
};
|
||||||
|
|
||||||
|
// add telemetry object as composition in lad table
|
||||||
|
mockObj.ladTable.composition.push(mockObj.telemetry.identifier);
|
||||||
|
|
||||||
|
// this setups up the app
|
||||||
|
beforeEach((done) => {
|
||||||
|
const appHolder = document.createElement('div');
|
||||||
|
appHolder.style.width = '640px';
|
||||||
|
appHolder.style.height = '480px';
|
||||||
|
|
||||||
|
openmct = createOpenMct();
|
||||||
|
|
||||||
|
parent = document.createElement('div');
|
||||||
|
child = document.createElement('div');
|
||||||
|
parent.appendChild(child);
|
||||||
|
|
||||||
|
spyOn(openmct.telemetry, 'request').and.returnValue(Promise.resolve([]));
|
||||||
|
|
||||||
|
ladPlugin = new LadPlugin();
|
||||||
|
openmct.install(ladPlugin);
|
||||||
|
|
||||||
|
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
|
||||||
|
|
||||||
|
openmct.time.bounds({ start: bounds.start, end: bounds.end });
|
||||||
|
|
||||||
|
openmct.on('start', done);
|
||||||
|
openmct.startHeadless(appHolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
resetApplicationState(openmct);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should provide a table view only for lad table objects", () => {
|
||||||
|
let applicableViews = openmct.objectViews.get(mockObj.ladTable),
|
||||||
|
ladTableView = applicableViews.find(
|
||||||
|
(viewProvider) => viewProvider.key === ladTableKey
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(applicableViews.length).toEqual(1);
|
||||||
|
expect(ladTableView).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('composition', () => {
|
||||||
|
let ladTableCompositionCollection;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
ladTableCompositionCollection = openmct.composition.get(mockObj.ladTable);
|
||||||
|
ladTableCompositionCollection.load();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should accept telemetry producing objects", () => {
|
||||||
|
expect(() => {
|
||||||
|
ladTableCompositionCollection.add(mockObj.telemetry);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should reject non-telemtry producing objects", () => {
|
||||||
|
expect(()=> {
|
||||||
|
ladTableCompositionCollection.add(mockObj.ladTable);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("table view", () => {
|
||||||
|
let applicableViews,
|
||||||
|
ladTableViewProvider,
|
||||||
|
ladTableView,
|
||||||
|
anotherTelemetryObj = getMockObjects({
|
||||||
|
objectKeyStrings: ['telemetry'],
|
||||||
|
overwrite: {
|
||||||
|
telemetry: {
|
||||||
|
name: "New Telemetry Object",
|
||||||
|
identifier: { namespace: "", key: "another-telemetry-object" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).telemetry;
|
||||||
|
|
||||||
|
// add another telemetry object as composition in lad table to test multi rows
|
||||||
|
mockObj.ladTable.composition.push(anotherTelemetryObj.identifier);
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let telemetryRequestResolve,
|
||||||
|
telemetryObjectResolve,
|
||||||
|
anotherTelemetryObjectResolve;
|
||||||
|
let telemetryRequestPromise = new Promise((resolve) => {
|
||||||
|
telemetryRequestResolve = resolve;
|
||||||
|
}),
|
||||||
|
telemetryObjectPromise = new Promise((resolve) => {
|
||||||
|
telemetryObjectResolve = resolve;
|
||||||
|
}),
|
||||||
|
anotherTelemetryObjectPromise = new Promise((resolve) => {
|
||||||
|
anotherTelemetryObjectResolve = resolve;
|
||||||
|
})
|
||||||
|
openmct.telemetry.request.and.callFake(() => {
|
||||||
|
telemetryRequestResolve(mockTelemetry);
|
||||||
|
return telemetryRequestPromise;
|
||||||
|
});
|
||||||
|
openmct.objects.get.and.callFake((obj) => {
|
||||||
|
if(obj.key === 'telemetry-object') {
|
||||||
|
telemetryObjectResolve(mockObj.telemetry);
|
||||||
|
return telemetryObjectPromise;
|
||||||
|
} else {
|
||||||
|
anotherTelemetryObjectResolve(anotherTelemetryObj);
|
||||||
|
return anotherTelemetryObjectPromise;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
openmct.time.bounds({ start: bounds.start, end: bounds.end });
|
||||||
|
|
||||||
|
applicableViews = openmct.objectViews.get(mockObj.ladTable);
|
||||||
|
ladTableViewProvider = applicableViews.find((viewProvider) => viewProvider.key === ladTableKey);
|
||||||
|
ladTableView = ladTableViewProvider.view(mockObj.ladTable, [mockObj.ladTable]);
|
||||||
|
ladTableView.show(child, true);
|
||||||
|
|
||||||
|
await Promise.all([telemetryRequestPromise, telemetryObjectPromise, anotherTelemetryObjectPromise]);
|
||||||
|
await Vue.nextTick();
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show one row per object in the composition", () => {
|
||||||
|
const rowCount = parent.querySelectorAll(TABLE_BODY_ROWS).length;
|
||||||
|
expect(rowCount).toBe(mockObj.ladTable.composition.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show the most recent datum from the telemetry producing object", async () => {
|
||||||
|
const latestDatum = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||||
|
const expectedDate = utcTimeFormat(latestDatum[timeFormat]);
|
||||||
|
await Vue.nextTick();
|
||||||
|
const latestDate = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||||
|
expect(latestDate).toBe(expectedDate);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show the name provided for the the telemetry producing object", () => {
|
||||||
|
const rowName = parent.querySelector(TABLE_BODY_FIRST_ROW_FIRST_DATA).innerText,
|
||||||
|
expectedName = mockObj.telemetry.name;
|
||||||
|
expect(rowName).toBe(expectedName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show the correct values for the datum based on domain and range hints", async () => {
|
||||||
|
const range = mockObj.telemetry.telemetry.values.find((val) => {
|
||||||
|
return val.hints && val.hints.range !== undefined;
|
||||||
|
}).key;
|
||||||
|
const domain = mockObj.telemetry.telemetry.values.find((val) => {
|
||||||
|
return val.hints && val.hints.domain !== undefined;
|
||||||
|
}).key;
|
||||||
|
const mostRecentTelemetry = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||||
|
const rangeValue = mostRecentTelemetry[range];
|
||||||
|
const domainValue = utcTimeFormat(mostRecentTelemetry[domain]);
|
||||||
|
await Vue.nextTick();
|
||||||
|
const actualDomainValue = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||||
|
const actualRangeValue = parent.querySelector(TABLE_BODY_FIRST_ROW_THIRD_DATA).innerText;
|
||||||
|
expect(actualRangeValue).toBe(rangeValue);
|
||||||
|
expect(actualDomainValue).toBe(domainValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("The LAD Table Set", () => {
|
||||||
|
const ladTableSetKey = 'LadTableSet';
|
||||||
|
|
||||||
|
let openmct,
|
||||||
|
ladPlugin,
|
||||||
|
parent,
|
||||||
|
child,
|
||||||
|
telemetryCount = 3,
|
||||||
|
timeFormat = 'utc',
|
||||||
|
mockTelemetry = getMockTelemetry({ count: telemetryCount, format: timeFormat }),
|
||||||
|
mockObj = getMockObjects({
|
||||||
|
objectKeyStrings: ['ladTable', 'ladTableSet', 'telemetry']
|
||||||
|
}),
|
||||||
|
bounds = {
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
};
|
||||||
|
// add mock telemetry to lad table and lad table to lad table set (composition)
|
||||||
|
mockObj.ladTable.composition.push(mockObj.telemetry.identifier);
|
||||||
|
mockObj.ladTableSet.composition.push(mockObj.ladTable.identifier);
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
const appHolder = document.createElement('div');
|
||||||
|
appHolder.style.width = '640px';
|
||||||
|
appHolder.style.height = '480px';
|
||||||
|
|
||||||
|
openmct = createOpenMct();
|
||||||
|
|
||||||
|
parent = document.createElement('div');
|
||||||
|
child = document.createElement('div');
|
||||||
|
parent.appendChild(child);
|
||||||
|
|
||||||
|
spyOn(openmct.telemetry, 'request').and.returnValue(Promise.resolve([]));
|
||||||
|
|
||||||
|
ladPlugin = new LadPlugin();
|
||||||
|
openmct.install(ladPlugin);
|
||||||
|
|
||||||
|
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
|
||||||
|
|
||||||
|
openmct.time.bounds({ start: bounds.start, end: bounds.end });
|
||||||
|
|
||||||
|
openmct.on('start', done);
|
||||||
|
openmct.start(appHolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
resetApplicationState(openmct);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should provide a lad table set view only for lad table set objects", () => {
|
||||||
|
let applicableViews = openmct.objectViews.get(mockObj.ladTableSet),
|
||||||
|
ladTableSetView = applicableViews.find(
|
||||||
|
(viewProvider) => viewProvider.key === ladTableSetKey
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(applicableViews.length).toEqual(1);
|
||||||
|
expect(ladTableSetView).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('composition', () => {
|
||||||
|
let ladTableSetCompositionCollection;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
ladTableSetCompositionCollection = openmct.composition.get(mockObj.ladTableSet);
|
||||||
|
ladTableSetCompositionCollection.load();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should accept lad table objects", () => {
|
||||||
|
expect(() => {
|
||||||
|
ladTableSetCompositionCollection.add(mockObj.ladTable);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should reject non lad table objects", () => {
|
||||||
|
expect(()=> {
|
||||||
|
ladTableSetCompositionCollection.add(mockObj.telemetry);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("table view", () => {
|
||||||
|
let applicableViews,
|
||||||
|
ladTableSetViewProvider,
|
||||||
|
ladTableSetView,
|
||||||
|
otherObj = getMockObjects({
|
||||||
|
objectKeyStrings: ['ladTable'],
|
||||||
|
overwrite: {
|
||||||
|
ladTable: {
|
||||||
|
name: "New LAD Table Object",
|
||||||
|
identifier: { namespace: "", key: "another-lad-object" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// add another lad table (with telemetry object) object to the lad table set for multi row test
|
||||||
|
otherObj.ladTable.composition.push(mockObj.telemetry.identifier);
|
||||||
|
mockObj.ladTableSet.composition.push(otherObj.ladTable.identifier);
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let telemetryRequestResolve,
|
||||||
|
ladObjectResolve,
|
||||||
|
anotherLadObjectResolve;
|
||||||
|
let telemetryRequestPromise = new Promise((resolve) => {
|
||||||
|
telemetryRequestResolve = resolve;
|
||||||
|
}),
|
||||||
|
ladObjectPromise = new Promise((resolve) => {
|
||||||
|
ladObjectResolve = resolve;
|
||||||
|
}),
|
||||||
|
anotherLadObjectPromise = new Promise((resolve) => {
|
||||||
|
anotherLadObjectResolve = resolve;
|
||||||
|
})
|
||||||
|
openmct.telemetry.request.and.callFake(() => {
|
||||||
|
telemetryRequestResolve(mockTelemetry);
|
||||||
|
return telemetryRequestPromise;
|
||||||
|
});
|
||||||
|
openmct.objects.get.and.callFake((obj) => {
|
||||||
|
if(obj.key === 'lad-object') {
|
||||||
|
ladObjectResolve(mockObj.ladObject);
|
||||||
|
return ladObjectPromise;
|
||||||
|
} else if(obj.key === 'another-lad-object') {
|
||||||
|
anotherLadObjectResolve(otherObj.ladObject);
|
||||||
|
return anotherLadObjectPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({});
|
||||||
|
});
|
||||||
|
|
||||||
|
openmct.time.bounds({ start: bounds.start, end: bounds.end });
|
||||||
|
|
||||||
|
applicableViews = openmct.objectViews.get(mockObj.ladTableSet);
|
||||||
|
ladTableSetViewProvider = applicableViews.find((viewProvider) => viewProvider.key === ladTableSetKey);
|
||||||
|
ladTableSetView = ladTableSetViewProvider.view(mockObj.ladTableSet, [mockObj.ladTableSet]);
|
||||||
|
ladTableSetView.show(child, true);
|
||||||
|
|
||||||
|
await Promise.all([telemetryRequestPromise, ladObjectPromise, anotherLadObjectPromise]);
|
||||||
|
await Vue.nextTick();
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show one row per lad table object in the composition", () => {
|
||||||
|
const rowCount = parent.querySelectorAll(LAD_SET_TABLE_HEADERS).length;
|
||||||
|
expect(rowCount).toBe(mockObj.ladTableSet.composition.length);
|
||||||
|
pending();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -185,7 +185,7 @@ define([
|
|||||||
plugins.FolderView = FolderView;
|
plugins.FolderView = FolderView;
|
||||||
plugins.Tabs = Tabs;
|
plugins.Tabs = Tabs;
|
||||||
plugins.FlexibleLayout = FlexibleLayout;
|
plugins.FlexibleLayout = FlexibleLayout;
|
||||||
plugins.LADTable = LADTable;
|
plugins.LADTable = LADTable.default;
|
||||||
plugins.Filters = Filters;
|
plugins.Filters = Filters;
|
||||||
plugins.ObjectMigration = ObjectMigration.default;
|
plugins.ObjectMigration = ObjectMigration.default;
|
||||||
plugins.GoToOriginalAction = GoToOriginalAction.default;
|
plugins.GoToOriginalAction = GoToOriginalAction.default;
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
import MCT from 'MCT';
|
import MCT from 'MCT';
|
||||||
let nativeFunctions = [];
|
let nativeFunctions = [],
|
||||||
|
mockObjects = setMockObjects();
|
||||||
|
|
||||||
export function createOpenMct() {
|
export function createOpenMct() {
|
||||||
const openmct = new MCT();
|
const openmct = new MCT();
|
||||||
@ -68,3 +69,205 @@ export function resetApplicationState(openmct) {
|
|||||||
function clearBuiltinSpy(funcDefinition) {
|
function clearBuiltinSpy(funcDefinition) {
|
||||||
funcDefinition.object[funcDefinition.functionName] = funcDefinition.nativeFunction;
|
funcDefinition.object[funcDefinition.functionName] = funcDefinition.nativeFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLatestTelemetry(telemetry = [], opts = {}) {
|
||||||
|
let latest = [],
|
||||||
|
timeFormat = opts.timeFormat || 'utc';
|
||||||
|
|
||||||
|
if(telemetry.length) {
|
||||||
|
latest = telemetry.reduce((prev, cur) => {
|
||||||
|
return prev[timeFormat] > cur[timeFormat] ? prev : cur;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return latest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXAMPLE:
|
||||||
|
// getMockObjects({
|
||||||
|
// name: 'Jamie Telemetry',
|
||||||
|
// keys: ['test','other','yeah','sup'],
|
||||||
|
// format: 'local',
|
||||||
|
// telemetryConfig: {
|
||||||
|
// hints: {
|
||||||
|
// test: {
|
||||||
|
// domain: 1
|
||||||
|
// },
|
||||||
|
// other: {
|
||||||
|
// range: 2
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
export function getMockObjects(opts = {}) {
|
||||||
|
opts.type = opts.type || 'default';
|
||||||
|
if(opts.objectKeyStrings && !Array.isArray(opts.objectKeyStrings)) {
|
||||||
|
throw `"getMockObjects" optional parameter "objectKeyStrings" must be an array of string object keys`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let requestedMocks = {};
|
||||||
|
|
||||||
|
if (!opts.objectKeyStrings) {
|
||||||
|
requestedMocks = copyObj(mockObjects[opts.type]);
|
||||||
|
} else {
|
||||||
|
opts.objectKeyStrings.forEach(objKey => {
|
||||||
|
if(mockObjects[opts.type] && mockObjects[opts.type][objKey]) {
|
||||||
|
requestedMocks[objKey] = copyObj(mockObjects[opts.type][objKey]);
|
||||||
|
} else {
|
||||||
|
throw `No mock object for object key "${objKey}" of type "${opts.type}"`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// build out custom telemetry mappings if necessary
|
||||||
|
if(requestedMocks.telemetry && opts.telemetryConfig) {
|
||||||
|
let keys = opts.telemetryConfig.keys,
|
||||||
|
format = opts.telemetryConfig.format || 'utc',
|
||||||
|
hints = opts.telemetryConfig.hints,
|
||||||
|
values;
|
||||||
|
|
||||||
|
// if utc, keep default
|
||||||
|
if(format === 'utc') {
|
||||||
|
// save for later if new keys
|
||||||
|
if(keys) {
|
||||||
|
format = requestedMocks.telemetry
|
||||||
|
.telemetry.values.find((vals) => vals.key === 'utc');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format = {
|
||||||
|
key: format,
|
||||||
|
name: "Time",
|
||||||
|
format: format === 'local' ? 'local-format' : format,
|
||||||
|
hints: {
|
||||||
|
domain: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keys) {
|
||||||
|
values = keys.map((key) => ({ key, name: key + ' attribute' }));
|
||||||
|
values.push(format); // add time format back in
|
||||||
|
} else {
|
||||||
|
values = requestedMocks.telemetry.telemetry.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hints) {
|
||||||
|
for(let val of values) {
|
||||||
|
if(hints[val.key]) {
|
||||||
|
val.hints = hints[val.key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestedMocks.telemetry.telemetry.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// overwrite any field keys
|
||||||
|
if(opts.overwrite) {
|
||||||
|
for(let mock in requestedMocks) {
|
||||||
|
if(opts.overwrite[mock]) {
|
||||||
|
for(let key in opts.overwrite[mock]) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(opts.overwrite[mock], key)) {
|
||||||
|
requestedMocks[mock][key] = opts.overwrite[mock][key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestedMocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXAMPLE:
|
||||||
|
// getMockTelemetry({
|
||||||
|
// name: 'My Telemetry',
|
||||||
|
// keys: ['test','other','yeah','sup'],
|
||||||
|
// count: 8,
|
||||||
|
// format: 'local'
|
||||||
|
// })
|
||||||
|
export function getMockTelemetry(opts = {}) {
|
||||||
|
let count = opts.count || 2,
|
||||||
|
format = opts.format || 'utc',
|
||||||
|
name = opts.name || 'Mock Telemetry Datum',
|
||||||
|
keyCount = 2,
|
||||||
|
keys = false,
|
||||||
|
telemetry = [];
|
||||||
|
|
||||||
|
if(opts.keys && Array.isArray(opts.keys)) {
|
||||||
|
keyCount = opts.keys.length;
|
||||||
|
keys = opts.keys;
|
||||||
|
} else if(opts.keyCount) {
|
||||||
|
keyCount = opts.keyCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let i = 1; i < count + 1; i++) {
|
||||||
|
let datum = {
|
||||||
|
[format]: i,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let k = 1; k < keyCount + 1; k++) {
|
||||||
|
let key = keys ? keys[k - 1] : 'some-key-' + k,
|
||||||
|
value = keys ? keys[k - 1] + ' value ' + i : 'some value ' + i + '-' + k;
|
||||||
|
datum[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry.push(datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
return telemetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy objects a bit more easily
|
||||||
|
function copyObj(obj) {
|
||||||
|
return JSON.parse(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add any other necessary types to this mockObjects object
|
||||||
|
function setMockObjects() {
|
||||||
|
return {
|
||||||
|
default: {
|
||||||
|
ladTable: {
|
||||||
|
identifier: { namespace: "", key: "lad-object"},
|
||||||
|
type: 'LadTable',
|
||||||
|
composition: []
|
||||||
|
},
|
||||||
|
ladTableSet: {
|
||||||
|
identifier: { namespace: "", key: "lad-set-object"},
|
||||||
|
type: 'LadTableSet',
|
||||||
|
composition: []
|
||||||
|
},
|
||||||
|
telemetry: {
|
||||||
|
identifier: { namespace: "", key: "telemetry-object"},
|
||||||
|
type: "test-telemetry-object",
|
||||||
|
name: "Test Telemetry Object",
|
||||||
|
telemetry: {
|
||||||
|
values: [{
|
||||||
|
key: "name",
|
||||||
|
name: "Name",
|
||||||
|
format: "string"
|
||||||
|
},{
|
||||||
|
key: "utc",
|
||||||
|
name: "Time",
|
||||||
|
format: "utc",
|
||||||
|
hints: {
|
||||||
|
domain: 1
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: "Some attribute 1",
|
||||||
|
key: "some-key-1",
|
||||||
|
hints: {
|
||||||
|
range: 1
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: "Some attribute 2",
|
||||||
|
key: "some-key-2"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
otherType: {
|
||||||
|
example: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user