* fix: Transaction-ify the CreateAction * test: add regression test and update tree locators * test: make object search test less flaky * test: revert locator
This commit is contained in:
@@ -133,6 +133,7 @@ test.describe('Grand Search', () => {
|
|||||||
const searchResults = page.locator(searchResultSelector);
|
const searchResults = page.locator(searchResultSelector);
|
||||||
|
|
||||||
// Verify that one result is found
|
// Verify that one result is found
|
||||||
|
await expect(searchResults).toBeVisible();
|
||||||
expect(await searchResults.count()).toBe(1);
|
expect(await searchResults.count()).toBe(1);
|
||||||
await expect(searchResults).toHaveText(folderName);
|
await expect(searchResults).toHaveText(folderName);
|
||||||
});
|
});
|
||||||
@@ -194,7 +195,7 @@ test.describe('Grand Search', () => {
|
|||||||
// Wait for search to finish
|
// Wait for search to finish
|
||||||
await waitForSearchCompletion(page);
|
await waitForSearchCompletion(page);
|
||||||
|
|
||||||
const searchResultDropDown = await page.locator(searchResultDropDownSelector);
|
const searchResultDropDown = page.locator(searchResultDropDownSelector);
|
||||||
|
|
||||||
// Verify that the search result/s correctly match the search query
|
// Verify that the search result/s correctly match the search query
|
||||||
await expect(searchResultDropDown).toContainText(folderName1);
|
await expect(searchResultDropDown).toContainText(folderName1);
|
||||||
|
|||||||
@@ -26,10 +26,35 @@ const {
|
|||||||
openObjectTreeContextMenu
|
openObjectTreeContextMenu
|
||||||
} = require('../../appActions.js');
|
} = require('../../appActions.js');
|
||||||
|
|
||||||
test.describe('Tree operations', () => {
|
test.describe('Main Tree', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto('./', { waitUntil: 'networkidle' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Creating a child object within a folder and immediately opening it shows the created object in the tree @couchdb', async ({ page }) => {
|
||||||
|
test.info().annotations.push({
|
||||||
|
type: 'issue',
|
||||||
|
description: 'https://github.com/nasa/openmct/issues/5975'
|
||||||
|
});
|
||||||
|
|
||||||
|
const folder = await createDomainObjectWithDefaults(page, {
|
||||||
|
type: 'Folder'
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.getByTitle('Show selected item in tree').click();
|
||||||
|
|
||||||
|
const clock = await createDomainObjectWithDefaults(page, {
|
||||||
|
type: 'Clock',
|
||||||
|
parent: folder.uuid
|
||||||
|
});
|
||||||
|
|
||||||
|
await expandTreePaneItemByName(page, folder.name);
|
||||||
|
await assertTreeItemIsVisible(page, clock.name);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
test('Renaming an object reorders the tree @unstable', async ({ page, openmctConfig }) => {
|
test('Renaming an object reorders the tree @unstable', async ({ page, openmctConfig }) => {
|
||||||
const { myItemsFolderName } = openmctConfig;
|
const { myItemsFolderName } = openmctConfig;
|
||||||
await page.goto('./', { waitUntil: 'networkidle' });
|
|
||||||
|
|
||||||
await createDomainObjectWithDefaults(page, {
|
await createDomainObjectWithDefaults(page, {
|
||||||
type: 'Folder',
|
type: 'Folder',
|
||||||
@@ -111,17 +136,30 @@ 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
|
||||||
*/
|
*/
|
||||||
async function expandTreePaneItemByName(page, name) {
|
async function expandTreePaneItemByName(page, name) {
|
||||||
const treePane = page.getByRole('tree', {
|
const mainTree = page.getByRole('tree', {
|
||||||
name: 'Main Tree'
|
name: 'Main Tree'
|
||||||
});
|
});
|
||||||
const treeItem = treePane.locator(`role=treeitem[expanded=false][name=/${name}/]`);
|
const treeItem = mainTree.getByRole('treeitem', {
|
||||||
const expandTriangle = treeItem.locator('.c-disclosure-triangle');
|
name,
|
||||||
await expandTriangle.click();
|
expanded: false
|
||||||
|
});
|
||||||
|
await treeItem.locator('.c-disclosure-triangle').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ import { v4 as uuid } from 'uuid';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export default class CreateAction extends PropertiesAction {
|
export default class CreateAction extends PropertiesAction {
|
||||||
|
#transaction;
|
||||||
|
|
||||||
constructor(openmct, type, parentDomainObject) {
|
constructor(openmct, type, parentDomainObject) {
|
||||||
super(openmct);
|
super(openmct);
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.parentDomainObject = parentDomainObject;
|
this.parentDomainObject = parentDomainObject;
|
||||||
|
this.#transaction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
invoke() {
|
invoke() {
|
||||||
@@ -77,6 +80,7 @@ export default class CreateAction extends PropertiesAction {
|
|||||||
await this.openmct.objects.save(this.domainObject);
|
await this.openmct.objects.save(this.domainObject);
|
||||||
const compositionCollection = await this.openmct.composition.get(parentDomainObject);
|
const compositionCollection = await this.openmct.composition.get(parentDomainObject);
|
||||||
compositionCollection.add(this.domainObject);
|
compositionCollection.add(this.domainObject);
|
||||||
|
await this.saveTransaction();
|
||||||
|
|
||||||
this._navigateAndEdit(this.domainObject, parentDomainObjectPath);
|
this._navigateAndEdit(this.domainObject, parentDomainObjectPath);
|
||||||
|
|
||||||
@@ -95,8 +99,12 @@ export default class CreateAction extends PropertiesAction {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_onCancel() {
|
_onCancel() {
|
||||||
//do Nothing
|
this.#transaction.cancel().then(() => {
|
||||||
|
this.openmct.objects.endTransaction();
|
||||||
|
this.#transaction = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -153,6 +161,8 @@ export default class CreateAction extends PropertiesAction {
|
|||||||
const formStructure = createWizard.getFormStructure(true);
|
const formStructure = createWizard.getFormStructure(true);
|
||||||
formStructure.title = 'Create a New ' + definition.name;
|
formStructure.title = 'Create a New ' + definition.name;
|
||||||
|
|
||||||
|
this.startTransaction();
|
||||||
|
|
||||||
this.openmct.forms.showForm(formStructure)
|
this.openmct.forms.showForm(formStructure)
|
||||||
.then(this._onSave.bind(this))
|
.then(this._onSave.bind(this))
|
||||||
.catch(this._onCancel.bind(this))
|
.catch(this._onCancel.bind(this))
|
||||||
@@ -160,4 +170,20 @@ export default class CreateAction extends PropertiesAction {
|
|||||||
this.openmct.objects.destroyMutable(this.domainObject);
|
this.openmct.objects.destroyMutable(this.domainObject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startTransaction() {
|
||||||
|
if (!this.openmct.objects.isTransactionActive()) {
|
||||||
|
this.#transaction = this.openmct.objects.startTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveTransaction() {
|
||||||
|
if (!this.#transaction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.#transaction.commit();
|
||||||
|
this.openmct.objects.endTransaction();
|
||||||
|
this.#transaction = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user