Compare commits

...

5 Commits

Author SHA1 Message Date
David Tsay
27f5243a56 plot w/ two telemetries in inspector 2022-05-24 14:44:56 -07:00
Michael Rogers
1ca5271c3e e2e test for image thumbnail visibility and size - 5106 (#5232)
* e2e test for timage thumbnail visibility and size

* Lint fix

* Remove URL comment

* Added comment and assigned selectors to var
2022-05-20 17:26:54 +00:00
Jesse Mazzella
6521b888d6 Enable lint enforcement on e2e tests and fix the existing errors (#5229)
* Add `e2e` folder to lint scripts

* Fix or add exceptions to all new linting errors

* fix an oopsie 👀
2022-05-19 16:09:22 -07:00
dependabot[bot]
85fce3c456 Bump jasmine-core from 4.0.1 to 4.1.1 (#5225)
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 4.0.1 to 4.1.1.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v4.0.1...v4.1.1)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
2022-05-19 15:03:41 -07:00
Michael Rogers
8d577a8958 Removed requestHistory call from mount and clearData method (#5223)
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
2022-05-19 20:07:20 +00:00
12 changed files with 231 additions and 116 deletions

View File

@@ -2,6 +2,7 @@
// playwright.config.js
// @ts-check
// eslint-disable-next-line no-unused-vars
const { devices } = require('@playwright/test');
/** @type {import('@playwright/test').PlaywrightTestConfig} */

View File

@@ -2,6 +2,7 @@
// playwright.config.js
// @ts-check
// eslint-disable-next-line no-unused-vars
const { devices } = require('@playwright/test');
/** @type {import('@playwright/test').PlaywrightTestConfig} */

View File

@@ -58,6 +58,6 @@ test.describe('Branding tests', () => {
page.waitForEvent('popup'),
page.locator('text=click here for third party licensing information').click()
]);
expect(page2.waitForURL('**\/licenses**')).toBeTruthy();
expect(page2.waitForURL('**/licenses**')).toBeTruthy();
});
});

View File

