 a3fb84ad43
			
		
	
	a3fb84ad43
	
	
	
		
			
			* fix: remove mystery webpack code * fix: remove type:module and specify exports - we aren't a module... yet * fix: rename webpack*.js to webpack*.mjs so we can use import/export. fix imports * fix: exports format * fix: woops, need to add `start` script back * chore: split e2e into its own module * fix: use normal Painterro import * fix: update e2e pathing * fix: copy over helper functions * chore: specify `cwd` for playwright configs so that openmct npm commands work as intended in any environment * chore: add pretest script to e2e package.json * chore: don't package e2e * refactor: tidy up webpack common config * chore: compile types to a single file * chore: fix visual test npm scripts * chore: fix import pathing * chore: define package exports, move test specific dependencies to the subpackage * chore: export test framework from openmct-e2e * chore: export baseFixtures also * chore: let `openmct` and `openmct-e2e` share `node_modules/` * chore: use `--workspace`, remove pretest script * Revert "fix: remove mystery webpack code" This reverts commit eb14d52569ffa27ab1a090b883694f4707b59cd0. * chore: update package-lock * chore: add `.npmignore` * fix: *js -> mjs
		
			
				
	
	
		
			167 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*****************************************************************************
 | |
|  * 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 performance tests to ensure that testability of performance
 | |
| is not broken upstream on Open MCT. Any assumptions made downstream will be tested here.
 | |
| 
 | |
| TODO:
 | |
|  - Update resolution of performance config
 | |
|  - Add Performance Observer on init to push all performance marks
 | |
|  - Move client CDP connection to before or to a fixture
 | |
| 
 | |
| */
 | |
| 
 | |
| import { expect, test } from '@playwright/test';
 | |
| 
 | |
| const notebookFilePath = 'test-data/PerformanceNotebook.json';
 | |
| 
 | |
