Skip to content

Commit

Permalink
Merge branch 'master' into stabilize-compass-per-timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
unlikelyzero authored Oct 10, 2024
2 parents 51b0526 + 4415fe7 commit be8f413
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 96 deletions.
16 changes: 8 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ executors:
- image: mcr.microsoft.com/playwright:v1.47.2-focal
environment:
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
PERCY_POSTINSTALL_BROWSER: "true" # Needed to store the percy browser in cache deps
PERCY_LOGLEVEL: "debug" # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742)
PERCY_POSTINSTALL_BROWSER: 'true' # Needed to store the percy browser in cache deps
PERCY_LOGLEVEL: 'debug' # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742)
PERCY_PARALLEL_TOTAL: 2
ubuntu:
machine:
image: ubuntu-2204:current
docker_layer_caching: true
commands:
build_and_install:
description: "All steps used to build and install."
description: 'All steps used to build and install.'
parameters:
node-version:
type: string
Expand All @@ -27,7 +27,7 @@ commands:
node-version: << parameters.node-version >>
- node/install-packages
generate_and_store_version_and_filesystem_artifacts:
description: "Track important packages and files"
description: 'Track important packages and files'
steps:
- run: |
[[ $EUID -ne 0 ]] && (sudo mkdir -p /tmp/artifacts && sudo chmod 777 /tmp/artifacts) || (mkdir -p /tmp/artifacts && chmod 777 /tmp/artifacts)
Expand Down Expand Up @@ -61,7 +61,7 @@ commands:
[[ $EUID -ne 0 ]] && sudo chmod +x codecov || chmod +x codecov
./codecov --help
generate_e2e_code_cov_report:
description: "Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test"
description: 'Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test'
parameters:
suite:
type: string
Expand Down Expand Up @@ -135,13 +135,13 @@ jobs:
suite: #ci or full
type: string
executor: pw-focal-development
parallelism: 7
parallelism: 8
steps:
- build_and_install:
node-version: lts/hydrogen
- when: #Only install chrome-beta when running the 'full' suite to save $$$
condition:
equal: ["full", <<parameters.suite>>]
equal: ['full', <<parameters.suite>>]
steps:
- run: npx playwright install chrome-beta
- run:
Expand Down Expand Up @@ -323,7 +323,7 @@ workflows:
- e2e-couchdb
triggers:
- schedule:
cron: "0 0 * * *"
cron: '0 0 * * *'
filters:
branches:
only:
Expand Down
51 changes: 51 additions & 0 deletions e2e/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,37 @@ async function createExampleTelemetryObject(page, parent = 'mine') {
};
}

/**
* Create a Stable State Telemetry Object (State Generator) for use in visual tests
* and tests against plotting telemetry (e.g. logPlot tests). This will change state every 2 seconds.
* @param {import('@playwright/test').Page} page
* @param {string | import('../src/api/objects/ObjectAPI').Identifier} [parent] the uuid or identifier of the parent object. Defaults to 'mine'
* @returns {Promise<CreatedObjectInfo>} An object containing information about the telemetry object.
*/
async function createStableStateTelemetry(page, parent = 'mine') {
const parentUrl = await getHashUrlToDomainObject(page, parent);

await page.goto(`${parentUrl}`);
const createdObject = await createDomainObjectWithDefaults(page, {
type: 'State Generator',
name: 'Stable State Generator'
});
// edit the state generator to have a 1 second update rate
await page.getByLabel('More actions').click();
await page.getByRole('menuitem', { name: 'Edit Properties...' }).click();
await page.getByLabel('State Duration (seconds)', { exact: true }).fill('2');
await page.getByLabel('Save').click();
// Wait until the URL is updated
const uuid = await getFocusedObjectUuid(page);
const url = await getHashUrlToDomainObject(page, uuid);

return {
name: createdObject.name,
uuid,
url
};
}

