From 8c2558bfe0fd8ab1f490ac1c7110d91c2475ca87 Mon Sep 17 00:00:00 2001 From: Jesse Mazzella Date: Mon, 11 Mar 2024 16:39:38 -0700 Subject: [PATCH] fix(#7524): Open in New Tab action from a sub-object in a layout (#7542) * refactor: url tools use named exports * fix: refactor method and remove customUrlParams * test(e2e): verify bounds are preserved in data pivoting * test: remove test as feature is no longer needed - dataVisualization logic has moved from MMGIS plugin to the open source. As such, we can just use the time conductor bounds * refactor: autoformat keeps changing this so i'mma just commit it * refactor: remove unnecessary code * refactor: simplify, add docs * Revert "refactor: remove unnecessary code" This reverts commit 87aef35c510230835fb682b80e89a6006ef2d923. * a11y: improve aria labels for ITC * fix: simplify url method * fix: update ITC app actions * test: add test to generate test data for display layout w/ overlay plot + ITC enabled * test(e2e): add suite + test for open in new tab from subobject - needs cleanup * a11y: various a11y improvement drivebys * a11y: clock indicator needs to be quiet * a11y: add `aria-live` to SuperMenu details * a11y: greatly improve a11y of Menus and SuperMenus * test(e2e): clean up test * fix: improve a11y for context menus, fix test * chore: remove nop-longer-recommended extension * feat: provide one more bound option for example data viz * fix: no need for `mount`, use dynamic rendering instead * Revert "fix: simplify url method" This reverts commit b24c7dabc783a9a1c3f2460eada99f452259f566. * fix: correct time conductor bounds when opening in a new tab from a plot in the inspector * test: fix e2e tests * Revert "test: remove test as feature is no longer needed" This reverts commit 759ebd4667bffb1979d5f62af6b47f349dcd9f77. * test: move 2p annotation to test * test: fix e2e * fix: no words for the word god today * test: fix e2e * fix: e2e test * test: fix test * driveby: fix perf test * fix: revert required prop change --------- Co-authored-by: David Tsay <3614296+davetsay@users.noreply.github.com> Co-authored-by: John Hill --- .vscode/extensions.json | 1 - e2e/appActions.js | 11 +- ...isplay_layout_with_child_overlay_plot.json | 26 ++++ e2e/tests/framework/appActions.e2e.spec.js | 2 +- .../generateLocalStorageData.e2e.spec.js | 54 +++++++- .../functional/planning/timestrip.e2e.spec.js | 10 +- .../conditionSet/conditionSet.e2e.spec.js | 2 +- .../displayLayout/displayLayout.e2e.spec.js | 115 +++++++++++++++++- .../flexibleLayout/flexibleLayout.e2e.spec.js | 9 +- .../plugins/gauge/gauge.e2e.spec.js | 4 +- .../numericData.e2e.spec.js | 6 + .../notebook/notebookSnapshots.e2e.spec.js | 2 +- .../styling/flexLayoutStyling.e2e.spec.js | 80 ++++++++---- .../styling/styleInspectorOptions.e2e.spec.js | 2 +- .../contract/imagery.contract.perf.spec.js | 2 +- .../components/header.visual.spec.js | 4 +- e2e/tests/visual-a11y/styling.visual.spec.js | 2 +- .../visual-a11y/telemetryViews.visual.spec.js | 4 +- .../ExampleDataVisualizationSource.vue | 8 ++ index.html | 2 +- src/api/menu/components/MenuComponent.vue | 24 +++- src/api/menu/components/SuperMenu.vue | 41 ++++--- src/plugins/LADTable/components/LadRow.vue | 4 +- .../clock/components/ClockIndicator.vue | 1 + .../NumericDataInspectorView.vue | 79 ++++-------- .../TelemetryFrame.vue | 17 ++- .../notebook/components/NotebookEmbed.vue | 2 +- .../components/NotebookMenuSwitcher.vue | 11 +- .../openInNewTabAction/openInNewTabAction.js | 24 +++- .../independent/IndependentTimeConductor.vue | 1 + src/styles/_global.scss | 16 ++- src/tools/url.js | 31 ++--- src/tools/urlSpec.js | 2 +- src/ui/components/ObjectFrame.vue | 5 + src/ui/layout/AppLayout.vue | 6 +- src/ui/layout/CreateButton.vue | 3 +- src/ui/layout/ViewSwitcher.vue | 8 +- src/ui/layout/search/ObjectSearchResult.vue | 4 +- src/ui/mixins/context-menu-gesture.js | 3 +- src/ui/mixins/object-link.js | 2 +- 40 files changed, 465 insertions(+), 165 deletions(-) create mode 100644 e2e/test-data/display_layout_with_child_overlay_plot.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 24ebdbe6fb..d88ed5d86a 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,7 +5,6 @@ // List of extensions which should be recommended for users of this workspace. "recommendations": [ "Vue.volar", - "Vue.vscode-typescript-vue-plugin", "dbaeumer.vscode-eslint", "rvest.vs-code-prettier-eslint" ], diff --git a/e2e/appActions.js b/e2e/appActions.js index 92b71fd281..0dcfbb3617 100644 --- a/e2e/appActions.js +++ b/e2e/appActions.js @@ -505,15 +505,14 @@ async function setTimeConductorBounds(page, startDate, endDate) { * @param {string} startDate * @param {string} endDate */ -async function setIndependentTimeConductorBounds(page, startDate, endDate) { - // Activate Independent Time Conductor in Fixed Time Mode - await page.getByRole('switch').click(); +async function setIndependentTimeConductorBounds(page, { start, end }) { + // Activate Independent Time Conductor + await page.getByLabel('Enable Independent Time Conductor').click(); // Bring up the time conductor popup - await page.click('.c-conductor-holder--compact .c-compact-tc'); + await page.getByLabel('Independent Time Conductor Settings').click(); await expect(page.locator('.itc-popout')).toBeInViewport(); - - await setTimeBounds(page, startDate, endDate); + await setTimeBounds(page, start, end); await page.keyboard.press('Enter'); } diff --git a/e2e/test-data/display_layout_with_child_overlay_plot.json b/e2e/test-data/display_layout_with_child_overlay_plot.json new file mode 100644 index 0000000000..b6854feba2 --- /dev/null +++ b/e2e/test-data/display_layout_with_child_overlay_plot.json @@ -0,0 +1,26 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:8080", + "localStorage": [ + { + "name": "mct", + "value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140},\"29836e66-111a-45f8-81ed-f662661be9f9\":{\"identifier\":{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"},\"name\":\"Parent Display Layout\",\"type\":\"layout\",\"composition\":[{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"}],\"configuration\":{\"items\":[{\"width\":32,\"height\":18,\"x\":1,\"y\":1,\"identifier\":{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"},\"hasFrame\":true,\"fontSize\":\"default\",\"font\":\"default\",\"type\":\"subobject-view\",\"id\":\"022720f7-a6b5-40c3-b051-75f5d10a9042\"}],\"layoutGrid\":[10,10]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604780,\"location\":\"mine\",\"created\":1732413602140,\"persisted\":1732413604780},\"55cd0300-6e57-4992-b670-0c2880c0e6b2\":{\"identifier\":{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"},\"name\":\"Child Overlay Plot 1\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"}],\"configuration\":{\"series\":[{\"identifier\":{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"}}],\"useIndependentTime\":true,\"timeOptions\":{\"clockOffsets\":{\"start\":-1800000,\"end\":30000},\"fixedOffsets\":{\"start\":1731438671000,\"end\":1731442271000},\"clock\":\"local\",\"mode\":\"fixed\"}},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413605500,\"location\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"created\":1732413603280,\"persisted\":1732413605500},\"ec13f652-4636-4763-8e88-898144cbc6f2\":{\"name\":\"Child SWG 1\",\"type\":\"generator\",\"identifier\":{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"},\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":0,\"infinityValues\":false,\"exceedFloat32\":false,\"staleness\":false},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"created\":1732413604440,\"persisted\":1732413604440}}" + }, + { + "name": "mct-tree-expanded", + "value": "[]" + }, + { + "name": "tcHistory", + "value": "{\"utc\":[{\"start\":1731352271000,\"end\":1731355871000}]}" + }, + { + "name": "mct-recent-objects", + "value": "[{\"objectPath\":[{\"identifier\":{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"},\"name\":\"Parent Display Layout\",\"type\":\"layout\",\"composition\":[{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"}],\"configuration\":{\"items\":[],\"layoutGrid\":[10,10]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413603280,\"location\":\"mine\",\"created\":1732413602140,\"persisted\":1732413603280},{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine/29836e66-111a-45f8-81ed-f662661be9f9\",\"domainObject\":{\"identifier\":{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"},\"name\":\"Parent Display Layout\",\"type\":\"layout\",\"composition\":[{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"}],\"configuration\":{\"items\":[],\"layoutGrid\":[10,10]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413603280,\"location\":\"mine\",\"created\":1732413602140,\"persisted\":1732413603280}},{\"objectPath\":[{\"identifier\":{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"},\"name\":\"Child SWG 1\",\"type\":\"generator\",\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":0,\"infinityValues\":false,\"exceedFloat32\":false,\"staleness\":false},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"created\":1732413604440,\"persisted\":1732413604440},{\"identifier\":{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"},\"name\":\"Child Overlay Plot 1\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"created\":1732413603280,\"persisted\":1732413604440},{\"identifier\":{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"},\"name\":\"Parent Display Layout\",\"type\":\"layout\",\"composition\":[{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"}],\"configuration\":{\"items\":[],\"layoutGrid\":[10,10]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413603280,\"location\":\"mine\",\"created\":1732413602140,\"persisted\":1732413603280},{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine/29836e66-111a-45f8-81ed-f662661be9f9/55cd0300-6e57-4992-b670-0c2880c0e6b2/ec13f652-4636-4763-8e88-898144cbc6f2\",\"domainObject\":{\"identifier\":{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"},\"name\":\"Child SWG 1\",\"type\":\"generator\",\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":0,\"infinityValues\":false,\"exceedFloat32\":false,\"staleness\":false},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"created\":1732413604440,\"persisted\":1732413604440}},{\"objectPath\":[{\"identifier\":{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"},\"name\":\"Child Overlay Plot 1\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"created\":1732413603280,\"persisted\":1732413604440},{\"identifier\":{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"},\"name\":\"Parent Display Layout\",\"type\":\"layout\",\"composition\":[{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"}],\"configuration\":{\"items\":[],\"layoutGrid\":[10,10]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413603280,\"location\":\"mine\",\"created\":1732413602140,\"persisted\":1732413603280},{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine/29836e66-111a-45f8-81ed-f662661be9f9/55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"domainObject\":{\"identifier\":{\"key\":\"55cd0300-6e57-4992-b670-0c2880c0e6b2\",\"namespace\":\"\"},\"name\":\"Child Overlay Plot 1\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"ec13f652-4636-4763-8e88-898144cbc6f2\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateLocalStorageData.e2e.spec.js\\nGenerate Visual Test Data @localStorage @generatedata\\nGenerate display layout with 1 child overlay plot\\nchrome\",\"modified\":1732413604440,\"location\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"created\":1732413603280,\"persisted\":1732413604440}},{\"objectPath\":[{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine\",\"domainObject\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"29836e66-111a-45f8-81ed-f662661be9f9\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1732413602140,\"created\":1732413600860,\"persisted\":1732413602140}}]" + } + ] + } + ] +} \ No newline at end of file diff --git a/e2e/tests/framework/appActions.e2e.spec.js b/e2e/tests/framework/appActions.e2e.spec.js index 4aba0e196e..cc93247951 100644 --- a/e2e/tests/framework/appActions.e2e.spec.js +++ b/e2e/tests/framework/appActions.e2e.spec.js @@ -174,6 +174,6 @@ test.describe('AppActions', () => { type: 'Folder' }); await openObjectTreeContextMenu(page, folder.url); - await expect(page.getByLabel('Menu')).toBeVisible(); + await expect(page.getByLabel(`${folder.name} Context Menu`)).toBeVisible(); }); }); diff --git a/e2e/tests/framework/generateLocalStorageData.e2e.spec.js b/e2e/tests/framework/generateLocalStorageData.e2e.spec.js index b01aba37c8..de8741cc88 100644 --- a/e2e/tests/framework/generateLocalStorageData.e2e.spec.js +++ b/e2e/tests/framework/generateLocalStorageData.e2e.spec.js @@ -33,7 +33,12 @@ import { fileURLToPath } from 'url'; -import { createDomainObjectWithDefaults, createExampleTelemetryObject } from '../../appActions.js'; +import { + createDomainObjectWithDefaults, + createExampleTelemetryObject, + setIndependentTimeConductorBounds, + setTimeConductorBounds +} from '../../appActions.js'; import { MISSION_TIME } from '../../constants.js'; import { expect, test } from '../../pluginFixtures.js'; @@ -89,6 +94,53 @@ test.describe('Generate Visual Test Data @localStorage @generatedata @clock', () }); }); + test('Generate display layout with 1 child overlay plot', async ({ page, context }) => { + const parent = await createDomainObjectWithDefaults(page, { + type: 'Display Layout', + name: 'Parent Display Layout' + }); + const overlayPlot = await createDomainObjectWithDefaults(page, { + type: 'Overlay Plot', + name: 'Child Overlay Plot 1', + parent: parent.uuid + }); + await createDomainObjectWithDefaults(page, { + type: 'Sine Wave Generator', + name: 'Child SWG 1', + parent: overlayPlot.uuid + }); + + await page.goto(parent.url, { waitUntil: 'domcontentloaded' }); + + await setIndependentTimeConductorBounds(page, { + start: '2024-11-12 19:11:11.000Z', + end: '2024-11-12 20:11:11.000Z' + }); + + const NEW_GLOBAL_START_BOUNDS = '2024-11-11 19:11:11.000Z'; + const NEW_GLOBAL_END_BOUNDS = '2024-11-11 20:11:11.000Z'; + + await setTimeConductorBounds(page, NEW_GLOBAL_START_BOUNDS, NEW_GLOBAL_END_BOUNDS); + + // Verify that the global time conductor bounds have been updated + expect( + await page.getByLabel('Global Time Conductor').getByLabel('Start bounds').textContent() + ).toEqual(NEW_GLOBAL_START_BOUNDS); + expect( + await page.getByLabel('Global Time Conductor').getByLabel('End bounds').textContent() + ).toEqual(NEW_GLOBAL_END_BOUNDS); + + //Save localStorage for future test execution + await context.storageState({ + path: fileURLToPath( + new URL( + '../../../e2e/test-data/display_layout_with_child_overlay_plot.json', + import.meta.url + ) + ) + }); + }); + test('Generate flexible layout with 2 child display layouts', async ({ page, context }) => { // Create Display Layout const parent = await createDomainObjectWithDefaults(page, { diff --git a/e2e/tests/functional/planning/timestrip.e2e.spec.js b/e2e/tests/functional/planning/timestrip.e2e.spec.js index 46abb087f9..e6b36181c7 100644 --- a/e2e/tests/functional/planning/timestrip.e2e.spec.js +++ b/e2e/tests/functional/planning/timestrip.e2e.spec.js @@ -131,7 +131,10 @@ test.describe('Time Strip', () => { const startBoundString = new Date(startBound).toISOString().replace('T', ' '); const endBoundString = new Date(endBound).toISOString().replace('T', ' '); - await setIndependentTimeConductorBounds(page, startBoundString, endBoundString); + await setIndependentTimeConductorBounds(page, { + start: startBoundString, + end: endBoundString + }); expect(await activityBounds.count()).toEqual(1); }); @@ -160,7 +163,10 @@ test.describe('Time Strip', () => { const startBoundString = new Date(startBound).toISOString().replace('T', ' '); const endBoundString = new Date(endBound).toISOString().replace('T', ' '); - await setIndependentTimeConductorBounds(page, startBoundString, endBoundString); + await setIndependentTimeConductorBounds(page, { + start: startBoundString, + end: endBoundString + }); // Verify that two events are displayed expect(await activityBounds.count()).toEqual(2); diff --git a/e2e/tests/functional/plugins/conditionSet/conditionSet.e2e.spec.js b/e2e/tests/functional/plugins/conditionSet/conditionSet.e2e.spec.js index a9684daabb..ade83caa8a 100644 --- a/e2e/tests/functional/plugins/conditionSet/conditionSet.e2e.spec.js +++ b/e2e/tests/functional/plugins/conditionSet/conditionSet.e2e.spec.js @@ -286,7 +286,7 @@ test.describe('Basic Condition Set Use', () => { await page.locator('button[title="Save"]').click(); await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click(); - await page.click('button[title="Change the current view"]'); + await page.getByLabel('Open the View Switcher Menu').click(); await expect(page.getByRole('menuitem', { name: /Lad Table/ })).toBeHidden(); await expect(page.getByRole('menuitem', { name: /Conditions View/ })).toBeVisible(); diff --git a/e2e/tests/functional/plugins/displayLayout/displayLayout.e2e.spec.js b/e2e/tests/functional/plugins/displayLayout/displayLayout.e2e.spec.js index f06b29b509..cc678d3b5b 100644 --- a/e2e/tests/functional/plugins/displayLayout/displayLayout.e2e.spec.js +++ b/e2e/tests/functional/plugins/displayLayout/displayLayout.e2e.spec.js @@ -23,6 +23,7 @@ import { fileURLToPath } from 'url'; import { createDomainObjectWithDefaults, + navigateToObjectWithFixedTimeBounds, setFixedTimeMode, setIndependentTimeConductorBounds, setRealTimeMode, @@ -30,12 +31,120 @@ import { } from '../../../../appActions.js'; import { expect, test } from '../../../../pluginFixtures.js'; -const LOCALSTORAGE_PATH = fileURLToPath( +const CHILD_LAYOUT_STORAGE_STATE_PATH = fileURLToPath( new URL('../../../../test-data/display_layout_with_child_layouts.json', import.meta.url) ); +const CHILD_PLOT_STORAGE_STATE_PATH = fileURLToPath( + new URL('../../../../test-data/display_layout_with_child_overlay_plot.json', import.meta.url) +); const TINY_IMAGE_BASE64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII'; +test.describe('Display Layout Sub-object Actions @localStorage', () => { + const INIT_ITC_START_BOUNDS = '2024-11-12 19:11:11.000Z'; + const INIT_ITC_END_BOUNDS = '2024-11-12 20:11:11.000Z'; + const NEW_GLOBAL_START_BOUNDS = '2024-11-11 19:11:11.000Z'; + const NEW_GLOBAL_END_BOUNDS = '2024-11-11 20:11:11.000Z'; + + test.use({ + storageState: CHILD_PLOT_STORAGE_STATE_PATH + }); + + test.beforeEach(async ({ page }) => { + await page.goto('./', { waitUntil: 'domcontentloaded' }); + await page.getByLabel('Expand My Items folder').click(); + const waitForMyItemsNavigation = page.waitForURL(`**/mine/?*`); + await page + .getByLabel('Main Tree') + .getByLabel('Navigate to Parent Display Layout layout Object') + .click(); + // Wait for the URL to change to the display layout + await waitForMyItemsNavigation; + }); + test('Open in New Tab action preserves time bounds @2p', async ({ page }) => { + test.info().annotations.push({ + type: 'issue', + description: 'https://github.com/nasa/openmct/issues/7524' + }); + test.info().annotations.push({ + type: 'issue', + description: 'https://github.com/nasa/openmct/issues/6982' + }); + + const TEST_FIXED_START_TIME = 1731352271000; // 2024-11-11 19:11:11.000Z + const TEST_FIXED_END_TIME = TEST_FIXED_START_TIME + 3600000; // 2024-11-11 20:11:11.000Z + + // Verify the ITC has the expected initial bounds + expect( + await page + .getByLabel('Child Overlay Plot 1 Frame Controls') + .getByLabel('Start bounds') + .textContent() + ).toEqual(INIT_ITC_START_BOUNDS); + expect( + await page + .getByLabel('Child Overlay Plot 1 Frame Controls') + .getByLabel('End bounds') + .textContent() + ).toEqual(INIT_ITC_END_BOUNDS); + + // Update the global fixed bounds to 2024-11-11 19:11:11.000Z / 2024-11-11 20:11:11.000Z + const url = page.url().split('?')[0]; + await navigateToObjectWithFixedTimeBounds( + page, + url, + TEST_FIXED_START_TIME, + TEST_FIXED_END_TIME + ); + + // ITC bounds should still match the initial ITC bounds + expect( + await page + .getByLabel('Child Overlay Plot 1 Frame Controls') + .getByLabel('Start bounds') + .textContent() + ).toEqual(INIT_ITC_START_BOUNDS); + expect( + await page + .getByLabel('Child Overlay Plot 1 Frame Controls') + .getByLabel('End bounds') + .textContent() + ).toEqual(INIT_ITC_END_BOUNDS); + + // Open the Child Overlay Plot 1 in a new tab + await page.getByLabel('View menu items').click(); + const pagePromise = page.context().waitForEvent('page'); + await page.getByLabel('Open In New Tab').click(); + + const newPage = await pagePromise; + await newPage.waitForLoadState('domcontentloaded'); + + // Verify that the global time conductor bounds in the new page match the updated global bounds + expect( + await newPage.getByLabel('Global Time Conductor').getByLabel('Start bounds').textContent() + ).toEqual(NEW_GLOBAL_START_BOUNDS); + expect( + await newPage.getByLabel('Global Time Conductor').getByLabel('End bounds').textContent() + ).toEqual(NEW_GLOBAL_END_BOUNDS); + + // Verify that the ITC is enabled in the new page + await expect(newPage.getByLabel('Disable Independent Time Conductor')).toBeVisible(); + // Verify that the ITC bounds in the new page match the original ITC bounds + expect( + await newPage + .getByLabel('Independent Time Conductor Panel') + .getByLabel('Start bounds') + .textContent() + ).toEqual(INIT_ITC_START_BOUNDS); + expect( + await newPage + .getByLabel('Independent Time Conductor Panel') + .getByLabel('End bounds') + .textContent() + ).toEqual(INIT_ITC_END_BOUNDS); + }); +}); + test.describe('Display Layout Toolbar Actions @localStorage', () => { const PARENT_DISPLAY_LAYOUT_NAME = 'Parent Display Layout'; const CHILD_DISPLAY_LAYOUT_NAME1 = 'Child Layout 1'; @@ -50,7 +159,7 @@ test.describe('Display Layout Toolbar Actions @localStorage', () => { await page.getByLabel('Edit Object').click(); }); test.use({ - storageState: LOCALSTORAGE_PATH + storageState: CHILD_LAYOUT_STORAGE_STATE_PATH }); test('can add/remove Text element to a single layout', async ({ page }) => { @@ -336,7 +445,7 @@ test.describe('Display Layout', () => { const startDate = '2021-12-30 01:01:00.000Z'; const endDate = '2021-12-30 01:11:00.000Z'; - await setIndependentTimeConductorBounds(page, startDate, endDate); + await setIndependentTimeConductorBounds(page, { start: startDate, end: endDate }); // check image date await expect(page.getByText('2021-12-30 01:11:00.000Z').first()).toBeVisible(); diff --git a/e2e/tests/functional/plugins/flexibleLayout/flexibleLayout.e2e.spec.js b/e2e/tests/functional/plugins/flexibleLayout/flexibleLayout.e2e.spec.js index e25283d8d6..17ad06b78a 100644 --- a/e2e/tests/functional/plugins/flexibleLayout/flexibleLayout.e2e.spec.js +++ b/e2e/tests/functional/plugins/flexibleLayout/flexibleLayout.e2e.spec.js @@ -248,11 +248,10 @@ test.describe('Flexible Layout', () => { await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click(); // flip on independent time conductor - await setIndependentTimeConductorBounds( - page, - '2021-12-30 01:01:00.000Z', - '2021-12-30 01:11:00.000Z' - ); + await setIndependentTimeConductorBounds(page, { + start: '2021-12-30 01:01:00.000Z', + end: '2021-12-30 01:11:00.000Z' + }); // check image date await expect(page.getByText('2021-12-30 01:11:00.000Z').first()).toBeVisible(); diff --git a/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js b/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js index 46a65ce579..d2dd067f30 100644 --- a/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js +++ b/e2e/tests/functional/plugins/gauge/gauge.e2e.spec.js @@ -175,13 +175,13 @@ test.describe('Gauge', () => { }); // Try to create a Folder into the Gauge. Should be disallowed. - await page.getByRole('button', { name: /Create/ }).click(); + await page.getByRole('button', { name: 'Create' }).click(); await page.getByRole('menuitem', { name: /Folder/ }).click(); await expect(page.locator('[aria-label="Save"]')).toBeDisabled(); await page.getByLabel('Cancel').click(); // Try to create a Display Layout into the Gauge. Should be disallowed. - await page.getByRole('button', { name: /Create/ }).click(); + await page.getByRole('button', { name: 'Create' }).click(); await page.getByRole('menuitem', { name: /Display Layout/ }).click(); await expect(page.locator('[aria-label="Save"]')).toBeDisabled(); }); diff --git a/e2e/tests/functional/plugins/inspectorDataVisualization/numericData.e2e.spec.js b/e2e/tests/functional/plugins/inspectorDataVisualization/numericData.e2e.spec.js index 8bfb1a666a..7166112b05 100644 --- a/e2e/tests/functional/plugins/inspectorDataVisualization/numericData.e2e.spec.js +++ b/e2e/tests/functional/plugins/inspectorDataVisualization/numericData.e2e.spec.js @@ -37,6 +37,8 @@ test.describe('Testing numeric data with inspector data visualization (i.e., dat }); test('Can click on telemetry and see data in inspector @2p', async ({ page, context }) => { + const initStartBounds = await page.getByLabel('Start bounds').textContent(); + const initEndBounds = await page.getByLabel('End bounds').textContent(); const exampleDataVisualizationSource = await createDomainObjectWithDefaults(page, { type: 'Example Data Visualization Source' }); @@ -78,5 +80,9 @@ test.describe('Testing numeric data with inspector data visualization (i.e., dat await newPage.waitForLoadState(); // expect new tab title to contain 'Second Sine Wave Generator' await expect(newPage).toHaveTitle('Second Sine Wave Generator'); + + // Verify that "Open in New Tab" preserves the time bounds + expect(initStartBounds).toEqual(await newPage.getByLabel('Start bounds').textContent()); + expect(initEndBounds).toEqual(await newPage.getByLabel('End bounds').textContent()); }); }); diff --git a/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js index b6064e8665..377b078366 100644 --- a/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js @@ -83,7 +83,7 @@ test.describe('Snapshot Container tests', () => { // name: "Dropped Overlay Plot" // }); - await page.getByLabel('Take a Notebook Snapshot').click(); + await page.getByLabel('Open the Notebook Snapshot Menu').click(); await page.getByRole('menuitem', { name: 'Save to Notebook Snapshots' }).click(); await page.getByLabel('Show Snapshots').click(); }); diff --git a/e2e/tests/functional/plugins/styling/flexLayoutStyling.e2e.spec.js b/e2e/tests/functional/plugins/styling/flexLayoutStyling.e2e.spec.js index 6431066eff..27129822fd 100644 --- a/e2e/tests/functional/plugins/styling/flexLayoutStyling.e2e.spec.js +++ b/e2e/tests/functional/plugins/styling/flexLayoutStyling.e2e.spec.js @@ -114,7 +114,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultFrameBorderColor), NO_STYLE_RGBA, hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2. Note: https://github.com/nasa/openmct/issues/7337 @@ -122,7 +124,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultFrameBorderColor), NO_STYLE_RGBA, hexToRGB(setTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); }); @@ -143,7 +147,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(defaultTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 @@ -151,7 +157,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(defaultTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Set styles using setStyles function on StackedPlot1 but not StackedPlot2 @@ -160,7 +168,7 @@ test.describe('Flexible Layout styling', () => { setBorderColor, setBackgroundColor, setTextColor, - page.getByLabel('StackedPlot1 Frame') + page.getByRole('group', { name: 'StackedPlot1 Frame' }) ); // Check styles on StackedPlot1 @@ -168,7 +176,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 @@ -176,7 +186,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(defaultTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Save Flexible Layout @@ -191,7 +203,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 @@ -199,7 +213,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(defaultTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); }); @@ -241,7 +257,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 to verify they are the default @@ -249,7 +267,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(defaultTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Set styles using setStyles function on StackedPlot2 @@ -258,7 +278,7 @@ test.describe('Flexible Layout styling', () => { setBorderColor, setBackgroundColor, setTextColor, - page.getByLabel('StackedPlot2 Frame') + page.getByRole('group', { name: 'StackedPlot2 Frame' }) ); // Check styles on StackedPlot2 @@ -266,7 +286,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Save Flexible Layout @@ -281,7 +303,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 @@ -289,7 +313,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Directly navigate to the flexible layout @@ -326,7 +352,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Check styles on StackedPlot2 matches previous set colors @@ -334,7 +362,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot2 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot2 Frame' }) + .getByLabel('Stacked Plot Style Target') ); }); @@ -356,7 +386,7 @@ test.describe('Flexible Layout styling', () => { setBorderColor, setBackgroundColor, setTextColor, - page.getByLabel('StackedPlot1 Frame') + page.getByRole('group', { name: 'StackedPlot1 Frame' }) ); // Check styles using checkStyles function @@ -364,7 +394,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(setBorderColor), hexToRGB(setBackgroundColor), hexToRGB(setTextColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Save Flexible Layout @@ -386,7 +418,7 @@ test.describe('Flexible Layout styling', () => { 'No Style', 'No Style', 'No Style', - page.getByLabel('StackedPlot1 Frame') + page.getByRole('group', { name: 'StackedPlot1 Frame' }) ); // Check styles using checkStyles function @@ -394,7 +426,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(inheritedColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); // Save Flexible Layout await page.getByRole('button', { name: 'Save' }).click(); @@ -408,7 +442,9 @@ test.describe('Flexible Layout styling', () => { hexToRGB(defaultBorderTargetColor), NO_STYLE_RGBA, hexToRGB(inheritedColor), - page.getByLabel('StackedPlot1 Frame').getByLabel('Stacked Plot Style Target') + page + .getByRole('group', { name: 'StackedPlot1 Frame' }) + .getByLabel('Stacked Plot Style Target') ); }); diff --git a/e2e/tests/functional/plugins/styling/styleInspectorOptions.e2e.spec.js b/e2e/tests/functional/plugins/styling/styleInspectorOptions.e2e.spec.js index 1898d8bad8..b64cf9b3c9 100644 --- a/e2e/tests/functional/plugins/styling/styleInspectorOptions.e2e.spec.js +++ b/e2e/tests/functional/plugins/styling/styleInspectorOptions.e2e.spec.js @@ -67,7 +67,7 @@ test.describe('Style Inspector Options', () => { await expect(page.getByRole('tab', { name: 'Styles' })).toBeVisible(); // Select Stacked Layout Column - await page.getByLabel('Stacked Plot Frame').click(); + await page.getByRole('group', { name: 'Stacked Plot Frame' }).click(); // The overall Flex Layout or Stacked Plot itself MUST be style-able. await expect(page.getByRole('tab', { name: 'Styles' })).toBeVisible(); diff --git a/e2e/tests/performance/contract/imagery.contract.perf.spec.js b/e2e/tests/performance/contract/imagery.contract.perf.spec.js index c87e6df5ea..1608b7956c 100644 --- a/e2e/tests/performance/contract/imagery.contract.perf.spec.js +++ b/e2e/tests/performance/contract/imagery.contract.perf.spec.js @@ -178,7 +178,7 @@ test.describe('Performance tests', () => { console.log('jpgResourceTiming ' + JSON.stringify(jpgResourceTiming)); // Click Close Icon - await page.locator('[aria-label="Close"]').click(); + await page.getByRole('button', { name: 'Close' }).click(); await page.evaluate(() => window.performance.mark('view-large-close-button')); //await client.send('HeapProfiler.enable'); diff --git a/e2e/tests/visual-a11y/components/header.visual.spec.js b/e2e/tests/visual-a11y/components/header.visual.spec.js index a42e7cea8d..f9af410dcd 100644 --- a/e2e/tests/visual-a11y/components/header.visual.spec.js +++ b/e2e/tests/visual-a11y/components/header.visual.spec.js @@ -69,14 +69,14 @@ test.describe('Visual - Header @a11y', () => { }); test('show snapshot button', async ({ page, theme }) => { - await page.getByLabel('Take a Notebook Snapshot').click(); + await page.getByLabel('Open the Notebook Snapshot Menu').click(); await page.getByRole('menuitem', { name: 'Save to Notebook Snapshots' }).click(); await percySnapshot(page, `Notebook Snapshot Show button (theme: '${theme}')`, { scope: header }); - await expect(await page.getByLabel('Show Snapshots')).toBeVisible(); + await expect(page.getByLabel('Show Snapshots')).toBeVisible(); }); }); diff --git a/e2e/tests/visual-a11y/styling.visual.spec.js b/e2e/tests/visual-a11y/styling.visual.spec.js index eccaef12e4..d8edc3b165 100644 --- a/e2e/tests/visual-a11y/styling.visual.spec.js +++ b/e2e/tests/visual-a11y/styling.visual.spec.js @@ -91,7 +91,7 @@ test.describe('Flexible Layout styling @a11y', () => { setBorderColor, setBackgroundColor, setTextColor, - page.getByLabel('StackedPlot1 Frame') + page.getByRole('group', { name: 'StackedPlot1 Frame' }) ); await percySnapshot( diff --git a/e2e/tests/visual-a11y/telemetryViews.visual.spec.js b/e2e/tests/visual-a11y/telemetryViews.visual.spec.js index 3e382c0b0b..acb6262804 100644 --- a/e2e/tests/visual-a11y/telemetryViews.visual.spec.js +++ b/e2e/tests/visual-a11y/telemetryViews.visual.spec.js @@ -53,11 +53,11 @@ test.describe('Visual - Telemetry Views', () => { await page.goto(telemetry.url, { waitUntil: 'domcontentloaded' }); //Click this button to see telemetry display options - await page.getByRole('button', { name: 'Plot' }).click(); + await page.getByLabel('Open the View Switcher Menu').click(); await page.getByLabel('Telemetry Table').click(); //Get Table View in place - expect(await page.getByLabel('Expand Columns')).toBeInViewport(); + await expect(page.getByLabel('Expand Columns')).toBeInViewport(); await percySnapshot(page, `Default Telemetry Table View (theme: ${theme})`); diff --git a/example/dataVisualization/components/ExampleDataVisualizationSource.vue b/example/dataVisualization/components/ExampleDataVisualizationSource.vue index b4856b60fe..7bb79497a6 100644 --- a/example/dataVisualization/components/ExampleDataVisualizationSource.vue +++ b/example/dataVisualization/components/ExampleDataVisualizationSource.vue @@ -55,6 +55,7 @@ diff --git a/src/api/menu/components/SuperMenu.vue b/src/api/menu/components/SuperMenu.vue index 1bbdaf940e..cd8d72f7be 100644 --- a/src/api/menu/components/SuperMenu.vue +++ b/src/api/menu/components/SuperMenu.vue @@ -38,8 +38,8 @@ :key="action.name" role="menuitem" :aria-disabled="action.isDisabled" + aria-describedby="item-description" :class="action.cssClass" - :title="action.description" @click="action.onItemClicked" @mouseover="toggleItemDescription(action)" @mouseleave="toggleItemDescription()" @@ -64,7 +64,7 @@ role="menuitem" :class="action.cssClass" :aria-label="action.name" - :title="action.description" + aria-describedby="item-description" @click="action.onItemClicked" @mouseover="toggleItemDescription(action)" @mouseleave="toggleItemDescription()" @@ -74,13 +74,13 @@
  • No actions defined.
  • -
    -
    +
    +
    - {{ hoveredItem.name }} + {{ hoveredItemName }}
    -
    - {{ hoveredItem.description }} +
    + {{ hoveredItemDescription }}
    @@ -90,26 +90,39 @@ import popupMenuMixin from '../mixins/popupMenuMixin.js'; export default { mixins: [popupMenuMixin], inject: ['options'], - data: function () { + data() { return { - hoveredItem: {} + hoveredItem: null }; }, computed: { optionsLabel() { const label = this.options.label ? `${this.options.label} Super Menu` : 'Super Menu'; return label; + }, + itemDescriptionIconClass() { + const iconClass = ['l-item-description__icon']; + if (this.hoveredItem) { + iconClass.push('bg-' + this.hoveredItem.cssClass); + } + return iconClass; + }, + hoveredItemName() { + return this.hoveredItem?.name ?? ''; + }, + hoveredItemDescription() { + return this.hoveredItem?.description ?? ''; } }, methods: { - toggleItemDescription(action = {}) { + toggleItemDescription(action = null) { const hoveredItem = { - name: action.name, - description: action.description, - cssClass: action.cssClass + name: action?.name, + description: action?.description, + cssClass: action?.cssClass }; - this.hoveredItem = Object.assign({}, this.hoveredItem, hoveredItem); + this.hoveredItem = hoveredItem; } } }; diff --git a/src/plugins/LADTable/components/LadRow.vue b/src/plugins/LADTable/components/LadRow.vue index ea7e525435..2adf23743d 100644 --- a/src/plugins/LADTable/components/LadRow.vue +++ b/src/plugins/LADTable/components/LadRow.vue @@ -58,7 +58,7 @@ const CONTEXT_MENU_ACTIONS = ['viewDatumAction', 'viewHistoricalData', 'remove']; const BLANK_VALUE = '---'; -import identifierToString from '/src/tools/url.js'; +import { objectPathToUrl } from '/src/tools/url.js'; import PreviewAction from '@/ui/preview/PreviewAction.js'; import tooltipHelpers from '../../../api/tooltips/tooltipMixins.js'; @@ -260,7 +260,7 @@ export default { event.preventDefault(); this.preview(this.objectPath); } else { - const resultUrl = identifierToString(this.openmct, this.objectPath); + const resultUrl = objectPathToUrl(this.openmct, this.objectPath); this.openmct.router.navigate(resultUrl); } }, diff --git a/src/plugins/clock/components/ClockIndicator.vue b/src/plugins/clock/components/ClockIndicator.vue index 2342679da3..8521934b5c 100644 --- a/src/plugins/clock/components/ClockIndicator.vue +++ b/src/plugins/clock/components/ClockIndicator.vue @@ -25,6 +25,7 @@ aria-label="Clock Indicator" class="c-indicator t-indicator-clock icon-clock no-minify c-indicator--not-clickable" role="complementary" + aria-live="off" > {{ timeTextValue }} diff --git a/src/plugins/inspectorDataVisualization/NumericDataInspectorView.vue b/src/plugins/inspectorDataVisualization/NumericDataInspectorView.vue index 049e5fbb6a..92a43eb1f6 100644 --- a/src/plugins/inspectorDataVisualization/NumericDataInspectorView.vue +++ b/src/plugins/inspectorDataVisualization/NumericDataInspectorView.vue @@ -25,7 +25,18 @@
    Numeric Data
    -
    +
    + + + +
    {{ noNumericDataText }} @@ -33,13 +44,15 @@