| test.describe('Performance tests', () => {
 | |
|   test.beforeEach(async ({ page, browser }, testInfo) => {
 | |
|     // Go to baseURL
 | |
|     await page.goto('./', { waitUntil: 'networkidle' });
 | |
| 
 | |
|     // Click a:has-text("My Items")
 | |
|     await page.locator('a:has-text("My Items")').click({
 | |
|       button: 'right'
 | |
|     });
 | |
| 
 | |
|     // Click text=Import from JSON
 | |
|     await page.locator('text=Import from JSON').click();
 | |
| 
 | |
|     // Upload Performance Display Layout.json
 | |
|     await page.setInputFiles('#fileElem', notebookFilePath);
 | |
| 
 | |
|     // TODO Fix this
 | |
|     await page.locator('text=OK >> nth=1').click();
 | |
| 
 | |
|     await expect(page.locator('a:has-text("Performance Notebook")')).toBeVisible();
 | |
| 
 | |
|     //Create a Chrome Performance Timeline trace to store as a test artifact
 | |
|     console.log('\n==== Devtools: startTracing ====\n');
 | |
|     await browser.startTracing(page, {
 | |
|       path: `${testInfo.outputPath()}-trace.json`,
 | |
|       screenshots: true
 | |
|     });
 | |
|   });
 | |
|   test.afterEach(async ({ page, browser }) => {
 | |
|     console.log('\n==== Devtools: stopTracing ====\n');
 | |
|     await browser.stopTracing();
 | |
| 
 | |
|     /* Measurement Section
 | |
|         / The following section includes a block of performance measurements.
 | |
|         */
 | |
|     const startTime = await page.evaluate(() => window.performance.timing.navigationStart);
 | |
|     console.log('window.performance.timing.navigationStart', startTime);
 | |
| 
 | |
|     //Get All Performance Marks
 | |
|     const getAllMarksJson = await page.evaluate(() =>
 | |
|       JSON.stringify(window.performance.getEntriesByType('mark'))
 | |
|     );
 | |
|     const getAllMarks = JSON.parse(getAllMarksJson);
 | |
|     console.log('window.performance.getEntriesByType("mark")', getAllMarks);
 | |
| 
 | |
|     //Get All Performance Measures
 | |
|     const getAllMeasuresJson = await page.evaluate(() =>
 | |
|       JSON.stringify(window.performance.getEntriesByType('measure'))
 | |
|     );
 | |
|     const getAllMeasures = JSON.parse(getAllMeasuresJson);
 | |
|     console.log('window.performance.getEntriesByType("measure")', getAllMeasures);
 | |
|   });
 | |
|   /* The following test will navigate to a previously created Performance Display Layout and measure the
 | |
|     /  following metrics:
 | |
|     /  - ElementResourceTiming
 | |
|     /  - Interaction Timing
 | |
|     */
 | |
|   test('Notebook Search, Add Entry, Update Entry are performant', async ({ page, browser }) => {
 | |
|     const client = await page.context().newCDPSession(page);
 | |
|     // Tell the DevTools session to record performance metrics
 | |
|     // https://chromedevtools.github.io/devtools-protocol/tot/Performance/#method-getMetrics
 | |
|     await client.send('Performance.enable');
 | |
|     // Go to baseURL
 | |
|     await page.goto('./');
 | |
| 
 | |
|     // To to Search Available after Launch
 | |
|     await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
 | |
|     await page.evaluate(() => window.performance.mark('search-available'));
 | |
|     // Fill Search input
 | |
|     await page
 | |
|       .locator('[aria-label="OpenMCT Search"] input[type="search"]')
 | |
|       .fill('Performance Notebook');
 | |
|     await page.evaluate(() => window.performance.mark('search-entered'));
 | |
|     //Search Result Appears and is clicked
 | |
|     await Promise.all([
 | |
|       page.waitForNavigation(),
 | |
|       page.locator('a:has-text("Performance Notebook")').first().click(),
 | |
|       page.evaluate(() => window.performance.mark('click-search-result'))
 | |
|     ]);
 | |
| 
 | |
|     await page.waitForSelector('.c-tree__item c-tree-and-search__loading loading', {
 | |
|       state: 'hidden'
 | |
|     });
 | |
|     await page.evaluate(() => window.performance.mark('search-spinner-gone'));
 | |
| 
 | |
|     await page.waitForSelector('.l-browse-bar__object-name', { state: 'visible' });
 | |
|     await page.evaluate(() => window.performance.mark('object-title-appears'));
 | |
| 
 | |
|     await page.waitForSelector('.c-notebook__entry >> nth=0', { state: 'visible' });
 | |
|     await page.evaluate(() => window.performance.mark('notebook-entry-appears'));
 | |
| 
 | |
|     // Click Add new Notebook Entry
 | |
|     await page.locator('.c-notebook__drag-area').click();
 | |
|     await page.evaluate(() => window.performance.mark('new-notebook-entry-created'));
 | |
| 
 | |
|     // Enter Notebook Entry text
 | |
|     await page.getByLabel('Notebook Entry Input').last().fill('New Entry');
 | |
|     await page.locator('.c-ne__save-button').click();
 | |
|     await page.evaluate(() => window.performance.mark('new-notebook-entry-filled'));
 | |
| 
 | |
|     //Individual Notebook Entry Search
 | |
|     await page.evaluate(() => window.performance.mark('notebook-search-start'));
 | |
|     await page.locator('.c-notebook__search >> input').fill('Existing Entry');
 | |
|     await page.evaluate(() => window.performance.mark('notebook-search-filled'));
 | |
|     await page.waitForSelector('text=Search Results (3)', { state: 'visible' });
 | |
|     await page.evaluate(() => window.performance.mark('notebook-search-processed'));
 | |
|     await page.waitForSelector('.c-notebook__entry >> nth=2', { state: 'visible' });
 | |
|     await page.evaluate(() => window.performance.mark('notebook-search-processed'));
 | |
| 
 | |
|     //Clear Search
 | |
|     await page.locator('.c-search.c-notebook__search .c-search__input').hover();
 | |
|     await page.locator('.c-search.c-notebook__search .c-search__clear-input').click();
 | |
|     await page.evaluate(() => window.performance.mark('notebook-search-processed'));
 | |
| 
 | |
|     // Hover on Last
 | |
|     await page.evaluate(() => window.performance.mark('new-notebook-entry-delete'));
 | |
|     await page.locator('div.c-ne__time-and-content').last().hover();
 | |
|     await page.locator('button[title="Delete this entry"]').last().click();
 | |
|     await page.locator('button:has-text("Ok")').click();
 | |
|     await page.waitForSelector('.c-notebook__entry >> nth=3', { state: 'detached' });
 | |
|     await page.evaluate(() => window.performance.mark('new-notebook-entry-deleted'));
 | |
| 
 | |
|     //await client.send('HeapProfiler.enable');
 | |
|     await client.send('HeapProfiler.collectGarbage');
 | |
| 
 | |
|     let performanceMetrics = await client.send('Performance.getMetrics');
 | |
|     console.log(performanceMetrics.metrics);
 | |
|   });
 | |
| });
 |