* fix: resize conductor properly * refactor: more computed properties, unregister listener * fix: beforeUnmounted hook * test(visual): add time conductor visual test for fixed mode * fix: initialize to `null` * feat: extend the base `screenshot` function to mask elements which will always create variance in an Open MCT screenshot * docs: add types for fixtures * fix: remove unneeded await * chore: add sinon timers types package back * docs: remove unused docs * doc: remove unused docs * test: add visual realtime url, update imports * feat: provide wrapped page.screenshot fixture that applies defaults * test: add basic timeConductor snapshot tests * chore: update eslint config * lint: remove unused disable directives * test: remove redundant navigation * fix: remove listeners * fix: maybe stabilize unit tests * docs: remove * fix: provide sourcemaps in unit tests * test: add regression snapshot test for time conductor axis * lint: remove unused imports * feat(e2e): add fixture to manually tick the clock and use it * test: reactivate test now that we don't use deploysentinel :( * test: update snapshots * test: add test for clockOptions and tick fixtures * test: add afterEach stub and fixme * test: try and stabilize fault management flake * lint: defy the word gods * chore: ignore `*-darwin.png` screenshots * chore: remove darwin screenshot binaries * docs: markdownlint * docs: remove MacOS specific instructions from snapshot testing * fix: remove a11y
@ -1,10 +1,13 @@
|
||||
const LEGACY_FILES = ['example/**'];
|
||||
module.exports = {
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
const config = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
es2024: true,
|
||||
jasmine: true,
|
||||
amd: true
|
||||
node: true,
|
||||
worker: true,
|
||||
serviceworker: true
|
||||
},
|
||||
globals: {
|
||||
_: 'readonly'
|
||||
@ -23,10 +26,11 @@ module.exports = {
|
||||
parser: '@babel/eslint-parser',
|
||||
requireConfigFile: false,
|
||||
allowImportExportEverywhere: true,
|
||||
ecmaVersion: 2015,
|
||||
ecmaVersion: 'latest',
|
||||
ecmaFeatures: {
|
||||
impliedStrict: true
|
||||
}
|
||||
},
|
||||
sourceType: 'module'
|
||||
},
|
||||
rules: {
|
||||
'simple-import-sort/imports': 'warn',
|
||||
@ -152,7 +156,7 @@ module.exports = {
|
||||
cases: {
|
||||
pascalCase: true
|
||||
},
|
||||
ignore: ['^.*\\.js$']
|
||||
ignore: ['^.*\\.(js|cjs|mjs)$']
|
||||
}
|
||||
],
|
||||
'vue/first-attribute-linebreak': 'error',
|
||||
@ -179,3 +183,5 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
3
.gitignore
vendored
@ -47,3 +47,6 @@ index.html.bak
|
||||
.nyc_output
|
||||
coverage
|
||||
codecov
|
||||
|
||||
# Don't commit MacOS screenshots
|
||||
*-darwin.png
|
||||
|
@ -76,28 +76,30 @@ To read about how to write a good visual test, please see [How to write a great
|
||||
|
||||
`npm run test:e2e:visual` commands will run all of the visual tests against a local instance of Open MCT. If no `PERCY_TOKEN` API key is found in the terminal or command line environment variables, no visual comparisons will be made.
|
||||
|
||||
- `npm run test:e2e:visual:ci` will run against every commit and PR.
|
||||
- `npm run test:e2e:visual:full` will run every night with additional comparisons made for Larger Displays and with the `snow` theme.
|
||||
- `npm run test:e2e:visual:ci` will run against every commit and PR.
|
||||
- `npm run test:e2e:visual:full` will run every night with additional comparisons made for Larger Displays and with the `snow` theme.
|
||||
|
||||
#### Percy.io
|
||||
|
||||
To make this possible, we're leveraging a 3rd party service, [Percy](https://percy.io/). This service maintains a copy of all changes, users, scm-metadata, and baselines to verify that the application looks and feels the same _unless approved by a Open MCT developer_. To request a Percy API token, please reach out to the Open MCT Dev team on GitHub. For more information, please see the official [Percy documentation](https://docs.percy.io/docs/visual-testing-basics).
|
||||
|
||||
At present, we are using percy with two configuration files: `./e2e/.percy.nightly.yml` and `./e2e/.percy.ci.yml`. This is mainly to reduce the number of snapshots.
|
||||
At present, we are using percy with two configuration files: `./e2e/.percy.nightly.yml` and `./e2e/.percy.ci.yml`. This is mainly to reduce the number of snapshots.
|
||||
|
||||
### Advanced: Snapshot Testing (Not Recommended)
|
||||
|
||||
While snapshot testing offers a precise way to detect changes in your application without relying on third-party services like Percy.io, we've found that it doesn't offer any advantages over visual testing in our use-cases. Therefore, snapshot testing is **not recommended** for further implementation.
|
||||
|
||||
#### CI vs Manual Checks
|
||||
|
||||
Snapshot tests can be reliably executed in Continuous Integration (CI) environments but lack the manual oversight provided by visual testing platforms like Percy.io. This means they may miss issues that a human reviewer could catch during manual checks.
|
||||
|
||||
#### Example
|
||||
|
||||
A single visual test assertion in Percy.io can be executed across 10 different browser and resolution combinations without additional setup, providing comprehensive testing with minimal configuration. In contrast, a snapshot test is restricted to a single OS and browser resolution, requiring more effort to achieve the same level of coverage.
|
||||
|
||||
|
||||
#### Further Reading
|
||||
For those interested in the mechanics of snapshot testing with Playwright, you can refer to the [Playwright Snapshots Documentation](https://playwright.dev/docs/test-snapshots). However, keep in mind that we do not recommend using this approach.
|
||||
|
||||
For those interested in the mechanics of snapshot testing with Playwright, you can refer to the [Playwright Snapshots Documentation](https://playwright.dev/docs/test-snapshots). However, keep in mind that we do not recommend using this approach.
|
||||
|
||||
#### Open MCT's implementation
|
||||
|
||||
@ -118,14 +120,6 @@ When the `@snapshot` tests fail, they will need to be evaluated to determine if
|
||||
|
||||
To compare a snapshot, run a test and open the html report with the 'Expected' vs 'Actual' screenshot. If the actual screenshot is preferred, then the source-controlled 'Expected' snapshots will need to be updated with the following scripts.
|
||||
|
||||
MacOS
|
||||
|
||||
```
|
||||
npm run test:e2e:updatesnapshots
|
||||
```
|
||||
|
||||
Linux/CI
|
||||
|
||||
```sh
|
||||
// Replace {X.X.X} with the current Playwright version
|
||||
// from our package.json or circleCI configuration file
|
||||
@ -335,9 +329,11 @@ We have a Mission-need to support iPad and mobile devices. To run our test suite
|
||||
In general, our test suite is not designed to run against mobile devices as the mobile experience is a focused version of the application. Core functionality is missing (chiefly the 'Create' button). To bypass the object creation, we leverage the `storageState` properties for starting the mobile tests with localstorage.
|
||||
|
||||
For now, the mobile tests will exist in the /tests/mobile/ suites and be executed with the
|
||||
|
||||
```sh
|
||||
npm run test:e2e:mobile
|
||||
```
|
||||
|
||||
command.
|
||||
|
||||
#### **Skipping or executing tests based on browser, os, and/os browser version:**
|
||||
@ -377,6 +373,7 @@ In general, strive to test only through the UI as a user would. As stated in the
|
||||
By adhering to this principle, we can create tests that are both robust and reflective of actual user experiences.
|
||||
|
||||
#### How to make tests robust to function in other contexts (VISTA, COUCHDB, YAMCS, VIPER, etc.)
|
||||
|
||||
1. Leverage the use of `appActions.js` methods such as `createDomainObjectWithDefaults()`. This ensures that your tests will create unique instances of objects for your test to interact with.
|
||||
1. Do not assert on the order or structure of objects available unless you created them yourself. These tests may be used against a persistent datastore like couchdb with many objects in the tree.
|
||||
1. Do not search for your created objects. Open MCT does not performance uniqueness checks so it's possible that your tests will break when run twice.
|
||||
@ -384,6 +381,7 @@ By adhering to this principle, we can create tests that are both robust and refl
|
||||
1. Leverage `await page.goto('./', { waitUntil: 'domcontentloaded' });` instead of `{ waitUntil: 'networkidle' }`. Tests run against deployments with websockets often have issues with the networkidle detection.
|
||||
|
||||
#### How to make tests faster and more resilient
|
||||
|
||||
1. Avoid app interaction when possible. The best way of doing this is to navigate directly by URL:
|
||||
|
||||
```js
|
||||
@ -396,10 +394,11 @@ By adhering to this principle, we can create tests that are both robust and refl
|
||||
|
||||
1. Leverage `await page.goto('./', { waitUntil: 'domcontentloaded' });`
|
||||
- Initial navigation should _almost_ always use the `{ waitUntil: 'domcontentloaded' }` option.
|
||||
1. Avoid repeated setup to test a single assertion. Write longer tests with multiple soft assertions.
|
||||
1. Avoid repeated setup to test a single assertion. Write longer tests with multiple soft assertions.
|
||||
This ensures that your changes will be picked up with large refactors.
|
||||
|
||||
##### Utilizing LocalStorage
|
||||
|
||||
1. In order to save test runtime in the case of tests that require a decent amount of initial setup (such as in the case of testing complex displays), you may use [Playwright's `storageState` feature](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state) to generate and load localStorage states.
|
||||
1. To generate a localStorage state to be used in a test:
|
||||
- Add an e2e test to our generateLocalStorageData suite which sets the initial state (creating/configuring objects, etc.), saving it in the `test-data` folder:
|
||||
@ -420,7 +419,6 @@ By adhering to this principle, we can create tests that are both robust and refl
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### How to write a great test
|
||||
|
||||
- Avoid using css locators to find elements to the page. Use modern web accessible locators like `getByRole`
|
||||
@ -436,7 +434,7 @@ By adhering to this principle, we can create tests that are both robust and refl
|
||||
await notesInput.fill(testNotes);
|
||||
```
|
||||
|
||||
#### How to Write a Great Visual Test
|
||||
#### How to Write a Great Visual Test
|
||||
|
||||
1. **Look for the Unknown Unknowns**: Avoid asserting on specific differences in the visual diff. Visual tests are most effective for identifying unknown unknowns.
|
||||
|
||||
@ -445,23 +443,27 @@ By adhering to this principle, we can create tests that are both robust and refl
|
||||
3. **Expect the Unexpected**: Use functional expect statements only to verify assumptions about the state between steps. A great visual test doesn't fail during the test itself, but rather when changes are reviewed in Percy.io.
|
||||
|
||||
4. **Control Variability**: Account for variations inherent in working with time-based telemetry and clocks.
|
||||
- Utilize `percyCSS` to ignore time-based elements. For more details, consult our [percyCSS file](./.percy.ci.yml).
|
||||
- Use Open MCT's fixed-time mode unless explicitly testing realtime clock
|
||||
- Employ the `createExampleTelemetryObject` appAction to source telemetry and specify a `name` to avoid autogenerated names.
|
||||
- Avoid creating objects with a time component like timers and clocks.
|
||||
|
||||
- Utilize `percyCSS` to ignore time-based elements. For more details, consult our [percyCSS file](./.percy.ci.yml).
|
||||
- Use Open MCT's fixed-time mode unless explicitly testing realtime clock
|
||||
- Employ the `createExampleTelemetryObject` appAction to source telemetry and specify a `name` to avoid autogenerated names.
|
||||
- Avoid creating objects with a time component like timers and clocks.
|
||||
|
||||
5. **Hide the Tree and Inspector**: Generally, your test will not require comparisons involving the tree and inspector. These aspects are covered in component-specific tests (explained below). To exclude them from the comparison by default, navigate to the root of the main view with the tree and inspector hidden:
|
||||
- `await page.goto('./#/browse/mine?hideTree=true&hideInspector=true')`
|
||||
|
||||
6. **Component-Specific Tests**: If you wish to focus on a particular component, use the `/visual-a11y/component/` folder and limit the scope of the comparison to that component. For instance:
|
||||
|
||||
```js
|
||||
await percySnapshot(page, `Tree Pane w/ single level expanded (theme: ${theme})`, {
|
||||
scope: treePane
|
||||
});
|
||||
```
|
||||
|
||||
- Note: The `scope` variable can be any valid CSS selector.
|
||||
|
||||
7. **Write many `percySnapshot` commands in a single test**: In line with our approach to longer functional tests, we recommend that many test percySnapshots are taken in a single test. For instance:
|
||||
|
||||
```js
|
||||
//<Some interesting state>
|
||||
await percySnapshot(page, `Before object expanded (theme: ${theme})`);
|
||||
@ -511,6 +513,7 @@ test.describe('foo test suite', () => {
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
More info and options for `overrideClock` can be found in [baseFixtures.js](baseFixtures.js)
|
||||
|
||||
- Working with multiple pages
|
||||
@ -539,7 +542,6 @@ const key = getFirstKeyFromOpenMctJson(jsonData);
|
||||
expect(jsonData.openmct[key]).toHaveProperty('name', 'e2e folder');
|
||||
```
|
||||
|
||||
|
||||
### Reporting
|
||||
|
||||
Test Reporting is done through official Playwright reporters and the CI Systems which execute them.
|
||||
@ -615,6 +617,7 @@ A single e2e test in Open MCT is extended to run:
|
||||
### Writing Tests
|
||||
|
||||
Playwright provides 3 supported methods of debugging and authoring tests:
|
||||
|
||||
- A 'watch mode' for running tests locally and debugging on the fly
|
||||
- A 'debug mode' for debugging tests and writing assertions against tests
|
||||
- A 'VSCode plugin' for debugging tests within the VSCode IDE.
|
||||
|
@ -36,27 +36,67 @@
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { expect, test } from './pluginFixtures.js';
|
||||
|
||||
// Constants for repeated values
|
||||
const TEST_RESULTS_DIR = './test-results';
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const TEST_RESULTS_DIR = path.join(__dirname, './test-results');
|
||||
|
||||
const extendedTest = test.extend({
|
||||
/**
|
||||
* Overrides the default screenshot function to apply default options that should apply to all
|
||||
* screenshots taken in the AVP tests.
|
||||
*
|
||||
* @param {import('@playwright/test').PlaywrightTestArgs} args - The Playwright test arguments.
|
||||
* @param {Function} use - The function to use the page object.
|
||||
* Defaults:
|
||||
* - Disables animations
|
||||
* - Masks the clock indicator
|
||||
* - Masks the time conductor last update time in realtime mode
|
||||
* - Masks the time conductor start bounds in fixed mode
|
||||
* - Masks the time conductor end bounds in fixed mode
|
||||
*/
|
||||
page: async ({ page }, use) => {
|
||||
const playwrightScreenshot = page.screenshot;
|
||||
|
||||
/**
|
||||
* Override the screenshot function to always mask a given set of locators which will always
|
||||
* show variance across screenshots. Defaults may be overridden by passing in options to the
|
||||
* screenshot function.
|
||||
* @param {import('@playwright/test').PageScreenshotOptions} options - The options for the screenshot.
|
||||
* @returns {Promise<Buffer>} Returns the screenshot as a buffer.
|
||||
*/
|
||||
page.screenshot = async function (options = {}) {
|
||||
const mask = [
|
||||
this.getByLabel('Clock Indicator'), // Mask the clock indicator
|
||||
this.getByLabel('Last update'), // Mask the time conductor last update time in realtime mode
|
||||
this.getByLabel('Start bounds'), // Mask the time conductor start bounds in fixed mode
|
||||
this.getByLabel('End bounds') // Mask the time conductor end bounds in fixed mode
|
||||
];
|
||||
|
||||
const result = await playwrightScreenshot.call(this, {
|
||||
animations: 'disabled',
|
||||
mask,
|
||||
...options // Pass through or override any options
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
await use(page);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Scans for accessibility violations on a page and writes a report to disk if violations are found.
|
||||
* Automatically asserts that no violations should be present.
|
||||
*
|
||||
* @typedef {Object} GenerateReportOptions
|
||||
* @property {string} [reportName] - The name for the report file.
|
||||
*
|
||||
* @param {import('playwright').Page} page - The page object from Playwright.
|
||||
* @param {string} testCaseName - The name of the test case.
|
||||
* @param {GenerateReportOptions} [options={}] - The options for the report generation.
|
||||
*
|
||||
* @returns {Promise<object|null>} Returns the accessibility scan results if violations are found,
|
||||
* otherwise returns null.
|
||||
* @param {{ reportName?: string }} [options={}] - The options for the report generation.
|
||||
* @returns {Promise<Object|null>} Returns the accessibility scan results if violations are found, otherwise returns null.
|
||||
*/
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
export async function scanForA11yViolations(page, testCaseName, options = {}) {
|
||||
const builder = new AxeBuilder({ page });
|
||||
builder.withTags(['wcag2aa']);
|
||||
@ -93,4 +133,4 @@ export async function scanForA11yViolations(page, testCaseName, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
export { expect, test };
|
||||
export { expect, extendedTest as test };
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-undef */
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -111,6 +110,40 @@ const extendedTest = test.extend({
|
||||
scope: 'test'
|
||||
}
|
||||
],
|
||||
/**
|
||||
* Exposes a function to manually tick the clock. This is useful when overriding the clock to not
|
||||
* tick (`shouldAdvanceTime: false`) for visual tests, as events such as re-renders and router params
|
||||
* updates are clock-driven and must be manually ticked.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* test.describe('Manual Clock Tick', () => {
|
||||
* test.use({
|
||||
* clockOptions: {
|
||||
* now: MISSION_TIME, // Set to the desired time
|
||||
* shouldAdvanceTime: false // Clock overridden to no longer tick
|
||||
* }
|
||||
* });
|
||||
* test('Visual - Manual Clock Tick', async ({ page, tick }) => {
|
||||
* // Tick the clock 2 seconds in the future
|
||||
* await tick(2000);
|
||||
* });
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param {Object} param0
|
||||
* @param {import('@playwright/test').Page} param0.page
|
||||
* @param {import('@playwright/test').Use} param0.use
|
||||
*/
|
||||
tick: async ({ page }, use) => {
|
||||
// eslint-disable-next-line func-style
|
||||
const tick = async (milliseconds) => {
|
||||
await page.evaluate((_milliseconds) => {
|
||||
window.__clock.tick(_milliseconds);
|
||||
}, milliseconds);
|
||||
};
|
||||
await use(tick);
|
||||
},
|
||||
/**
|
||||
* Extends the base context class to add codecoverage shim.
|
||||
* @see {@link https://github.com/mxschmitt/playwright-test-coverage Github Project}
|
||||
@ -154,17 +187,13 @@ const extendedTest = test.extend({
|
||||
// function in the generatorWorker context. This is necessary
|
||||
// to ensure that example telemetry data is generated for the new clock time.
|
||||
if (clockOptions?.now !== undefined) {
|
||||
page.on(
|
||||
'worker',
|
||||
(worker) => {
|
||||
if (worker.url().includes('generatorWorker')) {
|
||||
worker.evaluate((time) => {
|
||||
self.Date.now = () => time;
|
||||
});
|
||||
}
|
||||
},
|
||||
clockOptions.now
|
||||
);
|
||||
page.on('worker', (worker) => {
|
||||
if (worker.url().includes('generatorWorker')) {
|
||||
worker.evaluate((time) => {
|
||||
self.Date.now = () => time;
|
||||
}, clockOptions.now);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Capture any console errors during test execution
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
/**
|
||||
* Constants which may be used across all e2e tests.
|
||||
*/
|
||||
@ -8,12 +7,30 @@
|
||||
* - Used for overriding the browser clock in tests.
|
||||
*/
|
||||
export const MISSION_TIME = 1732413600000; // Saturday, November 23, 2024 6:00:00 PM GMT-08:00 (Thanksgiving Dinner Time)
|
||||
// Subtracting 30 minutes from MISSION_TIME
|
||||
export const MISSION_TIME_FIXED_START = 1732413600000 - 1800000; // 1732411800000
|
||||
|
||||
// Adding 1 minute to MISSION_TIME
|
||||
export const MISSION_TIME_FIXED_END = 1732413600000 + 60000; // 1732413660000
|
||||
/**
|
||||
* URL Constants
|
||||
* - This is the URL that the browser will be directed to when running visual tests. This URL
|
||||
* - hides the tree and inspector to prevent visual noise
|
||||
* - sets the time bounds to a fixed range
|
||||
* These constants are used for initial navigation in visual tests, in either fixed or realtime mode.
|
||||
* They navigate to the 'My Items' folder at MISSION_TIME.
|
||||
* They set the following url parameters:
|
||||
* - tc.mode - The time conductor mode ('fixed' or 'local')
|
||||
* - tc.startBound - The time conductor start bound (when in fixed mode)
|
||||
* - tc.endBound - The time conductor end bound (when in fixed mode)
|
||||
* - tc.startDelta - The time conductor start delta (when in realtime mode)
|
||||
* - tc.endDelta - The time conductor end delta (when in realtime mode)
|
||||
* - tc.timeSystem - The time conductor time system ('utc')
|
||||
* - view - The view to display ('grid')
|
||||
* - hideInspector - Whether to hide the inspector (true)
|
||||
* - hideTree - Whether to hide the tree (true)
|
||||
* @typedef {string} VisualUrl
|
||||
*/
|
||||
export const VISUAL_URL =
|
||||
'./#/browse/mine?tc.mode=fixed&tc.startBound=1693592063607&tc.endBound=1693593893607&tc.timeSystem=utc&view=grid&hideInspector=true&hideTree=true';
|
||||
|
||||
/** @type {VisualUrl} */
|
||||
export const VISUAL_FIXED_URL = `./#/browse/mine?tc.mode=fixed&tc.startBound=${MISSION_TIME_FIXED_START}&tc.endBound=${MISSION_TIME_FIXED_END}&tc.timeSystem=utc&view=grid&hideInspector=true&hideTree=true`;
|
||||
/** @type {VisualUrl} */
|
||||
export const VISUAL_REALTIME_URL =
|
||||
'./#/browse/mine?tc.mode=local&tc.timeSystem=utc&view=grid&tc.startDelta=1800000&tc.endDelta=30000&hideTree=true&hideInspector=true';
|
||||
|
@ -68,7 +68,6 @@ async function commitEntry(page) {
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
async function startAndAddRestrictedNotebookObject(page) {
|
||||
// eslint-disable-next-line no-undef
|
||||
await page.addInitScript({
|
||||
path: fileURLToPath(new URL('./addInitRestrictedNotebook.js', import.meta.url))
|
||||
});
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-undef */
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-undef */
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -123,7 +122,6 @@ const extendedTest = test.extend({
|
||||
theme: [theme, { option: true }],
|
||||
// eslint-disable-next-line no-shadow
|
||||
page: async ({ page, theme }, use, testInfo) => {
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
if (theme === 'snow') {
|
||||
//inject snow theme
|
||||
await page.addInitScript({
|
||||
|
@ -26,11 +26,12 @@ relates to how we've extended it (i.e. ./e2e/baseFixtures.js) and assumptions ma
|
||||
(`npm start` and ./e2e/webpack-dev-middleware.js)
|
||||
*/
|
||||
|
||||
import { test } from '../../baseFixtures.js';
|
||||
import { expect, test } from '../../baseFixtures.js';
|
||||
import { MISSION_TIME } from '../../constants.js';
|
||||
|
||||
test.describe('baseFixtures tests', () => {
|
||||
//Skip this test for now https://github.com/nasa/openmct/issues/6785
|
||||
test.fixme('Verify that tests fail if console.error is thrown', async ({ page }) => {
|
||||
test('Verify that tests fail if console.error is thrown', async ({ page }) => {
|
||||
test.fail();
|
||||
//Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
@ -52,3 +53,27 @@ test.describe('baseFixtures tests', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('baseFixtures tests @clock', () => {
|
||||
test.use({
|
||||
clockOptions: {
|
||||
now: MISSION_TIME,
|
||||
shouldAdvanceTime: false
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Can use clockOptions and tick fixtures to control the clock', async ({ page, tick }) => {
|
||||
let time = await page.evaluate(() => new Date().getTime());
|
||||
expect(time).toBe(MISSION_TIME);
|
||||
await tick(1000);
|
||||
time = await page.evaluate(() => new Date().getTime());
|
||||
expect(time).toBe(MISSION_TIME + 1000 * 1);
|
||||
await tick(1000);
|
||||
time = await page.evaluate(() => new Date().getTime());
|
||||
expect(time).toBe(MISSION_TIME + 1000 * 2);
|
||||
});
|
||||
});
|
||||
|
@ -24,7 +24,7 @@
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding imagery,
|
||||
but only assume that example imagery is present.
|
||||
*/
|
||||
/* globals process */
|
||||
|
||||
import { createDomainObjectWithDefaults, setRealTimeMode } from '../../../../appActions.js';
|
||||
import { waitForAnimations } from '../../../../baseFixtures.js';
|
||||
import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
@ -27,7 +27,6 @@ import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
||||
test.describe('Testing numeric data with inspector data visualization (i.e., data pivoting)', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
await page.addInitScript({
|
||||
path: fileURLToPath(
|
||||
new URL('../../../../helper/addInitDataVisualization.js', import.meta.url)
|
||||
|
@ -277,7 +277,6 @@ test.describe('Notebook entry tests', () => {
|
||||
// Create Notebook with URL Whitelist
|
||||
let notebookObject;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
await page.addInitScript({
|
||||
path: fileURLToPath(new URL('../../../../helper/addInitNotebookWithUrls.js', import.meta.url))
|
||||
});
|
||||
|
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 19 KiB |
@ -48,7 +48,7 @@ test.describe('Time conductor operations', () => {
|
||||
await setTimeConductorBounds(page, startDate);
|
||||
|
||||
// Bring up the time conductor popup
|
||||
const timeConductorMode = await page.locator('.c-compact-tc');
|
||||
const timeConductorMode = page.locator('.c-compact-tc');
|
||||
await timeConductorMode.click();
|
||||
const startDateLocator = page.locator('input[type="text"]').first();
|
||||
const endDateLocator = page.locator('input[type="text"]').nth(2);
|
||||
|
@ -299,7 +299,6 @@ test.describe('Navigation memory leak is not detected in', () => {
|
||||
// for detecting memory leaks.
|
||||
await page.evaluate(() => {
|
||||
window.gcPromise = new Promise((resolve) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
window.fr = new FinalizationRegistry(resolve);
|
||||
window.fr.register(
|
||||
window.openmct.layout.$refs.browseObject.$refs.objectViewWrapper.firstChild,
|
||||
|
@ -21,14 +21,13 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
|
||||
test.describe('a11y - Default', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test('main view', async ({ page }, testInfo) => {
|
||||
await page.goto('./');
|
||||
//Skipping for https://github.com/nasa/openmct/issues/7421
|
||||
//await scanForA11yViolations(page, testInfo.title);
|
||||
});
|
||||
|
@ -27,12 +27,12 @@ Tests the branding associated with the default deployment. At least the about mo
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { expect, scanForA11yViolations, test } from '../../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../../constants.js';
|
||||
|
||||
test.describe('Visual - Branding @a11y', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Go to baseURL and Hide Tree
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Visual - About Modal', async ({ page, theme }) => {
|
||||
|
@ -28,7 +28,7 @@ import percySnapshot from '@percy/playwright';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { expect, test } from '../../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../../constants.js';
|
||||
|
||||
//Declare the component scope of the visual test for Percy
|
||||
const header = '.l-shell__head';
|
||||
@ -36,7 +36,7 @@ const header = '.l-shell__head';
|
||||
test.describe('Visual - Header @a11y', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Go to baseURL and Hide Tree
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
// Wait for status bar to load
|
||||
await expect(
|
||||
page.getByRole('status', {
|
||||
|
@ -23,14 +23,14 @@
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { test } from '../../../avpFixtures.js';
|
||||
import { MISSION_TIME, VISUAL_URL } from '../../../constants.js';
|
||||
import { MISSION_TIME, VISUAL_FIXED_URL } from '../../../constants.js';
|
||||
|
||||
//Declare the scope of the visual test
|
||||
const inspectorPane = '.l-shell__pane-inspector';
|
||||
|
||||
test.describe('Visual - Inspector @ally @clock', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test.use({
|
||||
storageState: './e2e/test-data/overlay_plot_with_delay_storage.json',
|
||||
|
116
e2e/tests/visual-a11y/components/timeConductor.visual.spec.js
Normal file
@ -0,0 +1,116 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
Tests the visual appearance of the Time Conductor component
|
||||
*/
|
||||
|
||||
import { expect, test } from '../../../avpFixtures.js';
|
||||
import {
|
||||
MISSION_TIME,
|
||||
MISSION_TIME_FIXED_END,
|
||||
MISSION_TIME_FIXED_START,
|
||||
VISUAL_REALTIME_URL
|
||||
} from '../../../constants.js';
|
||||
|
||||
test.describe('Visual - Time Conductor', () => {
|
||||
test.use({
|
||||
clockOptions: {
|
||||
now: MISSION_TIME,
|
||||
shouldAdvanceTime: false
|
||||
}
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
// FIXME: checking for a11y violations times out. Might have something to do with the frozen clock.
|
||||
// test.afterEach(async ({ page }, testInfo) => {
|
||||
// await scanForA11yViolations(page, testInfo.title);
|
||||
// });
|
||||
|
||||
test('Visual - Time Conductor (Fixed time) @clock @snapshot', async ({ page }) => {
|
||||
// Navigate to a specific view that uses the Time Conductor in Fixed Time mode with inspect and browse panes collapsed
|
||||
await page.goto(
|
||||
`./#/browse/mine?tc.mode=fixed&tc.startBound=${MISSION_TIME_FIXED_START}&tc.endBound=${MISSION_TIME_FIXED_END}&tc.timeSystem=utc&view=grid&hideInspector=true&hideTree=true`,
|
||||
{
|
||||
waitUntil: 'domcontentloaded'
|
||||
}
|
||||
);
|
||||
|
||||
// Take a snapshot for comparison
|
||||
const snapshot = await page.screenshot({
|
||||
mask: []
|
||||
});
|
||||
expect(snapshot).toMatchSnapshot('time-conductor-fixed-time.png');
|
||||
});
|
||||
|
||||
test('Visual - Time Conductor (Realtime) @clock @snapshot', async ({ page }) => {
|
||||
// Navigate to a specific view that uses the Time Conductor in Fixed Time mode with inspect and browse panes collapsed
|
||||
await page.goto(VISUAL_REALTIME_URL, {
|
||||
waitUntil: 'domcontentloaded'
|
||||
});
|
||||
|
||||
const mask = [];
|
||||
|
||||
// Take a snapshot for comparison
|
||||
const snapshot = await page.screenshot({
|
||||
mask
|
||||
});
|
||||
expect(snapshot).toMatchSnapshot('time-conductor-realtime.png');
|
||||
});
|
||||
test(
|
||||
'Visual - Time Conductor Axis Resized @clock @snapshot',
|
||||
{ annotation: [{ type: 'issue', description: 'https://github.com/nasa/openmct/issues/7623' }] },
|
||||
async ({ page, tick }) => {
|
||||
const VISUAL_REALTIME_WITH_PANES = VISUAL_REALTIME_URL.replace(
|
||||
'hideTree=true',
|
||||
'hideTree=false'
|
||||
).replace('hideInspector=true', 'hideInspector=false');
|
||||
// Navigate to a specific view that uses the Time Conductor in Fixed Time mode with inspect
|
||||
await page.goto(VISUAL_REALTIME_WITH_PANES, {
|
||||
waitUntil: 'domcontentloaded'
|
||||
});
|
||||
|
||||
// Set the time conductor to fixed time mode
|
||||
await page.getByLabel('Time Conductor Mode').click();
|
||||
await page.getByLabel('Time Conductor Mode Menu').click();
|
||||
await page.getByLabel('Fixed Timespan').click();
|
||||
await page.getByLabel('Submit time bounds').click();
|
||||
|
||||
// Collapse the inspect and browse panes to trigger a resize of the conductor axis
|
||||
await page.getByLabel('Collapse Inspect Pane').click();
|
||||
await page.getByLabel('Collapse Browse Pane').click();
|
||||
|
||||
// manually tick the clock to trigger the resize / re-render
|
||||
await tick(1000 * 2);
|
||||
|
||||
const mask = [];
|
||||
|
||||
// Take a snapshot for comparison
|
||||
const snapshot = await page.screenshot({
|
||||
mask
|
||||
});
|
||||
expect(snapshot).toMatchSnapshot('time-conductor-axis-resized.png');
|
||||
}
|
||||
);
|
||||
});
|
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 29 KiB |
@ -23,7 +23,7 @@
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults, expandTreePaneItemByName } from '../../../appActions.js';
|
||||
import { VISUAL_URL } from '../../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../../constants.js';
|
||||
import { test } from '../../../pluginFixtures.js';
|
||||
|
||||
//Declare the scope of the visual test
|
||||
@ -32,7 +32,7 @@ const treePane = "[role=tree][aria-label='Main Tree']";
|
||||
test.describe('Visual - Tree Pane', () => {
|
||||
test('Tree pane in various states', async ({ page, theme, openmctConfig }) => {
|
||||
const { myItemsFolderName } = openmctConfig;
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
//Open Tree
|
||||
await page.getByRole('button', { name: 'Browse' }).click();
|
||||
|
@ -27,12 +27,12 @@ clockOptions plugin fixture.
|
||||
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { MISSION_TIME, VISUAL_URL } from '../../constants.js';
|
||||
import { MISSION_TIME, VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
|
||||
test.describe('Visual - Controlled Clock @clock', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test.use({
|
||||
storageState: './e2e/test-data/overlay_plot_with_delay_storage.json',
|
||||
@ -43,7 +43,7 @@ test.describe('Visual - Controlled Clock @clock', () => {
|
||||
});
|
||||
|
||||
test('Overlay Plot Loading Indicator @localStorage', async ({ page, theme }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page
|
||||
.getByRole('gridcell', { hasText: 'Overlay Plot with 5s Delay Overlay Plot' })
|
||||
.click();
|
||||
|
@ -30,11 +30,11 @@ import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
||||
import { expect, scanForA11yViolations, test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
|
||||
test.describe('Visual - Default @a11y', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Visual - Default Dashboard', async ({ page, theme }) => {
|
||||
|
@ -23,12 +23,18 @@
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { MISSION_TIME, VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { test } from '../../pluginFixtures.js';
|
||||
|
||||
test.describe('Visual - Display Layout', () => {
|
||||
test.beforeEach(async ({ page, theme }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
test.describe('Visual - Display Layout @clock', () => {
|
||||
test.use({
|
||||
clockOptions: {
|
||||
now: MISSION_TIME,
|
||||
shouldAdvanceTime: true
|
||||
}
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
const parentLayout = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
@ -59,12 +65,15 @@ test.describe('Visual - Display Layout', () => {
|
||||
await page.goto(parentLayout.url, { waitUntil: 'domcontentloaded' });
|
||||
await page.getByRole('button', { name: 'Edit Object' }).click();
|
||||
|
||||
//Move the Child Right Layout to the Right. It should be on top of the Left Layout at this point.
|
||||
// Select the child right layout
|
||||
await page
|
||||
.getByLabel('Child Right Layout Layout', { exact: true })
|
||||
.getByLabel('Move Sub-object Frame')
|
||||
.click();
|
||||
await page.getByLabel('Move Sub-object Frame').nth(3).click(); //I'm not sure why this step is necessary
|
||||
// FIXME: Click to select the parent object (layout)
|
||||
await page.getByLabel('Move Sub-object Frame').nth(3).click();
|
||||
|
||||
// Move the second layout element to the right
|
||||
await page.getByLabel('X:').click();
|
||||
await page.getByLabel('X:').fill('35');
|
||||
});
|
||||
|
@ -84,6 +84,12 @@ test.describe('Fault Management Visual Tests', () => {
|
||||
await shelveFault(page, 1);
|
||||
await changeViewTo(page, 'shelved');
|
||||
|
||||
/* cspell:disable-next-line */
|
||||
// Since fault management is heavily dependent on events (bleh), we need to wait for the correct
|
||||
// element counts
|
||||
await expect(page.getByLabel('Select fault:')).toHaveCount(1);
|
||||
await expect(page.getByLabel('Disposition Actions')).toHaveCount(1);
|
||||
|
||||
await percySnapshot(page, `Shelved faults appear in the shelved view (theme: '${theme}')`);
|
||||
|
||||
await openFaultRowMenu(page, 1);
|
||||
|
@ -24,7 +24,7 @@ import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults, setRealTimeMode } from '../../appActions.js';
|
||||
import { waitForAnimations } from '../../baseFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
|
||||
test.describe('Visual - Example Imagery', () => {
|
||||
@ -32,7 +32,7 @@ test.describe('Visual - Example Imagery', () => {
|
||||
let parentLayout;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
parentLayout = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
|
@ -23,14 +23,14 @@
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
|
||||
test.describe('Visual - LAD Table', () => {
|
||||
let ladTable;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create LAD Table
|
||||
ladTable = await createDomainObjectWithDefaults(page, {
|
||||
|
@ -24,7 +24,7 @@ import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults, expandTreePaneItemByName } from '../../appActions.js';
|
||||
import { expect, test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { enterTextEntry, startAndAddRestrictedNotebookObject } from '../../helper/notebookUtils.js';
|
||||
|
||||
test.describe('Visual - Restricted Notebook @a11y', () => {
|
||||
@ -80,7 +80,7 @@ test.describe('Visual - Notebook Snapshot @a11y', () => {
|
||||
test.describe('Visual - Notebook @a11y', () => {
|
||||
let notebook;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
notebook = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Notebook',
|
||||
name: 'Test Notebook'
|
||||
|
@ -28,11 +28,11 @@ import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createNotification } from '../../appActions.js';
|
||||
import { expect, scanForA11yViolations, test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
|
||||
test.describe('Visual - Notifications @a11y', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Alert Levels and Notification List Modal', async ({ page, theme }) => {
|
||||
|
@ -25,7 +25,7 @@ import fs from 'fs';
|
||||
|
||||
import { createDomainObjectWithDefaults, createPlanFromJSON } from '../../appActions.js';
|
||||
import { test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import {
|
||||
createTimelistWithPlanAndSetActivityInProgress,
|
||||
getFirstActivity,
|
||||
@ -64,7 +64,7 @@ test.describe('Visual - Timelist progress bar @clock', () => {
|
||||
|
||||
test.describe('Visual - Planning', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Plan View', async ({ page, theme }) => {
|
||||
@ -83,7 +83,7 @@ test.describe('Visual - Planning', () => {
|
||||
});
|
||||
const newPage = await newContext.newPage();
|
||||
|
||||
await newPage.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await newPage.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
const plan = await createPlanFromJSON(newPage, {
|
||||
name: 'Plan Visual Test',
|
||||
json: examplePlanSmall2
|
||||
@ -100,7 +100,7 @@ test.describe('Visual - Planning', () => {
|
||||
name: 'Plan Visual Test (Draft)',
|
||||
json: examplePlanSmall2
|
||||
});
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
await setDraftStatusForPlan(page, plan);
|
||||
|
||||
await setBoundsToSpanAllActivities(page, examplePlanSmall2, plan.url);
|
||||
@ -110,7 +110,7 @@ test.describe('Visual - Planning', () => {
|
||||
|
||||
test.describe('Visual - Gantt Chart', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test('Gantt Chart View', async ({ page, theme }) => {
|
||||
const ganttChart = await createDomainObjectWithDefaults(page, {
|
||||
@ -153,7 +153,7 @@ test.describe('Visual - Gantt Chart', () => {
|
||||
|
||||
await setDraftStatusForPlan(page, plan);
|
||||
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
await setBoundsToSpanAllActivities(page, examplePlanSmall2, ganttChart.url);
|
||||
await percySnapshot(page, `Gantt Chart View w/ draft status (theme: ${theme})`);
|
||||
|
@ -28,13 +28,13 @@ import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
||||
import { expect, scanForA11yViolations, test } from '../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
|
||||
test.describe('Grand Search @a11y', () => {
|
||||
let conditionWidget;
|
||||
let displayLayout;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
displayLayout = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
|
@ -23,14 +23,14 @@
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
||||
import { VISUAL_URL } from '../../constants.js';
|
||||
import { VISUAL_FIXED_URL } from '../../constants.js';
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
|
||||
test.describe('Visual - Telemetry Views', () => {
|
||||
let telemetry;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(VISUAL_URL, { waitUntil: 'domcontentloaded' });
|
||||
await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create SWG inside of LAD Table
|
||||
telemetry = await createDomainObjectWithDefaults(page, {
|
||||
|
@ -20,26 +20,32 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/*global module,process*/
|
||||
// eslint-disable-next-line func-style
|
||||
const loadWebpackConfig = async () => {
|
||||
if (process.env.KARMA_DEBUG) {
|
||||
return {
|
||||
config: (await import('./.webpack/webpack.dev.js')).default,
|
||||
browsers: ['ChromeDebugging'],
|
||||
singleRun: false
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
config: (await import('./.webpack/webpack.coverage.js')).default,
|
||||
browsers: ['ChromeHeadless'],
|
||||
singleRun: true
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = async (config) => {
|
||||
let webpackConfig;
|
||||
let browsers;
|
||||
let singleRun;
|
||||
|
||||
if (process.env.KARMA_DEBUG) {
|
||||
webpackConfig = (await import('./.webpack/webpack.dev.js')).default;
|
||||
browsers = ['ChromeDebugging'];
|
||||
singleRun = false;
|
||||
} else {
|
||||
webpackConfig = (await import('./.webpack/webpack.coverage.js')).default;
|
||||
browsers = ['ChromeHeadless'];
|
||||
singleRun = true;
|
||||
}
|
||||
const { config: webpackConfig, browsers, singleRun } = await loadWebpackConfig();
|
||||
|
||||
// Adjust webpack config for Karma
|
||||
delete webpackConfig.output;
|
||||
// karma doesn't support webpack entry
|
||||
delete webpackConfig.entry;
|
||||
delete webpackConfig.entry; // Karma doesn't support webpack entry
|
||||
|
||||
// Ensure source maps are enabled for better debugging
|
||||
webpackConfig.devtool = |