mirror of
https://github.com/nasa/openmct.git
synced 2025-01-31 08:25:31 +00:00
[Styles] add unit tests (#3557)
* unit tests for inspector styles feature * add mock capability for local storage Co-authored-by: Deep Tailor <deep.j.tailor@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
71392915c1
commit
7ca559fbe4
218
src/ui/inspector/InspectorStylesSpec.js
Normal file
218
src/ui/inspector/InspectorStylesSpec.js
Normal file
@ -0,0 +1,218 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
import {
|
||||
createOpenMct,
|
||||
resetApplicationState
|
||||
} from 'utils/testing';
|
||||
import {
|
||||
mockLocalStorage
|
||||
} from 'utils/testing/mockLocalStorage';
|
||||
import {
|
||||
mockTelemetryTableSelection,
|
||||
mockMultiSelectionSameStyles,
|
||||
mockMultiSelectionMixedStyles,
|
||||
mockMultiSelectionNonSpecificStyles,
|
||||
mockStyle
|
||||
} from './InspectorStylesSpecMocks';
|
||||
import Vue from 'vue';
|
||||
import StylesView from '@/plugins/condition/components/inspector/StylesView.vue';
|
||||
import SavedStylesView from '@/ui/inspector/styles/SavedStylesView.vue';
|
||||
import stylesManager from '@/ui/inspector/styles/StylesManager';
|
||||
|
||||
describe("the inspector", () => {
|
||||
let openmct;
|
||||
let selection;
|
||||
let stylesViewComponent;
|
||||
let savedStylesViewComponent;
|
||||
|
||||
mockLocalStorage();
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
|
||||
it("should allow a style to be saved", () => {
|
||||
selection = mockTelemetryTableSelection;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(0);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should display all saved styles", () => {
|
||||
selection = mockTelemetryTableSelection;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(0);
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should allow a saved style to be applied", () => {
|
||||
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
|
||||
|
||||
selection = mockTelemetryTableSelection;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleSelectorComponent = savedStylesViewComponent.$children[0].$children[0];
|
||||
|
||||
styleSelectorComponent.selectStyle();
|
||||
|
||||
savedStylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const styles = styleEditorComponent.$children.filter(component => component.options.value === mockStyle.color);
|
||||
|
||||
expect(styles.length).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should allow a saved style to be deleted", () => {
|
||||
selection = mockTelemetryTableSelection;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
|
||||
savedStylesViewComponent.$children[0].deleteStyle(0);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(0);
|
||||
});
|
||||
|
||||
it("should prevent a style from being saved when the number of saved styles is at the limit", () => {
|
||||
spyOn(SavedStylesView.methods, 'showLimitReachedDialog').and.callThrough();
|
||||
|
||||
selection = mockTelemetryTableSelection;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
}
|
||||
|
||||
expect(SavedStylesView.methods.showLimitReachedDialog).not.toHaveBeenCalled();
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(20);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
expect(SavedStylesView.methods.showLimitReachedDialog).toHaveBeenCalled();
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(20);
|
||||
});
|
||||
|
||||
it("should allow styles from multi-selections to be saved", () => {
|
||||
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
|
||||
|
||||
selection = mockMultiSelectionSameStyles;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
|
||||
expect(saveStyleButton.$listeners.click).not.toBe(undefined);
|
||||
|
||||
saveStyleButton.$listeners.click();
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should prevent mixed styles from being saved", () => {
|
||||
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
|
||||
|
||||
selection = mockMultiSelectionMixedStyles;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
|
||||
expect(saveStyleButton.$listeners.click).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
it("should prevent non-specific styles from being saved", () => {
|
||||
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
|
||||
|
||||
selection = mockMultiSelectionNonSpecificStyles;
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
|
||||
expect(saveStyleButton.$listeners.click).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
function createViewComponent(component) {
|
||||
const element = document.createElement('div');
|
||||
const child = document.createElement('div');
|
||||
element.appendChild(child);
|
||||
|
||||
const config = {
|
||||
provide: {
|
||||
openmct,
|
||||
selection,
|
||||
stylesManager
|
||||
},
|
||||
el: element,
|
||||
components: {},
|
||||
template: `<${component.name} />`
|
||||
};
|
||||
|
||||
config.components[component.name] = component;
|
||||
|
||||
return new Vue(config).$mount();
|
||||
}
|
||||
});
|
204
src/ui/inspector/InspectorStylesSpecMocks.js
Normal file
204
src/ui/inspector/InspectorStylesSpecMocks.js
Normal file
@ -0,0 +1,204 @@
|
||||
export const mockTelemetryTableSelection = [
|
||||
[{
|
||||
context: {
|
||||
item: {
|
||||
configuration: {},
|
||||
type: 'table',
|
||||
identifier: {
|
||||
key: 'mock-telemetry-table-1',
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
];
|
||||
|
||||
export const mockStyle = {
|
||||
backgroundColor: '#ff0000',
|
||||
border: '#ff0000',
|
||||
color: '#ff0000'
|
||||
};
|
||||
|
||||
const mockDisplayLayoutPath = {
|
||||
context: {
|
||||
item: {
|
||||
identifier: {
|
||||
key: "6af3200d-928b-4ff0-8ed0-b94a0e6752d1",
|
||||
namespace: ""
|
||||
},
|
||||
type: "layout",
|
||||
configuration: {
|
||||
items: [
|
||||
{
|
||||
id: "dd3202e5-40d0-4112-8951-00f0f1ed6a29",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
},
|
||||
{
|
||||
id: "b522d636-90b2-4f5f-9588-2a0345c30f87",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
},
|
||||
{
|
||||
id: "537b7596-b442-44fe-b464-07f56bdc67c8",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
},
|
||||
{
|
||||
id: "3f17162f-a822-4e39-8332-6aa39b79d022",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
},
|
||||
{
|
||||
id: "c1c5acd8-a14b-450c-8c94-ce0075dd9912",
|
||||
type: "text-view",
|
||||
fontSize: "8",
|
||||
font: "monospace-bold"
|
||||
}
|
||||
],
|
||||
objectStyles: {
|
||||
"dd3202e5-40d0-4112-8951-00f0f1ed6a29": {
|
||||
staticStyle: {
|
||||
style: {
|
||||
backgroundColor: "#0000ff",
|
||||
border: "1px solid #0000ff"
|
||||
}
|
||||
}
|
||||
},
|
||||
"b522d636-90b2-4f5f-9588-2a0345c30f87": {
|
||||
staticStyle: {
|
||||
style: {
|
||||
backgroundColor: "#ff0000",
|
||||
border: "1px solid #ff0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"537b7596-b442-44fe-b464-07f56bdc67c8": {
|
||||
staticStyle: {
|
||||
style: {
|
||||
backgroundColor: "#ff0000",
|
||||
border: "1px solid #ff0000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"3f17162f-a822-4e39-8332-6aa39b79d022": {
|
||||
staticStyle: {
|
||||
style: {
|
||||
backgroundColor: "#0000ff",
|
||||
border: "1px solid #0000ff",
|
||||
color: "#0000ff"
|
||||
}
|
||||
}
|
||||
},
|
||||
"c1c5acd8-a14b-450c-8c94-ce0075dd9912": {
|
||||
staticStyle: {
|
||||
style: {
|
||||
backgroundColor: "#0000ff",
|
||||
border: "1px solid #0000ff",
|
||||
color: "#0000ff"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
supportsMultiSelect: true
|
||||
}
|
||||
};
|
||||
|
||||
const mockTextBox1Path = {
|
||||
context: {
|
||||
index: 0,
|
||||
layoutItem: {
|
||||
id: "dd3202e5-40d0-4112-8951-00f0f1ed6a29",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockTextBox2Path = {
|
||||
context: {
|
||||
index: 1,
|
||||
layoutItem: {
|
||||
id: "b522d636-90b2-4f5f-9588-2a0345c30f87",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockTextBox3Path = {
|
||||
context: {
|
||||
index: 2,
|
||||
layoutItem: {
|
||||
id: "537b7596-b442-44fe-b464-07f56bdc67c8",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockTextBox4Path = {
|
||||
context: {
|
||||
index: 3,
|
||||
layoutItem: {
|
||||
id: "3f17162f-a822-4e39-8332-6aa39b79d022",
|
||||
type: "text-view",
|
||||
fontSize: "default",
|
||||
font: "default"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockTextBox5Path = {
|
||||
context: {
|
||||
index: 4,
|
||||
layoutItem: {
|
||||
id: "c1c5acd8-a14b-450c-8c94-ce0075dd9912",
|
||||
type: "text-view",
|
||||
fontSize: "8",
|
||||
font: "default-bold"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const mockMultiSelectionSameStyles = [
|
||||
[
|
||||
mockTextBox2Path,
|
||||
mockDisplayLayoutPath
|
||||
],
|
||||
[
|
||||
mockTextBox3Path,
|
||||
mockDisplayLayoutPath
|
||||
]
|
||||
];
|
||||
|
||||
export const mockMultiSelectionMixedStyles = [
|
||||
[
|
||||
mockTextBox1Path,
|
||||
mockDisplayLayoutPath
|
||||
],
|
||||
[
|
||||
mockTextBox2Path,
|
||||
mockDisplayLayoutPath
|
||||
]
|
||||
];
|
||||
|
||||
export const mockMultiSelectionNonSpecificStyles = [
|
||||
[
|
||||
mockTextBox4Path,
|
||||
mockDisplayLayoutPath
|
||||
],
|
||||
[
|
||||
mockTextBox5Path,
|
||||
mockDisplayLayoutPath
|
||||
]
|
||||
];
|
@ -21,6 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import MCT from 'MCT';
|
||||
|
||||
let nativeFunctions = [];
|
||||
let mockObjects = setMockObjects();
|
||||
|
||||
|
33
src/utils/testing/mockLocalStorage.js
Normal file
33
src/utils/testing/mockLocalStorage.js
Normal file
@ -0,0 +1,33 @@
|
||||
export function mockLocalStorage() {
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(Storage.prototype, 'getItem').and.callFake(getItem);
|
||||
spyOn(Storage.prototype, 'setItem').and.callFake(setItem);
|
||||
spyOn(Storage.prototype, 'removeItem').and.callFake(removeItem);
|
||||
spyOn(Storage.prototype, 'clear').and.callFake(clear);
|
||||
|
||||
store = {};
|
||||
|
||||
function getItem(key) {
|
||||
return store[key];
|
||||
}
|
||||
|
||||
function setItem(key, value) {
|
||||
store[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
||||
}
|
||||
|
||||
function removeItem(key) {
|
||||
store[key] = undefined;
|
||||
delete store[key];
|
||||
}
|
||||
|
||||
function clear() {
|
||||
store = {};
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
store = undefined;
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user