From 172965861842f14ccfbb187145f81ef84bb48eda Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Tue, 16 Jan 2024 17:33:13 -0800 Subject: [PATCH 01/19] Add status area back to mobile --- src/ui/layout/layout.scss | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ui/layout/layout.scss b/src/ui/layout/layout.scss index 19694152ded..f90ce231be0 100644 --- a/src/ui/layout/layout.scss +++ b/src/ui/layout/layout.scss @@ -171,7 +171,7 @@ } } - &__head, + //&__head, &__pane-inspector { body.mobile & { display: none; @@ -189,6 +189,14 @@ margin-bottom: $interiorMargin; // Needs some additional visual separation } + &__head{ + body.mobile & { + .c-create-button, .c-create-menu, .c-indicator, .c-icon-button { // Making status area visible, but hiding some widgets for mobile. + display: none; + } + } + } + body.mobile & .l-shell__main-view-browse-bar { margin-left: $mobileMenuIconD; // Make room for the hamburger! .c-button[class*='__actions__edit'] { From cde5f1528df6b7b2a2dce99484d3d6c8e031f36b Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Tue, 16 Jan 2024 18:16:31 -0800 Subject: [PATCH 02/19] Make search results responsive to width --- src/ui/layout/search/search.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ui/layout/search/search.scss b/src/ui/layout/search/search.scss index 362b12cc2fe..f8ec187070e 100644 --- a/src/ui/layout/search/search.scss +++ b/src/ui/layout/search/search.scss @@ -40,6 +40,10 @@ max-height: 500px; top: $formInputH; z-index: 60; + body.mobile & { + min-width: 90vw; + max-height: 90vh; + } } &__results, @@ -72,6 +76,10 @@ margin-top: $interiorMargin; } } + + body.mobile & { + width: auto; + } } .c-gsearch-result { @@ -142,4 +150,5 @@ .c-tag { font-size: 0.9em; } + } From 195f7d9b9b5b3b592778a2b8d9f9e2aeae5f5194 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Thu, 18 Jan 2024 17:17:34 -0800 Subject: [PATCH 03/19] Make clear search button always visible, regardless of hover --- src/ui/components/search.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/components/search.scss b/src/ui/components/search.scss index 96f01763867..ba46cf73e6b 100644 --- a/src/ui/components/search.scss +++ b/src/ui/components/search.scss @@ -47,6 +47,10 @@ display: none; order: 99; padding: 1px 0; + body.mobile & { + display: block; + } + } &.is-active { From 52156220481c3396280b4d7cd6983e49edef7bde Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Thu, 18 Jan 2024 17:29:53 -0800 Subject: [PATCH 04/19] Make clear search button visible, and fix weird margin in top left corner --- src/ui/layout/layout.scss | 33 ++++++++++++++++++++++++++------ src/ui/layout/search/search.scss | 4 ++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/ui/layout/layout.scss b/src/ui/layout/layout.scss index f90ce231be0..9aa7c8008fd 100644 --- a/src/ui/layout/layout.scss +++ b/src/ui/layout/layout.scss @@ -189,9 +189,13 @@ margin-bottom: $interiorMargin; // Needs some additional visual separation } - &__head{ + &__head { body.mobile & { - .c-create-button, .c-create-menu, .c-indicator, .c-icon-button { // Making status area visible, but hiding some widgets for mobile. + .c-create-button, + .c-create-menu, + .c-indicator, + .c-icon-button { + // Making status area visible, but hiding some widgets for mobile. display: none; } } @@ -249,7 +253,21 @@ border-left: $brdr; align-items: start; $p: $interiorMarginSm; - padding-left: $p; padding-right: $p; + padding-left: $p; + padding-right: $p; + } + + &__create-button, + &__app-logo { + flex: 0 0 auto; + } + + &__create-button { + margin-right: $interiorMarginLg; + body.mobile & { + // Fixes weird gap in mobile status area + margin-right: 0px; + } } &__indicators { @@ -262,7 +280,6 @@ height: 24px; overflow: hidden; } - } /******************************* MAIN AREA */ @@ -363,14 +380,18 @@ .is-editing { .l-shell__main-container { $m: 3px; - box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdw; + box-shadow: + $colorBodyBg 0 0 0 1px, + $editUIAreaShdw; margin-left: $m; margin-right: $m; top: $shellToolBarH + $shellMainBrowseBarH + $interiorMarginLg !important; &[s-selected] { // Provide a clearer selection context articulation for the main edit area - box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdwSelected; + box-shadow: + $colorBodyBg 0 0 0 1px, + $editUIAreaShdwSelected; } } } diff --git a/src/ui/layout/search/search.scss b/src/ui/layout/search/search.scss index f8ec187070e..3de5176bd53 100644 --- a/src/ui/layout/search/search.scss +++ b/src/ui/layout/search/search.scss @@ -41,8 +41,8 @@ top: $formInputH; z-index: 60; body.mobile & { - min-width: 90vw; - max-height: 90vh; + min-width: 95vw; + max-height: 95vh; } } From c3edfc052c1ea61e75b195628d3583440e7c8b55 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Mon, 22 Jan 2024 14:59:48 -0800 Subject: [PATCH 05/19] Fix input width, add logic to make close button work properly, fix margin on results so there is room for close button, fix various landscape mode issues --- .../layout/search/SearchResultsDropDown.vue | 5 +++ src/ui/layout/search/search.scss | 32 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/ui/layout/search/SearchResultsDropDown.vue b/src/ui/layout/search/SearchResultsDropDown.vue index a7943a2eb9a..5ff1b39834a 100644 --- a/src/ui/layout/search/SearchResultsDropDown.vue +++ b/src/ui/layout/search/SearchResultsDropDown.vue @@ -27,6 +27,11 @@ aria-label="Search Results Dropdown" class="c-gsearch__dropdown" > +
* + * { margin-top: $interiorMarginLg; } + body.mobile & { + // Add a margin to results so we have room for the close button + width: 93%; + } } &__results-section { @@ -69,6 +83,7 @@ &__results-section-title { @include propertiesHeader(); + width: 95%; } &__result-pane-msg { @@ -77,8 +92,20 @@ } } + &__results-close { + // Close button that appears for mobile only + display: none; + body.mobile & { + display: block; + } + } + body.mobile & { - width: auto; + width: 50%; + @include phonePortrait() { + // This logic only appears for a mobile portrait mode + width: 100%; + } } } @@ -150,5 +177,4 @@ .c-tag { font-size: 0.9em; } - } From 1988567e6c4e769c529bedf159086f278ffbf7bf Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 14 Feb 2024 16:20:47 -0800 Subject: [PATCH 06/19] update mobile testing --- .circleci/config.yml | 53 ++++++++++++++----- e2e/README.md | 12 +++-- e2e/playwright-local.config.js | 18 +------ e2e/playwright-mobile.config.js | 70 ++++++++++++++++++++++++++ e2e/tests/functional/smoke.e2e.spec.js | 2 +- e2e/tests/mobile/smoke.e2e.spec.js | 59 ++++++++++++++++++++++ package.json | 1 + 7 files changed, 183 insertions(+), 32 deletions(-) create mode 100644 e2e/playwright-mobile.config.js create mode 100644 e2e/tests/mobile/smoke.e2e.spec.js diff --git a/.circleci/config.yml b/.circleci/config.yml index edb7bb1c496..9ee063eeb75 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,20 +5,20 @@ executors: - image: mcr.microsoft.com/playwright:v1.39.0-focal environment: NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed - PERCY_POSTINSTALL_BROWSER: "true" # Needed to store the percy browser in cache deps - PERCY_LOGLEVEL: "debug" # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742) + PERCY_POSTINSTALL_BROWSER: 'true' # Needed to store the percy browser in cache deps + PERCY_LOGLEVEL: 'debug' # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742) ubuntu: machine: image: ubuntu-2204:current docker_layer_caching: true parameters: BUST_CACHE: - description: "Set this with the CircleCI UI Trigger Workflow button (boolean = true) to bust the cache!" + description: 'Set this with the CircleCI UI Trigger Workflow button (boolean = true) to bust the cache!' default: false type: boolean commands: build_and_install: - description: "All steps used to build and install. Will use cache if found" + description: 'All steps used to build and install. Will use cache if found' parameters: node-version: type: string @@ -30,7 +30,7 @@ commands: node-version: << parameters.node-version >> - run: npm install --no-audit --progress=false restore_cache_cmd: - description: "Custom command for restoring cache with the ability to bust cache. When BUST_CACHE is set to true, jobs will not restore cache" + description: 'Custom command for restoring cache with the ability to bust cache. When BUST_CACHE is set to true, jobs will not restore cache' parameters: node-version: type: string @@ -42,7 +42,7 @@ commands: - restore_cache: key: deps--{{ arch }}--{{ .Branch }}--<< parameters.node-version >>--{{ checksum "package.json" }}-{{ checksum ".circleci/config.yml" }} save_cache_cmd: - description: "Custom command for saving cache." + description: 'Custom command for saving cache.' parameters: node-version: type: string @@ -53,7 +53,7 @@ commands: - ~/.npm - node_modules generate_and_store_version_and_filesystem_artifacts: - description: "Track important packages and files" + description: 'Track important packages and files' steps: - run: | [[ $EUID -ne 0 ]] && (sudo mkdir -p /tmp/artifacts && sudo chmod 777 /tmp/artifacts) || (mkdir -p /tmp/artifacts && chmod 777 /tmp/artifacts) @@ -64,7 +64,7 @@ commands: - store_artifacts: path: /tmp/artifacts/ generate_e2e_code_cov_report: - description: "Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test" + description: 'Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test' parameters: suite: type: string @@ -133,7 +133,7 @@ jobs: node-version: lts/hydrogen - when: #Only install chrome-beta when running the 'full' suite to save $$$ condition: - equal: ["full", <>] + equal: ['full', <>] steps: - run: npx playwright install chrome-beta - run: @@ -160,6 +160,31 @@ jobs: equal: [42, 42] # Always generate version artifacts regardless of test failure https://discuss.circleci.com/t/make-custom-command-run-always-with-when-always/38957/2 steps: - generate_and_store_version_and_filesystem_artifacts + e2e-mobile: + executor: pw-focal-development + steps: + - build_and_install: + node-version: lts/hydrogen + - run: npm run test:e2e:mobile + - when: + condition: + equal: [42, 42] # Always run codecov reports regardless of test failure https://discuss.circleci.com/t/make-custom-command-run-always-with-when-always/38957/2 + steps: + - generate_e2e_code_cov_report: + suite: full + - store_test_results: + path: test-results/results.xml + - store_artifacts: + path: test-results + - store_artifacts: + path: coverage + - store_artifacts: + path: html-test-results + - when: + condition: + equal: [42, 42] # Always generate version artifacts regardless of test failure https://discuss.circleci.com/t/make-custom-command-run-always-with-when-always/38957/2 + steps: + - generate_and_store_version_and_filesystem_artifacts e2e-couchdb: executor: ubuntu steps: @@ -260,8 +285,11 @@ workflows: - e2e-test: name: e2e-stable suite: stable + - e2e-mobile + - mem-test + - perf-test - visual-a11y-tests: - name: visual-test-ci + name: visual-a11y-test-ci suite: ci the-nightly: #These jobs do not run on PRs, but against master at night @@ -277,15 +305,16 @@ workflows: - e2e-test: name: e2e-full-nightly suite: full + - e2e-mobile - mem-test - perf-test - visual-a11y-tests: - name: visual-test-nightly + name: visual-a11y-test-nightly suite: full - e2e-couchdb triggers: - schedule: - cron: "0 0 * * *" + cron: '0 0 * * *' filters: branches: only: diff --git a/e2e/README.md b/e2e/README.md index 83840a612e2..ee0debe9dd6 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -229,7 +229,7 @@ Current list of test tags: |Test Tag|Description| |:-:|-| -|`@ipad` | Test case or test suite is compatible with Playwright's iPad support and Open MCT's read-only mobile view (i.e. no create button).| +|`@mobile` | Test case or test suite is compatible with Playwright's iPad support and Open MCT's read-only mobile view (i.e. no create button).| |`@a11y` | Test case or test suite to execute playwright-axe accessibility checks and generate a11y reports.| |`@gds` | Denotes a GDS Test Case used in the VIPER Mission.| |`@addInit` | Initializes the browser with an injected and artificial state. Useful for loading non-default plugins. Likely will not work outside of `npm start`.| @@ -329,9 +329,15 @@ In terms of operating system testing, we're only limited by what the CI provider #### **Mobile** -We have the Mission-need to support iPad. To run our iPad suite, please see our `playwright-*.config.js` with the 'iPad' project. +We have a Mission-need to support iPad and mobile devices. To run our test suites with mobile devices, please see our `playwright-mobile.config.js` projects. -In general, our test suite is not designed to run against mobile devices as the mobile experience is a focused version of the application. Core functionality is missing (chiefly the 'Create' button) and so this will likely turn into a separate suite. +In general, our test suite is not designed to run against mobile devices as the mobile experience is a focused version of the application. Core functionality is missing (chiefly the 'Create' button). To bypass the object creation, we leverage the `storageState` properties for starting the mobile tests with localstorage. + +For now, the mobile tests will exist in the /tests/mobile/ suites and be executed with the +```sh +npm run test:e2e:mobile +``` +command. #### **Skipping or executing tests based on browser, os, and/os browser version:** diff --git a/e2e/playwright-local.config.js b/e2e/playwright-local.config.js index c90dd174965..13b4157a8f8 100644 --- a/e2e/playwright-local.config.js +++ b/e2e/playwright-local.config.js @@ -3,11 +3,13 @@ // eslint-disable-next-line no-unused-vars import { devices } from '@playwright/test'; +import path from 'path'; /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { retries: 0, testDir: 'tests', + testMatch: '**/*.e2e.spec.js', // only run e2e tests testIgnore: '**/*.perf.spec.js', timeout: 30 * 1000, webServer: { @@ -35,7 +37,6 @@ const config = { }, { name: 'MMOC', - testMatch: '**/*.e2e.spec.js', // only run e2e tests grepInvert: /@snapshot/, use: { browserName: 'chromium', @@ -47,8 +48,6 @@ const config = { }, { name: 'safari', - testMatch: '**/*.e2e.spec.js', // only run e2e tests - grep: /@ipad/, // only run ipad tests due to this bug https://github.com/microsoft/playwright/issues/8340 grepInvert: /@snapshot/, use: { browserName: 'webkit' @@ -56,7 +55,6 @@ const config = { }, { name: 'firefox', - testMatch: '**/*.e2e.spec.js', // only run e2e tests grepInvert: /@snapshot/, use: { browserName: 'firefox' @@ -64,7 +62,6 @@ const config = { }, { name: 'canary', - testMatch: '**/*.e2e.spec.js', // only run e2e tests grepInvert: /@snapshot/, use: { browserName: 'chromium', @@ -73,22 +70,11 @@ const config = { }, { name: 'chrome-beta', - testMatch: '**/*.e2e.spec.js', // only run e2e tests grepInvert: /@snapshot/, use: { browserName: 'chromium', channel: 'chrome-beta' } - }, - { - name: 'ipad', - testMatch: '**/*.e2e.spec.js', // only run e2e tests - grep: /@ipad/, - grepInvert: /@snapshot/, - use: { - browserName: 'webkit', - ...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json - } } ], reporter: [ diff --git a/e2e/playwright-mobile.config.js b/e2e/playwright-mobile.config.js new file mode 100644 index 00000000000..b66c4d24ef7 --- /dev/null +++ b/e2e/playwright-mobile.config.js @@ -0,0 +1,70 @@ +// playwright.config.js +// @ts-check + +// eslint-disable-next-line no-unused-vars +import { devices } from '@playwright/test'; +const MAX_FAILURES = 5; +const NUM_WORKERS = 2; + +import { fileURLToPath } from 'url'; + +/** @type {import('@playwright/test').PlaywrightTestConfig} */ +const config = { + retries: 1, //Retries 2 times for a total of 3 runs. When running sharded and with max-failures=5, this should ensure that flake is managed without failing the full suite + testDir: 'tests', + testIgnore: '**/*.perf.spec.js', //Ignore performance tests and define in playwright-perfromance.config.js + timeout: 30 * 1000, + webServer: { + command: 'npm run start:coverage', + url: 'http://localhost:8080/#', + timeout: 200 * 1000, + 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 + use: { + baseURL: 'http://localhost:8080/', + headless: true, + ignoreHTTPSErrors: true, + screenshot: 'only-on-failure', + trace: 'on-first-retry', + video: 'off' + }, + projects: [ + { + name: 'ipad', + grep: /@mobile/, + use: { + storageState: fileURLToPath( + new URL('./test-data/display_layout_with_child_layouts.json', import.meta.url) + ), + browserName: 'webkit', + ...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json + } + }, + { + name: 'iphone', + grep: /@mobile/, + use: { + storageState: fileURLToPath( + new URL('./test-data/display_layout_with_child_layouts.json', import.meta.url) + ), + browserName: 'webkit', + ...devices['iPhone 14 Pro'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json + } + } + ], + reporter: [ + ['list'], + [ + 'html', + { + open: 'never', + outputFolder: '../html-test-results' //Must be in different location due to https://github.com/microsoft/playwright/issues/12840 + } + ], + ['junit', { outputFile: '../test-results/results.xml' }] + ] +}; + +export default config; diff --git a/e2e/tests/functional/smoke.e2e.spec.js b/e2e/tests/functional/smoke.e2e.spec.js index a113c05afc6..316edba50ee 100644 --- a/e2e/tests/functional/smoke.e2e.spec.js +++ b/e2e/tests/functional/smoke.e2e.spec.js @@ -48,7 +48,7 @@ test('Verify that the create button appears and that the Folder Domain Object is await expect(page.locator(':nth-match(:text("Folder"), 2)')).toBeEnabled(); }); -test('Verify that My Items Tree appears @ipad', async ({ page, openmctConfig }) => { +test('Verify that My Items Tree appears', async ({ page, openmctConfig }) => { const { myItemsFolderName } = openmctConfig; //Go to baseURL await page.goto('./'); diff --git a/e2e/tests/mobile/smoke.e2e.spec.js b/e2e/tests/mobile/smoke.e2e.spec.js new file mode 100644 index 00000000000..01bce7fb6b6 --- /dev/null +++ b/e2e/tests/mobile/smoke.e2e.spec.js @@ -0,0 +1,59 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2024, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/* +This test suite is dedicated to tests which can quickly verify that any openmct installation is +operable and that any type of testing can proceed. + +Ideally, smoke tests should make zero assumptions about how and where they are run. This makes them +more resilient to change and therefor a better indicator of failure. Smoke tests will also run quickly +as they cover a very "thin surface" of functionality. + +When deciding between authoring new smoke tests or functional tests, ask yourself "would I feel +comfortable running this test during a live mission?" Avoid creating or deleting Domain Objects. +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 + await expect(page.getByLabel('Object Results').getByText('Parent Display Layout')).toBeVisible(); + //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(); +}); diff --git a/package.json b/package.json index a30fa9288f1..503bc03576d 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "test:debug": "KARMA_DEBUG=true karma start karma.conf.cjs", "test:e2e": "npx playwright test", "test:e2e:a11y": "npx playwright test --config=e2e/playwright-visual-a11y.config.js --project=chrome --grep @a11y", + "test:e2e:mobile": "npx playwright test --config=e2e/playwright-mobile.config.js", "test:e2e:couchdb": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome --grep @couchdb --workers=1", "test:e2e:stable": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome --grep-invert \"@unstable|@couchdb|@generatedata\"", "test:e2e:unstable": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome --grep @unstable", From 7d00f77c703c3c47e09b5922d3d63e5e3bf8fe9c Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Mon, 12 Feb 2024 15:38:14 -0800 Subject: [PATCH 07/19] Fix dropdown sizes, remove shadows and corners to make it look less like a popup and more full screen --- src/ui/layout/search/search.scss | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ui/layout/search/search.scss b/src/ui/layout/search/search.scss index 7e8b90d7f5a..4209e5560e8 100644 --- a/src/ui/layout/search/search.scss +++ b/src/ui/layout/search/search.scss @@ -50,9 +50,15 @@ max-height: 500px; top: $formInputH; z-index: 60; - body.mobile & { - min-width: 95vw; - min-height: 95vh; + body.mobile & { // Makes search in mobile look less like an overlay, and more fullscreen. + position: absolute; + top: 25px; + left: -12px; + height: calc(100vh - 22px); + min-width: 100vw; + max-height: none; + border-radius: 0px; + box-shadow: none; } } From 2636785af03983aaeb5d7803e578d28cdc782556 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Tue, 6 Feb 2024 15:49:08 -0800 Subject: [PATCH 08/19] Add animation and persist search bar in mobile --- src/ui/components/search.scss | 10 ++++++++++ src/ui/layout/search/search.scss | 34 ++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/ui/components/search.scss b/src/ui/components/search.scss index ba46cf73e6b..34b877ad27f 100644 --- a/src/ui/components/search.scss +++ b/src/ui/components/search.scss @@ -12,6 +12,9 @@ &:before { // Mag glass icon content: $glyph-icon-magnify; + body.mobile & { // Make search icon stand out in mobile + opacity: 1; + } } &__use-regex { @@ -54,12 +57,19 @@ } &.is-active { + body.mobile & { // In mobile, persist the expanded search bar instead of collapsing upon clicking away + background-color: rgba($colorHeadFg, 0.2) !important; + width: 50vw !important; + } .c-search__use-regex { margin-left: 0; } &:before { width: 0; + body.mobile & { + width: auto; + } } input[type='text'], diff --git a/src/ui/layout/search/search.scss b/src/ui/layout/search/search.scss index 4209e5560e8..78fd0ee0069 100644 --- a/src/ui/layout/search/search.scss +++ b/src/ui/layout/search/search.scss @@ -28,16 +28,19 @@ background: rgba($colorHeadFg, 0.2); box-shadow: none; flex: 1 1 auto; - // body.mobile & { - // @include phonePortrait() { // This logic of expanding the search input upon click only happens in mobile portrait mode - // background: $colorHeadBg; - // width: 15%; - // &:hover { - // background-color: rgba($colorHeadFg, 0.2); - // width: 100%; - // } - // } - // } + body.mobile & { + @include phonePortrait() { + // This logic of expanding the search input upon click only happens in mobile portrait mode + background: $colorHeadBg; + width: 15%; + &:hover { + // When clicked, expand the search bar + background-color: rgba($colorHeadFg, 0.2); + width: 50vw; + transition: width 120ms; + } + } + } } } @@ -50,7 +53,8 @@ max-height: 500px; top: $formInputH; z-index: 60; - body.mobile & { // Makes search in mobile look less like an overlay, and more fullscreen. + body.mobile & { + // Makes search in mobile look less like an overlay, and more fullscreen. position: absolute; top: 25px; left: -12px; @@ -107,7 +111,7 @@ } body.mobile & { - width: 50%; + width: 50vw; @include phonePortrait() { // This logic only appears for a mobile portrait mode width: 100%; @@ -154,9 +158,9 @@ } .c-location { - //color: $colorBodyFg; - //font-size: 0.9em; - //opacity: 0.8; + color: $colorBodyFg; + font-size: 0.9em; + opacity: 0.8; } } From f1d88d61a973ef6e6f69f55542263ae2e53e6aa3 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Thu, 15 Feb 2024 13:01:55 -0800 Subject: [PATCH 09/19] Fix linting issues --- .../src/DeviceMatchersSpec.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js b/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js index 3cd676ac661..00c3e722d45 100644 --- a/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js +++ b/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js @@ -46,14 +46,14 @@ describe('DeviceMatchers', function () { return 'is' + deviceType[0].toUpperCase() + deviceType.slice(1); } - ['mobile', 'phone', 'tablet', 'landscape', 'portrait', 'landscape', 'touch'].forEach( - function (deviceType) { - it('detects when a device is a ' + deviceType + ' device', function () { - mockAgent[method(deviceType)].and.returnValue(true); - expect(DeviceMatchers[deviceType](mockAgent)).toBe(true); - mockAgent[method(deviceType)].and.returnValue(false); - expect(DeviceMatchers[deviceType](mockAgent)).toBe(false); - }); - } - ); + ['mobile', 'phone', 'tablet', 'landscape', 'portrait', 'landscape', 'touch'].forEach(function ( + deviceType + ) { + it('detects when a device is a ' + deviceType + ' device', function () { + mockAgent[method(deviceType)].and.returnValue(true); + expect(DeviceMatchers[deviceType](mockAgent)).toBe(true); + mockAgent[method(deviceType)].and.returnValue(false); + expect(DeviceMatchers[deviceType](mockAgent)).toBe(false); + }); + }); }); From 7b765f6182c5d9b7712cd1ba2cc43d6e408ee484 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Tue, 20 Feb 2024 14:01:42 -0800 Subject: [PATCH 10/19] Fix padding in Desktop --- src/ui/layout/layout.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/layout/layout.scss b/src/ui/layout/layout.scss index 9aa7c8008fd..8e1e5cae5ed 100644 --- a/src/ui/layout/layout.scss +++ b/src/ui/layout/layout.scss @@ -263,7 +263,7 @@ } &__create-button { - margin-right: $interiorMarginLg; + // margin-right: $interiorMarginLg; body.mobile & { // Fixes weird gap in mobile status area margin-right: 0px; From 9511b8cd7ad65e8e7e81ea5b32a5dda2cacd97c0 Mon Sep 17 00:00:00 2001 From: Rukmini Bose Date: Tue, 20 Feb 2024 14:03:15 -0800 Subject: [PATCH 11/19] fix padding in status area --- src/ui/layout/layout.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ui/layout/layout.scss b/src/ui/layout/layout.scss index 8e1e5cae5ed..98eb93fc6e4 100644 --- a/src/ui/layout/layout.scss +++ b/src/ui/layout/layout.scss @@ -263,7 +263,6 @@ } &__create-button { - // margin-right: $interiorMarginLg; body.mobile & { // Fixes weird gap in mobile status area margin-right: 0px; From 41c3eb0b9d85bddc9dfcf7ac526c5c3fee10f082 Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 14:30:48 -0800 Subject: [PATCH 12/19] fix bad merge --- .circleci/config.yml | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9ee063eeb75..3860472e784 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,20 +5,20 @@ executors: - image: mcr.microsoft.com/playwright:v1.39.0-focal environment: NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed - PERCY_POSTINSTALL_BROWSER: 'true' # Needed to store the percy browser in cache deps - PERCY_LOGLEVEL: 'debug' # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742) + PERCY_POSTINSTALL_BROWSER: "true" # Needed to store the percy browser in cache deps + PERCY_LOGLEVEL: "debug" # Enable DEBUG level logging for Percy (Issue: https://github.com/nasa/openmct/issues/5742) ubuntu: machine: image: ubuntu-2204:current docker_layer_caching: true parameters: BUST_CACHE: - description: 'Set this with the CircleCI UI Trigger Workflow button (boolean = true) to bust the cache!' + description: "Set this with the CircleCI UI Trigger Workflow button (boolean = true) to bust the cache!" default: false type: boolean commands: build_and_install: - description: 'All steps used to build and install. Will use cache if found' + description: "All steps used to build and install. Will use cache if found" parameters: node-version: type: string @@ -30,7 +30,7 @@ commands: node-version: << parameters.node-version >> - run: npm install --no-audit --progress=false restore_cache_cmd: - description: 'Custom command for restoring cache with the ability to bust cache. When BUST_CACHE is set to true, jobs will not restore cache' + description: "Custom command for restoring cache with the ability to bust cache. When BUST_CACHE is set to true, jobs will not restore cache" parameters: node-version: type: string @@ -42,7 +42,7 @@ commands: - restore_cache: key: deps--{{ arch }}--{{ .Branch }}--<< parameters.node-version >>--{{ checksum "package.json" }}-{{ checksum ".circleci/config.yml" }} save_cache_cmd: - description: 'Custom command for saving cache.' + description: "Custom command for saving cache." parameters: node-version: type: string @@ -53,7 +53,7 @@ commands: - ~/.npm - node_modules generate_and_store_version_and_filesystem_artifacts: - description: 'Track important packages and files' + description: "Track important packages and files" steps: - run: | [[ $EUID -ne 0 ]] && (sudo mkdir -p /tmp/artifacts && sudo chmod 777 /tmp/artifacts) || (mkdir -p /tmp/artifacts && chmod 777 /tmp/artifacts) @@ -64,7 +64,7 @@ commands: - store_artifacts: path: /tmp/artifacts/ generate_e2e_code_cov_report: - description: 'Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test' + description: "Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test" parameters: suite: type: string @@ -133,7 +133,7 @@ jobs: node-version: lts/hydrogen - when: #Only install chrome-beta when running the 'full' suite to save $$$ condition: - equal: ['full', <>] + equal: ["full", <>] steps: - run: npx playwright install chrome-beta - run: @@ -306,15 +306,13 @@ workflows: name: e2e-full-nightly suite: full - e2e-mobile - - mem-test - - perf-test - visual-a11y-tests: name: visual-a11y-test-nightly suite: full - e2e-couchdb triggers: - schedule: - cron: '0 0 * * *' + cron: "0 0 * * *" filters: branches: only: From 5cc0dea5818e339cad95e94b1b0285ac8bed2d83 Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 14:30:55 -0800 Subject: [PATCH 13/19] lint fixes --- e2e/playwright-local.config.js | 4 ---- .../src/DeviceMatchersSpec.js | 20 +++++++++---------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/e2e/playwright-local.config.js b/e2e/playwright-local.config.js index 13b4157a8f8..37afca21529 100644 --- a/e2e/playwright-local.config.js +++ b/e2e/playwright-local.config.js @@ -1,10 +1,6 @@ // playwright.config.js // @ts-check -// eslint-disable-next-line no-unused-vars -import { devices } from '@playwright/test'; -import path from 'path'; - /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { retries: 0, diff --git a/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js b/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js index 00c3e722d45..3cd676ac661 100644 --- a/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js +++ b/src/plugins/DeviceClassifier/src/DeviceMatchersSpec.js @@ -46,14 +46,14 @@ describe('DeviceMatchers', function () { return 'is' + deviceType[0].toUpperCase() + deviceType.slice(1); } - ['mobile', 'phone', 'tablet', 'landscape', 'portrait', 'landscape', 'touch'].forEach(function ( - deviceType - ) { - it('detects when a device is a ' + deviceType + ' device', function () { - mockAgent[method(deviceType)].and.returnValue(true); - expect(DeviceMatchers[deviceType](mockAgent)).toBe(true); - mockAgent[method(deviceType)].and.returnValue(false); - expect(DeviceMatchers[deviceType](mockAgent)).toBe(false); - }); - }); + ['mobile', 'phone', 'tablet', 'landscape', 'portrait', 'landscape', 'touch'].forEach( + function (deviceType) { + it('detects when a device is a ' + deviceType + ' device', function () { + mockAgent[method(deviceType)].and.returnValue(true); + expect(DeviceMatchers[deviceType](mockAgent)).toBe(true); + mockAgent[method(deviceType)].and.returnValue(false); + expect(DeviceMatchers[deviceType](mockAgent)).toBe(false); + }); + } + ); }); From bc0ce80db8e14da9e63032a022621f8dc30e9a80 Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 14:39:36 -0800 Subject: [PATCH 14/19] fix bad merge... again --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3860472e784..b2533f34e09 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -286,8 +286,6 @@ workflows: name: e2e-stable suite: stable - e2e-mobile - - mem-test - - perf-test - visual-a11y-tests: name: visual-a11y-test-ci suite: ci From b5f86d6877d862709455b11a1e53b66650cbfcad Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 14:40:24 -0800 Subject: [PATCH 15/19] again --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b2533f34e09..0dcca1d322b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -304,6 +304,8 @@ workflows: name: e2e-full-nightly suite: full - e2e-mobile + - perf-test + - mem-test - visual-a11y-tests: name: visual-a11y-test-nightly suite: full From 65bc38147cf59905c9e5351570160adeecc04e3d Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 15:02:15 -0800 Subject: [PATCH 16/19] fixes to mobile --- e2e/playwright-ci.config.js | 1 + e2e/playwright-mobile.config.js | 1 - e2e/playwright-watch.config.js | 26 ++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/e2e/playwright-ci.config.js b/e2e/playwright-ci.config.js index 8c5c906bd5c..d86fd2507e0 100644 --- a/e2e/playwright-ci.config.js +++ b/e2e/playwright-ci.config.js @@ -10,6 +10,7 @@ const NUM_WORKERS = 2; const config = { retries: 2, //Retries 2 times for a total of 3 runs. When running sharded and with max-failures=5, this should ensure that flake is managed without failing the full suite testDir: 'tests', + grepInvert: /@mobile/, //Ignore mobile tests testIgnore: '**/*.perf.spec.js', //Ignore performance tests and define in playwright-perfromance.config.js timeout: 60 * 1000, webServer: { diff --git a/e2e/playwright-mobile.config.js b/e2e/playwright-mobile.config.js index b66c4d24ef7..387b29eacaf 100644 --- a/e2e/playwright-mobile.config.js +++ b/e2e/playwright-mobile.config.js @@ -1,7 +1,6 @@ // playwright.config.js // @ts-check -// eslint-disable-next-line no-unused-vars import { devices } from '@playwright/test'; const MAX_FAILURES = 5; const NUM_WORKERS = 2; diff --git a/e2e/playwright-watch.config.js b/e2e/playwright-watch.config.js index 1d65e655595..13723724685 100644 --- a/e2e/playwright-watch.config.js +++ b/e2e/playwright-watch.config.js @@ -1,6 +1,10 @@ // playwright.config.js // @ts-check +import { devices } from '@playwright/test'; +import { fileURLToPath } from 'url'; + + /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { retries: 0, //Retries are not needed with watch mode @@ -28,6 +32,28 @@ const config = { use: { browserName: 'chromium' } + }, + { + name: 'ipad', + grep: /@mobile/, + use: { + storageState: fileURLToPath( + new URL('./test-data/display_layout_with_child_layouts.json', import.meta.url) + ), + browserName: 'webkit', + ...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json + } + }, + { + name: 'iphone', + grep: /@mobile/, + use: { + storageState: fileURLToPath( + new URL('./test-data/display_layout_with_child_layouts.json', import.meta.url) + ), + browserName: 'webkit', + ...devices['iPhone 14 Pro'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json + } } ], reporter: [ From 6433872d79aee6dd5594a58519f951b94934f12d Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 15:02:22 -0800 Subject: [PATCH 17/19] update tests --- .../functional/plugins/imagery/exampleImagery.e2e.spec.js | 2 +- .../plugins/notebook/notebookSnapshotImage.e2e.spec.js | 2 +- e2e/tests/functional/plugins/plot/previews.e2e.spec.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js index 3a1931cd154..4f05e166607 100644 --- a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js +++ b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js @@ -363,7 +363,7 @@ test.describe('Example Imagery in Display Layout', () => { await page.locator('li[title="View Large"]').click(); await expect(pausePlayButton).toHaveClass(/is-paused/); - await page.locator('[aria-label="Close"]').click(); + await page.getByRole('button', { name: 'Close' }).click(); await expect.soft(pausePlayButton).not.toHaveClass(/is-paused/); }); diff --git a/e2e/tests/functional/plugins/notebook/notebookSnapshotImage.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebookSnapshotImage.e2e.spec.js index c6f4f902e88..15fd97b214d 100644 --- a/e2e/tests/functional/plugins/notebook/notebookSnapshotImage.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/notebookSnapshotImage.e2e.spec.js @@ -68,7 +68,7 @@ test.describe('Snapshot image tests', () => { // expect large image to be displayed await expect(page.getByRole('dialog').getByText('favicon-96x96.png')).toBeVisible(); - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); // drop another image onto the entry await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer }); diff --git a/e2e/tests/functional/plugins/plot/previews.e2e.spec.js b/e2e/tests/functional/plugins/plot/previews.e2e.spec.js index fc7f11a5a73..5d6211c3df7 100644 --- a/e2e/tests/functional/plugins/plot/previews.e2e.spec.js +++ b/e2e/tests/functional/plugins/plot/previews.e2e.spec.js @@ -57,7 +57,7 @@ test.describe('Plots work in Previews', () => { await page.getByLabel('Sine', { exact: true }).click({ button: 'right' }); await page.getByLabel('View Historical Data').click(); await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible(); - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); await page.getByLabel('Expand Test Display Layout layout').click(); // change to a plot and ensure embiggen works @@ -73,7 +73,7 @@ test.describe('Plots work in Previews', () => { await expect(page.getByLabel('Preview Container')).toBeHidden(); await page.getByLabel('Large View').click(); await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible(); - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); // get last sinewave tree item (in the display layout) await page @@ -83,6 +83,6 @@ test.describe('Plots work in Previews', () => { .click({ button: 'right' }); await page.getByLabel('View', { exact: true }).click(); await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible(); - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); }); }); From 8fcd4ddcd2c311c9518a126e3ae7c0866c01c47e Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 15:16:05 -0800 Subject: [PATCH 18/19] lint fix --- e2e/playwright-watch.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/playwright-watch.config.js b/e2e/playwright-watch.config.js index 13723724685..bd40be46388 100644 --- a/e2e/playwright-watch.config.js +++ b/e2e/playwright-watch.config.js @@ -4,7 +4,6 @@ import { devices } from '@playwright/test'; import { fileURLToPath } from 'url'; - /** @type {import('@playwright/test').PlaywrightTestConfig} */ const config = { retries: 0, //Retries are not needed with watch mode From 679e9b4980323fc55448a944636de8ac1ab1e727 Mon Sep 17 00:00:00 2001 From: John Hill Date: Wed, 21 Feb 2024 15:16:11 -0800 Subject: [PATCH 19/19] test fixes --- .../functional/plugins/imagery/exampleImagery.e2e.spec.js | 4 ++-- .../functional/plugins/telemetryTable/preview.e2e.spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js index 4f05e166607..19b3ff526bf 100644 --- a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js +++ b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js @@ -386,7 +386,7 @@ test.describe('Example Imagery in Display Layout', () => { await page.locator('li[title="View Large"]').click(); await expect(pausePlayButton).toHaveClass(/is-paused/); - await page.locator('[aria-label="Close"]').click(); + await page.getByRole('button', { name: 'Close' }).click(); await expect.soft(pausePlayButton).toHaveClass(/is-paused/); }); @@ -509,7 +509,7 @@ test.describe('Example Imagery in Flexible layout', () => { await page.getByRole('button', { name: 'Background Image', state: 'visible' }); // Close the large view - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); }); test.beforeEach(async ({ page }) => { diff --git a/e2e/tests/functional/plugins/telemetryTable/preview.e2e.spec.js b/e2e/tests/functional/plugins/telemetryTable/preview.e2e.spec.js index e7d98f38a05..fe7a823f8f3 100644 --- a/e2e/tests/functional/plugins/telemetryTable/preview.e2e.spec.js +++ b/e2e/tests/functional/plugins/telemetryTable/preview.e2e.spec.js @@ -53,7 +53,7 @@ test.describe('Preview mode', () => { await expect(page.getByLabel('Export Table Data')).toBeVisible(); await expect(page.getByLabel('Export Marked Rows')).toBeVisible(); await page.getByRole('menuitem', { name: 'Pause' }).click(); - await page.getByLabel('Close').click(); + await page.getByRole('button', { name: 'Close' }).click(); await expandEntireTree(page);