Mct4307 Clear data and condition widget tests (#4597)

Co-authored-by: John Hill <john.c.hill@nasa.gov>
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
This commit is contained in:
Scott Bell 2022-01-11 19:17:43 +01:00 committed by GitHub
parent 176e8167f0
commit f42f291790
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 332 additions and 155 deletions

View File

@ -48,7 +48,7 @@ define([
let indicator = {
element: component.$mount().$el,
key: 'clear-data-indicator',
key: 'global-clear-indicator',
priority: openmct.priority.DEFAULT
};

View File

@ -0,0 +1,228 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, 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 ClearDataPlugin from './plugin.js';
import Vue from 'vue';
import { createOpenMct, resetApplicationState, createMouseEvent } from 'utils/testing';
describe('The Clear Data Plugin:', () => {
let clearDataPlugin;
describe('The clear data action:', () => {
let openmct;
let selection;
let mockObjectPath;
let clearDataAction;
let testViewObject;
beforeEach((done) => {
openmct = createOpenMct();
clearDataPlugin = new ClearDataPlugin(
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
{indicator: true}
);
openmct.install(clearDataPlugin);
clearDataAction = openmct.actions.getAction('clear-data-action');
testViewObject = [{
identifier: {
key: "foo-table",
namespace: ''
},
type: "table"
}];
openmct.router.path = testViewObject;
mockObjectPath = [
{
name: 'Mock Table',
type: 'table',
identifier: {
key: "foo-table",
namespace: ''
}
}
];
selection = [
{
context: {
item: mockObjectPath[0]
}
}
];
openmct.selection.select(selection);
openmct.on('start', done);
openmct.startHeadless();
});
afterEach(() => {
openmct.router.path = null;
return resetApplicationState(openmct);
});
it('is installed', () => {
expect(clearDataAction).toBeDefined();
});
it('is applicable on applicable objects', () => {
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
expect(gatheredActions.applicableActions['clear-data-action']).toBeDefined();
});
it('is not applicable on inapplicable objects', () => {
testViewObject = [{
identifier: {
key: "foo-widget",
namespace: ''
},
type: "widget"
}];
mockObjectPath = [
{
name: 'Mock Widget',
type: 'widget',
identifier: {
key: "foo-widget",
namespace: ''
}
}
];
selection = [
{
context: {
item: mockObjectPath[0]
}
}
];
openmct.selection.select(selection);
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
expect(gatheredActions.applicableActions['clear-data-action']).toBeUndefined();
});
it('is not applicable if object not in the selection path and not a layout', () => {
selection = [
{
context: {
item: {
name: 'Some Random Widget',
type: 'not-in-path-widget',
identifier: {
key: "something-else-widget",
namespace: ''
}
}
}
}
];
openmct.selection.select(selection);
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
expect(gatheredActions.applicableActions['clear-data-action']).toBeUndefined();
});
it('is applicable if object not in the selection path and is a layout', () => {
selection = [
{
context: {
item: {
name: 'Some Random Widget',
type: 'not-in-path-widget',
identifier: {
key: "something-else-widget",
namespace: ''
}
}
}
}
];
openmct.selection.select(selection);
testViewObject = [{
identifier: {
key: "foo-layout",
namespace: ''
},
type: "layout"
}];
openmct.router.path = testViewObject;
const gatheredActions = openmct.actions.getActionsCollection(mockObjectPath);
expect(gatheredActions.applicableActions['clear-data-action']).toBeDefined();
});
it('fires an event upon invocation', (done) => {
openmct.objectViews.on('clearData', (domainObject) => {
expect(domainObject).toEqual(testViewObject[0]);
done();
});
clearDataAction.invoke(testViewObject);
});
});
describe('The clear data indicator:', () => {
let openmct;
let appHolder;
beforeEach((done) => {
openmct = createOpenMct();
clearDataPlugin = new ClearDataPlugin(
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
{indicator: true}
);
openmct.install(clearDataPlugin);
appHolder = document.createElement('div');
document.body.appendChild(appHolder);
openmct.on('start', done);
openmct.start(appHolder);
});
it('installs', () => {
const globalClearIndicator = openmct.indicators.indicatorObjects
.find(indicator => indicator.key === 'global-clear-indicator').element;
expect(globalClearIndicator).toBeDefined();
});
it("renders its major elements", async () => {
await Vue.nextTick();
const indicatorClass = appHolder.querySelector('.c-indicator');
const iconClass = appHolder.querySelector('.icon-clear-data');
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
const buttonElement = indicatorLabel.querySelector('button');
const hasMajorElements = Boolean(indicatorClass && iconClass && buttonElement);
expect(hasMajorElements).toBe(true);
expect(buttonElement.innerText).toEqual('Clear Data');
});
it("clicking the button fires the global clear", (done) => {
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
const buttonElement = indicatorLabel.querySelector('button');
const clickEvent = createMouseEvent('click');
openmct.objectViews.on('clearData', () => {
// when we click the button, this event should fire
done();
});
buttonElement.dispatchEvent(clickEvent);
});
});
});

View File

@ -1,143 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, 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 ClearDataActionPlugin from '../plugin.js';
import ClearDataAction from '../ClearDataAction.js';
describe('When the Clear Data Plugin is installed,', () => {
const mockObjectViews = jasmine.createSpyObj('objectViews', ['emit']);
const mockIndicatorProvider = jasmine.createSpyObj('indicators', ['add']);
const mockActionsProvider = jasmine.createSpyObj('actions', ['register']);
const goodMockSelectionPath = [[{
context: {
item: {
identifier: {
key: 'apple',
namespace: ''
}
}
}
}]];
const openmct = {
objectViews: mockObjectViews,
indicators: mockIndicatorProvider,
priority: {
DEFAULT: 0
},
actions: mockActionsProvider,
install: function (plugin) {
plugin(this);
},
selection: {
get: function () {
return goodMockSelectionPath;
}
},
objects: {
areIdsEqual: function (obj1, obj2) {
return true;
}
}
};
const mockObjectPath = [
{
name: 'mockObject1',
type: 'apple'
},
{
name: 'mockObject2',
type: 'banana'
}
];
it('Global Clear Indicator is installed', () => {
openmct.install(ClearDataActionPlugin(openmct, {indicator: true}));
expect(mockIndicatorProvider.add).toHaveBeenCalled();
});
it('Clear Data context menu action is installed', () => {
openmct.install(ClearDataActionPlugin(openmct, []));
expect(mockActionsProvider.register).toHaveBeenCalled();
});
it('clear data action emits a clearData event when invoked', () => {
const action = new ClearDataAction(openmct);
action.invoke(mockObjectPath);
expect(mockObjectViews.emit).toHaveBeenCalledWith('clearData', mockObjectPath[0]);
});
it('clears data on applicable objects', () => {
let action = new ClearDataAction(openmct, ['apple']);
const actionApplies = action.appliesTo(mockObjectPath);
expect(actionApplies).toBe(true);
});
it('does not clear data on inapplicable objects', () => {
let action = new ClearDataAction(openmct, ['pineapple']);
const actionApplies = action.appliesTo(mockObjectPath);
expect(actionApplies).toBe(false);
});
it('does not clear data if not in the selection path and not a layout', () => {
openmct.objects = {
areIdsEqual: function (obj1, obj2) {
return false;
}
};
openmct.router = {
path: [{type: 'not-a-layout'}]
};
let action = new ClearDataAction(openmct, ['apple']);
const actionApplies = action.appliesTo(mockObjectPath);
expect(actionApplies).toBe(false);
});
it('does clear data if not in the selection path and is a layout', () => {
openmct.objects = {
areIdsEqual: function (obj1, obj2) {
return false;
}
};
openmct.router = {
path: [{type: 'layout'}]
};
let action = new ClearDataAction(openmct, ['apple']);
const actionApplies = action.appliesTo(mockObjectPath);
expect(actionApplies).toBe(true);
});
});

View File

@ -3,14 +3,17 @@ import ConditionWidgetPlugin from "./plugin";
import Vue from 'vue';
describe('the plugin', function () {
const CONDITION_WIDGET_KEY = 'conditionWidget';
let objectDef;
let element;
let child;
let openmct;
let mockObjectPath;
let mockConditionObjectDefinition;
let mockConditionObject;
let mockConditionObjectPath;
beforeEach((done) => {
mockObjectPath = [
mockConditionObjectPath = [
{
name: 'mock folder',
type: 'fake-folder',
@ -29,6 +32,61 @@ describe('the plugin', function () {
}
];
mockConditionObjectDefinition = {
name: 'Condition Widget',
key: 'conditionWidget',
creatable: true
};
mockConditionObject = {
"conditionWidget": {
"identifier": {
"namespace": "",
"key": "condition-widget-object"
},
"url": "https://nasa.github.io/openmct/",
"label": "Foo Widget",
"type": "conditionWidget",
"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"
}
]
}
}
};
const timeSystem = {
timeSystemKey: 'utc',
bounds: {
@ -58,19 +116,13 @@ describe('the plugin', function () {
return resetApplicationState(openmct);
});
let mockObject = {
name: 'Condition Widget',
key: 'conditionWidget',
creatable: true
};
it('defines a conditionWidget object type with the correct key', () => {
expect(objectDef.key).toEqual(mockObject.key);
expect(objectDef.key).toEqual(mockConditionObjectDefinition.key);
});
describe('the conditionWidget object', () => {
it('is creatable', () => {
expect(objectDef.creatable).toEqual(mockObject.creatable);
expect(objectDef.creatable).toEqual(mockConditionObjectDefinition.creatable);
});
});
@ -88,7 +140,7 @@ describe('the plugin', function () {
type: "conditionWidget"
};
const applicableViews = openmct.objectViews.get(testViewObject, mockObjectPath);
const applicableViews = openmct.objectViews.get(testViewObject, mockConditionObjectPath);
conditionWidgetView = applicableViews.find((viewProvider) => viewProvider.key === 'conditionWidget');
let view = conditionWidgetView.view(testViewObject, element);
view.show(child, true);
@ -100,4 +152,44 @@ describe('the plugin', function () {
expect(conditionWidgetView).toBeDefined();
});
});
it("should have a view provider for condition widget objects", () => {
const applicableViews = openmct.objectViews.get(mockConditionObject[CONDITION_WIDGET_KEY], []);
const conditionWidgetViewProvider = applicableViews.find(
(viewProvider) => viewProvider.key === CONDITION_WIDGET_KEY
);
expect(applicableViews.length).toEqual(1);
expect(conditionWidgetViewProvider).toBeDefined();
});
it("should render a view with a URL and label", async () => {
const urlParent = document.createElement('div');
const urlChild = document.createElement('div');
urlParent.appendChild(urlChild);
const applicableViews = openmct.objectViews.get(mockConditionObject[CONDITION_WIDGET_KEY], []);
const conditionWidgetViewProvider = applicableViews.find(
(viewProvider) => viewProvider.key === CONDITION_WIDGET_KEY
);
const conditionWidgetView = conditionWidgetViewProvider.view(mockConditionObject[CONDITION_WIDGET_KEY], [mockConditionObject[CONDITION_WIDGET_KEY]]);
conditionWidgetView.show(urlChild);
await Vue.nextTick();
const domainUrl = mockConditionObject[CONDITION_WIDGET_KEY].url;
expect(urlParent.innerHTML).toContain(`<a href="${domainUrl}"`);
const conditionWidgetRender = urlParent.querySelector('.c-condition-widget');
expect(conditionWidgetRender).toBeDefined();
expect(conditionWidgetRender.innerHTML).toContain('<div class="c-condition-widget__label">');
const conditionWidgetLabel = conditionWidgetRender.querySelector('.c-condition-widget__label');
expect(conditionWidgetLabel).toBeDefined();
const domainLabel = mockConditionObject[CONDITION_WIDGET_KEY].label;
expect(conditionWidgetLabel.textContent).toContain(domainLabel);
});
});