Browse Source

test: unit test for calendar view

pull/7611/head
DarkPhoenix2704 7 months ago
parent
commit
8b1239ae39
  1. 11
      packages/nocodb/tests/unit/factory/view.ts
  2. 274
      packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

11
packages/nocodb/tests/unit/factory/view.ts

@ -9,10 +9,15 @@ const createView = async (
title, title,
table, table,
type, type,
range,
}: { }: {
title: string; title: string;
table: Model; table: Model;
type: ViewTypes; type: ViewTypes;
range?: {
fk_from_column_id?: string;
fk_to_column_id?: string;
};
}, },
) => { ) => {
const viewTypeStr = (type) => { const viewTypeStr = (type) => {
@ -25,6 +30,8 @@ const createView = async (
return 'grids'; return 'grids';
case ViewTypes.KANBAN: case ViewTypes.KANBAN:
return 'kanbans'; return 'kanbans';
case ViewTypes.CALENDAR:
return 'calendars';
default: default:
throw new Error('Invalid view type'); throw new Error('Invalid view type');
} }
@ -36,16 +43,16 @@ const createView = async (
.send({ .send({
title, title,
type, type,
...(range?.fk_from_column_id ? { calendar_range: [range] } : {}),
}); });
if (response.status !== 200) { if (response.status !== 200) {
throw new Error('createView', response.body.message); throw new Error('createView', response.body.message);
} }
const view = (await View.getByTitleOrId({ return (await View.getByTitleOrId({
fk_model_id: table.id, fk_model_id: table.id,
titleOrId: title, titleOrId: title,
})) as View; })) as View;
return view;
}; };
const getView = async ( const getView = async (

274
packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

@ -43,9 +43,12 @@ let sakilaProject: Base;
// models // models
let customerTable: Model; let customerTable: Model;
let filmTable: Model; let filmTable: Model;
let rentalTable: Model;
// columns // columns
let customerColumns; let customerColumns;
let filmColumns; let filmColumns;
let rentalColumns;
// views // views
let customerGridView: View; let customerGridView: View;
let customerGalleryView: View; let customerGalleryView: View;
@ -53,6 +56,9 @@ let customerFormView: View;
// use film table because it has single select field // use film table because it has single select field
let filmKanbanView: View; let filmKanbanView: View;
// Use rental table because it has a date field
let rentalCalendarView: View;
const testGetViewRowList = async (view: View) => { const testGetViewRowList = async (view: View) => {
const response = await request(context.app) const response = await request(context.app)
.get( .get(
@ -95,6 +101,21 @@ const testGetViewRowListKanban = async (view: View) => {
.and.to.be.a('number'); .and.to.be.a('number');
}; };
const testGetViewListCalendar = async (view: View) => {
const response = await request(context.app)
.get(
`/api/v1/db/data/noco/${sakilaProject.id}/${rentalTable.id}/views/${view.id}`,
)
.set('xc-auth', context.token)
.expect(200);
const pageInfo = response.body.pageInfo;
if (pageInfo.totalRows !== 16044 && response.body.list.length !== 16044) {
throw new Error('Calendar View row list is not correct');
}
};
function viewRowStaticTests() { function viewRowStaticTests() {
before(async function () { before(async function () {
console.time('#### viewRowTests'); console.time('#### viewRowTests');
@ -132,6 +153,24 @@ function viewRowStaticTests() {
table: filmTable, table: filmTable,
type: ViewTypes.KANBAN, type: ViewTypes.KANBAN,
}); });
rentalTable = await getTable({
base: sakilaProject,
name: 'rental',
});
rentalColumns = await rentalTable.getColumns();
rentalCalendarView = await createView(context, {
title: 'Rental Calendar',
table: rentalTable,
type: ViewTypes.CALENDAR,
range: {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalDate')
.id,
},
});
console.timeEnd('#### viewRowTests'); console.timeEnd('#### viewRowTests');
}); });
@ -148,14 +187,28 @@ function viewRowStaticTests() {
await testGetViewRowList(customerGridView); await testGetViewRowList(customerGridView);
}); });
it('Get view row list Calendar', async () => {
await testGetViewListCalendar(rentalCalendarView);
});
const testGetViewDataListWithRequiredColumns = async (view: View) => { const testGetViewDataListWithRequiredColumns = async (view: View) => {
const requiredColumns = customerColumns const columns =
view.type === ViewTypes.CALENDAR ? rentalColumns : customerColumns;
const requiredColumns = columns
.filter((_, index) => index < 3) .filter((_, index) => index < 3)
.filter((c: ColumnType) => c.uidt !== UITypes.ForeignKey); .filter((c: ColumnType) => c.uidt !== UITypes.ForeignKey);
let table;
if (view.type === ViewTypes.CALENDAR) {
table = rentalTable;
} else {
table = customerTable;
}
const response = await request(context.app) const response = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.query({ .query({
@ -188,6 +241,9 @@ function viewRowStaticTests() {
it('Get view data list with required columns grid', async () => { it('Get view data list with required columns grid', async () => {
await testGetViewDataListWithRequiredColumns(customerGridView); await testGetViewDataListWithRequiredColumns(customerGridView);
}); });
it('Get view data list with required columns grid', async () => {
await testGetViewDataListWithRequiredColumns(rentalCalendarView);
});
const testGetGroupedViewDataListWithRequiredColumns = async (view: View) => { const testGetGroupedViewDataListWithRequiredColumns = async (view: View) => {
const requiredColumns = filmColumns const requiredColumns = filmColumns
@ -457,6 +513,23 @@ function viewRowTests() {
table: filmTable, table: filmTable,
type: ViewTypes.KANBAN, type: ViewTypes.KANBAN,
}); });
rentalTable = await getTable({
base: sakilaProject,
name: 'rental',
});
rentalColumns = await rentalTable.getColumns();
rentalCalendarView = await createView(context, {
title: 'Rental Calendar',
table: rentalTable,
type: ViewTypes.CALENDAR,
range: {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalDate')
.id,
},
});
console.timeEnd('#### viewRowTests'); console.timeEnd('#### viewRowTests');
}); });
@ -554,6 +627,10 @@ function viewRowTests() {
await testGetViewDataListWithRequiredColumnsAndFilter(ViewTypes.GRID); await testGetViewDataListWithRequiredColumnsAndFilter(ViewTypes.GRID);
}); });
it('Get nested sorted filtered table data list with a lookup column Calendar', async function () {
await testGetViewDataListWithRequiredColumnsAndFilter(ViewTypes.CALENDAR);
});
const testGetNestedSortedFilteredTableDataListWithLookupColumn = async ( const testGetNestedSortedFilteredTableDataListWithLookupColumn = async (
viewType: ViewTypes, viewType: ViewTypes,
) => { ) => {
@ -657,6 +734,7 @@ function viewRowTests() {
const testCreateRowView = async (viewType: ViewTypes) => { const testCreateRowView = async (viewType: ViewTypes) => {
const table = await createTable(context, base); const table = await createTable(context, base);
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: table, table: table,
@ -691,8 +769,13 @@ function viewRowTests() {
await testCreateRowView(ViewTypes.KANBAN); await testCreateRowView(ViewTypes.KANBAN);
}); });
it('Create table row Calendar', async function () {
await testCreateRowView(ViewTypes.CALENDAR);
});
const testCreateRowViewWithWrongView = async (viewType: ViewTypes) => { const testCreateRowViewWithWrongView = async (viewType: ViewTypes) => {
const table = await createTable(context, base); const table = await createTable(context, base);
const nonRelatedView = await createView(context, { const nonRelatedView = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: customerTable,
@ -726,16 +809,22 @@ function viewRowTests() {
await testCreateRowViewWithWrongView(ViewTypes.KANBAN); await testCreateRowViewWithWrongView(ViewTypes.KANBAN);
}); });
it('Create table row wrong calendar id', async function () {
await testCreateRowViewWithWrongView(ViewTypes.CALENDAR);
});
// todo: Test that all the columns needed to be shown in the view are returned // todo: Test that all the columns needed to be shown in the view are returned
const testFindOneSortedDataWithRequiredColumns = async ( const testFindOneSortedDataWithRequiredColumns = async (
viewType: ViewTypes, viewType: ViewTypes,
) => { ) => {
const table = viewType === ViewTypes.CALENDAR ? rentalTable : customerTable;
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: table,
type: viewType, type: viewType,
}); });
const firstNameColumn = customerColumns.find( const firstNameColumn = customerColumns.find(
(col) => col.title === 'FirstName', (col) => col.title === 'FirstName',
); );
@ -954,6 +1043,9 @@ function viewRowTests() {
it('Groupby desc sorted and with rollup view data list with required columns GALLERY', async function () { it('Groupby desc sorted and with rollup view data list with required columns GALLERY', async function () {
await testGroupDescSorted(ViewTypes.GALLERY); await testGroupDescSorted(ViewTypes.GALLERY);
}); });
it('Groupby desc sorted and with rollup view data list with required columns CALENDAR', async function () {
await testGroupDescSorted(ViewTypes.CALENDAR);
});
const testGroupWithOffset = async (viewType: ViewTypes) => { const testGroupWithOffset = async (viewType: ViewTypes) => {
const view = await createView(context, { const view = await createView(context, {
@ -1006,41 +1098,81 @@ function viewRowTests() {
it('Groupby desc sorted and with rollup view data list with required columns GRID', async function () { it('Groupby desc sorted and with rollup view data list with required columns GRID', async function () {
await testGroupWithOffset(ViewTypes.GRID); await testGroupWithOffset(ViewTypes.GRID);
}); });
it('Groupby desc sorted and with rollup view data list with required columns CALENDAR', async function () {
await testGroupWithOffset(ViewTypes.CALENDAR);
});
const testCount = async (viewType: ViewTypes) => { const testCount = async (viewType: ViewTypes) => {
let calendar_range = {};
let table;
if (viewType === ViewTypes.CALENDAR) {
table = rentalTable;
calendar_range = {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalDate')
.id,
};
} else {
table = customerTable;
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const response = await request(context.app) const response = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}/count`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}/count`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
if (parseInt(response.body.count) !== 599) { if (viewType === ViewTypes.CALENDAR) {
throw new Error('Wrong count'); if (parseInt(response.body.count) !== 16044) {
throw new Error('Wrong count');
}
} else {
if (parseInt(response.body.count) !== 599) {
throw new Error('Wrong count');
}
} }
}; };
it('Count view data list with required columns', async function () { it('Count view data list with required columns', async function () {
await testCount(ViewTypes.GRID); await testCount(ViewTypes.GRID);
await testCount(ViewTypes.FORM); await testCount(ViewTypes.FORM);
await testCount(ViewTypes.GALLERY); await testCount(ViewTypes.GALLERY);
await testCount(ViewTypes.CALENDAR);
}); });
const testReadViewRow = async (viewType: ViewTypes) => { const testReadViewRow = async (viewType: ViewTypes) => {
let table;
let calendar_range = {};
let Id = 'CustomerId';
if (viewType === ViewTypes.CALENDAR) {
table = rentalTable;
calendar_range = {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalDate')
.id,
};
Id = 'RentalId';
} else {
table = customerTable;
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const listResponse = await request(context.app) const listResponse = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
@ -1049,13 +1181,13 @@ function viewRowTests() {
const readResponse = await request(context.app) const readResponse = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}/${row['CustomerId']}`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}/${row[Id]}`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
if ( if (
row['CustomerId'] !== readResponse.body['CustomerId'] || row[Id] !== readResponse.body[Id] ||
row['FirstName'] !== readResponse.body['FirstName'] row['FirstName'] !== readResponse.body['FirstName']
) { ) {
throw new Error('Wrong read'); throw new Error('Wrong read');
@ -1065,15 +1197,31 @@ function viewRowTests() {
await testReadViewRow(ViewTypes.GALLERY); await testReadViewRow(ViewTypes.GALLERY);
await testReadViewRow(ViewTypes.FORM); await testReadViewRow(ViewTypes.FORM);
await testReadViewRow(ViewTypes.GRID); await testReadViewRow(ViewTypes.GRID);
await testReadViewRow(ViewTypes.CALENDAR);
}); });
const testUpdateViewRow = async (viewType: ViewTypes) => { const testUpdateViewRow = async (viewType: ViewTypes) => {
const table = await createTable(context, base); const table = await createTable(context, base);
const row = await createRow(context, { base, table }); const row = await createRow(context, { base, table });
let calendar_range = {};
if (viewType === ViewTypes.CALENDAR) {
const column = await createColumn(context, table, {
title: 'RentalDate',
column_name: 'rental_date',
uidt: UITypes.Date,
});
calendar_range = {
fk_from_column_id: column.id,
};
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: table, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const updateResponse = await request(context.app) const updateResponse = await request(context.app)
@ -1099,6 +1247,9 @@ function viewRowTests() {
it('Update view row FORM', async function () { it('Update view row FORM', async function () {
await testUpdateViewRow(ViewTypes.FORM); await testUpdateViewRow(ViewTypes.FORM);
}); });
it('Update view row CALENDAR', async function () {
await testUpdateViewRow(ViewTypes.CALENDAR);
});
const testUpdateViewRowWithValidationAndInvalidData = async ( const testUpdateViewRowWithValidationAndInvalidData = async (
viewType: ViewTypes, viewType: ViewTypes,
@ -1112,10 +1263,25 @@ function viewRowTests() {
validate: true, validate: true,
}, },
}); });
let calendar_range = {};
if (viewType === ViewTypes.CALENDAR) {
const column = await createColumn(context, table, {
title: 'RentalDate',
column_name: 'rental_date',
uidt: UITypes.Date,
});
calendar_range = {
fk_from_column_id: column.id,
};
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: table, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const row = await createRow(context, { base, table }); const row = await createRow(context, { base, table });
@ -1139,7 +1305,9 @@ function viewRowTests() {
it('Update view row with validation and invalid data FORM', async function () { it('Update view row with validation and invalid data FORM', async function () {
await testUpdateViewRowWithValidationAndInvalidData(ViewTypes.FORM); await testUpdateViewRowWithValidationAndInvalidData(ViewTypes.FORM);
}); });
it('Update view row with validation and invalid data CALENDAR', async function () {
await testUpdateViewRowWithValidationAndInvalidData(ViewTypes.CALENDAR);
});
// todo: Test webhooks of before and after update // todo: Test webhooks of before and after update
// todo: Test with form view // todo: Test with form view
@ -1155,10 +1323,25 @@ function viewRowTests() {
validate: true, validate: true,
}, },
}); });
let calendar_range = {};
if (viewType === ViewTypes.CALENDAR) {
const column = await createColumn(context, table, {
title: 'RentalDate',
column_name: 'rental_date',
uidt: UITypes.Date,
});
calendar_range = {
fk_from_column_id: column.id,
};
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: table, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const row = await createRow(context, { base, table }); const row = await createRow(context, { base, table });
@ -1190,14 +1373,31 @@ function viewRowTests() {
it('Update view row with validation and valid data FORM', async function () { it('Update view row with validation and valid data FORM', async function () {
await testUpdateViewRowWithValidationAndValidData(ViewTypes.FORM); await testUpdateViewRowWithValidationAndValidData(ViewTypes.FORM);
}); });
it('Update view row with validation and valid data CALENDAR', async function () {
await testUpdateViewRowWithValidationAndValidData(ViewTypes.CALENDAR);
});
const testDeleteViewRow = async (viewType: ViewTypes) => { const testDeleteViewRow = async (viewType: ViewTypes) => {
const table = await createTable(context, base); const table = await createTable(context, base);
let calendar_range = {};
if (viewType === ViewTypes.CALENDAR) {
const range = await createColumn(context, table, {
title: 'RentalDate',
column_name: 'rental_date',
uidt: UITypes.Date,
});
calendar_range = {
fk_from_column_id: range.id,
};
}
const row = await createRow(context, { base, table }); const row = await createRow(context, { base, table });
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: table, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
await request(context.app) await request(context.app)
@ -1222,6 +1422,9 @@ function viewRowTests() {
it('Delete view row FORM', async function () { it('Delete view row FORM', async function () {
await testDeleteViewRow(ViewTypes.FORM); await testDeleteViewRow(ViewTypes.FORM);
}); });
it('Delete view row CALENDAR', async function () {
await testDeleteViewRow(ViewTypes.CALENDAR);
});
const testDeleteViewRowWithForeignKeyConstraint = async ( const testDeleteViewRowWithForeignKeyConstraint = async (
viewType: ViewTypes, viewType: ViewTypes,
@ -1275,21 +1478,40 @@ function viewRowTests() {
it('Delete view row with ltar foreign key constraint FORM', async function () { it('Delete view row with ltar foreign key constraint FORM', async function () {
await testDeleteViewRowWithForeignKeyConstraint(ViewTypes.FORM); await testDeleteViewRowWithForeignKeyConstraint(ViewTypes.FORM);
}); });
it('Delete view row with ltar foreign key constraint Calendar', async function () {
await testDeleteViewRowWithForeignKeyConstraint(ViewTypes.CALENDAR);
});
const testViewRowExists = async (viewType: ViewTypes) => { const testViewRowExists = async (viewType: ViewTypes) => {
let table;
let calendar_range = {};
let colTitle;
if (viewType === ViewTypes.CALENDAR) {
colTitle = 'RentalId';
table = rentalTable;
calendar_range = {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalId').id,
};
} else {
table = customerTable;
colTitle = 'CustomerId';
}
const row = await getOneRow(context, { const row = await getOneRow(context, {
base: sakilaProject, base: sakilaProject,
table: customerTable, table: table,
}); });
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const response = await request(context.app) const response = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}/${row['CustomerId']}/exist`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}/${row[colTitle]}/exist`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
@ -1302,17 +1524,34 @@ function viewRowTests() {
await testViewRowExists(ViewTypes.GALLERY); await testViewRowExists(ViewTypes.GALLERY);
await testViewRowExists(ViewTypes.GRID); await testViewRowExists(ViewTypes.GRID);
await testViewRowExists(ViewTypes.FORM); await testViewRowExists(ViewTypes.FORM);
await testViewRowExists(ViewTypes.CALENDAR);
}); });
const testViewRowNotExists = async (viewType: ViewTypes) => { const testViewRowNotExists = async (viewType: ViewTypes) => {
let calendar_range = {};
if (viewType === ViewTypes.CALENDAR) {
calendar_range = {
fk_from_column_id: rentalColumns.find((c) => c.title === 'RentalDate')
.id,
};
}
let table;
if (viewType === ViewTypes.CALENDAR) {
table = rentalTable;
} else {
table = customerTable;
}
const view = await createView(context, { const view = await createView(context, {
title: 'View', title: 'View',
table: customerTable, table: table,
type: viewType, type: viewType,
range: calendar_range,
}); });
const response = await request(context.app) const response = await request(context.app)
.get( .get(
`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}/999999/exist`, `/api/v1/db/data/noco/${sakilaProject.id}/${table.id}/views/${view.id}/999999/exist`,
) )
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
@ -1325,6 +1564,7 @@ function viewRowTests() {
await testViewRowNotExists(ViewTypes.GALLERY); await testViewRowNotExists(ViewTypes.GALLERY);
await testViewRowNotExists(ViewTypes.GRID); await testViewRowNotExists(ViewTypes.GRID);
await testViewRowNotExists(ViewTypes.FORM); await testViewRowNotExists(ViewTypes.FORM);
await testViewRowNotExists(ViewTypes.CALENDAR);
}); });
it('Export csv GRID', async function () { it('Export csv GRID', async function () {

Loading…
Cancel
Save