mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 07:16:39 +00:00
e2e Code Coverage and all test fixes (#5328)
Add e2e code coverage and fix all tests
This commit is contained in:
parent
8ce15521de
commit
0f352087f5
@ -2,7 +2,7 @@ version: 2.1
|
|||||||
executors:
|
executors:
|
||||||
pw-focal-development:
|
pw-focal-development:
|
||||||
docker:
|
docker:
|
||||||
- image: mcr.microsoft.com/playwright:v1.21.1-focal
|
- image: mcr.microsoft.com/playwright:v1.23.0-focal
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
|
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
|
||||||
parameters:
|
parameters:
|
||||||
@ -12,7 +12,7 @@ parameters:
|
|||||||
type: boolean
|
type: boolean
|
||||||
commands:
|
commands:
|
||||||
build_and_install:
|
build_and_install:
|
||||||
description: "All steps used to build and install. Will not work on node10"
|
description: "All steps used to build and install. Will use cache if found"
|
||||||
parameters:
|
parameters:
|
||||||
node-version:
|
node-version:
|
||||||
type: string
|
type: string
|
||||||
@ -58,10 +58,14 @@ commands:
|
|||||||
ls -latR >> /tmp/artifacts/dir.txt
|
ls -latR >> /tmp/artifacts/dir.txt
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: /tmp/artifacts/
|
path: /tmp/artifacts/
|
||||||
upload_code_covio:
|
generate_e2e_code_cov_report:
|
||||||
description: "Command to upload code coverage reports to codecov.io"
|
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"
|
||||||
steps:
|
parameters:
|
||||||
- run: curl -Os https://uploader.codecov.io/latest/linux/codecov;chmod +x codecov;./codecov
|
suite:
|
||||||
|
type: string
|
||||||
|
steps:
|
||||||
|
- run: npm run cov:e2e:report
|
||||||
|
- run: npm run cov:e2e:<<parameters.suite>>:publish
|
||||||
orbs:
|
orbs:
|
||||||
node: circleci/node@4.9.0
|
node: circleci/node@4.9.0
|
||||||
browser-tools: circleci/browser-tools@1.3.0
|
browser-tools: circleci/browser-tools@1.3.0
|
||||||
@ -114,12 +118,13 @@ jobs:
|
|||||||
- browser-tools/install-chrome:
|
- browser-tools/install-chrome:
|
||||||
replace-existing: false
|
replace-existing: false
|
||||||
- run: npm run test -- --browsers=<<parameters.browser>>
|
- run: npm run test -- --browsers=<<parameters.browser>>
|
||||||
|
- run: npm run cov:unit:publish
|
||||||
- save_cache_cmd:
|
- save_cache_cmd:
|
||||||
node-version: <<parameters.node-version>>
|
node-version: <<parameters.node-version>>
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: dist/reports/tests/
|
path: dist/reports/tests/
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: dist/reports/
|
path: coverage
|
||||||
- generate_and_store_version_and_filesystem_artifacts
|
- generate_and_store_version_and_filesystem_artifacts
|
||||||
e2e-test:
|
e2e-test:
|
||||||
parameters:
|
parameters:
|
||||||
@ -132,11 +137,22 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- build_and_install:
|
- build_and_install:
|
||||||
node-version: <<parameters.node-version>>
|
node-version: <<parameters.node-version>>
|
||||||
|
- when: #Only install chrome-beta when running the full suite to save $$$
|
||||||
|
condition:
|
||||||
|
equal: [ "full", <<parameters.suite>> ]
|
||||||
|
steps:
|
||||||
|
- run: npx playwright install chrome-beta
|
||||||
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npm run test:e2e:<<parameters.suite>> -- --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
|
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npm run test:e2e:<<parameters.suite>> -- --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
|
||||||
|
- generate_e2e_code_cov_report:
|
||||||
|
suite: <<parameters.suite>>
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: test-results/results.xml
|
path: test-results/results.xml
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: test-results
|
path: test-results
|
||||||
|
- store_artifacts:
|
||||||
|
path: coverage
|
||||||
|
- store_artifacts:
|
||||||
|
path: html-test-results
|
||||||
- generate_and_store_version_and_filesystem_artifacts
|
- generate_and_store_version_and_filesystem_artifacts
|
||||||
perf-test:
|
perf-test:
|
||||||
parameters:
|
parameters:
|
||||||
@ -151,19 +167,19 @@ jobs:
|
|||||||
path: test-results/results.xml
|
path: test-results/results.xml
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: test-results
|
path: test-results
|
||||||
- generate_and_store_version_and_filesystem_artifacts
|
- store_artifacts:
|
||||||
|
path: html-test-results
|
||||||
|
- generate_and_store_version_and_filesystem_artifacts
|
||||||
workflows:
|
workflows:
|
||||||
overall-circleci-commit-status: #These jobs run on every commit
|
overall-circleci-commit-status: #These jobs run on every commit
|
||||||
jobs:
|
jobs:
|
||||||
- lint:
|
- lint:
|
||||||
name: node16-lint
|
name: node14-lint
|
||||||
node-version: lts/gallium
|
|
||||||
- unit-test:
|
|
||||||
name: node14-chrome
|
|
||||||
node-version: lts/fermium
|
node-version: lts/fermium
|
||||||
|
- unit-test:
|
||||||
|
name: node16-chrome
|
||||||
|
node-version: lts/gallium
|
||||||
browser: ChromeHeadless
|
browser: ChromeHeadless
|
||||||
post-steps:
|
|
||||||
- upload_code_covio
|
|
||||||
- unit-test:
|
- unit-test:
|
||||||
name: node18-chrome
|
name: node18-chrome
|
||||||
node-version: "18"
|
node-version: "18"
|
||||||
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -15,8 +15,6 @@
|
|||||||
*.idea
|
*.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
# External dependencies
|
|
||||||
|
|
||||||
# Build output
|
# Build output
|
||||||
target
|
target
|
||||||
dist
|
dist
|
||||||
@ -24,30 +22,24 @@ dist
|
|||||||
# Mac OS X Finder
|
# Mac OS X Finder
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Closed source libraries
|
|
||||||
closed-lib
|
|
||||||
|
|
||||||
# Node, Bower dependencies
|
# Node, Bower dependencies
|
||||||
node_modules
|
node_modules
|
||||||
bower_components
|
bower_components
|
||||||
|
|
||||||
# Protractor logs
|
|
||||||
protractor/logs
|
|
||||||
|
|
||||||
# npm-debug log
|
# npm-debug log
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|
||||||
# karma reports
|
# karma reports
|
||||||
report.*.json
|
report.*.json
|
||||||
|
|
||||||
# Lighthouse reports
|
|
||||||
.lighthouseci
|
|
||||||
|
|
||||||
# e2e test artifacts
|
# e2e test artifacts
|
||||||
test-results
|
test-results
|
||||||
allure-results
|
html-test-results
|
||||||
|
|
||||||
package-lock.json
|
# codecov artifacts
|
||||||
|
.nyc_output
|
||||||
#codecov artifacts
|
coverage
|
||||||
codecov
|
codecov
|
||||||
|
|
||||||
|
# :(
|
||||||
|
package-lock.json
|
||||||
|
2
app.js
2
app.js
@ -49,7 +49,7 @@ class WatchRunPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const webpackConfig = require('./webpack.dev.js');
|
const webpackConfig = process.env.CI ? require('./webpack.coverage.js') : require('./webpack.dev.js');
|
||||||
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||||
webpackConfig.plugins.push(new WatchRunPlugin());
|
webpackConfig.plugins.push(new WatchRunPlugin());
|
||||||
|
|
||||||
|
17
codecov.yml
17
codecov.yml
@ -13,17 +13,16 @@ coverage:
|
|||||||
round: down
|
round: down
|
||||||
range: "66...100"
|
range: "66...100"
|
||||||
|
|
||||||
ignore:
|
flags:
|
||||||
|
unit:
|
||||||
parsers:
|
carryforward: true
|
||||||
gcov:
|
e2e-ci:
|
||||||
branch_detection:
|
carryforward: true
|
||||||
conditional: true
|
e2e-full:
|
||||||
loop: true
|
carryforward: true
|
||||||
method: false
|
|
||||||
macro: false
|
|
||||||
|
|
||||||
comment:
|
comment:
|
||||||
layout: "reach,diff,flags,files,footer"
|
layout: "reach,diff,flags,files,footer"
|
||||||
behavior: default
|
behavior: default
|
||||||
require_changes: false
|
require_changes: false
|
||||||
|
show_carryforward_flags: true
|
@ -1,8 +1,13 @@
|
|||||||
/* eslint-disable no-undef */
|
/* This file extends the base functionality of the playwright test framework to enable
|
||||||
|
* code coverage instrumentation, console log error detection and working with a 3rd
|
||||||
|
* party Chrome-as-a-service extension called Browserless.
|
||||||
|
*/
|
||||||
|
|
||||||
// This file extends the base functionality of the playwright test framework
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
const { expect } = require('@playwright/test');
|
const { expect } = require('@playwright/test');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { v4: uuid } = require('uuid');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a `ConsoleMessage` and returns a formatted string
|
* Takes a `ConsoleMessage` and returns a formatted string
|
||||||
@ -16,7 +21,30 @@ function consoleMessageToString(msg) {
|
|||||||
at (${url} ${lineNumber}:${columnNumber})`;
|
at (${url} ${lineNumber}:${columnNumber})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//The following is based on https://github.com/mxschmitt/playwright-test-coverage
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const istanbulCLIOutput = path.join(process.cwd(), '.nyc_output');
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
exports.test = base.test.extend({
|
exports.test = base.test.extend({
|
||||||
|
//The following is based on https://github.com/mxschmitt/playwright-test-coverage
|
||||||
|
context: async ({ context }, use) => {
|
||||||
|
await context.addInitScript(() =>
|
||||||
|
window.addEventListener('beforeunload', () =>
|
||||||
|
(window).collectIstanbulCoverage(JSON.stringify((window).__coverage__))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await fs.promises.mkdir(istanbulCLIOutput, { recursive: true });
|
||||||
|
await context.exposeFunction('collectIstanbulCoverage', (coverageJSON) => {
|
||||||
|
if (coverageJSON) {
|
||||||
|
fs.writeFileSync(path.join(istanbulCLIOutput, `playwright_coverage_${uuid()}.json`), coverageJSON);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await use(context);
|
||||||
|
for (const page of context.pages()) {
|
||||||
|
await page.evaluate(() => (window).collectIstanbulCoverage(JSON.stringify((window).__coverage__)));
|
||||||
|
}
|
||||||
|
},
|
||||||
page: async ({ baseURL, page }, use) => {
|
page: async ({ baseURL, page }, use) => {
|
||||||
const messages = [];
|
const messages = [];
|
||||||
page.on('console', (msg) => messages.push(msg));
|
page.on('console', (msg) => messages.push(msg));
|
||||||
|
@ -7,13 +7,13 @@ const { devices } = require('@playwright/test');
|
|||||||
|
|
||||||
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
retries: 1,
|
retries: 3, //Retries 3 times for a total of 4. When running sharded and with maxFailures = 5, this should ensure that flake is managed without failing the full suite
|
||||||
testDir: 'tests',
|
testDir: '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: {
|
||||||
command: 'npm run start',
|
command: 'npm run start',
|
||||||
port: 8080,
|
url: 'http://localhost:8080/#',
|
||||||
timeout: 200 * 1000,
|
timeout: 200 * 1000,
|
||||||
reuseExistingServer: !process.env.CI
|
reuseExistingServer: !process.env.CI
|
||||||
},
|
},
|
||||||
@ -36,6 +36,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MMOC',
|
name: 'MMOC',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'chromium',
|
browserName: 'chromium',
|
||||||
@ -44,20 +45,30 @@ const config = {
|
|||||||
height: 1440
|
height: 1440
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
/*{
|
{
|
||||||
name: 'ipad',
|
name: 'firefox',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'webkit',
|
browserName: 'firefox'
|
||||||
...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json
|
|
||||||
}
|
}
|
||||||
}*/
|
},
|
||||||
|
{
|
||||||
|
name: 'chrome-beta', //Only Chrome Beta is available on ubuntu -- not chrome canary
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
|
use: {
|
||||||
|
browserName: 'chromium',
|
||||||
|
channel: 'chrome-beta'
|
||||||
|
}
|
||||||
|
}
|
||||||
],
|
],
|
||||||
reporter: [
|
reporter: [
|
||||||
['list'],
|
['list'],
|
||||||
['html', {
|
['html', {
|
||||||
open: 'never',
|
open: 'never',
|
||||||
outputFolder: '../test-results/html/'
|
outputFolder: '../html-test-results' //Must be in different location due to https://github.com/microsoft/playwright/issues/12840
|
||||||
}],
|
}],
|
||||||
['junit', { outputFile: 'test-results/results.xml' }],
|
['junit', { outputFile: 'test-results/results.xml' }],
|
||||||
['github']
|
['github']
|
||||||
|
@ -13,7 +13,7 @@ const config = {
|
|||||||
timeout: 30 * 1000,
|
timeout: 30 * 1000,
|
||||||
webServer: {
|
webServer: {
|
||||||
command: 'npm run start',
|
command: 'npm run start',
|
||||||
port: 8080,
|
url: 'http://localhost:8080/#',
|
||||||
timeout: 120 * 1000,
|
timeout: 120 * 1000,
|
||||||
reuseExistingServer: !process.env.CI
|
reuseExistingServer: !process.env.CI
|
||||||
},
|
},
|
||||||
@ -36,6 +36,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MMOC',
|
name: 'MMOC',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
grepInvert: /@snapshot/,
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'chromium',
|
browserName: 'chromium',
|
||||||
@ -44,20 +45,58 @@ const config = {
|
|||||||
height: 1440
|
height: 1440
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
/*{
|
{
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'firefox',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
|
use: {
|
||||||
|
browserName: 'firefox'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'canary',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
|
use: {
|
||||||
|
browserName: 'chromium',
|
||||||
|
channel: 'chrome-canary' //Note this is not available in ubuntu/CircleCI
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'chrome-beta',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
|
use: {
|
||||||
|
browserName: 'chromium',
|
||||||
|
channel: 'chrome-beta'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
name: 'ipad',
|
name: 'ipad',
|
||||||
|
testMatch: '**/*.e2e.spec.js', // only run e2e tests
|
||||||
|
grep: /@ipad/,
|
||||||
|
grepInvert: /@snapshot/,
|
||||||
use: {
|
use: {
|
||||||
browserName: 'webkit',
|
browserName: 'webkit',
|
||||||
...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json
|
...devices['iPad (gen 7) landscape'] // Complete List https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
],
|
],
|
||||||
reporter: [
|
reporter: [
|
||||||
['list'],
|
['list'],
|
||||||
['html', {
|
['html', {
|
||||||
open: 'on-failure',
|
open: 'on-failure',
|
||||||
outputFolder: '../test-results'
|
outputFolder: '../html-test-results' //Must be in different location due to https://github.com/microsoft/playwright/issues/12840
|
||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
retries: 1, //Only for debugging purposes
|
retries: 1, //Only for debugging purposes because trace is enabled only on first retry
|
||||||
testDir: 'tests/performance/',
|
testDir: 'tests/performance/',
|
||||||
timeout: 60 * 1000,
|
timeout: 60 * 1000,
|
||||||
workers: 1, //Only run in serial with 1 worker
|
workers: 1, //Only run in serial with 1 worker
|
||||||
webServer: {
|
webServer: {
|
||||||
command: 'npm run start',
|
command: 'npm run start',
|
||||||
port: 8080,
|
url: 'http://localhost:8080/#',
|
||||||
timeout: 200 * 1000,
|
timeout: 200 * 1000,
|
||||||
reuseExistingServer: !process.env.CI
|
reuseExistingServer: !process.env.CI
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ const config = {
|
|||||||
workers: 1, // visual tests should never run in parallel due to test pollution
|
workers: 1, // visual tests should never run in parallel due to test pollution
|
||||||
webServer: {
|
webServer: {
|
||||||
command: 'npm run start',
|
command: 'npm run start',
|
||||||
port: 8080,
|
url: 'http://localhost:8080/#',
|
||||||
timeout: 200 * 1000,
|
timeout: 200 * 1000,
|
||||||
reuseExistingServer: !process.env.CI
|
reuseExistingServer: !process.env.CI
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@ test.describe('Branding tests', () => {
|
|||||||
page.waitForEvent('popup'),
|
page.waitForEvent('popup'),
|
||||||
page.locator('text=click here for third party licensing information').click()
|
page.locator('text=click here for third party licensing information').click()
|
||||||
]);
|
]);
|
||||||
|
await page2.waitForLoadState('networkidle'); //Avoids timing issues with juggler/firefox
|
||||||
expect(page2.waitForURL('**/licenses**')).toBeTruthy();
|
expect(page2.waitForURL('**/licenses**')).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,7 +28,9 @@ const { test } = require('../../../fixtures.js');
|
|||||||
const { expect } = require('@playwright/test');
|
const { expect } = require('@playwright/test');
|
||||||
|
|
||||||
test.describe('Sine Wave Generator', () => {
|
test.describe('Sine Wave Generator', () => {
|
||||||
test('Create new Sine Wave Generator Object and validate create Form Logic', async ({ page }) => {
|
test('Create new Sine Wave Generator Object and validate create Form Logic', async ({ page, browserName }) => {
|
||||||
|
test.fixme(browserName === 'firefox', 'This test needs to be updated to work with firefox');
|
||||||
|
|
||||||
//Go to baseURL
|
//Go to baseURL
|
||||||
await page.goto('/', { waitUntil: 'networkidle' });
|
await page.goto('/', { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
@ -40,44 +42,45 @@ test.describe('Sine Wave Generator', () => {
|
|||||||
|
|
||||||
// Verify that the each required field has required indicator
|
// Verify that the each required field has required indicator
|
||||||
// Title
|
// Title
|
||||||
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(/req/);
|
||||||
|
|
||||||
// Verify that the Notes row does not have a required indicator
|
// Verify that the Notes row does not have a required indicator
|
||||||
await expect(page.locator('.c-form__section div:nth-child(3) .form-row .c-form-row__state-indicator')).not.toContain('.req');
|
await expect(page.locator('.c-form__section div:nth-child(3) .form-row .c-form-row__state-indicator')).not.toContain('.req');
|
||||||
|
await page.locator('textarea[type="text"]').fill('Optional Note Text');
|
||||||
|
|
||||||
// Period
|
// Period
|
||||||
await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(4) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Amplitude
|
// Amplitude
|
||||||
await expect(page.locator('.c-form__section div:nth-child(5) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(5) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Offset
|
// Offset
|
||||||
await expect(page.locator('.c-form__section div:nth-child(6) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(6) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Data Rate
|
// Data Rate
|
||||||
await expect(page.locator('.c-form__section div:nth-child(7) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(7) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Phase
|
// Phase
|
||||||
await expect(page.locator('.c-form__section div:nth-child(8) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(8) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Randomness
|
// Randomness
|
||||||
await expect(page.locator('.c-form__section div:nth-child(9) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
|
await expect(page.locator('div:nth-child(9) .c-form-row__state-indicator')).toHaveClass(/req/);
|
||||||
|
|
||||||
// Verify that by removing value from required text field shows invalid indicator
|
// Verify that by removing value from required text field shows invalid indicator
|
||||||
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('');
|
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('');
|
||||||
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req invalid']);
|
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(/invalid/);
|
||||||
|
|
||||||
// Verify that by adding value to empty required text field changes invalid to valid indicator
|
// Verify that by adding value to empty required text field changes invalid to valid indicator
|
||||||
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('non empty');
|
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('New Sine Wave Generator');
|
||||||
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req valid']);
|
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(/valid/);
|
||||||
|
|
||||||
// Verify that by removing value from required number field shows invalid indicator
|
// Verify that by removing value from required number field shows invalid indicator
|
||||||
await page.locator('.field.control.l-input-sm input').first().fill('');
|
await page.locator('.field.control.l-input-sm input').first().fill('');
|
||||||
await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req invalid']);
|
await expect(page.locator('div:nth-child(4) .c-form-row__state-indicator')).toHaveClass(/invalid/);
|
||||||
|
|
||||||
// Verify that by adding value to empty required number field changes invalid to valid indicator
|
// Verify that by adding value to empty required number field changes invalid to valid indicator
|
||||||
await page.locator('.field.control.l-input-sm input').first().fill('3');
|
await page.locator('.field.control.l-input-sm input').first().fill('3');
|
||||||
await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req valid']);
|
await expect(page.locator('div:nth-child(4) .c-form-row__state-indicator')).toHaveClass(/valid/);
|
||||||
|
|
||||||
// Verify that can change value of number field by up/down arrows keys
|
// Verify that can change value of number field by up/down arrows keys
|
||||||
// Click .field.control.l-input-sm input >> nth=0
|
// Click .field.control.l-input-sm input >> nth=0
|
||||||
@ -90,57 +93,6 @@ test.describe('Sine Wave Generator', () => {
|
|||||||
const value = await page.locator('.field.control.l-input-sm input').first().inputValue();
|
const value = await page.locator('.field.control.l-input-sm input').first().inputValue();
|
||||||
await expect(value).toBe('6');
|
await expect(value).toBe('6');
|
||||||
|
|
||||||
// Click .c-form-row__state-indicator.grows
|
|
||||||
await page.locator('.c-form-row__state-indicator.grows').click();
|
|
||||||
|
|
||||||
// Click text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]
|
|
||||||
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').click();
|
|
||||||
|
|
||||||
// Click .c-form-row__state-indicator >> nth=0
|
|
||||||
await page.locator('.c-form-row__state-indicator').first().click();
|
|
||||||
|
|
||||||
// Fill text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]
|
|
||||||
await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('New Sine Wave Generator');
|
|
||||||
|
|
||||||
// Double click div:nth-child(4) .form-row .c-form-row__controls
|
|
||||||
await page.locator('div:nth-child(4) .form-row .c-form-row__controls').dblclick();
|
|
||||||
|
|
||||||
// Click .field.control.l-input-sm input >> nth=0
|
|
||||||
await page.locator('.field.control.l-input-sm input').first().click();
|
|
||||||
|
|
||||||
// Click div:nth-child(4) .form-row .c-form-row__state-indicator
|
|
||||||
await page.locator('div:nth-child(4) .form-row .c-form-row__state-indicator').click();
|
|
||||||
|
|
||||||
// Click .field.control.l-input-sm input >> nth=0
|
|
||||||
await page.locator('.field.control.l-input-sm input').first().click();
|
|
||||||
|
|
||||||
// Click .field.control.l-input-sm input >> nth=0
|
|
||||||
await page.locator('.field.control.l-input-sm input').first().click();
|
|
||||||
|
|
||||||
// Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
|
|
||||||
|
|
||||||
// Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
|
|
||||||
|
|
||||||
// Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
|
|
||||||
|
|
||||||
// Click div:nth-child(6) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(6) .form-row .c-form-row__controls .form-control .field input').click();
|
|
||||||
|
|
||||||
// Double click div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').dblclick();
|
|
||||||
|
|
||||||
// Click div:nth-child(7) .form-row .c-form-row__state-indicator
|
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__state-indicator').click();
|
|
||||||
|
|
||||||
// Click div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').click();
|
|
||||||
|
|
||||||
// Fill div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
|
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').fill('3');
|
|
||||||
|
|
||||||
//Click text=OK
|
//Click text=OK
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.waitForNavigation(),
|
page.waitForNavigation(),
|
||||||
@ -151,7 +103,7 @@ test.describe('Sine Wave Generator', () => {
|
|||||||
// Verify object properties
|
// Verify object properties
|
||||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('New Sine Wave Generator');
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText('New Sine Wave Generator');
|
||||||
|
|
||||||
// Verify canvas rendered
|
// Verify canvas rendered and can be interacted with
|
||||||
await page.locator('canvas').nth(1).click({
|
await page.locator('canvas').nth(1).click({
|
||||||
position: {
|
position: {
|
||||||
x: 341,
|
x: 341,
|
||||||
|
@ -59,9 +59,6 @@ test.describe('Move item tests', () => {
|
|||||||
await page.locator('text=Properties Title Notes >> input[type="text"]').click();
|
await page.locator('text=Properties Title Notes >> input[type="text"]').click();
|
||||||
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folder2);
|
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folder2);
|
||||||
|
|
||||||
// Click on My Items in Tree. Workaround for https://github.com/nasa/openmct/issues/5184
|
|
||||||
await page.click('form[name="mctForm"] a:has-text("My Items")');
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.waitForNavigation(),
|
page.waitForNavigation(),
|
||||||
page.locator('text=OK').click(),
|
page.locator('text=OK').click(),
|
||||||
|
@ -33,7 +33,7 @@ let conditionSetUrl;
|
|||||||
let getConditionSetIdentifierFromUrl;
|
let getConditionSetIdentifierFromUrl;
|
||||||
|
|
||||||
test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
||||||
test.beforeAll(async ({ browser }) => {
|
test.beforeAll(async ({ browser}) => {
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
//Go to baseURL
|
//Go to baseURL
|
||||||
@ -51,7 +51,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
|||||||
page.click('text=OK')
|
page.click('text=OK')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//Save localStorage for future test execution
|
//Save localStorage for future test execution.
|
||||||
await context.storageState({ path: './e2e/tests/recycled_storage.json' });
|
await context.storageState({ path: './e2e/tests/recycled_storage.json' });
|
||||||
|
|
||||||
//Set object identifier from url
|
//Set object identifier from url
|
||||||
@ -60,18 +60,17 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
|||||||
|
|
||||||
getConditionSetIdentifierFromUrl = await conditionSetUrl.split('/').pop().split('?')[0];
|
getConditionSetIdentifierFromUrl = await conditionSetUrl.split('/').pop().split('?')[0];
|
||||||
console.debug('getConditionSetIdentifierFromUrl ' + getConditionSetIdentifierFromUrl);
|
console.debug('getConditionSetIdentifierFromUrl ' + getConditionSetIdentifierFromUrl);
|
||||||
|
await page.close();
|
||||||
});
|
});
|
||||||
test.afterAll(async ({ browser }) => {
|
|
||||||
await browser.close();
|
//Load localStorage for subsequent tests. Note: this requires a file already in place -- even if blank.
|
||||||
});
|
|
||||||
//Load localStorage for subsequent tests
|
|
||||||
test.use({ storageState: './e2e/tests/recycled_storage.json' });
|
test.use({ storageState: './e2e/tests/recycled_storage.json' });
|
||||||
//Begin suite of tests again localStorage
|
//Begin suite of tests again localStorage
|
||||||
test('Condition set object properties persist in main view and inspector', async ({ page }) => {
|
test('Condition set object properties persist in main view and inspector @localStorage', async ({ page }) => {
|
||||||
//Navigate to baseURL with injected localStorage
|
//Navigate to baseURL with injected localStorage
|
||||||
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
//Assertions on loaded Condition Set in main view
|
//Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto()
|
||||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||||
|
|
||||||
//Assertions on loaded Condition Set in Inspector
|
//Assertions on loaded Condition Set in Inspector
|
||||||
@ -92,7 +91,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
|||||||
test('condition set object can be modified on @localStorage', async ({ page }) => {
|
test('condition set object can be modified on @localStorage', async ({ page }) => {
|
||||||
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
//Assertions on loaded Condition Set in main view
|
//Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto()
|
||||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||||
|
|
||||||
//Update the Condition Set properties
|
//Update the Condition Set properties
|
||||||
@ -153,23 +152,25 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
|||||||
//Navigate to baseURL
|
//Navigate to baseURL
|
||||||
await page.goto('/', { waitUntil: 'networkidle' });
|
await page.goto('/', { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
const numberOfConditionSetsToStart = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count();
|
//Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto()
|
||||||
//Expect Unnamed Condition Set to be visible in Main View
|
|
||||||
await expect(page.locator('a:has-text("Unnamed Condition Set Condition Set") >> nth=0')).toBeVisible();
|
await expect(page.locator('a:has-text("Unnamed Condition Set Condition Set") >> nth=0')).toBeVisible();
|
||||||
|
|
||||||
|
const numberOfConditionSetsToStart = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count();
|
||||||
|
|
||||||
// Search for Unnamed Condition Set
|
// Search for Unnamed Condition Set
|
||||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Unnamed Condition Set');
|
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Unnamed Condition Set');
|
||||||
// Click Search Result
|
// Click Search Result
|
||||||
await page.locator('[aria-label="OpenMCT Search"] >> text=Unnamed Condition Set').first().click();
|
await page.locator('[aria-label="OpenMCT Search"] >> text=Unnamed Condition Set').first().click();
|
||||||
// Click hamburger button
|
// Click hamburger button
|
||||||
await page.locator('[title="More options"]').click();
|
await page.locator('[title="More options"]').click();
|
||||||
|
|
||||||
// Click text=Remove
|
// Click text=Remove
|
||||||
await page.locator('text=Remove').click();
|
await page.locator('text=Remove').click();
|
||||||
|
|
||||||
await page.locator('text=OK').click();
|
await page.locator('text=OK').click();
|
||||||
|
|
||||||
//Expect Unnamed Condition Set to be removed in Main View
|
//Expect Unnamed Condition Set to be removed in Main View
|
||||||
const numberOfConditionSetsAtEnd = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count();
|
const numberOfConditionSetsAtEnd = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count();
|
||||||
|
|
||||||
expect(numberOfConditionSetsAtEnd).toEqual(numberOfConditionSetsToStart - 1);
|
expect(numberOfConditionSetsAtEnd).toEqual(numberOfConditionSetsToStart - 1);
|
||||||
|
|
||||||
//Feature?
|
//Feature?
|
||||||
|
@ -29,7 +29,9 @@ but only assume that example imagery is present.
|
|||||||
const { test } = require('../../../fixtures.js');
|
const { test } = require('../../../fixtures.js');
|
||||||
const { expect } = require('@playwright/test');
|
const { expect } = require('@playwright/test');
|
||||||
|
|
||||||
test.describe('Example Imagery', () => {
|
const backgroundImageSelector = '.c-imagery__main-image__background-image';
|
||||||
|
|
||||||
|
test.describe('Example Imagery Object', () => {
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
//Go to baseURL
|
//Go to baseURL
|
||||||
@ -44,35 +46,37 @@ test.describe('Example Imagery', () => {
|
|||||||
// Click on My Items in Tree. Workaround for https://github.com/nasa/openmct/issues/5184
|
// Click on My Items in Tree. Workaround for https://github.com/nasa/openmct/issues/5184
|
||||||
await page.click('form[name="mctForm"] a:has-text("My Items")');
|
await page.click('form[name="mctForm"] a:has-text("My Items")');
|
||||||
|
|
||||||
// Click text=OK
|
// Click text=OK and wait for save banner to appear
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.waitForNavigation({waitUntil: 'networkidle'}),
|
page.waitForNavigation({waitUntil: 'networkidle'}),
|
||||||
page.click('text=OK'),
|
page.click('text=OK'),
|
||||||
//Wait for Save Banner to appear
|
//Wait for Save Banner to appear
|
||||||
page.waitForSelector('.c-message-banner__message')
|
page.waitForSelector('.c-message-banner__message')
|
||||||
]);
|
]);
|
||||||
|
// Close Banner
|
||||||
|
await page.locator('.c-message-banner__close-button').click();
|
||||||
|
|
||||||
//Wait until Save Banner is gone
|
//Wait until Save Banner is gone
|
||||||
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
||||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
||||||
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
const backgroundImageSelector = '.c-imagery__main-image__background-image';
|
|
||||||
test('Can use Mouse Wheel to zoom in and out of latest image', async ({ page }) => {
|
test('Can use Mouse Wheel to zoom in and out of latest image', async ({ page }) => {
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
|
||||||
const deltaYStep = 100; //equivalent to 1x zoom
|
const deltaYStep = 100; //equivalent to 1x zoom
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
// zoom in
|
// zoom in
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await page.mouse.wheel(0, deltaYStep * 2);
|
await page.mouse.wheel(0, deltaYStep * 2);
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
// zoom out
|
// zoom out
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await page.mouse.wheel(0, -deltaYStep);
|
await page.mouse.wheel(0, -deltaYStep);
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const imageMouseZoomedOut = await page.locator(backgroundImageSelector).boundingBox();
|
const imageMouseZoomedOut = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
|
|
||||||
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
||||||
@ -81,7 +85,8 @@ test.describe('Example Imagery', () => {
|
|||||||
expect(imageMouseZoomedOut.width).toBeLessThan(imageMouseZoomedIn.width);
|
expect(imageMouseZoomedOut.width).toBeLessThan(imageMouseZoomedIn.width);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can adjust image brightness/contrast by dragging the sliders', async ({ page }) => {
|
test('Can adjust image brightness/contrast by dragging the sliders', async ({ page, browserName }) => {
|
||||||
|
test.fixme(browserName === 'firefox', 'This test needs to be updated to work with firefox');
|
||||||
// Open the image filter menu
|
// Open the image filter menu
|
||||||
await page.locator('[role=toolbar] button[title="Brightness and contrast"]').click();
|
await page.locator('[role=toolbar] button[title="Brightness and contrast"]').click();
|
||||||
|
|
||||||
@ -94,13 +99,12 @@ test.describe('Example Imagery', () => {
|
|||||||
const deltaYStep = 100; //equivalent to 1x zoom
|
const deltaYStep = 100; //equivalent to 1x zoom
|
||||||
const panHotkey = process.platform === 'linux' ? ['Control', 'Alt'] : ['Alt'];
|
const panHotkey = process.platform === 'linux' ? ['Control', 'Alt'] : ['Alt'];
|
||||||
|
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await bgImageLocator.hover({trial: true});
|
|
||||||
|
|
||||||
// zoom in
|
// zoom in
|
||||||
await page.mouse.wheel(0, deltaYStep * 2);
|
await page.mouse.wheel(0, deltaYStep * 2);
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const zoomedBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
||||||
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
||||||
// move to the right
|
// move to the right
|
||||||
@ -123,7 +127,7 @@ test.describe('Example Imagery', () => {
|
|||||||
await page.mouse.move(imageCenterX - 200, imageCenterY, 10);
|
await page.mouse.move(imageCenterX - 200, imageCenterY, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterRightPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterRightPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(zoomedBoundingBox.x).toBeGreaterThan(afterRightPanBoundingBox.x);
|
expect(zoomedBoundingBox.x).toBeGreaterThan(afterRightPanBoundingBox.x);
|
||||||
|
|
||||||
// pan left
|
// pan left
|
||||||
@ -132,7 +136,7 @@ test.describe('Example Imagery', () => {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY, 10);
|
await page.mouse.move(imageCenterX, imageCenterY, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterLeftPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterLeftPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterRightPanBoundingBox.x).toBeLessThan(afterLeftPanBoundingBox.x);
|
expect(afterRightPanBoundingBox.x).toBeLessThan(afterLeftPanBoundingBox.x);
|
||||||
|
|
||||||
// pan up
|
// pan up
|
||||||
@ -142,7 +146,7 @@ test.describe('Example Imagery', () => {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY + 200, 10);
|
await page.mouse.move(imageCenterX, imageCenterY + 200, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterUpPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterUpPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterUpPanBoundingBox.y).toBeGreaterThan(afterLeftPanBoundingBox.y);
|
expect(afterUpPanBoundingBox.y).toBeGreaterThan(afterLeftPanBoundingBox.y);
|
||||||
|
|
||||||
// pan down
|
// pan down
|
||||||
@ -151,60 +155,58 @@ test.describe('Example Imagery', () => {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY - 200, 10);
|
await page.mouse.move(imageCenterX, imageCenterY - 200, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterDownPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterDownPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterDownPanBoundingBox.y).toBeLessThan(afterUpPanBoundingBox.y);
|
expect(afterDownPanBoundingBox.y).toBeLessThan(afterUpPanBoundingBox.y);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can use + - buttons to zoom on the image', async ({ page }) => {
|
test('Can use + - buttons to zoom on the image', async ({ page }) => {
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await bgImageLocator.hover({trial: true});
|
|
||||||
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
||||||
const zoomOutBtn = page.locator('.t-btn-zoom-out').nth(0);
|
const zoomOutBtn = page.locator('.t-btn-zoom-out').nth(0);
|
||||||
const initialBoundingBox = await bgImageLocator.boundingBox();
|
const initialBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
|
|
||||||
await zoomInBtn.click();
|
await zoomInBtn.click();
|
||||||
await zoomInBtn.click();
|
await zoomInBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const zoomedInBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedInBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(zoomedInBoundingBox.height).toBeGreaterThan(initialBoundingBox.height);
|
expect(zoomedInBoundingBox.height).toBeGreaterThan(initialBoundingBox.height);
|
||||||
expect(zoomedInBoundingBox.width).toBeGreaterThan(initialBoundingBox.width);
|
expect(zoomedInBoundingBox.width).toBeGreaterThan(initialBoundingBox.width);
|
||||||
|
|
||||||
await zoomOutBtn.click();
|
await zoomOutBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const zoomedOutBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedOutBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(zoomedOutBoundingBox.height).toBeLessThan(zoomedInBoundingBox.height);
|
expect(zoomedOutBoundingBox.height).toBeLessThan(zoomedInBoundingBox.height);
|
||||||
expect(zoomedOutBoundingBox.width).toBeLessThan(zoomedInBoundingBox.width);
|
expect(zoomedOutBoundingBox.width).toBeLessThan(zoomedInBoundingBox.width);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can use the reset button to reset the image', async ({ page }) => {
|
test('Can use the reset button to reset the image', async ({ page }) => {
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
|
|
||||||
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
||||||
const zoomResetBtn = page.locator('.t-btn-zoom-reset').nth(0);
|
const zoomResetBtn = page.locator('.t-btn-zoom-reset').nth(0);
|
||||||
const initialBoundingBox = await bgImageLocator.boundingBox();
|
const initialBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
|
|
||||||
await zoomInBtn.click();
|
await zoomInBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await zoomInBtn.click();
|
await zoomInBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
|
|
||||||
const zoomedInBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedInBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect.soft(zoomedInBoundingBox.height).toBeGreaterThan(initialBoundingBox.height);
|
expect.soft(zoomedInBoundingBox.height).toBeGreaterThan(initialBoundingBox.height);
|
||||||
expect.soft(zoomedInBoundingBox.width).toBeGreaterThan(initialBoundingBox.width);
|
expect.soft(zoomedInBoundingBox.width).toBeGreaterThan(initialBoundingBox.width);
|
||||||
|
|
||||||
await zoomResetBtn.click();
|
await zoomResetBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
|
|
||||||
const resetBoundingBox = await bgImageLocator.boundingBox();
|
const resetBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect.soft(resetBoundingBox.height).toBeLessThan(zoomedInBoundingBox.height);
|
expect.soft(resetBoundingBox.height).toBeLessThan(zoomedInBoundingBox.height);
|
||||||
expect.soft(resetBoundingBox.width).toBeLessThan(zoomedInBoundingBox.width);
|
expect.soft(resetBoundingBox.width).toBeLessThan(zoomedInBoundingBox.width);
|
||||||
|
|
||||||
@ -213,10 +215,9 @@ test.describe('Example Imagery', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Using the zoom features does not pause telemetry', async ({ page }) => {
|
test('Using the zoom features does not pause telemetry', async ({ page }) => {
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
|
||||||
const pausePlayButton = page.locator('.c-button.pause-play');
|
const pausePlayButton = page.locator('.c-button.pause-play');
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
|
|
||||||
// open the time conductor drop down
|
// open the time conductor drop down
|
||||||
await page.locator('button:has-text("Fixed Timespan")').click();
|
await page.locator('button:has-text("Fixed Timespan")').click();
|
||||||
@ -227,7 +228,7 @@ test.describe('Example Imagery', () => {
|
|||||||
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
const zoomInBtn = page.locator('.t-btn-zoom-in').nth(0);
|
||||||
await zoomInBtn.click();
|
await zoomInBtn.click();
|
||||||
// wait for zoom animation to finish
|
// wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
|
|
||||||
return expect(pausePlayButton).not.toHaveClass(/is-paused/);
|
return expect(pausePlayButton).not.toHaveClass(/is-paused/);
|
||||||
});
|
});
|
||||||
@ -240,8 +241,8 @@ test.describe('Example Imagery', () => {
|
|||||||
// ('Clicking on the left arrow should pause the imagery and go to previous image');
|
// ('Clicking on the left arrow should pause the imagery and go to previous image');
|
||||||
// ('If the imagery view is in pause mode, it should not be updated when new images come in');
|
// ('If the imagery view is in pause mode, it should not be updated when new images come in');
|
||||||
// ('If the imagery view is not in pause mode, it should be updated when new images come in');
|
// ('If the imagery view is not in pause mode, it should be updated when new images come in');
|
||||||
const backgroundImageSelector = '.c-imagery__main-image__background-image';
|
test('Example Imagery in Display layout', async ({ page, browserName }) => {
|
||||||
test('Example Imagery in Display layout', async ({ page }) => {
|
test.fixme(browserName === 'firefox', 'This test needs to be updated to work with firefox');
|
||||||
test.info().annotations.push({
|
test.info().annotations.push({
|
||||||
type: 'issue',
|
type: 'issue',
|
||||||
description: 'https://github.com/nasa/openmct/issues/5265'
|
description: 'https://github.com/nasa/openmct/issues/5265'
|
||||||
@ -271,8 +272,7 @@ test('Example Imagery in Display layout', async ({ page }) => {
|
|||||||
// Wait until Save Banner is gone
|
// Wait until Save Banner is gone
|
||||||
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
||||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await bgImageLocator.hover({trial: true});
|
|
||||||
|
|
||||||
// Click previous image button
|
// Click previous image button
|
||||||
const previousImageButton = page.locator('.c-nav--prev');
|
const previousImageButton = page.locator('.c-nav--prev');
|
||||||
@ -284,15 +284,15 @@ test('Example Imagery in Display layout', async ({ page }) => {
|
|||||||
|
|
||||||
// Zoom in
|
// Zoom in
|
||||||
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const deltaYStep = 100; // equivalent to 1x zoom
|
const deltaYStep = 100; // equivalent to 1x zoom
|
||||||
await page.mouse.wheel(0, deltaYStep * 2);
|
await page.mouse.wheel(0, deltaYStep * 2);
|
||||||
const zoomedBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
||||||
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
||||||
|
|
||||||
// Wait for zoom animation to finish
|
// Wait for zoom animation to finish
|
||||||
await bgImageLocator.hover({trial: true});
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
||||||
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
|
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
|
||||||
@ -446,7 +446,8 @@ test.describe('Example imagery thumbnails resize in display layouts', () => {
|
|||||||
// test.fixme('If the imagery view is in pause mode, images still come in');
|
// test.fixme('If the imagery view is in pause mode, images still come in');
|
||||||
// test.fixme('If the imagery view is not in pause mode, it should be updated when new images come in');
|
// test.fixme('If the imagery view is not in pause mode, it should be updated when new images come in');
|
||||||
test.describe('Example Imagery in Flexible layout', () => {
|
test.describe('Example Imagery in Flexible layout', () => {
|
||||||
test('Example Imagery in Flexible layout', async ({ page }) => {
|
test('Example Imagery in Flexible layout', async ({ page, browserName }) => {
|
||||||
|
test.fixme(browserName === 'firefox', 'This test needs to be updated to work with firefox');
|
||||||
test.info().annotations.push({
|
test.info().annotations.push({
|
||||||
type: 'issue',
|
type: 'issue',
|
||||||
description: 'https://github.com/nasa/openmct/issues/5326'
|
description: 'https://github.com/nasa/openmct/issues/5326'
|
||||||
@ -475,8 +476,7 @@ test.describe('Example Imagery in Flexible layout', () => {
|
|||||||
// Wait until Save Banner is gone
|
// Wait until Save Banner is gone
|
||||||
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
||||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
|
||||||
const bgImageLocator = await page.locator(backgroundImageSelector);
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
await bgImageLocator.hover();
|
|
||||||
|
|
||||||
// Click the Create button
|
// Click the Create button
|
||||||
await page.click('button:has-text("Create")');
|
await page.click('button:has-text("Create")');
|
||||||
@ -487,15 +487,11 @@ test.describe('Example Imagery in Flexible layout', () => {
|
|||||||
// Assert Flexable layout
|
// Assert Flexable layout
|
||||||
await expect(page.locator('.js-form-title')).toHaveText('Create a New Flexible Layout');
|
await expect(page.locator('.js-form-title')).toHaveText('Create a New Flexible Layout');
|
||||||
|
|
||||||
// Click text=OK
|
await page.locator('form[name="mctForm"] >> text=My Items').click();
|
||||||
page.click('text=OK');
|
|
||||||
|
|
||||||
// Wait until Save Banner is gone
|
|
||||||
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
|
|
||||||
|
|
||||||
// Click My Items
|
// Click My Items
|
||||||
await page.locator('form[name="mctForm"] >> text=My Items').click();
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
page.locator('text=OK').click(),
|
||||||
page.waitForNavigation({waitUntil: 'networkidle'})
|
page.waitForNavigation({waitUntil: 'networkidle'})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -524,7 +520,7 @@ test.describe('Example Imagery in Flexible layout', () => {
|
|||||||
await mouseZoomIn(page);
|
await mouseZoomIn(page);
|
||||||
|
|
||||||
// Center the mouse pointer
|
// Center the mouse pointer
|
||||||
const zoomedBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedBoundingBox = await await page.locator(backgroundImageSelector).boundingBox();
|
||||||
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
||||||
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
||||||
await page.mouse.move(imageCenterX, imageCenterY);
|
await page.mouse.move(imageCenterX, imageCenterY);
|
||||||
@ -601,7 +597,7 @@ async function dragBrightnessSliderAndAssertFilterValues(page) {
|
|||||||
const brightnessMidX = brightnessBoundingBox.x + brightnessBoundingBox.width / 2;
|
const brightnessMidX = brightnessBoundingBox.x + brightnessBoundingBox.width / 2;
|
||||||
const brightnessMidY = brightnessBoundingBox.y + brightnessBoundingBox.height / 2;
|
const brightnessMidY = brightnessBoundingBox.y + brightnessBoundingBox.height / 2;
|
||||||
|
|
||||||
await page.locator(brightnessSlider).hover();
|
await page.locator(brightnessSlider).hover({trial: true});
|
||||||
await page.mouse.down();
|
await page.mouse.down();
|
||||||
await page.mouse.move(brightnessBoundingBox.x + brightnessBoundingBox.width, brightnessMidY);
|
await page.mouse.move(brightnessBoundingBox.x + brightnessBoundingBox.width, brightnessMidY);
|
||||||
await assertBackgroundImageBrightness(page, '500');
|
await assertBackgroundImageBrightness(page, '500');
|
||||||
@ -622,7 +618,7 @@ async function dragContrastSliderAndAssertFilterValues(page) {
|
|||||||
const contrastMidX = contrastBoundingBox.x + contrastBoundingBox.width / 2;
|
const contrastMidX = contrastBoundingBox.x + contrastBoundingBox.width / 2;
|
||||||
const contrastMidY = contrastBoundingBox.y + contrastBoundingBox.height / 2;
|
const contrastMidY = contrastBoundingBox.y + contrastBoundingBox.height / 2;
|
||||||
|
|
||||||
await page.locator(contrastSlider).hover();
|
await page.locator(contrastSlider).hover({trial: true});
|
||||||
await page.mouse.down();
|
await page.mouse.down();
|
||||||
await page.mouse.move(contrastBoundingBox.x + contrastBoundingBox.width, contrastMidY);
|
await page.mouse.move(contrastBoundingBox.x + contrastBoundingBox.width, contrastMidY);
|
||||||
await assertBackgroundImageContrast(page, '500');
|
await assertBackgroundImageContrast(page, '500');
|
||||||
@ -700,8 +696,7 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
const expectedAltText = process.platform === 'linux' ? 'Ctrl+Alt drag to pan' : 'Alt drag to pan';
|
const expectedAltText = process.platform === 'linux' ? 'Ctrl+Alt drag to pan' : 'Alt drag to pan';
|
||||||
const imageryHintsText = await page.locator('.c-imagery__hints').innerText();
|
const imageryHintsText = await page.locator('.c-imagery__hints').innerText();
|
||||||
expect(expectedAltText).toEqual(imageryHintsText);
|
expect(expectedAltText).toEqual(imageryHintsText);
|
||||||
const bgImageLocator = page.locator(backgroundImageSelector);
|
const zoomedBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
const zoomedBoundingBox = await bgImageLocator.boundingBox();
|
|
||||||
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
||||||
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
||||||
|
|
||||||
@ -711,7 +706,7 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
await page.mouse.move(imageCenterX - 200, imageCenterY, 10);
|
await page.mouse.move(imageCenterX - 200, imageCenterY, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterRightPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterRightPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(zoomedBoundingBox.x).toBeGreaterThan(afterRightPanBoundingBox.x);
|
expect(zoomedBoundingBox.x).toBeGreaterThan(afterRightPanBoundingBox.x);
|
||||||
|
|
||||||
// Pan left
|
// Pan left
|
||||||
@ -720,7 +715,7 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY, 10);
|
await page.mouse.move(imageCenterX, imageCenterY, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterLeftPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterLeftPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterRightPanBoundingBox.x).toBeLessThan(afterLeftPanBoundingBox.x);
|
expect(afterRightPanBoundingBox.x).toBeLessThan(afterLeftPanBoundingBox.x);
|
||||||
|
|
||||||
// Pan up
|
// Pan up
|
||||||
@ -730,7 +725,7 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY + 200, 10);
|
await page.mouse.move(imageCenterX, imageCenterY + 200, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterUpPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterUpPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterUpPanBoundingBox.y).toBeGreaterThanOrEqual(afterLeftPanBoundingBox.y);
|
expect(afterUpPanBoundingBox.y).toBeGreaterThanOrEqual(afterLeftPanBoundingBox.y);
|
||||||
|
|
||||||
// Pan down
|
// Pan down
|
||||||
@ -739,7 +734,7 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY - 200, 10);
|
await page.mouse.move(imageCenterX, imageCenterY - 200, 10);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
await Promise.all(panHotkey.map(x => page.keyboard.up(x)));
|
||||||
const afterDownPanBoundingBox = await bgImageLocator.boundingBox();
|
const afterDownPanBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(afterDownPanBoundingBox.y).toBeLessThanOrEqual(afterUpPanBoundingBox.y);
|
expect(afterDownPanBoundingBox.y).toBeLessThanOrEqual(afterUpPanBoundingBox.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,13 +742,12 @@ async function panZoomAndAssertImageProperties(page) {
|
|||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
*/
|
*/
|
||||||
async function mouseZoomIn(page) {
|
async function mouseZoomIn(page) {
|
||||||
const bgImageLocator = await page.locator(backgroundImageSelector);
|
|
||||||
// Zoom in
|
// Zoom in
|
||||||
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
await bgImageLocator.hover();
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const deltaYStep = 100; // equivalent to 1x zoom
|
const deltaYStep = 100; // equivalent to 1x zoom
|
||||||
await page.mouse.wheel(0, deltaYStep * 2);
|
await page.mouse.wheel(0, deltaYStep * 2);
|
||||||
const zoomedBoundingBox = await bgImageLocator.boundingBox();
|
const zoomedBoundingBox = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
|
||||||
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
|
||||||
|
|
||||||
@ -761,7 +755,7 @@ async function mouseZoomIn(page) {
|
|||||||
await page.mouse.move(imageCenterX, imageCenterY);
|
await page.mouse.move(imageCenterX, imageCenterY);
|
||||||
|
|
||||||
// Wait for zoom animation to finish
|
// Wait for zoom animation to finish
|
||||||
await bgImageLocator.hover();
|
await page.locator(backgroundImageSelector).hover({trial: true});
|
||||||
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
|
||||||
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
|
||||||
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
|
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
|
||||||
|
@ -27,108 +27,11 @@ const path = require('path');
|
|||||||
const TEST_TEXT = 'Testing text for entries.';
|
const TEST_TEXT = 'Testing text for entries.';
|
||||||
const TEST_TEXT_NAME = 'Test Page';
|
const TEST_TEXT_NAME = 'Test Page';
|
||||||
const CUSTOM_NAME = 'CUSTOM_NAME';
|
const CUSTOM_NAME = 'CUSTOM_NAME';
|
||||||
const COMMIT_BUTTON_TEXT = 'button:has-text("Commit Entries")';
|
|
||||||
const SINE_WAVE_GENERATOR = 'text=Unnamed Sine Wave Generator';
|
|
||||||
const NOTEBOOK_DROP_AREA = '.c-notebook__drag-area';
|
const NOTEBOOK_DROP_AREA = '.c-notebook__drag-area';
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import('@playwright/test').Page} page
|
|
||||||
*/
|
|
||||||
async function startAndAddNotebookObject(page) {
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
await page.addInitScript({ path: path.join(__dirname, 'addInitRestrictedNotebook.js') });
|
|
||||||
//Go to baseURL
|
|
||||||
await page.goto('/', { waitUntil: 'networkidle' });
|
|
||||||
//Click the Create button
|
|
||||||
await page.click('button:has-text("Create")');
|
|
||||||
// Click text=CUSTOME_NAME
|
|
||||||
await page.click(`text=${CUSTOM_NAME}`); // secondarily tests renamability also
|
|
||||||
// Click text=OK
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation({waitUntil: 'networkidle'}),
|
|
||||||
page.click('text=OK')
|
|
||||||
]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import('@playwright/test').Page} page
|
|
||||||
*/
|
|
||||||
async function enterTextEntry(page) {
|
|
||||||
// Click .c-notebook__drag-area
|
|
||||||
await page.locator(NOTEBOOK_DROP_AREA).click();
|
|
||||||
|
|
||||||
// enter text
|
|
||||||
await page.locator('div.c-ne__text').click();
|
|
||||||
await page.locator('div.c-ne__text').fill(TEST_TEXT);
|
|
||||||
await page.locator('div.c-ne__text').press('Enter');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import('@playwright/test').Page} page
|
|
||||||
*/
|
|
||||||
async function dragAndDropEmbed(page) {
|
|
||||||
// Click button:has-text("Create")
|
|
||||||
await page.locator('button:has-text("Create")').click();
|
|
||||||
// Click li:has-text("Sine Wave Generator")
|
|
||||||
await page.locator('li:has-text("Sine Wave Generator")').click();
|
|
||||||
// Click form[name="mctForm"] >> text=My Items
|
|
||||||
await page.locator('form[name="mctForm"] >> text=My Items').click();
|
|
||||||
// Click text=OK
|
|
||||||
await page.locator('text=OK').click();
|
|
||||||
// Click text=Open MCT My Items >> span >> nth=3
|
|
||||||
await page.locator('text=Open MCT My Items >> span').nth(3).click();
|
|
||||||
// Click text=Unnamed CUSTOM_NAME
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('text=Unnamed CUSTOM_NAME').click()
|
|
||||||
]);
|
|
||||||
|
|
||||||
await page.dragAndDrop(SINE_WAVE_GENERATOR, NOTEBOOK_DROP_AREA);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import('@playwright/test').Page} page
|
|
||||||
*/
|
|
||||||
async function lockPage(page) {
|
|
||||||
const commitButton = page.locator(COMMIT_BUTTON_TEXT);
|
|
||||||
await commitButton.click();
|
|
||||||
|
|
||||||
// confirmation dialog click
|
|
||||||
await page.locator('text=Lock Page').click();
|
|
||||||
|
|
||||||
// waiting for mutation of locked page
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import('@playwright/test').Page} page
|
|
||||||
*/
|
|
||||||
async function openContextMenuRestrictedNotebook(page) {
|
|
||||||
// Click text=Open MCT My Items (This expands the My Items folder to show it's chilren in the tree)
|
|
||||||
await page.locator('text=Open MCT My Items >> span').nth(3).click();
|
|
||||||
|
|
||||||
// Click a:has-text("Unnamed CUSTOM_NAME")
|
|
||||||
await page.locator(`a:has-text("Unnamed ${CUSTOM_NAME}")`).click({
|
|
||||||
button: 'right'
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('Restricted Notebook', () => {
|
test.describe('Restricted Notebook', () => {
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await startAndAddNotebookObject(page);
|
await startAndAddRestrictedNotebookObject(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can be renamed', async ({ page }) => {
|
test('Can be renamed', async ({ page }) => {
|
||||||
@ -146,13 +49,16 @@ test.describe('Restricted Notebook', () => {
|
|||||||
// notbook tree object exists
|
// notbook tree object exists
|
||||||
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1);
|
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1);
|
||||||
|
|
||||||
// Click text=Remove
|
// Click Remove Text
|
||||||
await page.locator('text=Remove').click();
|
await page.locator('text=Remove').click();
|
||||||
// Click text=OK
|
|
||||||
|
//Wait until Save Banner is gone
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.waitForNavigation(/*{ url: 'http://localhost:8080/#/browse/mine?tc.mode=fixed&tc.startBound=1653671067340&tc.endBound=1653672867340&tc.timeSystem=utc&view=grid' }*/),
|
page.waitForNavigation(),
|
||||||
page.locator('text=OK').click()
|
page.locator('text=OK').click(),
|
||||||
|
page.waitForSelector('.c-message-banner__message')
|
||||||
]);
|
]);
|
||||||
|
await page.locator('.c-message-banner__close-button').click();
|
||||||
|
|
||||||
// has been deleted
|
// has been deleted
|
||||||
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(0);
|
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(0);
|
||||||
@ -162,7 +68,7 @@ test.describe('Restricted Notebook', () => {
|
|||||||
|
|
||||||
await enterTextEntry(page);
|
await enterTextEntry(page);
|
||||||
|
|
||||||
const commitButton = page.locator(COMMIT_BUTTON_TEXT);
|
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||||
expect.soft(await commitButton.count()).toEqual(1);
|
expect.soft(await commitButton.count()).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -171,7 +77,7 @@ test.describe('Restricted Notebook', () => {
|
|||||||
test.describe('Restricted Notebook with at least one entry and with the page locked', () => {
|
test.describe('Restricted Notebook with at least one entry and with the page locked', () => {
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await startAndAddNotebookObject(page);
|
await startAndAddRestrictedNotebookObject(page);
|
||||||
await enterTextEntry(page);
|
await enterTextEntry(page);
|
||||||
await lockPage(page);
|
await lockPage(page);
|
||||||
|
|
||||||
@ -179,7 +85,7 @@ test.describe('Restricted Notebook with at least one entry and with the page loc
|
|||||||
await page.locator('button.c-notebook__toggle-nav-button').click();
|
await page.locator('button.c-notebook__toggle-nav-button').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Locked page should now be in a locked state', async ({ page }) => {
|
test.fixme('Locked page should now be in a locked state', async ({ page }) => {
|
||||||
// main lock message on page
|
// main lock message on page
|
||||||
const lockMessage = page.locator('text=This page has been committed and cannot be modified or removed');
|
const lockMessage = page.locator('text=This page has been committed and cannot be modified or removed');
|
||||||
expect.soft(await lockMessage.count()).toEqual(1);
|
expect.soft(await lockMessage.count()).toEqual(1);
|
||||||
@ -218,7 +124,7 @@ test.describe('Restricted Notebook with at least one entry and with the page loc
|
|||||||
await enterTextEntry(page);
|
await enterTextEntry(page);
|
||||||
|
|
||||||
// expect new page to be lockable
|
// expect new page to be lockable
|
||||||
const commitButton = page.locator(COMMIT_BUTTON_TEXT);
|
const commitButton = page.locator('BUTTON:HAS-TEXT("COMMIT ENTRIES")');
|
||||||
expect.soft(await commitButton.count()).toEqual(1);
|
expect.soft(await commitButton.count()).toEqual(1);
|
||||||
|
|
||||||
// Click text=Unnamed PageTest Page >> button
|
// Click text=Unnamed PageTest Page >> button
|
||||||
@ -240,7 +146,7 @@ test.describe('Restricted Notebook with at least one entry and with the page loc
|
|||||||
test.describe('Restricted Notebook with a page locked and with an embed', () => {
|
test.describe('Restricted Notebook with a page locked and with an embed', () => {
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await startAndAddNotebookObject(page);
|
await startAndAddRestrictedNotebookObject(page);
|
||||||
await dragAndDropEmbed(page);
|
await dragAndDropEmbed(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -262,3 +168,95 @@ test.describe('Restricted Notebook with a page locked and with an embed', () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
async function startAndAddRestrictedNotebookObject(page) {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
await page.addInitScript({ path: path.join(__dirname, 'addInitRestrictedNotebook.js') });
|
||||||
|
//Go to baseURL
|
||||||
|
await page.goto('/', { waitUntil: 'networkidle' });
|
||||||
|
//Click the Create button
|
||||||
|
await page.click('button:has-text("Create")');
|
||||||
|
// Click text=CUSTOME_NAME
|
||||||
|
await page.click(`text=${CUSTOM_NAME}`); // secondarily tests renamability also
|
||||||
|
// Click text=OK
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForNavigation({waitUntil: 'networkidle'}),
|
||||||
|
page.click('text=OK')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
async function enterTextEntry(page) {
|
||||||
|
// Click .c-notebook__drag-area
|
||||||
|
await page.locator(NOTEBOOK_DROP_AREA).click();
|
||||||
|
|
||||||
|
// enter text
|
||||||
|
await page.locator('div.c-ne__text').click();
|
||||||
|
await page.locator('div.c-ne__text').fill(TEST_TEXT);
|
||||||
|
await page.locator('div.c-ne__text').press('Enter');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
async function dragAndDropEmbed(page) {
|
||||||
|
// Click button:has-text("Create")
|
||||||
|
await page.locator('button:has-text("Create")').click();
|
||||||
|
// Click li:has-text("Sine Wave Generator")
|
||||||
|
await page.locator('li:has-text("Sine Wave Generator")').click();
|
||||||
|
// Click form[name="mctForm"] >> text=My Items
|
||||||
|
await page.locator('form[name="mctForm"] >> text=My Items').click();
|
||||||
|
// Click text=OK
|
||||||
|
await page.locator('text=OK').click();
|
||||||
|
// Click text=Open MCT My Items >> span >> nth=3
|
||||||
|
await page.locator('text=Open MCT My Items >> span').nth(3).click();
|
||||||
|
// Click text=Unnamed CUSTOM_NAME
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator('text=Unnamed CUSTOM_NAME').click()
|
||||||
|
]);
|
||||||
|
|
||||||
|
await page.dragAndDrop('text=UNNAMED SINE WAVE GENERATOR', NOTEBOOK_DROP_AREA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
async function lockPage(page) {
|
||||||
|
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||||
|
await commitButton.click();
|
||||||
|
|
||||||
|
//Wait until Lock Banner is visible
|
||||||
|
await Promise.all([
|
||||||
|
page.locator('text=Lock Page').click(),
|
||||||
|
page.waitForSelector('.c-message-banner__message')
|
||||||
|
]);
|
||||||
|
// Close Lock Banner
|
||||||
|
await page.locator('.c-message-banner__close-button').click();
|
||||||
|
|
||||||
|
//artifically wait to avoid mutation delay TODO: https://github.com/nasa/openmct/issues/5409
|
||||||
|
// eslint-disable-next-line playwright/no-wait-for-timeout
|
||||||
|
await page.waitForTimeout(1 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
*/
|
||||||
|
async function openContextMenuRestrictedNotebook(page) {
|
||||||
|
// Click text=Open MCT My Items (This expands the My Items folder to show it's chilren in the tree)
|
||||||
|
await page.locator('text=Open MCT My Items >> span').nth(3).click();
|
||||||
|
|
||||||
|
//artifically wait to avoid mutation delay TODO: https://github.com/nasa/openmct/issues/5409
|
||||||
|
// eslint-disable-next-line playwright/no-wait-for-timeout
|
||||||
|
await page.waitForTimeout(1 * 1000);
|
||||||
|
|
||||||
|
// Click a:has-text("Unnamed CUSTOM_NAME")
|
||||||
|
await page.locator(`a:has-text("Unnamed ${CUSTOM_NAME}")`).click({
|
||||||
|
button: 'right'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -24,22 +24,9 @@
|
|||||||
Testsuite for plot autoscale.
|
Testsuite for plot autoscale.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { test: _test } = require('../../../fixtures.js');
|
const { test } = require('../../../fixtures.js');
|
||||||
const { expect } = require('@playwright/test');
|
const { expect } = require('@playwright/test');
|
||||||
|
|
||||||
// create a new `test` API that will not append platform details to snapshot
|
|
||||||
// file names, only for the tests in this file, so that the same snapshots will
|
|
||||||
// be used for all platforms.
|
|
||||||
const test = _test.extend({
|
|
||||||
_autoSnapshotSuffix: [
|
|
||||||
async ({}, use, testInfo) => {
|
|
||||||
testInfo.snapshotSuffix = '';
|
|
||||||
await use();
|
|
||||||
},
|
|
||||||
{ auto: true }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
test.use({
|
test.use({
|
||||||
viewport: {
|
viewport: {
|
||||||
width: 1280,
|
width: 1280,
|
||||||
@ -50,7 +37,7 @@ test.use({
|
|||||||
test.describe('ExportAsJSON', () => {
|
test.describe('ExportAsJSON', () => {
|
||||||
test('User can set autoscale with a valid range @snapshot', async ({ page }) => {
|
test('User can set autoscale with a valid range @snapshot', async ({ page }) => {
|
||||||
//This is necessary due to the size of the test suite.
|
//This is necessary due to the size of the test suite.
|
||||||
await test.setTimeout(120 * 1000);
|
test.slow();
|
||||||
|
|
||||||
await page.goto('/', { waitUntil: 'networkidle' });
|
await page.goto('/', { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
@ -62,16 +49,16 @@ test.describe('ExportAsJSON', () => {
|
|||||||
|
|
||||||
await turnOffAutoscale(page);
|
await turnOffAutoscale(page);
|
||||||
|
|
||||||
|
// Make sure that after turning off autoscale, the user selected range values start at the same values the plot had prior.
|
||||||
|
await testYTicks(page, ['-1.00', '-0.50', '0.00', '0.50', '1.00']);
|
||||||
|
|
||||||
const canvas = page.locator('canvas').nth(1);
|
const canvas = page.locator('canvas').nth(1);
|
||||||
|
|
||||||
// Make sure that after turning off autoscale, the user selected range values start at the same values the plot had prior.
|
await canvas.hover({trial: true});
|
||||||
await Promise.all([
|
|
||||||
testYTicks(page, ['-1.00', '-0.50', '0.00', '0.50', '1.00']),
|
|
||||||
new Promise(r => setTimeout(r, 100))
|
|
||||||
.then(() => canvas.screenshot())
|
|
||||||
.then(shot => expect(shot).toMatchSnapshot('autoscale-canvas-prepan.png', { maxDiffPixels: 40 }))
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
expect(await canvas.screenshot()).toMatchSnapshot('autoscale-canvas-prepan');
|
||||||
|
|
||||||
|
//Alt Drag Start
|
||||||
await page.keyboard.down('Alt');
|
await page.keyboard.down('Alt');
|
||||||
|
|
||||||
await canvas.dragTo(canvas, {
|
await canvas.dragTo(canvas, {
|
||||||
@ -85,15 +72,15 @@ test.describe('ExportAsJSON', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Alt Drag End
|
||||||
await page.keyboard.up('Alt');
|
await page.keyboard.up('Alt');
|
||||||
|
|
||||||
// Ensure the drag worked.
|
// Ensure the drag worked.
|
||||||
await Promise.all([
|
await testYTicks(page, ['0.00', '0.50', '1.00', '1.50', '2.00']);
|
||||||
testYTicks(page, ['0.00', '0.50', '1.00', '1.50', '2.00']),
|
|
||||||
new Promise(r => setTimeout(r, 100))
|
await canvas.hover({trial: true});
|
||||||
.then(() => canvas.screenshot())
|
|
||||||
.then(shot => expect(shot).toMatchSnapshot('autoscale-canvas-panned.png', { maxDiffPixels: 40 }))
|
expect(await canvas.screenshot()).toMatchSnapshot('autoscale-canvas-panned');
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB |
@ -30,8 +30,8 @@ const { expect } = require('@playwright/test');
|
|||||||
|
|
||||||
test.describe('Log plot tests', () => {
|
test.describe('Log plot tests', () => {
|
||||||
test('Log Plot ticks are functionally correct in regular and log mode and after refresh', async ({ page }) => {
|
test('Log Plot ticks are functionally correct in regular and log mode and after refresh', async ({ page }) => {
|
||||||
//This is necessary due to the size of the test suite.
|
//Test.slow decorator is currently broken. Needs to be fixed in https://github.com/nasa/openmct/issues/5374
|
||||||
await test.setTimeout(120 * 1000);
|
test.slow();
|
||||||
|
|
||||||
await makeOverlayPlot(page);
|
await makeOverlayPlot(page);
|
||||||
await testRegularTicks(page);
|
await testRegularTicks(page);
|
||||||
@ -44,20 +44,6 @@ test.describe('Log plot tests', () => {
|
|||||||
await testLogTicks(page);
|
await testLogTicks(page);
|
||||||
await saveOverlayPlot(page);
|
await saveOverlayPlot(page);
|
||||||
await testLogTicks(page);
|
await testLogTicks(page);
|
||||||
//await testLogPlotPixels(page);
|
|
||||||
|
|
||||||
// FIXME: Get rid of the waitForTimeout() and lint warning exception.
|
|
||||||
// eslint-disable-next-line playwright/no-wait-for-timeout
|
|
||||||
await page.waitForTimeout(1 * 1000);
|
|
||||||
|
|
||||||
// refresh page and wait for charts and ticks to load
|
|
||||||
await page.reload({ waitUntil: 'networkidle'});
|
|
||||||
await page.waitForSelector('.gl-plot-chart-area');
|
|
||||||
await page.waitForSelector('.gl-plot-y-tick-label');
|
|
||||||
|
|
||||||
// test log ticks hold up after refresh
|
|
||||||
await testLogTicks(page);
|
|
||||||
//await testLogPlotPixels(page);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Leaving test as 'TODO' for now.
|
// Leaving test as 'TODO' for now.
|
||||||
@ -121,14 +107,14 @@ async function makeOverlayPlot(page) {
|
|||||||
|
|
||||||
// set amplitude to 6, offset 4, period 2
|
// set amplitude to 6, offset 4, period 2
|
||||||
|
|
||||||
await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
|
await page.locator('div:nth-child(5) .c-form-row__controls .form-control .field input').click();
|
||||||
await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').fill('6');
|
await page.locator('div:nth-child(5) .c-form-row__controls .form-control .field input').fill('6');
|
||||||
|
|
||||||
await page.locator('div:nth-child(6) .form-row .c-form-row__controls .form-control .field input').click();
|
await page.locator('div:nth-child(6) .c-form-row__controls .form-control .field input').click();
|
||||||
await page.locator('div:nth-child(6) .form-row .c-form-row__controls .form-control .field input').fill('4');
|
await page.locator('div:nth-child(6) .c-form-row__controls .form-control .field input').fill('4');
|
||||||
|
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').click();
|
await page.locator('div:nth-child(7) .c-form-row__controls .form-control .field input').click();
|
||||||
await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').fill('2');
|
await page.locator('div:nth-child(7) .c-form-row__controls .form-control .field input').fill('2');
|
||||||
|
|
||||||
// Click OK to make generator
|
// Click OK to make generator
|
||||||
|
|
||||||
|
@ -4,19 +4,19 @@
|
|||||||
{
|
{
|
||||||
"origin": "http://localhost:8080",
|
"origin": "http://localhost:8080",
|
||||||
"localStorage": [
|
"localStorage": [
|
||||||
|
{
|
||||||
|
"name": "mct-tree-expanded",
|
||||||
|
"value": "[]"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tcHistory",
|
"name": "tcHistory",
|
||||||
"value": "{\"utc\":[{\"start\":1652301954635,\"end\":1652303754635}]}"
|
"value": "{\"utc\":[{\"start\":1656473493306,\"end\":1656475293306},{\"start\":1655769110258,\"end\":1655770910258},{\"start\":1652301954635,\"end\":1652303754635}]}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mct",
|
"name": "mct",
|
||||||
"value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"persisted\":1652303756008,\"modified\":1652303756007},\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\":{\"name\":\"Unnamed Condition Set\",\"type\":\"conditionSet\",\"identifier\":{\"key\":\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\",\"namespace\":\"\"},\"configuration\":{\"conditionTestData\":[],\"conditionCollection\":[{\"isDefault\":true,\"id\":\"73f2d9ae-d1f3-4561-b7fc-ecd5df557249\",\"configuration\":{\"name\":\"Default\",\"output\":\"Default\",\"trigger\":\"all\",\"criteria\":[]},\"summary\":\"Default condition\"}]},\"composition\":[],\"telemetry\":{},\"modified\":1652303755999,\"location\":\"mine\",\"persisted\":1652303756002}}"
|
"value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\",\"namespace\":\"\"},{\"key\":\"18ba28bf-152e-4e0f-9b9c-638fb2ade0c3\",\"namespace\":\"\"},{\"key\":\"fa64bd6c-9351-4d94-a54e-e062a93be3b6\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"persisted\":1656475294042,\"modified\":1656475294042},\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\":{\"name\":\"Unnamed Condition Set\",\"type\":\"conditionSet\",\"identifier\":{\"key\":\"f64bea3b-58a7-4586-8c05-8b651e5f0bfd\",\"namespace\":\"\"},\"configuration\":{\"conditionTestData\":[],\"conditionCollection\":[{\"isDefault\":true,\"id\":\"73f2d9ae-d1f3-4561-b7fc-ecd5df557249\",\"configuration\":{\"name\":\"Default\",\"output\":\"Default\",\"trigger\":\"all\",\"criteria\":[]},\"summary\":\"Default condition\"}]},\"composition\":[],\"telemetry\":{},\"modified\":1652303755999,\"location\":\"mine\",\"persisted\":1652303756002},\"18ba28bf-152e-4e0f-9b9c-638fb2ade0c3\":{\"name\":\"Unnamed Condition Set\",\"type\":\"conditionSet\",\"identifier\":{\"key\":\"18ba28bf-152e-4e0f-9b9c-638fb2ade0c3\",\"namespace\":\"\"},\"configuration\":{\"conditionTestData\":[],\"conditionCollection\":[{\"isDefault\":true,\"id\":\"43cfb4b1-348c-43c0-a681-c4cf53b5335f\",\"configuration\":{\"name\":\"Default\",\"output\":\"Default\",\"trigger\":\"all\",\"criteria\":[]},\"summary\":\"Default condition\"}]},\"composition\":[],\"telemetry\":{},\"modified\":1655770911020,\"location\":\"mine\",\"persisted\":1655770911020},\"fa64bd6c-9351-4d94-a54e-e062a93be3b6\":{\"name\":\"Unnamed Condition Set\",\"type\":\"conditionSet\",\"identifier\":{\"key\":\"fa64bd6c-9351-4d94-a54e-e062a93be3b6\",\"namespace\":\"\"},\"configuration\":{\"conditionTestData\":[],\"conditionCollection\":[{\"isDefault\":true,\"id\":\"26739ce0-9a56-466c-91dd-f08bd9bfc9d7\",\"configuration\":{\"name\":\"Default\",\"output\":\"Default\",\"trigger\":\"all\",\"criteria\":[]},\"summary\":\"Default condition\"}]},\"composition\":[],\"telemetry\":{},\"modified\":1656475294040,\"location\":\"mine\",\"persisted\":1656475294040}}"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mct-tree-expanded",
|
|
||||||
"value": "[]"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -45,6 +45,15 @@ test('Verify that the create button appears and that the Folder Domain Object is
|
|||||||
await page.click('button:has-text("Create")');
|
await page.click('button:has-text("Create")');
|
||||||
|
|
||||||
// Verify that Create Folder appears in the dropdown
|
// Verify that Create Folder appears in the dropdown
|
||||||
const locator = page.locator(':nth-match(:text("Folder"), 2)');
|
await expect(page.locator(':nth-match(:text("Folder"), 2)')).toBeEnabled();
|
||||||
await expect(locator).toBeEnabled();
|
});
|
||||||
|
|
||||||
|
test('Verify that My Items Tree appears @ipad', async ({ page }) => {
|
||||||
|
//Test.slow annotation is currently broken. Needs to be fixed in https://github.com/nasa/openmct/issues/5374
|
||||||
|
test.slow();
|
||||||
|
//Go to baseURL
|
||||||
|
await page.goto('/');
|
||||||
|
|
||||||
|
//My Items to be visible
|
||||||
|
await expect(page.locator('a:has-text("My Items")')).toBeEnabled();
|
||||||
});
|
});
|
||||||
|
@ -32,7 +32,8 @@ to "fail" on assertions. Instead, they should be used to detect changes between
|
|||||||
Note: Larger testsuite sizes are OK due to the setup time associated with these tests.
|
Note: Larger testsuite sizes are OK due to the setup time associated with these tests.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { test, expect } = require('@playwright/test');
|
const { test } = require('../../fixtures.js');
|
||||||
|
const { expect } = require('@playwright/test');
|
||||||
const percySnapshot = require('@percy/playwright');
|
const percySnapshot = require('@percy/playwright');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const sinon = require('sinon');
|
const sinon = require('sinon');
|
||||||
@ -96,7 +97,11 @@ test('Visual - Default Condition Set', async ({ page }) => {
|
|||||||
await percySnapshot(page, 'Default Condition Set');
|
await percySnapshot(page, 'Default Condition Set');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Visual - Default Condition Widget', async ({ page }) => {
|
test.fixme('Visual - Default Condition Widget', async ({ page }) => {
|
||||||
|
test.info().annotations.push({
|
||||||
|
type: 'issue',
|
||||||
|
description: 'https://github.com/nasa/openmct/issues/5349'
|
||||||
|
});
|
||||||
//Go to baseURL
|
//Go to baseURL
|
||||||
await page.goto('/', { waitUntil: 'networkidle' });
|
await page.goto('/', { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
|
@ -74,13 +74,8 @@ module.exports = (config) => {
|
|||||||
},
|
},
|
||||||
coverageIstanbulReporter: {
|
coverageIstanbulReporter: {
|
||||||
fixWebpackSourcePaths: true,
|
fixWebpackSourcePaths: true,
|
||||||
dir: "dist/reports/coverage",
|
dir: "coverage/unit",
|
||||||
reports: ['lcovonly', 'text-summary'],
|
reports: ['lcovonly']
|
||||||
thresholds: {
|
|
||||||
global: {
|
|
||||||
lines: 52
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
specReporter: {
|
specReporter: {
|
||||||
maxLogLines: 5,
|
maxLogLines: 5,
|
||||||
|
11
package.json
11
package.json
@ -7,7 +7,7 @@
|
|||||||
"@braintree/sanitize-url": "6.0.0",
|
"@braintree/sanitize-url": "6.0.0",
|
||||||
"@percy/cli": "1.2.1",
|
"@percy/cli": "1.2.1",
|
||||||
"@percy/playwright": "1.0.4",
|
"@percy/playwright": "1.0.4",
|
||||||
"@playwright/test": "1.21.1",
|
"@playwright/test": "1.23.0",
|
||||||
"@types/eventemitter3": "^1.0.0",
|
"@types/eventemitter3": "^1.0.0",
|
||||||
"@types/jasmine": "^4.0.1",
|
"@types/jasmine": "^4.0.1",
|
||||||
"@types/karma": "^6.3.2",
|
"@types/karma": "^6.3.2",
|
||||||
@ -16,6 +16,7 @@
|
|||||||
"babel-loader": "8.2.5",
|
"babel-loader": "8.2.5",
|
||||||
"babel-plugin-istanbul": "6.1.1",
|
"babel-plugin-istanbul": "6.1.1",
|
||||||
"comma-separated-values": "3.6.4",
|
"comma-separated-values": "3.6.4",
|
||||||
|
"codecov":"3.8.3",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"copy-webpack-plugin": "11.0.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"css-loader": "4.0.0",
|
"css-loader": "4.0.0",
|
||||||
@ -54,6 +55,7 @@
|
|||||||
"moment-duration-format": "2.3.2",
|
"moment-duration-format": "2.3.2",
|
||||||
"moment-timezone": "0.5.34",
|
"moment-timezone": "0.5.34",
|
||||||
"node-bourbon": "4.2.3",
|
"node-bourbon": "4.2.3",
|
||||||
|
"nyc":"15.1.0",
|
||||||
"painterro": "1.2.78",
|
"painterro": "1.2.78",
|
||||||
"plotly.js-basic-dist": "2.12.0",
|
"plotly.js-basic-dist": "2.12.0",
|
||||||
"plotly.js-gl2d-dist": "2.12.0",
|
"plotly.js-gl2d-dist": "2.12.0",
|
||||||
@ -89,9 +91,10 @@
|
|||||||
"test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run",
|
"test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run",
|
||||||
"test:firefox": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run --browsers=FirefoxHeadless",
|
"test:firefox": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run --browsers=FirefoxHeadless",
|
||||||
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
|
||||||
|
"test:e2e": "npx playwright test",
|
||||||
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke branding default condition timeConductor clock exampleImagery persistence performance",
|
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke branding default condition timeConductor clock exampleImagery persistence performance",
|
||||||
"test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome",
|
"test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome",
|
||||||
"test:e2e:updatesnapshots": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome --grep @snapshot --update-snapshots",
|
"test:e2e:updatesnapshots": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome --grep @snapshot --update-snapshots",
|
||||||
"test:e2e:visual": "percy exec --config ./e2e/.percy.yml -- npx playwright test --config=e2e/playwright-visual.config.js",
|
"test:e2e:visual": "percy exec --config ./e2e/.percy.yml -- npx playwright test --config=e2e/playwright-visual.config.js",
|
||||||
"test:e2e:full": "npx playwright test --config=e2e/playwright-ci.config.js",
|
"test:e2e:full": "npx playwright test --config=e2e/playwright-ci.config.js",
|
||||||
"test:perf": "npx playwright test --config=e2e/playwright-performance.config.js",
|
"test:perf": "npx playwright test --config=e2e/playwright-performance.config.js",
|
||||||
@ -101,6 +104,10 @@
|
|||||||
"update-copyright-date": "npm run update-about-dialog-copyright && grep -lr --null --include=*.{js,scss,vue,ts,sh,html,md,frag} 'Copyright (c) 20' . | xargs -r0 perl -pi -e 's/Copyright\\s\\(c\\)\\s20\\d\\d\\-20\\d\\d/Copyright \\(c\\)\\ 2014\\-2022/gm'",
|
"update-copyright-date": "npm run update-about-dialog-copyright && grep -lr --null --include=*.{js,scss,vue,ts,sh,html,md,frag} 'Copyright (c) 20' . | xargs -r0 perl -pi -e 's/Copyright\\s\\(c\\)\\s20\\d\\d\\-20\\d\\d/Copyright \\(c\\)\\ 2014\\-2022/gm'",
|
||||||
"otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'",
|
"otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'",
|
||||||
"docs": "npm run jsdoc ; npm run otherdoc",
|
"docs": "npm run jsdoc ; npm run otherdoc",
|
||||||
|
"cov:e2e:report":"nyc report --reporter=lcovonly --report-dir=./coverage/e2e",
|
||||||
|
"cov:e2e:full:publish":"codecov --disable=gcov -f ./coverage/e2e/lcov.info -F e2e-full",
|
||||||
|
"cov:e2e:ci:publish":"codecov --disable=gcov -f ./coverage/e2e/lcov.info -F e2e-ci",
|
||||||
|
"cov:unit:publish":"codecov --disable=gcov -f ./coverage/unit/lcov.info -F unit",
|
||||||
"prepare": "npm run build:prod"
|
"prepare": "npm run build:prod"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -94,8 +94,13 @@ const config = {
|
|||||||
{
|
{
|
||||||
loader: 'css-loader'
|
loader: 'css-loader'
|
||||||
},
|
},
|
||||||
'resolve-url-loader',
|
{
|
||||||
'sass-loader'
|
loader: 'resolve-url-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
options: {sourceMap: true }
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ config.module.rules.push({
|
|||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
options: {
|
options: {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
configFile: path.resolve(process.cwd(), 'babel.coverage.js')
|
configFile: path.resolve(process.cwd(), 'babel.coverage.js')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user