mirror of https://github.com/nocodb/nocodb
Raju Udava
11 months ago
committed by
GitHub
5 changed files with 835 additions and 46 deletions
@ -0,0 +1,318 @@
|
||||
// Fields
|
||||
|
||||
import BasePage from '../../Base'; |
||||
import { expect, Locator } from '@playwright/test'; |
||||
import { DetailsPage } from './index'; |
||||
import { UITypes } from 'nocodb-sdk'; |
||||
|
||||
export class FieldsPage extends BasePage { |
||||
readonly detailsPage: DetailsPage; |
||||
|
||||
readonly searchFieldInput: Locator; |
||||
readonly addNewFieldButton: Locator; |
||||
readonly resetFieldChangesButton: Locator; |
||||
readonly saveChangesButton: Locator; |
||||
|
||||
readonly addOrEditColumn: Locator; |
||||
readonly fieldListWrapper: Locator; |
||||
|
||||
constructor(details: DetailsPage) { |
||||
super(details.rootPage); |
||||
this.detailsPage = details; |
||||
this.searchFieldInput = this.get().getByTestId('nc-field-search-input'); |
||||
this.addNewFieldButton = this.get().getByTestId('nc-field-add-new'); |
||||
this.resetFieldChangesButton = this.get().getByTestId('nc-field-reset'); |
||||
this.saveChangesButton = this.get().getByTestId('nc-field-save-changes'); |
||||
this.addOrEditColumn = this.get().getByTestId('add-or-edit-column'); |
||||
this.fieldListWrapper = this.get().getByTestId('nc-field-list-wrapper'); |
||||
} |
||||
|
||||
get() { |
||||
return this.detailsPage.get().locator('.nc-fields-wrapper'); |
||||
} |
||||
|
||||
async fillSearch({ title }: { title: string }) { |
||||
const searchInput = this.get().getByTestId('nc-field-search-input'); |
||||
await searchInput.click(); |
||||
await searchInput.fill(title); |
||||
} |
||||
|
||||
async clearSearch() { |
||||
await this.get().getByTestId('nc-field-clear-search').click(); |
||||
} |
||||
|
||||
async clickNewField() { |
||||
await this.addNewFieldButton.click(); |
||||
} |
||||
|
||||
async clickRestoreField({ title }: { title: string }) { |
||||
await this.getField({ title }).getByTestId('nc-field-restore-changes').click(); |
||||
} |
||||
|
||||
async createOrUpdate({ |
||||
title, |
||||
type = UITypes.SingleLineText, |
||||
isUpdateMode = false, |
||||
saveChanges = true, |
||||
formula = '', |
||||
qrCodeValueColumnTitle = '', |
||||
barcodeValueColumnTitle = '', |
||||
barcodeFormat = '', |
||||
childTable = '', |
||||
childColumn = '', |
||||
relationType = '', |
||||
rollupType = '', |
||||
format = '', |
||||
dateFormat = 'YYYY-MM-DD', |
||||
timeFormat = 'HH:mm', |
||||
insertAboveColumnTitle, |
||||
insertBelowColumnTitle, |
||||
}: { |
||||
title: string; |
||||
type?: UITypes; |
||||
isUpdateMode?: boolean; |
||||
saveChanges?: boolean; |
||||
formula?: string; |
||||
qrCodeValueColumnTitle?: string; |
||||
barcodeValueColumnTitle?: string; |
||||
barcodeFormat?: string; |
||||
childTable?: string; |
||||
childColumn?: string; |
||||
relationType?: string; |
||||
rollupType?: string; |
||||
format?: string; |
||||
dateFormat?: string; |
||||
timeFormat?: string; |
||||
insertAboveColumnTitle?: string; |
||||
insertBelowColumnTitle?: string; |
||||
}) { |
||||
if (!isUpdateMode) { |
||||
if (insertAboveColumnTitle) { |
||||
await this.selectFieldAction({ title: insertAboveColumnTitle, action: 'insert-above' }); |
||||
} else if (insertBelowColumnTitle) { |
||||
await this.selectFieldAction({ title: insertBelowColumnTitle, action: 'insert-below' }); |
||||
} else { |
||||
await this.clickNewField(); |
||||
} |
||||
} |
||||
await this.addOrEditColumn.waitFor({ state: 'visible' }); |
||||
|
||||
await this.fillTitle({ title }); |
||||
|
||||
await this.selectType({ type }); |
||||
await this.rootPage.waitForTimeout(500); |
||||
|
||||
switch (type) { |
||||
case 'SingleSelect': |
||||
case 'MultiSelect': |
||||
break; |
||||
case 'Duration': |
||||
if (format) { |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`, { |
||||
hasText: format, |
||||
}) |
||||
.click(); |
||||
} |
||||
break; |
||||
case 'Date': |
||||
await this.addOrEditColumn.locator('.nc-date-select').click(); |
||||
await this.rootPage.locator('.nc-date-select').pressSequentially(dateFormat); |
||||
await this.rootPage.locator('.ant-select-item').locator(`text="${dateFormat}"`).click(); |
||||
break; |
||||
case 'DateTime': |
||||
// Date Format
|
||||
await this.addOrEditColumn.locator('.nc-date-select').click(); |
||||
await this.rootPage.locator('.ant-select-item').locator(`text="${dateFormat}"`).click(); |
||||
// Time Format
|
||||
await this.addOrEditColumn.locator('.nc-time-select').click(); |
||||
await this.rootPage.locator('.ant-select-item').locator(`text="${timeFormat}"`).click(); |
||||
break; |
||||
case 'Formula': |
||||
await this.addOrEditColumn.locator('.nc-formula-input').fill(formula); |
||||
break; |
||||
case 'QrCode': |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`) |
||||
.locator(`[data-testid="nc-qr-${qrCodeValueColumnTitle}"]`) |
||||
.click(); |
||||
break; |
||||
case 'Barcode': |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`, { |
||||
hasText: new RegExp(`^${barcodeValueColumnTitle}$`), |
||||
}) |
||||
.click(); |
||||
break; |
||||
case 'Lookup': |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`, { |
||||
hasText: childTable, |
||||
}) |
||||
.click(); |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(2).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`, { |
||||
hasText: childColumn, |
||||
}) |
||||
.last() |
||||
.click(); |
||||
break; |
||||
case 'Rollup': |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage |
||||
.locator(`.ant-select-item`, { |
||||
hasText: childTable, |
||||
}) |
||||
.click(); |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(2).click(); |
||||
await this.rootPage |
||||
.locator(`.nc-dropdown-relation-column >> .ant-select-item`, { |
||||
hasText: childColumn, |
||||
}) |
||||
.click(); |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(3).click(); |
||||
await this.rootPage |
||||
.locator(`.nc-dropdown-rollup-function >> .ant-select-item`, { |
||||
hasText: rollupType, |
||||
}) |
||||
.nth(0) |
||||
.click(); |
||||
break; |
||||
case 'Links': |
||||
await this.addOrEditColumn |
||||
.locator('.nc-ltar-relation-type >> .ant-radio') |
||||
.nth(relationType === 'Has Many' ? 0 : 1) |
||||
.click(); |
||||
await this.addOrEditColumn.locator('.ant-select-single').nth(1).click(); |
||||
await this.rootPage.locator(`.nc-ltar-child-table >> input[type="search"]`).fill(childTable); |
||||
await this.rootPage |
||||
.locator(`.nc-dropdown-ltar-child-table >> .ant-select-item`, { |
||||
hasText: childTable, |
||||
}) |
||||
.nth(0) |
||||
.click(); |
||||
break; |
||||
case 'User': |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
if (saveChanges) { |
||||
await this.saveChanges(); |
||||
|
||||
const fieldsText = await this.getAllFieldText(); |
||||
|
||||
if (insertAboveColumnTitle) { |
||||
// verify field inserted above the target field
|
||||
expect(fieldsText[fieldsText.findIndex(title => title.startsWith(insertAboveColumnTitle)) - 1]).toBe(title); |
||||
} else if (insertBelowColumnTitle) { |
||||
// verify field inserted below the target field
|
||||
expect(fieldsText[fieldsText.findIndex(title => title.startsWith(insertBelowColumnTitle)) + 1]).toBe(title); |
||||
} else { |
||||
// verify field inserted at the end
|
||||
expect(fieldsText[fieldsText.length - 1]).toBe(title); |
||||
} |
||||
} |
||||
} |
||||
|
||||
async fillTitle({ title }: { title: string }) { |
||||
const fieldTitleInput = this.addOrEditColumn.locator('.nc-fields-input'); |
||||
await fieldTitleInput.click(); |
||||
await fieldTitleInput.fill(title); |
||||
} |
||||
|
||||
async selectType({ type }: { type: string }) { |
||||
await this.addOrEditColumn.locator('.ant-select-selector > .ant-select-selection-item').click(); |
||||
|
||||
await this.addOrEditColumn.locator('.ant-select-selection-search-input[aria-expanded="true"]').waitFor(); |
||||
await this.addOrEditColumn.locator('.ant-select-selection-search-input[aria-expanded="true"]').fill(type); |
||||
|
||||
// Select column type
|
||||
await this.rootPage.locator('.rc-virtual-list-holder-inner > div').locator(`text="${type}"`).click(); |
||||
} |
||||
|
||||
async saveChanges() { |
||||
await this.waitForResponse({ |
||||
uiAction: async () => await this.saveChangesButton.click(), |
||||
requestUrlPathToMatch: 'api/v1/db/meta/views/', |
||||
httpMethodsToMatch: ['GET'], |
||||
responseJsonMatcher: json => json['list'], |
||||
}); |
||||
await this.rootPage.waitForTimeout(200); |
||||
} |
||||
|
||||
getField({ title }: { title: string }) { |
||||
return this.fieldListWrapper.getByTestId(`nc-field-item-${title}`); |
||||
} |
||||
|
||||
async getFieldVisibilityCheckbox({ title }: { title: string }) { |
||||
return this.getField({ title }).getByTestId('nc-field-visibility-checkbox'); |
||||
} |
||||
|
||||
async selectFieldAction({ |
||||
title, |
||||
action, |
||||
isDisplayValueField = false, |
||||
}: { |
||||
title: string; |
||||
action: 'copy-id' | 'duplicate' | 'insert-above' | 'insert-below' | 'delete'; |
||||
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' }); |
||||
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; |
||||
} |
||||
} |
@ -0,0 +1,380 @@
|
||||
import { expect, test } from '@playwright/test'; |
||||
import { DashboardPage } from '../../../pages/Dashboard'; |
||||
import setup, { unsetup } from '../../../setup'; |
||||
import { FieldsPage } from '../../../pages/Dashboard/Details/FieldsPage'; |
||||
import { getTextExcludeIconText } from '../../utils/general'; |
||||
import { UITypes } from 'nocodb-sdk'; |
||||
|
||||
const allFieldList = [ |
||||
{ |
||||
title: 'Single Line Text', |
||||
type: UITypes.SingleLineText, |
||||
}, |
||||
{ |
||||
title: 'Long Text', |
||||
type: UITypes.LongText, |
||||
}, |
||||
{ |
||||
title: 'Number', |
||||
type: UITypes.Number, |
||||
}, |
||||
{ |
||||
title: 'Decimal', |
||||
type: UITypes.Decimal, |
||||
}, |
||||
{ |
||||
title: 'Attachment', |
||||
type: UITypes.Attachment, |
||||
}, |
||||
{ |
||||
title: 'Checkbox', |
||||
type: UITypes.Checkbox, |
||||
}, |
||||
{ |
||||
title: 'MultiSelect', |
||||
type: UITypes.MultiSelect, |
||||
}, |
||||
{ |
||||
title: 'SingleSelect', |
||||
type: UITypes.SingleSelect, |
||||
}, |
||||
{ |
||||
title: 'Date', |
||||
type: UITypes.Date, |
||||
}, |
||||
{ |
||||
title: 'DateTime', |
||||
type: UITypes.DateTime, |
||||
}, |
||||
{ |
||||
title: 'Year', |
||||
type: UITypes.Year, |
||||
}, |
||||
{ |
||||
title: 'Time', |
||||
type: UITypes.Time, |
||||
}, |
||||
{ |
||||
title: 'PhoneNumber', |
||||
type: UITypes.PhoneNumber, |
||||
}, |
||||
{ |
||||
title: 'Email', |
||||
type: UITypes.Email, |
||||
}, |
||||
{ |
||||
title: 'URL', |
||||
type: UITypes.URL, |
||||
}, |
||||
{ |
||||
title: 'Currency', |
||||
type: UITypes.Currency, |
||||
}, |
||||
{ |
||||
title: 'Percent', |
||||
type: UITypes.Percent, |
||||
}, |
||||
{ |
||||
title: 'Duration', |
||||
type: UITypes.Duration, |
||||
}, |
||||
{ |
||||
title: 'Rating', |
||||
type: UITypes.Rating, |
||||
}, |
||||
{ |
||||
title: 'Formula', |
||||
type: UITypes.Formula, |
||||
formula: 'LEN({Title})', |
||||
}, |
||||
{ |
||||
title: 'QrCode', |
||||
type: UITypes.QrCode, |
||||
qrCodeValueColumnTitle: 'Title', |
||||
}, |
||||
{ |
||||
title: 'Barcode', |
||||
type: UITypes.Barcode, |
||||
barcodeValueColumnTitle: 'Title', |
||||
}, |
||||
{ |
||||
title: 'Geometry', |
||||
type: UITypes.Geometry, |
||||
}, |
||||
{ |
||||
title: 'JSON', |
||||
type: UITypes.JSON, |
||||
}, |
||||
{ |
||||
title: 'User', |
||||
type: UITypes.User, |
||||
}, |
||||
{ |
||||
title: 'Links', |
||||
type: UITypes.Links, |
||||
relationType: 'Has Many', |
||||
childTable: 'Multifield', |
||||
}, |
||||
]; |
||||
|
||||
test.describe('Multi Field Editor', () => { |
||||
let dashboard: DashboardPage, fields: FieldsPage; |
||||
let context: any; |
||||
const defaultFieldName = 'Multi Field Editor'; |
||||
|
||||
test.beforeEach(async ({ page }) => { |
||||
context = await setup({ page, isEmptyProject: true }); |
||||
dashboard = new DashboardPage(page, context.base); |
||||
fields = dashboard.details.fields; |
||||
|
||||
await dashboard.treeView.createTable({ title: 'Multifield', baseTitle: context.base.title }); |
||||
await openMultiFieldOfATable(); |
||||
}); |
||||
|
||||
test.afterEach(async () => { |
||||
await unsetup(context); |
||||
}); |
||||
|
||||
async function openMultiFieldOfATable() { |
||||
await dashboard.grid.topbar.openDetailedTab(); |
||||
await dashboard.details.clickFieldsTab(); |
||||
} |
||||
|
||||
async function toggleShowSystemFieldsFromDataTab() { |
||||
await dashboard.grid.topbar.openDataTab(); |
||||
await dashboard.grid.toolbar.fields.toggleShowSystemFields(); |
||||
await openMultiFieldOfATable(); |
||||
} |
||||
|
||||
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(); |
||||
}; |
||||
|
||||
const searchAndVerifyFields = async ({ searchQuery, fieldList }: { searchQuery: string; fieldList: string[] }) => { |
||||
await fields.searchFieldInput.fill(searchQuery); |
||||
|
||||
const allFields = await fields.getAllFieldText(); |
||||
expect(allFields).toEqual( |
||||
searchQuery ? fieldList.filter(field => field.toLowerCase().includes(searchQuery.toLowerCase())) : fieldList |
||||
); |
||||
}; |
||||
|
||||
test('Verify system fields are not listed, Add New field, update & Restore, reset', async () => { |
||||
//Verify system fields are not listed
|
||||
await toggleShowSystemFieldsFromDataTab(); |
||||
let fieldsText = await fields.getAllFieldText(); |
||||
expect(fieldsText.length).toBe(1); |
||||
await toggleShowSystemFieldsFromDataTab(); |
||||
|
||||
// Add New Field
|
||||
await fields.createOrUpdate({ title: 'Name', saveChanges: false }); |
||||
await expect(fields.getField({ title: 'Name' })).toContainText('New field'); |
||||
await fields.saveChanges(); |
||||
|
||||
// Update Field title
|
||||
await fields.getField({ title: 'Name' }).click(); |
||||
await fields.createOrUpdate({ title: 'Updated Name', saveChanges: false, isUpdateMode: true }); |
||||
await expect(fields.getField({ title: 'Updated Name' })).toContainText('Updated field'); |
||||
await fields.saveChanges(); |
||||
|
||||
// Update and restore field changes
|
||||
await fields.getField({ title: 'Updated Name' }).click(); |
||||
await fields.createOrUpdate({ title: 'Updated Name to restore', saveChanges: false, isUpdateMode: true }); |
||||
await fields.clickRestoreField({ title: 'Updated Name to restore' }); |
||||
|
||||
// verify grid column header
|
||||
fieldsText = await fields.getAllFieldText(); |
||||
expect(fieldsText).toEqual(['Title', 'Updated Name']); |
||||
await verifyGridColumnHeaders({ fields: fieldsText }); |
||||
|
||||
// add new fields then reset changes and verify
|
||||
await fields.createOrUpdate({ title: 'field to reset', saveChanges: false }); |
||||
await fields.createOrUpdate({ title: 'Random', saveChanges: false }); |
||||
await fields.resetFieldChangesButton.click(); |
||||
|
||||
// verify with old fields
|
||||
await verifyGridColumnHeaders({ fields: fieldsText }); |
||||
}); |
||||
|
||||
// Todo: remove `skip`, if `optimized dependencies changed. reloading` issue is fixed
|
||||
test.skip('Add all fields and check status on clicking each field', async () => { |
||||
// Add all fields, verify status and save
|
||||
for (const field of allFieldList) { |
||||
await fields.createOrUpdate({ ...field, saveChanges: false }); |
||||
await expect(fields.getField({ title: field.title })).toContainText('New field'); |
||||
await fields.saveChanges(); |
||||
} |
||||
let fieldsText = await fields.getAllFieldText(); |
||||
|
||||
// verify all newly added field and its order
|
||||
expect(fieldsText).toEqual(['Title', ...allFieldList.map(field => field.title)]); |
||||
|
||||
// click on each field and check status
|
||||
fieldsText = await fields.getAllFieldText(); |
||||
for (const title of fieldsText) { |
||||
await fields.getField({ title }).click(); |
||||
await expect(fields.getField({ title })).not.toContainText(['New field', 'Updated field']); |
||||
} |
||||
}); |
||||
|
||||
test('Field operations: CopyId, Duplicate, InsertAbove, InsertBelow, Delete, Hide', async () => { |
||||
// Add New Field
|
||||
await fields.createOrUpdate({ title: defaultFieldName }); |
||||
|
||||
// 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 expect(fields.getField({ title: `${defaultFieldName}_copy` })).toContainText('Deleted field'); |
||||
|
||||
await fields.saveChanges(); |
||||
|
||||
fieldsText = await fields.getAllFieldText(); |
||||
expect(!fieldsText.includes(`${defaultFieldName}_copy`)).toBeTruthy(); |
||||
|
||||
// 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) }); |
||||
}); |
||||
|
||||
test('Search field and verify', async () => { |
||||
const fieldList = ['Single Line Text', 'Long text', 'Rich text', 'Number', 'Percentage']; |
||||
|
||||
for (const field of fieldList) { |
||||
await fields.createOrUpdate({ title: field, saveChanges: false }); |
||||
} |
||||
await fields.saveChanges(); |
||||
|
||||
let searchQuery = 'text'; |
||||
await searchAndVerifyFields({ |
||||
searchQuery, |
||||
fieldList, |
||||
}); |
||||
|
||||
searchQuery = 'Rich text'; |
||||
await searchAndVerifyFields({ |
||||
searchQuery, |
||||
fieldList: ['Title', ...fieldList], |
||||
}); |
||||
|
||||
// clear search and verify
|
||||
await fields.clearSearch(); |
||||
await searchAndVerifyFields({ |
||||
searchQuery: '', |
||||
fieldList: ['Title', ...fieldList], |
||||
}); |
||||
}); |
||||
|
||||
test('Field Reorder and verify', async () => { |
||||
// default order: ['Title', 'Single Line Text', 'Long Text', 'Number', 'Percent','Links']
|
||||
const fieldList = [ |
||||
{ |
||||
title: 'Single Line Text', |
||||
type: UITypes.SingleLineText, |
||||
}, |
||||
{ |
||||
title: 'Long Text', |
||||
type: UITypes.LongText, |
||||
}, |
||||
{ |
||||
title: 'Number', |
||||
type: UITypes.Number, |
||||
}, |
||||
{ |
||||
title: 'Percent', |
||||
type: UITypes.Percent, |
||||
}, |
||||
{ |
||||
title: 'Links', |
||||
type: UITypes.Links, |
||||
relationType: 'Has Many', |
||||
childTable: 'Multifield', |
||||
}, |
||||
]; |
||||
|
||||
for (const field of fieldList) { |
||||
await fields.createOrUpdate({ ...field, saveChanges: false }); |
||||
} |
||||
await fields.saveChanges(); |
||||
// updated order : ['Title', 'Long Text','Single Line Text', 'Number', 'Percent','Links']
|
||||
await fields.getField({ title: fieldList[0].title }).dragTo(fields.getField({ title: fieldList[1].title })); |
||||
await expect(fields.getField({ title: fieldList[0].title })).toContainText('Updated field'); |
||||
|
||||
// updated order : ['Title', 'Long Text','Single Line Text', 'Number','Links', 'Percent']
|
||||
await fields.getField({ title: fieldList[4].title }).dragTo(fields.getField({ title: fieldList[3].title })); |
||||
await expect(fields.getField({ title: fieldList[4].title })).toContainText('Updated field'); |
||||
|
||||
await fields.saveChanges(); |
||||
const fieldsText = await fields.getAllFieldText(); |
||||
const expectedFieldText = ['Title', 'Long Text', 'Single Line Text', 'Number', 'Links', 'Percent']; |
||||
|
||||
expect(fieldsText).toEqual(expectedFieldText); |
||||
|
||||
await verifyGridColumnHeaders({ fields: expectedFieldText }); |
||||
}); |
||||
|
||||
test('Keyboard shortcuts: add new field, save and delete', async () => { |
||||
// add new field
|
||||
await dashboard.rootPage.keyboard.press('Alt+C'); |
||||
|
||||
// verify field is added and has `New field` status
|
||||
let fieldsText = await fields.getAllFieldText(); |
||||
await expect(fields.getField({ title: fieldsText[fieldsText.length - 1] })).toContainText('New field'); |
||||
|
||||
// update title
|
||||
await fields.createOrUpdate({ title: defaultFieldName, isUpdateMode: true }); |
||||
|
||||
// save the changes
|
||||
await dashboard.rootPage.keyboard.press((await dashboard.isMacOs()) ? 'Meta+S' : 'Control+S'); |
||||
await dashboard.rootPage.waitForTimeout(500); |
||||
|
||||
// verify result
|
||||
fieldsText = await fields.getAllFieldText(); |
||||
expect(fieldsText).toEqual(['Title', defaultFieldName]); |
||||
|
||||
// delete field
|
||||
await fields.getField({ title: defaultFieldName }).click(); |
||||
await dashboard.rootPage.keyboard.press((await dashboard.isMacOs()) ? 'Meta+Delete' : 'Delete'); |
||||
await expect(fields.getField({ title: defaultFieldName })).toContainText('Deleted field'); |
||||
|
||||
// save the changes
|
||||
await dashboard.rootPage.keyboard.press((await dashboard.isMacOs()) ? 'Meta+S' : 'Control+S'); |
||||
await dashboard.rootPage.waitForTimeout(500); |
||||
|
||||
fieldsText = await fields.getAllFieldText(); |
||||
expect(fieldsText).toEqual(['Title']); |
||||
}); |
||||
}); |
Loading…
Reference in new issue