diff --git a/packages/nc-gui/components/smartsheet/details/Fields.vue b/packages/nc-gui/components/smartsheet/details/Fields.vue
index a7143ed4ab..87182660f8 100644
--- a/packages/nc-gui/components/smartsheet/details/Fields.vue
+++ b/packages/nc-gui/components/smartsheet/details/Fields.vue
@@ -1034,7 +1034,7 @@ watch(
>
{{ $t('labels.idColon') }}
-
diff --git a/tests/playwright/pages/Dashboard/Details/FieldsPage.ts b/tests/playwright/pages/Dashboard/Details/FieldsPage.ts
index 4b29a47054..c9aac907c4 100644
--- a/tests/playwright/pages/Dashboard/Details/FieldsPage.ts
+++ b/tests/playwright/pages/Dashboard/Details/FieldsPage.ts
@@ -198,14 +198,7 @@ export class FieldsPage extends BasePage {
await this.saveChanges();
- const fieldsText = [];
- const locator = this.fieldListWrapper.locator('>div');
- const count = await locator.count();
- for (let i = 0; i < count; i++) {
- await locator.nth(i).scrollIntoViewIfNeeded();
- const text = await locator.nth(i).getByTestId('nc-field-title').textContent();
- fieldsText.push(text);
- }
+ const fieldsText = await this.getAllFieldText();
if (insertAboveColumnTitle) {
// verify field inserted above the target field
@@ -275,6 +268,42 @@ export class FieldsPage extends BasePage {
await fieldActionDropdown.waitFor({ state: 'visible' });
await fieldActionDropdown.getByTestId(`nc-field-item-action-${action}`).click();
+
+ if (action === 'copy-id') {
+ await field.getByTestId('nc-field-item-action-button').click();
+ }
+
+ await fieldActionDropdown.waitFor({ state: 'hidden' });
+ }
+
+ async getAllFieldText() {
+ const fieldsText = [];
+ const locator = this.fieldListWrapper.locator('>div');
+ const count = await locator.count();
+ for (let i = 0; i < count; i++) {
+ await locator.nth(i).scrollIntoViewIfNeeded();
+ const text = await locator.nth(i).getByTestId('nc-field-title').textContent();
+ fieldsText.push(text);
+ }
+ return fieldsText;
+ }
+
+ async getFieldId({ title, isDisplayValueField = false }: { title: string; isDisplayValueField?: boolean }) {
+ const field = this.getField({ title });
+ await field.scrollIntoViewIfNeeded();
+
+ await field.hover();
+ await field.getByTestId('nc-field-item-action-button').waitFor({ state: 'visible' });
+ await field.getByTestId('nc-field-item-action-button').click();
+
+ const fieldActionDropdown = isDisplayValueField
+ ? this.rootPage.locator('.nc-field-item-action-dropdown-display-column')
+ : this.rootPage.locator('.nc-field-item-action-dropdown');
+
+ await fieldActionDropdown.waitFor({ state: 'visible' });
+ const fieldId = await fieldActionDropdown.getByTestId('nc-field-item-id').textContent();
+ await field.getByTestId('nc-field-item-action-button').click();
await fieldActionDropdown.waitFor({ state: 'hidden' });
+ return fieldId;
}
}
diff --git a/tests/playwright/tests/db/features/multiFieldEditor.spec.ts b/tests/playwright/tests/db/features/multiFieldEditor.spec.ts
index c88c80b0a9..5469ee9c49 100644
--- a/tests/playwright/tests/db/features/multiFieldEditor.spec.ts
+++ b/tests/playwright/tests/db/features/multiFieldEditor.spec.ts
@@ -1,8 +1,9 @@
-import { test } from '@playwright/test';
+import { expect, test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard';
import { GridPage } from '../../../pages/Dashboard/Grid';
import setup, { unsetup } from '../../../setup';
import { FieldsPage } from '../../../pages/Dashboard/Details/FieldsPage';
+import { getTextExcludeIconText } from '../../utils/general';
test.describe('Multi Field Editor', () => {
let dashboard: DashboardPage, grid: GridPage, fields: FieldsPage;
@@ -16,8 +17,7 @@ test.describe('Multi Field Editor', () => {
fields = dashboard.details.fields;
await dashboard.treeView.createTable({ title: 'Multifield', baseTitle: context.base.title });
- await dashboard.grid.topbar.openDetailedTab();
- await dashboard.details.clickFieldsTab();
+ await openMultiFieldOfATable();
// Add New Field
await fields.createOrUpdate({ title: defaultFieldName });
@@ -27,10 +27,27 @@ test.describe('Multi Field Editor', () => {
await unsetup(context);
});
- const openMultiFieldOfATable = async (tableName: string) => {
- await dashboard.treeView.openTable({ title: tableName });
+ async function openMultiFieldOfATable() {
await dashboard.grid.topbar.openDetailedTab();
- await dashboard.details.clickRelationsTab();
+ await dashboard.details.clickFieldsTab();
+ }
+
+ const verifyGridColumnHeaders = async ({ fields = [] }: { fields: string[] }) => {
+ await dashboard.grid.topbar.openDataTab();
+
+ const locator = dashboard.grid.get().locator(`th`);
+ const count = await locator.count();
+
+ // exclude first checkbox and last add new column
+ expect(count - 2).toBe(fields.length);
+
+ for (let i = 1; i < count - 1; i++) {
+ const header = locator.nth(i);
+ const text = await getTextExcludeIconText(header);
+ expect(text).toBe(fields[i - 1]);
+ }
+
+ await openMultiFieldOfATable();
};
test('Add New field and update', async () => {
@@ -42,8 +59,37 @@ test.describe('Multi Field Editor', () => {
await fields.createOrUpdate({ title: 'Updated Name', isUpdateMode: true });
});
- test('Field action menu: CopyId, Duplicate, InsertAbove, InsertBelow', async () => {
+ test.only('Field operations: CopyId, Duplicate, InsertAbove, InsertBelow, Hide', async () => {
+ // copy-id and verify
+ const fieldId = await fields.getFieldId({ title: defaultFieldName });
+ await fields.selectFieldAction({ title: defaultFieldName, action: 'copy-id' });
+ expect(fieldId).toBe(await dashboard.getClipboardText());
+
+ // duplicate and verify
+ await fields.selectFieldAction({ title: defaultFieldName, action: 'duplicate' });
+ await fields.saveChanges();
+
+ let fieldsText = await fields.getAllFieldText();
+ expect(fieldsText[fieldsText.findIndex(field => field === defaultFieldName) + 1]).toBe(`${defaultFieldName}_copy`);
+
+ // insert and verify
await fields.createOrUpdate({ title: 'Above Inserted Field', insertAboveColumnTitle: defaultFieldName });
await fields.createOrUpdate({ title: 'Below Inserted Field', insertBelowColumnTitle: defaultFieldName });
+
+ // delete and verify
+ await fields.selectFieldAction({ title: `${defaultFieldName}_copy`, action: 'delete' });
+ await fields.saveChanges();
+
+ fieldsText = await fields.getAllFieldText();
+ expect(fieldsText.findIndex(field => field === `${defaultFieldName}_copy`)).toBe(-1);
+
+ // verify grid column header
+ await verifyGridColumnHeaders({ fields: fieldsText });
+
+ // Hide field and verify grid column header
+ await (await fields.getFieldVisibilityCheckbox({ title: defaultFieldName })).click();
+ await fields.saveChanges();
+
+ await verifyGridColumnHeaders({ fields: fieldsText.filter(field => field !== defaultFieldName) });
});
});