mirror of
https://github.com/nasa/openmct.git
synced 2025-05-13 05:53:18 +00:00
* touch every file on earth to update copyright * update one more * pick up 2017 2018 2019 * revert fuchs copyright * revert other bundle copyrights * somehow missed one
406 lines
15 KiB
JavaScript
406 lines
15 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT, Copyright (c) 2014-2022, 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, createMouseEvent, resetApplicationState } from 'utils/testing';
|
|
import notebookPlugin from './plugin';
|
|
import Vue from 'vue';
|
|
|
|
describe("Notebook plugin:", () => {
|
|
let openmct;
|
|
let notebookDefinition;
|
|
let element;
|
|
let child;
|
|
let appHolder;
|
|
let objectProviderObserver;
|
|
|
|
let notebookDomainObject;
|
|
|
|
beforeEach((done) => {
|
|
notebookDomainObject = {
|
|
identifier: {
|
|
key: 'notebook',
|
|
namespace: 'test-namespace'
|
|
},
|
|
type: 'notebook'
|
|
};
|
|
|
|
appHolder = document.createElement('div');
|
|
appHolder.style.width = '640px';
|
|
appHolder.style.height = '480px';
|
|
document.body.appendChild(appHolder);
|
|
|
|
openmct = createOpenMct();
|
|
|
|
element = document.createElement('div');
|
|
child = document.createElement('div');
|
|
element.appendChild(child);
|
|
|
|
openmct.install(notebookPlugin());
|
|
|
|
notebookDefinition = openmct.types.get('notebook').definition;
|
|
notebookDefinition.initialize(notebookDomainObject);
|
|
|
|
openmct.on('start', done);
|
|
openmct.start(appHolder);
|
|
});
|
|
|
|
afterEach(() => {
|
|
appHolder.remove();
|
|
|
|
return resetApplicationState(openmct);
|
|
});
|
|
|
|
it("has type as Notebook", () => {
|
|
expect(notebookDefinition.name).toEqual('Notebook');
|
|
});
|
|
|
|
it("is creatable", () => {
|
|
expect(notebookDefinition.creatable).toEqual(true);
|
|
});
|
|
|
|
describe("Notebook view:", () => {
|
|
let notebookViewProvider;
|
|
let notebookView;
|
|
let notebookViewObject;
|
|
let mutableNotebookObject;
|
|
|
|
beforeEach(() => {
|
|
notebookViewObject = {
|
|
...notebookDomainObject,
|
|
id: "test-object",
|
|
name: 'Notebook',
|
|
configuration: {
|
|
defaultSort: 'oldest',
|
|
entries: {
|
|
"test-section-1": {
|
|
"test-page-1": [{
|
|
"id": "entry-0",
|
|
"createdOn": 0,
|
|
"text": "First Test Entry",
|
|
"embeds": []
|
|
}, {
|
|
"id": "entry-1",
|
|
"createdOn": 0,
|
|
"text": "Second Test Entry",
|
|
"embeds": []
|
|
}]
|
|
}
|
|
},
|
|
pageTitle: 'Page',
|
|
sections: [{
|
|
"id": "test-section-1",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Section",
|
|
"pages": [{
|
|
"id": "test-page-1",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Page 1",
|
|
"pageTitle": "Page"
|
|
}, {
|
|
"id": "test-page-2",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Page 2",
|
|
"pageTitle": "Page"
|
|
}]
|
|
}, {
|
|
"id": "test-section-2",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Section 2",
|
|
"pages": [{
|
|
"id": "test-page-3",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Page 3",
|
|
"pageTitle": "Page"
|
|
}]
|
|
}],
|
|
sectionTitle: 'Section',
|
|
type: 'General'
|
|
}
|
|
};
|
|
const testObjectProvider = jasmine.createSpyObj('testObjectProvider', [
|
|
'get',
|
|
'create',
|
|
'update',
|
|
'observe'
|
|
]);
|
|
|
|
openmct.editor = {};
|
|
openmct.editor.isEditing = () => false;
|
|
|
|
const applicableViews = openmct.objectViews.get(notebookViewObject, [notebookViewObject]);
|
|
notebookViewProvider = applicableViews.find(viewProvider => viewProvider.key === 'notebook-vue');
|
|
|
|
testObjectProvider.get.and.returnValue(Promise.resolve(notebookViewObject));
|
|
testObjectProvider.create.and.returnValue(Promise.resolve(notebookViewObject));
|
|
openmct.objects.addProvider('test-namespace', testObjectProvider);
|
|
testObjectProvider.observe.and.returnValue(() => {});
|
|
testObjectProvider.create.and.returnValue(Promise.resolve(true));
|
|
testObjectProvider.update.and.returnValue(Promise.resolve(true));
|
|
|
|
return openmct.objects.getMutable(notebookViewObject.identifier).then((mutableObject) => {
|
|
mutableNotebookObject = mutableObject;
|
|
objectProviderObserver = testObjectProvider.observe.calls.mostRecent().args[1];
|
|
|
|
notebookView = notebookViewProvider.view(mutableNotebookObject);
|
|
notebookView.show(child);
|
|
|
|
return Vue.nextTick();
|
|
});
|
|
|
|
});
|
|
|
|
afterEach(() => {
|
|
notebookView.destroy();
|
|
openmct.objects.destroyMutable(mutableNotebookObject);
|
|
});
|
|
|
|
it("provides notebook view", () => {
|
|
expect(notebookViewProvider).toBeDefined();
|
|
});
|
|
|
|
it("renders notebook element", () => {
|
|
const notebookElement = element.querySelectorAll('.c-notebook');
|
|
expect(notebookElement.length).toBe(1);
|
|
});
|
|
|
|
it("renders major elements", () => {
|
|
const notebookElement = element.querySelector('.c-notebook');
|
|
const searchElement = notebookElement.querySelector('.c-search');
|
|
const sidebarElement = notebookElement.querySelector('.c-sidebar');
|
|
const pageViewElement = notebookElement.querySelector('.c-notebook__page-view');
|
|
const hasMajorElements = Boolean(searchElement && sidebarElement && pageViewElement);
|
|
|
|
expect(hasMajorElements).toBe(true);
|
|
});
|
|
|
|
it("renders a row for each entry", () => {
|
|
const notebookEntryElements = element.querySelectorAll('.c-notebook__entry');
|
|
const firstEntryText = getEntryText(0);
|
|
expect(notebookEntryElements.length).toBe(2);
|
|
expect(firstEntryText.innerText).toBe('First Test Entry');
|
|
});
|
|
|
|
describe("synchronization", () => {
|
|
|
|
it("updates an entry when another user modifies it", () => {
|
|
expect(getEntryText(0).innerText).toBe("First Test Entry");
|
|
notebookViewObject.configuration.entries["test-section-1"]["test-page-1"][0].text = "Modified entry text";
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(getEntryText(0).innerText).toBe("Modified entry text");
|
|
});
|
|
});
|
|
|
|
it("shows new entry when another user adds one", () => {
|
|
expect(allNotebookEntryElements().length).toBe(2);
|
|
notebookViewObject.configuration.entries["test-section-1"]["test-page-1"].push({
|
|
"id": "entry-3",
|
|
"createdOn": 0,
|
|
"text": "Third Test Entry",
|
|
"embeds": []
|
|
});
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookEntryElements().length).toBe(3);
|
|
});
|
|
});
|
|
it("removes an entry when another user removes one", () => {
|
|
expect(allNotebookEntryElements().length).toBe(2);
|
|
let entries = notebookViewObject.configuration.entries["test-section-1"]["test-page-1"];
|
|
notebookViewObject.configuration.entries["test-section-1"]["test-page-1"] = entries.splice(0, 1);
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookEntryElements().length).toBe(1);
|
|
});
|
|
});
|
|
|
|
it("updates the notebook when a user adds a page", () => {
|
|
const newPage = {
|
|
"id": "test-page-4",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Page 4",
|
|
"pageTitle": "Page"
|
|
};
|
|
|
|
expect(allNotebookPageElements().length).toBe(2);
|
|
notebookViewObject.configuration.sections[0].pages.push(newPage);
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookPageElements().length).toBe(3);
|
|
});
|
|
|
|
});
|
|
|
|
it("updates the notebook when a user removes a page", () => {
|
|
expect(allNotebookPageElements().length).toBe(2);
|
|
notebookViewObject.configuration.sections[0].pages.splice(0, 1);
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookPageElements().length).toBe(1);
|
|
});
|
|
});
|
|
|
|
it("updates the notebook when a user adds a section", () => {
|
|
const newSection = {
|
|
"id": "test-section-3",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Section 3",
|
|
"pages": [{
|
|
"id": "test-page-4",
|
|
"isDefault": false,
|
|
"isSelected": false,
|
|
"name": "Test Page 4",
|
|
"pageTitle": "Page"
|
|
}]
|
|
};
|
|
|
|
expect(allNotebookSectionElements().length).toBe(2);
|
|
notebookViewObject.configuration.sections.push(newSection);
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookSectionElements().length).toBe(3);
|
|
});
|
|
});
|
|
|
|
it("updates the notebook when a user removes a section", () => {
|
|
expect(allNotebookSectionElements().length).toBe(2);
|
|
notebookViewObject.configuration.sections.splice(0, 1);
|
|
objectProviderObserver(notebookViewObject);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
expect(allNotebookSectionElements().length).toBe(1);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Notebook Snapshots view:", () => {
|
|
let snapshotIndicator;
|
|
let drawerElement;
|
|
|
|
function clickSnapshotIndicator() {
|
|
const indicator = element.querySelector('.icon-camera');
|
|
const button = indicator.querySelector('button');
|
|
const clickEvent = createMouseEvent('click');
|
|
|
|
button.dispatchEvent(clickEvent);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
snapshotIndicator = openmct.indicators.indicatorObjects
|
|
.find(indicator => indicator.key === 'notebook-snapshot-indicator').element;
|
|
|
|
element.append(snapshotIndicator);
|
|
|
|
return Vue.nextTick().then(() => {
|
|
drawerElement = document.querySelector('.l-shell__drawer');
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (drawerElement) {
|
|
drawerElement.classList.remove('is-expanded');
|
|
}
|
|
|
|
snapshotIndicator.remove();
|
|
snapshotIndicator = undefined;
|
|
|
|
if (drawerElement) {
|
|
drawerElement.remove();
|
|
drawerElement = undefined;
|
|
}
|
|
});
|
|
|
|
it("has Snapshots indicator", () => {
|
|
const hasSnapshotIndicator = snapshotIndicator !== null && snapshotIndicator !== undefined;
|
|
expect(hasSnapshotIndicator).toBe(true);
|
|
});
|
|
|
|
it("snapshots container has class isExpanded", () => {
|
|
let classes = drawerElement.classList;
|
|
const isExpandedBefore = classes.contains('is-expanded');
|
|
|
|
clickSnapshotIndicator();
|
|
classes = drawerElement.classList;
|
|
const isExpandedAfterFirstClick = classes.contains('is-expanded');
|
|
|
|
expect(isExpandedBefore).toBeFalse();
|
|
expect(isExpandedAfterFirstClick).toBeTrue();
|
|
});
|
|
|
|
it("snapshots container does not have class isExpanded", () => {
|
|
let classes = drawerElement.classList;
|
|
const isExpandedBefore = classes.contains('is-expanded');
|
|
|
|
clickSnapshotIndicator();
|
|
classes = drawerElement.classList;
|
|
const isExpandedAfterFirstClick = classes.contains('is-expanded');
|
|
|
|
clickSnapshotIndicator();
|
|
classes = drawerElement.classList;
|
|
const isExpandedAfterSecondClick = classes.contains('is-expanded');
|
|
|
|
expect(isExpandedBefore).toBeFalse();
|
|
expect(isExpandedAfterFirstClick).toBeTrue();
|
|
expect(isExpandedAfterSecondClick).toBeFalse();
|
|
});
|
|
|
|
it("show notebook snapshots container text", () => {
|
|
clickSnapshotIndicator();
|
|
|
|
const notebookSnapshots = drawerElement.querySelector('.l-browse-bar__object-name');
|
|
const snapshotsText = notebookSnapshots.textContent.trim();
|
|
|
|
expect(snapshotsText).toBe('Notebook Snapshots');
|
|
});
|
|
});
|
|
|
|
function getEntryText(entryNumber) {
|
|
return element.querySelectorAll('.c-notebook__entry .c-ne__text')[entryNumber];
|
|
}
|
|
|
|
function allNotebookEntryElements() {
|
|
return element.querySelectorAll('.c-notebook__entry');
|
|
}
|
|
|
|
function allNotebookSectionElements() {
|
|
return element.querySelectorAll('.js-sidebar-sections .js-list__item');
|
|
}
|
|
|
|
function allNotebookPageElements() {
|
|
return element.querySelectorAll('.js-sidebar-pages .js-list__item');
|
|
}
|
|
});
|