mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
[CI] Fix flake with clocks and state generators (#7867)
* add two appActions * replace with appAction * replace with determinsitic appAction * fix lint * speed
This commit is contained in:
parent
55c023d1eb
commit
47f0b66c7e
@ -8,8 +8,8 @@ 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:
|
||||
@ -17,7 +17,7 @@ executors:
|
||||
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
|
||||
@ -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)
|
||||
@ -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
|
||||
@ -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:
|
||||
@ -323,7 +323,7 @@ workflows:
|
||||
- e2e-couchdb
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
cron: '0 0 * * *'
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
|
@ -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.
|
||||
@ -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,
|
||||
|
@ -26,8 +26,10 @@ import {
|
||||
createExampleTelemetryObject,
|
||||
createNotification,
|
||||
createPlanFromJSON,
|
||||
createStableStateTelemetry,
|
||||
expandEntireTree,
|
||||
getCanvasPixels,
|
||||
linkParameterToObject,
|
||||
navigateToObjectWithFixedTimeBounds,
|
||||
navigateToObjectWithRealTime,
|
||||
setEndOffset,
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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';
|
||||
|
||||
@ -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' });
|
||||
@ -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();
|
||||
}
|
||||
|
@ -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';
|
||||
|
||||
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user