Skip to content

Commit 5de9da4

Browse files
authored
Merge branch 'master' into fix-remote-clock-subscription
2 parents 4c99364 + 57743e5 commit 5de9da4

File tree

7 files changed

+90
-82
lines changed

7 files changed

+90
-82
lines changed

.eslintrc.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = {
1313
extends: [
1414
'eslint:recommended',
1515
'plugin:compat/recommended',
16-
'plugin:vue/recommended',
16+
'plugin:vue/vue3-recommended',
1717
'plugin:you-dont-need-lodash-underscore/compatible',
1818
'plugin:prettier/recommended'
1919
],
@@ -28,6 +28,8 @@ module.exports = {
2828
}
2929
},
3030
rules: {
31+
'vue/no-deprecated-dollar-listeners-api': 'warn',
32+
'vue/no-deprecated-events-api': 'warn',
3133
'vue/no-v-for-template-key': 'off',
3234
'vue/no-v-for-template-key-on-child': 'error',
3335
'prettier/prettier': 'error',

e2e/tests/functional/plugins/conditionSet/conditionSet.e2e.spec.js

+74-72
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ demonstrate some playwright for test developers. This pattern should not be re-u
2727
*/
2828

2929
const { test, expect } = require('../../../../pluginFixtures.js');
30-
const { createDomainObjectWithDefaults } = require('../../../../appActions');
30+
const {
31+
createDomainObjectWithDefaults,
32+
createExampleTelemetryObject
33+
} = require('../../../../appActions');
3134

3235
let conditionSetUrl;
3336
let getConditionSetIdentifierFromUrl;
@@ -205,23 +208,31 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
205208
});
206209