@@ -25,6 +25,8 @@ This test suite is dedicated to tests which verify the basic operations surround
*/
const { test } = require('../../../fixtures.js');
// FIXME: Remove this eslint exception once tests are implemented
// eslint-disable-next-line no-unused-vars
const { expect } = require('@playwright/test');
test.describe('ExportAsJSON', () => {

View File

@@ -25,6 +25,8 @@ This test suite is dedicated to tests which verify the basic operations surround
*/
const { test } = require('../../../fixtures.js');
// FIXME: Remove this eslint exception once tests are implemented
// eslint-disable-next-line no-unused-vars
const { expect } = require('@playwright/test');
test.describe('ExportAsJSON', () => {

View File

@@ -235,113 +235,204 @@ test.describe('Example Imagery', () => {
// ('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 }) => {
// Go to baseURL
await page.goto('/', { waitUntil: 'networkidle' });
// Go to baseURL
await page.goto('/', { waitUntil: 'networkidle' });
// Click the Create button
await page.click('button:has-text("Create")');
// Click the Create button
await page.click('button:has-text("Create")');
// Click text=Example Imagery
await page.click('text=Example Imagery');
// Click text=Example Imagery
await page.click('text=Example Imagery');
// Clear and set Image load delay (milliseconds)
await page.click('input[type="number"]', {clickCount: 3})
await page.type('input[type="number"]', "20")
// Clear and set Image load delay (milliseconds)
await page.click('input[type="number"]', {clickCount: 3});
await page.type('input[type="number"]', "20");
// Click text=OK
await Promise.all([
page.waitForNavigation({waitUntil: 'networkidle'}),
page.click('text=OK'),
//Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message')
]);
// Wait until Save Banner is gone
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
const bgImageLocator = await page.locator(backgroundImageSelector);
await bgImageLocator.hover();
// Click text=OK
await Promise.all([
page.waitForNavigation({waitUntil: 'networkidle'}),
page.click('text=OK'),
//Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message')
]);
// Wait until Save Banner is gone
await page.waitForSelector('.c-message-banner__message', { state: 'detached'});
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery');
const bgImageLocator = await page.locator(backgroundImageSelector);
await bgImageLocator.hover();
// Click previous image button
const previousImageButton = await page.locator('.c-nav--prev');
await previousImageButton.click();
// Click previous image button
const previousImageButton = await page.locator('.c-nav--prev');
await previousImageButton.click();
// Verify previous image
const selectedImage = page.locator('.selected');
await expect(selectedImage).toBeVisible();
// Verify previous image
const selectedImage = page.locator('.selected');
await expect(selectedImage).toBeVisible();
// Zoom in
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
await bgImageLocator.hover();
const deltaYStep = 100; // equivalent to 1x zoom
await page.mouse.wheel(0, deltaYStep * 2);
const zoomedBoundingBox = await bgImageLocator.boundingBox();
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
// Zoom in
const originalImageDimensions = await page.locator(backgroundImageSelector).boundingBox();
await bgImageLocator.hover();
const deltaYStep = 100; // equivalent to 1x zoom
await page.mouse.wheel(0, deltaYStep * 2);
const zoomedBoundingBox = await bgImageLocator.boundingBox();
const imageCenterX = zoomedBoundingBox.x + zoomedBoundingBox.width / 2;
const imageCenterY = zoomedBoundingBox.y + zoomedBoundingBox.height / 2;
// Wait for zoom animation to finish
await bgImageLocator.hover();
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
// Wait for zoom animation to finish
await bgImageLocator.hover();
const imageMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
expect(imageMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
expect(imageMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
// Center the mouse pointer
await page.mouse.move(imageCenterX, imageCenterY);
// Center the mouse pointer
await page.mouse.move(imageCenterX, imageCenterY);
// Pan Imagery Hints
console.log('process.platform is '+process.platform);
const expectedAltText = process.platform === 'linux' ? 'Ctrl+Alt drag to pan' : 'Alt drag to pan';
const imageryHintsText = await page.locator('.c-imagery__hints').innerText();
expect(expectedAltText).toEqual(imageryHintsText);
// Pan Imagery Hints
console.log('process.platform is ' + process.platform);
const expectedAltText = process.platform === 'linux' ? 'Ctrl+Alt drag to pan' : 'Alt drag to pan';
const imageryHintsText = await page.locator('.c-imagery__hints').innerText();
expect(expectedAltText).toEqual(imageryHintsText);
// Click next image button
const nextImageButton = await page.locator('.c-nav--next');
await nextImageButton.click();
// Click next image button
const nextImageButton = await page.locator('.c-nav--next');
await nextImageButton.click();
// Click fixed timespan button
await page.locator('.c-button__label >> text=Fixed Timespan').click();
// Click fixed timespan button
await page.locator('.c-button__label >> text=Fixed Timespan').click();
// Click local clock
await page.locator('.icon-clock >> text=Local Clock').click();
// Click local clock
await page.locator('.icon-clock >> text=Local Clock').click();
// Zoom in on next image
await bgImageLocator.hover();
await page.mouse.wheel(0, deltaYStep * 2);
// Zoom in on next image
await bgImageLocator.hover();
await page.mouse.wheel(0, deltaYStep * 2);
// Wait for zoom animation to finish
await bgImageLocator.hover();
const imageNextMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
expect(imageNextMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
expect(imageNextMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
// Wait for zoom animation to finish
await bgImageLocator.hover();
const imageNextMouseZoomedIn = await page.locator(backgroundImageSelector).boundingBox();
expect(imageNextMouseZoomedIn.height).toBeGreaterThan(originalImageDimensions.height);
expect(imageNextMouseZoomedIn.width).toBeGreaterThan(originalImageDimensions.width);
// Click previous image button
await previousImageButton.click();
// Click previous image button
await previousImageButton.click();
// Verify previous image
await expect(selectedImage).toBeVisible();
// Verify previous image
await expect(selectedImage).toBeVisible();
// Wait 20ms to verify no new image has come in
await page.waitForTimeout(21);
// Wait 20ms to verify no new image has come in
await page.waitForTimeout(21);
//Get background-image url from background-image css prop
const backgroundImage = await page.locator('.c-imagery__main-image__background-image');
let backgroundImageUrl = await backgroundImage.evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue('background-image').match(/url\(([^)]+)\)/)[1];
});
let backgroundImageUrl1 = backgroundImageUrl.slice(1, -1); //forgive me, padre
console.log('backgroundImageUrl1 ' + backgroundImageUrl1)
//Get background-image url from background-image css prop
const backgroundImage = await page.locator('.c-imagery__main-image__background-image');
let backgroundImageUrl = await backgroundImage.evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue('background-image').match(/url\(([^)]+)\)/)[1];
});
let backgroundImageUrl1 = backgroundImageUrl.slice(1, -1); //forgive me, padre
console.log('backgroundImageUrl1 ' + backgroundImageUrl1);
// sleep 21ms
await page.waitForTimeout(21);
// sleep 21ms
await page.waitForTimeout(21);
// Verify next image has updated
let backgroundImageUrlNext = await backgroundImage.evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue('background-image').match(/url\(([^)]+)\)/)[1];
});
let backgroundImageUrl2 = backgroundImageUrlNext.slice(1, -1); //forgive me, padre
console.log('backgroundImageUrl2 ' + backgroundImageUrl2)
// Verify next image has updated
let backgroundImageUrlNext = await backgroundImage.evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue('background-image').match(/url\(([^)]+)\)/)[1];
});
let backgroundImageUrl2 = backgroundImageUrlNext.slice(1, -1); //forgive me, padre
console.log('backgroundImageUrl2 ' + backgroundImageUrl2);
// Expect backgroundImageUrl2 to be greater then backgroundImageUrl1
expect(backgroundImageUrl2 >= backgroundImageUrl1);
});
test.describe('Example imagery thumbnails resize in display layouts', () => {
test('Resizing the layout changes thumbnail visibility and size', async ({ page }) => {
await page.goto('/', { waitUntil: 'networkidle' });
const thumbsWrapperLocator = await page.locator('.c-imagery__thumbs-wrapper');
// Click button:has-text("Create")
await page.locator('button:has-text("Create")').click();
// Click li:has-text("Display Layout")
await page.locator('li:has-text("Display Layout")').click();
const displayLayoutTitleField = page.locator('text=Properties Title Notes Horizontal grid (px) Vertical grid (px) Horizontal size ( >> input[type="text"]');
await displayLayoutTitleField.click();
await displayLayoutTitleField.fill('Thumbnail Display Layout');
// Click text=OK
await Promise.all([
page.waitForNavigation(),
page.locator('text=OK').click()
]);
// Click text=Snapshot Save and Finish Editing Save and Continue Editing >> button >> nth=1
await page.locator('text=Snapshot Save and Finish Editing Save and Continue Editing >> button').nth(1).click();
// Click text=Save and Finish Editing
await page.locator('text=Save and Finish Editing').click();
// Click button:has-text("Create")
await page.locator('button:has-text("Create")').click();
// Click li:has-text("Example Imagery")
await page.locator('li:has-text("Example Imagery")').click();
const imageryTitleField = page.locator('text=Properties Title Notes Images url list (comma separated) Image load delay (milli >> input[type="text"]');
// Click text=Properties Title Notes Images url list (comma separated) Image load delay (milli >> input[type="text"]
await imageryTitleField.click();
// Fill text=Properties Title Notes Images url list (comma separated) Image load delay (milli >> input[type="text"]
await imageryTitleField.fill('Thumbnail Example Imagery');
// Click text=OK
await Promise.all([
page.waitForNavigation(),
page.locator('text=OK').click()
]);
// Click text=Thumbnail Example Imagery Imagery Layout Snapshot >> button >> nth=0
await Promise.all([
page.waitForNavigation(),
page.locator('text=Thumbnail Example Imagery Imagery Layout Snapshot >> button').first().click()
]);
// Edit mode
await page.locator('text=Thumbnail Display Layout Snapshot >> button').nth(3).click();
// Click on example imagery to expose toolbar
await page.locator('text=Thumbnail Example Imagery Snapshot Large View').click();
// expect thumbnails not be visible when first added
await expect.soft(thumbsWrapperLocator.isHidden()).toBeTruthy();
// Resize the example imagery vertically to change the thumbnail visibility
/*
The following arbitrary values are added to observe the separate visual
conditions of the thumbnails (hidden, small thumbnails, regular thumbnails).
Specifically, height is set to 50px for small thumbs and 100px for regular
*/
// Click #mct-input-id-103
await page.locator('#mct-input-id-103').click();
// Fill #mct-input-id-103
await page.locator('#mct-input-id-103').fill('50');
expect(thumbsWrapperLocator.isVisible()).toBeTruthy();
await expect(thumbsWrapperLocator).toHaveClass(/is-small-thumbs/);
// Resize the example imagery vertically to change the thumbnail visibility
// Click #mct-input-id-103
await page.locator('#mct-input-id-103').click();
// Fill #mct-input-id-103
await page.locator('#mct-input-id-103').fill('100');
expect(thumbsWrapperLocator.isVisible()).toBeTruthy();
await expect(thumbsWrapperLocator).not.toHaveClass(/is-small-thumbs/);
});
// Expect backgroundImageUrl2 to be greater then backgroundImageUrl1
expect(backgroundImageUrl2 >= backgroundImageUrl1);
});
test.describe('Example Imagery in Flexible layout', () => {

View File

@@ -242,6 +242,8 @@ async function saveOverlayPlot(page) {
/**
* @param {import('@playwright/test').Page} page
*/
// FIXME: Remove this eslint exception once implemented
// eslint-disable-next-line no-unused-vars
async function testLogPlotPixels(page) {
const pixelsMatch = await page.evaluate(async () => {
// TODO get canvas pixels at a few locations to make sure they're the correct color, to test that the plot comes out as expected.

View File

@@ -76,9 +76,6 @@ test.describe('Time conductor input fields real-time mode', () => {
//Go to baseURL
await page.goto('/', { waitUntil: 'networkidle' });
// Set realtime "local clock" mode offsets
const timeInputs = page.locator('input.c-input--datetime');
// Click fixed timespan button
await page.locator('.c-button__label >> text=Fixed Timespan').click();

View File

@@ -35,7 +35,7 @@
"git-rev-sync": "3.0.2",
"html2canvas": "1.4.1",
"imports-loader": "0.8.0",
"jasmine-core": "4.0.1",
"jasmine-core": "4.1.1",
"jsdoc": "3.5.5",
"karma": "6.3.18",
"karma-chrome-launcher": "3.1.1",
@@ -82,8 +82,8 @@
"clean": "rm -rf ./dist ./node_modules ./package-lock.json",
"clean-test-lint": "npm run clean; npm install; npm run test; npm run lint",
"start": "node app.js",
"lint": "eslint example src --ext .js,.vue openmct.js",
"lint:fix": "eslint example src --ext .js,.vue openmct.js --fix",
"lint": "eslint example src e2e --ext .js,.vue openmct.js",
"lint:fix": "eslint example src e2e --ext .js,.vue openmct.js --fix",
"build:prod": "cross-env webpack --config webpack.prod.js",
"build:dev": "webpack --config webpack.dev.js",
"build:coverage": "webpack --config webpack.coverage.js",

View File

@@ -55,7 +55,7 @@
<div
v-if="zoomFactor > 1"
class="c-imagery__hints"
>{{formatImageAltText}}</div>
>{{ formatImageAltText }}</div>
<div
ref="focusedImageWrapper"
class="image-wrapper"

View File

@@ -46,7 +46,6 @@ export default {
// kickoff
this.subscribe();
this.requestHistory();
},
beforeDestroy() {
if (this.unsubscribe) {
@@ -169,8 +168,6 @@ export default {
// splice array to encourage garbage collection
this.imageHistory.splice(0, this.imageHistory.length);
// requesting history effectively clears imageHistory array
return this.requestHistory();
},
timeSystemChange() {
this.timeSystem = this.timeContext.timeSystem();

View File

@@ -25,39 +25,60 @@
<div class="c-inspect-properties__header">
Details
</div>
<ul
v-if="hasDetails"
class="c-inspect-properties__section"
>
<Component
:is="getComponent(detail)"
v-for="detail in details"
:key="detail.name"
:detail="detail"
<ObjectView
style="min-height:300px;"
:default-object="defaultObject"
:show-edit-view="showEditView"
:object-view-key="objectViewKey"
/>
</ul>
<div
v-else
class="c-inspect-properties__row--span-all"
>
{{ noDetailsMessage }}
</div>
</div>
</template>
<script>
import Moment from 'moment';
import DetailText from './DetailText.vue';
import ObjectView from '../../components/ObjectView.vue';
export default {
components: {
DetailText
ObjectView
},
inject: ['openmct'],
data() {
const STACKED_PLOT_TYPE_KEY = 'telemetry.plot.stacked';
const stackedPlotType = this.openmct.types.get(STACKED_PLOT_TYPE_KEY);
const composition = [
'b66a22b6-7f12-4358-bd95-a9092486ddd3',
'0072d390-12b6-4ecc-93e5-2598df36b6d7'
];
const tempStackedPlot = {
identifier: {
namespace: '',
key: 'temporary-stacked-plot'
},
name: 'Data Pivot',
type: STACKED_PLOT_TYPE_KEY
};
stackedPlotType.definition.initialize(tempStackedPlot);
tempStackedPlot.configuration = {
useIndependentTime: true,
timeOptions: {
mode: {
key: "fixed" //'local'
},
fixedOffsets: {
start: 1653334980000, //timestamp
end: 1653335080000
}
}
};
tempStackedPlot.composition.push(...composition);
return {
selection: undefined
selection: undefined,
defaultObject: tempStackedPlot,
showEditView: false,
objectViewKey: 'plot-stacked'
};
},
computed: {
@@ -200,6 +221,7 @@ export default {
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection(this.openmct.selection.get());
},
beforeDestroy() {
this.openmct.selection.off('change', this.updateSelection);