Skip to content

Commit

Permalink
Merge branch 'master' into vomct398
Browse files Browse the repository at this point in the history
  • Loading branch information
ozyx committed Nov 13, 2023
2 parents 8c8d6d5 + deacd91 commit 0e8fa4c
Show file tree
Hide file tree
Showing 13 changed files with 558 additions and 211 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@
"blockquotes",
"Blockquote",
"Blockquotes",
"oger",
"lcovonly",
"gcov"
],
Expand Down
74 changes: 74 additions & 0 deletions e2e/tests/functional/plugins/tabs/tabs.e2e.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*****************************************************************************
* 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.
*****************************************************************************/

const { createDomainObjectWithDefaults } = require('../../../../appActions');
const { test, expect } = require('../../../../pluginFixtures');

test.describe('Tabs View', () => {
test('Renders tabbed elements', async ({ page }) => {
await page.goto('./', { waitUntil: 'domcontentloaded' });

const tabsView = await createDomainObjectWithDefaults(page, {
type: 'Tabs View'
});
const table = await createDomainObjectWithDefaults(page, {
type: 'Telemetry Table',
parent: tabsView.uuid
});
await createDomainObjectWithDefaults(page, {
type: 'Event Message Generator',
parent: table.uuid
});
const notebook = await createDomainObjectWithDefaults(page, {
type: 'Notebook',
parent: tabsView.uuid
});
const sineWaveGenerator = await createDomainObjectWithDefaults(page, {
type: 'Sine Wave Generator',
parent: tabsView.uuid
});

page.goto(tabsView.url);

// select first tab
await page.getByLabel(`${table.name} tab`).click();
// ensure table header visible
await expect(page.getByRole('searchbox', { name: 'message filter input' })).toBeVisible();

// select second tab
await page.getByLabel(`${notebook.name} tab`).click();

// ensure notebook visible
await expect(page.locator('.c-notebook__drag-area')).toBeVisible();

// select third tab
await page.getByLabel(`${sineWaveGenerator.name} tab`).click();

// expect sine wave generator visible
expect(await page.locator('.c-plot').isVisible()).toBe(true);

// now try to select the first tab again
await page.getByLabel(`${table.name} tab`).click();
// ensure table header visible
await expect(page.getByRole('searchbox', { name: 'message filter input' })).toBeVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,85 @@ test.describe('Telemetry Table', () => {
const endBoundMilliseconds = Date.parse(endDate);
expect(latestMilliseconds).toBeLessThanOrEqual(endBoundMilliseconds);
});

test('Supports filtering telemetry by regular text search', async ({ page }) => {
await page.goto('./', { waitUntil: 'domcontentloaded' });

const table = await createDomainObjectWithDefaults(page, { type: 'Telemetry Table' });
await createDomainObjectWithDefaults(page, {
type: 'Event Message Generator',
parent: table.uuid
});

// focus the Telemetry Table
await page.goto(table.url);

await page.getByRole('searchbox', { name: 'message filter input' }).click();
await page.getByRole('searchbox', { name: 'message filter input' }).fill('Roger');

let cells = await page.getByRole('cell', { name: /Roger/ }).all();
// ensure we've got more than one cell
expect(cells.length).toBeGreaterThan(1);
// ensure the text content of each cell contains the search term
for (const cell of cells) {
const text = await cell.textContent();
expect(text).toContain('Roger');
}

await page.getByRole('searchbox', { name: 'message filter input' }).click();
await page.getByRole('searchbox', { name: 'message filter input' }).fill('Dodger');

cells = await page.getByRole('cell', { name: /Dodger/ }).all();
// ensure we've got more than one cell
expect(cells.length).toBe(0);
// ensure the text content of each cell contains the search term
for (const cell of cells) {
const text = await cell.textContent();
expect(text).not.toContain('Dodger');
}

// Click pause button
await page.click('button[title="Pause"]');
});

test('Supports filtering using Regex', async ({ page }) => {
await page.goto('./', { waitUntil: 'domcontentloaded' });

const table = await createDomainObjectWithDefaults(page, { type: 'Telemetry Table' });
await createDomainObjectWithDefaults(page, {
type: 'Event Message Generator',
parent: table.uuid
});

// focus the Telemetry Table
page.goto(table.url);
await page.getByRole('searchbox', { name: 'message filter input' }).hover();
await page.getByLabel('Message filter header').getByRole('button', { name: '/R/' }).click();
await page.getByRole('searchbox', { name: 'message filter input' }).click();
await page.getByRole('searchbox', { name: 'message filter input' }).fill('/[Rr]oger/');

let cells = await page.getByRole('cell', { name: /Roger/ }).all();
// ensure we've got more than one cell
expect(cells.length).toBeGreaterThan(1);
// ensure the text content of each cell contains the search term
for (const cell of cells) {
const text = await cell.textContent();
expect(text).toContain('Roger');
}

await page.getByRole('searchbox', { name: 'message filter input' }).click();
await page.getByRole('searchbox', { name: 'message filter input' }).fill('/[Dd]oger/');

cells = await page.getByRole('cell', { name: /Dodger/ }).all();
// ensure we've got more than one cell
expect(cells.length).toBe(0);
// ensure the text content of each cell contains the search term
for (const cell of cells) {
const text = await cell.textContent();
expect(text).not.toContain('Dodger');
}

// Click pause button
await page.click('button[title="Pause"]');
});
});
100 changes: 100 additions & 0 deletions e2e/tests/performance/tabs.e2e.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*****************************************************************************
* 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.
*****************************************************************************/

const { createDomainObjectWithDefaults, waitForPlotsToRender } = require('../../appActions');
const { test, expect } = require('../../pluginFixtures');

test.describe('Tabs View', () => {
test('Renders tabbed elements nicely', async ({ page }) => {
// Code to hook into the requestAnimationFrame function and log each call
let animationCalls = [];
await page.exposeFunction('logCall', (callCount) => {
animationCalls.push(callCount);
});
await page.addInitScript(() => {
const oldRequestAnimationFrame = window.requestAnimationFrame;
let callCount = 0;
window.requestAnimationFrame = function (callback) {
// eslint-disable-next-line no-undef
logCall(callCount++);
return oldRequestAnimationFrame(callback);
};
});
await page.goto('./', { waitUntil: 'domcontentloaded' });

const tabsView = await createDomainObjectWithDefaults(page, {
type: 'Tabs View'
});
const table = await createDomainObjectWithDefaults(page, {
type: 'Telemetry Table',
parent: tabsView.uuid
});
await createDomainObjectWithDefaults(page, {
type: 'Event Message Generator',
parent: table.uuid
});
const notebook = await createDomainObjectWithDefaults(page, {
type: 'Notebook',
parent: tabsView.uuid
});
const sineWaveGenerator = await createDomainObjectWithDefaults(page, {
type: 'Sine Wave Generator',
parent: tabsView.uuid
});

page.goto(tabsView.url);

// select first tab
await page.getByLabel(`${table.name} tab`).click();
// ensure table header visible
await expect(page.getByRole('searchbox', { name: 'message filter input' })).toBeVisible();

// select second tab
await page.getByLabel(`${notebook.name} tab`).click();

// expect notebook visible
await expect(page.locator('.c-notebook__drag-area')).toBeVisible();

// select third tab
await page.getByLabel(`${sineWaveGenerator.name} tab`).click();

// ensure sine wave generator visible
expect(await page.locator('.c-plot').isVisible()).toBe(true);

// now select notebook and clear animation calls
await page.getByLabel(`${notebook.name} tab`).click();
animationCalls = [];
// expect notebook visible
await expect(page.locator('.c-notebook__drag-area')).toBeVisible();
const notebookAnimationCalls = animationCalls.length;

// select sine wave generator and clear animation calls
animationCalls = [];
await page.getByLabel(`${sineWaveGenerator.name} tab`).click();

// ensure sine wave generator visible
await waitForPlotsToRender(page);
// we should be calling animation frames
const sineWaveAnimationCalls = animationCalls.length;
expect(sineWaveAnimationCalls).toBeGreaterThanOrEqual(notebookAnimationCalls);
});
});

0 comments on commit 0e8fa4c

Please sign in to comment.