first pass of lint fixes

This commit is contained in:
John Hill 2024-02-26 08:59:20 -08:00
parent 0590b50d59
commit 2897ca65b3
21 changed files with 112 additions and 100 deletions

View File

@ -6,9 +6,15 @@ module.exports = {
}, },
overrides: [ overrides: [
{ {
files: ['tests/visual/*.spec.js'], files: ['**/*.visual.spec.js'],
rules: { rules: {
'playwright/no-wait-for-timeout': 'off' 'playwright/expect-expect': 'off'
}
},
{
files: ['**/*.perf.spec.js'],
rules: {
'playwright/expect-expect': 'off'
} }
} }
] ]

View File

@ -382,7 +382,7 @@ By adhering to this principle, we can create tests that are both robust and refl
1. Avoid creating locator aliases. This likely means that you're compensating for a bad locator. Improve the application instead. 1. Avoid creating locator aliases. This likely means that you're compensating for a bad locator. Improve the application instead.
1. Leverage `await page.goto('./', { waitUntil: 'domcontentloaded' });` instead of `{ waitUntil: 'networkidle' }`. Tests run against deployments with websockets often have issues with the networkidle detection. 1. Leverage `await page.goto('./', { waitUntil: 'domcontentloaded' });` instead of `{ waitUntil: 'networkidle' }`. Tests run against deployments with websockets often have issues with the networkidle detection.
#### How to make tests faster and more resilient #### How to make tests faster and more resilient to application changes
1. Avoid app interaction when possible. The best way of doing this is to navigate directly by URL: 1. Avoid app interaction when possible. The best way of doing this is to navigate directly by URL:
```js ```js
@ -397,6 +397,16 @@ By adhering to this principle, we can create tests that are both robust and refl
- Initial navigation should _almost_ always use the `{ waitUntil: 'domcontentloaded' }` option. - Initial navigation should _almost_ always use the `{ waitUntil: 'domcontentloaded' }` option.
1. Avoid repeated setup to test a single assertion. Write longer tests with multiple soft assertions. 1. Avoid repeated setup to test a single assertion. Write longer tests with multiple soft assertions.
This ensures that your changes will be picked up with large refactors. This ensures that your changes will be picked up with large refactors.
1. Use [user-facing locators](https://playwright.dev/docs/best-practices#use-locators) (Now a eslint rule!)
```js
page.getByRole('button', { name: 'Create' } )
```
Instead of
```js
page.locator('.c-create-button')
```
Note: `page.locator()` can be used in performance tests as xk6-browser does not yet support the new `page.getBy` pattern and css lookups can be [1.5x faster](https://serpapi.com/blog/css-selectors-faster-than-getbyrole-playwright/)
##### Utilizing LocalStorage ##### Utilizing LocalStorage
1. In order to save test runtime in the case of tests that require a decent amount of initial setup (such as in the case of testing complex displays), you may use [Playwright's `storageState` feature](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state) to generate and load localStorage states. 1. In order to save test runtime in the case of tests that require a decent amount of initial setup (such as in the case of testing complex displays), you may use [Playwright's `storageState` feature](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state) to generate and load localStorage states.

View File

@ -58,7 +58,7 @@ async function navigateToFaultManagementWithoutExample(page) {
* @param {import('@playwright/test').Page} page * @param {import('@playwright/test').Page} page
*/ */
async function navigateToFaultItemInTree(page) { async function navigateToFaultItemInTree(page) {
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
const faultManagementTreeItem = page const faultManagementTreeItem = page
.getByRole('tree', { .getByRole('tree', {

View File

@ -41,7 +41,7 @@ test.describe('CouchDB Status Indicator with mocked responses @couchdb', () => {
//Go to baseURL //Go to baseURL
await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', { await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', {
waitUntil: 'networkidle' waitUntil: 'domcontentloaded'
}); });
await expect(page.locator('div:has-text("CouchDB is connected")').nth(3)).toBeVisible(); await expect(page.locator('div:has-text("CouchDB is connected")').nth(3)).toBeVisible();
}); });
@ -56,7 +56,7 @@ test.describe('CouchDB Status Indicator with mocked responses @couchdb', () => {
//Go to baseURL //Go to baseURL
await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', { await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', {
waitUntil: 'networkidle' waitUntil: 'domcontentloaded'
}); });
await expect(page.locator('div:has-text("CouchDB is offline")').nth(3)).toBeVisible(); await expect(page.locator('div:has-text("CouchDB is offline")').nth(3)).toBeVisible();
}); });
@ -71,7 +71,7 @@ test.describe('CouchDB Status Indicator with mocked responses @couchdb', () => {
//Go to baseURL //Go to baseURL
await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', { await page.goto('./#/browse/mine?hideTree=true&hideInspector=true', {
waitUntil: 'networkidle' waitUntil: 'domcontentloaded'
}); });
await expect(page.locator('div:has-text("CouchDB connectivity unknown")').nth(3)).toBeVisible(); await expect(page.locator('div:has-text("CouchDB connectivity unknown")').nth(3)).toBeVisible();
}); });

