mirror of
https://github.com/nasa/openmct.git
synced 2025-05-11 04:52:57 +00:00
[Mobile] Add Global Search to Mobile (#7477)
* Add status area back to mobile * Make search results responsive to width * Make clear search button always visible, regardless of hover * Make clear search button visible, and fix weird margin in top left corner * 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 * update mobile testing * Fix dropdown sizes, remove shadows and corners to make it look less like a popup and more full screen * Add animation and persist search bar in mobile * Fix linting issues * Fix padding in Desktop * fix padding in status area * fix bad merge * lint fixes * fix bad merge... again * again * fixes to mobile * update tests * lint fix * test fixes --------- Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
parent
6bbabf9c45
commit
6393a77c19
@ -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
|
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:
|
steps:
|
||||||
- generate_and_store_version_and_filesystem_artifacts
|
- 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:
|
e2e-couchdb:
|
||||||
executor: ubuntu
|
executor: ubuntu
|
||||||
steps:
|
steps:
|
||||||
@ -260,8 +285,9 @@ workflows:
|
|||||||
- e2e-test:
|
- e2e-test:
|
||||||
name: e2e-stable
|
name: e2e-stable
|
||||||
suite: stable
|
suite: stable
|
||||||
|
- e2e-mobile
|
||||||
- visual-a11y-tests:
|
- visual-a11y-tests:
|
||||||
name: visual-test-ci
|
name: visual-a11y-test-ci
|
||||||
suite: ci
|
suite: ci
|
||||||
|
|
||||||
the-nightly: #These jobs do not run on PRs, but against master at night
|
the-nightly: #These jobs do not run on PRs, but against master at night
|
||||||
@ -277,10 +303,11 @@ workflows:
|
|||||||
- e2e-test:
|
- e2e-test:
|
||||||
name: e2e-full-nightly
|
name: e2e-full-nightly
|
||||||
suite: full
|
suite: full
|
||||||
- mem-test
|
- e2e-mobile
|
||||||
- perf-test
|
- perf-test
|
||||||
|
- mem-test
|
||||||
- visual-a11y-tests:
|
- visual-a11y-tests:
|
||||||
name: visual-test-nightly
|
name: visual-a11y-test-nightly
|
||||||
suite: full
|
suite: full
|
||||||
- e2e-couchdb
|
- e2e-couchdb
|
||||||
triggers:
|
triggers:
|
||||||
|
@ -229,7 +229,7 @@ Current list of test tags:
|
|||||||
|
|
||||||
|Test Tag|Description|
|
|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.|
|
|`@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.|
|
|`@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`.|
|
|`@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**
|
#### **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:**
|
#### **Skipping or executing tests based on browser, os, and/os browser version:**
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ const NUM_WORKERS = 2;
|
|||||||
const config = {
|
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
|
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',
|
testDir: 'tests',
|
||||||
|
grepInvert: /@mobile/, //Ignore mobile tests
|
||||||
testIgnore: '**/*.perf.spec.js', //Ignore performance tests and define in playwright-perfromance.config.js
|
testIgnore: '**/*.perf.spec.js', //Ignore performance tests and define in playwright-perfromance.config.js
|
||||||
timeout: 60 * 1000,
|
timeout: 60 * 1000,
|
||||||
webServer: {
|
webServer: {
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
// playwright.config.js
|
// playwright.config.js
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
import { devices } from '@playwright/test';
|
|
||||||
|
|
||||||
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
retries: 0,
|
retries: 0,
|
||||||
testDir: 'tests',
|
testDir: 'tests',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
testIgnore: '**/*.perf.spec.js',
|
testIgnore: '**/*.perf.spec.js',
|
||||||
timeout: 30 * 1000,
|
timeout: 30 * 1000,
|
||||||
webServer: {
|
webServer: {
|
||||||
@ -35,7 +33,6 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MMOC',
|
name: 'MMOC',
|
||||||
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'chromium',
|
browserName: 'chromium',
|
||||||
@ -47,8 +44,6 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'safari',
|
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/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'webkit'
|
browserName: 'webkit'
|
||||||
@ -56,7 +51,6 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'firefox',
|
name: 'firefox',
|
||||||
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'firefox'
|
browserName: 'firefox'
|
||||||
@ -64,7 +58,6 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'canary',
|
name: 'canary',
|
||||||
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'chromium',
|
browserName: 'chromium',
|
||||||
@ -73,22 +66,11 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'chrome-beta',
|
name: 'chrome-beta',
|
||||||
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'chromium',
|
browserName: 'chromium',
|
||||||
channel: 'chrome-beta'
|
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: [
|
reporter: [
|
||||||
|
69
e2e/playwright-mobile.config.js
Normal file
69
e2e/playwright-mobile.config.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// playwright.config.js
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
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;
|
@ -1,6 +1,9 @@
|
|||||||
// playwright.config.js
|
// playwright.config.js
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
import { devices } from '@playwright/test';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
retries: 0, //Retries are not needed with watch mode
|
retries: 0, //Retries are not needed with watch mode
|
||||||
@ -28,6 +31,28 @@ const config = {
|
|||||||
use: {
|
use: {
|
||||||
browserName: 'chromium'
|
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: [
|
reporter: [
|
||||||
|
@ -363,7 +363,7 @@ test.describe('Example Imagery in Display Layout', () => {
|
|||||||
await page.locator('li[title="View Large"]').click();
|
await page.locator('li[title="View Large"]').click();
|
||||||
await expect(pausePlayButton).toHaveClass(/is-paused/);
|
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/);
|
await expect.soft(pausePlayButton).not.toHaveClass(/is-paused/);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -386,7 +386,7 @@ test.describe('Example Imagery in Display Layout', () => {
|
|||||||
await page.locator('li[title="View Large"]').click();
|
await page.locator('li[title="View Large"]').click();
|
||||||
await expect(pausePlayButton).toHaveClass(/is-paused/);
|
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/);
|
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' });
|
await page.getByRole('button', { name: 'Background Image', state: 'visible' });
|
||||||
|
|
||||||
// Close the large view
|
// Close the large view
|
||||||
await page.getByLabel('Close').click();
|
await page.getByRole('button', { name: 'Close' }).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
|
@ -68,7 +68,7 @@ test.describe('Snapshot image tests', () => {
|
|||||||
// expect large image to be displayed
|
// expect large image to be displayed
|
||||||
await expect(page.getByRole('dialog').getByText('favicon-96x96.png')).toBeVisible();
|
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
|
// drop another image onto the entry
|
||||||
await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer });
|
await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer });
|
||||||
|
@ -57,7 +57,7 @@ test.describe('Plots work in Previews', () => {
|
|||||||
await page.getByLabel('Sine', { exact: true }).click({ button: 'right' });
|
await page.getByLabel('Sine', { exact: true }).click({ button: 'right' });
|
||||||
await page.getByLabel('View Historical Data').click();
|
await page.getByLabel('View Historical Data').click();
|
||||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
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();
|
await page.getByLabel('Expand Test Display Layout layout').click();
|
||||||
|
|
||||||
// change to a plot and ensure embiggen works
|
// 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 expect(page.getByLabel('Preview Container')).toBeHidden();
|
||||||
await page.getByLabel('Large View').click();
|
await page.getByLabel('Large View').click();
|
||||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
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)
|
// get last sinewave tree item (in the display layout)
|
||||||
await page
|
await page
|
||||||
@ -83,6 +83,6 @@ test.describe('Plots work in Previews', () => {
|
|||||||
.click({ button: 'right' });
|
.click({ button: 'right' });
|
||||||
await page.getByLabel('View', { exact: true }).click();
|
await page.getByLabel('View', { exact: true }).click();
|
||||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
||||||
await page.getByLabel('Close').click();
|
await page.getByRole('button', { name: 'Close' }).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ test.describe('Preview mode', () => {
|
|||||||
await expect(page.getByLabel('Export Table Data')).toBeVisible();
|
await expect(page.getByLabel('Export Table Data')).toBeVisible();
|
||||||
await expect(page.getByLabel('Export Marked Rows')).toBeVisible();
|
await expect(page.getByLabel('Export Marked Rows')).toBeVisible();
|
||||||
await page.getByRole('menuitem', { name: 'Pause' }).click();
|
await page.getByRole('menuitem', { name: 'Pause' }).click();
|
||||||
await page.getByLabel('Close').click();
|
await page.getByRole('button', { name: 'Close' }).click();
|
||||||
|
|
||||||
await expandEntireTree(page);
|
await expandEntireTree(page);
|
||||||
|
|
||||||
|
@ -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();
|
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;
|
const { myItemsFolderName } = openmctConfig;
|
||||||
//Go to baseURL
|
//Go to baseURL
|
||||||
await page.goto('./');
|
await page.goto('./');
|
||||||
|
59
e2e/tests/mobile/smoke.e2e.spec.js
Normal file
59
e2e/tests/mobile/smoke.e2e.spec.js
Normal file
@ -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();
|
||||||
|
});
|
@ -107,6 +107,7 @@
|
|||||||
"test:debug": "KARMA_DEBUG=true karma start karma.conf.cjs",
|
"test:debug": "KARMA_DEBUG=true karma start karma.conf.cjs",
|
||||||
"test:e2e": "npx playwright test",
|
"test:e2e": "npx playwright test",
|
||||||
"test:e2e:a11y": "npx playwright test --config=e2e/playwright-visual-a11y.config.js --project=chrome --grep @a11y",
|
"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: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: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",
|
"test:e2e:unstable": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome --grep @unstable",
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
&:before {
|
&:before {
|
||||||
// Mag glass icon
|
// Mag glass icon
|
||||||
content: $glyph-icon-magnify;
|
content: $glyph-icon-magnify;
|
||||||
|
body.mobile & { // Make search icon stand out in mobile
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__use-regex {
|
&__use-regex {
|
||||||
@ -47,15 +50,26 @@
|
|||||||
display: none;
|
display: none;
|
||||||
order: 99;
|
order: 99;
|
||||||
padding: 1px 0;
|
padding: 1px 0;
|
||||||
|
body.mobile & {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-active {
|
&.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 {
|
.c-search__use-regex {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
width: 0;
|
width: 0;
|
||||||
|
body.mobile & {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='text'],
|
input[type='text'],
|
||||||
|
@ -171,7 +171,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__head,
|
//&__head,
|
||||||
&__pane-inspector {
|
&__pane-inspector {
|
||||||
body.mobile & {
|
body.mobile & {
|
||||||
display: none;
|
display: none;
|
||||||
@ -189,6 +189,18 @@
|
|||||||
margin-bottom: $interiorMargin; // Needs some additional visual separation
|
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 {
|
body.mobile & .l-shell__main-view-browse-bar {
|
||||||
margin-left: $mobileMenuIconD; // Make room for the hamburger!
|
margin-left: $mobileMenuIconD; // Make room for the hamburger!
|
||||||
.c-button[class*='__actions__edit'] {
|
.c-button[class*='__actions__edit'] {
|
||||||
@ -241,7 +253,20 @@
|
|||||||
border-left: $brdr;
|
border-left: $brdr;
|
||||||
align-items: start;
|
align-items: start;
|
||||||
$p: $interiorMarginSm;
|
$p: $interiorMarginSm;
|
||||||
padding-left: $p; padding-right: $p;
|
padding-left: $p;
|
||||||
|
padding-right: $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__create-button,
|
||||||
|
&__app-logo {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__create-button {
|
||||||
|
body.mobile & {
|
||||||
|
// Fixes weird gap in mobile status area
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__indicators {
|
&__indicators {
|
||||||
@ -254,7 +279,6 @@
|
|||||||
height: 24px;
|
height: 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************* MAIN AREA */
|
/******************************* MAIN AREA */
|
||||||
@ -355,14 +379,18 @@
|
|||||||
.is-editing {
|
.is-editing {
|
||||||
.l-shell__main-container {
|
.l-shell__main-container {
|
||||||
$m: 3px;
|
$m: 3px;
|
||||||
box-shadow: $colorBodyBg 0 0 0 1px, $editUIAreaShdw;
|
box-shadow:
|
||||||
|
$colorBodyBg 0 0 0 1px,
|
||||||
|
$editUIAreaShdw;
|
||||||
margin-left: $m;
|
margin-left: $m;
|
||||||
margin-right: $m;
|
margin-right: $m;
|
||||||
top: $shellToolBarH + $shellMainBrowseBarH + $interiorMarginLg !important;
|
top: $shellToolBarH + $shellMainBrowseBarH + $interiorMarginLg !important;
|
||||||
|
|
||||||
&[s-selected] {
|
&[s-selected] {
|
||||||
// Provide a clearer selection context articulation for the main edit area
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
aria-label="Search Results Dropdown"
|
aria-label="Search Results Dropdown"
|
||||||
class="c-gsearch__dropdown"
|
class="c-gsearch__dropdown"
|
||||||
>
|
>
|
||||||
|
<button
|
||||||
|
aria-label="Close"
|
||||||
|
class="c-gsearch__results-close c-click-icon c-overlay__close-button icon-x"
|
||||||
|
@click="selectedResult"
|
||||||
|
></button>
|
||||||
<div class="c-gsearch__results" :class="{ 'search-finished': !searchLoading }">
|
<div class="c-gsearch__results" :class="{ 'search-finished': !searchLoading }">
|
||||||
<div
|
<div
|
||||||
v-if="objectResults?.length"
|
v-if="objectResults?.length"
|
||||||
|
@ -28,6 +28,19 @@
|
|||||||
background: rgba($colorHeadFg, 0.2);
|
background: rgba($colorHeadFg, 0.2);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
flex: 1 1 auto;
|
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 {
|
||||||
|
// When clicked, expand the search bar
|
||||||
|
background-color: rgba($colorHeadFg, 0.2);
|
||||||
|
width: 50vw;
|
||||||
|
transition: width 120ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +53,17 @@
|
|||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
top: $formInputH;
|
top: $formInputH;
|
||||||
z-index: 60;
|
z-index: 60;
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__results,
|
&__results,
|
||||||
@ -55,6 +79,10 @@
|
|||||||
> * + * {
|
> * + * {
|
||||||
margin-top: $interiorMarginLg;
|
margin-top: $interiorMarginLg;
|
||||||
}
|
}
|
||||||
|
body.mobile & {
|
||||||
|
// Add a margin to results so we have room for the close button
|
||||||
|
width: 93%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__results-section {
|
&__results-section {
|
||||||
@ -65,6 +93,7 @@
|
|||||||
|
|
||||||
&__results-section-title {
|
&__results-section-title {
|
||||||
@include propertiesHeader();
|
@include propertiesHeader();
|
||||||
|
width: 95%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__result-pane-msg {
|
&__result-pane-msg {
|
||||||
@ -72,6 +101,22 @@
|
|||||||
margin-top: $interiorMargin;
|
margin-top: $interiorMargin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__results-close {
|
||||||
|
// Close button that appears for mobile only
|
||||||
|
display: none;
|
||||||
|
body.mobile & {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body.mobile & {
|
||||||
|
width: 50vw;
|
||||||
|
@include phonePortrait() {
|
||||||
|
// This logic only appears for a mobile portrait mode
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.c-gsearch-result {
|
.c-gsearch-result {
|
||||||
@ -113,9 +158,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.c-location {
|
.c-location {
|
||||||
//color: $colorBodyFg;
|
color: $colorBodyFg;
|
||||||
//font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
//opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user