mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
[Conditionals] Increase performance, switch to TelemetryCollections (#7841)
* adding telemetry collections to condition manager * handling telemetry collection data not datum * adding from maaster * addressing PR comments * update unit test to work with telemetry collections * fixing tests * removing unnecessary addition * removing focused describe * removing focused it * fix weird test bleed * adding test for conditional styling * removing some auto fix es-lint * got a bit overzealous * clarification * using raf utility which handles it correctly and moving visiblity handling into the raf for consistency and performance * using raf correctly * removing raf, was causing issues * move the test and add some determinism * oops only * missed lint * got it! * fix comments * test(condStyling): stabilize test --------- Co-authored-by: John Hill <john.c.hill@nasa.gov> Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
This commit is contained in:
parent
43cc963328
commit
37b2660f27
@ -0,0 +1,177 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, 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.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding conditionSets and styling
|
||||
*/
|
||||
|
||||
import { createDomainObjectWithDefaults, setRealTimeMode } from '../../../../appActions.js';
|
||||
import { MISSION_TIME } from '../../../../constants.js';
|
||||
import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
||||
test.describe('Conditionally Styling, using a Condition Set', () => {
|
||||
let stateGenerator;
|
||||
let conditionSet;
|
||||
let displayLayout;
|
||||
const STATE_CHANGE_INTERVAL = '1';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Install the clock and set the time to the mission time such that the state generator will be controllable
|
||||
await page.clock.install({ time: MISSION_TIME });
|
||||
await page.clock.resume();
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
// Create Condition Set, State Generator, and Display Layout
|
||||
conditionSet = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Condition Set',
|
||||
name: 'Test Condition Set'
|
||||
});
|
||||
stateGenerator = await createDomainObjectWithDefaults(page, {
|
||||
type: 'State Generator',
|
||||
name: 'One Second State Generator'
|
||||
});
|
||||
// edit the state generator to have a 1 second update rate
|
||||
await page.getByTitle('More actions').click();
|
||||
await page.getByRole('menuitem', { name: 'Edit Properties...' }).click();
|
||||
await page.getByLabel('State Duration (seconds)', { exact: true }).fill(STATE_CHANGE_INTERVAL);
|
||||
await page.getByLabel('Save').click();
|
||||
|
||||
displayLayout = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
name: 'Test Display Layout'
|
||||
});
|
||||
});
|
||||
|
||||
test('Conditional styling, using a Condition Set, will style correctly based on the output @clock', async ({
|
||||
page
|
||||
}) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/7840'
|
||||
});
|
||||
|
||||
// set up the condition set to use the state generator
|
||||
await page.goto(conditionSet.url, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Add the State Generator to the Condition Set by dragging from the main tree
|
||||
await page.getByLabel('Show selected item in tree').click();
|
||||
await page
|
||||
.getByRole('tree', {
|
||||
name: 'Main Tree'
|
||||
})
|
||||
.getByRole('treeitem', {
|
||||
name: stateGenerator.name
|
||||
})
|
||||
.dragTo(page.locator('#conditionCollection'));
|
||||
|
||||
// Add the state generator to the first criterion such that there is a condition named 'OFF' when the state generator is off
|
||||
await page.getByLabel('Add Condition').click();
|
||||
await page
|
||||
.getByLabel('Criterion Telemetry Selection')
|
||||
.selectOption({ label: stateGenerator.name });
|
||||
await page.getByLabel('Criterion Metadata Selection').selectOption({ label: 'State' });
|
||||
await page.getByLabel('Criterion Comparison Selection').selectOption({ label: 'is' });
|
||||
await page.getByLabel('Condition Name Input').first().fill('OFF');
|
||||
await page.getByLabel('Save').click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
await searchAndLinkParameterToObject(page, stateGenerator.name, displayLayout.name);
|
||||
|
||||
//Add a box to the display layout
|
||||
await page.goto(displayLayout.url, { waitUntil: 'domcontentloaded' });
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
//Add a box to the display layout and move it to the right
|
||||
//TEMP: Click the layout such that the state generator is deselected
|
||||
await page.getByLabel('Test Display Layout Layout Grid').locator('div').nth(1).click();
|
||||
await page.getByLabel('Add Drawing Object').click();
|
||||
await page.getByText('Box').click();
|
||||
await page.getByLabel('X:').click();
|
||||
await page.getByLabel('X:').fill('10');
|
||||
await page.getByLabel('X:').press('Enter');
|
||||
|
||||
// set up conditional styling such that the box is red when the state generator condition is 'OFF'
|
||||
await page.getByRole('tab', { name: 'Styles' }).click();
|
||||
await page.getByRole('button', { name: 'Use Conditional Styling...' }).click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Expand My Items folder').click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel(`Preview ${conditionSet.name}`).click();
|
||||
await page.getByText('Ok').click();
|
||||
await page.getByLabel('Set background color').first().click();
|
||||
await page.getByLabel('#ff0000').click();
|
||||
await page.getByLabel('Save', { exact: true }).click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
await setRealTimeMode(page);
|
||||
|
||||
//Pause at a time when the state generator is 'OFF' which is 20 minutes in the future
|
||||
await page.clock.pauseAt(new Date(MISSION_TIME + 1200000));
|
||||
|
||||
const redBG = 'background-color: rgb(255, 0, 0);';
|
||||
const defaultBG = 'background-color: rgb(102, 102, 102);';
|
||||
const textElement = page.getByLabel('Alpha-numeric telemetry value').locator('div:first-child');
|
||||
const styledElement = page.getByLabel('Box', { exact: true });
|
||||
|
||||
await page.clock.resume();
|
||||
|
||||
// Check if the style is red when text is 'OFF'
|
||||
await expect(textElement).toHaveText('OFF');
|
||||
await waitForStyleChange(styledElement, redBG);
|
||||
|
||||
// Fast forward to the next state change
|
||||
await page.clock.fastForward(STATE_CHANGE_INTERVAL * 1000);
|
||||
|
||||
// Check if the style is not red when text is 'ON'
|
||||
await expect(textElement).toHaveText('ON');
|
||||
await waitForStyleChange(styledElement, defaultBG);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for the style of an element to change to the expected style.
|
||||
* @param {import('@playwright/test').Locator} element - The element to check.
|
||||
* @param {string} expectedStyle - The expected style to wait for.
|
||||
* @param {number} timeout - The timeout in milliseconds.
|
||||
*/
|
||||
async function waitForStyleChange(element, expectedStyle, timeout = 0) {
|
||||
await expect(async () => {
|
||||
const style = await element.getAttribute('style');
|
||||
|
||||
// eslint-disable-next-line playwright/prefer-web-first-assertions
|
||||
expect(style).toBe(expectedStyle);
|
||||
}).toPass({ timeout: 1000 }); // timeout allows for the style to be applied
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for telemetry and link it to an object. objectName should come from the domainObject.name function.
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {string} parameterName
|
||||
* @param {string} objectName
|
||||
*/
|
||||
async function searchAndLinkParameterToObject(page, parameterName, objectName) {
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).click();
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).fill(parameterName);
|
||||
await page.getByLabel('Object Results').getByText(parameterName).click();
|
||||
await page.getByLabel('More actions').click();
|
||||
await page.getByLabel('Create Link').click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Search Input').click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Search Input').fill(objectName);
|
||||
await page.getByLabel('Modal Overlay').getByLabel(`Navigate to ${objectName}`).click();
|
||||
await page.getByLabel('Save').click();
|
||||
}
|
@ -39,7 +39,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.shouldEvaluateNewTelemetry = this.shouldEvaluateNewTelemetry.bind(this);
|
||||
|
||||
this.compositionLoad = this.composition.load();
|
||||
this.subscriptions = {};
|
||||
this.telemetryCollections = {};
|
||||
this.telemetryObjects = {};
|
||||
this.testData = {
|
||||
conditionTestInputs: this.conditionSetDomainObject.configuration.conditionTestData,
|
||||
@ -48,55 +48,46 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
async requestLatestValue(endpoint) {
|
||||
const options = {
|
||||
subscribeToTelemetry(telemetryObject) {
|
||||
const keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
|
||||
if (this.telemetryCollections[keyString]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestOptions = {
|
||||
size: 1,
|
||||
strategy: 'latest'
|
||||
};
|
||||
const latestData = await this.openmct.telemetry.request(endpoint, options);
|
||||
|
||||
if (!latestData) {
|
||||
throw new Error('Telemetry request failed by returning a falsy response');
|
||||
}
|
||||
if (latestData.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.telemetryReceived(endpoint, latestData[0]);
|
||||
}
|
||||
|
||||
subscribeToTelemetry(endpoint) {
|
||||
const telemetryKeyString = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
if (this.subscriptions[telemetryKeyString]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const metadata = this.openmct.telemetry.getMetadata(endpoint);
|
||||
|
||||
this.telemetryObjects[telemetryKeyString] = Object.assign({}, endpoint, {
|
||||
telemetryMetaData: metadata ? metadata.valueMetadatas : []
|
||||
});
|
||||
|
||||
// get latest telemetry value (in case subscription is cached and no new data is coming in)
|
||||
this.requestLatestValue(endpoint);
|
||||
|
||||
this.subscriptions[telemetryKeyString] = this.openmct.telemetry.subscribe(
|
||||
endpoint,
|
||||
this.telemetryReceived.bind(this, endpoint)
|
||||
this.telemetryCollections[keyString] = this.openmct.telemetry.requestCollection(
|
||||
telemetryObject,
|
||||
requestOptions
|
||||
);
|
||||
|
||||
const metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
const telemetryMetaData = metadata ? metadata.valueMetadatas : [];
|
||||
|
||||
this.telemetryObjects[keyString] = { ...telemetryObject, telemetryMetaData };
|
||||
|
||||
this.telemetryCollections[keyString].on(
|
||||
'add',
|
||||
this.telemetryReceived.bind(this, telemetryObject)
|
||||
);
|
||||
this.telemetryCollections[keyString].load();
|
||||
|
||||
this.updateConditionTelemetryObjects();
|
||||
}
|
||||
|
||||
unsubscribeFromTelemetry(endpointIdentifier) {
|
||||
const id = this.openmct.objects.makeKeyString(endpointIdentifier);
|
||||
if (!this.subscriptions[id]) {
|
||||
console.log('no subscription to remove');
|
||||
|
||||
const keyString = this.openmct.objects.makeKeyString(endpointIdentifier);
|
||||
if (!this.telemetryCollections[keyString]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
delete this.telemetryObjects[id];
|
||||
this.telemetryCollections[keyString].destroy();
|
||||
this.telemetryCollections[keyString] = null;
|
||||
this.telemetryObjects[keyString] = null;
|
||||
this.removeConditionTelemetryObjects();
|
||||
|
||||
//force re-computation of condition set result as we might be in a state where
|
||||
@ -107,7 +98,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.timeSystems,
|
||||
this.openmct.time.getTimeSystem()
|
||||
);
|
||||
this.updateConditionResults({ id: id });
|
||||
this.updateConditionResults({ id: keyString });
|
||||
this.updateCurrentCondition(latestTimestamp);
|
||||
|
||||
if (Object.keys(this.telemetryObjects).length === 0) {
|
||||
@ -410,11 +401,13 @@ export default class ConditionManager extends EventEmitter {
|
||||
return this.openmct.time.getBounds().end >= currentTimestamp;
|
||||
}
|
||||
|
||||
telemetryReceived(endpoint, datum) {
|
||||
telemetryReceived(endpoint, data) {
|
||||
if (!this.isTelemetryUsed(endpoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const datum = data[0];
|
||||
|
||||
const normalizedDatum = this.createNormalizedDatum(datum, endpoint);
|
||||
const timeSystemKey = this.openmct.time.getTimeSystem().key;
|
||||
let timestamp = {};
|
||||
@ -507,8 +500,9 @@ export default class ConditionManager extends EventEmitter {
|
||||
destroy() {
|
||||
this.composition.off('add', this.subscribeToTelemetry, this);
|
||||
this.composition.off('remove', this.unsubscribeFromTelemetry, this);
|
||||
Object.values(this.subscriptions).forEach((unsubscribe) => unsubscribe());
|
||||
delete this.subscriptions;
|
||||
Object.values(this.telemetryCollections).forEach((telemetryCollection) =>
|
||||
telemetryCollection.destroy()
|
||||
);
|
||||
|
||||
this.conditions.forEach((condition) => {
|
||||
condition.destroy();
|
||||
|
@ -720,50 +720,69 @@ describe('the plugin', function () {
|
||||
};
|
||||
});
|
||||
|
||||
it('should evaluate as old when telemetry is not received in the allotted time', (done) => {
|
||||
it('should evaluate as old when telemetry is not received in the allotted time', async () => {
|
||||
let onAddResolve;
|
||||
const onAddCalledPromise = new Promise((resolve) => {
|
||||
onAddResolve = resolve;
|
||||
});
|
||||
const mockTelemetryCollection = {
|
||||
load: jasmine.createSpy('load'),
|
||||
on: jasmine.createSpy('on').and.callFake((event, callback) => {
|
||||
if (event === 'add') {
|
||||
onAddResolve();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
openmct.telemetry = jasmine.createSpyObj('telemetry', [
|
||||
'subscribe',
|
||||
'getMetadata',
|
||||
'request',
|
||||
'getValueFormatter',
|
||||
'abortAllRequests'
|
||||
'abortAllRequests',
|
||||
'requestCollection'
|
||||
]);
|
||||
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
||||
openmct.telemetry.getMetadata.and.returnValue({
|
||||
...testTelemetryObject.telemetry,
|
||||
valueMetadatas: []
|
||||
valueMetadatas: testTelemetryObject.telemetry.values,
|
||||
valuesForHints: jasmine
|
||||
.createSpy('valuesForHints')
|
||||
.and.returnValue(testTelemetryObject.telemetry.values),
|
||||
value: jasmine.createSpy('value').and.callFake((key) => {
|
||||
return testTelemetryObject.telemetry.values.find((value) => value.key === key);
|
||||
})
|
||||
});
|
||||
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
||||
openmct.telemetry.requestCollection.and.returnValue(mockTelemetryCollection);
|
||||
openmct.telemetry.getValueFormatter.and.returnValue({
|
||||
parse: function (value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||
conditionMgr.telemetryObjects = {
|
||||
'test-object': testTelemetryObject
|
||||
};
|
||||
conditionMgr.updateConditionTelemetryObjects();
|
||||
setTimeout(() => {
|
||||
expect(mockListener).toHaveBeenCalledWith({
|
||||
output: 'Any old telemetry',
|
||||
id: {
|
||||
namespace: '',
|
||||
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
||||
},
|
||||
conditionId: '39584410-cbf9-499e-96dc-76f27e69885d',
|
||||
utc: undefined
|
||||
});
|
||||
done();
|
||||
}, 400);
|
||||
// Wait for the 'on' callback to be called
|
||||
await onAddCalledPromise;
|
||||
|
||||
// Simulate the passage of time and no data received
|
||||
await new Promise((resolve) => setTimeout(resolve, 400));
|
||||
|
||||
expect(mockListener).toHaveBeenCalledWith({
|
||||
output: 'Any old telemetry',
|
||||
id: {
|
||||
namespace: '',
|
||||
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
||||
},
|
||||
conditionId: '39584410-cbf9-499e-96dc-76f27e69885d',
|
||||
utc: undefined
|
||||
});
|
||||
});
|
||||
|
||||
it('should not evaluate as old when telemetry is received in the allotted time', (done) => {
|
||||
openmct.telemetry.getMetadata = jasmine.createSpy('getMetadata');
|
||||
openmct.telemetry.getMetadata.and.returnValue({
|
||||
...testTelemetryObject.telemetry,
|
||||
valueMetadatas: testTelemetryObject.telemetry.values
|
||||
});
|
||||
it('should not evaluate as old when telemetry is received in the allotted time', async () => {
|
||||
const testDatum = {
|
||||
'some-key2': '',
|
||||
utc: 1,
|
||||
@ -771,8 +790,49 @@ describe('the plugin', function () {
|
||||
'some-key': null,
|
||||
id: 'test-object'
|
||||
};
|
||||
openmct.telemetry.request = jasmine.createSpy('request');
|
||||
|
||||
let onAddResolve;
|
||||
let onAddCallback;
|
||||
const onAddCalledPromise = new Promise((resolve) => {
|
||||
onAddResolve = resolve;
|
||||
});
|
||||
|
||||
const mockTelemetryCollection = {
|
||||
load: jasmine.createSpy('load'),
|
||||
on: jasmine.createSpy('on').and.callFake((event, callback) => {
|
||||
if (event === 'add') {
|
||||
onAddCallback = callback;
|
||||
onAddResolve();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
openmct.telemetry = jasmine.createSpyObj('telemetry', [
|
||||
'getMetadata',
|
||||
'getValueFormatter',
|
||||
'request',
|
||||
'subscribe',
|
||||
'requestCollection'
|
||||
]);
|
||||
openmct.telemetry.subscribe.and.returnValue(function () {});
|
||||
openmct.telemetry.request.and.returnValue(Promise.resolve([testDatum]));
|
||||
openmct.telemetry.getMetadata.and.returnValue({
|
||||
...testTelemetryObject.telemetry,
|
||||
valueMetadatas: testTelemetryObject.telemetry.values,
|
||||
valuesForHints: jasmine
|
||||
.createSpy('valuesForHints')
|
||||
.and.returnValue(testTelemetryObject.telemetry.values),
|
||||
value: jasmine.createSpy('value').and.callFake((key) => {
|
||||
return testTelemetryObject.telemetry.values.find((value) => value.key === key);
|
||||
})
|
||||
});
|
||||
openmct.telemetry.requestCollection.and.returnValue(mockTelemetryCollection);
|
||||
openmct.telemetry.getValueFormatter.and.returnValue({
|
||||
parse: function (value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
||||
const date = 1;
|
||||
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input =
|
||||
['0.4'];
|
||||
@ -782,19 +842,25 @@ describe('the plugin', function () {
|
||||
'test-object': testTelemetryObject
|
||||
};
|
||||
conditionMgr.updateConditionTelemetryObjects();
|
||||
conditionMgr.telemetryReceived(testTelemetryObject, testDatum);
|
||||
setTimeout(() => {
|
||||
expect(mockListener).toHaveBeenCalledWith({
|
||||
output: 'Default',
|
||||
id: {
|
||||
namespace: '',
|
||||
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
||||
},
|
||||
conditionId: '2532d90a-e0d6-4935-b546-3123522da2de',
|
||||
utc: date
|
||||
});
|
||||
done();
|
||||
}, 300);
|
||||
|
||||
// Wait for the 'on' callback to be called
|
||||
await onAddCalledPromise;
|
||||
|
||||
// Simulate receiving telemetry data
|
||||
onAddCallback([testDatum]);
|
||||
|
||||
// Wait a bit for the condition manager to process the data
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
expect(mockListener).toHaveBeenCalledWith({
|
||||
output: 'Default',
|
||||
id: {
|
||||
namespace: '',
|
||||
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
||||
},
|
||||
conditionId: '2532d90a-e0d6-4935-b546-3123522da2de',
|
||||
utc: date
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -902,17 +968,25 @@ describe('the plugin', function () {
|
||||
openmct.telemetry.getMetadata = jasmine.createSpy('getMetadata');
|
||||
openmct.telemetry.getMetadata.and.returnValue({
|
||||
...testTelemetryObject.telemetry,
|
||||
valueMetadatas: []
|
||||
valueMetadatas: testTelemetryObject.telemetry.values,
|
||||
valuesForHints: jasmine
|
||||
.createSpy('valuesForHints')
|
||||
.and.returnValue(testTelemetryObject.telemetry.values),
|
||||
value: jasmine.createSpy('value').and.callFake((key) => {
|
||||
return testTelemetryObject.telemetry.values.find((value) => value.key === key);
|
||||
})
|
||||
});
|
||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||
conditionMgr.telemetryObjects = {
|
||||
'test-object': testTelemetryObject
|
||||
};
|
||||
conditionMgr.updateConditionTelemetryObjects();
|
||||
conditionMgr.telemetryReceived(testTelemetryObject, {
|
||||
'some-key': 2,
|
||||
utc: date
|
||||
});
|
||||
conditionMgr.telemetryReceived(testTelemetryObject, [
|
||||
{
|
||||
'some-key': 2,
|
||||
utc: date
|
||||
}
|
||||
]);
|
||||
let result = conditionMgr.conditions.map((condition) => condition.result);
|
||||
expect(result[2]).toBeUndefined();
|
||||
});
|
||||
@ -1002,26 +1076,37 @@ describe('the plugin', function () {
|
||||
}
|
||||
};
|
||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
||||
// const mockTransactionService = jasmine.createSpyObj(
|
||||
// 'transactionService',
|
||||
// ['commit']
|
||||
// );
|
||||
openmct.telemetry = jasmine.createSpyObj('telemetry', [
|
||||
'isTelemetryObject',
|
||||
'request',
|
||||
'subscribe',
|
||||
'getMetadata',
|
||||
'getValueFormatter',
|
||||
'request'
|
||||
'requestCollection'
|
||||
]);
|
||||
openmct.telemetry.isTelemetryObject.and.returnValue(true);
|
||||
openmct.telemetry.subscribe.and.returnValue(function () {});
|
||||
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
||||
openmct.telemetry.isTelemetryObject.and.returnValue(true);
|
||||
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry);
|
||||
openmct.telemetry.getMetadata.and.returnValue({
|
||||
...testTelemetryObject.telemetry,
|
||||
valueMetadatas: testTelemetryObject.telemetry.values,
|
||||
valuesForHints: jasmine
|
||||
.createSpy('valuesForHints')
|
||||
.and.returnValue(testTelemetryObject.telemetry.values),
|
||||
value: jasmine.createSpy('value').and.callFake((key) => {
|
||||
return testTelemetryObject.telemetry.values.find((value) => value.key === key);
|
||||
})
|
||||
});
|
||||
openmct.telemetry.getValueFormatter.and.returnValue({
|
||||
parse: function (value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry);
|
||||
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
||||
openmct.telemetry.requestCollection.and.returnValue({
|
||||
load: jasmine.createSpy('load'),
|
||||
on: jasmine.createSpy('on')
|
||||
});
|
||||
|
||||
const styleRuleManger = new StyleRuleManager(stylesObject, openmct, null, true);
|
||||
spyOn(styleRuleManger, 'subscribeToConditionSet');
|
||||
|
@ -128,35 +128,22 @@ export default {
|
||||
}
|
||||
},
|
||||
updateStyle(styleObj) {
|
||||
let elemToStyle = this.getStyleReceiver();
|
||||
const elemToStyle = this.getStyleReceiver();
|
||||
|
||||
if (!styleObj || elemToStyle === undefined) {
|
||||
if (!styleObj || !elemToStyle) {
|
||||
return;
|
||||
}
|
||||
// handle visibility separately
|
||||
if (styleObj.isStyleInvisible !== undefined) {
|
||||
elemToStyle.classList.toggle(STYLE_CONSTANTS.isStyleInvisible, styleObj.isStyleInvisible);
|
||||
styleObj.isStyleInvisible = null;
|
||||
}
|
||||
|
||||
let keys = Object.keys(styleObj);
|
||||
|
||||
keys.forEach((key) => {
|
||||
if (elemToStyle) {
|
||||
if (typeof styleObj[key] === 'string' && styleObj[key].indexOf('__no_value') > -1) {
|
||||
if (elemToStyle.style[key]) {
|
||||
elemToStyle.style[key] = '';
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!styleObj.isStyleInvisible &&
|
||||
elemToStyle.classList.contains(STYLE_CONSTANTS.isStyleInvisible)
|
||||
) {
|
||||
elemToStyle.classList.remove(STYLE_CONSTANTS.isStyleInvisible);
|
||||
} else if (
|
||||
styleObj.isStyleInvisible &&
|
||||
!elemToStyle.classList.contains(styleObj.isStyleInvisible)
|
||||
) {
|
||||
elemToStyle.classList.add(styleObj.isStyleInvisible);
|
||||
}
|
||||
|
||||
elemToStyle.style[key] = styleObj[key];
|
||||
}
|
||||
Object.entries(styleObj).forEach(([key, value]) => {
|
||||
if (typeof value !== 'string' || !value.includes('__no_value')) {
|
||||
elemToStyle.style[key] = value;
|
||||
} else {
|
||||
elemToStyle.style[key] = ''; // remove the property
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user