View File

@ -188,8 +188,8 @@ test.describe('Persistence operations @couchdb', () => {
// Both pages: Go to baseURL // Both pages: Go to baseURL
await Promise.all([ await Promise.all([
page.goto('./', { waitUntil: 'networkidle' }), page.goto('./', { waitUntil: 'domcontentloaded' }),
page2.goto('./', { waitUntil: 'networkidle' }) page2.goto('./', { waitUntil: 'domcontentloaded' })
]); ]);
//Slow down the test a bit //Slow down the test a bit

View File

@ -76,7 +76,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage @2p', () =>
description: 'https://github.com/nasa/openmct/issues/7421' description: 'https://github.com/nasa/openmct/issues/7421'
}); });
//Navigate to baseURL with injected localStorage //Navigate to baseURL with injected localStorage
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' }); await page.goto(conditionSetUrl, { waitUntil: 'domcontentloaded' });
//Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto() //Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto()
await expect await expect
@ -87,7 +87,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage @2p', () =>
expect.soft(page.locator('_vue=item.name=Unnamed Condition Set')).toBeTruthy(); expect.soft(page.locator('_vue=item.name=Unnamed Condition Set')).toBeTruthy();
//Reload Page //Reload Page
await Promise.all([page.reload(), page.waitForLoadState('networkidle')]); await Promise.all([page.reload(), page.waitForLoadState('domcontentloaded')]);
//Re-verify after reload //Re-verify after reload
await expect await expect
@ -100,7 +100,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage @2p', () =>
test('condition set object can be modified on @localStorage', async ({ page, openmctConfig }) => { test('condition set object can be modified on @localStorage', async ({ page, openmctConfig }) => {
const { myItemsFolderName } = openmctConfig; const { myItemsFolderName } = openmctConfig;
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' }); await page.goto(conditionSetUrl, { waitUntil: 'domcontentloaded' });
//Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto() //Assertions on loaded Condition Set in main view. This is a stateful transition step after page.goto()
await expect await expect
@ -151,7 +151,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage @2p', () =>
expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy(); expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy();
//Reload Page //Reload Page
await Promise.all([page.reload(), page.waitForLoadState('networkidle')]); await Promise.all([page.reload(), page.waitForLoadState('domcontentloaded')]);
//Verify Main section reflects updated Name Property //Verify Main section reflects updated Name Property
await expect await expect
@ -213,7 +213,7 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage @2p', () =>
//Feature? //Feature?
//Domain Object is still available by direct URL after delete //Domain Object is still available by direct URL after delete
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' }); await page.goto(conditionSetUrl, { waitUntil: 'domcontentloaded' });
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set'); await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
}); });
}); });

View File

