mirror of https://github.com/nocodb/nocodb
Browse Source
Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>test/pw-duplicate-check
Raju Udava
1 year ago
5 changed files with 237 additions and 1 deletions
@ -0,0 +1,143 @@ |
|||||||
|
import { expect, Locator } from '@playwright/test'; |
||||||
|
import BasePage from '../../Base'; |
||||||
|
import { DashboardPage } from '..'; |
||||||
|
import { DateTimeCellPageObject } from '../common/Cell/DateTimeCell'; |
||||||
|
import { getTextExcludeIconText } from '../../../tests/utils/general'; |
||||||
|
|
||||||
|
export class BulkUpdatePage extends BasePage { |
||||||
|
readonly dashboard: DashboardPage; |
||||||
|
readonly bulkUpdateButton: Locator; |
||||||
|
readonly formHeader: Locator; |
||||||
|
readonly columnsDrawer: Locator; |
||||||
|
readonly form: Locator; |
||||||
|
|
||||||
|
constructor(dashboard: DashboardPage) { |
||||||
|
super(dashboard.rootPage); |
||||||
|
this.dashboard = dashboard; |
||||||
|
this.bulkUpdateButton = this.dashboard.get().locator('.nc-bulk-update-save-btn'); |
||||||
|
this.formHeader = this.dashboard.get().locator('.nc-bulk-update-form-header'); |
||||||
|
this.columnsDrawer = this.dashboard.get().locator('.nc-columns-drawer'); |
||||||
|
this.form = this.dashboard.get().locator('div.form'); |
||||||
|
} |
||||||
|
|
||||||
|
get() { |
||||||
|
return this.dashboard.get().locator(`.nc-drawer-bulk-update`); |
||||||
|
} |
||||||
|
|
||||||
|
async close() { |
||||||
|
return this.dashboard.rootPage.keyboard.press('Escape'); |
||||||
|
} |
||||||
|
|
||||||
|
async getInactiveColumn(index: number) { |
||||||
|
const inactiveColumns = await this.columnsDrawer.locator('.ant-card'); |
||||||
|
return inactiveColumns.nth(index); |
||||||
|
} |
||||||
|
|
||||||
|
async getActiveColumn(index: number) { |
||||||
|
const activeColumns = await this.form.locator('[data-testid="nc-form-fields"]'); |
||||||
|
return activeColumns.nth(index); |
||||||
|
} |
||||||
|
|
||||||
|
async getInactiveColumns() { |
||||||
|
const inactiveColumns = await this.columnsDrawer.locator('.ant-card'); |
||||||
|
const inactiveColumnsCount = await inactiveColumns.count(); |
||||||
|
const inactiveColumnsTitles = []; |
||||||
|
// get title for each inactive column
|
||||||
|
for (let i = 0; i < inactiveColumnsCount; i++) { |
||||||
|
const title = await getTextExcludeIconText(inactiveColumns.nth(i).locator('.ant-card-body')); |
||||||
|
inactiveColumnsTitles.push(title); |
||||||
|
} |
||||||
|
|
||||||
|
return inactiveColumnsTitles; |
||||||
|
} |
||||||
|
|
||||||
|
async getActiveColumns() { |
||||||
|
const activeColumns = await this.form.locator('[data-testid="nc-form-fields"]'); |
||||||
|
const activeColumnsCount = await activeColumns.count(); |
||||||
|
const activeColumnsTitles = []; |
||||||
|
// get title for each active column
|
||||||
|
for (let i = 0; i < activeColumnsCount; i++) { |
||||||
|
const title = await getTextExcludeIconText(activeColumns.nth(i).locator('[data-testid="nc-form-input-label"]')); |
||||||
|
activeColumnsTitles.push(title); |
||||||
|
} |
||||||
|
|
||||||
|
return activeColumnsTitles; |
||||||
|
} |
||||||
|
|
||||||
|
async removeField(index: number) { |
||||||
|
const removeFieldButton = await this.form.locator('[data-testid="nc-form-fields"]'); |
||||||
|
const removeFieldButtonCount = await removeFieldButton.count(); |
||||||
|
await removeFieldButton.nth(index).locator('[data-testid="nc-form-fields-close-icon"]').click(); |
||||||
|
const newRemoveFieldButtonCount = await removeFieldButton.count(); |
||||||
|
expect(newRemoveFieldButtonCount).toBe(removeFieldButtonCount - 1); |
||||||
|
} |
||||||
|
|
||||||
|
async addField(index: number) { |
||||||
|
const addFieldButton = await this.columnsDrawer.locator('.ant-card'); |
||||||
|
const addFieldButtonCount = await addFieldButton.count(); |
||||||
|
await addFieldButton.nth(index).click(); |
||||||
|
const newAddFieldButtonCount = await addFieldButton.count(); |
||||||
|
expect(newAddFieldButtonCount).toBe(addFieldButtonCount - 1); |
||||||
|
} |
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
async fillField({ columnTitle, value, type = 'text' }: { columnTitle: string; value: string; type?: string }) { |
||||||
|
const field = this.form.locator(`[data-testid="nc-form-input-${columnTitle}"]`); |
||||||
|
await field.hover(); |
||||||
|
switch (type) { |
||||||
|
case 'text': |
||||||
|
await field.locator('input').fill(value); |
||||||
|
break; |
||||||
|
case 'geodata': { |
||||||
|
const [lat, long] = value.split(','); |
||||||
|
await this.rootPage.locator(`[data-testid="nc-geo-data-set-location-button"]`).click(); |
||||||
|
await this.rootPage.locator(`[data-testid="nc-geo-data-latitude"]`).fill(lat); |
||||||
|
await this.rootPage.locator(`[data-testid="nc-geo-data-longitude"]`).fill(long); |
||||||
|
await this.rootPage.locator(`[data-testid="nc-geo-data-save"]`).click(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 'belongsTo': |
||||||
|
await field.locator('.nc-action-icon').click(); |
||||||
|
await this.dashboard.linkRecord.select(value); |
||||||
|
break; |
||||||
|
case 'hasMany': |
||||||
|
case 'manyToMany': |
||||||
|
await field.locator(`[data-testid="nc-child-list-button-link-to"]`).click(); |
||||||
|
await this.dashboard.linkRecord.select(value); |
||||||
|
break; |
||||||
|
case 'dateTime': |
||||||
|
await field.locator('.nc-cell').click(); |
||||||
|
// eslint-disable-next-line no-case-declarations
|
||||||
|
const dateTimeObj = new DateTimeCellPageObject(this.dashboard.grid.cell); |
||||||
|
await dateTimeObj.selectDate({ date: value.slice(0, 10) }); |
||||||
|
await dateTimeObj.selectTime({ hour: +value.slice(11, 13), minute: +value.slice(14, 16) }); |
||||||
|
await dateTimeObj.save(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
async save({ |
||||||
|
awaitResponse = true, |
||||||
|
}: { |
||||||
|
awaitResponse?: boolean; |
||||||
|
} = {}) { |
||||||
|
await this.bulkUpdateButton.click(); |
||||||
|
const confirmModal = await this.rootPage.locator('.ant-modal-confirm'); |
||||||
|
|
||||||
|
const saveRowAction = () => confirmModal.locator('.ant-btn-primary').click(); |
||||||
|
if (!awaitResponse) { |
||||||
|
await saveRowAction(); |
||||||
|
} else { |
||||||
|
await this.waitForResponse({ |
||||||
|
uiAction: saveRowAction, |
||||||
|
requestUrlPathToMatch: 'api/v1/db/data/noco/', |
||||||
|
httpMethodsToMatch: ['GET'], |
||||||
|
responseJsonMatcher: json => json['pageInfo'], |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
await this.get().waitFor({ state: 'hidden' }); |
||||||
|
await this.rootPage.locator('[data-testid="grid-load-spinner"]').waitFor({ state: 'hidden' }); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
import { expect, test } from '@playwright/test'; |
||||||
|
import setup from '../../setup'; |
||||||
|
import { DashboardPage } from '../../pages/Dashboard'; |
||||||
|
import { Api } from 'nocodb-sdk'; |
||||||
|
import { createDemoTable } from '../../setup/demoTable'; |
||||||
|
import { BulkUpdatePage } from '../../pages/Dashboard/BulkUpdate'; |
||||||
|
|
||||||
|
test.describe('Bulk update', () => { |
||||||
|
let dashboard: DashboardPage; |
||||||
|
let bulkUpdateForm: BulkUpdatePage; |
||||||
|
let context: any; |
||||||
|
let api: Api<any>; |
||||||
|
let records: any[]; |
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => { |
||||||
|
context = await setup({ page, isEmptyProject: true }); |
||||||
|
dashboard = new DashboardPage(page, context.project); |
||||||
|
bulkUpdateForm = dashboard.bulkUpdateForm; |
||||||
|
|
||||||
|
api = new Api({ |
||||||
|
baseURL: `http://localhost:8080/`, |
||||||
|
headers: { |
||||||
|
'xc-auth': context.token, |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
const table = await createDemoTable({ context, type: 'textBased', recordCnt: 50 }); |
||||||
|
records = await api.dbTableRow.list('noco', context.project.id, table.id, { limit: 50 }); |
||||||
|
await page.reload(); |
||||||
|
|
||||||
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
||||||
|
await dashboard.treeView.openTable({ title: 'textBased' }); |
||||||
|
|
||||||
|
// Open bulk update form
|
||||||
|
await dashboard.grid.updateAll(); |
||||||
|
}); |
||||||
|
|
||||||
|
test('General- Click to add & remove', async () => { |
||||||
|
let inactiveColumns = await bulkUpdateForm.getInactiveColumns(); |
||||||
|
expect(inactiveColumns).toEqual(['SingleLineText', 'MultiLineText', 'Email', 'PhoneNumber', 'URL']); |
||||||
|
|
||||||
|
let activeColumns = await bulkUpdateForm.getActiveColumns(); |
||||||
|
expect(activeColumns).toEqual([]); |
||||||
|
|
||||||
|
await bulkUpdateForm.addField(0); |
||||||
|
await bulkUpdateForm.addField(0); |
||||||
|
|
||||||
|
inactiveColumns = await bulkUpdateForm.getInactiveColumns(); |
||||||
|
expect(inactiveColumns).toEqual(['Email', 'PhoneNumber', 'URL']); |
||||||
|
|
||||||
|
activeColumns = await bulkUpdateForm.getActiveColumns(); |
||||||
|
expect(activeColumns).toEqual(['SingleLineText', 'MultiLineText']); |
||||||
|
}); |
||||||
|
|
||||||
|
test('General- Drag drop', async () => { |
||||||
|
const src = await bulkUpdateForm.getInactiveColumn(0); |
||||||
|
const dst = await bulkUpdateForm.form; |
||||||
|
|
||||||
|
await src.dragTo(dst); |
||||||
|
expect(await bulkUpdateForm.getActiveColumns()).toEqual(['SingleLineText']); |
||||||
|
expect(await bulkUpdateForm.getInactiveColumns()).toEqual(['MultiLineText', 'Email', 'PhoneNumber', 'URL']); |
||||||
|
|
||||||
|
const src2 = await bulkUpdateForm.getActiveColumn(0); |
||||||
|
const dst2 = await bulkUpdateForm.columnsDrawer; |
||||||
|
|
||||||
|
await src2.dragTo(dst2); |
||||||
|
expect(await bulkUpdateForm.getActiveColumns()).toEqual([]); |
||||||
|
expect(await bulkUpdateForm.getInactiveColumns()).toEqual([ |
||||||
|
'SingleLineText', |
||||||
|
'MultiLineText', |
||||||
|
'Email', |
||||||
|
'PhoneNumber', |
||||||
|
'URL', |
||||||
|
]); |
||||||
|
}); |
||||||
|
}); |
Loading…
Reference in new issue