fix: use loadDelay generator setting in subscriptions as well (#6918)

* refactor: use `getBounds()` instead of `bounds()`

* fix: use `loadDelay` in generator subscription

* refactor: fix up e2e test

* fix: remove `.only()`

* refactor: lint

* Start to fix up conditionSet test with comments

* test: edit conditionSet to add delay value

* test: tests the case where telemetry is available

* fix: remove `.only()`

* test: add comments, clarify assertion

* refactor: lint:fix

* test: fix conditionSet default condition name test

* test: add assertions to stabilize tags tests

---------

Co-authored-by: Scott Bell <scott@traclabs.com>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
Jesse Mazzella 2023-08-14 12:04:01 -07:00 committed by GitHub
parent f3b819a786
commit 57743e5918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 77 deletions

View File

@ -27,7 +27,10 @@ demonstrate some playwright for test developers. This pattern should not be re-u
*/ */
const { test, expect } = require('../../../../pluginFixtures.js'); const { test, expect } = require('../../../../pluginFixtures.js');
const { createDomainObjectWithDefaults } = require('../../../../appActions'); const {
createDomainObjectWithDefaults,
createExampleTelemetryObject
} = require('../../../../appActions');
let conditionSetUrl; let conditionSetUrl;
let getConditionSetIdentifierFromUrl; let getConditionSetIdentifierFromUrl;
@ -205,23 +208,31 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
}); });
test.describe('Basic Condition Set Use', () => { test.describe('Basic Condition Set Use', () => {
let conditionSet;
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
// Open a browser, navigate to the main page, and wait until all network events to resolve // Open a browser, navigate to the main page, and wait until all network events to resolve
await page.goto('./', { waitUntil: 'domcontentloaded' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
});
test('Can add a condition', async ({ page }) => {
// Create a new condition set // Create a new condition set
await createDomainObjectWithDefaults(page, { conditionSet = await createDomainObjectWithDefaults(page, {
type: 'Condition Set', type: 'Condition Set',
name: 'Test Condition Set' name: 'Test Condition Set'
}); });
});
test('Creating a condition defaults the condition name to "Unnamed Condition"', async ({
page
}) => {
await page.goto(conditionSet.url);
// Change the object to edit mode // Change the object to edit mode
await page.locator('[title="Edit"]').click(); await page.locator('[title="Edit"]').click();
// Click Add Condition button // Click Add Condition button
await page.locator('#addCondition').click(); await page.locator('#addCondition').click();
// Check that the new Unnamed Condition section appears // Check that the new Unnamed Condition section appears
const numOfUnnamedConditions = await page.locator('text=Unnamed Condition').count(); const numOfUnnamedConditions = await page
.locator('.c-condition__name', { hasText: 'Unnamed Condition' })
.count();
expect(numOfUnnamedConditions).toEqual(1); expect(numOfUnnamedConditions).toEqual(1);
}); });
test('ConditionSet should display appropriate view options', async ({ page }) => { test('ConditionSet should display appropriate view options', async ({ page }) => {
@ -238,16 +249,13 @@ test.describe('Basic Condition Set Use', () => {
type: 'Sine Wave Generator', type: 'Sine Wave Generator',
name: 'Beta Sine Wave Generator' name: 'Beta Sine Wave Generator'
}); });
const conditionSet1 = await createDomainObjectWithDefaults(page, {
type: 'Condition Set', await page.goto(conditionSet.url);
name: 'Test Condition Set'
});
// Change the object to edit mode // Change the object to edit mode
await page.locator('[title="Edit"]').click(); await page.locator('[title="Edit"]').click();
// Expand the 'My Items' folder in the left tree // Expand the 'My Items' folder in the left tree
await page.goto(conditionSet1.url);
page.click('button[title="Show selected item in tree"]'); page.click('button[title="Show selected item in tree"]');
// Add the Alpha & Beta Sine Wave Generator to the Condition Set and save changes // Add the Alpha & Beta Sine Wave Generator to the Condition Set and save changes
const treePane = page.getByRole('tree', { const treePane = page.getByRole('tree', {
@ -264,9 +272,9 @@ test.describe('Basic Condition Set Use', () => {
await alphaGeneratorTreeItem.dragTo(conditionCollection); await alphaGeneratorTreeItem.dragTo(conditionCollection);
await betaGeneratorTreeItem.dragTo(conditionCollection); await betaGeneratorTreeItem.dragTo(conditionCollection);
const saveButtonLocator = page.locator('button[title="Save"]'); await page.locator('button[title="Save"]').click();
await saveButtonLocator.click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click(); await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
await page.click('button[title="Change the current view"]'); await page.click('button[title="Change the current view"]');
await expect(page.getByRole('menuitem', { name: /Lad Table/ })).toBeHidden(); await expect(page.getByRole('menuitem', { name: /Lad Table/ })).toBeHidden();
@ -274,95 +282,89 @@ test.describe('Basic Condition Set Use', () => {
await expect(page.getByRole('menuitem', { name: /Plot/ })).toBeVisible(); await expect(page.getByRole('menuitem', { name: /Plot/ })).toBeVisible();
await expect(page.getByRole('menuitem', { name: /Telemetry Table/ })).toBeVisible(); await expect(page.getByRole('menuitem', { name: /Telemetry Table/ })).toBeVisible();
}); });
test('ConditionSet should output blank instead of the default value', async ({ page }) => { test('ConditionSet has correct outputs when telemetry is and is not available', async ({
//Navigate to baseURL page
await page.goto('./', { waitUntil: 'domcontentloaded' }); }) => {
const exampleTelemetry = await createExampleTelemetryObject(page);
//Click the Create button await page.getByTitle('Show selected item in tree').click();
await page.click('button:has-text("Create")'); await page.goto(conditionSet.url);
// Click the object specified by 'type'
await page.click(`li[role='menuitem']:text("Sine Wave Generator")`);
await page.getByRole('spinbutton', { name: 'Loading Delay (ms)' }).fill('8000');
const nameInput = page.locator('form[name="mctForm"] .first input[type="text"]');
await nameInput.fill('Delayed Sine Wave Generator');
// Click OK button and wait for Navigate event
await Promise.all([
page.waitForLoadState(),
page.click('[aria-label="Save"]'),
// Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message')
]);
// Create a new condition set
await createDomainObjectWithDefaults(page, {
type: 'Condition Set',
name: 'Test Blank Output of Condition Set'
});
// Change the object to edit mode // Change the object to edit mode
await page.locator('[title="Edit"]').click(); await page.locator('[title="Edit"]').click();
// Click Add Condition button twice // Create two conditions
await page.locator('#addCondition').click(); await page.locator('#addCondition').click();
await page.locator('#addCondition').click(); await page.locator('#addCondition').click();
await page.locator('#conditionCollection').getByRole('textbox').nth(0).fill('First Condition'); await page.locator('#conditionCollection').getByRole('textbox').nth(0).fill('First Condition');
await page.locator('#conditionCollection').getByRole('textbox').nth(1).fill('Second Condition'); await page.locator('#conditionCollection').getByRole('textbox').nth(1).fill('Second Condition');
// Expand the 'My Items' folder in the left tree // Add Telemetry to ConditionSet
await page.locator('.c-tree__item__view-control.c-disclosure-triangle').first().click(); const sineWaveGeneratorTreeItem = page
// Add the Sine Wave Generator to the Condition Set and save changes .getByRole('tree', {
const treePane = page.getByRole('tree', {
name: 'Main Tree' name: 'Main Tree'
})
.getByRole('treeitem', {
name: exampleTelemetry.name
}); });
const sineWaveGeneratorTreeItem = treePane.getByRole('treeitem', { const conditionCollection = page.locator('#conditionCollection');
name: 'Delayed Sine Wave Generator'
});
const conditionCollection = await page.locator('#conditionCollection');
await sineWaveGeneratorTreeItem.dragTo(conditionCollection); await sineWaveGeneratorTreeItem.dragTo(conditionCollection);
const firstCriterionTelemetry = await page.locator( // Modify First Criterion
const firstCriterionTelemetry = page.locator(
'[aria-label="Criterion Telemetry Selection"] >> nth=0' '[aria-label="Criterion Telemetry Selection"] >> nth=0'
); );
firstCriterionTelemetry.selectOption({ label: 'Delayed Sine Wave Generator' }); firstCriterionTelemetry.selectOption({ label: exampleTelemetry.name });
const firstCriterionMetadata = page.locator(
const secondCriterionTelemetry = await page.locator(
'[aria-label="Criterion Telemetry Selection"] >> nth=1'
);
secondCriterionTelemetry.selectOption({ label: 'Delayed Sine Wave Generator' });
const firstCriterionMetadata = await page.locator(
'[aria-label="Criterion Metadata Selection"] >> nth=0' '[aria-label="Criterion Metadata Selection"] >> nth=0'
); );
firstCriterionMetadata.selectOption({ label: 'Sine' }); firstCriterionMetadata.selectOption({ label: 'Sine' });
const firstCriterionComparison = page.locator(
'[aria-label="Criterion Comparison Selection"] >> nth=0'
);
firstCriterionComparison.selectOption({ label: 'is greater than or equal to' });
const firstCriterionInput = page.locator('[aria-label="Criterion Input"] >> nth=0');
await firstCriterionInput.fill('0');
const secondCriterionMetadata = await page.locator( // Modify First Criterion
const secondCriterionTelemetry = page.locator(
'[aria-label="Criterion Telemetry Selection"] >> nth=1'
);
secondCriterionTelemetry.selectOption({ label: exampleTelemetry.name });
const secondCriterionMetadata = page.locator(
'[aria-label="Criterion Metadata Selection"] >> nth=1' '[aria-label="Criterion Metadata Selection"] >> nth=1'
); );
secondCriterionMetadata.selectOption({ label: 'Sine' }); secondCriterionMetadata.selectOption({ label: 'Sine' });
const firstCriterionComparison = await page.locator( const secondCriterionComparison = page.locator(
'[aria-label="Criterion Comparison Selection"] >> nth=0'
);
firstCriterionComparison.selectOption({ label: 'is greater than or equal to' });
const secondCriterionComparison = await page.locator(
'[aria-label="Criterion Comparison Selection"] >> nth=1' '[aria-label="Criterion Comparison Selection"] >> nth=1'
); );
secondCriterionComparison.selectOption({ label: 'is less than' }); secondCriterionComparison.selectOption({ label: 'is less than' });
const firstCriterionInput = await page.locator('[aria-label="Criterion Input"] >> nth=0'); const secondCriterionInput = page.locator('[aria-label="Criterion Input"] >> nth=1');
await firstCriterionInput.fill('0');
const secondCriterionInput = await page.locator('[aria-label="Criterion Input"] >> nth=1');
await secondCriterionInput.fill('0'); await secondCriterionInput.fill('0');
const saveButtonLocator = page.locator('button[title="Save"]'); // Save ConditionSet
await saveButtonLocator.click(); await page.locator('button[title="Save"]').click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click(); await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
const outputValue = await page.locator('[aria-label="Current Output Value"]'); // Validate that the condition set is evaluating and outputting
// the correct value when the underlying telemetry subscription is active.
let outputValue = page.locator('[aria-label="Current Output Value"]');
await expect(outputValue).toHaveText('false');
await page.goto(exampleTelemetry.url);
// Edit SWG to add 8 second loading delay to simulate the case
// where telemetry is not available.
await page.getByTitle('More options').click();
await page.getByRole('menuitem', { name: 'Edit Properties...' }).click();
await page.getByRole('spinbutton', { name: 'Loading Delay (ms)' }).fill('8000');
await page.getByLabel('Save').click();
// Expect that the output value is blank or '---' if the
// underlying telemetry subscription is not active.
await page.goto(conditionSet.url);
await expect(outputValue).toHaveText('---'); await expect(outputValue).toHaveText('---');
}); });
}); });

View File

@ -29,7 +29,8 @@ const {
createDomainObjectWithDefaults, createDomainObjectWithDefaults,
setRealTimeMode, setRealTimeMode,
setFixedTimeMode, setFixedTimeMode,
waitForPlotsToRender waitForPlotsToRender,
selectInspectorTab
} = require('../../../../appActions'); } = require('../../../../appActions');
test.describe('Plot Tagging', () => { test.describe('Plot Tagging', () => {
@ -146,7 +147,10 @@ test.describe('Plot Tagging', () => {
// wait for plots to load // wait for plots to load
await waitForPlotsToRender(page); await waitForPlotsToRender(page);
await page.getByText('Annotations').click(); await expect(page.getByRole('tab', { name: 'Annotations' })).not.toHaveClass(/is-current/);
await selectInspectorTab(page, 'Annotations');
await expect(page.getByRole('tab', { name: 'Annotations' })).toHaveClass(/is-current/);
await expect(page.getByText('No tags to display for this item')).toBeVisible(); await expect(page.getByText('No tags to display for this item')).toBeVisible();
const canvas = page.locator('canvas').nth(1); const canvas = page.locator('canvas').nth(1);

View File

@ -88,10 +88,10 @@ define(['uuid'], function ({ v4: uuid }) {
}; };
WorkerInterface.prototype.subscribe = function (request, cb) { WorkerInterface.prototype.subscribe = function (request, cb) {
const id = request.id; const { id, loadDelay } = request;
const messageId = this.dispatch('subscribe', request, (message) => { const messageId = this.dispatch('subscribe', request, (message) => {
if (!this.staleTelemetryIds[id]) { if (!this.staleTelemetryIds[id]) {
cb(message.data); setTimeout(() => cb(message.data), Math.max(loadDelay, 0));
} }
}); });

View File

@ -399,7 +399,7 @@ export default class ConditionManager extends EventEmitter {
} }
shouldEvaluateNewTelemetry(currentTimestamp) { shouldEvaluateNewTelemetry(currentTimestamp) {
return this.openmct.time.bounds().end >= currentTimestamp; return this.openmct.time.getBounds().end >= currentTimestamp;
} }
telemetryReceived(endpoint, datum) { telemetryReceived(endpoint, datum) {