mirror of
https://github.com/nasa/openmct.git
synced 2024-12-29 17:38:53 +00:00
Mct7367-tests (#7387)
* refactor(ExportAsJSONAction): use private methods * refactor: remove unnecessary webpack alias * refactor: lint * fix: tests for `ExportAsJSONAction` * test: stabilize `InspectorStylesSpec` tests * docs: fix jsdocs * chore: remove dead / redundant code * refactor(LocalStorageObjectProvider): use `getItem()` and `setItem()` * refactor(ExportAsJSONAction): use `Promise.all` where applicable * refactor(MenuAPI): one-liner * feat: add percentage ProgressBar to ExportAsJSONAction * fix(ProgressBar.vue): v-if conditionals * test(fix): update mockLocalStorage * test: fix locators * test: remove unneeded awaits * fix: example imagery urls (moved after NASA wordpress migration) * Revert "refactor(LocalStorageObjectProvider): use `getItem()` and `setItem()`" This reverts commit4f8403adab
. * test(e2e): fix logPlot test * Revert "Revert "refactor(LocalStorageObjectProvider): use `getItem()` and `setItem()`"" This reverts commit0de66401cd
. * test(e2e): remove waitForNavigations * driveby and fixes * aria improvement * getting tests back oline * more tests * add last test * Add a11y * lint * lint * driveby * review comments * driveby rename * fix selectors and break up test suites * add test for snapshot in header * last lint fixes * stable --------- Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
This commit is contained in:
parent
43ae3cf655
commit
4cf63062c0
e2e
appActions.jsuserRoles.e2e.spec.js
helper
tests
framework
functional
plugins
importAndExportAsJSON
inspectorDataVisualization
lad
notebook
operatorStatus
visual-a11y/components
src
@ -284,7 +284,7 @@ async function navigateToObjectWithFixedTimeBounds(page, url, start, end) {
|
||||
*/
|
||||
async function openObjectTreeContextMenu(page, url) {
|
||||
await page.goto(url);
|
||||
await page.click('button[title="Show selected item in tree"]');
|
||||
await page.getByLabel('Show selected item in tree').click();
|
||||
await page.locator('.is-navigated-object').click({
|
||||
button: 'right'
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ async function dragAndDropEmbed(page, notebookObject) {
|
||||
// Navigate to notebook
|
||||
await page.goto(notebookObject.url);
|
||||
// Expand the tree to reveal the notebook
|
||||
await page.click('button[title="Show selected item in tree"]');
|
||||
await page.getByLabel('Show selected item in tree').click();
|
||||
// Drag and drop the SWG into the notebook
|
||||
await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA);
|
||||
await commitEntry(page);
|
||||
|
@ -23,7 +23,8 @@
|
||||
import {
|
||||
createDomainObjectWithDefaults,
|
||||
createNotification,
|
||||
expandEntireTree
|
||||
expandEntireTree,
|
||||
openObjectTreeContextMenu
|
||||
} from '../../appActions.js';
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
|
||||
@ -166,4 +167,13 @@ test.describe('AppActions', () => {
|
||||
const locatorTreeCollapsedItems = locatorTree.locator('role=treeitem[expanded=false]');
|
||||
expect(await locatorTreeCollapsedItems.count()).toBe(0);
|
||||
});
|
||||
test('openObjectTreeContextMenu', async ({ page }) => {
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
const folder = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Folder'
|
||||
});
|
||||
await openObjectTreeContextMenu(page, folder.url);
|
||||
await expect(page.getByLabel('Menu')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
@ -24,36 +24,182 @@
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding exportAsJSON.
|
||||
*/
|
||||
|
||||
// FIXME: Remove this eslint exception once tests are implemented
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import fs from 'fs/promises';
|
||||
|
||||
import {
|
||||
createDomainObjectWithDefaults,
|
||||
openObjectTreeContextMenu
|
||||
} from '../../../../appActions.js';
|
||||
import { expect, test } from '../../../../baseFixtures.js';
|
||||
import { navigateToFaultManagementWithExample } from '../../../../helper/faultUtils.js';
|
||||
|
||||
test.describe('ExportAsJSON', () => {
|
||||
test.fixme(
|
||||
'Create a basic object and verify that it can be exported as JSON from Tree',
|
||||
async ({ page }) => {
|
||||
//Create domain object
|
||||
//Save Domain Object
|
||||
//Verify that the newly created domain object can be exported as JSON from the Tree
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'Create a basic object and verify that it can be exported as JSON from 3 dot menu',
|
||||
async ({ page }) => {
|
||||
//Create domain object
|
||||
//Save Domain Object
|
||||
//Verify that the newly created domain object can be exported as JSON from the 3 dot menu
|
||||
}
|
||||
);
|
||||
test.fixme('Verify that a nested Object can be exported as JSON', async ({ page }) => {
|
||||
// Create 2 objects with hierarchy
|
||||
// Export as JSON
|
||||
// Verify Hierarchy
|
||||
let folder;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Go to baseURL
|
||||
await page.goto('./');
|
||||
// Perform actions to create the domain object
|
||||
folder = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Folder',
|
||||
name: 'e2e folder'
|
||||
});
|
||||
});
|
||||
test('Create a basic object and verify that it can be exported as JSON from Tree', async ({
|
||||
page
|
||||
}) => {
|
||||
// Navigate to the page
|
||||
await page.goto(folder.url);
|
||||
|
||||
// Open context menu and initiate download
|
||||
await openObjectTreeContextMenu(page, folder.url);
|
||||
const [download] = await Promise.all([
|
||||
page.waitForEvent('download'), // Waits for the download event
|
||||
page.getByLabel('Export as JSON').click() // Triggers the download
|
||||
]);
|
||||
|
||||
// Wait for the download process to complete
|
||||
const path = await download.path();
|
||||
|
||||
// Read the contents of the downloaded file using readFile from fs/promises
|
||||
const fileContents = await fs.readFile(path, 'utf8');
|
||||
const jsonData = JSON.parse(fileContents);
|
||||
|
||||
// Use the function to retrieve the key
|
||||
const key = getFirstKeyFromOpenMctJson(jsonData);
|
||||
|
||||
// Verify the contents of the JSON file
|
||||
expect(jsonData.openmct[key]).toHaveProperty('name', 'e2e folder');
|
||||
expect(jsonData.openmct[key]).toHaveProperty('type', 'folder');
|
||||
});
|
||||
test('Create a basic object and verify that it can be exported as JSON from 3 dot menu', async ({
|
||||
page
|
||||
}) => {
|
||||
// Navigate to the page
|
||||
await page.goto(folder.url);
|
||||
//3 dot menu
|
||||
await page.getByLabel('More actions').click();
|
||||
// Open context menu and initiate download
|
||||
const [download] = await Promise.all([
|
||||
page.waitForEvent('download'), // Waits for the download event
|
||||
page.getByLabel('Export as JSON').click() // Triggers the download
|
||||
]);
|
||||
|
||||
// Read the contents of the downloaded file using readFile from fs/promises
|
||||
const fileContents = await fs.readFile(await download.path(), 'utf8');
|
||||
const jsonData = JSON.parse(fileContents);
|
||||
|
||||
// Use the function to retrieve the key
|
||||
const key = getFirstKeyFromOpenMctJson(jsonData);
|
||||
|
||||
// Verify the contents of the JSON file
|
||||
expect(jsonData.openmct[key]).toHaveProperty('name', 'e2e folder');
|
||||
expect(jsonData.openmct[key]).toHaveProperty('type', 'folder');
|
||||
});
|
||||
test('Verify that a nested Object can be exported as JSON', async ({ page }) => {
|
||||
const timer = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Timer',
|
||||
name: 'timer',
|
||||
parent: folder.uuid
|
||||
});
|
||||
// Navigate to the page
|
||||
await page.goto(timer.url);
|
||||
|
||||
//do this against parent folder.url, NOT timer.url child
|
||||
await openObjectTreeContextMenu(page, folder.url);
|
||||
// Open context menu and initiate download
|
||||
const [download] = await Promise.all([
|
||||
page.waitForEvent('download'), // Waits for the download event
|
||||
page.getByLabel('Export as JSON').click() // Triggers the download
|
||||
]);
|
||||
|
||||
// Read the contents of the downloaded file
|
||||
const fileContents = await fs.readFile(await download.path(), 'utf8');
|
||||
const jsonData = JSON.parse(fileContents);
|
||||
|
||||
// Retrieve the keys for folder and timer
|
||||
const folderKey = getFirstKeyFromOpenMctJson(jsonData);
|
||||
const timerKey = jsonData.openmct[folderKey].composition[0].key;
|
||||
|
||||
// Verify the folder properties
|
||||
expect(jsonData.openmct[folderKey]).toHaveProperty('name', 'e2e folder');
|
||||
expect(jsonData.openmct[folderKey]).toHaveProperty('type', 'folder');
|
||||
|
||||
// Verify the timer properties
|
||||
expect(jsonData.openmct[timerKey]).toHaveProperty('name', 'timer');
|
||||
expect(jsonData.openmct[timerKey]).toHaveProperty('type', 'timer');
|
||||
|
||||
// Verify the composition of the folder includes the timer
|
||||
expect(jsonData.openmct[folderKey].composition).toEqual(
|
||||
expect.arrayContaining([expect.objectContaining({ key: timerKey })])
|
||||
);
|
||||
});
|
||||
test.fixme(
|
||||
'Verify that the ExportAsJSON dropdown does not appear for the item X',
|
||||
async ({ page }) => {
|
||||
// Other than non-persistable objects
|
||||
}
|
||||
);
|
||||
});
|
||||
test.describe('ExportAsJSON Disabled Actions', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Use a Fault Management Object which is not composable
|
||||
await navigateToFaultManagementWithExample(page);
|
||||
});
|
||||
test('Verify that the ExportAsJSON dropdown does not appear for the item X', async ({ page }) => {
|
||||
await page.getByLabel('More actions').click();
|
||||
await expect(await page.getByLabel('Export as JSON')).toHaveCount(0);
|
||||
|
||||
await page.getByRole('treeitem', { name: 'Fault Management' }).click({
|
||||
button: 'right'
|
||||
});
|
||||
await expect(await page.getByLabel('Export as JSON')).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
test.describe('ExportAsJSON ProgressBar @couchdb', () => {
|
||||
let folder;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('./', { waitUntil: 'networkidle' });
|
||||
// Perform actions to create the domain object
|
||||
folder = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Folder'
|
||||
});
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Timer',
|
||||
parent: folder.uuid
|
||||
});
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Timer',
|
||||
parent: folder.uuid
|
||||
});
|
||||
});
|
||||
test('Verify that the ExportAsJSON action creates a progressbar', async ({ page }) => {
|
||||
// Navigate to the page
|
||||
await page.goto(folder.url);
|
||||
|
||||
//Export My Items to create a large export
|
||||
await page.getByRole('treeitem', { name: 'My Items' }).click({ button: 'right' });
|
||||
// Open context menu and initiate download
|
||||
await Promise.all([
|
||||
page.getByRole('progressbar'), // This is just a check for the progress bar
|
||||
page.getByText(
|
||||
'Do not navigate away from this page or close this browser tab while this message'
|
||||
), // This is the text associated with the download
|
||||
page.waitForEvent('download'), // Waits for the download event
|
||||
page.getByLabel('Export as JSON').click() // Triggers the download
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Retrieves the first key from the 'openmct' property of the provided JSON object.
|
||||
*
|
||||
* @param {Object} jsonData - The JSON object containing the 'openmct' property.
|
||||
* @returns {string} The first key found in the 'openmct' object.
|
||||
* @throws {Error} If no keys are found in the 'openmct' object.
|
||||
*/
|
||||
function getFirstKeyFromOpenMctJson(jsonData) {
|
||||
if (!jsonData.openmct) {
|
||||
throw new Error("The provided JSON object does not have an 'openmct' property.");
|
||||
}
|
||||
|
||||
const keys = Object.keys(jsonData.openmct);
|
||||
if (keys.length === 0) {
|
||||
throw new Error('No keys found in the openmct object');
|
||||
}
|
||||
|
||||
return keys[0];
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ test.describe('Testing numeric data with inspector data visualization (i.e., dat
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
|
||||
test('Can click on telemetry and see data in inspector', async ({ page, context }) => {
|
||||
test('Can click on telemetry and see data in inspector @2p', async ({ page, context }) => {
|
||||
const exampleDataVisualizationSource = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Example Data Visualization Source'
|
||||
});
|
||||
|
@ -53,6 +53,9 @@ test.describe('LAD Table Sets', () => {
|
||||
|
||||
await page.goto(ladTableSet.url);
|
||||
|
||||
// Wait for the initial value to show after mount
|
||||
await expect(page.getByLabel('lad value').first()).not.toContainText('---');
|
||||
|
||||
const valueFromFirstSineWave = await page.getByLabel('lad value').first().innerText();
|
||||
const firstSineWaveNumber = parseFloat(valueFromFirstSineWave);
|
||||
// ensure we have a float value in the cell and it's finite
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding Notebooks.
|
||||
*/
|
||||
|
||||
import fs from 'fs/promises';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../../../appActions.js';
|
||||
import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
||||
const NOTEBOOK_NAME = 'Notebook';
|
||||
|
||||
test.describe('Snapshot image tests', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
|
||||
test('Can drop an image onto a notebook and create a new entry', async ({ page }) => {
|
||||
const imageData = await fs.readFile(
|
||||
fileURLToPath(
|
||||
new URL('../../../../../src/images/favicons/favicon-96x96.png', import.meta.url)
|
||||
)
|
||||
);
|
||||
const imageArray = new Uint8Array(imageData);
|
||||
const fileData = Array.from(imageArray);
|
||||
|
||||
const dropTransfer = await page.evaluateHandle((data) => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([new Uint8Array(data)], 'favicon-96x96.png', { type: 'image/png' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
await page.locator('.c-ne__save-button > button').click();
|
||||
// be sure that entry was created
|
||||
await expect(page.getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).click();
|
||||
// expect large image to be displayed
|
||||
await expect(page.getByRole('dialog').getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
await page.getByLabel('Close').click();
|
||||
|
||||
// drop another image onto the entry
|
||||
await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
const secondThumbnail = page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).nth(1);
|
||||
await secondThumbnail.waitFor({ state: 'attached' });
|
||||
// expect two embedded images now
|
||||
expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(2);
|
||||
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More actions').click();
|
||||
|
||||
await page.getByRole('menuitem', { name: /Remove This Embed/ }).click();
|
||||
await page.getByRole('button', { name: 'Ok', exact: true }).click();
|
||||
// Ensure that the thumbnail is removed before we assert
|
||||
await secondThumbnail.waitFor({ state: 'detached' });
|
||||
|
||||
// expect one embedded image now as we deleted the other
|
||||
expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Snapshot image failure tests', () => {
|
||||
test.use({ failOnConsoleError: false });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping unknown file onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
// fill Uint8Array array with some garbage data
|
||||
const garbageData = new Uint8Array(100);
|
||||
const fileData = Array.from(garbageData);
|
||||
|
||||
const dropTransfer = await page.evaluateHandle((data) => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([new Uint8Array(data)], 'someGarbage.foo', { type: 'unknown/garbage' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it
|
||||
await expect(page.getByText('Unknown object(s) dropped and cannot embed')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping big files onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
const garbageSize = 15 * 1024 * 1024; // 15 megabytes
|
||||
|
||||
await page.addScriptTag({
|
||||
// make the garbage client side
|
||||
content: `window.bigGarbageData = new Uint8Array(${garbageSize})`
|
||||
});
|
||||
|
||||
const bigDropTransfer = await page.evaluateHandle(() => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([window.bigGarbageData], 'bigBoy.png', { type: 'image/png' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
});
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: bigDropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it as it's too big
|
||||
await expect(page.getByText('unable to embed')).toBeVisible();
|
||||
});
|
||||
});
|
@ -24,14 +24,8 @@
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding Notebooks.
|
||||
*/
|
||||
|
||||
import fs from 'fs/promises';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../../../appActions.js';
|
||||
import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
||||
const NOTEBOOK_NAME = 'Notebook';
|
||||
|
||||
test.describe('Snapshot Menu tests', () => {
|
||||
test.fixme(
|
||||
'When no default notebook is selected, Snapshot Menu dropdown should only have a single option',
|
||||
@ -91,22 +85,13 @@ test.describe('Snapshot Container tests', () => {
|
||||
|
||||
await page.getByLabel('Take a Notebook Snapshot').click();
|
||||
await page.getByRole('menuitem', { name: 'Save to Notebook Snapshots' }).click();
|
||||
await page.getByRole('button', { name: 'Show' }).click();
|
||||
await page.getByLabel('Show Snapshots').click();
|
||||
});
|
||||
test('A snapshot can be Quick Viewed from Container with 3 dot action menu', async ({ page }) => {
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More actions').click();
|
||||
await page.getByRole('menuitem', { name: 'Quick View' }).click();
|
||||
await expect(page.locator('.c-overlay__outer')).toBeVisible();
|
||||
});
|
||||
test.fixme('5 Snapshots can be added to a container', async ({ page }) => {});
|
||||
test.fixme(
|
||||
'5 Snapshots can be added to a container and Deleted with Delete All action',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Deleted from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Viewed, Annotated, display deleted, and saved from Container with 3 dot action menu',
|
||||
async ({ page }) => {
|
||||
@ -122,7 +107,15 @@ test.describe('Snapshot Container tests', () => {
|
||||
//await expect(await page.locator)
|
||||
}
|
||||
);
|
||||
|
||||
test.fixme('5 Snapshots can be added to a container', async ({ page }) => {});
|
||||
test.fixme(
|
||||
'5 Snapshots can be added to a container and Deleted with Delete All action',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Deleted from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Navigated To from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
@ -166,117 +159,3 @@ test.describe('Snapshot Container tests', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test.describe('Snapshot image tests', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
|
||||
test('Can drop an image onto a notebook and create a new entry', async ({ page }) => {
|
||||
const imageData = await fs.readFile(
|
||||
fileURLToPath(
|
||||
new URL('../../../../../src/images/favicons/favicon-96x96.png', import.meta.url)
|
||||
)
|
||||
);
|
||||
const imageArray = new Uint8Array(imageData);
|
||||
const fileData = Array.from(imageArray);
|
||||
|
||||
const dropTransfer = await page.evaluateHandle((data) => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([new Uint8Array(data)], 'favicon-96x96.png', { type: 'image/png' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
await page.locator('.c-ne__save-button > button').click();
|
||||
// be sure that entry was created
|
||||
await expect(page.getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).click();
|
||||
// expect large image to be displayed
|
||||
await expect(page.getByRole('dialog').getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
await page.getByLabel('Close').click();
|
||||
|
||||
// drop another image onto the entry
|
||||
await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
const secondThumbnail = page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).nth(1);
|
||||
await secondThumbnail.waitFor({ state: 'attached' });
|
||||
// expect two embedded images now
|
||||
expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(2);
|
||||
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More actions').click();
|
||||
|
||||
await page.getByRole('menuitem', { name: /Remove This Embed/ }).click();
|
||||
await page.getByRole('button', { name: 'Ok', exact: true }).click();
|
||||
// Ensure that the thumbnail is removed before we assert
|
||||
await secondThumbnail.waitFor({ state: 'detached' });
|
||||
|
||||
// expect one embedded image now as we deleted the other
|
||||
expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Snapshot image failure tests', () => {
|
||||
test.use({ failOnConsoleError: false });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping unknown file onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
// fill Uint8Array array with some garbage data
|
||||
const garbageData = new Uint8Array(100);
|
||||
const fileData = Array.from(garbageData);
|
||||
|
||||
const dropTransfer = await page.evaluateHandle((data) => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([new Uint8Array(data)], 'someGarbage.foo', { type: 'unknown/garbage' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it
|
||||
await expect(page.getByText('Unknown object(s) dropped and cannot embed')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping big files onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
const garbageSize = 15 * 1024 * 1024; // 15 megabytes
|
||||
|
||||
await page.addScriptTag({
|
||||
// make the garbage client side
|
||||
content: `window.bigGarbageData = new Uint8Array(${garbageSize})`
|
||||
});
|
||||
|
||||
const bigDropTransfer = await page.evaluateHandle(() => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([window.bigGarbageData], 'bigBoy.png', { type: 'image/png' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
});
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: bigDropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it as it's too big
|
||||
await expect(page.getByText('unable to embed')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ test.describe('Operator Status', () => {
|
||||
// Description should be empty https://github.com/nasa/openmct/issues/6978
|
||||
await expect(page.locator('.c-message__action-text')).toBeHidden();
|
||||
// set role
|
||||
await page.getByRole('button', { name: 'Select' }).click();
|
||||
await page.getByRole('button', { name: 'Select', exact: true }).click();
|
||||
// dismiss role confirmation popup
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
});
|
||||
|
@ -34,13 +34,13 @@ test.describe('User Roles', () => {
|
||||
// we have multiple available roles, so it should prompt the user
|
||||
await expect(page.getByText('Select Role')).toBeVisible();
|
||||
await page.getByRole('combobox').selectOption('driver');
|
||||
await page.getByRole('button', { name: 'Select' }).click();
|
||||
await page.getByRole('button', { name: 'Select', exact: true }).click();
|
||||
await expect(page.getByLabel('User Role')).toContainText('driver');
|
||||
|
||||
// attempt changing the role to another valid available role
|
||||
await page.getByRole('button', { name: 'Change Role' }).click();
|
||||
await page.getByRole('combobox').selectOption('flight');
|
||||
await page.getByRole('button', { name: 'Select' }).click();
|
||||
await page.getByRole('button', { name: 'Select', exact: true }).click();
|
||||
await expect(page.getByLabel('User Role')).toContainText('flight');
|
||||
|
||||
// reload page
|
||||
@ -63,7 +63,7 @@ test.describe('User Roles', () => {
|
||||
|
||||
// select real role of "driver"
|
||||
await page.getByRole('combobox').selectOption('driver');
|
||||
await page.getByRole('button', { name: 'Select' }).click();
|
||||
await page.getByRole('button', { name: 'Select', exact: true }).click();
|
||||
await expect(page.getByLabel('User Role')).toContainText('driver');
|
||||
});
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ Tests the branding associated with the default deployment. At least the about mo
|
||||
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import { scanForA11yViolations, test } from '../../../avpFixtures.js';
|
||||
import { expect, scanForA11yViolations, test } from '../../../avpFixtures.js';
|
||||
import { VISUAL_URL } from '../../../constants.js';
|
||||
|
||||
//Declare the scope of the visual test
|
||||
@ -50,6 +50,17 @@ test.describe('Visual - Header @a11y', () => {
|
||||
scope: header
|
||||
});
|
||||
});
|
||||
|
||||
test('show snapshot button', async ({ page, theme }) => {
|
||||
await page.getByLabel('Take a Notebook Snapshot').click();
|
||||
|
||||
await page.getByRole('menuitem', { name: 'Save to Notebook Snapshots' }).click();
|
||||
|
||||
await percySnapshot(page, `Notebook Snapshot Show button (theme: '${theme}')`, {
|
||||
scope: header
|
||||
});
|
||||
await expect(await page.getByLabel('Show Snapshots')).toBeVisible();
|
||||
});
|
||||
});
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
await scanForA11yViolations(page, testInfo.title);
|
||||
|
@ -56,8 +56,8 @@
|
||||
{{ formatImageAltText }}
|
||||
</div>
|
||||
<div
|
||||
role="button"
|
||||
ref="focusedImageWrapper"
|
||||
role="button"
|
||||
class="image-wrapper"
|
||||
aria-label="Image Wrapper"
|
||||
:style="{
|
||||
@ -74,8 +74,8 @@
|
||||
:style="getVisibleLayerStyles(layer)"
|
||||
></div>
|
||||
<img
|
||||
aria-label="Focused Image"
|
||||
ref="focusedImage"
|
||||
aria-label="Focused Image"
|
||||
class="c-imagery__main-image__image js-imageryView-image"
|
||||
:src="imageUrl"
|
||||
:draggable="!isSelectable"
|
||||
|
@ -25,6 +25,10 @@
|
||||
class="c-progress-bar__bar"
|
||||
:class="{ '--indeterminate': !progressPerc }"
|
||||
:style="styleBarWidth"
|
||||
role="progressbar"
|
||||
:aria-valuenow="progressPerc"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
></div>
|
||||
<div v-if="progressText !== ''" class="c-progress-bar__text">
|
||||
<span v-if="progressPerc > 0">{{ progressPerc }}% complete.</span>
|
||||
|
@ -85,11 +85,13 @@
|
||||
<template #controls>
|
||||
<button
|
||||
class="c-icon-button l-shell__reset-tree-button icon-folders-collapse"
|
||||
aria-label="Collapse all tree items"
|
||||
title="Collapse all tree items"
|
||||
@click="handleTreeReset"
|
||||
></button>
|
||||
<button
|
||||
class="c-icon-button l-shell__sync-tree-button icon-target"
|
||||
aria-label="Show selected item in tree"
|
||||
title="Show selected item in tree"
|
||||
@click="handleSyncTreeNavigation"
|
||||
></button>
|
||||
|
Loading…
Reference in New Issue
Block a user