/**
* Navigates directly to a given object url, in fixed time mode, with the given start and end bounds. Note: does not set
* default view type.
Expand Down Expand Up @@ -629,13 +660,33 @@ async function getCanvasPixels(page, canvasSelector) {
);
}

/**
* 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 linkParameterToObject(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();
}

export {
createDomainObjectWithDefaults,
createExampleTelemetryObject,
createNotification,
createPlanFromJSON,
createStableStateTelemetry,
expandEntireTree,
getCanvasPixels,
linkParameterToObject,
navigateToObjectWithFixedTimeBounds,
navigateToObjectWithRealTime,
setEndOffset,
Expand Down
21 changes: 21 additions & 0 deletions e2e/tests/framework/appActions.e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import {
createExampleTelemetryObject,
createNotification,
createPlanFromJSON,
createStableStateTelemetry,
expandEntireTree,
getCanvasPixels,
linkParameterToObject,
navigateToObjectWithFixedTimeBounds,
navigateToObjectWithRealTime,
setEndOffset,
Expand Down Expand Up @@ -339,4 +341,23 @@ test.describe('AppActions @framework', () => {
// Expect this step to fail
await waitForPlotsToRender(page, { timeout: 1000 });
});
test('createStableStateTelemetry', async ({ page }) => {
const stableStateTelemetry = await createStableStateTelemetry(page);
expect(stableStateTelemetry.name).toBe('Stable State Generator');
expect(stableStateTelemetry.url).toBe(`./#/browse/mine/${stableStateTelemetry.uuid}`);
expect(stableStateTelemetry.uuid).toBeDefined();
});
test('linkParameterToObject', async ({ page }) => {
const displayLayout = await createDomainObjectWithDefaults(page, {
type: 'Display Layout',
name: 'Test Display Layout'
});
const exampleTelemetry = await createExampleTelemetryObject(page);

await linkParameterToObject(page, exampleTelemetry.name, displayLayout.name);
await page.goto(displayLayout.url);
await expect(page.getByRole('main').getByText('Test Display Layout')).toBeVisible();
await expandEntireTree(page);
await expect(page.getByLabel('Navigate to VIPER Rover').first()).toBeVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
This test suite is dedicated to tests which verify the basic operations surrounding conditionSets and styling
*/

import { createDomainObjectWithDefaults, setRealTimeMode } from '../../../../appActions.js';
import {
createDomainObjectWithDefaults,
linkParameterToObject,
setRealTimeMode
} from '../../../../appActions.js';
import { MISSION_TIME } from '../../../../constants.js';
import { expect, test } from '../../../../pluginFixtures.js';

