Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[e2e] Update to quickstart fixure, add makefile, and add tests Mct7343 and 7198 #414

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions src/providers/limit-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export default class LimitProvider {
const limits = domainObject.configuration.limits;

return {
// eslint-disable-next-line require-await
limits: async () => limits
};
}
Expand Down
49 changes: 49 additions & 0 deletions tests/e2e/framework/quickstartFixtures.e2e.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2024, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/

/*
This test suite is dedicated to testing our use of our custom fixtures to verify
that they are working as expected.
*/

import { expect, filterNonFetchRequests, test} from '../quickstartFixtures.js';

test.describe('quickstartFixtures tests', () => {
// Keeping track of network requests during the tests.
let allNetworkRequests = [];
let fetchRequests = [];

test('filterNonFetchRequests', async ({ page }) => {
// Listening for all network requests and pushing them into allNetworkRequests array.
page.on('request', request => allNetworkRequests.push(request));

// Setting up promises to wait for specific network responses.
// Testing the initial page load and verifying the presence of specific elements.
await page.goto("./", { waitUntil: "networkidle" });
fetchRequests = filterNonFetchRequests(allNetworkRequests);
expect(allNetworkRequests.length).toBeGreaterThan(0);
expect(fetchRequests.length).toBeGreaterThan(0);

// Removing the 'request' event listener to prevent potential memory leaks.
page.removeListener('request', request => allNetworkRequests.push(request));
});
});
2 changes: 1 addition & 1 deletion tests/e2e/playwright-quickstart.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const config = {
command: 'npm run start:coverage',
url: 'http://localhost:9000/#',
timeout: 120 * 1000,
reuseExistingServer: false
reuseExistingServer: true
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

driveby. We're moving away from 'false' for faster debugging

},
workers: 1,
projects: [
Expand Down
54 changes: 54 additions & 0 deletions tests/e2e/quickstartFixtures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2024, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/

/**
* The file contains custom fixtures which extend the base functionality of the Playwright fixtures
* and appActions. These fixtures should be generalized across all plugins.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will become the prototypical fixtures file that we expect openmct-e2e-as-a-dependency users to follow. They will source pluginFixture.js to set their 'My Items' per deployment

*/

// import { createDomainObjectWithDefaults } from './appActions.js';
import { test, request, expect } from './opensource/pluginFixtures.js';

/**
* The name of the "My Items" folder in the domain object tree.
*
* Default: `"My Items"`
*
* @type {string}
*/
export const myItemsFolderName = 'My Items';

export { expect, request, test };

/**
* Filters out non-fetch requests from the given array of network requests.
* This includes preflight CORS, fetching stylesheets, page icons, etc.
* Requires that a page requests instantiated like so
* ```js
* page.on('request', request => allNetworkRequests.push(request));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need better jsdoc

* ```
* @param {Array} requests - Array of network requests to filter.
* @returns {Array} Filtered network requests.
*/
export function filterNonFetchRequests(requests) {
return requests.filter(request => request.resourceType() === 'fetch');
}
171 changes: 171 additions & 0 deletions tests/e2e/yamcs/actions.e2e.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2022, 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.
*****************************************************************************/
/*
* Network Specific Tests for Open MCT and YAMCS connectivity.
* This suite verifies the network requests made by the application to ensure correct interaction with YAMCS.
*/

import { test, expect, filterNonFetchRequests } from '../quickstartFixtures.js';
import { createDomainObjectWithDefaults, setFixedTimeMode } from '../opensource/appActions.js';

test.describe('Reload action', () => {
let displayLayout;
let batchGet;
let batchGet2;
let battery1tempRequest;
let battery1tempRequestCont;
let battery1voltageRequest;
let battery1voltageRequestCont;
let allNetworkRequests = [];
test.beforeEach(async ({ page }) => {
await page.goto('./', { waitUntil: 'domcontentloaded' });

displayLayout = await createDomainObjectWithDefaults(page, {
type: 'Display Layout'
});

await createDomainObjectWithDefaults(page, {
type: 'Telemetry Table',
name: 'Alpha Table'
});

//Expand the quickstart myproject twice
await page.getByLabel('Expand myproject folder').click();
await page.getByLabel('Expand myproject folder').click();

//Add Battery1_Temp to Alpha Table
await page.getByLabel('Edit Object').click();
await page.getByRole('treeitem', { name: 'Battery1_Temp' }).dragTo(page.locator('.c-table__body-w'));
await page.getByRole('button', { name: 'Save' }).click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();

await createDomainObjectWithDefaults(page, {
type: 'Telemetry Table',
name: 'Beta Table'
});

//Add Battery1_Voltage to Beta Table
await page.getByLabel('Edit Object').click();
await page.getByRole('treeitem', { name: 'Battery1_Voltage' }).dragTo(page.locator('.c-table__body-w'));
await page.getByRole('button', { name: 'Save' }).click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();

//Add both Telemetry Tables to the Display Layout
await page.goto(displayLayout.url, { waitUntil: 'domcontentloaded' });
await page.getByLabel('Edit Object', { exact: true }).click();
await page.getByLabel('Collapse myproject folder').first().click();
await page.getByLabel('Expand My Items folder').click();
await page.dragAndDrop(`text='Alpha Table'`, '.l-layout__grid-holder', {
targetPosition: { x: 0, y: 0 }
});
await page.dragAndDrop(`text='Beta Table'`, '.l-layout__grid-holder', {
targetPosition: { x: 0, y: 250 }
});
await page.locator('button[title="Save"]').click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();


await page.goto(displayLayout.url, { waitUntil: 'networkidle' });
//Set to 1 Minute to reduce the time the opportunity for paginated data
// await page.getByRole('menuitem', { name: /Real-Time/ }).click();
await page.getByLabel('Start offset: 00:30:00').click();
await page.getByLabel('Start offset minutes').fill('1');
await page.getByLabel('Submit time offsets').click();
await page.waitForLoadState('networkidle');
});

test.only('can reload display layout and its telemetry table children', async ({ page }) => {
// Listening for all network requests and pushing them into allNetworkRequests array.
page.on('request', request => allNetworkRequests.push(request));

const beforeReloadAlphaTelemetryValue = await page
.getByLabel('Alpha Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');
const beforeReloadBetaTelemetryValue = await page
.getByLabel('Beta Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');

//reload Alpha Table and verify network correctness
await page.waitForLoadState('networkidle');
allNetworkRequests = [];

battery1tempRequest = page.waitForResponse('**/api/archive/myproject/parameters/myproject/Battery1_Temp**')
battery1tempRequestCont = page.waitForResponse('**/api/archive/myproject/parameters/myproject/Battery1_Temp**')
batchGet = page.waitForResponse('**/api/processors/myproject/realtime/parameters:batchGet');

await page.getByTitle('View menu items').first().click();
await page.getByRole('menuitem', { name: /Reload/ }).click();
await Promise.all([battery1tempRequest, battery1tempRequestCont, batchGet]);
await page.waitForLoadState('networkidle');
expect(allNetworkRequests.length).toBe(2);


const afterReloadAlphaTelemetryValue = await page
.getByLabel('Alpha Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');
const afterReloadBetaTelemetryValue = await page
.getByLabel('Beta Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');

expect(beforeReloadAlphaTelemetryValue).not.toEqual(afterReloadAlphaTelemetryValue);
expect(beforeReloadBetaTelemetryValue).toEqual(afterReloadBetaTelemetryValue);

await page.waitForLoadState('networkidle');
allNetworkRequests = [];

battery1tempRequest = page.waitForResponse('**/api/archive/myproject/parameters/myproject/Battery1_Temp**')
battery1voltageRequest = page.waitForResponse('**/api/archive/myproject/parameters/myproject/Battery1_Voltage**')
batchGet = page.waitForResponse('**/api/processors/myproject/realtime/parameters:batchGet');
batchGet2 = page.waitForResponse('**/api/processors/myproject/realtime/parameters:batchGet');

await page.getByTitle('More actions').click();
await page.getByRole('menuitem', { name: /Reload/ }).click();
await Promise.all([battery1tempRequest, battery1voltageRequest, batchGet, batchGet2]);
await page.waitForLoadState('networkidle');

expect(allNetworkRequests.length).toBe(3);

const fullReloadAlphaTelemetryValue = await page
.getByLabel('Alpha Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');
const fullReloadBetaTelemetryValue = await page
.getByLabel('Beta Table table content')
.getByLabel('value table cell')
.first()
.getAttribute('title');

expect(fullReloadAlphaTelemetryValue).not.toEqual(afterReloadAlphaTelemetryValue);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These earlier tests were predicated on the sinewave generator, that created new telemetry on every page load. If we're going to use YAMCS telemetry, we can't rely on the telemetry changing underneath us on reload.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long and short of it: I think we should get rid of these expects

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And instead add some network measuring on reload. I think this will be the best to see if the reload actually performed as expected

Copy link
Collaborator

@scottbell scottbell Sep 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still makes sense 9 months later to me 😀

expect(fullReloadBetaTelemetryValue).not.toEqual(afterReloadBetaTelemetryValue);
});
test.fixme('can reload notebook', async ({ page }) => {});
test.fixme('can reload gauge', async ({ page }) => {});
});
Loading