Browse Source

test: text based list api

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>
pull/5901/head
Raju Udava 2 years ago
parent
commit
a9f4b21f98
  1. 161
      packages/nocodb/tests/unit/factory/column.ts
  2. 33
      packages/nocodb/tests/unit/factory/row.ts
  3. 84
      packages/nocodb/tests/unit/factory/view.ts
  4. 5
      packages/nocodb/tests/unit/init/index.ts
  5. 2
      packages/nocodb/tests/unit/rest/index.test.ts
  6. 653
      packages/nocodb/tests/unit/rest/tests/newDataApis.test.ts

161
packages/nocodb/tests/unit/factory/column.ts

@ -1,13 +1,13 @@
import { UITypes } from 'nocodb-sdk'; import { UITypes } from 'nocodb-sdk';
import request from 'supertest'; import request from 'supertest';
import Column from '../../../src/models/Column';
import FormViewColumn from '../../../src/models/FormViewColumn';
import GalleryViewColumn from '../../../src/models/GalleryViewColumn';
import GridViewColumn from '../../../src/models/GridViewColumn';
import Model from '../../../src/models/Model'; import Model from '../../../src/models/Model';
import Project from '../../../src/models/Project'; import { isPg, isSqlite } from '../init/db';
import View from '../../../src/models/View'; import type Column from '../../../src/models/Column';
import { isSqlite, isPg } from '../init/db'; import type FormViewColumn from '../../../src/models/FormViewColumn';
import type GalleryViewColumn from '../../../src/models/GalleryViewColumn';
import type GridViewColumn from '../../../src/models/GridViewColumn';
import type Project from '../../../src/models/Project';
import type View from '../../../src/models/View';
const defaultColumns = function (context) { const defaultColumns = function (context) {
return [ return [
@ -46,6 +46,120 @@ const defaultColumns = function (context) {
]; ];
}; };
const customColumns = function (type: string) {
switch (type) {
case 'textBased':
return [
{
column_name: 'Id',
title: 'Id',
uidt: UITypes.ID,
},
{
column_name: 'SingleLineText',
title: 'SingleLineText',
uidt: UITypes.SingleLineText,
},
{
column_name: 'MultiLineText',
title: 'MultiLineText',
uidt: UITypes.LongText,
},
{
column_name: 'Email',
title: 'Email',
uidt: UITypes.Email,
},
{
column_name: 'Phone',
title: 'Phone',
uidt: UITypes.PhoneNumber,
},
{
column_name: 'Url',
title: 'Url',
uidt: UITypes.URL,
},
];
case 'numberBased':
return [
{
column_name: 'Id',
title: 'Id',
uidt: UITypes.ID,
},
{
column_name: 'Number',
title: 'Number',
uidt: UITypes.Number,
},
{
column_name: 'Decimal',
title: 'Decimal',
uidt: UITypes.Decimal,
},
{
column_name: 'Currency',
title: 'Currency',
uidt: UITypes.Currency,
},
{
column_name: 'Percent',
title: 'Percent',
uidt: UITypes.Percent,
},
{
column_name: 'Duration',
title: 'Duration',
uidt: UITypes.Duration,
},
{
column_name: 'Rating',
title: 'Rating',
uidt: UITypes.Rating,
},
];
case 'dateBased':
return [
{
column_name: 'Id',
title: 'Id',
uidt: UITypes.ID,
},
{
column_name: 'Date',
title: 'Date',
uidt: UITypes.Date,
},
{
column_name: 'DateTime',
title: 'DateTime',
uidt: UITypes.DateTime,
},
];
case 'selectBased':
return [
{
column_name: 'Id',
title: 'Id',
uidt: UITypes.ID,
},
{
column_name: 'SingleSelect',
title: 'SingleSelect',
uidt: UITypes.SingleSelect,
dtxp: "'jan','feb','mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'",
},
{
column_name: 'MultiSelect',
title: 'MultiSelect',
uidt: UITypes.MultiSelect,
dtxp: "'jan','feb','mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'",
},
];
}
};
const createColumn = async (context, table, columnAttr) => { const createColumn = async (context, table, columnAttr) => {
await request(context.app) await request(context.app)
.post(`/api/v1/db/meta/tables/${table.id}/columns`) .post(`/api/v1/db/meta/tables/${table.id}/columns`)
@ -55,7 +169,7 @@ const createColumn = async (context, table, columnAttr) => {
}); });
const column: Column = (await table.getColumns()).find( const column: Column = (await table.getColumns()).find(
(column) => column.title === columnAttr.title (column) => column.title === columnAttr.title,
); );
return column; return column;
}; };
@ -76,7 +190,7 @@ const createRollupColumn = async (
table: Model; table: Model;
relatedTableName: string; relatedTableName: string;
relatedTableColumnTitle: string; relatedTableColumnTitle: string;
} },
) => { ) => {
const childBases = await project.getBases(); const childBases = await project.getBases();
const childTable = await Model.getByIdOrName({ const childTable = await Model.getByIdOrName({
@ -86,13 +200,13 @@ const createRollupColumn = async (
}); });
const childTableColumns = await childTable.getColumns(); const childTableColumns = await childTable.getColumns();
const childTableColumn = await childTableColumns.find( const childTableColumn = await childTableColumns.find(
(column) => column.title === relatedTableColumnTitle (column) => column.title === relatedTableColumnTitle,
); );
const ltarColumn = (await table.getColumns()).find( const ltarColumn = (await table.getColumns()).find(
(column) => (column) =>
column.uidt === UITypes.LinkToAnotherRecord && column.uidt === UITypes.LinkToAnotherRecord &&
column.colOptions?.fk_related_model_id === childTable.id column.colOptions?.fk_related_model_id === childTable.id,
); );
const rollupColumn = await createColumn(context, table, { const rollupColumn = await createColumn(context, table, {
@ -122,7 +236,7 @@ const createLookupColumn = async (
table: Model; table: Model;
relatedTableName: string; relatedTableName: string;
relatedTableColumnTitle: string; relatedTableColumnTitle: string;
} },
) => { ) => {
const childBases = await project.getBases(); const childBases = await project.getBases();
const childTable = await Model.getByIdOrName({ const childTable = await Model.getByIdOrName({
@ -132,19 +246,19 @@ const createLookupColumn = async (
}); });
const childTableColumns = await childTable.getColumns(); const childTableColumns = await childTable.getColumns();
const childTableColumn = await childTableColumns.find( const childTableColumn = await childTableColumns.find(
(column) => column.title === relatedTableColumnTitle (column) => column.title === relatedTableColumnTitle,
); );
if (!childTableColumn) { if (!childTableColumn) {
throw new Error( throw new Error(
`Could not find column ${relatedTableColumnTitle} in ${relatedTableName}` `Could not find column ${relatedTableColumnTitle} in ${relatedTableName}`,
); );
} }
const ltarColumn = (await table.getColumns()).find( const ltarColumn = (await table.getColumns()).find(
(column) => (column) =>
column.uidt === UITypes.LinkToAnotherRecord && column.uidt === UITypes.LinkToAnotherRecord &&
column.colOptions?.fk_related_model_id === childTable.id column.colOptions?.fk_related_model_id === childTable.id,
); );
const lookupColumn = await createColumn(context, table, { const lookupColumn = await createColumn(context, table, {
title: title, title: title,
@ -168,15 +282,15 @@ const createQrCodeColumn = async (
title: string; title: string;
table: Model; table: Model;
referencedQrValueTableColumnTitle: string; referencedQrValueTableColumnTitle: string;
} },
) => { ) => {
const referencedQrValueTableColumnId = await table const referencedQrValueTableColumnId = await table
.getColumns() .getColumns()
.then( .then(
(cols) => (cols) =>
cols.find( cols.find(
(column) => column.title == referencedQrValueTableColumnTitle (column) => column.title == referencedQrValueTableColumnTitle,
)['id'] )['id'],
); );
const qrCodeColumn = await createColumn(context, table, { const qrCodeColumn = await createColumn(context, table, {
@ -198,15 +312,15 @@ const createBarcodeColumn = async (
title: string; title: string;
table: Model; table: Model;
referencedBarcodeValueTableColumnTitle: string; referencedBarcodeValueTableColumnTitle: string;
} },
) => { ) => {
const referencedBarcodeValueTableColumnId = await table const referencedBarcodeValueTableColumnId = await table
.getColumns() .getColumns()
.then( .then(
(cols) => (cols) =>
cols.find( cols.find(
(column) => column.title == referencedBarcodeValueTableColumnTitle (column) => column.title == referencedBarcodeValueTableColumnTitle,
)['id'] )['id'],
); );
const barcodeColumn = await createColumn(context, table, { const barcodeColumn = await createColumn(context, table, {
@ -230,7 +344,7 @@ const createLtarColumn = async (
parentTable: Model; parentTable: Model;
childTable: Model; childTable: Model;
type: string; type: string;
} },
) => { ) => {
const ltarColumn = await createColumn(context, parentTable, { const ltarColumn = await createColumn(context, parentTable, {
title: title, title: title,
@ -246,7 +360,7 @@ const createLtarColumn = async (
const updateViewColumn = async ( const updateViewColumn = async (
context, context,
{ view, column, attr }: { column: Column; view: View; attr: any } { view, column, attr }: { column: Column; view: View; attr: any },
) => { ) => {
const res = await request(context.app) const res = await request(context.app)
.patch(`/api/v1/db/meta/views/${view.id}/columns/${column.id}`) .patch(`/api/v1/db/meta/views/${view.id}/columns/${column.id}`)
@ -263,6 +377,7 @@ const updateViewColumn = async (
}; };
export { export {
customColumns,
defaultColumns, defaultColumns,
createColumn, createColumn,
createQrCodeColumn, createQrCodeColumn,

33
packages/nocodb/tests/unit/factory/row.ts

@ -1,11 +1,12 @@
import { ColumnType, UITypes } from 'nocodb-sdk'; import { UITypes } from 'nocodb-sdk';
import request from 'supertest'; import request from 'supertest';
import Column from '../../../src/models/Column';
import Filter from '../../../src/models/Filter';
import Model from '../../../src/models/Model'; import Model from '../../../src/models/Model';
import Project from '../../../src/models/Project';
import Sort from '../../../src/models/Sort';
import NcConnectionMgrv2 from '../../../src/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '../../../src/utils/common/NcConnectionMgrv2';
import type { ColumnType } from 'nocodb-sdk';
import type Column from '../../../src/models/Column';
import type Filter from '../../../src/models/Filter';
import type Project from '../../../src/models/Project';
import type Sort from '../../../src/models/Sort';
const rowValue = (column: ColumnType, index: number) => { const rowValue = (column: ColumnType, index: number) => {
switch (column.uidt) { switch (column.uidt) {
@ -175,9 +176,15 @@ const rowMixedValue = (column: ColumnType, index: number) => {
case UITypes.Date: case UITypes.Date:
// set startDate as 400 days before today // set startDate as 400 days before today
// eslint-disable-next-line no-case-declarations // eslint-disable-next-line no-case-declarations
const result = new Date(); const d1 = new Date();
result.setDate(result.getDate() - 400 + index); d1.setDate(d1.getDate() - 400 + index);
return result.toISOString().slice(0, 10); return d1.toISOString().slice(0, 10);
case UITypes.DateTime:
// set startDate as 400 days before today
// eslint-disable-next-line no-case-declarations
const d2 = new Date();
d2.setDate(d2.getDate() - 400 + index);
return d2.toISOString();
case UITypes.URL: case UITypes.URL:
return urls[index % urls.length]; return urls[index % urls.length];
case UITypes.SingleSelect: case UITypes.SingleSelect:
@ -228,7 +235,7 @@ const listRow = async ({
const getOneRow = async ( const getOneRow = async (
context, context,
{ project, table }: { project: Project; table: Model } { project, table }: { project: Project; table: Model },
) => { ) => {
const response = await request(context.app) const response = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${table.id}/find-one`) .get(`/api/v1/db/data/noco/${project.id}/${table.id}/find-one`)
@ -266,7 +273,7 @@ const createRow = async (
project: Project; project: Project;
table: Model; table: Model;
index?: number; index?: number;
} },
) => { ) => {
const columns = await table.getColumns(); const columns = await table.getColumns();
const rowData = generateDefaultRowAttributes({ columns, index }); const rowData = generateDefaultRowAttributes({ columns, index });
@ -289,7 +296,7 @@ const createBulkRows = async (
project: Project; project: Project;
table: Model; table: Model;
values: any[]; values: any[];
} },
) => { ) => {
await request(context.app) await request(context.app)
.post(`/api/v1/db/data/bulk/noco/${project.id}/${table.id}`) .post(`/api/v1/db/data/bulk/noco/${project.id}/${table.id}`)
@ -317,7 +324,7 @@ const createChildRow = async (
rowId?: string; rowId?: string;
childRowId?: string; childRowId?: string;
type: string; type: string;
} },
) => { ) => {
if (!rowId) { if (!rowId) {
const row = await createRow(context, { project, table }); const row = await createRow(context, { project, table });
@ -331,7 +338,7 @@ const createChildRow = async (
await request(context.app) await request(context.app)
.post( .post(
`/api/v1/db/data/noco/${project.id}/${table.id}/${rowId}/${type}/${column.title}/${childRowId}` `/api/v1/db/data/noco/${project.id}/${table.id}/${rowId}/${type}/${column.title}/${childRowId}`,
) )
.set('xc-auth', context.token); .set('xc-auth', context.token);

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

@ -1,9 +1,20 @@
import { ViewTypes } from 'nocodb-sdk'; import { ViewTypes } from 'nocodb-sdk';
import request from 'supertest'; import request from 'supertest';
import Model from '../../../src/models/Model';
import View from '../../../src/models/View'; import View from '../../../src/models/View';
import type Model from '../../../src/models/Model';
const createView = async (context, {title, table, type}: {title: string, table: Model, type: ViewTypes}) => { const createView = async (
context,
{
title,
table,
type,
}: {
title: string;
table: Model;
type: ViewTypes;
},
) => {
const viewTypeStr = (type) => { const viewTypeStr = (type) => {
switch (type) { switch (type) {
case ViewTypes.GALLERY: case ViewTypes.GALLERY:
@ -26,13 +37,70 @@ const createView = async (context, {title, table, type}: {title: string, table:
title, title,
type, type,
}); });
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({
fk_model_id: table.id,
titleOrId: title,
})) as View;
return view;
};
const updateView = async (
context,
{
table,
view,
filter = [],
sort = [],
field = [],
}: {
table: Model;
view: View;
filter?: any[];
sort?: any[];
field?: any[];
},
) => {
if (filter.length) {
for (let i = 0; i < filter.length; i++) {
await request(context.app)
.post(`/api/v1/db/meta/views/${view.id}/filters`)
.set('xc-auth', context.token)
.send(filter[i])
.expect(200);
}
} }
const view = await View.getByTitleOrId({fk_model_id: table.id, titleOrId:title}) as View; if (sort.length) {
for (let i = 0; i < sort.length; i++) {
await request(context.app)
.post(`/api/v1/db/meta/views/${view.id}/sorts`)
.set('xc-auth', context.token)
.send(sort[i])
.expect(200);
}
}
if (field.length) {
for (let i = 0; i < field.length; i++) {
const columns = await table.getColumns();
const viewColumns = await view.getColumns();
return view const columnId = columns.find((c) => c.title === field[i]).id;
} const viewColumnId = viewColumns.find(
(c) => c.fk_column_id === columnId,
).id;
// configure view to hide selected fields
await request(context.app)
.patch(`/api/v1/db/meta/views/${view.id}/columns/${viewColumnId}`)
.set('xc-auth', context.token)
.send({ show: false })
.expect(200);
}
}
};
export {createView} export { createView, updateView };

5
packages/nocodb/tests/unit/init/index.ts

@ -25,7 +25,7 @@ const serverInit = async () => {
const isFirstTimeRun = () => !server; const isFirstTimeRun = () => !server;
export default async function () { export default async function (isSakila = true) {
const { default: TestDbMngr } = await import('../TestDbMngr'); const { default: TestDbMngr } = await import('../TestDbMngr');
if (isFirstTimeRun()) { if (isFirstTimeRun()) {
@ -33,7 +33,10 @@ export default async function () {
server = await serverInit(); server = await serverInit();
} }
if (isSakila) {
await cleanUpSakila(); await cleanUpSakila();
}
await cleanupMeta(); await cleanupMeta();
const { token } = await createUser({ app: server }, { roles: 'editor' }); const { token } = await createUser({ app: server }, { roles: 'editor' });

2
packages/nocodb/tests/unit/rest/index.test.ts

@ -8,6 +8,7 @@ import tableRowTests from './tests/tableRow.test';
import viewRowTests from './tests/viewRow.test'; import viewRowTests from './tests/viewRow.test';
import attachmentTests from './tests/attachment.test'; import attachmentTests from './tests/attachment.test';
import filterTest from './tests/filter.test'; import filterTest from './tests/filter.test';
import newDataApisTest from './tests/newDataApis.test';
function restTests() { function restTests() {
authTests(); authTests();
@ -19,6 +20,7 @@ function restTests() {
columnTypeSpecificTests(); columnTypeSpecificTests();
attachmentTests(); attachmentTests();
filterTest(); filterTest();
newDataApisTest();
} }
export default function () { export default function () {

653
packages/nocodb/tests/unit/rest/tests/newDataApis.test.ts

@ -80,3 +80,656 @@
* - invalid table ID * - invalid table ID
* - invalid record ID * - invalid record ID
*/ */
import 'mocha';
import { UITypes, ViewTypes } from 'nocodb-sdk';
import { expect } from 'chai';
import request from 'supertest';
import init from '../../init';
import { createProject, createSakilaProject } from '../../factory/project';
import { createTable, getTable } from '../../factory/table';
import { createBulkRows, listRow, rowMixedValue } from '../../factory/row';
import { customColumns } from '../../factory/column';
import { createView, updateView } from '../../factory/view';
import type { Api } from 'nocodb-sdk';
import type { ColumnType } from 'nocodb-sdk';
import type Project from '../../../../src/models/Project';
import type Model from '../../../../src/models/Model';
let api: Api<any>;
const debugMode = true;
let context;
let project: Project;
let table: Model;
let columns: any[];
let insertedRecords: any[] = [];
let sakilaProject: Project;
let customerTable: Model;
let customerColumns;
// Optimisation scope for time reduction
// 1. BeforeEach can be changed to BeforeAll for List and Read APIs
///////////////////////////////////////////////////////////////////////////////
// Utility routines
const verifyColumnsInRsp = (row, columns: ColumnType[]) => {
const responseColumnsListStr = Object.keys(row).sort().join(',');
const expectedColumnsListStr = columns
.map((c) => c.title)
.sort()
.join(',');
return responseColumnsListStr === expectedColumnsListStr;
};
async function ncAxiosGet(url: string, query = {}, status = 200) {
const response = await request(context.app)
.get(url)
.set('xc-auth', context.token)
.query(query)
.send({})
.expect(status);
return response;
}
async function ncAxiosPost(url: string, body = {}, status = 200) {
const response = await request(context.app)
.post(url)
.set('xc-auth', context.token)
.send(body)
.expect(status);
return response;
}
///////////////////////////////////////////////////////////////////////////////
// generic table, sakila based
function generalDb() {
beforeEach(async function () {
context = await init();
sakilaProject = await createSakilaProject(context);
project = await createProject(context);
customerTable = await getTable({
project: sakilaProject,
name: 'customer',
});
customerColumns = await customerTable.getColumns();
});
}
function textBased() {
// prepare data for test cases
beforeEach(async function () {
context = await init(false);
project = await createProject(context);
table = await createTable(context, project, {
table_name: 'textBased',
title: 'TextBased',
columns: customColumns('textBased'),
});
// retrieve column meta
columns = await table.getColumns();
// build records
const rowAttributes = [];
for (let i = 0; i < 400; i++) {
const row = {
SingleLineText: rowMixedValue(columns[1], i),
MultiLineText: rowMixedValue(columns[2], i),
Email: rowMixedValue(columns[3], i),
Phone: rowMixedValue(columns[4], i),
Url: rowMixedValue(columns[5], i),
};
rowAttributes.push(row);
}
// insert records
// creating bulk records using older set of APIs
await createBulkRows(context, {
project,
table,
values: rowAttributes,
});
// retrieve inserted records
insertedRecords = await listRow({ project, table });
// verify length of unfiltered records to be 400
expect(insertedRecords.length).to.equal(400);
});
/////////////////////////////////////////////////////////////////////////////
// LIST
//
/////////////////////////////////////////////////////////////////////////////
it('List: default', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
);
const expectedPageInfo = {
totalRows: 400,
page: 1,
pageSize: 25,
isFirstPage: true,
isLastPage: false,
};
expect(rsp.body.pageInfo).to.deep.equal(expectedPageInfo);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
});
it('List: offset, limit', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ offset: 200, limit: 100 },
);
const expectedPageInfo = {
totalRows: 400,
page: 3,
pageSize: 100,
isFirstPage: false,
isLastPage: false,
};
expect(rsp.body.pageInfo).to.deep.equal(expectedPageInfo);
});
it('List: fields, single', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ fields: 'SingleLineText' },
);
expect(
verifyColumnsInRsp(rsp.body.list[0], [{ title: 'SingleLineText' }]),
).to.equal(true);
});
it('List: fields, multiple', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ fields: ['SingleLineText', 'MultiLineText'] },
);
expect(
verifyColumnsInRsp(rsp.body.list[0], [
{ title: 'SingleLineText' },
{ title: 'MultiLineText' },
]),
).to.equal(true);
});
it('List: sort, ascending', async function () {
const sortColumn = columns.find((c) => c.title === 'SingleLineText');
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ sort: 'SingleLineText', limit: 400 },
);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
const sortedArray = rsp.body.list.map((r) => r[sortColumn.title]);
expect(sortedArray).to.deep.equal(sortedArray.sort());
});
it('List: sort, descending', async function () {
const sortColumn = columns.find((c) => c.title === 'SingleLineText');
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ sort: '-SingleLineText', limit: 400 },
);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
const descSortedArray = rsp.body.list.map((r) => r[sortColumn.title]);
expect(descSortedArray).to.deep.equal(descSortedArray.sort().reverse());
});
it('List: sort, multiple', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ sort: ['-SingleLineText', '-MultiLineText'], limit: 400 },
);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
// Combination of SingleLineText & MultiLineText should be in descending order
const sortedArray = rsp.body.list.map(
(r) => r.SingleLineText + r.MultiLineText,
);
expect(sortedArray).to.deep.equal(sortedArray.sort().reverse());
});
it('List: filter, single', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ where: '(SingleLineText,eq,Afghanistan)', limit: 400 },
);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
const filteredArray = rsp.body.list.map((r) => r.SingleLineText);
expect(filteredArray).to.deep.equal(filteredArray.fill('Afghanistan'));
});
it('List: filter, multiple', async function () {
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
where:
'(SingleLineText,eq,Afghanistan)~and(MultiLineText,eq,Allahabad, India)',
limit: 400,
},
);
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
const filteredArray = rsp.body.list.map(
(r) => r.SingleLineText + ' ' + r.MultiLineText,
);
expect(filteredArray).to.deep.equal(
filteredArray.fill('Afghanistan Allahabad, India'),
);
});
it('List: view ID', async function () {
const gridView = await createView(context, {
title: 'grid0',
table,
type: ViewTypes.GRID,
});
const fk_column_id = columns.find((c) => c.title === 'SingleLineText').id;
await updateView(context, {
table,
view: gridView,
filter: [
{
comparison_op: 'eq',
fk_column_id,
logical_op: 'or',
value: 'Afghanistan',
},
],
});
// fetch records from view
let rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ viewId: gridView.id },
);
expect(rsp.body.pageInfo.totalRows).to.equal(31);
await updateView(context, {
table,
view: gridView,
filter: [
{
comparison_op: 'eq',
fk_column_id,
logical_op: 'or',
value: 'Austria',
},
],
});
// fetch records from view
rsp = await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
viewId: gridView.id,
});
expect(rsp.body.pageInfo.totalRows).to.equal(61);
// Sort by SingleLineText
await updateView(context, {
table,
view: gridView,
sort: [
{
direction: 'asc',
fk_column_id,
push_to_top: true,
},
],
});
// fetch records from view
rsp = await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
viewId: gridView.id,
});
expect(rsp.body.pageInfo.totalRows).to.equal(61);
// verify sorted order
// Would contain all 'Afghanistan' as we have 31 records for it
expect(verifyColumnsInRsp(rsp.body.list[0], columns)).to.equal(true);
const filteredArray = rsp.body.list.map((r) => r.SingleLineText);
expect(filteredArray).to.deep.equal(filteredArray.fill('Afghanistan'));
await updateView(context, {
table,
view: gridView,
field: ['SingleLineText'],
});
// fetch records from view
rsp = await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
viewId: gridView.id,
});
const displayColumns = columns.filter((c) => c.title !== 'SingleLineText');
expect(verifyColumnsInRsp(rsp.body.list[0], displayColumns)).to.equal(true);
});
async function prepareViewForTests() {
const gridView = await createView(context, {
title: 'grid0',
table,
type: ViewTypes.GRID,
});
const fk_column_id = columns.find((c) => c.title === 'SingleLineText').id;
await updateView(context, {
table,
view: gridView,
filter: [
{
comparison_op: 'eq',
fk_column_id,
logical_op: 'or',
value: 'Afghanistan',
},
{
comparison_op: 'eq',
fk_column_id,
logical_op: 'or',
value: 'Austria',
},
],
sort: [
{
direction: 'asc',
fk_column_id,
push_to_top: true,
},
],
field: ['MultiLineText', 'Email'],
});
// fetch records from view
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ viewId: gridView.id },
);
expect(rsp.body.pageInfo.totalRows).to.equal(61);
const displayColumns = columns.filter(
(c) => c.title !== 'MultiLineText' && c.title !== 'Email',
);
expect(verifyColumnsInRsp(rsp.body.list[0], displayColumns)).to.equal(true);
return gridView;
}
it('List: view ID + sort', async function () {
const gridView = await prepareViewForTests();
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
viewId: gridView.id,
sort: 'Url',
limit: 100,
},
);
const displayColumns = columns.filter(
(c) => c.title !== 'MultiLineText' && c.title !== 'Email',
);
expect(rsp.body.pageInfo.totalRows).to.equal(61);
expect(verifyColumnsInRsp(rsp.body.list[0], displayColumns)).to.equal(true);
const sortedArray = rsp.body.list.map((r) => r['Url']);
expect(sortedArray).to.deep.equal(sortedArray.sort());
});
it('List: view ID + filter', async function () {
const gridView = await prepareViewForTests();
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
viewId: gridView.id,
where: '(Phone,eq,1-541-754-3010)',
limit: 100,
},
);
const displayColumns = columns.filter(
(c) => c.title !== 'MultiLineText' && c.title !== 'Email',
);
expect(rsp.body.pageInfo.totalRows).to.equal(7);
expect(verifyColumnsInRsp(rsp.body.list[0], displayColumns)).to.equal(true);
const filteredArray = rsp.body.list.map((r) => r['Phone']);
expect(filteredArray).to.deep.equal(filteredArray.fill('1-541-754-3010'));
});
it('List: view ID + fields', async function () {
const gridView = await prepareViewForTests();
const rsp = await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
viewId: gridView.id,
fields: ['Phone', 'MultiLineText', 'SingleLineText', 'Email'],
limit: 100,
},
);
expect(rsp.body.pageInfo.totalRows).to.equal(61);
expect(
verifyColumnsInRsp(rsp.body.list[0], [
{ title: 'Phone' },
{ title: 'SingleLineText' },
]),
).to.equal(true);
});
// Error handling
it('List: invalid ID', async function () {
// Invalid table ID
await ncAxiosGet(`/api/v1/base/${project.id}/tables/123456789`, {}, 400);
// Invalid project ID
await ncAxiosGet(`/api/v1/base/123456789/tables/123456789`, {}, 400);
// Invalid view ID
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{ viewId: '123456789' },
400,
);
});
it('List: invalid limit & offset', async function () {
// Invalid limit
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
limit: -100,
},
200,
);
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
limit: 'abc',
},
200,
);
// Invalid offset
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
offset: -100,
},
200,
);
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
offset: 'abc',
},
200,
);
await ncAxiosGet(
`/api/v1/base/${project.id}/tables/${table.id}`,
{
offset: 10000,
},
200,
);
});
it('List: invalid sort, filter, fields', async function () {
await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
sort: 'abc',
});
await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
where: 'abc',
});
await ncAxiosGet(`/api/v1/base/${project.id}/tables/${table.id}`, {
fields: 'abc',
});
});
}
function numberBased() {
// prepare data for test cases
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project, {
table_name: 'numberBased',
title: 'numberBased',
columns: customColumns('numberBased'),
});
// retrieve column meta
columns = await table.getColumns();
// build records
const rowAttributes = [];
for (let i = 0; i < 400; i++) {
const row = {
Number: rowMixedValue(columns[1], i),
Decimal: rowMixedValue(columns[2], i),
Currency: rowMixedValue(columns[3], i),
Percent: rowMixedValue(columns[4], i),
Duration: rowMixedValue(columns[5], i),
Rating: rowMixedValue(columns[6], i),
};
rowAttributes.push(row);
}
// insert records
await createBulkRows(context, {
project,
table,
values: rowAttributes,
});
// retrieve inserted records
insertedRecords = await listRow({ project, table });
// verify length of unfiltered records to be 400
expect(insertedRecords.length).to.equal(400);
});
}
function selectBased() {
// prepare data for test cases
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project, {
table_name: 'selectBased',
title: 'selectBased',
columns: customColumns('selectBased'),
});
// retrieve column meta
columns = await table.getColumns();
// build records
const rowAttributes = [];
for (let i = 0; i < 400; i++) {
const row = {
SingleSelect: rowMixedValue(columns[1], i),
MultiSelect: rowMixedValue(columns[2], i),
};
rowAttributes.push(row);
}
// insert records
await createBulkRows(context, {
project,
table,
values: rowAttributes,
});
// retrieve inserted records
insertedRecords = await listRow({ project, table });
// verify length of unfiltered records to be 400
expect(insertedRecords.length).to.equal(400);
});
}
function dateBased() {
// prepare data for test cases
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project, {
table_name: 'dateBased',
title: 'dateBased',
columns: customColumns('dateBased'),
});
// retrieve column meta
columns = await table.getColumns();
// build records
// 800: one year before to one year after
const rowAttributes = [];
for (let i = 0; i < 800; i++) {
const row = {
Date: rowMixedValue(columns[1], i),
};
rowAttributes.push(row);
}
// insert records
await createBulkRows(context, {
project,
table,
values: rowAttributes,
});
// retrieve inserted records
insertedRecords = await listRow({ project, table });
// verify length of unfiltered records to be 800
expect(insertedRecords.length).to.equal(800);
});
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
export default function () {
// describe('General', generalDb);
describe('Text based', textBased);
// describe('Numerical', numberBased);
// describe('Select based', selectBased);
// describe('Date based', dateBased);
}
///////////////////////////////////////////////////////////////////////////////

Loading…
Cancel
Save