diff --git a/e2e/playwright-mobile.config.js b/e2e/playwright-mobile.config.js index 387b29eaca..a7cbf2b685 100644 --- a/e2e/playwright-mobile.config.js +++ b/e2e/playwright-mobile.config.js @@ -3,7 +3,6 @@ import { devices } from '@playwright/test'; const MAX_FAILURES = 5; -const NUM_WORKERS = 2; import { fileURLToPath } from 'url'; @@ -20,7 +19,8 @@ const config = { reuseExistingServer: true //This was originally disabled to prevent differences in local debugging vs. CI. However, it significantly speeds up local debugging. }, maxFailures: MAX_FAILURES, //Limits failures to 5 to reduce CI Waste - workers: NUM_WORKERS, //Limit to 2 for CircleCI Agent + workers: 1, //Limit to 1 due to resource constraints similar to https://github.com/percy/cli/discussions/1067 + use: { baseURL: 'http://localhost:8080/', headless: true, diff --git a/e2e/tests/mobile/smoke.e2e.spec.js b/e2e/tests/mobile/smoke.e2e.spec.js index 01bce7fb6b..d787b5c987 100644 --- a/e2e/tests/mobile/smoke.e2e.spec.js +++ b/e2e/tests/mobile/smoke.e2e.spec.js @@ -34,20 +34,16 @@ Make no assumptions about the order that elements appear in the DOM. */ import { expect, test } from '../../pluginFixtures.js'; - test('Verify that My Items Tree appears @mobile', async ({ page, openmctConfig }) => { const { myItemsFolderName } = openmctConfig; //Go to baseURL await page.goto('./'); - //My Items to be visible await expect(page.getByRole('treeitem', { name: `${myItemsFolderName}` })).toBeVisible(); }); - test('Verify that user can search @mobile', async ({ page }) => { //For now, this test is going to be hardcoded against './test-data/display_layout_with_child_layouts.json' await page.goto('./'); - await page.getByRole('searchbox', { name: 'Search Input' }).click(); await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout'); //Search Results appear in search modal @@ -57,3 +53,23 @@ test('Verify that user can search @mobile', async ({ page }) => { await page.getByTitle('Collapse Browse Pane').click(); await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible(); }); +test('Remove Object and confirmation dialog @mobile', async ({ page }) => { + await page.goto('./'); + await page.getByRole('searchbox', { name: 'Search Input' }).click(); + await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout'); + //Search Results appear in search modal + //Clicking on the search result takes you to the object + await page.getByLabel('Object Results').getByText('Parent Display Layout').click(); + await page.getByTitle('Collapse Browse Pane').click(); + await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible(); + //Verify both objects are in view + await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible(); + await expect(await page.getByLabel('Child Layout 2 Layout')).toBeVisible(); + //Remove First Object to bring up confirmation dialog + await page.getByLabel('View menu items').nth(1).click(); + await page.getByLabel('Remove').click(); + await page.getByRole('button', { name: 'OK' }).click(); + //Verify that the object is removed + await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible(); + expect(await page.getByLabel('Child Layout 2 Layout').count()).toBe(0); +}); diff --git a/src/api/overlays/components/OverlayComponent.vue b/src/api/overlays/components/OverlayComponent.vue index c59d5d9471..9c2dd0736e 100644 --- a/src/api/overlays/components/OverlayComponent.vue +++ b/src/api/overlays/components/OverlayComponent.vue @@ -29,27 +29,29 @@ class="c-click-icon c-overlay__close-button icon-x" @click.stop="destroy" > - -
- + aria-modal="true" + aria-label="Overlay" + role="dialog" + >
+
+ +
diff --git a/src/api/overlays/components/dialog-component.scss b/src/api/overlays/components/dialog-component.scss index 92edae42ac..08b41d8cac 100644 --- a/src/api/overlays/components/dialog-component.scss +++ b/src/api/overlays/components/dialog-component.scss @@ -15,7 +15,7 @@ &__icon { // Holds a background SVG graphic - $s: 80px; + $s: 50px; flex: 0 0 auto; min-width: $s; min-height: $s; diff --git a/src/api/overlays/components/overlay-component.scss b/src/api/overlays/components/overlay-component.scss index be0a22b7c6..1ed0fd7ee1 100644 --- a/src/api/overlays/components/overlay-component.scss +++ b/src/api/overlays/components/overlay-component.scss @@ -19,7 +19,9 @@ z-index: 70; &__blocker { - display: none; // Mobile-first + // Mobile-first: use the blocker to create a full look to dialogs + @include abs(); + background: $colorBodyBg; } &__outer { @@ -27,7 +29,13 @@ background: $colorBodyBg; display: flex; flex-direction: column; - padding: $overlayInnerMargin; + + body.mobile .l-overlay-fit & { + // Vertically center small dialogs in mobile + top: 50%; + bottom: auto; + transform: translateY(-50%); + } } &__close-button { @@ -39,12 +47,32 @@ z-index: 99; } + &__content-wrapper { + display: flex; + height: 100%; + overflow: auto; + flex-direction: column; + gap: $interiorMargin; + + body.desktop & { + overflow: hidden; + } + + .l-overlay-fit &, + .l-overlay-dialog & { + margin: $overlayInnerMargin; + } + } + &__contents { flex: 1 1 auto; display: flex; flex-direction: column; outline: none; overflow: auto; + body.mobile & { + flex: none; + } } &__top-bar { @@ -78,6 +106,10 @@ display: flex; justify-content: flex-end; margin-top: $interiorMargin; + body.mobile & { + justify-content: flex-end; + padding-right: $interiorMargin; + } > * + * { margin-left: $interiorMargin;