Adds tests for Condition class

This commit is contained in:
Joshi 2020-01-10 10:43:55 -08:00
parent 55a674ba7b
commit 91c877f234
3 changed files with 173 additions and 48 deletions

View File

@ -64,6 +64,7 @@
"request": "^2.69.0",
"split": "^1.0.0",
"style-loader": "^1.0.1",
"uuid": "^3.3.3",
"v8-compile-cache": "^1.1.0",
"vue": "2.5.6",
"vue-loader": "^15.2.6",

View File

@ -21,9 +21,8 @@
*****************************************************************************/
import * as EventEmitter from 'eventemitter3';
import UUID from 'uuid';
import uuid from 'uuid';
import TelemetryCriterion from "@/plugins/condition/criterion/TelemetryCriterion";
import {computeConditionForAll, computeConditionForAny} from 'utils/evaluator'
import { TRIGGER } from "@/plugins/condition/utils/constants";
/*
@ -31,12 +30,10 @@ import { TRIGGER } from "@/plugins/condition/utils/constants";
* trigger: 'any'/'all',
* criteria: [
* {
* object: {
* operator: '',
* input: '',
* metaDataKey: '',
* telemetryObjectKey: 'someTelemetryObjectKey'
* }
* operation: '',
* input: '',
* metaDataKey: '',
* key: 'someTelemetryObjectKey'
* }
* ]
* }
@ -47,8 +44,12 @@ export default class Condition extends EventEmitter {
super();
this.openmct = openmct;
this.id = new UUID();
this.criteriaMap = conditionDefinition.criteria ? this.createCriteria(conditionDefinition.criteria) : {};
this.id = uuid();
if (conditionDefinition.criteria) {
this.createCriteria(conditionDefinition.criteria);
} else {
this.criteria = [];
}
this.trigger = conditionDefinition.trigger;
this.result = null;
}
@ -60,13 +61,13 @@ export default class Condition extends EventEmitter {
}
}
generateNewCriterion() {
generateCriterion(criterionDefinition) {
return {
id: new UUID(),
object: '',
key: '',
operation: '',
values: []
id: uuid(),
operation: criterionDefinition.operation || '',
input: criterionDefinition.input === undefined ? [] : criterionDefinition.input,
metaDataKey: criterionDefinition.metaDataKey || '',
key: criterionDefinition.key || ''
};
}
@ -85,23 +86,43 @@ export default class Condition extends EventEmitter {
* adds criterion to the condition.
*/
addCriterion(criterionDefinition) {
if (!criterionDefinition) {
criterionDefinition = this.generateNewCriterion();
let criterionDefinitionWithId = this.generateCriterion(criterionDefinition || null);
let criterion = new TelemetryCriterion(criterionDefinitionWithId, this.openmct);
criterion.on('criterionUpdated', this.handleCriterionUpdated);
if (!this.criteria) {
this.criteria = [];
}
let criterion = new TelemetryCriterion(criterionDefinition.object, this.openmct);
criterion.on('criterion::Update', this.handleCriterionUpdated);
this.criteriaMap[criterionDefinition.id] = criterion;
this.criteria.push(criterion);
this.handleConditionUpdated();
return criterionDefinition.id;
return criterionDefinitionWithId.id;
}
findCriterion(id) {
return this.criteriaMap[id] || null;
let criterion;
for (let i=0, ii=this.criteria.length; i < ii; i ++) {
if (this.criteria[i].id === id) {
criterion = {
item: this.criteria[i],
index: i
}
}
}
return criterion;
}
updateCriterion(id, criterionDefinition) {
if (this.destroyCriterion(id)) {
this.criteriaMap[id] = new TelemetryCriterion(criterionDefinition.object, this.openmct);
let found = this.findCriterion(id);
if (found) {
const newCriterionDefinition = this.generateCriterion(criterionDefinition);
let newCriterion = new TelemetryCriterion(newCriterionDefinition, this.openmct);
let criterion = found.item;
criterion.unsubscribe();
criterion.off('criterionUpdated', (result) => {
this.handleCriterionUpdated(id, result);
});
this.criteria.splice(found.index, 1, newCriterion);
this.handleConditionUpdated();
}
}
@ -113,14 +134,14 @@ export default class Condition extends EventEmitter {
}
destroyCriterion(id) {
let criterion = this.findCriterion(id);
const criterionId = id;
if (criterion) {
let found = this.findCriterion(id);
if (found) {
let criterion = found.item;
criterion.unsubscribe();
criterion.off('criterion::Update', (result) => {
this.handleCriterionUpdated(criterionId, result);
criterion.off('criterionUpdated', (result) => {
this.handleCriterionUpdated(id, result);
});
delete this.criteriaMap[id];
this.criteria.splice(found.index, 1);
return true;
}
return false;
@ -135,41 +156,33 @@ export default class Condition extends EventEmitter {
handleConditionUpdated() {
// trigger an updated event so that consumers can react accordingly
this.emitResult();
}
getCriteria() {
let criteria = [];
for(let id in this.criteriaMap) {
if (this.criteriaMap.hasOwnProperty(id) && this.criteriaMap[id]) {
criteria.push(this.criteriaMap[id]);
}
}
return criteria;
return this.criteria;
}
destroyCriteria() {
let success = true;
for(let id in this.criteriaMap) {
if (this.criteriaMap.hasOwnProperty(id) && this.criteriaMap[id]) {
success = success && this.destroyCriterion(this.criteriaMap[id]);
}
//looping through the array backwards since destroyCriterion modifies the criteria array
for (let i=this.criteria.length-1; i >= 0; i--) {
success = success && this.destroyCriterion(this.criteria[i].id);
}
return success;
}
//TODO: implement as part of the evaluator class task.
evaluate() {
let criteria = this.getCriteria();
if (this.trigger === TRIGGER.ANY) {
this.result = computeConditionForAny(criteria);
this.result = false;
} else if (this.trigger === TRIGGER.ALL) {
this.result = computeConditionForAll(criteria);
this.result = false;
}
}
emitResult(data, error) {
this.emit('condition::Update', {
this.emit('conditionUpdated', {
identifier: this.id,
data: data,
error: error

View File

@ -0,0 +1,111 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2019, 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 Condition from "./Condition";
import {TRIGGER} from "./utils/constants";
import TelemetryCriterion from "./criterion/TelemetryCriterion";
let openmct = {},
mockListener,
testConditionDefinition,
testTelemetryObject,
conditionObj;
describe("The condition", function () {
beforeEach (() => {
mockListener = jasmine.createSpy('listener');
testTelemetryObject = {
identifier:{ namespace: "", key: "test-object"},
type: "test-object",
name: "Test Object",
telemetry: {
values: [{
key: "some-key",
name: "Some attribute",
hints: {
domain: 1
}
}, {
key: "some-other-key",
name: "Another attribute",
hints: {
range: 1
}
}]
}
};
openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString']);
openmct.objects.get.and.returnValue(testTelemetryObject);
openmct.objects.makeKeyString.and.returnValue(testTelemetryObject.identifier.key);
openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject']);
openmct.telemetry.isTelemetryObject.and.returnValue(true);
testConditionDefinition = {
trigger: TRIGGER.ANY,
criteria: [
{
operation: 'equalTo',
input: false,
metaDataKey: 'value',
key: testTelemetryObject.identifier
}
]
};
conditionObj = new Condition(
testConditionDefinition,
openmct
);
conditionObj.on('conditionUpdated', mockListener);
});
it("generates criteria with an id", function () {
const testCriterion = testConditionDefinition.criteria[0];
let criterion = conditionObj.generateCriterion(testCriterion);
expect(criterion.id).toBeDefined();
expect(criterion.operation).toEqual(testCriterion.operation);
expect(criterion.input).toEqual(testCriterion.input);
expect(criterion.metaDataKey).toEqual(testCriterion.metaDataKey);
expect(criterion.key).toEqual(testCriterion.key);
});
it("initializes with an id", function () {
expect(conditionObj.id).toBeDefined();
});
it("initializes with criteria from the condition definition", function () {
expect(conditionObj.criteria.length).toEqual(1);
let criterion = conditionObj.criteria[0];
expect(criterion instanceof TelemetryCriterion).toBeTrue();
expect(criterion.operator).toEqual(testConditionDefinition.operator);
expect(criterion.input).toEqual(testConditionDefinition.input);
expect(criterion.metaDataKey).toEqual(testConditionDefinition.metaDataKey);
expect(criterion.key).toEqual(testConditionDefinition.key);
});
it("initializes with the trigger from the condition definition", function () {
expect(conditionObj.trigger).toEqual(testConditionDefinition.trigger);
});
});