mirror of
https://github.com/nasa/openmct.git
synced 2025-02-11 05:12:14 +00:00
* 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>
178 lines
8.0 KiB
JavaScript
178 lines
8.0 KiB
JavaScript
/*****************************************************************************
|
|
* 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();
|
|
}
|