|
|
|
@ -1,18 +1,40 @@
|
|
|
|
|
import { expect, Page, test } from '@playwright/test'; |
|
|
|
|
import { DashboardPage } from '../pages/Dashboard'; |
|
|
|
|
import setup from '../setup'; |
|
|
|
|
import { ToolbarPage } from '../pages/Dashboard/common/Toolbar'; |
|
|
|
|
import { Api, UITypes } from 'nocodb-sdk'; |
|
|
|
|
import { rowMixedValue } from '../setup/xcdb-records'; |
|
|
|
|
import { GridPage } from '../pages/Dashboard/Grid'; |
|
|
|
|
|
|
|
|
|
let dashboard: DashboardPage, grid: GridPage, context: any, api: Api<any>, records: Record<string, any>, table: any; |
|
|
|
|
let dashboard: DashboardPage, |
|
|
|
|
grid: GridPage, |
|
|
|
|
context: any, |
|
|
|
|
api: Api<any>, |
|
|
|
|
records: Record<string, any>, |
|
|
|
|
table: any, |
|
|
|
|
cityTable: any, |
|
|
|
|
countryTable: any; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
This change provides undo/redo on multiple actions over UI. |
|
|
|
|
|
|
|
|
|
Scope Actions |
|
|
|
|
------------------------------ |
|
|
|
|
Row Create, Update, Delete |
|
|
|
|
LTAR Link, Unlink |
|
|
|
|
Fields Show/hide, Reorder |
|
|
|
|
Sort Add, Update, Delete |
|
|
|
|
Filters Add, Update, Delete (Excluding Filter Groups) |
|
|
|
|
Row Height Update |
|
|
|
|
Column width Update |
|
|
|
|
View Rename |
|
|
|
|
Table Rename |
|
|
|
|
|
|
|
|
|
**/ |
|
|
|
|
|
|
|
|
|
test.describe('Undo Redo', () => { |
|
|
|
|
test.beforeEach(async ({ page }) => { |
|
|
|
|
context = await setup({ page, isEmptyProject: true }); |
|
|
|
|
dashboard = new DashboardPage(page, context.project); |
|
|
|
|
const toolbar: ToolbarPage = dashboard.grid.toolbar; |
|
|
|
|
grid = dashboard.grid; |
|
|
|
|
|
|
|
|
|
api = new Api({ |
|
|
|
@ -93,23 +115,6 @@ test.describe('Undo Redo', () => {
|
|
|
|
|
await verifyRecords(values); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
This change provides undo/redo on multiple actions over UI. |
|
|
|
|
|
|
|
|
|
Scope Actions |
|
|
|
|
------------------------------ |
|
|
|
|
Row Create, Update, Delete |
|
|
|
|
LTAR Link, Unlink |
|
|
|
|
Fields Show/hide, Reorder |
|
|
|
|
Sort Add, Update, Delete |
|
|
|
|
Filters Add, Update, Delete (Excluding Filter Groups) |
|
|
|
|
Row Height Update |
|
|
|
|
Column width Update |
|
|
|
|
View Rename |
|
|
|
|
Table Rename |
|
|
|
|
|
|
|
|
|
**/ |
|
|
|
|
|
|
|
|
|
test('Row: Create, Update, Delete', async ({ page }) => { |
|
|
|
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
|
|
|
|
await dashboard.treeView.openTable({ title: 'numberBased' }); |
|
|
|
@ -140,7 +145,135 @@ test.describe('Undo Redo', () => {
|
|
|
|
|
// Undo : Row.Create
|
|
|
|
|
await undo({ page, values: [333] }); |
|
|
|
|
await undo({ page, values: [] }); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
test.describe('Undo Redo - 2', () => { |
|
|
|
|
test.beforeEach(async ({ page }) => { |
|
|
|
|
context = await setup({ page, isEmptyProject: true }); |
|
|
|
|
dashboard = new DashboardPage(page, context.project); |
|
|
|
|
grid = dashboard.grid; |
|
|
|
|
|
|
|
|
|
api = new Api({ |
|
|
|
|
baseURL: `http://localhost:8080/`, |
|
|
|
|
headers: { |
|
|
|
|
'xc-auth': context.token, |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
console.log('records', records); |
|
|
|
|
const cityColumns = [ |
|
|
|
|
{ |
|
|
|
|
column_name: 'Id', |
|
|
|
|
title: 'Id', |
|
|
|
|
uidt: UITypes.ID, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
column_name: 'City', |
|
|
|
|
title: 'City', |
|
|
|
|
uidt: UITypes.SingleLineText, |
|
|
|
|
pv: true, |
|
|
|
|
}, |
|
|
|
|
]; |
|
|
|
|
const countryColumns = [ |
|
|
|
|
{ |
|
|
|
|
column_name: 'Id', |
|
|
|
|
title: 'Id', |
|
|
|
|
uidt: UITypes.ID, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
column_name: 'Country', |
|
|
|
|
title: 'Country', |
|
|
|
|
uidt: UITypes.SingleLineText, |
|
|
|
|
pv: true, |
|
|
|
|
}, |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
const project = await api.project.read(context.project.id); |
|
|
|
|
cityTable = await api.base.tableCreate(context.project.id, project.bases?.[0].id, { |
|
|
|
|
table_name: 'City', |
|
|
|
|
title: 'City', |
|
|
|
|
columns: cityColumns, |
|
|
|
|
}); |
|
|
|
|
countryTable = await api.base.tableCreate(context.project.id, project.bases?.[0].id, { |
|
|
|
|
table_name: 'Country', |
|
|
|
|
title: 'Country', |
|
|
|
|
columns: countryColumns, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const cityRowAttributes = [{ City: 'Mumbai' }, { City: 'Pune' }, { City: 'Delhi' }, { City: 'Bangalore' }]; |
|
|
|
|
await api.dbTableRow.bulkCreate('noco', context.project.id, cityTable.id, cityRowAttributes); |
|
|
|
|
|
|
|
|
|
const countryRowAttributes = [ |
|
|
|
|
{ Country: 'India' }, |
|
|
|
|
{ Country: 'USA' }, |
|
|
|
|
{ Country: 'UK' }, |
|
|
|
|
{ Country: 'Australia' }, |
|
|
|
|
]; |
|
|
|
|
await api.dbTableRow.bulkCreate('noco', context.project.id, countryTable.id, countryRowAttributes); |
|
|
|
|
|
|
|
|
|
// create LTAR Country has-many City
|
|
|
|
|
await api.dbTableColumn.create(countryTable.id, { |
|
|
|
|
column_name: 'CityList', |
|
|
|
|
title: 'CityList', |
|
|
|
|
uidt: UITypes.LinkToAnotherRecord, |
|
|
|
|
parentId: countryTable.id, |
|
|
|
|
childId: cityTable.id, |
|
|
|
|
type: 'hm', |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// await api.dbTableRow.nestedAdd('noco', context.project.id, countryTable.id, '1', 'hm', 'CityList', '1');
|
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
async function verifyRecords(values: any[] = []) { |
|
|
|
|
// inserted values
|
|
|
|
|
const expectedValues = [...values]; |
|
|
|
|
|
|
|
|
|
const currentRecords: Record<string, any> = await api.dbTableRow.list('noco', context.project.id, countryTable.id, { |
|
|
|
|
fields: ['CityList'], |
|
|
|
|
limit: 100, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// verify if expectedValues array includes all the values in currentRecords
|
|
|
|
|
// currentRecords [ { Id: 1, City: 'Mumbai' }, { Id: 3, City: 'Delhi' } ]
|
|
|
|
|
// expectedValues [ 'Mumbai', 'Delhi' ]
|
|
|
|
|
currentRecords.list[0].CityList.forEach((record: any) => { |
|
|
|
|
expect(expectedValues).toContain(record.City); |
|
|
|
|
}); |
|
|
|
|
expect(currentRecords.list[0].CityList.length).toBe(expectedValues.length); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function undo({ page, values }: { page: Page; values: string[] }) { |
|
|
|
|
const isMac = await grid.isMacOs(); |
|
|
|
|
await dashboard.grid.waitForResponse({ |
|
|
|
|
uiAction: () => page.keyboard.press(isMac ? 'Meta+z' : 'Control+z'), |
|
|
|
|
httpMethodsToMatch: ['GET'], |
|
|
|
|
requestUrlPathToMatch: `/api/v1/db/data/noco/`, |
|
|
|
|
responseJsonMatcher: json => json.pageInfo, |
|
|
|
|
}); |
|
|
|
|
await verifyRecords(values); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
test('Row: Link, Unlink', async ({ page }) => { |
|
|
|
|
await dashboard.closeTab({ title: 'Team & Auth' }); |
|
|
|
|
await dashboard.treeView.openTable({ title: 'Country' }); |
|
|
|
|
|
|
|
|
|
await grid.cell.inCellAdd({ index: 0, columnHeader: 'CityList' }); |
|
|
|
|
await dashboard.linkRecord.select('Mumbai'); |
|
|
|
|
|
|
|
|
|
await grid.cell.inCellAdd({ index: 0, columnHeader: 'CityList' }); |
|
|
|
|
await dashboard.linkRecord.select('Delhi'); |
|
|
|
|
|
|
|
|
|
await grid.cell.unlinkVirtualCell({ index: 0, columnHeader: 'CityList' }); |
|
|
|
|
await grid.cell.unlinkVirtualCell({ index: 0, columnHeader: 'CityList' }); |
|
|
|
|
|
|
|
|
|
await verifyRecords([]); |
|
|
|
|
await undo({ page, values: ['Delhi'] }); |
|
|
|
|
await undo({ page, values: ['Mumbai', 'Delhi'] }); |
|
|
|
|
await undo({ page, values: ['Mumbai'] }); |
|
|
|
|
await undo({ page, values: [] }); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|