207210
test.describe('Basic Condition Set Use', () => {
211+
let conditionSet;
212+
208213
test.beforeEach(async ({ page }) => {
209214
// Open a browser, navigate to the main page, and wait until all network events to resolve
210215
await page.goto('./', { waitUntil: 'domcontentloaded' });
211-
});
212-
test('Can add a condition', async ({ page }) => {
213216
// Create a new condition set
214-
await createDomainObjectWithDefaults(page, {
217+
conditionSet = await createDomainObjectWithDefaults(page, {
215218
type: 'Condition Set',
216219
name: 'Test Condition Set'
217220
});
221+
});
222+
test('Creating a condition defaults the condition name to "Unnamed Condition"', async ({
223+
page
224+
}) => {
225+
await page.goto(conditionSet.url);
226+
218227
// Change the object to edit mode
219228
await page.locator('[title="Edit"]').click();
220229

221230
// Click Add Condition button
222231
await page.locator('#addCondition').click();
223232
// Check that the new Unnamed Condition section appears
224-
const numOfUnnamedConditions = await page.locator('text=Unnamed Condition').count();
233+
const numOfUnnamedConditions = await page
234+
.locator('.c-condition__name', { hasText: 'Unnamed Condition' })
235+
.count();
225236
expect(numOfUnnamedConditions).toEqual(1);
226237
});
227238
test('ConditionSet should display appropriate view options', async ({ page }) => {
@@ -238,16 +249,13 @@ test.describe('Basic Condition Set Use', () => {
238249
type: 'Sine Wave Generator',
239250
name: 'Beta Sine Wave Generator'
240251
});
241-
const conditionSet1 = await createDomainObjectWithDefaults(page, {
242-
type: 'Condition Set',
243-
name: 'Test Condition Set'
244-
});
252+
253+
await page.goto(conditionSet.url);
245254

246255
// Change the object to edit mode
247256
await page.locator('[title="Edit"]').click();
248257

249258
// Expand the 'My Items' folder in the left tree
250-
await page.goto(conditionSet1.url);
251259
page.click('button[title="Show selected item in tree"]');
252260
// Add the Alpha & Beta Sine Wave Generator to the Condition Set and save changes
253261
const treePane = page.getByRole('tree', {
@@ -264,105 +272,99 @@ test.describe('Basic Condition Set Use', () => {
264272
await alphaGeneratorTreeItem.dragTo(conditionCollection);
265273
await betaGeneratorTreeItem.dragTo(conditionCollection);
266274

267-
const saveButtonLocator = page.locator('button[title="Save"]');
268-
await saveButtonLocator.click();
275+
await page.locator('button[title="Save"]').click();
269276
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
277+
270278
await page.click('button[title="Change the current view"]');
271279

272280
await expect(page.getByRole('menuitem', { name: /Lad Table/ })).toBeHidden();
273281
await expect(page.getByRole('menuitem', { name: /Conditions View/ })).toBeVisible();
274282
await expect(page.getByRole('menuitem', { name: /Plot/ })).toBeVisible();
275283
await expect(page.getByRole('menuitem', { name: /Telemetry Table/ })).toBeVisible();
276284
});
277-
test('ConditionSet should output blank instead of the default value', async ({ page }) => {
278-
//Navigate to baseURL
279-
await page.goto('./', { waitUntil: 'domcontentloaded' });
280-
281-
//Click the Create button
282-
await page.click('button:has-text("Create")');
283-
284-
// Click the object specified by 'type'
285-
await page.click(`li[role='menuitem']:text("Sine Wave Generator")`);
286-
await page.getByRole('spinbutton', { name: 'Loading Delay (ms)' }).fill('8000');
287-
const nameInput = page.locator('form[name="mctForm"] .first input[type="text"]');
288-
await nameInput.fill('Delayed Sine Wave Generator');
289-
290-
// Click OK button and wait for Navigate event
291-
await Promise.all([
292-
page.waitForLoadState(),
293-
page.click('[aria-label="Save"]'),
294-
// Wait for Save Banner to appear
295-
page.waitForSelector('.c-message-banner__message')
296-
]);
285+
test('ConditionSet has correct outputs when telemetry is and is not available', async ({
286+
page
287+
}) => {
288+
const exampleTelemetry = await createExampleTelemetryObject(page);
297289

298-
// Create a new condition set
299-
await createDomainObjectWithDefaults(page, {
300-
type: 'Condition Set',
301-
name: 'Test Blank Output of Condition Set'
302-
});
290+
await page.getByTitle('Show selected item in tree').click();
291+
await page.goto(conditionSet.url);
303292
// Change the object to edit mode
304293
await page.locator('[title="Edit"]').click();
305294

306-
// Click Add Condition button twice
295+
// Create two conditions
307296
await page.locator('#addCondition').click();
308297
await page.locator('#addCondition').click();
309298
await page.locator('#conditionCollection').getByRole('textbox').nth(0).fill('First Condition');
310299
await page.locator('#conditionCollection').getByRole('textbox').nth(1).fill('Second Condition');
311300

312-
// Expand the 'My Items' folder in the left tree
313-
await page.locator('.c-tree__item__view-control.c-disclosure-triangle').first().click();
314-
// Add the Sine Wave Generator to the Condition Set and save changes
315-
const treePane = page.getByRole('tree', {
316-
name: 'Main Tree'
317-
});
318-
const sineWaveGeneratorTreeItem = treePane.getByRole('treeitem', {
319-
name: 'Delayed Sine Wave Generator'
320-
});
321-
const conditionCollection = await page.locator('#conditionCollection');
322-
301+
// Add Telemetry to ConditionSet
302+
const sineWaveGeneratorTreeItem = page
303+
.getByRole('tree', {
304+
name: 'Main Tree'
305+
})
306+
.getByRole('treeitem', {
307+
name: exampleTelemetry.name
308+
});
309+
const conditionCollection = page.locator('#conditionCollection');
323310
await sineWaveGeneratorTreeItem.dragTo(conditionCollection);
324311

325-
const firstCriterionTelemetry = await page.locator(
312+
// Modify First Criterion
313+
const firstCriterionTelemetry = page.locator(
326314
'[aria-label="Criterion Telemetry Selection"] >> nth=0'
327315
);
328-
firstCriterionTelemetry.selectOption({ label: 'Delayed Sine Wave Generator' });
329-
330-
const secondCriterionTelemetry = await page.locator(
331-
'[aria-label="Criterion Telemetry Selection"] >> nth=1'
332-
);
333-
secondCriterionTelemetry.selectOption({ label: 'Delayed Sine Wave Generator' });
334-
335-
const firstCriterionMetadata = await page.locator(
316+
firstCriterionTelemetry.selectOption({ label: exampleTelemetry.name });
317+
const firstCriterionMetadata = page.locator(
336318
'[aria-label="Criterion Metadata Selection"] >> nth=0'
337319
);
338320
firstCriterionMetadata.selectOption({ label: 'Sine' });
321+
const firstCriterionComparison = page.locator(
322+
'[aria-label="Criterion Comparison Selection"] >> nth=0'
323+
);
324+
firstCriterionComparison.selectOption({ label: 'is greater than or equal to' });
325+
const firstCriterionInput = page.locator('[aria-label="Criterion Input"] >> nth=0');
326+
await firstCriterionInput.fill('0');
339327

340-
const secondCriterionMetadata = await page.locator(
341-
'[aria-label="Criterion Metadata Selection"] >> nth=1'
328+
// Modify First Criterion
329+
const secondCriterionTelemetry = page.locator(
330+
'[aria-label="Criterion Telemetry Selection"] >> nth=1'
342331
);
343-
secondCriterionMetadata.selectOption({ label: 'Sine' });
332+
secondCriterionTelemetry.selectOption({ label: exampleTelemetry.name });
344333

345-
const firstCriterionComparison = await page.locator(
346-
'[aria-label="Criterion Comparison Selection"] >> nth=0'
334+
const secondCriterionMetadata = page.locator(
335+
'[aria-label="Criterion Metadata Selection"] >> nth=1'
347336
);
348-
firstCriterionComparison.selectOption({ label: 'is greater than or equal to' });
337+
secondCriterionMetadata.selectOption({ label: 'Sine' });
349338

350-
const secondCriterionComparison = await page.locator(
339+
const secondCriterionComparison = page.locator(
351340
'[aria-label="Criterion Comparison Selection"] >> nth=1'
352341
);
353342
secondCriterionComparison.selectOption({ label: 'is less than' });
354343

355-
const firstCriterionInput = await page.locator('[aria-label="Criterion Input"] >> nth=0');
356-
await firstCriterionInput.fill('0');
357-
358-
const secondCriterionInput = await page.locator('[aria-label="Criterion Input"] >> nth=1');
344+
const secondCriterionInput = page.locator('[aria-label="Criterion Input"] >> nth=1');
359345
await secondCriterionInput.fill('0');
360346

361-
const saveButtonLocator = page.locator('button[title="Save"]');
362-
await saveButtonLocator.click();
347+
// Save ConditionSet
348+
await page.locator('button[title="Save"]').click();
363349
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
364350

365-
const outputValue = await page.locator('[aria-label="Current Output Value"]');
351+
// Validate that the condition set is evaluating and outputting
352+
// the correct value when the underlying telemetry subscription is active.
353+
let outputValue = page.locator('[aria-label="Current Output Value"]');
354+
await expect(outputValue).toHaveText('false');
355+
356+
await page.goto(exampleTelemetry.url);
357+
358+
// Edit SWG to add 8 second loading delay to simulate the case
359+
// where telemetry is not available.
360+
await page.getByTitle('More options').click();
361+
await page.getByRole('menuitem', { name: 'Edit Properties...' }).click();
362+
await page.getByRole('spinbutton', { name: 'Loading Delay (ms)' }).fill('8000');
363+
await page.getByLabel('Save').click();
364+
365+
// Expect that the output value is blank or '---' if the
366+
// underlying telemetry subscription is not active.
367+
await page.goto(conditionSet.url);
366368
await expect(outputValue).toHaveText('---');
367369
});
368370
});

e2e/tests/functional/plugins/plot/tagging.e2e.spec.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const {
2929
createDomainObjectWithDefaults,
3030
setRealTimeMode,
3131
setFixedTimeMode,
32-
waitForPlotsToRender
32+
waitForPlotsToRender,
33+
selectInspectorTab
3334
} = require('../../../../appActions');
3435

3536
test.describe('Plot Tagging', () => {
@@ -146,7 +147,10 @@ test.describe('Plot Tagging', () => {
146147
// wait for plots to load
147148
await waitForPlotsToRender(page);
148149

149-
await page.getByText('Annotations').click();
150+
await expect(page.getByRole('tab', { name: 'Annotations' })).not.toHaveClass(/is-current/);
151+
await selectInspectorTab(page, 'Annotations');
152+
await expect(page.getByRole('tab', { name: 'Annotations' })).toHaveClass(/is-current/);
153+
150154
await expect(page.getByText('No tags to display for this item')).toBeVisible();
151155

152156
const canvas = page.locator('canvas').nth(1);

example/generator/WorkerInterface.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ define(['uuid'], function ({ v4: uuid }) {
8888
};
8989

9090
WorkerInterface.prototype.subscribe = function (request, cb) {
91-
const id = request.id;
91+
const { id, loadDelay } = request;
9292
const messageId = this.dispatch('subscribe', request, (message) => {
9393
if (!this.staleTelemetryIds[id]) {
94-
cb(message.data);
94+
setTimeout(() => cb(message.data), Math.max(loadDelay, 0));
9595
}
9696
});
9797

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"clean-test-lint": "npm run clean; npm install; npm run test; npm run lint; npm run lint:spelling",
8282
"start": "npx webpack serve --config ./.webpack/webpack.dev.js",
8383
"start:coverage": "npx webpack serve --config ./.webpack/webpack.coverage.js",
84-
"lint": "eslint example src e2e --ext .js,.vue openmct.js --max-warnings=0",
84+
"lint": "eslint example src e2e --ext .js openmct.js --max-warnings=0 && eslint example src --ext .vue",
8585
"lint:spelling": "cspell \"**/*.{js,md,vue}\" --show-context --gitignore",
8686
"lint:fix": "eslint example src e2e --ext .js,.vue openmct.js --fix",
8787
"build:prod": "webpack --config ./.webpack/webpack.prod.js",

src/plugins/condition/ConditionManager.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ export default class ConditionManager extends EventEmitter {
399399
}
400400

401401
shouldEvaluateNewTelemetry(currentTimestamp) {
402-
return this.openmct.time.bounds().end >= currentTimestamp;
402+
return this.openmct.time.getBounds().end >= currentTimestamp;
403403
}
404404

405405
telemetryReceived(endpoint, datum) {

src/plugins/timeConductor/ConductorClock.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,19 @@ export default {
5858
}
5959
}
6060
},
61-
data: function () {
61+
data() {
6262
const activeClock = this.getActiveClock();
6363

6464
return {
6565
selectedClock: activeClock ? this.getClockMetadata(activeClock) : undefined,
6666
clocks: []
6767
};
6868
},
69-
mounted: function () {
69+
mounted() {
7070
this.loadClocks(this.configuration.menuOptions);
7171
this.openmct.time.on(TIME_CONTEXT_EVENTS.clockChanged, this.setViewFromClock);
7272
},
73-
destroyed: function () {
73+
unmounted() {
7474
this.openmct.time.off(TIME_CONTEXT_EVENTS.clockChanged, this.setViewFromClock);
7575
},
7676
methods: {

0 commit comments

Comments
 (0)