Compare commits
19 Commits
6359-sub-o
...
performanc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0fd1f0171 | ||
|
|
c7fd584b58 | ||
|
|
16ca994cfa | ||
|
|
ebe5323f82 | ||
|
|
7a8a6d3649 | ||
|
|
25e7a16c77 | ||
|
|
141939295a | ||
|
|
2c1040c7c0 | ||
|
|
d94fe8806b | ||
|
|
7bf983210c | ||
|
|
8f92cd4206 | ||
|
|
13311b9fc8 | ||
|
|
2daec448da | ||
|
|
5bd8d17592 | ||
|
|
954c72b100 | ||
|
|
43338f3980 | ||
|
|
1414f54c17 | ||
|
|
9849e0398e | ||
|
|
76889cf60d |
@@ -15,7 +15,8 @@ module.exports = {
|
||||
'plugin:compat/recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:you-dont-need-lodash-underscore/compatible',
|
||||
'plugin:prettier/recommended'
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:no-unsanitized/DOM'
|
||||
],
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
|
||||
2
.github/workflows/e2e-couchdb.yml
vendored
2
.github/workflows/e2e-couchdb.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/hydrogen'
|
||||
|
||||
|
||||
2
.github/workflows/e2e-pr.yml
vendored
2
.github/workflows/e2e-pr.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
- windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/hydrogen'
|
||||
|
||||
|
||||
4
.github/workflows/npm-prerelease.yml
vendored
4
.github/workflows/npm-prerelease.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/hydrogen
|
||||
- run: npm install
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/hydrogen
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
2
.github/workflows/pr-platform.yml
vendored
2
.github/workflows/pr-platform.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
architecture: ${{ matrix.architecture }}
|
||||
|
||||
@@ -77,8 +77,7 @@ const config = {
|
||||
MCT: path.join(projectRootDir, 'src/MCT'),
|
||||
testUtils: path.join(projectRootDir, 'src/utils/testUtils.js'),
|
||||
objectUtils: path.join(projectRootDir, 'src/api/objects/object-utils.js'),
|
||||
utils: path.join(projectRootDir, 'src/utils'),
|
||||
vue: path.join(projectRootDir, 'node_modules/@vue/compat/dist/vue.esm-bundler.js'),
|
||||
utils: path.join(projectRootDir, 'src/utils')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
@@ -86,7 +85,9 @@ const config = {
|
||||
__OPENMCT_VERSION__: `'${packageDefinition.version}'`,
|
||||
__OPENMCT_BUILD_DATE__: `'${new Date()}'`,
|
||||
__OPENMCT_REVISION__: `'${gitRevision}'`,
|
||||
__OPENMCT_BUILD_BRANCH__: `'${gitBranch}'`
|
||||
__OPENMCT_BUILD_BRANCH__: `'${gitBranch}'`,
|
||||
__VUE_OPTIONS_API__: true, // enable/disable Options API support, default: true
|
||||
__VUE_PROD_DEVTOOLS__: false // enable/disable devtools support in production, default: false
|
||||
}),
|
||||
new VueLoaderPlugin(),
|
||||
new CopyWebpackPlugin({
|
||||
@@ -115,7 +116,7 @@ const config = {
|
||||
new webpack.BannerPlugin({
|
||||
test: /.*Theme\.css$/,
|
||||
raw: true,
|
||||
banner: '@charset "UTF-8";',
|
||||
banner: '@charset "UTF-8";'
|
||||
})
|
||||
],
|
||||
module: {
|
||||
@@ -142,10 +143,7 @@ const config = {
|
||||
options: {
|
||||
compilerOptions: {
|
||||
hoistStatic: false,
|
||||
whitespace: 'preserve',
|
||||
compatConfig: {
|
||||
MODE: 2
|
||||
}
|
||||
whitespace: 'preserve'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
59
e2e/tests/functional/clearDataAction.e2e.spec.js
Normal file
59
e2e/tests/functional/clearDataAction.e2e.spec.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2023, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
Verify that the "Clear Data" menu action performs as expected for various object types.
|
||||
*/
|
||||
|
||||
const { test, expect } = require('../../pluginFixtures.js');
|
||||
const { createDomainObjectWithDefaults } = require('../../appActions.js');
|
||||
|
||||
const backgroundImageSelector = '.c-imagery__main-image__background-image';
|
||||
|
||||
test.describe('Clear Data Action', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create a default 'Example Imagery' object
|
||||
const exampleImagery = await createDomainObjectWithDefaults(page, { type: 'Example Imagery' });
|
||||
|
||||
// Verify that the created object is focused
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText(exampleImagery.name);
|
||||
await page.locator('.c-imagery__main-image__bg').hover({ trial: true });
|
||||
await expect(page.locator(backgroundImageSelector)).toBeVisible();
|
||||
});
|
||||
test('works as expected with Example Imagery', async ({ page }) => {
|
||||
await expect(await page.locator('.c-thumb__image').count()).toBeGreaterThan(0);
|
||||
// Click the "Clear Data" menu action
|
||||
await page.getByTitle('More options').click();
|
||||
const clearDataMenuItem = page.getByRole('menuitem', {
|
||||
name: 'Clear Data'
|
||||
});
|
||||
await expect(clearDataMenuItem).toBeEnabled();
|
||||
await clearDataMenuItem.click();
|
||||
|
||||
// Verify that the background image is no longer visible
|
||||
await expect(page.locator(backgroundImageSelector)).toBeHidden();
|
||||
await expect(await page.locator('.c-thumb__image').count()).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,7 @@ test.describe('The Fault Management Plugin using example faults', () => {
|
||||
}) => {
|
||||
await utils.selectFaultItem(page, 1);
|
||||
|
||||
await page.getByRole('tab', { name: 'Fault Management Configuration' }).click();
|
||||
await page.getByRole('tab', { name: 'Config' }).click();
|
||||
const selectedFaultName = await page
|
||||
.locator('.c-fault-mgmt__list.is-selected .c-fault-mgmt__list-faultname')
|
||||
.textContent();
|
||||
@@ -65,7 +65,7 @@ test.describe('The Fault Management Plugin using example faults', () => {
|
||||
);
|
||||
expect.soft(await selectedRows.count()).toEqual(2);
|
||||
|
||||
await page.getByRole('tab', { name: 'Fault Management Configuration' }).click();
|
||||
await page.getByRole('tab', { name: 'Config' }).click();
|
||||
const firstSelectedFaultName = await selectedRows.nth(0).textContent();
|
||||
const secondSelectedFaultName = await selectedRows.nth(1).textContent();
|
||||
const firstNameInInspectorCount = await page
|
||||
|
||||
@@ -77,11 +77,11 @@ test.describe('Grand Search', () => {
|
||||
|
||||
// Click [aria-label="OpenMCT Search"] a >> nth=0
|
||||
await page.locator('[aria-label="Search Result"] >> nth=0').click();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeInViewport();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden();
|
||||
|
||||
// Fill [aria-label="OpenMCT Search"] input[type="search"]
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('foo');
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).not.toBeInViewport();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden();
|
||||
|
||||
// Click text=Snapshot Save and Finish Editing Save and Continue Editing >> button >> nth=1
|
||||
await page
|
||||
|
||||
@@ -89,20 +89,6 @@ test.describe('Verify tooltips', () => {
|
||||
await expandEntireTree(page);
|
||||
});
|
||||
|
||||
// LAD Tables - DONE
|
||||
// Expanded collapsed plot legend - DONE
|
||||
// Object Labels - DONE
|
||||
// Display Layout headers - DONE
|
||||
// Flexible Layout headers - DONE
|
||||
// Tab View layout headers - DONE
|
||||
// Search - DONE
|
||||
// Gauge -
|
||||
// Notebook Embed - DONE
|
||||
// Telemetry Table -
|
||||
// Timeline Objects
|
||||
// Tree - DONE
|
||||
// Recent Objects
|
||||
|
||||
test('display correct paths for LAD tables', async ({ page, openmctConfig }) => {
|
||||
// Create LAD table
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
@@ -254,13 +240,13 @@ test.describe('Verify tooltips', () => {
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe('My Items / Test Overlay Plot');
|
||||
|
||||
// await page.keyboard.up('Control');
|
||||
// await page.locator('.c-plot-legend__view-control >> nth=0').click();
|
||||
// await page.keyboard.down('Control');
|
||||
// await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover();
|
||||
// tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
await page.keyboard.up('Control');
|
||||
await page.locator('.c-plot-legend__view-control >> nth=0').click();
|
||||
await page.keyboard.down('Control');
|
||||
await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
|
||||
await page.getByText('Test Stacked Plot').nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
@@ -345,18 +331,18 @@ test.describe('Verify tooltips', () => {
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
test('display path for source telemetry when hovering over gauge', ({ page }) => {
|
||||
expect(true).toBe(true);
|
||||
// await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Gauge',
|
||||
// name: 'Test Gauge'
|
||||
// });
|
||||
// await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-gauge__wrapper');
|
||||
// await page.keyboard.down('Control');
|
||||
// await page.locator('.c-gauge__current-value-text-wrapper').hover();
|
||||
// let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
test('display path for source telemetry when hovering over gauge', async ({ page }) => {
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Gauge',
|
||||
name: 'Test Gauge'
|
||||
});
|
||||
await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-gauge__wrapper');
|
||||
await page.keyboard.down('Control');
|
||||
// eslint-disable-next-line playwright/no-force-option
|
||||
await page.locator('.c-gauge.c-dial').hover({ position: { x: 0, y: 0 }, force: true });
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for notebook embeds', async ({ page }) => {
|
||||
@@ -373,26 +359,105 @@ test.describe('Verify tooltips', () => {
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
// test('display tooltip path for telemetry table names', async ({ page }) => {
|
||||
// await setEndOffset(page, { secs: '10' });
|
||||
// await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Telemetry Table',
|
||||
// name: 'Test Telemetry Table'
|
||||
// });
|
||||
test('display tooltip path for telemetry table names', async ({ page }) => {
|
||||
// set endBound to 10 seconds after start bound
|
||||
const url = await page.url();
|
||||
const parsedUrl = new URL(url.replace('#', '!'));
|
||||
const startBound = Number(parsedUrl.searchParams.get('tc.startBound'));
|
||||
const tenSecondsInMilliseconds = 10 * 1000;
|
||||
const endBound = startBound + tenSecondsInMilliseconds;
|
||||
parsedUrl.searchParams.set('tc.endBound', endBound);
|
||||
await page.goto(parsedUrl.href.replace('!', '#'));
|
||||
|
||||
// await page.dragAndDrop(`text=${sineWaveObject1.name}`, '.c-telemetry-table');
|
||||
// await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-telemetry-table');
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Telemetry Table',
|
||||
name: 'Test Telemetry Table'
|
||||
});
|
||||
|
||||
// await page.locator('button[title="Save"]').click();
|
||||
// await page.locator('text=Save and Finish Editing').click();
|
||||
await page.dragAndDrop(`text=${sineWaveObject1.name}`, '.c-telemetry-table');
|
||||
await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-telemetry-table');
|
||||
|
||||
// // .c-telemetry-table__body
|
||||
await page.locator('button[title="Save"]').click();
|
||||
await page.locator('text=Save and Finish Editing').click();
|
||||
await page.keyboard.down('Control');
|
||||
|
||||
// await page.keyboard.down('Control');
|
||||
await page.locator('.noselect > [title="SWG 3"]').first().hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
|
||||
// await page.locator('.noselect > [title="SWG 3"]').first().hover();
|
||||
// let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
// });
|
||||
await page.locator('.noselect > [title="SWG 1"]').first().hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for recently viewed items', async ({ page }) => {
|
||||
// drag up Recently Viewed pane
|
||||
await page
|
||||
.locator('.l-pane.l-pane--vertical-handle-before', {
|
||||
hasText: 'Recently Viewed'
|
||||
})
|
||||
.locator('.l-pane__handle')
|
||||
.hover();
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(0, 300);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.keyboard.down('Control');
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject3.name).hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject2.name).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject2.path);
|
||||
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject1.name).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for time strips', async ({ page }) => {
|
||||
// Create Time Strip
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Time Strip',
|
||||
name: 'Test Time Strip'
|
||||
});
|
||||
// Edit Overlay Plot
|
||||
await page.locator('[title="Edit"]').click();
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject1.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject2.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject3.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.locator('button[title="Save"]').click();
|
||||
await page.locator('text=Save and Finish Editing').click();
|
||||
|
||||
await page.keyboard.down('Control');
|
||||
await page.getByText(sineWaveObject1.name).nth(2).hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
|
||||
await page.getByText(sineWaveObject2.name).nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject2.path);
|
||||
|
||||
await page.getByText(sineWaveObject3.name).nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
||||
randomness: 0,
|
||||
phase: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false
|
||||
infinityValues: false,
|
||||
exceedFloat32: false
|
||||
};
|
||||
|
||||
function GeneratorProvider(openmct, StalenessProvider) {
|
||||
@@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
||||
'randomness',
|
||||
'phase',
|
||||
'loadDelay',
|
||||
'infinityValues'
|
||||
'infinityValues',
|
||||
'exceedFloat32'
|
||||
];
|
||||
|
||||
request = request || {};
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues
|
||||
data.infinityValues,
|
||||
data.exceedFloat32
|
||||
),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
@@ -96,7 +97,8 @@
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues
|
||||
data.infinityValues,
|
||||
data.exceedFloat32
|
||||
)
|
||||
}
|
||||
});
|
||||
@@ -136,6 +138,7 @@
|
||||
var randomness = request.randomness;
|
||||
var loadDelay = Math.max(request.loadDelay, 0);
|
||||
var infinityValues = request.infinityValues;
|
||||
var exceedFloat32 = request.exceedFloat32;
|
||||
|
||||
var step = 1000 / dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
@@ -146,10 +149,28 @@
|
||||
data.push({
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues),
|
||||
sin: sin(
|
||||
nextStep,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues)
|
||||
cos: cos(
|
||||
nextStep,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -176,9 +197,26 @@
|
||||
});
|
||||
}
|
||||
|
||||
function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
function cos(
|
||||
timestamp,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
) {
|
||||
if (infinityValues && exceedFloat32) {
|
||||
if (Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
} else if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -188,9 +226,26 @@
|
||||
);
|
||||
}
|
||||
|
||||
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
function sin(
|
||||
timestamp,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
) {
|
||||
if (infinityValues && exceedFloat32) {
|
||||
if (Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
} else if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -200,6 +255,13 @@
|
||||
);
|
||||
}
|
||||
|
||||
// Values exceeding float32 range (Positive: 3.4+38, Negative: -3.4+38)
|
||||
function getRandomFloat32OverflowValue() {
|
||||
const sign = Math.random() > 0.5 ? 1 : -1;
|
||||
|
||||
return sign * 3.4e39;
|
||||
}
|
||||
|
||||
function wavelengths() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
|
||||
@@ -122,6 +122,13 @@ export default function (openmct) {
|
||||
key: 'infinityValues',
|
||||
property: ['telemetry', 'infinityValues']
|
||||
},
|
||||
{
|
||||
name: 'Exceed Float32 Limits',
|
||||
control: 'toggleSwitch',
|
||||
cssClass: 'l-input',
|
||||
key: 'exceedFloat32',
|
||||
property: ['telemetry', 'exceedFloat32']
|
||||
},
|
||||
{
|
||||
name: 'Provide Staleness Updates',
|
||||
control: 'toggleSwitch',
|
||||
@@ -140,6 +147,7 @@ export default function (openmct) {
|
||||
randomness: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false,
|
||||
exceedFloat32: false,
|
||||
staleness: false
|
||||
};
|
||||
}
|
||||
|
||||
22
package.json
22
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "3.1.0-next",
|
||||
"version": "3.2.0-next",
|
||||
"description": "The Open MCT core platform",
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "7.22.5",
|
||||
"@braintree/sanitize-url": "6.0.2",
|
||||
"@braintree/sanitize-url": "6.0.4",
|
||||
"@deploysentinel/playwright": "0.3.4",
|
||||
"@percy/cli": "1.26.0",
|
||||
"@percy/playwright": "1.0.4",
|
||||
@@ -12,14 +12,13 @@
|
||||
"@types/eventemitter3": "1.2.0",
|
||||
"@types/jasmine": "4.3.4",
|
||||
"@types/lodash": "4.14.192",
|
||||
"@vue/compat": "3.3.4",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"babel-loader": "9.1.0",
|
||||
"babel-plugin-istanbul": "6.1.1",
|
||||
"codecov": "3.8.3",
|
||||
"comma-separated-values": "3.6.4",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"cspell": "7.3.6",
|
||||
"cspell": "7.3.8",
|
||||
"css-loader": "6.8.1",
|
||||
"d3-axis": "3.0.0",
|
||||
"d3-scale": "3.3.0",
|
||||
@@ -27,11 +26,12 @@
|
||||
"eslint": "8.48.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-plugin-compat": "4.2.0",
|
||||
"eslint-plugin-no-unsanitized": "4.0.2",
|
||||
"eslint-plugin-playwright": "0.12.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "10.0.0",
|
||||
"eslint-plugin-unicorn": "44.0.2",
|
||||
"eslint-plugin-vue": "9.15.0",
|
||||
"eslint-plugin-unicorn": "48.0.1",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "6.12.0",
|
||||
"eventemitter3": "1.2.0",
|
||||
"file-saver": "2.0.5",
|
||||
@@ -39,7 +39,7 @@
|
||||
"git-rev-sync": "3.0.2",
|
||||
"html2canvas": "1.4.1",
|
||||
"imports-loader": "4.0.1",
|
||||
"jasmine-core": "5.0.0",
|
||||
"jasmine-core": "5.1.1",
|
||||
"karma": "6.4.2",
|
||||
"karma-chrome-launcher": "3.2.0",
|
||||
"karma-cli": "2.0.0",
|
||||
@@ -59,22 +59,22 @@
|
||||
"moment-timezone": "0.5.41",
|
||||
"npm-run-all2": "6.0.6",
|
||||
"nyc": "15.1.0",
|
||||
"painterro": "1.2.78",
|
||||
"painterro": "1.2.87",
|
||||
"plotly.js-basic-dist": "2.20.0",
|
||||
"plotly.js-gl2d-dist": "2.20.0",
|
||||
"prettier": "2.8.7",
|
||||
"printj": "1.3.1",
|
||||
"resolve-url-loader": "5.0.0",
|
||||
"sanitize-html": "2.11.0",
|
||||
"sass": "1.63.4",
|
||||
"sass": "1.68.0",
|
||||
"sass-loader": "13.3.2",
|
||||
"sinon": "15.1.0",
|
||||
"sinon": "17.0.0",
|
||||
"style-loader": "3.3.3",
|
||||
"tiny-emitter": "2.1.0",
|
||||
"typescript": "5.2.2",
|
||||
"uuid": "9.0.0",
|
||||
"vue": "3.3.4",
|
||||
"vue-eslint-parser": "9.3.1",
|
||||
"vue-eslint-parser": "9.3.2",
|
||||
"vue-loader": "16.8.3",
|
||||
"webpack": "5.88.0",
|
||||
"webpack-cli": "5.1.1",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from '../../utils/testing';
|
||||
import Menu from './menu';
|
||||
@@ -186,7 +186,7 @@ describe('The Menu API', () => {
|
||||
superMenuItem.dispatchEvent(mouseOverEvent);
|
||||
const itemDescription = document.querySelector('.l-item-description__description');
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(menuElement).not.toBeNull();
|
||||
expect(itemDescription.innerText).toEqual(actionsArray[0].description);
|
||||
|
||||
|
||||
@@ -71,11 +71,6 @@ class Menu extends EventEmitter {
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
// TODO: Remove this exception upon full migration to Vue 3
|
||||
// https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#render-function-argument
|
||||
compatConfig: {
|
||||
RENDER_FUNCTION: false
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,11 +93,6 @@ class Menu extends EventEmitter {
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
// TODO: Remove this exception upon full migration to Vue 3
|
||||
// https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#render-function-argument
|
||||
compatConfig: {
|
||||
RENDER_FUNCTION: false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ export default class ObjectAPI {
|
||||
const provider = this.getProvider(identifier);
|
||||
|
||||
if (!provider) {
|
||||
throw new Error(`No Provider Matched for keyString "${this.makeKeyString(identifier)}}"`);
|
||||
throw new Error(`No Provider Matched for keyString "${this.makeKeyString(identifier)}"`);
|
||||
}
|
||||
|
||||
if (!provider.get) {
|
||||
|
||||
@@ -192,11 +192,7 @@ export default {
|
||||
reorderLadTables(reorderPlan) {
|
||||
let oldComposition = this.ladTableObjects.slice();
|
||||
reorderPlan.forEach((reorderEvent) => {
|
||||
this.$set(
|
||||
this.ladTableObjects,
|
||||
reorderEvent.newIndex,
|
||||
oldComposition[reorderEvent.oldIndex]
|
||||
);
|
||||
this.ladTableObjects[reorderEvent.newIndex] = oldComposition[reorderEvent.oldIndex];
|
||||
});
|
||||
},
|
||||
addTelemetryObject(ladTable) {
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
resetApplicationState,
|
||||
spyOnBuiltins
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import LadPlugin from './plugin.js';
|
||||
|
||||
@@ -233,7 +233,7 @@ describe('The LAD Table', () => {
|
||||
anotherTelemetryObjectPromise,
|
||||
aggregateTelemetryObjectResolve
|
||||
]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should show one row per object in the composition', () => {
|
||||
@@ -244,7 +244,7 @@ describe('The LAD Table', () => {
|
||||
it('should show the most recent datum from the telemetry producing object', async () => {
|
||||
const latestDatum = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||
const expectedDate = utcTimeFormat(latestDatum[timeFormat]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const latestDate = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||
expect(latestDate).toBe(expectedDate);
|
||||
const dataType = parent
|
||||
@@ -254,7 +254,7 @@ describe('The LAD Table', () => {
|
||||
});
|
||||
|
||||
it('should show aggregate telemetry type with blank data', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const latestData = parent
|
||||
.querySelectorAll(TABLE_BODY_ROWS)[1]
|
||||
.querySelectorAll('td')[2].innerText;
|
||||
@@ -282,7 +282,7 @@ describe('The LAD Table', () => {
|
||||
const mostRecentTelemetry = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||
const rangeValue = mostRecentTelemetry[range];
|
||||
const domainValue = utcTimeFormat(mostRecentTelemetry[domain]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const actualDomainValue = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||
const actualRangeValue = parent.querySelector(TABLE_BODY_FIRST_ROW_THIRD_DATA).innerText;
|
||||
expect(actualRangeValue).toBe(rangeValue);
|
||||
@@ -424,7 +424,7 @@ describe('The LAD Table Set', () => {
|
||||
ladTableSetView = ladTableSetViewProvider.view(mockObj.ladTableSet, [mockObj.ladTableSet]);
|
||||
ladTableSetView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('should show one row per lad table object in the composition', () => {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import { createOpenMct, resetApplicationState, spyOnBuiltins } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import AutoflowTabularConstants from './AutoflowTabularConstants';
|
||||
import AutoflowTabularPlugin from './AutoflowTabularPlugin';
|
||||
@@ -175,7 +175,7 @@ xdescribe('AutoflowTabularPlugin', () => {
|
||||
view = provider.view(testObject, [testObject]);
|
||||
view.show(testContainer);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import BarGraphOptions from './BarGraphOptions.vue';
|
||||
export default function BarGraphInspectorViewProvider(openmct) {
|
||||
return {
|
||||
key: BAR_GRAPH_INSPECTOR_KEY,
|
||||
name: 'Bar Graph Configuration',
|
||||
name: 'Config',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// import BarGraph from './BarGraphPlot.vue';
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { BAR_GRAPH_KEY, BAR_GRAPH_VIEW } from './BarGraphConstants';
|
||||
import { BAR_GRAPH_INSPECTOR_KEY, BAR_GRAPH_KEY, BAR_GRAPH_VIEW } from './BarGraphConstants';
|
||||
import BarGraphPlugin from './plugin';
|
||||
|
||||
describe('the plugin', function () {
|
||||
@@ -153,7 +153,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('provides a bar graph view', () => {
|
||||
@@ -254,7 +254,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('Renders spectral plots', async () => {
|
||||
@@ -305,8 +305,8 @@ describe('the plugin', function () {
|
||||
barGraphView.show(child, true);
|
||||
mockComposition.emit('add', dotFullTelemetryObject);
|
||||
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
const plotElement = element.querySelector('.cartesianlayer .scatterlayer .trace .lines');
|
||||
expect(plotElement).not.toBeNull();
|
||||
@@ -578,12 +578,10 @@ describe('the plugin', function () {
|
||||
child.append(viewContainer);
|
||||
|
||||
const applicableViews = openmct.inspectorViews.get(selection);
|
||||
plotInspectorView = applicableViews.filter(
|
||||
(view) => view.name === 'Bar Graph Configuration'
|
||||
)[0];
|
||||
plotInspectorView = applicableViews.filter((view) => view.key === BAR_GRAPH_INSPECTOR_KEY)[0];
|
||||
plotInspectorView.show(viewContainer);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
optionsElement = element.querySelector('.c-bar-graph-options');
|
||||
});
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ScatterPlotPlugin from './plugin';
|
||||
import { SCATTER_PLOT_KEY, SCATTER_PLOT_VIEW } from './scatterPlotConstants';
|
||||
@@ -178,7 +178,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('provides a scatter plot view', () => {
|
||||
@@ -406,7 +406,7 @@ describe('the plugin', function () {
|
||||
plotInspectorView = applicableViews[0];
|
||||
plotInspectorView.show(viewContainer);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
optionsElement = element.querySelector('.c-scatter-plot-options');
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ClearDataPlugin from './plugin.js';
|
||||
|
||||
@@ -213,7 +213,7 @@ describe('The Clear Data Plugin:', () => {
|
||||
});
|
||||
|
||||
it('renders its major elements', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const indicatorClass = appHolder.querySelector('.c-indicator');
|
||||
const iconClass = appHolder.querySelector('.icon-clear-data');
|
||||
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import clockPlugin from './plugin';
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('Clock plugin:', () => {
|
||||
clockView = clockViewProvider.view(mutableClockObject);
|
||||
clockView.show(child);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
});
|
||||
|
||||
@@ -232,7 +232,7 @@ describe('Clock plugin:', () => {
|
||||
it('contains text', async () => {
|
||||
await setupClock(true);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
|
||||
clockIndicator = openmct.indicators.indicatorObjects.find(
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<!-- Save Styles -->
|
||||
<toolbar-button
|
||||
v-if="canSaveStyle"
|
||||
ref="saveStyleButton"
|
||||
class="c-style__toolbar-button--save c-local-controls--show-on-hover c-icon-button c-icon-button--major"
|
||||
:options="saveOptions"
|
||||
@click="saveItemStyle()"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<div class="c-inspect-styles__content">
|
||||
<div v-if="staticStyle" class="c-inspect-styles__style">
|
||||
<StyleEditor
|
||||
ref="styleEditor"
|
||||
class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="allowEditing"
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import mount from 'utils/mount';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ConditionManager from '@/plugins/condition/ConditionManager';
|
||||
|
||||
@@ -142,6 +143,7 @@ describe('the plugin', function () {
|
||||
let conditionWidgetItem;
|
||||
let selection;
|
||||
let component;
|
||||
let _destroy;
|
||||
let styleViewComponentObject;
|
||||
const conditionSetDomainObject = {
|
||||
configuration: {
|
||||
@@ -238,8 +240,7 @@ describe('the plugin', function () {
|
||||
];
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
const { vNode, destroy } = mount({
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
@@ -248,17 +249,20 @@ describe('the plugin', function () {
|
||||
selection: selection,
|
||||
stylesManager
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
template: '<styles-view ref="root"/>'
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
styleViewComponentObject = component.$root.$children[0];
|
||||
component = vNode.componentInstance;
|
||||
_destroy = destroy;
|
||||
|
||||
return nextTick().then(() => {
|
||||
styleViewComponentObject = component.$refs.root;
|
||||
styleViewComponentObject.setEditState(true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.$destroy();
|
||||
_destroy();
|
||||
});
|
||||
|
||||
it('does not include the output label when the flag is disabled', () => {
|
||||
@@ -267,7 +271,7 @@ describe('the plugin', function () {
|
||||
styleViewComponentObject.initializeConditionalStyles();
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
const hasNoOutput =
|
||||
styleViewComponentObject.domainObject.configuration.objectStyles.styles.every((style) => {
|
||||
return style.style.output === '' || style.style.output === undefined;
|
||||
@@ -286,7 +290,7 @@ describe('the plugin', function () {
|
||||
styleViewComponentObject.useConditionSetOutputAsLabel = true;
|
||||
styleViewComponentObject.persistLabelConfiguration();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
const outputs = styleViewComponentObject.domainObject.configuration.objectStyles.styles.map(
|
||||
(style) => {
|
||||
return style.style.output;
|
||||
@@ -306,6 +310,7 @@ describe('the plugin', function () {
|
||||
let selection;
|
||||
let component;
|
||||
let styleViewComponentObject;
|
||||
let _destroy;
|
||||
const conditionSetDomainObject = {
|
||||
configuration: {
|
||||
conditionTestData: [
|
||||
@@ -560,8 +565,7 @@ describe('the plugin', function () {
|
||||
];
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
const { vNode, destroy } = mount({
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
@@ -570,15 +574,22 @@ describe('the plugin', function () {
|
||||
selection: selection,
|
||||
stylesManager
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
template: '<styles-view ref="root"/>'
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
styleViewComponentObject = component.$root.$children[0];
|
||||
component = vNode.componentInstance;
|
||||
_destroy = destroy;
|
||||
|
||||
return nextTick().then(() => {
|
||||
styleViewComponentObject = component.$refs.root;
|
||||
styleViewComponentObject.setEditState(true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
_destroy();
|
||||
});
|
||||
|
||||
it('initializes the items in the view', () => {
|
||||
expect(styleViewComponentObject.items.length).toBe(3);
|
||||
});
|
||||
@@ -597,7 +608,7 @@ describe('the plugin', function () {
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
styleViewComponentObject.updateConditionalStyle(conditionalStyle, 'border');
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
|
||||
[boxLayoutItem, lineLayoutItem, notCreatableObjectItem].forEach((item) => {
|
||||
const itemStyles =
|
||||
@@ -627,7 +638,7 @@ describe('the plugin', function () {
|
||||
it('updates applicable static styles', () => {
|
||||
styleViewComponentObject.updateStaticStyle(staticStyle, 'border');
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
|
||||
[boxLayoutItem, lineLayoutItem, notCreatableObjectItem].forEach((item) => {
|
||||
const itemStyle =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ConditionWidgetPlugin from './plugin';
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('the plugin', function () {
|
||||
let view = conditionWidgetView.view(testViewObject, element);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('provides a view', () => {
|
||||
@@ -184,7 +184,7 @@ describe('the plugin', function () {
|
||||
);
|
||||
conditionWidgetView.show(urlChild);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const domainUrl = mockConditionObject[CONDITION_WIDGET_KEY].url;
|
||||
expect(urlParent.innerHTML).toContain(
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import DisplayLayoutPlugin from './plugin';
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('the plugin', function () {
|
||||
const view = displayLayoutViewProvider.view(displayLayoutItem, displayLayoutItem);
|
||||
view.show(child, false);
|
||||
|
||||
Vue.nextTick(done);
|
||||
nextTick(done);
|
||||
});
|
||||
|
||||
it('will sync composition and layout items', () => {
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function FaultManagementInspectorViewProvider(openmct) {
|
||||
return {
|
||||
openmct: openmct,
|
||||
key: FAULT_MANAGEMENT_INSPECTOR,
|
||||
name: 'Fault Management Configuration',
|
||||
name: 'Config',
|
||||
canView: (selection) => {
|
||||
if (selection.length !== 1 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
import { createOpenMct, resetApplicationState } from '../../utils/testing';
|
||||
import {
|
||||
FAULT_MANAGEMENT_INSPECTOR,
|
||||
FAULT_MANAGEMENT_NAMESPACE,
|
||||
FAULT_MANAGEMENT_TYPE,
|
||||
FAULT_MANAGEMENT_VIEW
|
||||
@@ -86,7 +87,7 @@ describe('The Fault Management Plugin', () => {
|
||||
];
|
||||
const applicableInspectorViews = openmct.inspectorViews.get(faultDomainObjectSelection);
|
||||
const faultManagementInspectorView = applicableInspectorViews.filter(
|
||||
(view) => view.name === 'Fault Management Configuration'
|
||||
(view) => view.key === FAULT_MANAGEMENT_INSPECTOR
|
||||
);
|
||||
|
||||
expect(faultManagementInspectorView.length).toEqual(1);
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
type="text"
|
||||
:aria-label="label"
|
||||
:disabled="useGlobal"
|
||||
:value="persistedValue(filter)"
|
||||
@change="updateFilterValueFromString($event, filter)"
|
||||
:value="persistedValue(filter.comparator)"
|
||||
@change="updateFilterValueFromString($event, filter.comparator)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import { toRaw } from 'vue';
|
||||
|
||||
import FilterObject from './FilterObject.vue';
|
||||
import GlobalFilters from './GlobalFilters.vue';
|
||||
@@ -155,11 +156,7 @@ export default {
|
||||
mutateFilters = true;
|
||||
}
|
||||
|
||||
this.$set(
|
||||
this.persistedFilters[keyString],
|
||||
metadatum.key,
|
||||
this.globalFilters[metadatum.key]
|
||||
);
|
||||
this.persistedFilters[keyString][metadatum.key] = this.globalFilters[metadatum.key];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -271,14 +268,14 @@ export default {
|
||||
this.openmct.objects.mutate(
|
||||
this.providedObject,
|
||||
'configuration.filters',
|
||||
this.persistedFilters
|
||||
toRaw(this.persistedFilters)
|
||||
);
|
||||
},
|
||||
mutateConfigurationGlobalFilters() {
|
||||
this.openmct.objects.mutate(
|
||||
this.providedObject,
|
||||
'configuration.globalFilters',
|
||||
this.globalFilters
|
||||
toRaw(this.globalFilters)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +161,11 @@ export default {
|
||||
let originalClassName = this.dragGhost.classList[0];
|
||||
this.dragGhost.className = '';
|
||||
this.dragGhost.classList.add(originalClassName, iconClass);
|
||||
this.dragGhost.textContent = '';
|
||||
const span = document.createElement('span');
|
||||
span.textContent = this.domainObject.name;
|
||||
this.dragGhost.appendChild(span);
|
||||
|
||||
this.dragGhost.innerHTML = `<span>${this.domainObject.name}</span>`;
|
||||
event.dataTransfer.setDragImage(this.dragGhost, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import FlexibleLayout from './plugin';
|
||||
|
||||
@@ -105,7 +105,7 @@ describe('the plugin', function () {
|
||||
const flexibleView = flexibleLayoutViewProvider.view(testViewObject, [testViewObject]);
|
||||
flexibleView.show(child, false);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
console.log(child);
|
||||
const flexTitle = child.querySelector('.c-fl');
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import FolderPlugin from './plugin.js';
|
||||
|
||||
@@ -132,7 +132,7 @@ describe('The folder plugin', () => {
|
||||
let folderView = gridViewProvider.view(folderObject, [folderObject]);
|
||||
folderView.show(childDiv, true);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let children = parentDiv.getElementsByClassName('js-folder-child');
|
||||
expect(children.length).toBe(folderObject.composition.length);
|
||||
@@ -147,7 +147,7 @@ describe('The folder plugin', () => {
|
||||
let folderView = listViewProvider.view(folderObject, [folderObject]);
|
||||
folderView.show(childDiv, true);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let children = parentDiv.getElementsByClassName('js-folder-child');
|
||||
expect(children.length).toBe(folderObject.composition.length);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
import { debounce } from 'lodash';
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
describe('EditPropertiesAction plugin', () => {
|
||||
let editPropertiesAction;
|
||||
@@ -106,7 +106,7 @@ describe('EditPropertiesAction plugin', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
const form = document.querySelector('.js-form');
|
||||
const title = form.querySelector('input');
|
||||
expect(title.value).toEqual(domainObject.name);
|
||||
@@ -153,7 +153,7 @@ describe('EditPropertiesAction plugin', () => {
|
||||
|
||||
editPropertiesAction.invoke([domainObject]);
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
const form = document.querySelector('.js-form');
|
||||
const title = form.querySelector('input');
|
||||
const notes = form.querySelector('textArea');
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
import { debounce } from 'lodash';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
let gaugeDomainObject = {
|
||||
identifier: {
|
||||
@@ -174,7 +174,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -221,7 +221,7 @@ describe('Gauge plugin', () => {
|
||||
}
|
||||
|
||||
const debouncedWatchUpdate = debounce(WatchUpdateValue, 200);
|
||||
Vue.nextTick(debouncedWatchUpdate);
|
||||
nextTick(debouncedWatchUpdate);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -316,7 +316,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -363,7 +363,7 @@ describe('Gauge plugin', () => {
|
||||
}
|
||||
|
||||
const debouncedWatchUpdate = debounce(WatchUpdateValue, 200);
|
||||
Vue.nextTick(debouncedWatchUpdate);
|
||||
nextTick(debouncedWatchUpdate);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -458,7 +458,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -505,7 +505,7 @@ describe('Gauge plugin', () => {
|
||||
}
|
||||
|
||||
const debouncedWatchUpdate = debounce(WatchUpdateValue, 200);
|
||||
Vue.nextTick(debouncedWatchUpdate);
|
||||
nextTick(debouncedWatchUpdate);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -562,7 +562,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -645,7 +645,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -773,7 +773,7 @@ describe('Gauge plugin', () => {
|
||||
gaugeView = gaugeViewProvider.view(mutablegaugeObject, [mutablegaugeObject]);
|
||||
gaugeView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -821,7 +821,7 @@ describe('Gauge plugin', () => {
|
||||
}
|
||||
|
||||
const debouncedWatchUpdate = debounce(WatchUpdateValue, 200);
|
||||
Vue.nextTick(debouncedWatchUpdate);
|
||||
nextTick(debouncedWatchUpdate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
</template>
|
||||
|
||||
<template v-if="typeMeter">
|
||||
<div class="c-meter">
|
||||
<div class="c-meter" @mouseover.ctrl="showToolTip" @mouseleave="hideToolTip">
|
||||
<div v-if="displayMinMax" class="c-gauge__range c-meter__range js-gauge-meter-range">
|
||||
<div class="c-meter__range__high">{{ rangeHigh }}</div>
|
||||
<div class="c-meter__range__low">{{ rangeLow }}</div>
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function ImageryTimestripViewProvider(openmct) {
|
||||
domainObject: domainObject,
|
||||
objectPath: objectPath
|
||||
},
|
||||
template: '<imagery-time-view></imagery-time-view>'
|
||||
template: '<imagery-time-view ref="root"></imagery-time-view>'
|
||||
},
|
||||
{
|
||||
app: openmct.app,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import Vue from 'vue';
|
||||
import mount from 'utils/mount';
|
||||
|
||||
import Compass from './CompassComponent.vue';
|
||||
|
||||
@@ -27,7 +27,7 @@ const COMPASS_ROSE_CLASS = '.c-direction-rose';
|
||||
const COMPASS_HUD_CLASS = '.c-compass__hud';
|
||||
|
||||
describe('The Compass component', () => {
|
||||
let app;
|
||||
let _destroy;
|
||||
let instance;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -55,7 +55,7 @@ describe('The Compass component', () => {
|
||||
}
|
||||
};
|
||||
|
||||
app = new Vue({
|
||||
const { vNode, destroy } = mount({
|
||||
components: { Compass },
|
||||
data() {
|
||||
return propsData;
|
||||
@@ -66,11 +66,12 @@ describe('The Compass component', () => {
|
||||
:sized-image-dimensions="sizedImageDimensions"
|
||||
/>`
|
||||
});
|
||||
instance = app.$mount();
|
||||
_destroy = destroy;
|
||||
instance = vNode.componentInstance;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
app.$destroy();
|
||||
_destroy();
|
||||
});
|
||||
|
||||
describe('when a heading value and cameraAngleOfView exists on the image', () => {
|
||||
|
||||
@@ -26,9 +26,7 @@ import {
|
||||
resetApplicationState,
|
||||
simulateKeyEvent
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
|
||||
import ClearDataPlugin from '../clearData/plugin';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const ONE_MINUTE = 1000 * 60;
|
||||
const TEN_MINUTES = ONE_MINUTE * 10;
|
||||
@@ -319,63 +317,6 @@ describe('The Imagery View Layouts', () => {
|
||||
expect(imageryView).toBeDefined();
|
||||
});
|
||||
|
||||
describe('Clear data action for imagery', () => {
|
||||
let applicableViews;
|
||||
let imageryViewProvider;
|
||||
let imageryView;
|
||||
let componentView;
|
||||
let clearDataPlugin;
|
||||
let clearDataAction;
|
||||
|
||||
beforeEach(() => {
|
||||
openmct.time.timeSystem('utc', {
|
||||
start: START - 5 * ONE_MINUTE,
|
||||
end: START + 5 * ONE_MINUTE
|
||||
});
|
||||
|
||||
applicableViews = openmct.objectViews.get(imageryObject, [imageryObject]);
|
||||
imageryViewProvider = applicableViews.find((viewProvider) => viewProvider.key === imageryKey);
|
||||
imageryView = imageryViewProvider.view(imageryObject, [imageryObject]);
|
||||
imageryView.show(child);
|
||||
componentView = imageryView._getInstance().$children[0];
|
||||
|
||||
clearDataPlugin = new ClearDataPlugin(['example.imagery'], { indicator: true });
|
||||
openmct.install(clearDataPlugin);
|
||||
clearDataAction = openmct.actions.getAction('clear-data-action');
|
||||
|
||||
return Vue.nextTick();
|
||||
});
|
||||
|
||||
it('clear data action is installed', () => {
|
||||
expect(clearDataAction).toBeDefined();
|
||||
});
|
||||
|
||||
it('on clearData action should clear data for object is selected', (done) => {
|
||||
// force show the thumbnails
|
||||
componentView.forceShowThumbnails = true;
|
||||
Vue.nextTick(() => {
|
||||
let clearDataResolve;
|
||||
let telemetryRequestPromise = new Promise((resolve) => {
|
||||
clearDataResolve = resolve;
|
||||
});
|
||||
expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0);
|
||||
|
||||
openmct.objectViews.on('clearData', (_domainObject) => {
|
||||
return Vue.nextTick(() => {
|
||||
expect(parent.querySelectorAll('.c-imagery__thumb').length).toBe(0);
|
||||
|
||||
clearDataResolve();
|
||||
});
|
||||
});
|
||||
clearDataAction.invoke(imageryObject);
|
||||
|
||||
telemetryRequestPromise.then(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('imagery view', () => {
|
||||
let applicableViews;
|
||||
let imageryViewProvider;
|
||||
@@ -392,54 +333,35 @@ describe('The Imagery View Layouts', () => {
|
||||
imageryView = imageryViewProvider.view(imageryObject, [imageryObject]);
|
||||
imageryView.show(child);
|
||||
|
||||
imageryView._getInstance().$children[0].forceShowThumbnails = true;
|
||||
imageryView._getInstance().$refs.ImageryContainer.forceShowThumbnails = true;
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('on mount should show the the most recent image', async () => {
|
||||
//Looks like we need Vue.nextTick here so that computed properties settle down
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
//Looks like we need nextTick here so that computed properties settle down
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageInfo = getImageInfo(parent);
|
||||
expect(imageInfo.url.indexOf(imageTelemetry[COUNT - 1].timeId)).not.toEqual(-1);
|
||||
});
|
||||
|
||||
it('on mount should show any image layers', async () => {
|
||||
//Looks like we need Vue.nextTick here so that computed properties settle down
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
//Looks like we need nextTick here so that computed properties settle down
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const layerEls = parent.querySelectorAll('.js-layer-image');
|
||||
expect(layerEls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should use the image thumbnailUrl for thumbnails', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
const fullSizeImageUrl = imageTelemetry[5].url;
|
||||
const thumbnailUrl = formatThumbnail(imageTelemetry[5].url);
|
||||
|
||||
// Ensure thumbnails are shown w/ thumbnail Urls
|
||||
const thumbnails = parent.querySelectorAll(`img[src='${thumbnailUrl}']`);
|
||||
expect(thumbnails.length).toBeGreaterThan(0);
|
||||
|
||||
// Click a thumbnail
|
||||
parent.querySelectorAll(`img[src='${thumbnailUrl}']`)[0].click();
|
||||
await Vue.nextTick();
|
||||
|
||||
// Ensure full size image is shown w/ full size url
|
||||
const fullSizeImages = parent.querySelectorAll(`img[src='${fullSizeImageUrl}']`);
|
||||
expect(fullSizeImages.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should show the clicked thumbnail as the main image', async () => {
|
||||
//Looks like we need Vue.nextTick here so that computed properties settle down
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
//Looks like we need nextTick here so that computed properties settle down
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const thumbnailUrl = formatThumbnail(imageTelemetry[5].url);
|
||||
parent.querySelectorAll(`img[src='${thumbnailUrl}']`)[0].click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const imageInfo = getImageInfo(parent);
|
||||
|
||||
expect(imageInfo.url.indexOf(imageTelemetry[5].timeId)).not.toEqual(-1);
|
||||
@@ -451,7 +373,7 @@ describe('The Imagery View Layouts', () => {
|
||||
end: 1000
|
||||
});
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
// used in code, need to wait to the 500ms here too
|
||||
setTimeout(() => {
|
||||
const imageIsNew = isNew(parent);
|
||||
@@ -462,20 +384,20 @@ describe('The Imagery View Layouts', () => {
|
||||
});
|
||||
|
||||
it('should show that an image is not new', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const target = formatThumbnail(imageTelemetry[4].url);
|
||||
parent.querySelectorAll(`img[src='${target}']`)[0].click();
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const imageIsNew = isNew(parent);
|
||||
|
||||
expect(imageIsNew).toBeFalse();
|
||||
});
|
||||
|
||||
it('should navigate via arrow keys', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const keyOpts = {
|
||||
element: parent.querySelector('.c-imagery'),
|
||||
key: 'ArrowLeft',
|
||||
@@ -485,14 +407,14 @@ describe('The Imagery View Layouts', () => {
|
||||
|
||||
simulateKeyEvent(keyOpts);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const imageInfo = getImageInfo(parent);
|
||||
expect(imageInfo.url.indexOf(imageTelemetry[COUNT - 2].timeId)).not.toEqual(-1);
|
||||
});
|
||||
|
||||
it('should navigate via numerous arrow keys', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const element = parent.querySelector('.c-imagery');
|
||||
const type = 'keyup';
|
||||
const leftKeyOpts = {
|
||||
@@ -515,15 +437,15 @@ describe('The Imagery View Layouts', () => {
|
||||
// right once
|
||||
simulateKeyEvent(rightKeyOpts);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const imageInfo = getImageInfo(parent);
|
||||
expect(imageInfo.url.indexOf(imageTelemetry[COUNT - 3].timeId)).not.toEqual(-1);
|
||||
});
|
||||
it('shows an auto scroll button when scroll to left', (done) => {
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
// to mock what a scroll would do
|
||||
imageryView._getInstance().$refs.ImageryContainer.autoScroll = false;
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
let autoScrollButton = parent.querySelector('.c-imagery__auto-scroll-resume-button');
|
||||
expect(autoScrollButton).toBeTruthy();
|
||||
done();
|
||||
@@ -531,16 +453,16 @@ describe('The Imagery View Layouts', () => {
|
||||
});
|
||||
});
|
||||
it('scrollToRight is called when clicking on auto scroll button', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
// use spyon to spy the scroll function
|
||||
spyOn(imageryView._getInstance().$refs.ImageryContainer, 'scrollHandler');
|
||||
imageryView._getInstance().$refs.ImageryContainer.autoScroll = false;
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
parent.querySelector('.c-imagery__auto-scroll-resume-button').click();
|
||||
expect(imageryView._getInstance().$refs.ImageryContainer.scrollHandler);
|
||||
});
|
||||
xit('should change the image zoom factor when using the zoom buttons', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let imageSizeBefore;
|
||||
let imageSizeAfter;
|
||||
|
||||
@@ -549,7 +471,7 @@ describe('The Imagery View Layouts', () => {
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
.getBoundingClientRect();
|
||||
parent.querySelector('.t-btn-zoom-in').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
imageSizeAfter = parent
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
.getBoundingClientRect();
|
||||
@@ -560,7 +482,7 @@ describe('The Imagery View Layouts', () => {
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
.getBoundingClientRect();
|
||||
parent.querySelector('.t-btn-zoom-out').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
imageSizeAfter = parent
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
.getBoundingClientRect();
|
||||
@@ -568,15 +490,15 @@ describe('The Imagery View Layouts', () => {
|
||||
expect(imageSizeAfter.width).toBeLessThan(imageSizeBefore.width);
|
||||
});
|
||||
xit('should reset the zoom factor on the image when clicking the zoom button', async (done) => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
// test clicking the zoom reset button
|
||||
// zoom in to scale up the image dimensions
|
||||
parent.querySelector('.t-btn-zoom-in').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let imageSizeBefore = parent
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
.getBoundingClientRect();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
parent.querySelector('.t-btn-zoom-reset').click();
|
||||
let imageSizeAfter = parent
|
||||
.querySelector('.c-imagery_main-image_background-image')
|
||||
@@ -587,22 +509,22 @@ describe('The Imagery View Layouts', () => {
|
||||
});
|
||||
|
||||
it('should display the viewable area when zoom factor is greater than 1', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
expect(parent.querySelectorAll('.c-thumb__viewable-area').length).toBe(0);
|
||||
|
||||
parent.querySelector('.t-btn-zoom-in').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(parent.querySelectorAll('.c-thumb__viewable-area').length).toBe(1);
|
||||
|
||||
parent.querySelector('.t-btn-zoom-reset').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(parent.querySelectorAll('.c-thumb__viewable-area').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should reset the brightness and contrast when clicking the reset button', async () => {
|
||||
const viewInstance = imageryView._getInstance();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Save the original brightness and contrast values
|
||||
const origBrightness = viewInstance.$refs.ImageryContainer.filters.brightness;
|
||||
@@ -613,7 +535,7 @@ describe('The Imagery View Layouts', () => {
|
||||
brightness: 200,
|
||||
contrast: 200
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify that the values actually changed
|
||||
expect(viewInstance.$refs.ImageryContainer.filters.brightness).toBe(200);
|
||||
@@ -621,7 +543,7 @@ describe('The Imagery View Layouts', () => {
|
||||
|
||||
// Click the reset button
|
||||
parent.querySelector('.t-btn-reset').click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify that the values were reset
|
||||
expect(viewInstance.$refs.ImageryContainer.filters.brightness).toBe(origBrightness);
|
||||
@@ -631,8 +553,8 @@ describe('The Imagery View Layouts', () => {
|
||||
|
||||
describe('imagery time strip view', () => {
|
||||
let applicableViews;
|
||||
let imageryViewProvider;
|
||||
let imageryView;
|
||||
let imageryTimestripViewProvider;
|
||||
let imageryTimeView;
|
||||
let componentView;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -671,10 +593,10 @@ describe('The Imagery View Layouts', () => {
|
||||
type: 'time-strip'
|
||||
}
|
||||
]);
|
||||
imageryViewProvider = applicableViews.find(
|
||||
imageryTimestripViewProvider = applicableViews.find(
|
||||
(viewProvider) => viewProvider.key === imageryForTimeStripKey
|
||||
);
|
||||
imageryView = imageryViewProvider.view(imageryObject, [
|
||||
imageryTimeView = imageryTimestripViewProvider.view(imageryObject, [
|
||||
imageryObject,
|
||||
{
|
||||
identifier: {
|
||||
@@ -684,12 +606,12 @@ describe('The Imagery View Layouts', () => {
|
||||
type: 'time-strip'
|
||||
}
|
||||
]);
|
||||
imageryView.show(child);
|
||||
imageryTimeView.show(child);
|
||||
|
||||
componentView = imageryView.getComponent().$children[0];
|
||||
componentView = imageryTimeView.getComponent().$refs.root;
|
||||
spyOn(componentView.previewAction, 'invoke').and.callThrough();
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -697,19 +619,19 @@ describe('The Imagery View Layouts', () => {
|
||||
});
|
||||
|
||||
it('on mount should show imagery within the given bounds', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
|
||||
expect(imageElements.length).toEqual(5);
|
||||
});
|
||||
|
||||
it('should show the clicked thumbnail as the preview image', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const mouseDownEvent = createMouseEvent('mousedown');
|
||||
let imageWrapper = parent.querySelectorAll(`.c-imagery-tsv__image-wrapper`);
|
||||
imageWrapper[2].dispatchEvent(mouseDownEvent);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const timestamp = imageWrapper[2].id.replace('wrapper-', '');
|
||||
expect(componentView.previewAction.invoke).toHaveBeenCalledWith(
|
||||
[componentView.objectPath[0]],
|
||||
@@ -722,8 +644,8 @@ describe('The Imagery View Layouts', () => {
|
||||
|
||||
it('should remove images when clock advances', async () => {
|
||||
openmct.time.tick(ONE_MINUTE * 2);
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
|
||||
expect(imageElements.length).toEqual(4);
|
||||
});
|
||||
@@ -733,8 +655,8 @@ describe('The Imagery View Layouts', () => {
|
||||
start: START,
|
||||
end: START + 5 * ONE_MINUTE
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
|
||||
expect(imageElements.length).toEqual(1);
|
||||
});
|
||||
@@ -744,8 +666,8 @@ describe('The Imagery View Layouts', () => {
|
||||
start: START - 5 * ONE_MINUTE,
|
||||
end: START - 2 * ONE_MINUTE
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
|
||||
expect(imageElements.length).toEqual(4);
|
||||
});
|
||||
@@ -755,8 +677,8 @@ describe('The Imagery View Layouts', () => {
|
||||
start: START - 2 * ONE_MINUTE,
|
||||
end: START + 2 * ONE_MINUTE
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
|
||||
expect(imageElements.length).toEqual(3);
|
||||
});
|
||||
|
||||
@@ -410,7 +410,7 @@ export default {
|
||||
this.manageEmbedLayout();
|
||||
this.timestampAndUpdate();
|
||||
},
|
||||
convertMarkDownToHtml(text) {
|
||||
convertMarkDownToHtml(text = '') {
|
||||
let markDownHtml = this.marked.parse(text, {
|
||||
breaks: true,
|
||||
renderer: this.renderer
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { NotebookPlugin } from './plugin';
|
||||
|
||||
@@ -189,7 +189,7 @@ describe('Notebook plugin:', () => {
|
||||
notebookView = notebookViewProvider.view(mutableNotebookObject, [mutableNotebookObject]);
|
||||
notebookView.show(child);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -237,7 +237,7 @@ describe('Notebook plugin:', () => {
|
||||
'Modified entry text';
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(getEntryText(0).innerText.trim()).toBe('Modified entry text');
|
||||
});
|
||||
});
|
||||
@@ -252,7 +252,7 @@ describe('Notebook plugin:', () => {
|
||||
});
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(allNotebookEntryElements().length).toBe(3);
|
||||
});
|
||||
});
|
||||
@@ -263,7 +263,7 @@ describe('Notebook plugin:', () => {
|
||||
entries.splice(0, 1);
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(allNotebookEntryElements().length).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -281,7 +281,7 @@ describe('Notebook plugin:', () => {
|
||||
objectCloneToSyncFrom.configuration.sections[0].pages.push(newPage);
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(allNotebookPageElements().length).toBe(3);
|
||||
});
|
||||
|
||||
@@ -290,7 +290,7 @@ describe('Notebook plugin:', () => {
|
||||
objectCloneToSyncFrom.configuration.sections[0].pages.splice(0, 1);
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(allNotebookPageElements().length).toBe(1);
|
||||
});
|
||||
|
||||
@@ -315,7 +315,7 @@ describe('Notebook plugin:', () => {
|
||||
objectCloneToSyncFrom.configuration.sections.push(newSection);
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(allNotebookSectionElements().length).toBe(3);
|
||||
});
|
||||
});
|
||||
@@ -325,7 +325,7 @@ describe('Notebook plugin:', () => {
|
||||
objectCloneToSyncFrom.configuration.sections.splice(0, 1);
|
||||
objectProviderObserver(objectCloneToSyncFrom);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(allNotebookSectionElements().length).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -351,7 +351,7 @@ describe('Notebook plugin:', () => {
|
||||
|
||||
element.append(snapshotIndicator);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
drawerElement = document.querySelector('.l-shell__drawer');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import NotificationIndicatorPlugin from './plugin.js';
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('the plugin', () => {
|
||||
beforeEach(() => {
|
||||
parentElement.append(indicatorElement);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('notifies the user of the number of notifications', () => {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import { createOpenMct, resetApplicationState, spyOnBuiltins } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { CONNECTED, DISCONNECTED, PENDING, UNKNOWN } from './CouchStatusIndicator';
|
||||
import CouchPlugin from './plugin.js';
|
||||
@@ -478,7 +478,7 @@ describe('the view', () => {
|
||||
namespace: '',
|
||||
key: 'object-1'
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
assertCouchIndicatorStatus(CONNECTED);
|
||||
});
|
||||
@@ -490,7 +490,7 @@ describe('the view', () => {
|
||||
namespace: '',
|
||||
key: 'object-1'
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
assertCouchIndicatorStatus(DISCONNECTED);
|
||||
});
|
||||
@@ -523,7 +523,7 @@ describe('the view', () => {
|
||||
|
||||
// Simulate 'pending' state from worker message
|
||||
provider.onSharedWorkerMessage(workerMessage);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
assertCouchIndicatorStatus(PENDING);
|
||||
});
|
||||
@@ -556,7 +556,7 @@ describe('the view', () => {
|
||||
|
||||
// Simulate 'pending' state from worker message
|
||||
provider.onSharedWorkerMessage(workerMessage);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
assertCouchIndicatorStatus(UNKNOWN);
|
||||
});
|
||||
|
||||
@@ -69,11 +69,11 @@ export default {
|
||||
const label = this.activity[key].label;
|
||||
const value = String(this.activity[key].value);
|
||||
|
||||
this.$set(this.timeProperties, this.timeProperties.length, {
|
||||
this.timeProperties[this.timeProperties.length] = {
|
||||
id: uuid(),
|
||||
label,
|
||||
value
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import mount from 'utils/mount';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import Properties from '../inspectorViews/properties/PropertiesComponent.vue';
|
||||
import PlanPlugin from '../plan/plugin';
|
||||
@@ -187,7 +188,7 @@ describe('the plugin', function () {
|
||||
let view = planView.view(planDomainObject, mockObjectPath);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('loads activities into the view', () => {
|
||||
@@ -210,7 +211,7 @@ describe('the plugin', function () {
|
||||
|
||||
openmct.time.bounds(bounds);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const rectEls = element.querySelectorAll('.c-plan__contents use');
|
||||
expect(rectEls.length).toEqual(2);
|
||||
const textEls = element.querySelectorAll('.c-plan__contents text');
|
||||
@@ -226,7 +227,7 @@ describe('the plugin', function () {
|
||||
'draft'
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const statusEl = element.querySelector('.c-plan__contents .is-status--draft');
|
||||
expect(statusEl).toBeDefined();
|
||||
});
|
||||
@@ -235,6 +236,7 @@ describe('the plugin', function () {
|
||||
describe('the plan version', () => {
|
||||
let component;
|
||||
let componentObject;
|
||||
let _destroy;
|
||||
let testPlanObject = {
|
||||
name: 'Plan',
|
||||
type: 'plan',
|
||||
@@ -267,27 +269,28 @@ describe('the plugin', function () {
|
||||
false
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
const { vNode, destroy } = mount({
|
||||
components: {
|
||||
Properties
|
||||
},
|
||||
provide: {
|
||||
openmct: openmct
|
||||
},
|
||||
template: '<properties/>'
|
||||
template: '<properties ref="root"/>'
|
||||
});
|
||||
_destroy = destroy;
|
||||
component = vNode.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.$destroy();
|
||||
_destroy();
|
||||
});
|
||||
|
||||
it('provides an inspector view with the version information if available', () => {
|
||||
componentObject = component.$root.$children[0];
|
||||
componentObject = component.$refs.root;
|
||||
const propertiesEls = componentObject.$el.querySelectorAll('.c-inspect-properties__row');
|
||||
const found = Array.from(propertiesEls).some((propertyEl) => {
|
||||
return (
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
:model="{ progressPerc: null }"
|
||||
/>
|
||||
<mct-plot
|
||||
ref="mctPlot"
|
||||
:class="[plotLegendExpandedStateClass, plotLegendPositionClass]"
|
||||
:init-grid-lines="gridLinesProp"
|
||||
:init-cursor-guide="cursorGuide"
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
|
||||
<template>
|
||||
<div class="gl-plot-chart-area">
|
||||
<span v-html="canvasTemplate"></span>
|
||||
<span v-html="canvasTemplate"></span>
|
||||
<canvas :style="canvasStyle"></canvas>
|
||||
<canvas :style="canvasStyle"></canvas>
|
||||
<div ref="limitArea" class="js-limit-area">
|
||||
<limit-label
|
||||
v-for="(limitLabel, index) in visibleLimitLabels"
|
||||
@@ -147,12 +145,20 @@ export default {
|
||||
emits: ['chart-loaded', 'plot-reinitialize-canvas'],
|
||||
data() {
|
||||
return {
|
||||
canvasTemplate:
|
||||
'<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>',
|
||||
visibleLimitLabels: [],
|
||||
visibleLimitLines: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canvasStyle() {
|
||||
return {
|
||||
position: 'absolute',
|
||||
background: 'none',
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
highlights: {
|
||||
handler() {
|
||||
@@ -488,7 +494,10 @@ export default {
|
||||
// Have to throw away the old canvas elements and replace with new
|
||||
// canvas elements in order to get new drawing contexts.
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = this.canvasTemplate + this.canvasTemplate;
|
||||
div.innerHTML = `
|
||||
<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>
|
||||
<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>
|
||||
`;
|
||||
const mainCanvas = div.querySelectorAll('canvas')[1];
|
||||
const overlayCanvas = div.querySelectorAll('canvas')[0];
|
||||
this.canvas.parentNode.replaceChild(mainCanvas, this.canvas);
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import _ from 'lodash';
|
||||
|
||||
import configStore from '../configuration/ConfigStore';
|
||||
import { MARKER_SHAPES } from '../draw/MarkerShapes';
|
||||
import { symlog } from '../mathUtils';
|
||||
@@ -64,6 +62,10 @@ import Model from './Model';
|
||||
*
|
||||
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
|
||||
*/
|
||||
|
||||
const FLOAT32_MAX = 3.4e38;
|
||||
const FLOAT32_MIN = -3.4e38;
|
||||
|
||||
export default class PlotSeries extends Model {
|
||||
logMode = false;
|
||||
|
||||
@@ -371,7 +373,7 @@ export default class PlotSeries extends Model {
|
||||
let stats = this.get('stats');
|
||||
let changed = false;
|
||||
if (!stats) {
|
||||
if ([Infinity, -Infinity].includes(value)) {
|
||||
if ([Infinity, -Infinity].includes(value) || !this.isValidFloat32(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -383,13 +385,13 @@ export default class PlotSeries extends Model {
|
||||
};
|
||||
changed = true;
|
||||
} else {
|
||||
if (stats.maxValue < value && value !== Infinity) {
|
||||
if (stats.maxValue < value && value !== Infinity && this.isValidFloat32(value)) {
|
||||
stats.maxValue = value;
|
||||
stats.maxPoint = point;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (stats.minValue > value && value !== -Infinity) {
|
||||
if (stats.minValue > value && value !== -Infinity && this.isValidFloat32(value)) {
|
||||
stats.minValue = value;
|
||||
stats.minPoint = point;
|
||||
changed = true;
|
||||
@@ -425,7 +427,7 @@ export default class PlotSeries extends Model {
|
||||
const lastYVal = this.getYVal(data[insertIndex - 1]);
|
||||
|
||||
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
||||
console.warn('[Plot] Invalid Y Values detected');
|
||||
console.warn(`[Plot] Invalid Y Values detected: ${currentYVal} ${lastYVal}`);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -453,7 +455,15 @@ export default class PlotSeries extends Model {
|
||||
* @private
|
||||
*/
|
||||
isValueInvalid(val) {
|
||||
return Number.isNaN(val) || this.unPlottableValues.includes(val);
|
||||
return Number.isNaN(val) || this.unPlottableValues.includes(val) || !this.isValidFloat32(val);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
isValidFloat32(val) {
|
||||
return val < FLOAT32_MAX && val > FLOAT32_MIN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
resetApplicationState,
|
||||
spyOnBuiltins
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import configStore from './configuration/ConfigStore';
|
||||
import PlotConfigurationModel from './configuration/PlotConfigurationModel';
|
||||
@@ -172,7 +172,7 @@ describe('the plugin', function () {
|
||||
end: 2
|
||||
});
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
configStore.deleteAll();
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
@@ -296,7 +296,7 @@ describe('the plugin', function () {
|
||||
];
|
||||
const applicableInspectorViews = openmct.inspectorViews.get(selection);
|
||||
const plotInspectorView = applicableInspectorViews.find(
|
||||
(view) => (view.name = 'Plots Configuration')
|
||||
(view) => view.key === 'plots-inspector'
|
||||
);
|
||||
|
||||
expect(plotInspectorView).toBeDefined();
|
||||
@@ -374,7 +374,7 @@ describe('the plugin', function () {
|
||||
plotView = plotViewProvider.view(testTelemetryObject, []);
|
||||
plotView.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -386,14 +386,14 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
it('Renders a collapsed legend for every telemetry', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let legend = element.querySelectorAll('.plot-wrapper-collapsed-legend .plot-series-name');
|
||||
expect(legend.length).toBe(1);
|
||||
expect(legend[0].innerHTML).toEqual('Test Object');
|
||||
});
|
||||
|
||||
it('Renders an expanded legend for every telemetry', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let legendControl = element.querySelector(
|
||||
'.c-plot-legend__view-control.gl-plot-legend__view-control.c-disclosure-triangle'
|
||||
);
|
||||
@@ -413,7 +413,7 @@ describe('the plugin', function () {
|
||||
max: 4
|
||||
});
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
let xAxisElement = element.querySelectorAll(
|
||||
'.gl-plot-axis-area.gl-plot-x .gl-plot-tick-wrapper'
|
||||
);
|
||||
@@ -427,7 +427,7 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
it('Renders Y-axis options for the telemetry object', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let yAxisElement = element.querySelectorAll(
|
||||
'.gl-plot-axis-area.gl-plot-y .gl-plot-y-label__select'
|
||||
);
|
||||
@@ -468,11 +468,11 @@ describe('the plugin', function () {
|
||||
end: 100
|
||||
});
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('shows the pause controls', (done) => {
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
let pauseEl = element.querySelectorAll('.c-button-set .icon-pause');
|
||||
expect(pauseEl.length).toBe(1);
|
||||
done();
|
||||
@@ -484,7 +484,7 @@ describe('the plugin', function () {
|
||||
const clickEvent = createMouseEvent('click');
|
||||
|
||||
pauseEl.dispatchEvent(clickEvent);
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
let playEl = element.querySelectorAll('.c-button-set .is-paused');
|
||||
expect(playEl.length).toBe(1);
|
||||
done();
|
||||
@@ -500,7 +500,7 @@ describe('the plugin', function () {
|
||||
end: 100
|
||||
});
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('clicking the plot view without movement resumes the plot while active', async () => {
|
||||
@@ -516,7 +516,7 @@ describe('the plugin', function () {
|
||||
canvas.dispatchEvent(mouseDownEvent);
|
||||
// mouseup event is bound to the window
|
||||
window.dispatchEvent(mouseUpEvent);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const pauseElAfterClick = element.querySelectorAll('.c-button-set .icon-pause');
|
||||
console.log('pauseElAfterClick', pauseElAfterClick);
|
||||
@@ -527,7 +527,7 @@ describe('the plugin', function () {
|
||||
const pauseEl = element.querySelector('.c-button-set .icon-pause');
|
||||
// pause the plot
|
||||
pauseEl.dispatchEvent(createMouseEvent('click'));
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const playEl = element.querySelectorAll('.c-button-set .is-paused');
|
||||
expect(playEl.length).toBe(1);
|
||||
@@ -540,7 +540,7 @@ describe('the plugin', function () {
|
||||
canvas.dispatchEvent(mouseDownEvent);
|
||||
// mouseup event is bound to the window
|
||||
window.dispatchEvent(mouseUpEvent);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const playElAfterChartClick = element.querySelectorAll('.c-button-set .is-paused');
|
||||
expect(playElAfterChartClick.length).toBe(1);
|
||||
@@ -557,7 +557,7 @@ describe('the plugin', function () {
|
||||
canvas.dispatchEvent(mouseDownEvent);
|
||||
// mouseup event is bound to the window
|
||||
window.dispatchEvent(mouseUpEvent);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(openmct.telemetry.request).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
@@ -569,7 +569,7 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
it('lines are displayed when configuration is set to true', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const configId = openmct.objects.makeKeyString(testTelemetryObject.identifier);
|
||||
const config = configStore.get(configId);
|
||||
config.yAxis.set('displayRange', {
|
||||
@@ -578,7 +578,7 @@ describe('the plugin', function () {
|
||||
});
|
||||
config.series.models[0].set('limitLines', true);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let limitEl = element.querySelectorAll('.js-limit-area .js-limit-line');
|
||||
expect(limitEl.length).toBe(4);
|
||||
});
|
||||
@@ -666,13 +666,13 @@ describe('the plugin', function () {
|
||||
|
||||
plotContainerResizeObserver = new ResizeObserver(handlePlotResize);
|
||||
plotContainerResizeObserver.observe(
|
||||
plotView.getComponent().$children[0].$children[1].$parent.$refs.plotWrapper
|
||||
plotView.getComponent().$refs.plotComponent.$refs.plotWrapper
|
||||
);
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
plotView.getComponent().$children[0].$children[1].stopFollowingTimeContext();
|
||||
return nextTick(() => {
|
||||
plotView.getComponent().$refs.plotComponent.$refs.mctPlot.stopFollowingTimeContext();
|
||||
spyOn(
|
||||
plotView.getComponent().$children[0].$children[1],
|
||||
plotView.getComponent().$refs.plotComponent.$refs.mctPlot,
|
||||
'loadSeriesData'
|
||||
).and.callThrough();
|
||||
});
|
||||
@@ -684,22 +684,20 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
xit('requests historical data when over the threshold', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
element.style.width = '680px';
|
||||
await resizePromise;
|
||||
expect(
|
||||
plotView.getComponent().$children[0].$children[1].loadSeriesData
|
||||
plotView.getComponent().$refs.plotComponent.$refs.mctPlot.loadSeriesData
|
||||
).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not request historical data when under the threshold', (done) => {
|
||||
it('does not request historical data when under the threshold', async () => {
|
||||
element.style.width = '644px';
|
||||
resizePromise.then(() => {
|
||||
expect(
|
||||
plotView.getComponent().$children[0].$children[1].loadSeriesData
|
||||
).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
await resizePromise;
|
||||
expect(
|
||||
plotView.getComponent().$refs.plotComponent.$refs.mctPlot.loadSeriesData
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -815,7 +813,7 @@ describe('the plugin', function () {
|
||||
domainObject: selection[0][0].context.item,
|
||||
path: [selection[0][0].context.item, selection[0][1].context.item]
|
||||
},
|
||||
template: '<plot-options/>'
|
||||
template: '<plot-options ref="root"/>'
|
||||
},
|
||||
{
|
||||
element: viewContainer
|
||||
@@ -823,8 +821,8 @@ describe('the plugin', function () {
|
||||
);
|
||||
component = vNode.componentInstance;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
viewComponentObject = component.$root.$children[0];
|
||||
nextTick(() => {
|
||||
viewComponentObject = component.$refs.root;
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -873,7 +871,7 @@ describe('the plugin', function () {
|
||||
|
||||
beforeEach((done) => {
|
||||
viewComponentObject.setEditState(true);
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
editOptionsEl = viewComponentObject.$el.querySelector('.js-plot-options-edit');
|
||||
browseOptionsEl = viewComponentObject.$el.querySelector('.js-plot-options-browse');
|
||||
done();
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<div class="l-view-section">
|
||||
<stacked-plot-item
|
||||
v-for="objectWrapper in compositionObjects"
|
||||
ref="stackedPlotItems"
|
||||
:key="objectWrapper.keyString"
|
||||
class="c-plot--stacked-container"
|
||||
:child-object="objectWrapper.object"
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
resetApplicationState,
|
||||
spyOnBuiltins
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick, ref } from 'vue';
|
||||
|
||||
import configStore from '../configuration/ConfigStore';
|
||||
import PlotConfigurationModel from '../configuration/PlotConfigurationModel';
|
||||
@@ -342,7 +342,7 @@ describe('the plugin', function () {
|
||||
destroyStackedPlot = destroy;
|
||||
|
||||
await telemetryPromise;
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
plotViewComponentObject = component.$refs.stackedPlotRef;
|
||||
const configId = openmct.objects.makeKeyString(testTelemetryObject.identifier);
|
||||
config = configStore.get(configId);
|
||||
@@ -390,7 +390,7 @@ describe('the plugin', function () {
|
||||
min: 10,
|
||||
max: 20
|
||||
});
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let yAxisElement = element.querySelectorAll(
|
||||
'.gl-plot-axis-area.gl-plot-y .gl-plot-tick-wrapper'
|
||||
);
|
||||
@@ -411,10 +411,10 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
it('turns on cursor Guides all telemetry objects', async () => {
|
||||
let cursorGuide = Vue.ref(plotViewComponentObject.cursorGuide);
|
||||
let cursorGuide = ref(plotViewComponentObject.cursorGuide);
|
||||
expect(cursorGuide.value).toBeFalse();
|
||||
cursorGuide.value = true;
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let childCursorGuides = element.querySelectorAll('.c-cursor-guide--v');
|
||||
expect(childCursorGuides.length).toBe(1);
|
||||
});
|
||||
@@ -432,10 +432,10 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
it('hides grid lines for all telemetry objects', async () => {
|
||||
let gridLines = Vue.ref(plotViewComponentObject.gridLines);
|
||||
let gridLines = ref(plotViewComponentObject.gridLines);
|
||||
expect(gridLines.value).toBeTrue();
|
||||
gridLines.value = false;
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(gridLines.value).toBeFalse();
|
||||
let gridLinesContainer = element.querySelectorAll('.gl-plot-display-area .js-ticks');
|
||||
let visible = 0;
|
||||
@@ -488,7 +488,7 @@ describe('the plugin', function () {
|
||||
max: 10
|
||||
});
|
||||
expect(
|
||||
plotViewComponentObject.$children[0].component.$children[0].$children[1].xScale.domain()
|
||||
plotViewComponentObject.$refs.stackedPlotItems[0].component.$refs.plotComponent.$refs.mctPlot.xScale.domain()
|
||||
).toEqual({
|
||||
min: 0,
|
||||
max: 10
|
||||
@@ -505,7 +505,8 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
const yAxesScales =
|
||||
plotViewComponentObject.$children[0].component.$children[0].$children[1].yScale;
|
||||
plotViewComponentObject.$refs.stackedPlotItems[0].component.$refs.plotComponent.$refs
|
||||
.mctPlot.yScale;
|
||||
yAxesScales.forEach((yAxisScale) => {
|
||||
expect(yAxisScale.scale.domain()).toEqual({
|
||||
min: 10,
|
||||
@@ -628,7 +629,7 @@ describe('the plugin', function () {
|
||||
);
|
||||
destroyPlotOptions = destroy;
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
viewComponentObject = vNode.componentInstance;
|
||||
});
|
||||
|
||||
@@ -783,7 +784,7 @@ describe('the plugin', function () {
|
||||
);
|
||||
destroyPlotOptions = destroy;
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
viewComponentObject = vNode.componentInstance;
|
||||
});
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ define([
|
||||
const options = this.generateSelectOptions();
|
||||
|
||||
newInput = document.createElement('select');
|
||||
newInput.innerHTML = options;
|
||||
newInput.appendChild(options);
|
||||
|
||||
emitChange = true;
|
||||
} else {
|
||||
@@ -244,12 +244,16 @@ define([
|
||||
|
||||
Condition.prototype.generateSelectOptions = function () {
|
||||
let telemetryMetadata = this.conditionManager.getTelemetryMetadata(this.config.object);
|
||||
let options = '';
|
||||
let fragment = document.createDocumentFragment();
|
||||
|
||||
telemetryMetadata[this.config.key].enumerations.forEach((enumeration) => {
|
||||
options += '<option value="' + enumeration.value + '">' + enumeration.string + '</option>';
|
||||
const option = document.createElement('option');
|
||||
option.value = enumeration.value;
|
||||
option.textContent = enumeration.string;
|
||||
fragment.appendChild(option);
|
||||
});
|
||||
|
||||
return options;
|
||||
return fragment;
|
||||
};
|
||||
|
||||
return Condition;
|
||||
|
||||
@@ -167,7 +167,8 @@ define([
|
||||
const ruleHeader = self.domElement
|
||||
.querySelectorAll('.widget-rule-header')[0]
|
||||
.cloneNode(true);
|
||||
indicator.innerHTML = ruleHeader;
|
||||
indicator.textContent = '';
|
||||
indicator.appendChild(ruleHeader);
|
||||
});
|
||||
self.widgetDnD.setDragImage(
|
||||
self.domElement.querySelectorAll('.widget-rule-header')[0].cloneNode(true)
|
||||
@@ -239,8 +240,8 @@ define([
|
||||
this.listenTo(this.toggleConfigButton, 'click', toggleConfig);
|
||||
this.listenTo(this.trigger, 'change', onTriggerInput);
|
||||
|
||||
this.title.innerHTML = self.config.name;
|
||||
this.description.innerHTML = self.config.description;
|
||||
this.title.innerText = self.config.name;
|
||||
this.description.innerText = self.config.description;
|
||||
this.trigger.value = self.config.trigger;
|
||||
|
||||
this.listenTo(this.grippy, 'mousedown', onDragStart);
|
||||
@@ -456,7 +457,7 @@ define([
|
||||
const lastOfType = self.conditionArea.querySelector('li:last-of-type');
|
||||
lastOfType.parentNode.insertBefore($condition, lastOfType);
|
||||
if (loopCnt > 0) {
|
||||
$condition.querySelector('.t-condition-context').innerHTML = triggerContextStr + ' when';
|
||||
$condition.querySelector('.t-condition-context').innerText = triggerContextStr + ' when';
|
||||
}
|
||||
|
||||
loopCnt++;
|
||||
@@ -528,7 +529,7 @@ define([
|
||||
}
|
||||
|
||||
description = description === '' ? this.config.description : description;
|
||||
this.description.innerHTML = self.config.description;
|
||||
this.description.innerText = self.config.description;
|
||||
this.config.description = description;
|
||||
};
|
||||
|
||||
|
||||
@@ -247,9 +247,10 @@ define([
|
||||
SummaryWidget.prototype.updateWidget = function () {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
const activeRule = this.rulesById[this.activeId];
|
||||
|
||||
this.applyStyle(this.domElement.querySelector('#widget'), activeRule.getProperty('style'));
|
||||
this.domElement.querySelector('#widget').title = activeRule.getProperty('message');
|
||||
this.domElement.querySelector('#widgetLabel').innerHTML = activeRule.getProperty('label');
|
||||
this.domElement.querySelector('#widgetLabel').textContent = activeRule.getProperty('label');
|
||||
this.domElement.querySelector('#widgetIcon').classList =
|
||||
WIDGET_ICON_CLASS + ' ' + activeRule.getProperty('icon');
|
||||
};
|
||||
|
||||
@@ -44,11 +44,12 @@ define([
|
||||
self.setNullOption(this.nullOption);
|
||||
|
||||
self.items.forEach(function (item) {
|
||||
const itemElement = `<div class = "c-palette__item ${item}" data-item = "${item}"></div>`;
|
||||
const temp = document.createElement('div');
|
||||
temp.innerHTML = itemElement;
|
||||
self.itemElements[item] = temp.firstChild;
|
||||
self.domElement.querySelector('.c-palette__items').appendChild(temp.firstChild);
|
||||
const itemElement = document.createElement('div');
|
||||
itemElement.className = 'c-palette__item ' + item;
|
||||
itemElement.setAttribute('data-item', item);
|
||||
|
||||
self.itemElements[item] = itemElement;
|
||||
self.domElement.querySelector('.c-palette__items').appendChild(itemElement);
|
||||
});
|
||||
|
||||
self.domElement.querySelector('.c-menu').style.display = 'none';
|
||||
|
||||
@@ -1,35 +1,60 @@
|
||||
define(['./summary-widget.html', '@braintree/sanitize-url'], function (
|
||||
summaryWidgetTemplate,
|
||||
urlSanitizeLib
|
||||
) {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
import * as urlSanitizeLib from '@braintree/sanitize-url';
|
||||
|
||||
function SummaryWidgetView(domainObject, openmct) {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
|
||||
class SummaryWidgetView {
|
||||
#createSummaryWidgetTemplate() {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.classList.add(
|
||||
't-summary-widget',
|
||||
'c-summary-widget',
|
||||
'js-sw',
|
||||
'u-links',
|
||||
'u-fills-container'
|
||||
);
|
||||
|
||||
const widgetIcon = document.createElement('div');
|
||||
widgetIcon.id = 'widgetIcon';
|
||||
widgetIcon.classList.add('c-sw__icon', 'js-sw__icon');
|
||||
anchor.appendChild(widgetIcon);
|
||||
|
||||
const widgetLabel = document.createElement('div');
|
||||
widgetLabel.id = 'widgetLabel';
|
||||
widgetLabel.classList.add('c-sw__label', 'js-sw__label');
|
||||
widgetLabel.textContent = 'Loading...';
|
||||
anchor.appendChild(widgetLabel);
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
constructor(domainObject, openmct) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.hasUpdated = false;
|
||||
this.render = this.render.bind(this);
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.updateState = function (datum) {
|
||||
updateState(datum) {
|
||||
this.hasUpdated = true;
|
||||
this.widget.style.color = datum.textColor;
|
||||
this.widget.style.backgroundColor = datum.backgroundColor;
|
||||
this.widget.style.borderColor = datum.borderColor;
|
||||
this.widget.title = datum.message;
|
||||
this.label.title = datum.message;
|
||||
this.label.innerHTML = datum.ruleLabel;
|
||||
this.label.textContent = datum.ruleLabel;
|
||||
this.icon.className = WIDGET_ICON_CLASS + ' ' + datum.icon;
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.render = function () {
|
||||
render() {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
this.hasUpdated = false;
|
||||
|
||||
this.container.innerHTML = summaryWidgetTemplate;
|
||||
const anchor = this.#createSummaryWidgetTemplate();
|
||||
this.container.appendChild(anchor);
|
||||
|
||||
this.widget = this.container.querySelector('a');
|
||||
this.icon = this.container.querySelector('#widgetIcon');
|
||||
this.label = this.container.querySelector('.js-sw__label');
|
||||
@@ -49,33 +74,32 @@ define(['./summary-widget.html', '@braintree/sanitize-url'], function (
|
||||
|
||||
const renderTracker = {};
|
||||
this.renderTracker = renderTracker;
|
||||
|
||||
this.openmct.telemetry
|
||||
.request(this.domainObject, {
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
})
|
||||
.then(
|
||||
function (results) {
|
||||
if (
|
||||
this.destroyed ||
|
||||
this.hasUpdated ||
|
||||
this.renderTracker !== renderTracker ||
|
||||
results.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
.then((results) => {
|
||||
if (
|
||||
this.destroyed ||
|
||||
this.hasUpdated ||
|
||||
this.renderTracker !== renderTracker ||
|
||||
results.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateState(results[results.length - 1]);
|
||||
}.bind(this)
|
||||
);
|
||||
this.updateState(results[results.length - 1]);
|
||||
});
|
||||
|
||||
this.unsubscribe = this.openmct.telemetry.subscribe(
|
||||
this.domainObject,
|
||||
this.updateState.bind(this)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.show = function (container) {
|
||||
show(container) {
|
||||
this.container = container;
|
||||
this.render();
|
||||
this.removeMutationListener = this.openmct.objects.observe(
|
||||
@@ -84,14 +108,14 @@ define(['./summary-widget.html', '@braintree/sanitize-url'], function (
|
||||
this.onMutation.bind(this)
|
||||
);
|
||||
this.openmct.time.on('timeSystem', this.render);
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.onMutation = function (domainObject) {
|
||||
onMutation(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.render();
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.destroy = function (container) {
|
||||
destroy() {
|
||||
this.unsubscribe();
|
||||
this.removeMutationListener();
|
||||
this.openmct.time.off('timeSystem', this.render);
|
||||
@@ -100,7 +124,7 @@ define(['./summary-widget.html', '@braintree/sanitize-url'], function (
|
||||
delete this.label;
|
||||
delete this.openmct;
|
||||
delete this.domainObject;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return SummaryWidgetView;
|
||||
});
|
||||
export default SummaryWidgetView;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<a class="t-summary-widget c-summary-widget js-sw u-links u-fills-container">
|
||||
<div id="widgetIcon" class="c-sw__icon js-sw__icon"></div>
|
||||
<div id="widgetLabel" class="c-sw__label js-sw__label">Loading...</div>
|
||||
</a>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import TabsLayout from './plugin';
|
||||
|
||||
@@ -128,7 +128,7 @@ describe('the plugin', function () {
|
||||
let view = tabsLayoutViewProvider.view(testViewObject, []);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('provides a view', () => {
|
||||
@@ -172,7 +172,7 @@ describe('the plugin', function () {
|
||||
let view = tabsLayoutViewProvider.view(testViewObject, []);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -194,7 +194,7 @@ describe('the plugin', function () {
|
||||
const tab = tabEls[i];
|
||||
|
||||
tab.click();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const tabViewEls = element.querySelectorAll('.c-tabs-view__object');
|
||||
expect(tabViewEls.length).toEqual(2);
|
||||
@@ -204,7 +204,7 @@ describe('the plugin', function () {
|
||||
it('false, will only keep the current tab view loaded', async () => {
|
||||
testViewObject.keep_alive = false;
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let tabViewEls = element.querySelectorAll('.c-tabs-view__object');
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import TelemetryTableConfiguration from './TelemetryTableConfiguration';
|
||||
export default function TableConfigurationViewProvider(openmct) {
|
||||
return {
|
||||
key: 'table-configuration',
|
||||
name: 'Configuration',
|
||||
name: 'Config',
|
||||
canView: function (selection) {
|
||||
if (selection.length !== 1 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -153,40 +153,41 @@ define(['lodash', 'EventEmitter'], function (_, EventEmitter) {
|
||||
});
|
||||
}
|
||||
|
||||
mergeSortedRows(rows) {
|
||||
mergeSortedRows(incomingRows) {
|
||||
const mergedRows = [];
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
let existingRowIndex = 0;
|
||||
let incomingRowIndex = 0;
|
||||
|
||||
while (i < this.rows.length && j < rows.length) {
|
||||
const existingRow = this.rows[i];
|
||||
const incomingRow = rows[j];
|
||||
while (existingRowIndex < this.rows.length && incomingRowIndex < incomingRows.length) {
|
||||
const existingRow = this.rows[existingRowIndex];
|
||||
const incomingRow = incomingRows[incomingRowIndex];
|
||||
|
||||
const index = this.getInPlaceUpdateIndex(incomingRow);
|
||||
if (index > -1) {
|
||||
this.updateRowInPlace(incomingRow, index);
|
||||
const inPlaceIndex = this.getInPlaceUpdateIndex(incomingRow);
|
||||
if (inPlaceIndex > -1) {
|
||||
this.updateRowInPlace(incomingRow, inPlaceIndex);
|
||||
incomingRowIndex++;
|
||||
} else {
|
||||
if (this.firstRowInSortOrder(existingRow, incomingRow) === existingRow) {
|
||||
mergedRows.push(existingRow);
|
||||
i++;
|
||||
existingRowIndex++;
|
||||
} else {
|
||||
mergedRows.push(incomingRow);
|
||||
j++;
|
||||
incomingRowIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tail of existing rows is all that is left to merge
|
||||
if (i < this.rows.length) {
|
||||
for (i; i < this.rows.length; i++) {
|
||||
mergedRows.push(this.rows[i]);
|
||||
if (existingRowIndex < this.rows.length) {
|
||||
for (existingRowIndex; existingRowIndex < this.rows.length; existingRowIndex++) {
|
||||
mergedRows.push(this.rows[existingRowIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
// tail of incoming rows is all that is left to merge
|
||||
if (j < rows.length) {
|
||||
for (j; j < rows.length; j++) {
|
||||
mergedRows.push(rows[j]);
|
||||
if (incomingRowIndex < incomingRows.length) {
|
||||
for (incomingRowIndex; incomingRowIndex < incomingRows.length; incomingRowIndex++) {
|
||||
mergedRows.push(incomingRows[incomingRowIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,14 +157,19 @@ export default {
|
||||
},
|
||||
getFilterLabels(filterObject, metadatum) {
|
||||
let filterLabels = [];
|
||||
|
||||
Object.values(filterObject).forEach((comparator) => {
|
||||
comparator.forEach((filterValue) => {
|
||||
metadatum.filters[0].possibleValues.forEach((option) => {
|
||||
if (option.value === filterValue) {
|
||||
filterLabels.push(option.label);
|
||||
}
|
||||
if (typeof comparator !== 'string') {
|
||||
comparator.forEach((filterValue) => {
|
||||
metadatum.filters[0].possibleValues.forEach((option) => {
|
||||
if (option.value === filterValue) {
|
||||
filterLabels.push(option.label);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
filterLabels.push(comparator);
|
||||
}
|
||||
});
|
||||
|
||||
return filterLabels;
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
resetApplicationState,
|
||||
spyOnBuiltins
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import TablePlugin from './plugin.js';
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('the plugin', () => {
|
||||
let tablePlugin;
|
||||
let element;
|
||||
let child;
|
||||
let historicalProvider;
|
||||
let historicalTelemetryProvider;
|
||||
let originalRouterPath;
|
||||
let unlistenConfigMutation;
|
||||
|
||||
@@ -61,12 +61,12 @@ describe('the plugin', () => {
|
||||
tablePlugin = new TablePlugin();
|
||||
openmct.install(tablePlugin);
|
||||
|
||||
historicalProvider = {
|
||||
historicalTelemetryProvider = {
|
||||
request: () => {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
};
|
||||
spyOn(openmct.telemetry, 'findRequestProvider').and.returnValue(historicalProvider);
|
||||
spyOn(openmct.telemetry, 'findRequestProvider').and.returnValue(historicalTelemetryProvider);
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
@@ -137,11 +137,12 @@ describe('the plugin', () => {
|
||||
let tableView;
|
||||
let tableInstance;
|
||||
let mockClock;
|
||||
let telemetryCallback;
|
||||
|
||||
beforeEach(async () => {
|
||||
openmct.time.timeSystem('utc', {
|
||||
start: 0,
|
||||
end: 4
|
||||
end: 10
|
||||
});
|
||||
|
||||
mockClock = jasmine.createSpyObj('clock', ['on', 'off', 'currentValue']);
|
||||
@@ -151,7 +152,7 @@ describe('the plugin', () => {
|
||||
openmct.time.addClock(mockClock);
|
||||
openmct.time.clock('mockClock', {
|
||||
start: 0,
|
||||
end: 4
|
||||
end: 10
|
||||
});
|
||||
|
||||
testTelemetryObject = {
|
||||
@@ -214,7 +215,21 @@ describe('the plugin', () => {
|
||||
}
|
||||
];
|
||||
|
||||
historicalProvider.request = () => Promise.resolve(testTelemetry);
|
||||
historicalTelemetryProvider.request = () => {
|
||||
return Promise.resolve(testTelemetry);
|
||||
};
|
||||
|
||||
const realtimeTelemetryProvider = {
|
||||
supportsSubscribe: () => true,
|
||||
subscribe: (domainObject, passedCallback) => {
|
||||
telemetryCallback = passedCallback;
|
||||
return Promise.resolve(() => {});
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(openmct.telemetry, 'findSubscriptionProvider').and.returnValue(
|
||||
realtimeTelemetryProvider
|
||||
);
|
||||
|
||||
openmct.router.path = [testTelemetryObject];
|
||||
|
||||
@@ -225,7 +240,7 @@ describe('the plugin', () => {
|
||||
|
||||
tableInstance = tableView.getTable();
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -242,7 +257,7 @@ describe('the plugin', () => {
|
||||
|
||||
it('Shows a progress bar while making requests', async () => {
|
||||
tableInstance.incrementOutstandingRequests();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let progressBar = element.querySelector('.c-progress-bar');
|
||||
|
||||
@@ -252,10 +267,27 @@ describe('the plugin', () => {
|
||||
|
||||
it('Renders a row for every telemetry datum returned', async () => {
|
||||
let rows = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(rows.length).toBe(3);
|
||||
});
|
||||
|
||||
it('Adds a row in place when updating with existing telemetry', async () => {
|
||||
let rows = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
await nextTick();
|
||||
expect(rows.length).toBe(3);
|
||||
// fire some telemetry
|
||||
const newTelemetry = {
|
||||
utc: 2,
|
||||
'some-key': 'some-value 2',
|
||||
'some-other-key': 'spacecraft'
|
||||
};
|
||||
spyOn(tableInstance.tableRows, 'getInPlaceUpdateIndex').and.returnValue(1);
|
||||
spyOn(tableInstance.tableRows, 'updateRowInPlace').and.callThrough();
|
||||
telemetryCallback(newTelemetry);
|
||||
|
||||
expect(tableInstance.tableRows.updateRowInPlace.calls.count()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('Renders a column for every item in telemetry metadata', () => {
|
||||
let headers = element.querySelectorAll('span.c-telemetry-table__headers__label');
|
||||
expect(headers.length).toBe(4);
|
||||
@@ -287,7 +319,7 @@ describe('the plugin', () => {
|
||||
toColumn.dispatchEvent(dragOverEvent);
|
||||
toColumn.dispatchEvent(dropEvent);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
columns = element.querySelectorAll('tr.c-telemetry-table__headers__labels th');
|
||||
let firstColumn = columns[0];
|
||||
let secondColumn = columns[1];
|
||||
@@ -305,12 +337,12 @@ describe('the plugin', () => {
|
||||
|
||||
it('Supports filtering telemetry by regular text search', async () => {
|
||||
tableInstance.tableRows.setColumnFilter('some-key', '1');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let filteredRowElements = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
|
||||
expect(filteredRowElements.length).toEqual(1);
|
||||
tableInstance.tableRows.setColumnFilter('some-key', '');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let allRowElements = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
expect(allRowElements.length).toEqual(3);
|
||||
@@ -318,13 +350,13 @@ describe('the plugin', () => {
|
||||
|
||||
it('Supports filtering using Regex', async () => {
|
||||
tableInstance.tableRows.setColumnRegexFilter('some-key', '^some-value$');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let filteredRowElements = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
|
||||
expect(filteredRowElements.length).toEqual(0);
|
||||
|
||||
tableInstance.tableRows.setColumnRegexFilter('some-key', '^some-value');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let allRowElements = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
|
||||
expect(allRowElements.length).toEqual(3);
|
||||
@@ -339,7 +371,7 @@ describe('the plugin', () => {
|
||||
tableInstanceConfiguration
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let tableHeaderElements = element.querySelectorAll('.c-telemetry-table__headers__label');
|
||||
expect(tableHeaderElements.length).toEqual(3);
|
||||
|
||||
@@ -350,7 +382,7 @@ describe('the plugin', () => {
|
||||
tableInstanceConfiguration
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
tableHeaderElements = element.querySelectorAll('.c-telemetry-table__headers__label');
|
||||
expect(tableHeaderElements.length).toEqual(4);
|
||||
});
|
||||
@@ -364,7 +396,7 @@ describe('the plugin', () => {
|
||||
tableInstanceConfiguration
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
let tableRowCells = element.querySelectorAll(
|
||||
'table.c-telemetry-table__body > tbody > tr:first-child td'
|
||||
);
|
||||
@@ -377,7 +409,7 @@ describe('the plugin', () => {
|
||||
tableInstanceConfiguration
|
||||
);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
tableRowCells = element.querySelectorAll(
|
||||
'table.c-telemetry-table__body > tbody > tr:first-child td'
|
||||
);
|
||||
@@ -391,7 +423,7 @@ describe('the plugin', () => {
|
||||
// Mark a row
|
||||
firstRow.dispatchEvent(clickEvent);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).not.toBeNull();
|
||||
@@ -404,13 +436,13 @@ describe('the plugin', () => {
|
||||
// Mark a row
|
||||
firstRow.dispatchEvent(clickEvent);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).not.toBeNull();
|
||||
|
||||
const currentBounds = openmct.time.bounds();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const newBounds = {
|
||||
start: currentBounds.start,
|
||||
end: currentBounds.end - 3
|
||||
@@ -418,7 +450,7 @@ describe('the plugin', () => {
|
||||
|
||||
// Manually change the time bounds
|
||||
openmct.time.bounds(newBounds);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is no longer paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).toBeNull();
|
||||
@@ -429,13 +461,13 @@ describe('the plugin', () => {
|
||||
|
||||
// Pause by button
|
||||
viewContext.togglePauseByButton();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).not.toBeNull();
|
||||
|
||||
const currentBounds = openmct.time.bounds();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const newBounds = {
|
||||
start: currentBounds.start,
|
||||
@@ -444,7 +476,7 @@ describe('the plugin', () => {
|
||||
// Manually change the time bounds
|
||||
openmct.time.bounds(newBounds);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is no longer paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).toBeNull();
|
||||
@@ -456,7 +488,7 @@ describe('the plugin', () => {
|
||||
// Pause by button
|
||||
viewContext.togglePauseByButton();
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table displays the correct number of rows
|
||||
let tableRows = element.querySelectorAll('table.c-telemetry-table__body > tbody > tr');
|
||||
@@ -468,12 +500,12 @@ describe('the plugin', () => {
|
||||
// Tick the clock
|
||||
openmct.time.tick(1);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table is still paused
|
||||
expect(element.querySelector('div.c-table.is-paused')).not.toBeNull();
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
// Verify table displays the correct number of rows
|
||||
tableRows = element.querySelectorAll('table.c-telemetry-table__body > tbody > tr');
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { FIXED_MODE_KEY } from '../../api/time/constants';
|
||||
import { getPreciseDuration, millisecondsToDHMS } from '../../utils/duration';
|
||||
@@ -80,7 +80,7 @@ describe('time conductor', () => {
|
||||
start: config.menuOptions[0].bounds.start,
|
||||
end: config.menuOptions[0].bounds.end
|
||||
});
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -118,18 +118,18 @@ describe('time conductor', () => {
|
||||
const switcher = appHolder.querySelector('.is-fixed-mode');
|
||||
const clickEvent = createMouseEvent('click');
|
||||
switcher.dispatchEvent(clickEvent);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const modeButton = switcher.querySelector('.c-tc-input-popup .c-button--menu');
|
||||
const clickEvent1 = createMouseEvent('click');
|
||||
modeButton.dispatchEvent(clickEvent1);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const clockItem = document.querySelectorAll(
|
||||
'.c-conductor__mode-menu .c-super-menu__menu li'
|
||||
)[1];
|
||||
const clickEvent2 = createMouseEvent('click');
|
||||
clockItem.dispatchEvent(clickEvent2);
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('shows delta inputs', () => {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { createOpenMct, resetApplicationState } from '@/utils/testing';
|
||||
|
||||
@@ -184,11 +184,11 @@ describe('the plugin', function () {
|
||||
let view = timelineView.view(testViewObject, mockObjectPath);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('provides a view', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(timelineView).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -240,12 +240,12 @@ describe('the plugin', function () {
|
||||
let view = timelineView.view(timelineDomainObject, [timelineDomainObject]);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
xit('loads the plan from composition', async () => {
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
const items = element.querySelectorAll('.js-timeline__content');
|
||||
expect(items.length).toEqual(1);
|
||||
});
|
||||
@@ -267,11 +267,11 @@ describe('the plugin', function () {
|
||||
let view = timelineView.view(testViewObject, mockObjectPath);
|
||||
view.show(child, true);
|
||||
|
||||
Vue.nextTick(done);
|
||||
nextTick(done);
|
||||
});
|
||||
|
||||
xit('displays an independent time conductor with saved options - local clock', () => {
|
||||
return Vue.nextTick(() => {
|
||||
return nextTick(() => {
|
||||
const independentTimeConductorEl = element.querySelector(
|
||||
'.c-timeline-holder > .c-conductor__controls'
|
||||
);
|
||||
@@ -308,11 +308,11 @@ describe('the plugin', function () {
|
||||
let view = timelineView.view(testViewObject2, mockObjectPath);
|
||||
view.show(child, true);
|
||||
|
||||
Vue.nextTick(done);
|
||||
nextTick(done);
|
||||
});
|
||||
|
||||
xit('displays an independent time conductor with saved options - fixed timespan', () => {
|
||||
return Vue.nextTick(() => {
|
||||
return nextTick(() => {
|
||||
const independentTimeConductorEl = element.querySelector(
|
||||
'.c-timeline-holder > .c-conductor__controls'
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { FIXED_MODE_KEY } from '../../api/time/constants';
|
||||
import { TIMELIST_TYPE } from './constants';
|
||||
@@ -210,7 +210,7 @@ describe('the plugin', function () {
|
||||
let view = timelistView.view(timelistDomainObject, []);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('displays the activities', () => {
|
||||
@@ -226,7 +226,7 @@ describe('the plugin', function () {
|
||||
it('displays activity details', (done) => {
|
||||
const timeFormat = openmct.time.timeSystem().timeFormat;
|
||||
const timeFormatter = openmct.telemetry.getValueFormatter({ format: timeFormat }).formatter;
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
const itemEls = element.querySelectorAll(LIST_ITEM_CLASS);
|
||||
const itemValues = itemEls[0].querySelectorAll(LIST_ITEM_VALUE_CLASS);
|
||||
expect(itemValues.length).toEqual(4);
|
||||
@@ -287,13 +287,13 @@ describe('the plugin', function () {
|
||||
let view = timelistView.view(timelistDomainObject, [timelistDomainObject]);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('loads the plan from composition', () => {
|
||||
mockComposition.emit('add', planObject);
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
return nextTick(() => {
|
||||
const items = element.querySelectorAll(LIST_ITEM_CLASS);
|
||||
expect(items.length).toEqual(2);
|
||||
});
|
||||
@@ -342,13 +342,13 @@ describe('the plugin', function () {
|
||||
let view = timelistView.view(timelistDomainObject, [timelistDomainObject]);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('activities', () => {
|
||||
mockComposition.emit('add', planObject);
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
return nextTick(() => {
|
||||
const items = element.querySelectorAll(LIST_ITEM_CLASS);
|
||||
expect(items.length).toEqual(1);
|
||||
});
|
||||
@@ -397,13 +397,13 @@ describe('the plugin', function () {
|
||||
let view = timelistView.view(timelistDomainObject, [timelistDomainObject]);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('hides past events', () => {
|
||||
mockComposition.emit('add', planObject);
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
return nextTick(() => {
|
||||
const items = element.querySelectorAll(LIST_ITEM_CLASS);
|
||||
expect(items.length).toEqual(1);
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState, spyOnBuiltins } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import timerPlugin from './plugin';
|
||||
|
||||
@@ -108,7 +108,7 @@ xdescribe('Timer plugin:', () => {
|
||||
timerView = timerViewProvider.view(mutableTimerObject, timerObjectPath);
|
||||
timerView.show(child);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -168,7 +168,7 @@ xdescribe('Timer plugin:', () => {
|
||||
timerView = timerViewProvider.view(mutableTimerObject, timerObjectPath);
|
||||
timerView.show(child);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -211,7 +211,7 @@ xdescribe('Timer plugin:', () => {
|
||||
});
|
||||
|
||||
it('gets errors from actions if configuration is not passed', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const objectPath = _.cloneDeep(timerObjectPath);
|
||||
delete objectPath[0].configuration;
|
||||
|
||||
@@ -265,7 +265,7 @@ xdescribe('Timer plugin:', () => {
|
||||
openmct.objects.mutate(timerViewObject, 'configuration.timestamp', newBaseTime);
|
||||
|
||||
jasmine.clock().tick(5000);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const timerElement = element.querySelector('.c-timer');
|
||||
const timerPausePlayButton = timerElement.querySelector('.c-timer__ctrl-pause-play');
|
||||
@@ -282,7 +282,7 @@ xdescribe('Timer plugin:', () => {
|
||||
openmct.objects.mutate(timerViewObject, 'configuration.timestamp', newBaseTime);
|
||||
|
||||
jasmine.clock().tick(5000);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const timerElement = element.querySelector('.c-timer');
|
||||
const timerPausePlayButton = timerElement.querySelector('.c-timer__ctrl-pause-play');
|
||||
@@ -296,14 +296,14 @@ xdescribe('Timer plugin:', () => {
|
||||
|
||||
it('displays a paused timer correctly in the DOM', async () => {
|
||||
jasmine.clock().tick(5000);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
let action = openmct.actions.getAction('timer.pause');
|
||||
if (action) {
|
||||
action.invoke(timerObjectPath, timerView);
|
||||
}
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const timerElement = element.querySelector('.c-timer');
|
||||
const timerPausePlayButton = timerElement.querySelector('.c-timer__ctrl-pause-play');
|
||||
let timerValue = timerElement.querySelector('.c-timer__value').innerText;
|
||||
@@ -312,7 +312,7 @@ xdescribe('Timer plugin:', () => {
|
||||
expect(timerValue).toBe('0D 23:59:55');
|
||||
|
||||
jasmine.clock().tick(5000);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
expect(timerValue).toBe('0D 23:59:55');
|
||||
|
||||
action = openmct.actions.getAction('timer.start');
|
||||
@@ -320,13 +320,13 @@ xdescribe('Timer plugin:', () => {
|
||||
action.invoke(timerObjectPath, timerView);
|
||||
}
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
action = openmct.actions.getAction('timer.pause');
|
||||
if (action) {
|
||||
action.invoke(timerObjectPath, timerView);
|
||||
}
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
timerValue = timerElement.querySelector('.c-timer__value').innerText;
|
||||
expect(timerValue).toBe('1D 00:00:00');
|
||||
});
|
||||
@@ -337,7 +337,7 @@ xdescribe('Timer plugin:', () => {
|
||||
action.invoke(timerObjectPath, timerView);
|
||||
}
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const timerElement = element.querySelector('.c-timer');
|
||||
const timerValue = timerElement.querySelector('.c-timer__value').innerText;
|
||||
const timerResetButton = timerElement.querySelector('.c-timer__ctrl-reset');
|
||||
@@ -355,7 +355,7 @@ xdescribe('Timer plugin:', () => {
|
||||
}
|
||||
|
||||
jasmine.clock().tick(5000);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const timerElement = element.querySelector('.c-timer');
|
||||
const timerValue = timerElement.querySelector('.c-timer__value').innerText;
|
||||
const timerPausePlayButton = timerElement.querySelector('.c-timer__ctrl-pause-play');
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ExampleUserProvider from '../../../example/exampleUser/ExampleUserProvider';
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('The User Indicator plugin', () => {
|
||||
|
||||
openmct.user.setProvider(provider);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('exists', () => {
|
||||
@@ -85,7 +85,7 @@ describe('The User Indicator plugin', () => {
|
||||
openmct.user
|
||||
.getCurrentUser()
|
||||
.then(async (user) => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
userIndicator = openmct.indicators.indicatorObjects.find(
|
||||
(indicator) => indicator.key === 'user-indicator'
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import { toRaw } from 'vue';
|
||||
|
||||
import StyleRuleManager from '@/plugins/condition/StyleRuleManager';
|
||||
import { STYLE_CONSTANTS } from '@/plugins/condition/utils/constants';
|
||||
@@ -272,16 +273,16 @@ export default {
|
||||
|
||||
if (provider.edit && this.showEditView) {
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
this.currentView = provider.edit(this.domainObject, true, objectPath);
|
||||
this.currentView = provider.edit(toRaw(this.domainObject), true, objectPath);
|
||||
} else {
|
||||
this.currentView = provider.view(this.domainObject, objectPath);
|
||||
this.currentView = provider.view(toRaw(this.domainObject), objectPath);
|
||||
}
|
||||
|
||||
this.openmct.editor.on('isEditing', this.toggleEditView);
|
||||
this.releaseEditModeHandler = () =>
|
||||
this.openmct.editor.off('isEditing', this.toggleEditView);
|
||||
} else {
|
||||
this.currentView = provider.view(this.domainObject, objectPath);
|
||||
this.currentView = provider.view(toRaw(this.domainObject), objectPath);
|
||||
|
||||
if (this.currentView.onEditModeChange) {
|
||||
this.openmct.editor.on('isEditing', this.invokeEditModeHandler);
|
||||
@@ -439,7 +440,7 @@ export default {
|
||||
if (
|
||||
provider &&
|
||||
provider.canEdit &&
|
||||
provider.canEdit(this.domainObject, objectPath) &&
|
||||
provider.canEdit(toRaw(this.domainObject), objectPath) &&
|
||||
this.isEditingAllowed() &&
|
||||
!this.openmct.editor.isEditing()
|
||||
) {
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<template>
|
||||
<div class="c-search" :class="{ 'is-active': active }">
|
||||
<div class="c-search" v-bind="$attrs" :class="{ 'is-active': active }">
|
||||
<input
|
||||
v-bind="$attrs"
|
||||
class="c-search__input"
|
||||
aria-label="Search Input"
|
||||
tabindex="10000"
|
||||
type="search"
|
||||
:value="value"
|
||||
@input="handleInput"
|
||||
@click="handleClick"
|
||||
v-bind="$attrs"
|
||||
@click="() => $emit('click')"
|
||||
@input="($event) => $emit('input', $event.target.value)"
|
||||
/>
|
||||
<a v-if="value" class="c-search__clear-input icon-x-in-circle" @click="clearInput"></a>
|
||||
<slot></slot>
|
||||
@@ -46,7 +46,7 @@ export default {
|
||||
}
|
||||
},
|
||||
emits: ['input', 'clear', 'click'],
|
||||
data: function () {
|
||||
data() {
|
||||
return {
|
||||
active: false
|
||||
};
|
||||
@@ -61,12 +61,6 @@ export default {
|
||||
// Clear the user's input and set 'active' to false
|
||||
this.$emit('clear', '');
|
||||
this.active = false;
|
||||
},
|
||||
handleInput(event) {
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
handleClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const INSPECTOR_SELECTOR_PREFIX = '.c-inspect-properties__';
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('the inspector', () => {
|
||||
|
||||
it('displays default details for selection', async () => {
|
||||
openmct.selection.select(selection);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const details = getDetails();
|
||||
const [title, type, createdBy, modifiedBy, notes, timestamp] = details;
|
||||
@@ -92,7 +92,7 @@ describe('the inspector', () => {
|
||||
folderItem.modified = modifiedTimestamp;
|
||||
|
||||
openmct.selection.select(selection);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const details = getDetails();
|
||||
const timestamp = details[details.length - 1];
|
||||
@@ -115,7 +115,7 @@ describe('the inspector', () => {
|
||||
selection[0].context.details = customDetails;
|
||||
|
||||
openmct.selection.select(selection);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const details = getDetails();
|
||||
|
||||
|
||||
@@ -60,11 +60,11 @@ describe('the inspector', () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(0);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(0);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should display all saved styles', () => {
|
||||
@@ -72,11 +72,11 @@ describe('the inspector', () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(0);
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(0);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(1);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -87,17 +87,15 @@ describe('the inspector', () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
const styleSelectorComponent = savedStylesViewComponent.$children[0].$children[0];
|
||||
const styleSelectorComponent = savedStylesViewComponent.$refs.root.$refs.root;
|
||||
|
||||
styleSelectorComponent.selectStyle();
|
||||
|
||||
return savedStylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent =
|
||||
stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const styleEditorComponent = stylesViewComponent.$refs.root.$refs.styleEditor;
|
||||
const styles = styleEditorComponent.$children.filter(
|
||||
(component) => component.options.value === mockStyle.color
|
||||
);
|
||||
@@ -112,13 +110,13 @@ describe('the inspector', () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(1);
|
||||
|
||||
savedStylesViewComponent.$children[0].deleteStyle(0);
|
||||
savedStylesViewComponent.$refs.root.deleteStyle(0);
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(0);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should prevent a style from being saved when the number of saved styles is at the limit', () => {
|
||||
@@ -129,16 +127,16 @@ describe('the inspector', () => {
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
for (let i = 1; i <= 20; i++) {
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
}
|
||||
|
||||
expect(SavedStylesView.methods.showLimitReachedDialog).not.toHaveBeenCalled();
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(20);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(20);
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
stylesViewComponent.$refs.root.saveStyle(mockStyle);
|
||||
|
||||
expect(SavedStylesView.methods.showLimitReachedDialog).toHaveBeenCalled();
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(20);
|
||||
expect(savedStylesViewComponent.$refs.root.savedStyles.length).toBe(20);
|
||||
});
|
||||
|
||||
it('should allow styles from multi-selections to be saved', () => {
|
||||
@@ -149,17 +147,14 @@ describe('the inspector', () => {
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent =
|
||||
stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
const styleEditorComponent = stylesViewComponent.$refs.root.$refs.styleEditor;
|
||||
const saveStyleButton = styleEditorComponent.$refs.saveStyleButton;
|
||||
|
||||
expect(saveStyleButton.$listeners.click).not.toBe(undefined);
|
||||
expect(saveStyleButton).not.toBe(undefined);
|
||||
|
||||
saveStyleButton.$listeners.click();
|
||||
saveStyleButton.$refs.button.click();
|
||||
|
||||
expect(savedStylesViewComponent.$children[0].savedStyles.length).toBe(1);
|
||||
expect(savedStylesViewComponent.$refs.root.$data.savedStyles.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -171,13 +166,11 @@ describe('the inspector', () => {
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent =
|
||||
stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
const styleEditorComponent = stylesViewComponent.$refs.root.$refs.styleEditor;
|
||||
const saveStyleButton = styleEditorComponent.$refs.saveStyleButton;
|
||||
|
||||
expect(saveStyleButton.$listeners.click).toBe(undefined);
|
||||
// Saving should not be enabled, thus the button ref should be undefined
|
||||
expect(saveStyleButton).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -189,13 +182,11 @@ describe('the inspector', () => {
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent =
|
||||
stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
const saveStyleButton = styleEditorComponent.$children[saveStyleButtonIndex];
|
||||
const styleEditorComponent = stylesViewComponent.$refs.root.$refs.styleEditor;
|
||||
const saveStyleButton = styleEditorComponent.$refs.saveStyleButton;
|
||||
|
||||
expect(saveStyleButton.$listeners.click).toBe(undefined);
|
||||
// Saving should not be enabled, thus the button ref should be undefined
|
||||
expect(saveStyleButton).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -211,7 +202,7 @@ describe('the inspector', () => {
|
||||
stylesManager
|
||||
},
|
||||
components: {},
|
||||
template: `<${component.name} />`
|
||||
template: `<${component.name} ref="root"/>`
|
||||
};
|
||||
|
||||
config.components[component.name] = component;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import mount from 'utils/mount';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import Layout from './AppLayout.vue';
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('Open MCT Layout:', () => {
|
||||
describe('the pane:', () => {
|
||||
it('is displayed on layout load', async () => {
|
||||
await createLayout();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
Object.entries(components).forEach(([name, component]) => {
|
||||
expect(component.pane).toBeTruthy();
|
||||
@@ -61,8 +61,8 @@ describe('Open MCT Layout:', () => {
|
||||
setHideParams();
|
||||
|
||||
await createLayout();
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
Object.entries(components).forEach(([name, component]) => {
|
||||
expect(isCollapsed(component.pane)).toBeTrue();
|
||||
@@ -71,9 +71,9 @@ describe('Open MCT Layout:', () => {
|
||||
|
||||
it('on toggle collapses if expanded', async () => {
|
||||
await createLayout();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
toggleCollapseButtons();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
Object.entries(components).forEach(([name, component]) => {
|
||||
expect(openmct.router.getSearchParam(component.param)).toEqual('true');
|
||||
@@ -86,7 +86,7 @@ describe('Open MCT Layout:', () => {
|
||||
setHideParams();
|
||||
|
||||
await createLayout();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
toggleExpandButtons();
|
||||
|
||||
Object.entries(components).forEach(([name, component]) => {
|
||||
|
||||
@@ -187,7 +187,7 @@ export default {
|
||||
const clickedPreviewClose =
|
||||
event.target.parentElement &&
|
||||
event.target.parentElement.querySelector('.js-preview-window');
|
||||
const searchResultsDropDown = this.$refs.searchResultsDropDown._data;
|
||||
const searchResultsDropDown = this.$refs.searchResultsDropDown._.data;
|
||||
if (
|
||||
!clickedInsideDropdown &&
|
||||
searchResultsDropDown.resultsShown &&
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import mount from 'utils/mount';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ExampleTagsPlugin from '../../../../example/exampleTags/plugin';
|
||||
import DisplayLayoutPlugin from '../../../plugins/displayLayout/plugin';
|
||||
@@ -197,7 +197,7 @@ describe('GrandSearch', () => {
|
||||
provide: {
|
||||
openmct
|
||||
},
|
||||
template: '<GrandSearch/>'
|
||||
template: '<GrandSearch ref="root"/>'
|
||||
},
|
||||
{
|
||||
element: viewContainer
|
||||
@@ -205,7 +205,7 @@ describe('GrandSearch', () => {
|
||||
);
|
||||
grandSearchComponent = vNode.componentInstance;
|
||||
_destroy = destroy;
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
done();
|
||||
});
|
||||
openmct.startHeadless();
|
||||
@@ -220,8 +220,8 @@ describe('GrandSearch', () => {
|
||||
});
|
||||
|
||||
it('should render an object search result', async () => {
|
||||
await grandSearchComponent.$children[0].searchEverything('foo');
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('foo');
|
||||
await nextTick();
|
||||
const searchResults = document.querySelectorAll(
|
||||
'[aria-label="fooRabbitNotebook notebook result"]'
|
||||
);
|
||||
@@ -233,9 +233,9 @@ describe('GrandSearch', () => {
|
||||
const composition = openmct.composition.get(mockFolderObject);
|
||||
composition.add(mockNewObject);
|
||||
// after adding, need to wait a beat for the folder to be indexed
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$children[0].searchEverything('apple');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('apple');
|
||||
await nextTick();
|
||||
const searchResults = document.querySelectorAll(
|
||||
'[aria-label="New Apple Test Folder folder result"]'
|
||||
);
|
||||
@@ -259,8 +259,8 @@ describe('GrandSearch', () => {
|
||||
|
||||
const composition = openmct.composition.get(mockFolderObject);
|
||||
composition.add(mockNewObject);
|
||||
await grandSearchComponent.$children[0].searchEverything('apple');
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('apple');
|
||||
await nextTick();
|
||||
const searchResults = document.querySelectorAll(
|
||||
'[aria-label="New Apple Test Folder folder result"]'
|
||||
);
|
||||
@@ -270,24 +270,24 @@ describe('GrandSearch', () => {
|
||||
});
|
||||
|
||||
it('should render an annotation search result', async () => {
|
||||
await grandSearchComponent.$children[0].searchEverything('S');
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('S');
|
||||
await nextTick();
|
||||
const annotationResults = document.querySelectorAll('[aria-label="Search Result"]');
|
||||
expect(annotationResults.length).toBe(2);
|
||||
expect(annotationResults[1].innerText).toContain('Driving');
|
||||
});
|
||||
|
||||
it('should render no annotation search results if no match', async () => {
|
||||
await grandSearchComponent.$children[0].searchEverything('Qbert');
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('Qbert');
|
||||
await nextTick();
|
||||
const annotationResults = document.querySelectorAll('[aria-label="Search Result"]');
|
||||
expect(annotationResults.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should preview object search results in edit mode if object clicked', async () => {
|
||||
await grandSearchComponent.$children[0].searchEverything('Folder');
|
||||
grandSearchComponent.$children[0].openmct.router.path = [mockDisplayLayout];
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('Folder');
|
||||
grandSearchComponent.$refs.root.openmct.router.path = [mockDisplayLayout];
|
||||
await nextTick();
|
||||
const searchResults = document.querySelectorAll('[name="Test Folder"]');
|
||||
expect(searchResults.length).toBe(1);
|
||||
expect(searchResults[0].innerText).toContain('Folder');
|
||||
@@ -297,9 +297,9 @@ describe('GrandSearch', () => {
|
||||
});
|
||||
|
||||
it('should preview annotation search results in edit mode if annotation clicked', async () => {
|
||||
await grandSearchComponent.$children[0].searchEverything('Dri');
|
||||
grandSearchComponent.$children[0].openmct.router.path = [mockDisplayLayout];
|
||||
await Vue.nextTick();
|
||||
await grandSearchComponent.$refs.root.searchEverything('Dri');
|
||||
grandSearchComponent.$refs.root.openmct.router.path = [mockDisplayLayout];
|
||||
await nextTick();
|
||||
const annotationResults = document.querySelectorAll('[aria-label="Search Result"]');
|
||||
expect(annotationResults.length).toBe(1);
|
||||
expect(annotationResults[0].innerText).toContain('Driving');
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<template>
|
||||
<div class="c-ctrl-wrapper">
|
||||
<div
|
||||
ref="button"
|
||||
class="c-icon-button"
|
||||
:title="options.title"
|
||||
:class="{
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
export function convertTemplateToHTML(templateString) {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = templateString;
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(templateString, 'text/html');
|
||||
|
||||
return template.content.cloneNode(true).children;
|
||||
// Create a document fragment to hold the parsed content
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// Append nodes from the parsed content to the fragment
|
||||
while (doc.body.firstChild) {
|
||||
fragment.appendChild(doc.body.firstChild);
|
||||
}
|
||||
|
||||
// Convert children of the fragment to an array and return
|
||||
return Array.from(fragment.children);
|
||||
}
|
||||
|
||||
export function toggleClass(element, className) {
|
||||
|
||||
Reference in New Issue
Block a user