Browse Source

refactor/Added unit test for view row api

pull/3358/head
Muhammed Mustafa 2 years ago
parent
commit
8929971d80
  1. 1
      packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts
  2. 36
      packages/nocodb/tests/unit/rest/tests/factory/view.ts
  3. 221
      packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

1
packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts

@ -10,6 +10,7 @@ import { getViewAndModelFromRequestByAliasOrId } from './helpers';
import apiMetrics from '../../helpers/apiMetrics'; import apiMetrics from '../../helpers/apiMetrics';
import getAst from '../../../db/sql-data-mapper/lib/sql/helpers/getAst'; import getAst from '../../../db/sql-data-mapper/lib/sql/helpers/getAst';
// todo: Handle the error case where view doesnt belong to model
async function dataList(req: Request, res: Response) { async function dataList(req: Request, res: Response) {
const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); const { model, view } = await getViewAndModelFromRequestByAliasOrId(req);
res.json(await getDataList(model, view, req)); res.json(await getDataList(model, view, req));

36
packages/nocodb/tests/unit/rest/tests/factory/view.ts

@ -0,0 +1,36 @@
import { UITypes, ViewTypes } from 'nocodb-sdk';
import request from 'supertest';
import Column from '../../../../../src/lib/models/Column';
import Model from '../../../../../src/lib/models/Model';
import View from '../../../../../src/lib/models/View';
const createView = async (context, {title, table, type}: {title: string, table: Model, type: ViewTypes}) => {
const viewTypeStr = (type) => {
switch (type) {
case ViewTypes.GALLERY:
return 'galleries';
case ViewTypes.FORM:
return 'forms';
case ViewTypes.GRID:
return 'grids';
case ViewTypes.KANBAN:
return 'kanbans';
default:
throw new Error('Invalid view type');
}
};
await request(context.app)
.post(`/api/v1/db/meta/tables/${table.id}/${viewTypeStr(type)}`)
.set('xc-auth', context.token)
.send({
title,
type,
});
const view = await View.getByTitleOrId({fk_model_id: table.id, titleOrId:title}) as View;
return view
}
export {createView}

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

@ -6,7 +6,9 @@ import Project from '../../../../src/lib/models/Project';
import Model from '../../../../src/lib/models/Model'; import Model from '../../../../src/lib/models/Model';
import { getTable } from './factory/table'; import { getTable } from './factory/table';
import View from '../../../../src/lib/models/View'; import View from '../../../../src/lib/models/View';
import { ColumnType } from 'nocodb-sdk'; import { ColumnType, UITypes, ViewType, ViewTypes } from 'nocodb-sdk';
import { createView } from './factory/view';
import { createLookupColumn } from './factory/column';
const isColumnsCorrectInResponse = (row, columns: ColumnType[]) => { const isColumnsCorrectInResponse = (row, columns: ColumnType[]) => {
const responseColumnsListStr = Object.keys(row).sort().join(','); const responseColumnsListStr = Object.keys(row).sort().join(',');
@ -18,12 +20,15 @@ const isColumnsCorrectInResponse = (row, columns: ColumnType[]) => {
return responseColumnsListStr === customerColumnsListStr; return responseColumnsListStr === customerColumnsListStr;
}; };
function tableTest() { function viewRowTests() {
let context; let context;
let project: Project; let project: Project;
let sakilaProject: Project; let sakilaProject: Project;
let customerTable: Model; let customerTable: Model;
let customerColumns; let customerColumns;
let customerGridView: View;
let customerGalleryView: View;
let customerFormView: View;
beforeEach(async function () { beforeEach(async function () {
context = await init(); context = await init();
@ -32,25 +37,49 @@ function tableTest() {
project = await createProject(context); project = await createProject(context);
customerTable = await getTable({project: sakilaProject, name: 'customer'}) customerTable = await getTable({project: sakilaProject, name: 'customer'})
customerColumns = await customerTable.getColumns(); customerColumns = await customerTable.getColumns();
customerGridView = await createView(context, {
title: 'Customer Gallery',
table: customerTable,
type: ViewTypes.GRID
});
customerGalleryView = await createView(context, {
title: 'Customer Gallery',
table: customerTable,
type: ViewTypes.GALLERY
});
customerFormView = await createView(context, {
title: 'Customer Form',
table: customerTable,
type: ViewTypes.FORM
});
}); });
it.only('Get view row list', async () => { const testGetViewRowListGallery = async (view: View) => {
const view = (await View.list(customerTable.id))[0]
const response = await request(context.app) const response = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`) .get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`)
.set('xc-auth', context.token) .set('xc-auth', context.token)
.expect(200); .expect(200);
const pageInfo = response.body.pageInfo; const pageInfo = response.body.pageInfo;
if(pageInfo.totalRows !== 599 || response.body.list[0]['CustomerId'] !== 1){ if(pageInfo.totalRows !== 599 || response.body.list[0]['CustomerId'] !== 1){
throw new Error('View row list is not correct'); throw new Error('View row list is not correct');
} }
}
it('Get view row list gallery', async () => {
await testGetViewRowListGallery(customerGalleryView);
})
it('Get view row list form', async () => {
await testGetViewRowListGallery(customerFormView);
})
it('Get view row list grid', async () => {
await testGetViewRowListGallery(customerGridView);
}) })
it('Get table data list with required columns', async function () { const testGetViewDataListWithRequiredColumns = async (view: View) => {
const view = (await View.list(customerTable.id))[0] const requiredColumns = customerColumns.filter((_, index) => index < 3).filter((c: ColumnType) => c.uidt !== UITypes.ForeignKey);
const requiredColumns = customerColumns.filter((_, index) => index < 3);
const response = await request(context.app) const response = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`) .get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`)
@ -66,12 +95,24 @@ function tableTest() {
} }
if (!isColumnsCorrectInResponse(response.body.list[0], requiredColumns)) { if (!isColumnsCorrectInResponse(response.body.list[0], requiredColumns)) {
console.log(response.body.list[0], requiredColumns.map((c: ColumnType) => ({title: c.title,uidt: c.uidt})));
throw new Error('Wrong columns'); throw new Error('Wrong columns');
} }
}); }
it('Get view data list with required columns gallery', async () => {
await testGetViewDataListWithRequiredColumns(customerGalleryView);
})
it('Get view data list with required columns form', async () => {
await testGetViewDataListWithRequiredColumns(customerFormView);
})
it('Get view data list with required columns grid', async () => {
await testGetViewDataListWithRequiredColumns(customerGridView);
})
it('Get desc sorted table data list with required columns', async function () { const testDescSortedViewDataList = async (view: View) => {
const view = (await View.list(customerTable.id))[0]
const firstNameColumn = customerColumns.find( const firstNameColumn = customerColumns.find(
(col) => col.title === 'FirstName' (col) => col.title === 'FirstName'
); );
@ -105,7 +146,7 @@ function tableTest() {
const lastPageOffset = const lastPageOffset =
Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize; Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize;
const lastPageResponse = await request(context.app) const lastPageResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}`) .get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`)
.set('xc-auth', context.token) .set('xc-auth', context.token)
.query({ .query({
fields: visibleColumns.map((c) => c.title), fields: visibleColumns.map((c) => c.title),
@ -122,10 +163,21 @@ function tableTest() {
console.log(lastPageOffset, lastPageResponse.body.list); console.log(lastPageOffset, lastPageResponse.body.list);
throw new Error('Wrong sort on last page'); throw new Error('Wrong sort on last page');
} }
}
it('Get desc sorted table data list with required columns gallery', async function () {
await testDescSortedViewDataList(customerGalleryView);
});
it('Get desc sorted table data list with required columns form', async function () {
await testDescSortedViewDataList(customerFormView);
}); });
it('Get asc sorted table data list with required columns', async function () { it('Get desc sorted table data list with required columns grid', async function () {
const view = (await View.list(customerTable.id))[0] await testDescSortedViewDataList(customerGridView);
});
const testAscSortedViewDataList = async (view: View) => {
const firstNameColumn = customerColumns.find( const firstNameColumn = customerColumns.find(
(col) => col.title === 'FirstName' (col) => col.title === 'FirstName'
); );
@ -159,7 +211,7 @@ function tableTest() {
const lastPageOffset = const lastPageOffset =
Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize; Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize;
const lastPageResponse = await request(context.app) const lastPageResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}`) .get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}/views/${view.id}`)
.set('xc-auth', context.token) .set('xc-auth', context.token)
.query({ .query({
fields: visibleColumns.map((c) => c.title), fields: visibleColumns.map((c) => c.title),
@ -176,7 +228,144 @@ function tableTest() {
console.log(lastPageOffset, lastPageResponse.body.list); console.log(lastPageOffset, lastPageResponse.body.list);
throw new Error('Wrong sort on last page'); throw new Error('Wrong sort on last page');
} }
}
it('Get asc sorted view data list with required columns gallery', async function () {
await testAscSortedViewDataList(customerGalleryView);
});
it('Get asc sorted view data list with required columns form', async function () {
await testAscSortedViewDataList(customerFormView);
});
it('Get asc sorted view data list with required columns grid', async function () {
await testAscSortedViewDataList(customerGridView);
});
const testGetViewDataListWithRequiredColumnsAndFilter = async (viewType: ViewTypes) => {
const rentalTable = await getTable({project: sakilaProject, name: 'rental'});
const view = await createView(context, {
title: 'View',
table: rentalTable,
type: viewType
});
const lookupColumn = await createLookupColumn(context, {
project: sakilaProject,
title: 'Lookup',
table: rentalTable,
relatedTableName: customerTable.table_name,
relatedTableColumnTitle: 'FirstName',
}); });
const paymentListColumn = (await rentalTable.getColumns()).find(
(c) => c.title === 'Payment List'
);
const returnDateColumn = (await rentalTable.getColumns()).find(
(c) => c.title === 'ReturnDate'
);
const nestedFilter = {
is_group: true,
status: 'create',
logical_op: 'and',
children: [
{
fk_column_id: lookupColumn?.id,
status: 'create',
logical_op: 'and',
comparison_op: 'like',
value: '%a%',
},
{
fk_column_id: paymentListColumn?.id,
status: 'create',
logical_op: 'and',
comparison_op: 'notempty',
},
{
is_group: true,
status: 'create',
logical_op: 'and',
children: [
{
logical_op: 'and',
fk_column_id: returnDateColumn?.id,
status: 'create',
comparison_op: 'gte',
value: '2005-06-02 04:33',
},
],
},
],
};
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${rentalTable.id}/views/${view.id}`)
.set('xc-auth', context.token)
.query({
filterArrJson: JSON.stringify([nestedFilter]),
});
if (response.body.pageInfo.totalRows !== 9133)
throw new Error('Wrong number of rows');
if (response.body.list[0][lookupColumn.title] !== 'ANDREW')
throw new Error('Wrong filter');
const ascResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${rentalTable.id}/views/${view.id}`)
.set('xc-auth', context.token)
.query({
filterArrJson: JSON.stringify([nestedFilter]),
sortArrJson: JSON.stringify([
{
fk_column_id: lookupColumn?.id,
direction: 'asc',
},
]),
})
.expect(200);
if (ascResponse.body.pageInfo.totalRows !== 9133)
throw new Error('Wrong number of rows asc');
if (ascResponse.body.list[0][lookupColumn.title] !== 'AARON') {
console.log(ascResponse.body.list[0][lookupColumn.title]);
throw new Error('Wrong filter asc');
} }
export default tableTest; const descResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${rentalTable.id}/views/${view.id}`)
.set('xc-auth', context.token)
.query({
filterArrJson: JSON.stringify([nestedFilter]),
sortArrJson: JSON.stringify([
{
fk_column_id: lookupColumn?.id,
direction: 'desc',
},
]),
})
.expect(200);
if (descResponse.body.pageInfo.totalRows !== 9133)
throw new Error('Wrong number of rows desc');
if (descResponse.body.list[0][lookupColumn.title] !== 'ZACHARY')
throw new Error('Wrong filter desc');
}
it('Get nested sorted filtered table data list with a lookup column gallery', async function () {
await testGetViewDataListWithRequiredColumnsAndFilter(ViewTypes.GALLERY);
});
it('Get nested sorted filtered table data list with a lookup column grid', async function () {
await testGetViewDataListWithRequiredColumnsAndFilter(ViewTypes.GRID);
});
}
export default function () {
describe('ViewRow', viewRowTests);
}
Loading…
Cancel
Save