test(e2e): unique names for created objects by default (#5945)

* feat(e2e): default unique names for new objects

* refactor(e2e): reference generated object names

- Fixes the tests that were locating "Unnamed <object_type>" to use the generated unique names

* feat(e2e): add testInfo into domainObject notes

- adds info about the currently running test and its project to notes

* fix(e2e): fix selector for notes section

* feat: ARIA: menu role for menus and SuperMenus

- Implements the [ARIA: menu role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/roles/menu_role) for Menus and SuperMenus,

* refactor(e2e): use role selectors for menu items

* refactor(e2e): better selectors for "OK" button

* refactor(e2e): better selectors for menu items

* refactor(e2e): improve selector

* refactor(e2e): update test to use appActions

* refactor(e2e): update test to use object name

* refactor(e2e): improve selectors for menu items

* test(e2e): fix search test

* refactor(e2e): update more plain 'text=' selectors

* fix: resolve codeQL error

- remove superfluous argument

* refactor(e2e): move testNotes to `pluginFixtures` and update imports

* refactor(e2e): remove unused fixture from test

* refactor: add dynamic id to form textareas

* refactor(e2e): improve notes textarea selector

* refactor(e2e): remove unused fixture
This commit is contained in:
Jesse Mazzella
2022-11-07 15:50:33 -08:00
committed by GitHub
parent 6abdbfdff0
commit d545124942
30 changed files with 238 additions and 238 deletions

View File

@ -46,6 +46,7 @@
*/ */
const Buffer = require('buffer').Buffer; const Buffer = require('buffer').Buffer;
const genUuid = require('uuid').v4;
/** /**
* This common function creates a domain object with the default options. It is the preferred way of creating objects * This common function creates a domain object with the default options. It is the preferred way of creating objects
@ -56,6 +57,10 @@ const Buffer = require('buffer').Buffer;
* @returns {Promise<CreatedObjectInfo>} An object containing information about the newly created domain object. * @returns {Promise<CreatedObjectInfo>} An object containing information about the newly created domain object.
*/ */
async function createDomainObjectWithDefaults(page, { type, name, parent = 'mine' }) { async function createDomainObjectWithDefaults(page, { type, name, parent = 'mine' }) {
if (!name) {
name = `${type}:${genUuid()}`;
}
const parentUrl = await getHashUrlToDomainObject(page, parent); const parentUrl = await getHashUrlToDomainObject(page, parent);
// Navigate to the parent object. This is necessary to create the object // Navigate to the parent object. This is necessary to create the object
@ -70,11 +75,14 @@ async function createDomainObjectWithDefaults(page, { type, name, parent = 'mine
await page.click(`li:text("${type}")`); await page.click(`li:text("${type}")`);
// Modify the name input field of the domain object to accept 'name' // Modify the name input field of the domain object to accept 'name'
if (name) {
const nameInput = page.locator('form[name="mctForm"] .first input[type="text"]'); const nameInput = page.locator('form[name="mctForm"] .first input[type="text"]');
await nameInput.fill(""); await nameInput.fill("");
await nameInput.fill(name); await nameInput.fill(name);
}
// Fill the "Notes" section with information about the
// currently running test and its project.
const notesInput = page.locator('form[name="mctForm"] #notes-textarea');
await notesInput.fill(page.testNotes);
// Click OK button and wait for Navigate event // Click OK button and wait for Navigate event
await Promise.all([ await Promise.all([
@ -96,8 +104,8 @@ async function createDomainObjectWithDefaults(page, { type, name, parent = 'mine
} }
return { return {
name: name || `Unnamed ${type}`, name,
uuid: uuid, uuid,
url: objectUrl url: objectUrl
}; };
} }

View File

@ -20,6 +20,8 @@
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
const { createDomainObjectWithDefaults } = require('../appActions');
const NOTEBOOK_DROP_AREA = '.c-notebook__drag-area'; const NOTEBOOK_DROP_AREA = '.c-notebook__drag-area';
/** /**
@ -38,24 +40,17 @@ async function enterTextEntry(page, text) {
/** /**
* @param {import('@playwright/test').Page} page * @param {import('@playwright/test').Page} page
*/ */
async function dragAndDropEmbed(page, myItemsFolderName) { async function dragAndDropEmbed(page, notebookObject) {
// Click button:has-text("Create") // Create example telemetry object
await page.locator('button:has-text("Create")').click(); const swg = await createDomainObjectWithDefaults(page, {
// Click li:has-text("Sine Wave Generator") type: "Sine Wave Generator"
await page.locator('li:has-text("Sine Wave Generator")').click(); });
// Click form[name="mctForm"] >> text=My Items // Navigate to notebook
await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click(); await page.goto(notebookObject.url);
// Click text=OK // Expand the tree to reveal the notebook
await page.locator('text=OK').click(); await page.click('button[title="Show selected item in tree"]');
// Click text=Open MCT My Items >> span >> nth=3 // Drag and drop the SWG into the notebook
await page.locator(`text=Open MCT ${myItemsFolderName} >> span`).nth(3).click(); await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA);
// Click text=Unnamed CUSTOM_NAME
await Promise.all([
page.waitForNavigation(),
page.locator('text=Unnamed CUSTOM_NAME').click()
]);
await page.dragAndDrop('text=UNNAMED SINE WAVE GENERATOR', NOTEBOOK_DROP_AREA);
} }
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef

View File

@ -126,13 +126,21 @@ exports.test = test.extend({
// This should follow in the Project's configuration. Can be set to 'snow' in playwright config.js // This should follow in the Project's configuration. Can be set to 'snow' in playwright config.js
theme: [theme, { option: true }], theme: [theme, { option: true }],
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
page: async ({ page, theme }, use) => { page: async ({ page, theme }, use, testInfo) => {
// eslint-disable-next-line playwright/no-conditional-in-test // eslint-disable-next-line playwright/no-conditional-in-test
if (theme === 'snow') { if (theme === 'snow') {
//inject snow theme //inject snow theme
await page.addInitScript({ path: path.join(__dirname, './helper', './useSnowTheme.js') }); await page.addInitScript({ path: path.join(__dirname, './helper', './useSnowTheme.js') });
} }
// Attach info about the currently running test and its project.
// This will be used by appActions to fill in the created
// domain object's notes.
page.testNotes = [
`${testInfo.titlePath.join('\n')}`,
`${testInfo.project.name}`
].join('\n');
await use(page); await use(page);
}, },
myItemsFolderName: [myItemsFolderName, { option: true }], myItemsFolderName: [myItemsFolderName, { option: true }],
@ -140,22 +148,5 @@ exports.test = test.extend({
openmctConfig: async ({ myItemsFolderName }, use) => { openmctConfig: async ({ myItemsFolderName }, use) => {
await use({ myItemsFolderName }); await use({ myItemsFolderName });
} }
// objectCreateOptions: [objectCreateOptions, {option: true}],
// eslint-disable-next-line no-shadow
// domainObject: [async ({ page, objectCreateOptions }, use) => {
// // FIXME: This is a false-positive caused by a bug in the eslint-plugin-playwright rule.
// // eslint-disable-next-line playwright/no-conditional-in-test
// if (objectCreateOptions === null) {
// await use(page);
// return;
// }
// //Go to baseURL
// await page.goto('./', { waitUntil: 'networkidle' });
// const uuid = await getOrCreateDomainObject(page, objectCreateOptions);
// await use({ uuid });
// }, { auto: true }]
}); });
exports.expect = expect; exports.expect = expect;

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
const { test, expect } = require('../../baseFixtures.js'); const { test, expect } = require('../../pluginFixtures.js');
const { createDomainObjectWithDefaults } = require('../../appActions.js'); const { createDomainObjectWithDefaults } = require('../../appActions.js');
test.describe('AppActions', () => { test.describe('AppActions', () => {
@ -50,11 +50,11 @@ test.describe('AppActions', () => {
}); });
await page.goto(timer1.url, { waitUntil: 'networkidle' }); await page.goto(timer1.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Timer Foo'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(timer1.name);
await page.goto(timer2.url, { waitUntil: 'networkidle' }); await page.goto(timer2.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Timer Bar'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(timer2.name);
await page.goto(timer3.url, { waitUntil: 'networkidle' }); await page.goto(timer3.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Timer Baz'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(timer3.name);
}); });
await test.step('Create multiple nested objects in a row', async () => { await test.step('Create multiple nested objects in a row', async () => {
@ -74,11 +74,11 @@ test.describe('AppActions', () => {
parent: folder2.uuid parent: folder2.uuid
}); });
await page.goto(folder1.url, { waitUntil: 'networkidle' }); await page.goto(folder1.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Folder Foo'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(folder1.name);
await page.goto(folder2.url, { waitUntil: 'networkidle' }); await page.goto(folder2.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Folder Bar'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(folder2.name);
await page.goto(folder3.url, { waitUntil: 'networkidle' }); await page.goto(folder3.url, { waitUntil: 'networkidle' });
await expect(page.locator('.l-browse-bar__object-name')).toHaveText('Folder Baz'); await expect(page.locator('.l-browse-bar__object-name')).toHaveText(folder3.name);
expect(folder1.url).toBe(`${e2eFolder.url}/${folder1.uuid}`); expect(folder1.url).toBe(`${e2eFolder.url}/${folder1.uuid}`);
expect(folder2.url).toBe(`${e2eFolder.url}/${folder1.uuid}/${folder2.uuid}`); expect(folder2.url).toBe(`${e2eFolder.url}/${folder1.uuid}/${folder2.uuid}`);

View File

@ -45,7 +45,7 @@
*/ */
// Structure: Some standard Imports. Please update the required pathing. // Structure: Some standard Imports. Please update the required pathing.
const { test, expect } = require('../../baseFixtures'); const { test, expect } = require('../../pluginFixtures');
const { createDomainObjectWithDefaults } = require('../../appActions'); const { createDomainObjectWithDefaults } = require('../../appActions');
/** /**
@ -144,5 +144,5 @@ async function renameTimerFrom3DotMenu(page, timerUrl, newNameForTimer) {
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(newNameForTimer); await page.locator('text=Properties Title Notes >> input[type="text"]').fill(newNameForTimer);
// Click Ok button to Save // Click Ok button to Save
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
} }

View File

@ -43,14 +43,14 @@ test('Generate Visual Test Data @localStorage', async ({ page, context }) => {
await page.locator('button:has-text("Create")').click(); await page.locator('button:has-text("Create")').click();
// add sine wave generator with defaults // add sine wave generator with defaults
await page.locator('li:has-text("Sine Wave Generator")').click(); await page.locator('li[role="menuitem"]:has-text("Sine Wave Generator")').click();
//Add a 5000 ms Delay //Add a 5000 ms Delay
await page.locator('[aria-label="Loading Delay \\(ms\\)"]').fill('5000'); await page.locator('[aria-label="Loading Delay \\(ms\\)"]').fill('5000');
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.locator('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')
]); ]);
@ -58,7 +58,7 @@ test('Generate Visual Test Data @localStorage', async ({ page, context }) => {
// focus the overlay plot // focus the overlay plot
await page.goto(overlayPlot.url); await page.goto(overlayPlot.url);
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Overlay Plot'); await expect(page.locator('.l-browse-bar__object-name')).toContainText(overlayPlot.name);
//Save localStorage for future test execution //Save localStorage for future test execution
await context.storageState({ path: './e2e/test-data/VisualTestData_storage.json' }); await context.storageState({ path: './e2e/test-data/VisualTestData_storage.json' });
}); });

View File

@ -25,7 +25,7 @@
* *
*/ */
const { test, expect } = require('../../baseFixtures'); const { test, expect } = require('../../pluginFixtures');
test.describe("CouchDB Status Indicator @couchdb", () => { test.describe("CouchDB Status Indicator @couchdb", () => {
test.use({ failOnConsoleError: false }); test.use({ failOnConsoleError: false });

View File

@ -24,7 +24,7 @@
This test suite is dedicated to tests which verify the basic operations surrounding the example event generator. This test suite is dedicated to tests which verify the basic operations surrounding the example event generator.
*/ */
const { test, expect } = require('../../../baseFixtures'); const { test, expect } = require('../../../pluginFixtures');
const { createDomainObjectWithDefaults } = require('../../../appActions'); const { createDomainObjectWithDefaults } = require('../../../appActions');
test.describe('Example Event Generator CRUD Operations', () => { test.describe('Example Event Generator CRUD Operations', () => {

View File

@ -96,7 +96,7 @@ test.describe('Sine Wave Generator', () => {
//Click text=OK //Click text=OK
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.click('text=OK') page.click('button:has-text("OK")')
]); ]);
// Verify that the Sine Wave Generator is displayed and correct // Verify that the Sine Wave Generator is displayed and correct

View File

@ -43,7 +43,7 @@ test.describe('Form Validation Behavior', () => {
await page.press('text=Properties Title Notes >> input[type="text"]', 'Tab'); await page.press('text=Properties Title Notes >> input[type="text"]', 'Tab');
//Required Field Form Validation //Required Field Form Validation
await expect(page.locator('text=OK')).toBeDisabled(); await expect(page.locator('button:has-text("OK")')).toBeDisabled();
await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(/invalid/); await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(/invalid/);
//Correct Form Validation for missing title and trigger validation with 'Tab' //Correct Form Validation for missing title and trigger validation with 'Tab'
@ -52,13 +52,13 @@ test.describe('Form Validation Behavior', () => {
await page.press('text=Properties Title Notes >> input[type="text"]', 'Tab'); await page.press('text=Properties Title Notes >> input[type="text"]', 'Tab');
//Required Field Form Validation is corrected //Required Field Form Validation is corrected
await expect(page.locator('text=OK')).toBeEnabled(); await expect(page.locator('button:has-text("OK")')).toBeEnabled();
await expect(page.locator('.c-form-row__state-indicator').first()).not.toHaveClass(/invalid/); await expect(page.locator('.c-form-row__state-indicator').first()).not.toHaveClass(/invalid/);
//Finish Creating Domain Object //Finish Creating Domain Object
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.click('text=OK') page.click('button:has-text("OK")')
]); ]);
//Verify that the Domain Object has been created with the corrected title property //Verify that the Domain Object has been created with the corrected title property

View File

@ -81,7 +81,7 @@ test.describe('Move & link item tests', () => {
await page.locator('li.icon-move').click(); await page.locator('li.icon-move').click();
await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click(); await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// Expect that Child Folder is in My Items, the root folder // Expect that Child Folder is in My Items, the root folder
expect(page.locator(`text=${myItemsFolderName} >> nth=0:has(text=Child Folder)`)).toBeTruthy(); expect(page.locator(`text=${myItemsFolderName} >> nth=0:has(text=Child Folder)`)).toBeTruthy();
@ -95,11 +95,11 @@ test.describe('Move & link item tests', () => {
// Create Telemetry Table // Create Telemetry Table
let telemetryTable = 'Test Telemetry Table'; let telemetryTable = 'Test Telemetry Table';
await page.locator('button:has-text("Create")').click(); await page.locator('button:has-text("Create")').click();
await page.locator('li:has-text("Telemetry Table")').click(); await page.locator('li[role="menuitem"]:has-text("Telemetry Table")').click();
await page.locator('text=Properties Title Notes >> input[type="text"]').click(); await page.locator('text=Properties Title Notes >> input[type="text"]').click();
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(telemetryTable); await page.locator('text=Properties Title Notes >> input[type="text"]').fill(telemetryTable);
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// Finish editing and save Telemetry Table // Finish editing and save Telemetry Table
await page.locator('.c-button--menu.c-button--major.icon-save').click(); await page.locator('.c-button--menu.c-button--major.icon-save').click();
@ -108,7 +108,7 @@ test.describe('Move & link item tests', () => {
// Create New Folder Basic Domain Object // Create New Folder Basic Domain Object
let folder = 'Test Folder'; let folder = 'Test Folder';
await page.locator('button:has-text("Create")').click(); await page.locator('button:has-text("Create")').click();
await page.locator('li:has-text("Folder")').click(); await page.locator('li[role="menuitem"]:has-text("Folder")').click();
await page.locator('text=Properties Title Notes >> input[type="text"]').click(); await page.locator('text=Properties Title Notes >> input[type="text"]').click();
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folder); await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folder);
@ -120,7 +120,7 @@ test.describe('Move & link item tests', () => {
// Continue test regardless of assertion and create it in My Items // Continue test regardless of assertion and create it in My Items
await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click(); await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// Open My Items // Open My Items
await page.locator(`text=Open MCT ${myItemsFolderName} >> span`).nth(3).click(); await page.locator(`text=Open MCT ${myItemsFolderName} >> span`).nth(3).click();
@ -196,7 +196,7 @@ test.describe('Move & link item tests', () => {
await page.locator('li.icon-link').click(); await page.locator('li.icon-link').click();
await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click(); await page.locator(`form[name="mctForm"] >> text=${myItemsFolderName}`).click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// Expect that Child Folder is in My Items, the root folder // Expect that Child Folder is in My Items, the root folder
expect(page.locator(`text=${myItemsFolderName} >> nth=0:has(text=Child Folder)`)).toBeTruthy(); expect(page.locator(`text=${myItemsFolderName} >> nth=0:has(text=Child Folder)`)).toBeTruthy();

View File

@ -40,11 +40,11 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'networkidle' });
await page.click('button:has-text("Create")'); await page.click('button:has-text("Create")');
await page.locator('li:has-text("Condition Set")').click(); await page.locator('li[role="menuitem"]:has-text("Condition Set")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.click('text=OK') page.click('button:has-text("OK")')
]); ]);
//Save localStorage for future test execution //Save localStorage for future test execution
@ -163,9 +163,9 @@ test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
// Click hamburger button // Click hamburger button
await page.locator('[title="More options"]').click(); await page.locator('[title="More options"]').click();
// Click text=Remove // Click 'Remove' and press OK
await page.locator('text=Remove').click(); await page.locator('li[role="menuitem"]:has-text("Remove")').click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
//Expect Unnamed Condition Set to be removed in Main View //Expect Unnamed Condition Set to be removed in Main View
const numberOfConditionSetsAtEnd = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count(); const numberOfConditionSetsAtEnd = await page.locator('a:has-text("Unnamed Condition Set Condition Set")').count();

View File

@ -116,8 +116,8 @@ test.describe('Testing Display Layout @unstable', () => {
// Bring up context menu and remove // Bring up context menu and remove
await page.locator('.c-tree__item.is-alias .c-tree__item__name:text("Test Sine Wave Generator")').first().click({ button: 'right' }); await page.locator('.c-tree__item.is-alias .c-tree__item__name:text("Test Sine Wave Generator")').first().click({ button: 'right' });
await page.locator('text=Remove').click(); await page.locator('li[role="menuitem"]:has-text("Remove")').click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// delete // delete
@ -150,7 +150,7 @@ test.describe('Testing Display Layout @unstable', () => {
// Bring up context menu and remove // Bring up context menu and remove
await page.locator('.c-tree__item.is-alias .c-tree__item__name:text("Test Sine Wave Generator")').click({ button: 'right' }); await page.locator('.c-tree__item.is-alias .c-tree__item__name:text("Test Sine Wave Generator")').click({ button: 'right' });
await page.locator('text=Remove').click(); await page.locator('text=Remove').click();
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
// navigate back to the display layout to confirm it has been removed // navigate back to the display layout to confirm it has been removed
await page.locator('.c-tree__item .c-tree__item__name:text("Test Display Layout")').click(); await page.locator('.c-tree__item .c-tree__item__name:text("Test Display Layout")').click();

View File

@ -40,10 +40,10 @@ test.describe('Example Imagery Object', () => {
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'networkidle' });
// Create a default 'Example Imagery' object // Create a default 'Example Imagery' object
await createDomainObjectWithDefaults(page, { type: 'Example Imagery' }); const exampleImagery = await createDomainObjectWithDefaults(page, { type: 'Example Imagery' });
// Verify that the created object is focused // Verify that the created object is focused
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Example Imagery'); await expect(page.locator('.l-browse-bar__object-name')).toContainText(exampleImagery.name);
await page.locator(backgroundImageSelector).hover({trial: true}); await page.locator(backgroundImageSelector).hover({trial: true});
}); });
@ -188,7 +188,7 @@ test.describe('Example Imagery in Display Layout', () => {
await page.click('button:has-text("Create")'); await page.click('button:has-text("Create")');
// Click text=Example Imagery // Click text=Example Imagery
await page.click('text=Example Imagery'); await page.click('li[role="menuitem"]:has-text("Example Imagery")');
// Clear and set Image load delay to minimum value // Clear and set Image load delay to minimum value
await page.locator('input[type="number"]').fill(''); await page.locator('input[type="number"]').fill('');
@ -197,7 +197,7 @@ test.describe('Example Imagery in Display Layout', () => {
// Click text=OK // Click text=OK
await Promise.all([ await Promise.all([
page.waitForNavigation({waitUntil: 'networkidle'}), page.waitForNavigation({waitUntil: 'networkidle'}),
page.click('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')
]); ]);
@ -275,7 +275,7 @@ test.describe('Example Imagery in Flexible layout', () => {
await page.click('button:has-text("Create")'); await page.click('button:has-text("Create")');
// Click text=Example Imagery // Click text=Example Imagery
await page.click('text=Example Imagery'); await page.click('li[role="menuitem"]:has-text("Example Imagery")');
// Clear and set Image load delay to minimum value // Clear and set Image load delay to minimum value
await page.locator('input[type="number"]').fill(''); await page.locator('input[type="number"]').fill('');
@ -284,7 +284,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: 'networkidle'}),
page.click('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')
]); ]);
@ -317,7 +317,7 @@ test.describe('Example Imagery in Tabs View', () => {
await page.click('button:has-text("Create")'); await page.click('button:has-text("Create")');
// Click text=Example Imagery // Click text=Example Imagery
await page.click('text=Example Imagery'); await page.click('li[role="menuitem"]:has-text("Example Imagery")');
// Clear and set Image load delay to minimum value // Clear and set Image load delay to minimum value
await page.locator('input[type="number"]').fill(''); await page.locator('input[type="number"]').fill('');
@ -326,7 +326,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: 'networkidle'}),
page.click('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

@ -26,7 +26,7 @@ This test suite is dedicated to tests which verify the basic operations surround
// FIXME: Remove this eslint exception once tests are implemented // FIXME: Remove this eslint exception once tests are implemented
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const { test, expect } = require('../../../../baseFixtures'); const { test, expect } = require('../../../../pluginFixtures');
const { expandTreePaneItemByName, createDomainObjectWithDefaults } = require('../../../../appActions'); const { expandTreePaneItemByName, createDomainObjectWithDefaults } = require('../../../../appActions');
const nbUtils = require('../../../../helper/notebookUtils'); const nbUtils = require('../../../../helper/notebookUtils');

View File

@ -24,7 +24,7 @@
This test suite is dedicated to tests which verify the basic operations surrounding Notebooks with CouchDB. This test suite is dedicated to tests which verify the basic operations surrounding Notebooks with CouchDB.
*/ */
const { test, expect } = require('../../../../baseFixtures'); const { test, expect } = require('../../../../pluginFixtures');
const { createDomainObjectWithDefaults } = require('../../../../appActions'); const { createDomainObjectWithDefaults } = require('../../../../appActions');
test.describe('Notebook Tests with CouchDB @couchdb', () => { test.describe('Notebook Tests with CouchDB @couchdb', () => {

View File

@ -36,27 +36,27 @@ test.describe('Restricted Notebook', () => {
}); });
test('Can be renamed @addInit', async ({ page }) => { test('Can be renamed @addInit', async ({ page }) => {
await expect(page.locator('.l-browse-bar__object-name')).toContainText(`Unnamed ${CUSTOM_NAME}`); await expect(page.locator('.l-browse-bar__object-name')).toContainText(`${notebook.name}`);
}); });
test('Can be deleted if there are no locked pages @addInit', async ({ page, openmctConfig }) => { test('Can be deleted if there are no locked pages @addInit', async ({ page }) => {
await openObjectTreeContextMenu(page, notebook.url); await openObjectTreeContextMenu(page, notebook.url);
const menuOptions = page.locator('.c-menu ul'); const menuOptions = page.locator('.c-menu ul');
await expect.soft(menuOptions).toContainText('Remove'); await expect.soft(menuOptions).toContainText('Remove');
const restrictedNotebookTreeObject = page.locator(`a:has-text("Unnamed ${CUSTOM_NAME}")`); const restrictedNotebookTreeObject = page.locator(`a:has-text("${notebook.name}")`);
// notebook tree object exists // notebook tree object exists
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1); expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1);
// Click Remove Text // Click Remove Text
await page.locator('text=Remove').click(); await page.locator('li[role="menuitem"]:has-text("Remove")').click();
// Click 'OK' on confirmation window and wait for save banner to appear // Click 'OK' on confirmation window and wait for save banner to appear
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.locator('text=OK').click(), page.locator('button:has-text("OK")').click(),
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
]); ]);
@ -134,7 +134,7 @@ test.describe('Restricted Notebook with at least one entry and with the page loc
// Click text=Ok // Click text=Ok
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.locator('text=Ok').click() page.locator('button:has-text("OK")').click()
]); ]);
// deleted page, should no longer exist // deleted page, should no longer exist
@ -145,10 +145,9 @@ test.describe('Restricted Notebook with at least one entry and with the page loc
test.describe('Restricted Notebook with a page locked and with an embed @addInit', () => { test.describe('Restricted Notebook with a page locked and with an embed @addInit', () => {
test.beforeEach(async ({ page, openmctConfig }) => { test.beforeEach(async ({ page }) => {
const { myItemsFolderName } = openmctConfig; const notebook = await startAndAddRestrictedNotebookObject(page);
await startAndAddRestrictedNotebookObject(page); await nbUtils.dragAndDropEmbed(page, notebook);
await nbUtils.dragAndDropEmbed(page, myItemsFolderName);
}); });
test('Allows embeds to be deleted if page unlocked @addInit', async ({ page }) => { test('Allows embeds to be deleted if page unlocked @addInit', async ({ page }) => {

View File

@ -36,7 +36,7 @@ async function createNotebookAndEntry(page, iterations = 1) {
//Go to baseURL //Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'networkidle' });
createDomainObjectWithDefaults(page, { type: 'Notebook' }); const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' });
for (let iteration = 0; iteration < iterations; iteration++) { for (let iteration = 0; iteration < iterations; iteration++) {
// Create an entry // Create an entry
@ -45,6 +45,8 @@ async function createNotebookAndEntry(page, iterations = 1) {
await page.locator(entryLocator).click(); await page.locator(entryLocator).click();
await page.locator(entryLocator).fill(`Entry ${iteration}`); await page.locator(entryLocator).fill(`Entry ${iteration}`);
} }
return notebook;
} }
/** /**
@ -53,7 +55,7 @@ async function createNotebookAndEntry(page, iterations = 1) {
* @param {number} [iterations = 1] - the number of entries (and tags) to create * @param {number} [iterations = 1] - the number of entries (and tags) to create
*/ */
async function createNotebookEntryAndTags(page, iterations = 1) { async function createNotebookEntryAndTags(page, iterations = 1) {
await createNotebookAndEntry(page, iterations); const notebook = await createNotebookAndEntry(page, iterations);
for (let iteration = 0; iteration < iterations; iteration++) { for (let iteration = 0; iteration < iterations; iteration++) {
// Hover and click "Add Tag" button // Hover and click "Add Tag" button
@ -75,6 +77,8 @@ async function createNotebookEntryAndTags(page, iterations = 1) {
// Select the "Science" tag // Select the "Science" tag
await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click(); await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click();
} }
return notebook;
} }
test.describe('Tagging in Notebooks @addInit', () => { test.describe('Tagging in Notebooks @addInit', () => {
@ -173,10 +177,10 @@ test.describe('Tagging in Notebooks @addInit', () => {
//Go to baseURL //Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'networkidle' });
await createDomainObjectWithDefaults(page, { type: 'Clock' }); const clock = await createDomainObjectWithDefaults(page, { type: 'Clock' });
const ITERATIONS = 4; const ITERATIONS = 4;
await createNotebookEntryAndTags(page, ITERATIONS); const notebook = await createNotebookEntryAndTags(page, ITERATIONS);
for (let iteration = 0; iteration < ITERATIONS; iteration++) { for (let iteration = 0; iteration < ITERATIONS; iteration++) {
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`; const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
@ -189,11 +193,11 @@ test.describe('Tagging in Notebooks @addInit', () => {
page.goto('./#/browse/mine?hideTree=false'), page.goto('./#/browse/mine?hideTree=false'),
page.click('.c-disclosure-triangle') page.click('.c-disclosure-triangle')
]); ]);
// Click Unnamed Clock // Click Clock
await page.click('text="Unnamed Clock"'); await page.click(`text=${clock.name}`);
// Click Unnamed Notebook // Click Notebook
await page.click('text="Unnamed Notebook"'); await page.click(`text=${notebook.name}`);
for (let iteration = 0; iteration < ITERATIONS; iteration++) { for (let iteration = 0; iteration < ITERATIONS; iteration++) {
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`; const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
@ -207,14 +211,13 @@ test.describe('Tagging in Notebooks @addInit', () => {
page.waitForLoadState('networkidle') page.waitForLoadState('networkidle')
]); ]);
// Click Unnamed Notebook // Click Notebook
await page.click('text="Unnamed Notebook"'); await page.click(`text="${notebook.name}"`);
for (let iteration = 0; iteration < ITERATIONS; iteration++) { for (let iteration = 0; iteration < ITERATIONS; iteration++) {
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`; const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
await expect(page.locator(entryLocator)).toContainText("Science"); await expect(page.locator(entryLocator)).toContainText("Science");
await expect(page.locator(entryLocator)).toContainText("Driving"); await expect(page.locator(entryLocator)).toContainText("Driving");
} }
}); });
}); });

View File

@ -110,10 +110,10 @@ async function createSinewaveOverlayPlot(page, myItemsFolderName) {
await page.locator('button:has-text("Create")').click(); await page.locator('button:has-text("Create")').click();
// add overlay plot with defaults // add overlay plot with defaults
await page.locator('li:has-text("Overlay Plot")').click(); await page.locator('li[role="menuitem"]:has-text("Overlay Plot")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.locator('text=OK').click(), page.locator('button:has-text("OK")').click(),
//Wait for Save Banner to appear1 //Wait for Save Banner to appear1
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
]); ]);
@ -129,10 +129,10 @@ async function createSinewaveOverlayPlot(page, myItemsFolderName) {
await page.locator('button:has-text("Create")').click(); await page.locator('button:has-text("Create")').click();
// add sine wave generator with defaults // add sine wave generator with defaults
await page.locator('li: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(), page.waitForNavigation(),
page.locator('text=OK').click(), page.locator('button:has-text("OK")').click(),
//Wait for Save Banner to appear1 //Wait for Save Banner to appear1
page.waitForSelector('.c-message-banner__message') page.waitForSelector('.c-message-banner__message')
]); ]);

View File

@ -88,10 +88,10 @@ async function makeOverlayPlot(page, myItemsFolderName) {
// create overlay plot // create overlay plot
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li:has-text("Overlay Plot")').click(); await page.locator('li[role="menuitem"]:has-text("Overlay Plot")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle'}), page.waitForNavigation({ waitUntil: 'networkidle'}),
page.locator('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')
]); ]);
@ -106,7 +106,7 @@ async function makeOverlayPlot(page, myItemsFolderName) {
// create a sinewave generator // create a sinewave generator
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li:has-text("Sine Wave Generator")').click(); await page.locator('li[role="menuitem"]:has-text("Sine Wave Generator")').click();
// set amplitude to 6, offset 4, period 2 // set amplitude to 6, offset 4, period 2
@ -123,7 +123,7 @@ async function makeOverlayPlot(page, myItemsFolderName) {
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle'}), page.waitForNavigation({ waitUntil: 'networkidle'}),
page.locator('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

@ -88,11 +88,11 @@ async function makeStackedPlot(page, myItemsFolderName) {
// create stacked plot // create stacked plot
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li: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: 'networkidle'}),
page.locator('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')
]); ]);
@ -146,11 +146,11 @@ async function saveStackedPlot(page) {
async function createSineWaveGenerator(page) { async function createSineWaveGenerator(page) {
//Create sine wave generator //Create sine wave generator
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li: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: 'networkidle'}),
page.locator('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

@ -68,10 +68,10 @@ async function makeOverlayPlot(page) {
// create overlay plot // create overlay plot
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li:has-text("Overlay Plot")').click(); await page.locator('li[role="menuitem"]:has-text("Overlay Plot")').click();
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle'}), page.waitForNavigation({ waitUntil: 'networkidle'}),
page.locator('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')
]); ]);
@ -86,13 +86,13 @@ async function makeOverlayPlot(page) {
// create a sinewave generator // create a sinewave generator
await page.locator('button.c-create-button').click(); await page.locator('button.c-create-button').click();
await page.locator('li:has-text("Sine Wave Generator")').click(); await page.locator('li[role="menuitem"]:has-text("Sine Wave Generator")').click();
// Click OK to make generator // Click OK to make generator
await Promise.all([ await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle'}), page.waitForNavigation({ waitUntil: 'networkidle'}),
page.locator('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

@ -25,7 +25,7 @@
* *
*/ */
const { test, expect } = require('../../../../baseFixtures'); const { test, expect } = require('../../../../pluginFixtures');
const { createDomainObjectWithDefaults } = require('../../../../appActions'); const { createDomainObjectWithDefaults } = require('../../../../appActions');
test.describe('Plot Integrity Testing @unstable', () => { test.describe('Plot Integrity Testing @unstable', () => {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
const { test, expect } = require('../../../../baseFixtures'); const { test, expect } = require('../../../../pluginFixtures');
const { setFixedTimeMode, setRealTimeMode, setStartOffset, setEndOffset } = require('../../../../appActions'); const { setFixedTimeMode, setRealTimeMode, setStartOffset, setEndOffset } = require('../../../../appActions');
test.describe('Time conductor operations', () => { test.describe('Time conductor operations', () => {

View File

@ -30,7 +30,7 @@ test.describe('Timer', () => {
timer = await createDomainObjectWithDefaults(page, { type: 'timer' }); timer = await createDomainObjectWithDefaults(page, { type: 'timer' });
}); });
test('Can perform actions on the Timer', async ({ page, openmctConfig }) => { test('Can perform actions on the Timer', async ({ page }) => {
test.info().annotations.push({ test.info().annotations.push({
type: 'issue', type: 'issue',
description: 'https://github.com/nasa/openmct/issues/4313' description: 'https://github.com/nasa/openmct/issues/4313'

View File

@ -31,7 +31,7 @@ test.describe('Grand Search', () => {
test('Can search for objects, and subsequent search dropdown behaves properly', async ({ page, openmctConfig }) => { test('Can search for objects, and subsequent search dropdown behaves properly', async ({ page, openmctConfig }) => {
const { myItemsFolderName } = openmctConfig; const { myItemsFolderName } = openmctConfig;
await createObjectsForSearch(page, myItemsFolderName); const createdObjects = await createObjectsForSearch(page);
// Click [aria-label="OpenMCT Search"] input[type="search"] // Click [aria-label="OpenMCT Search"] input[type="search"]
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click(); await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
@ -41,8 +41,8 @@ test.describe('Grand Search', () => {
await expect(page.locator('[aria-label="Search Result"] >> nth=1')).toContainText(`Clock B ${myItemsFolderName} Red Folder Blue Folder`); await expect(page.locator('[aria-label="Search Result"] >> nth=1')).toContainText(`Clock B ${myItemsFolderName} Red Folder Blue Folder`);
await expect(page.locator('[aria-label="Search Result"] >> nth=2')).toContainText(`Clock C ${myItemsFolderName} Red Folder Blue Folder`); await expect(page.locator('[aria-label="Search Result"] >> nth=2')).toContainText(`Clock C ${myItemsFolderName} Red Folder Blue Folder`);
await expect(page.locator('[aria-label="Search Result"] >> nth=3')).toContainText(`Clock D ${myItemsFolderName} Red Folder Blue Folder`); await expect(page.locator('[aria-label="Search Result"] >> nth=3')).toContainText(`Clock D ${myItemsFolderName} Red Folder Blue Folder`);
// Click text=Elements >> nth=0 // Click the Elements pool to dismiss the search menu
await page.locator('text=Elements').first().click(); await page.locator('.l-pane__label:has-text("Elements")').click();
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden(); await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden();
await page.locator('[aria-label="OpenMCT Search"] [aria-label="Search Input"]').click(); await page.locator('[aria-label="OpenMCT Search"] [aria-label="Search Input"]').click();
@ -77,7 +77,7 @@ test.describe('Grand Search', () => {
await expect(page.locator('.is-object-type-clock')).toBeVisible(); await expect(page.locator('.is-object-type-clock')).toBeVisible();
await page.locator('[aria-label="OpenMCT Search"] [aria-label="Search Input"]').fill('Disp'); await page.locator('[aria-label="OpenMCT Search"] [aria-label="Search Input"]').fill('Disp');
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toContainText('Unnamed Display Layout'); await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toContainText(createdObjects.displayLayout.name);
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).not.toContainText('Folder'); await expect(page.locator('[aria-label="Search Result"] >> nth=0')).not.toContainText('Folder');
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Clock C'); await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Clock C');
@ -185,7 +185,7 @@ async function createFolderObject(page, folderName) {
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folderName); await page.locator('text=Properties Title Notes >> input[type="text"]').fill(folderName);
// Create folder object // Create folder object
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
} }
async function waitForSearchCompletion(page) { async function waitForSearchCompletion(page) {
@ -197,75 +197,56 @@ async function waitForSearchCompletion(page) {
* Creates some domain objects for searching * Creates some domain objects for searching
* @param {import('@playwright/test').Page} page * @param {import('@playwright/test').Page} page
*/ */
async function createObjectsForSearch(page, myItemsFolderName) { async function createObjectsForSearch(page) {
//Go to baseURL //Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' }); await page.goto('./', { waitUntil: 'networkidle' });
await page.locator('button:has-text("Create")').click(); const redFolder = await createDomainObjectWithDefaults(page, {
await page.locator('li:has-text("Folder") >> nth=1').click(); type: 'Folder',
await Promise.all([ name: 'Red Folder'
page.waitForNavigation(), });
await page.locator('text=Properties Title Notes >> input[type="text"]').fill('Red Folder'),
await page.locator(`text=Save In Open MCT ${myItemsFolderName} >> span`).nth(3).click(),
page.locator('button:has-text("OK")').click()
]);
await page.locator('button:has-text("Create")').click(); const blueFolder = await createDomainObjectWithDefaults(page, {
await page.locator('li:has-text("Folder") >> nth=2').click(); type: 'Folder',
await Promise.all([ name: 'Blue Folder',
page.waitForNavigation(), parent: redFolder.uuid
await page.locator('text=Properties Title Notes >> input[type="text"]').fill('Blue Folder'), });
await page.locator('form[name="mctForm"] >> text=Red Folder').click(),
page.locator('button:has-text("OK")').click()
]);
await page.locator('button:has-text("Create")').click(); const clockA = await createDomainObjectWithDefaults(page, {
await page.locator('li[title="A digital clock that uses system time and supports a variety of display formats and timezones."]').click(); type: 'Clock',
await Promise.all([ name: 'Clock A',
page.waitForNavigation(), parent: blueFolder.uuid
await page.locator('text=Properties Title Notes >> input[type="text"] >> nth=0').fill('Clock A'), });
await page.locator('form[name="mctForm"] >> text=Blue Folder').click(), const clockB = await createDomainObjectWithDefaults(page, {
page.locator('button:has-text("OK")').click() type: 'Clock',
]); name: 'Clock B',
parent: blueFolder.uuid
});
const clockC = await createDomainObjectWithDefaults(page, {
type: 'Clock',
name: 'Clock C',
parent: blueFolder.uuid
});
const clockD = await createDomainObjectWithDefaults(page, {
type: 'Clock',
name: 'Clock D',
parent: blueFolder.uuid
});
await page.locator('button:has-text("Create")').click(); const displayLayout = await createDomainObjectWithDefaults(page, {
await page.locator('li[title="A digital clock that uses system time and supports a variety of display formats and timezones."]').click(); type: 'Display Layout'
await Promise.all([ });
page.waitForNavigation(),
await page.locator('text=Properties Title Notes >> input[type="text"] >> nth=0').fill('Clock B'),
await page.locator('form[name="mctForm"] >> text=Blue Folder').click(),
page.locator('button:has-text("OK")').click()
]);
await page.locator('button:has-text("Create")').click(); // Go back into edit mode for the display layout
await page.locator('li[title="A digital clock that uses system time and supports a variety of display formats and timezones."]').click(); await page.locator('button[title="Edit"]').click();
await Promise.all([
page.waitForNavigation(),
await page.locator('text=Properties Title Notes >> input[type="text"] >> nth=0').fill('Clock C'),
await page.locator('form[name="mctForm"] >> text=Blue Folder').click(),
page.locator('button:has-text("OK")').click()
]);
await page.locator('button:has-text("Create")').click(); return {
await page.locator('li[title="A digital clock that uses system time and supports a variety of display formats and timezones."]').click(); redFolder,
await Promise.all([ blueFolder,
page.waitForNavigation(), clockA,
await page.locator('text=Properties Title Notes >> input[type="text"] >> nth=0').fill('Clock D'), clockB,
await page.locator('form[name="mctForm"] >> text=Blue Folder').click(), clockC,
page.locator('button:has-text("OK")').click() clockD,
]); displayLayout
};
await Promise.all([
page.waitForNavigation(),
page.locator(`a:has-text("${myItemsFolderName}") >> nth=0`).click()
]);
// Click button:has-text("Create")
await page.locator('button:has-text("Create")').click();
// Click li:has-text("Notebook")
await page.locator('li:has-text("Display Layout")').click();
// Click button:has-text("OK")
await Promise.all([
page.waitForNavigation(),
page.locator('button:has-text("OK")').click()
]);
} }

View File

@ -53,7 +53,7 @@ test.describe('Performance tests', () => {
await page.setInputFiles('#fileElem', filePath); await page.setInputFiles('#fileElem', filePath);
// Click text=OK // Click text=OK
await page.locator('text=OK').click(); await page.locator('button:has-text("OK")').click();
await expect(page.locator('a:has-text("Performance Display Layout Display Layout")')).toBeVisible(); await expect(page.locator('a:has-text("Performance Display Layout Display Layout")')).toBeVisible();

View File

@ -27,6 +27,7 @@
:class="model.cssClass" :class="model.cssClass"
> >
<textarea <textarea
:id="`${model.key}-textarea`"
v-model="field" v-model="field"
type="text" type="text"
:size="model.size" :size="model.size"

View File

@ -3,13 +3,21 @@
class="c-menu" class="c-menu"
:class="options.menuClass" :class="options.menuClass"
> >
<ul v-if="options.actions.length && options.actions[0].length"> <ul
v-if="options.actions.length && options.actions[0].length"
role="menu"
>
<template <template
v-for="(actionGroups, index) in options.actions" v-for="(actionGroups, index) in options.actions"
>
<div
:key="index"
role="group"
> >
<li <li
v-for="action in actionGroups" v-for="action in actionGroups"
:key="action.name" :key="action.name"
role="menuitem"
:class="[action.cssClass, action.isDisabled ? 'disabled' : '']" :class="[action.cssClass, action.isDisabled ? 'disabled' : '']"
:title="action.description" :title="action.description"
:data-testid="action.testId || false" :data-testid="action.testId || false"
@ -20,6 +28,7 @@
<div <div
v-if="index !== options.actions.length - 1" v-if="index !== options.actions.length - 1"
:key="index" :key="index"
role="separator"
class="c-menu__section-separator" class="c-menu__section-separator"
> >
</div> </div>
@ -29,13 +38,17 @@
> >
No actions defined. No actions defined.
</li> </li>
</template> </div></template>
</ul> </ul>
<ul v-else> <ul
v-else
role="menu"
>
<li <li
v-for="action in options.actions" v-for="action in options.actions"
:key="action.name" :key="action.name"
role="menuitem"
:class="[action.cssClass, action.isDisabled ? 'disabled' : '']" :class="[action.cssClass, action.isDisabled ? 'disabled' : '']"
:title="action.description" :title="action.description"
:data-testid="action.testId || false" :data-testid="action.testId || false"

View File

@ -5,14 +5,20 @@
> >
<ul <ul
v-if="options.actions.length && options.actions[0].length" v-if="options.actions.length && options.actions[0].length"
role="menu"
class="c-super-menu__menu" class="c-super-menu__menu"
> >
<template <template
v-for="(actionGroups, index) in options.actions" v-for="(actionGroups, index) in options.actions"
>
<div
:key="index"
role="group"
> >
<li <li
v-for="action in actionGroups" v-for="action in actionGroups"
:key="action.name" :key="action.name"
role="menuitem"
:class="[action.cssClass, action.isDisabled ? 'disabled' : '']" :class="[action.cssClass, action.isDisabled ? 'disabled' : '']"
:title="action.description" :title="action.description"
:data-testid="action.testId || false" :data-testid="action.testId || false"
@ -25,6 +31,7 @@
<div <div
v-if="index !== options.actions.length - 1" v-if="index !== options.actions.length - 1"
:key="index" :key="index"
role="separator"
class="c-menu__section-separator" class="c-menu__section-separator"
> >
</div> </div>
@ -34,16 +41,18 @@
> >
No actions defined. No actions defined.
</li> </li>
</template> </div></template>
</ul> </ul>
<ul <ul
v-else v-else
class="c-super-menu__menu" class="c-super-menu__menu"
role="menu"
> >
<li <li
v-for="action in options.actions" v-for="action in options.actions"
:key="action.name" :key="action.name"
role="menuitem"
:class="action.cssClass" :class="action.cssClass"
:title="action.description" :title="action.description"
:data-testid="action.testId || false" :data-testid="action.testId || false"