@ -410,7 +410,7 @@ test.describe('Display Layout', () => {
await page.reload(); await page.reload();
// wait for annotations requests to be batched and requested // wait for annotations requests to be batched and requested
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
// Network requests for the composite telemetry with multiple items should be: // Network requests for the composite telemetry with multiple items should be:
// 1. a single batched request for annotations // 1. a single batched request for annotations
expect(networkRequests.length).toBe(1); expect(networkRequests.length).toBe(1);
@ -422,7 +422,7 @@ test.describe('Display Layout', () => {
await page.reload(); await page.reload();
// wait for annotations to not load (if we have any, we've got a problem) // wait for annotations to not load (if we have any, we've got a problem)
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
// In real time mode, we don't fetch annotations at all // In real time mode, we don't fetch annotations at all
expect(networkRequests.length).toBe(0); expect(networkRequests.length).toBe(0);

View File

@ -531,7 +531,7 @@ test.describe('Example Imagery in Flexible layout', () => {
// Click text=OK // Click text=OK
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }), page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.click('button:has-text("OK")'), page.click('button:has-text("OK")'),
//Wait for Save Banner to appear //Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
@ -575,7 +575,7 @@ test.describe('Example Imagery in Tabs View', () => {
// Click text=OK // Click text=OK
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }), page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.click('button:has-text("OK")'), page.click('button:has-text("OK")'),
//Wait for Save Banner to appear //Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
@ -1023,7 +1023,7 @@ async function createImageryView(page) {
// Click text=OK // Click text=OK
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }), page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.click('button:has-text("OK")'), page.click('button:has-text("OK")'),
//Wait for Save Banner to appear //Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')

View File

@ -152,7 +152,7 @@ test.describe('ExportAsJSON Disabled Actions', () => {
test.describe('ExportAsJSON ProgressBar @couchdb', () => { test.describe('ExportAsJSON ProgressBar @couchdb', () => {
let folder; let folder;
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
// Perform actions to create the domain object // Perform actions to create the domain object
folder = await createDomainObjectWithDefaults(page, { folder = await createDomainObjectWithDefaults(page, {
type: 'Folder' type: 'Folder'

View File

@ -37,7 +37,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
// Create Notebook // Create Notebook
testNotebook = await createDomainObjectWithDefaults(page, { type: 'Notebook' }); testNotebook = await createDomainObjectWithDefaults(page, { type: 'Notebook' });
await page.goto(testNotebook.url, { waitUntil: 'networkidle' }); await page.goto(testNotebook.url, { waitUntil: 'domcontentloaded' });
}); });
test('Inspect Notebook Entry Network Requests', async ({ page }) => { test('Inspect Notebook Entry Network Requests', async ({ page }) => {
@ -58,7 +58,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
page.click('[aria-label="Add Page"]') page.click('[aria-label="Add Page"]')
]); ]);
// Ensures that there are no other network requests // Ensures that there are no other network requests
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
// Assert that only two requests are made // Assert that only two requests are made
// Network Requests are: // Network Requests are:
@ -77,7 +77,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
// 2) The shared worker event from 👆 POST request // 2) The shared worker event from 👆 POST request
notebookElementsRequests = []; notebookElementsRequests = [];
await nbUtils.enterTextEntry(page, 'First Entry'); await nbUtils.enterTextEntry(page, 'First Entry');
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
expect(notebookElementsRequests.length).toBeLessThanOrEqual(2); expect(notebookElementsRequests.length).toBeLessThanOrEqual(2);
// Add some tags // Add some tags
@ -141,7 +141,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
// 4) The shared worker event from 👆 POST request // 4) The shared worker event from 👆 POST request
notebookElementsRequests = []; notebookElementsRequests = [];
await nbUtils.enterTextEntry(page, 'Fourth Entry'); await nbUtils.enterTextEntry(page, 'Fourth Entry');
page.waitForLoadState('networkidle'); page.waitForLoadState('domcontentloaded');
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4); expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
@ -153,7 +153,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
// 4) The shared worker event from 👆 POST request // 4) The shared worker event from 👆 POST request
notebookElementsRequests = []; notebookElementsRequests = [];
await nbUtils.enterTextEntry(page, 'Fifth Entry'); await nbUtils.enterTextEntry(page, 'Fifth Entry');
page.waitForLoadState('networkidle'); page.waitForLoadState('domcontentloaded');
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4); expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
@ -164,7 +164,7 @@ test.describe('Notebook Tests with CouchDB @couchdb', () => {
// 4) The shared worker event from 👆 POST request // 4) The shared worker event from 👆 POST request
notebookElementsRequests = []; notebookElementsRequests = [];
await nbUtils.enterTextEntry(page, 'Sixth Entry'); await nbUtils.enterTextEntry(page, 'Sixth Entry');
page.waitForLoadState('networkidle'); page.waitForLoadState('domcontentloaded');
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4); expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
}); });
@ -227,7 +227,7 @@ async function addTagAndAwaitNetwork(page, tagName) {
page.locator(`[aria-label="Autocomplete Options"] >> text=${tagName}`).click(), page.locator(`[aria-label="Autocomplete Options"] >> text=${tagName}`).click(),
expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeVisible() expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeVisible()
]); ]);
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
} }
/** /**
@ -246,5 +246,5 @@ async function removeTagAndAwaitNetwork(page, tagName) {
) )
]); ]);
await expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeHidden(); await expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeHidden();
await page.waitForLoadState('networkidle'); await page.waitForLoadState('domcontentloaded');
} }

View File

@ -59,7 +59,7 @@ test.describe('Handle missing object for plots', () => {
await page.evaluate(`window.localStorage.setItem('mct', '${JSON.stringify(parsedData)}')`); await page.evaluate(`window.localStorage.setItem('mct', '${JSON.stringify(parsedData)}')`);
//Reloads page and clicks on stacked plot //Reloads page and clicks on stacked plot
await Promise.all([page.reload(), page.waitForLoadState('networkidle')]); await Promise.all([page.reload(), page.waitForLoadState('domcontentloaded')]);
//Verify Main section is there on load //Verify Main section is there on load
await expect await expect
@ -92,7 +92,7 @@ async function makeStackedPlot(page, myItemsFolderName) {
await page.locator('li[role="menuitem"]:has-text("Stacked Plot")').click(); await page.locator('li[role="menuitem"]:has-text("Stacked Plot")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }), page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.locator('button:has-text("OK")').click(), page.locator('button:has-text("OK")').click(),
//Wait for Save Banner to appear //Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
@ -153,7 +153,7 @@ async function createSineWaveGenerator(page) {
await page.locator('li[role="menuitem"]:has-text("Sine Wave Generator")').click(); await page.locator('li[role="menuitem"]:has-text("Sine Wave Generator")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }), page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.locator('button:has-text("OK")').click(), page.locator('button:has-text("OK")').click(),
//Wait for Save Banner to appear //Wait for Save Banner to appear
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')

View File

@ -30,7 +30,7 @@ import { expect, test } from '../../baseFixtures.js';
test.describe('Renaming objects', () => { test.describe('Renaming objects', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
// Go to baseURL // Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
}); });
test('When renaming objects, the browse bar and various components all update', async ({ test('When renaming objects, the browse bar and various components all update', async ({

View File

@ -89,7 +89,7 @@ test.describe('Verify tooltips', () => {
await expandEntireTree(page); await expandEntireTree(page);
}); });
test('display correct paths for LAD tables', async ({ page, openmctConfig }) => { test('display correct paths for LAD tables', async ({ page }) => {
// Create LAD table // Create LAD table
await createDomainObjectWithDefaults(page, { await createDomainObjectWithDefaults(page, {
type: 'LAD Table', type: 'LAD Table',
@ -110,7 +110,7 @@ test.describe('Verify tooltips', () => {
async function getToolTip(object) { async function getToolTip(object) {
await page.locator('.c-create-button').hover(); await page.locator('.c-create-button').hover();
await page.getByRole('cell', { name: object.name }).hover(); await page.getByRole('cell', { name: object.name }).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
return tooltipText.replace('\n', '').trim(); return tooltipText.replace('\n', '').trim();
} }
@ -142,7 +142,7 @@ test.describe('Verify tooltips', () => {
await page await page
.locator('.plot-series-name', { has: page.locator(`text="${object.name} Hz"`) }) .locator('.plot-series-name', { has: page.locator(`text="${object.name} Hz"`) })
.hover(); .hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
return tooltipText.replace('\n', '').trim(); return tooltipText.replace('\n', '').trim();
} }
@ -151,7 +151,7 @@ test.describe('Verify tooltips', () => {
await page await page
.locator('.plot-series-name', { has: page.locator(`text="${object.name}"`) }) .locator('.plot-series-name', { has: page.locator(`text="${object.name}"`) })
.hover(); .hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
return tooltipText.replace('\n', '').trim(); return tooltipText.replace('\n', '').trim();
} }
@ -181,7 +181,7 @@ test.describe('Verify tooltips', () => {
has: page.locator(`text="${object.name}"`) has: page.locator(`text="${object.name}"`)
}) })
.hover(); .hover();
const tooltipText = await page.locator('.c-tooltip').textContent(); const tooltipText = await page.locator('.c-tooltip').innerText();
await page.keyboard.up('Control'); await page.keyboard.up('Control');
return tooltipText.replace('\n', '').trim(); return tooltipText.replace('\n', '').trim();
} }
@ -236,7 +236,7 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByText('Test Overlay Plot').nth(2).hover(); await page.getByText('Test Overlay Plot').nth(2).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe('My Items / Test Overlay Plot'); expect(tooltipText).toBe('My Items / Test Overlay Plot');
@ -244,17 +244,17 @@ test.describe('Verify tooltips', () => {
await page.locator('.c-plot-legend__view-control >> nth=0').click(); await page.locator('.c-plot-legend__view-control >> nth=0').click();
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover(); await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
await page.getByText('Test Stacked Plot').nth(2).hover(); await page.getByText('Test Stacked Plot').nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe('My Items / Test Stacked Plot'); expect(tooltipText).toBe('My Items / Test Stacked Plot');
await page.getByText('SWG 3').nth(2).hover(); await page.getByText('SWG 3').nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(sineWaveObject3.path).toBe(tooltipText); expect(sineWaveObject3.path).toBe(tooltipText);
}); });
@ -273,12 +273,12 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByText('SWG 1').nth(2).hover(); await page.getByText('SWG 1').nth(2).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
await page.getByText('SWG 3').nth(2).hover(); await page.getByText('SWG 3').nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -297,12 +297,12 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByText('SWG 1').nth(2).hover(); await page.getByText('SWG 1').nth(2).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
await page.getByText('SWG 3').nth(2).hover(); await page.getByText('SWG 3').nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -310,12 +310,12 @@ test.describe('Verify tooltips', () => {
test('display correct paths when hovering tree items', async ({ page }) => { test('display correct paths when hovering tree items', async ({ page }) => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByText('SWG 1').nth(0).hover(); await page.getByText('SWG 1').nth(0).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
await page.getByText('SWG 3').nth(0).hover(); await page.getByText('SWG 3').nth(0).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -326,7 +326,7 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.locator('.c-gsearch-result__title').hover(); await page.locator('.c-gsearch-result__title').hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -340,7 +340,7 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
// eslint-disable-next-line playwright/no-force-option // eslint-disable-next-line playwright/no-force-option
await page.locator('.c-gauge.c-dial').hover({ position: { x: 0, y: 0 }, force: true }); await page.locator('.c-gauge.c-dial').hover({ position: { x: 0, y: 0 }, force: true });
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -354,7 +354,7 @@ test.describe('Verify tooltips', () => {
await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-notebook__drag-area'); await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-notebook__drag-area');
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.locator('.c-ne__embed').hover(); await page.locator('.c-ne__embed').hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });
@ -386,12 +386,12 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.locator('.noselect > [title="SWG 3"]').first().hover(); await page.locator('.noselect > [title="SWG 3"]').first().hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
await page.locator('.noselect > [title="SWG 1"]').first().hover(); await page.locator('.noselect > [title="SWG 1"]').first().hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
}); });
@ -410,17 +410,17 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByLabel('Recent Objects').getByText(sineWaveObject3.name).hover(); await page.getByLabel('Recent Objects').getByText(sineWaveObject3.name).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
await page.getByLabel('Recent Objects').getByText(sineWaveObject2.name).hover(); await page.getByLabel('Recent Objects').getByText(sineWaveObject2.name).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject2.path); expect(tooltipText).toBe(sineWaveObject2.path);
await page.getByLabel('Recent Objects').getByText(sineWaveObject1.name).hover(); await page.getByLabel('Recent Objects').getByText(sineWaveObject1.name).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
}); });
@ -450,17 +450,17 @@ test.describe('Verify tooltips', () => {
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.getByText(sineWaveObject1.name).nth(2).hover(); await page.getByText(sineWaveObject1.name).nth(2).hover();
let tooltipText = await page.locator('.c-tooltip').textContent(); let tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject1.path); expect(tooltipText).toBe(sineWaveObject1.path);
await page.getByText(sineWaveObject2.name).nth(2).hover(); await page.getByText(sineWaveObject2.name).nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject2.path); expect(tooltipText).toBe(sineWaveObject2.path);
await page.getByText(sineWaveObject3.name).nth(2).hover(); await page.getByText(sineWaveObject3.name).nth(2).hover();
tooltipText = await page.locator('.c-tooltip').textContent(); tooltipText = await page.locator('.c-tooltip').innerText();
tooltipText = tooltipText.replace('\n', '').trim(); tooltipText = tooltipText.replace('\n', '').trim();
expect(tooltipText).toBe(sineWaveObject3.path); expect(tooltipText).toBe(sineWaveObject3.path);
}); });

View File

@ -48,7 +48,9 @@ test.describe('Main Tree', () => {
}); });
await expandTreePaneItemByName(page, folder.name); await expandTreePaneItemByName(page, folder.name);
await assertTreeItemIsVisible(page, clock.name); await expect(
page.getByRole('tree', { name: 'Main Tree' }).getByRole('treeitem', { name: clock.name })
).toBeVisible();
}); });
test('Creating a child object on one tab and expanding its parent on the other shows the correct composition @2p', async ({ test('Creating a child object on one tab and expanding its parent on the other shows the correct composition @2p', async ({
@ -65,8 +67,8 @@ test.describe('Main Tree', () => {
// Both pages: Go to baseURL // Both pages: Go to baseURL
await Promise.all([ await Promise.all([
page.goto('./', { waitUntil: 'networkidle' }), page.goto('./', { waitUntil: 'domcontentloaded' }),
page2.goto('./', { waitUntil: 'networkidle' }) page2.goto('./', { waitUntil: 'domcontentloaded' })
]); ]);
const page1Folder = await createDomainObjectWithDefaults(page, { const page1Folder = await createDomainObjectWithDefaults(page, {
@ -74,7 +76,11 @@ test.describe('Main Tree', () => {
}); });
await expandTreePaneItemByName(page2, myItemsFolderName); await expandTreePaneItemByName(page2, myItemsFolderName);
await assertTreeItemIsVisible(page2, page1Folder.name); await expect(
page2
.getByRole('tree', { name: 'Main Tree' })
.getByRole('treeitem', { name: page1Folder.name })
).toBeVisible();
}); });
test('Creating a child object on one tab and expanding its parent on the other shows the correct composition @couchdb @2p', async ({ test('Creating a child object on one tab and expanding its parent on the other shows the correct composition @couchdb @2p', async ({
@ -91,8 +97,8 @@ test.describe('Main Tree', () => {
// Both pages: Go to baseURL // Both pages: Go to baseURL
await Promise.all([ await Promise.all([
page.goto('./', { waitUntil: 'networkidle' }), page.goto('./', { waitUntil: 'domcontentloaded' }),
page2.goto('./', { waitUntil: 'networkidle' }) page2.goto('./', { waitUntil: 'domcontentloaded' })
]); ]);
const page1Folder = await createDomainObjectWithDefaults(page, { const page1Folder = await createDomainObjectWithDefaults(page, {
@ -100,7 +106,11 @@ test.describe('Main Tree', () => {
}); });
await expandTreePaneItemByName(page2, myItemsFolderName); await expandTreePaneItemByName(page2, myItemsFolderName);
await assertTreeItemIsVisible(page2, page1Folder.name); await expect(
page2
.getByRole('tree', { name: 'Main Tree' })
.getByRole('treeitem', { name: page1Folder.name })
).toBeVisible();
}); });
test('Renaming an object reorders the tree @unstable', async ({ page, openmctConfig }) => { test('Renaming an object reorders the tree @unstable', async ({ page, openmctConfig }) => {
@ -221,17 +231,6 @@ async function getAndAssertTreeItems(page, expected) {
expect(allTexts).toEqual(expected); expect(allTexts).toEqual(expected);
} }
async function assertTreeItemIsVisible(page, name) {
const mainTree = page.getByRole('tree', {
name: 'Main Tree'
});
const treeItem = mainTree.getByRole('treeitem', {
name
});
await expect(treeItem).toBeVisible();
}
/** /**
* @param {import('@playwright/test').Page} page * @param {import('@playwright/test').Page} page
* @param {string} name * @param {string} name

View File

@ -39,7 +39,7 @@ const filePath = 'e2e/test-data/PerformanceDisplayLayout.json';
test.describe('Performance tests', () => { test.describe('Performance tests', () => {
test.beforeEach(async ({ page, browser }, testInfo) => { test.beforeEach(async ({ page, browser }, testInfo) => {
// Go to baseURL // Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
// Click a:has-text("My Items") // Click a:has-text("My Items")
await page.locator('a:has-text("My Items")').click({ await page.locator('a:has-text("My Items")').click({
@ -129,12 +129,12 @@ test.describe('Performance tests', () => {
]); ]);
//Time to Example Imagery Frame loads within Display Layout //Time to Example Imagery Frame loads within Display Layout
await page.waitForSelector('.c-imagery__main-image__bg', { state: 'visible' }); await page.locator('.c-imagery__main-image__bg').waitFor({ state: 'visible' });
//Time to Example Imagery object loads //Time to Example Imagery object loads
await page.waitForSelector('.c-imagery__main-image__background-image', { state: 'visible' }); await page.locator('.c-imagery__main-image__background-image').waitFor({ state: 'visible' });
//Get background-image url from background-image css prop //Get background-image url from background-image css prop
const backgroundImage = await page.locator('.c-imagery__main-image__background-image'); const backgroundImage = page.locator('.c-imagery__main-image__background-image');
let backgroundImageUrl = await backgroundImage.evaluate((el) => { let backgroundImageUrl = await backgroundImage.evaluate((el) => {
return window return window
.getComputedStyle(el) .getComputedStyle(el)
@ -156,15 +156,15 @@ test.describe('Performance tests', () => {
await page.evaluate(() => window.performance.mark('viewLarge.start.test')); //This is a mark only to compare evaluate timing await page.evaluate(() => window.performance.mark('viewLarge.start.test')); //This is a mark only to compare evaluate timing
//Time to Imagery Rendered in Large Frame //Time to Imagery Rendered in Large Frame
await page.waitForSelector('.c-imagery__main-image__bg', { state: 'visible' }); await page.locator('.c-imagery__main-image__bg').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('background-image-frame')); await page.evaluate(() => window.performance.mark('background-image-frame'));
//Time to Example Imagery object loads //Time to Example Imagery object loads
await page.waitForSelector('.c-imagery__main-image__background-image', { state: 'visible' }); await page.locator('.c-imagery__main-image__background-image').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('background-image-visible')); await page.evaluate(() => window.performance.mark('background-image-visible'));
// Get Current number of images in thumbstrip // Get Current number of images in thumbstrip
await page.waitForSelector('.c-imagery__thumb'); await page.locator('.c-imagery__thumb').waitFor({ state: 'visible' });
const thumbCount = await page.locator('.c-imagery__thumb').count(); const thumbCount = await page.locator('.c-imagery__thumb').count();
console.log('number of thumbs rendered ' + thumbCount); console.log('number of thumbs rendered ' + thumbCount);
await page.locator('.c-imagery__thumb').last().click(); await page.locator('.c-imagery__thumb').last().click();

View File

@ -38,7 +38,7 @@ const notebookFilePath = 'e2e/test-data/PerformanceNotebook.json';
test.describe('Performance tests', () => { test.describe('Performance tests', () => {
test.beforeEach(async ({ page, browser }, testInfo) => { test.beforeEach(async ({ page, browser }, testInfo) => {
// Go to baseURL // Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'domcontentloaded' });
// Click a:has-text("My Items") // Click a:has-text("My Items")
await page.locator('a:has-text("My Items")').click({ await page.locator('a:has-text("My Items")').click({
@ -110,20 +110,19 @@ test.describe('Performance tests', () => {
await page.evaluate(() => window.performance.mark('search-entered')); await page.evaluate(() => window.performance.mark('search-entered'));
//Search Result Appears and is clicked //Search Result Appears and is clicked
await Promise.all([ await Promise.all([
page.waitForNavigation(),
page.locator('a:has-text("Performance Notebook")').first().click(), page.locator('a:has-text("Performance Notebook")').first().click(),
page.evaluate(() => window.performance.mark('click-search-result')) page.evaluate(() => window.performance.mark('click-search-result'))
]); ]);
await page.waitForSelector('.c-tree__item c-tree-and-search__loading loading', { await page
state: 'hidden' .locator('.c-tree__item c-tree-and-search__loading loading')
}); .waitFor({ state: 'hidden' });
await page.evaluate(() => window.performance.mark('search-spinner-gone')); await page.evaluate(() => window.performance.mark('search-spinner-gone'));
await page.waitForSelector('.l-browse-bar__object-name', { state: 'visible' }); await page.locator('.l-browse-bar__object-name').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('object-title-appears')); await page.evaluate(() => window.performance.mark('object-title-appears'));
await page.waitForSelector('.c-notebook__entry >> nth=0', { state: 'visible' }); await page.locator('.c-notebook__entry >> nth=0').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('notebook-entry-appears')); await page.evaluate(() => window.performance.mark('notebook-entry-appears'));
// Click Add new Notebook Entry // Click Add new Notebook Entry
@ -139,9 +138,9 @@ test.describe('Performance tests', () => {
await page.evaluate(() => window.performance.mark('notebook-search-start')); await page.evaluate(() => window.performance.mark('notebook-search-start'));
await page.locator('.c-notebook__search >> input').fill('Existing Entry'); await page.locator('.c-notebook__search >> input').fill('Existing Entry');
await page.evaluate(() => window.performance.mark('notebook-search-filled')); await page.evaluate(() => window.performance.mark('notebook-search-filled'));
await page.waitForSelector('text=Search Results (3)', { state: 'visible' }); await page.locator('text=Search Results (3)').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('notebook-search-processed')); await page.evaluate(() => window.performance.mark('notebook-search-processed'));
await page.waitForSelector('.c-notebook__entry >> nth=2', { state: 'visible' }); await page.locator('.c-notebook__entry >> nth=2').waitFor({ state: 'visible' });
await page.evaluate(() => window.performance.mark('notebook-search-processed')); await page.evaluate(() => window.performance.mark('notebook-search-processed'));
//Clear Search //Clear Search
@ -154,7 +153,7 @@ test.describe('Performance tests', () => {
await page.locator('div.c-ne__time-and-content').last().hover(); 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[title="Delete this entry"]').last().click();
await page.locator('button:has-text("Ok")').click(); await page.locator('button:has-text("Ok")').click();
await page.waitForSelector('.c-notebook__entry >> nth=3', { state: 'detached' }); await page.locator('.c-notebook__entry >> nth=3').waitFor({ state: 'detached' });
await page.evaluate(() => window.performance.mark('new-notebook-entry-deleted')); await page.evaluate(() => window.performance.mark('new-notebook-entry-deleted'));
//await client.send('HeapProfiler.enable'); //await client.send('HeapProfiler.enable');

View File

@ -228,9 +228,7 @@ test.describe('Navigation memory leak is not detected in', () => {
expect(result).toBe(true); expect(result).toBe(true);
}); });
test('display layout with plots of swgs, alphanumerics, and condition sets, ', async ({ test('display layout with plots of swgs, alphanumerics, and condition sets', async ({ page }) => {
page
}) => {
const result = await navigateToObjectAndDetectMemoryLeak( const result = await navigateToObjectAndDetectMemoryLeak(
page, page,
'display-layout-simple-telemetry' 'display-layout-simple-telemetry'

View File

@ -78,7 +78,7 @@ test.describe('Tabs View', () => {
await page.getByLabel(`${sineWaveGenerator.name} tab`, { exact: true }).click(); await page.getByLabel(`${sineWaveGenerator.name} tab`, { exact: true }).click();
// ensure sine wave generator visible // ensure sine wave generator visible
expect(await page.locator('.c-plot').isVisible()).toBe(true); await expect(page.locator('.c-plot')).toBeVisible();
// now select notebook and clear animation calls // now select notebook and clear animation calls
await page.getByLabel(`${notebook.name} tab`, { exact: true }).click(); await page.getByLabel(`${notebook.name} tab`, { exact: true }).click();

View File

@ -84,7 +84,7 @@ test.describe('Plot Tagging Performance', () => {
await setRealTimeMode(page); await setRealTimeMode(page);
// Search for Science // Search for Science
await page.getByRole('searchbox', { name: 'Search Input' }); await page.getByRole('searchbox', { name: 'Search Input' }).click();
await page.getByRole('searchbox', { name: 'Search Input' }).fill('sc'); await page.getByRole('searchbox', { name: 'Search Input' }).fill('sc');
// click on the search result // click on the search result

View File

@ -75,7 +75,7 @@ test.describe('Visual - Header @a11y', () => {
await percySnapshot(page, `Notebook Snapshot Show button (theme: '${theme}')`, { await percySnapshot(page, `Notebook Snapshot Show button (theme: '${theme}')`, {
scope: header scope: header
}); });
await expect(await page.getByLabel('Show Snapshots')).toBeVisible(); await expect(page.getByLabel('Show Snapshots')).toBeVisible();
}); });
}); });
// Skipping for https://github.com/nasa/openmct/issues/7421 // Skipping for https://github.com/nasa/openmct/issues/7421

View File

@ -57,7 +57,7 @@ test.describe('Visual - Telemetry Views', () => {
await page.getByLabel('Telemetry Table').click(); await page.getByLabel('Telemetry Table').click();
//Get Table View in place //Get Table View in place
expect(await page.getByLabel('Expand Columns')).toBeInViewport(); await expect(page.getByLabel('Expand Columns')).toBeInViewport();
await percySnapshot(page, `Default Telemetry Table View (theme: ${theme})`); await percySnapshot(page, `Default Telemetry Table View (theme: ${theme})`);