diff --git a/.cspell.json b/.cspell.json index 3ba2caaac6..9915d5f666 100644 --- a/.cspell.json +++ b/.cspell.json @@ -483,7 +483,8 @@ "countup", "darkmatter", "Undeletes", - "SSSZ" + "SSSZ", + "pageerror" ], "dictionaries": ["npm", "softwareTerms", "node", "html", "css", "bash", "en_US", "en-gb", "misc"], "ignorePaths": [ diff --git a/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js b/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js index d85c89883a..128dd25699 100644 --- a/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js +++ b/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js @@ -28,7 +28,9 @@ import { v4 as uuid } from 'uuid'; import { createDomainObjectWithDefaults, - createExampleTelemetryObject + createExampleTelemetryObject, + setRealTimeMode, + setStartOffset } from '../../../../appActions.js'; import { expect, test } from '../../../../pluginFixtures.js'; @@ -166,6 +168,57 @@ test.describe('Gauge', () => { ); }); + test('Gauge does not break when an object is missing', async ({ page }) => { + // Set up error listeners + const pageErrors = []; + + // Listen for uncaught exceptions + page.on('pageerror', (err) => { + pageErrors.push(err.message); + }); + + await setRealTimeMode(page); + + // Create a Gauge + const gauge = await createDomainObjectWithDefaults(page, { + type: 'Gauge', + name: 'Gauge with missing object' + }); + + // Create a Sine Wave Generator in the Gauge with a loading delay + const missingSWG = await createExampleTelemetryObject(page, gauge.uuid); + + // Remove the object from local storage + await page.evaluate( + ([missingObject]) => { + const mct = localStorage.getItem('mct'); + const mctObjects = JSON.parse(mct); + delete mctObjects[missingObject.uuid]; + localStorage.setItem('mct', JSON.stringify(mctObjects)); + }, + [missingSWG] + ); + + // Verify start bounds + await expect(page.getByLabel('Start offset: 00:30:00')).toBeVisible(); + + // Nav to the Gauge + await page.goto(gauge.url, { waitUntil: 'domcontentloaded' }); + + // adjust time bounds and ensure they are updated + await setStartOffset(page, { + startHours: '00', + startMins: '45', + startSecs: '00' + }); + + // Verify start bounds changed + await expect(page.getByLabel('Start offset: 00:45:00')).toBeVisible(); + + // // Verify no errors were thrown + expect(pageErrors).toHaveLength(0); + }); + test('Gauge enforces composition policy', async ({ page }) => { // Create a Gauge await createDomainObjectWithDefaults(page, { diff --git a/src/plugins/gauge/components/GaugeComponent.vue b/src/plugins/gauge/components/GaugeComponent.vue index d14bc6c15c..080d6593c1 100644 --- a/src/plugins/gauge/components/GaugeComponent.vue +++ b/src/plugins/gauge/components/GaugeComponent.vue @@ -649,6 +649,11 @@ export default { }, request(domainObject = this.telemetryObject) { this.metadata = this.openmct.telemetry.getMetadata(domainObject); + + if (!this.metadata) { + return; + } + this.formats = this.openmct.telemetry.getFormatMap(this.metadata); const LimitEvaluator = this.openmct.telemetry.getLimits(domainObject); LimitEvaluator.limits().then(this.updateLimits);