Expand Down Expand Up @@ -92,7 +96,7 @@ test.describe('Conditionally Styling, using a Condition Set', () => {
await page.getByLabel('Save').click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();

await searchAndLinkParameterToObject(page, stateGenerator.name, displayLayout.name);
await linkParameterToObject(page, stateGenerator.name, displayLayout.name);

//Add a box to the display layout
await page.goto(displayLayout.url, { waitUntil: 'domcontentloaded' });
Expand Down Expand Up @@ -157,21 +161,3 @@ async function waitForStyleChange(element, expectedStyle, timeout = 0) {
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();
}
23 changes: 12 additions & 11 deletions e2e/tests/visual-a11y/displayLayout.visual.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@

import percySnapshot from '@percy/playwright';

import { createDomainObjectWithDefaults } from '../../appActions.js';
import {
createDomainObjectWithDefaults,
createStableStateTelemetry,
linkParameterToObject
} from '../../appActions.js';
import { MISSION_TIME, VISUAL_FIXED_URL } from '../../constants.js';
import { test } from '../../pluginFixtures.js';

Expand All @@ -47,16 +51,13 @@ test.describe('Visual - Display Layout @clock', () => {
name: 'Child Right Layout',
parent: parentLayout.uuid
});
await createDomainObjectWithDefaults(page, {
type: 'Sine Wave Generator',
name: 'SWG 1',
parent: child1Layout.uuid
});
await createDomainObjectWithDefaults(page, {
type: 'Sine Wave Generator',
name: 'SWG 2',
parent: child2Layout.uuid
});

const stableStateTelemetry = await createStableStateTelemetry(page);
await linkParameterToObject(page, stableStateTelemetry.name, child1Layout.name);
await linkParameterToObject(page, stableStateTelemetry.name, child2Layout.name);

// Pause the clock at a time where the telemetry is stable 20 minutes in the future
await page.clock.pauseAt(new Date(MISSION_TIME + 1200000));

await page.goto(parentLayout.url, { waitUntil: 'domcontentloaded' });
await page.getByRole('button', { name: 'Edit Object' }).click();
Expand Down
26 changes: 10 additions & 16 deletions src/api/telemetry/TelemetryAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,26 +231,20 @@ export default class TelemetryAPI {
* @returns {TelemetryRequestOptions} the options, with defaults filled in
*/
standardizeRequestOptions(options = {}) {
if (!Object.hasOwn(options, 'start')) {
const bounds = options.timeContext?.getBounds();
if (bounds?.start) {
options.start = options.timeContext.getBounds().start;
} else {
options.start = this.openmct.time.getBounds().start;
}
if (!Object.hasOwn(options, 'timeContext')) {
options.timeContext = this.openmct.time;
}

if (!Object.hasOwn(options, 'end')) {
const bounds = options.timeContext?.getBounds();
if (bounds?.end) {
options.end = options.timeContext.getBounds().end;
} else {
options.end = this.openmct.time.getBounds().end;
}
if (!Object.hasOwn(options, 'domain')) {
options.domain = options.timeContext.getTimeSystem().key;
}

if (!Object.hasOwn(options, 'domain')) {
options.domain = this.openmct.time.getTimeSystem().key;
if (!Object.hasOwn(options, 'start')) {
options.start = options.timeContext.getBounds().start;
}

if (!Object.hasOwn(options, 'end')) {
options.end = options.timeContext.getBounds().end;
}

return options;
Expand Down
30 changes: 18 additions & 12 deletions src/api/telemetry/TelemetryAPISpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,36 +269,40 @@ describe('Telemetry API', () => {

await telemetryAPI.request(domainObject);
const { signal } = new AbortController();
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
signal,
start: 0,
end: 1,
domain: 'system'
domain: 'system',
timeContext: openmct.time
});

expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
signal,
start: 0,
end: 1,
domain: 'system'
domain: 'system',
timeContext: openmct.time
});

telemetryProvider.supportsRequest.calls.reset();
telemetryProvider.request.calls.reset();

await telemetryAPI.request(domainObject, {});
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
signal,
start: 0,
end: 1,
domain: 'system'
domain: 'system',
timeContext: openmct.time
});

expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
signal,
start: 0,
end: 1,
domain: 'system'
domain: 'system',
timeContext: openmct.time
});
});

Expand All @@ -313,18 +317,20 @@ describe('Telemetry API', () => {
domain: 'someDomain'
});
const { signal } = new AbortController();
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
start: 20,
end: 30,
domain: 'someDomain',
signal
signal,
timeContext: openmct.time
});

expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
start: 20,
end: 30,
domain: 'someDomain',
signal
signal,
timeContext: openmct.time
});
});
describe('telemetry batching support', () => {
Expand Down
8 changes: 4 additions & 4 deletions src/api/telemetry/TelemetryCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ export default class TelemetryCollection extends EventEmitter {
this.futureBuffer = [];
this.parseTime = undefined;
this.metadata = this.openmct.telemetry.getMetadata(domainObject);
if (!Object.hasOwn(options, 'timeContext')) {
options.timeContext = this.openmct.time;
}
this.options = options;
this.unsubscribe = undefined;
this.pageState = undefined;
Expand All @@ -84,6 +81,9 @@ export default class TelemetryCollection extends EventEmitter {
this._error(LOADED_ERROR);
}

if (!Object.hasOwn(this.options, 'timeContext')) {
this.options.timeContext = this.openmct.time;
}
this._setTimeSystem(this.options.timeContext.getTimeSystem());
this.lastBounds = this.options.timeContext.getBounds();
this._watchBounds();
Expand Down Expand Up @@ -127,7 +127,7 @@ export default class TelemetryCollection extends EventEmitter {
* @private
*/
async _requestHistoricalTelemetry() {
let options = this.openmct.telemetry.standardizeRequestOptions({ ...this.options });
const options = this.openmct.telemetry.standardizeRequestOptions({ ...this.options });
const historicalProvider = this.openmct.telemetry.findRequestProvider(
this.domainObject,
options
Expand Down
Loading

0 comments on commit be8f413

Please sign in to comment.