Browse Source

refactor/Added unit tests for table row data api

pull/3358/head
Muhammed Mustafa 2 years ago
parent
commit
607f0d1cbb
  1. 4
      packages/nocodb/package.json
  2. 70
      packages/nocodb/src/__tests__/tsconfig.json
  3. 30
      packages/nocodb/src/__tests__/unit/rest/init/cleanupMeta.ts
  4. 4
      packages/nocodb/src/__tests__/unit/rest/tests/helpers/project.ts
  5. 292
      packages/nocodb/src/__tests__/unit/rest/tests/tableRow.test.ts

4
packages/nocodb/package.json

@ -21,8 +21,8 @@
"local:test:graphql": "cross-env DATABASE_URL=mysql://root:password@localhost:3306/sakila TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register src/__tests__/graphql.test.ts --recursive --timeout 10000 --exit",
"test:graphql": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register src/__tests__/graphql.test.ts --recursive --timeout 10000 --exit",
"test:grpc": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register src/__tests__/grpc.test.ts --recursive --timeout 10000 --exit",
"local:test:rest": "cross-env mocha -r ts-node/register src/__tests__/unit/rest/index.test.ts --recursive --timeout 10000 --exit",
"test:rest": "cross-env mocha -r ts-node/register src/__tests__/unit/rest/index.test.ts --recursive --timeout 10000 --exit",
"local:test:rest": "cross-env TS_NODE_PROJECT=./src/__tests__/tsconfig.json mocha -r ts-node/register src/__tests__/unit/rest/index.test.ts --recursive --timeout 10000 --exit",
"test:rest": "cross-env TS_NODE_PROJECT=./src/__tests__/tsconfig.json mocha -r ts-node/register src/__tests__/unit/rest/index.test.ts --recursive --timeout 10000 --exit",
"test1": "run-s build test:*",
"test:lint": "tslint --project . && prettier \"src/**/*.ts\" --list-different",
"test:unit": "nyc --silent ava",

70
packages/nocodb/src/__tests__/tsconfig.json

@ -0,0 +1,70 @@
{
"compilerOptions": {
"skipLibCheck": true,
"composite": true,
"target": "es2017",
"outDir": "build/main",
"rootDir": "src",
"moduleResolution": "node",
"module": "commonjs",
"declaration": true,
"inlineSourceMap": true,
"esModuleInterop": true
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"allowJs": false,
// "strict": true /* Enable all strict type-checking options. */,
/* Strict Type-Checking Options */
// "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
// "strictNullChecks": true /* Enable strict null checks. */,
// "strictFunctionTypes": true /* Enable strict checking of function types. */,
// "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
// "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
// "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
"resolveJsonModule": true,
/* Additional Checks */
"noUnusedLocals": false
/* Report errors on unused locals. */,
"noUnusedParameters": false
/* Report errors on unused parameters. */,
"noImplicitReturns": false
/* Report error when not all code paths in function return a value. */,
"noFallthroughCasesInSwitch": false
/* Report errors for fallthrough cases in switch statement. */,
/* Debugging Options */
"traceResolution": false
/* Report module resolution log messages. */,
"listEmittedFiles": false
/* Print names of generated files part of the compilation. */,
"listFiles": false
/* Print names of files part of the compilation. */,
"pretty": true
/* Stylize errors and messages using color and context. */,
/* Experimental Options */
// "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
// "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
"lib": [
"es2017"
],
"types": [
"mocha", "node"
],
"typeRoots": [
"node_modules/@types",
"src/types"
]
},
"include": [
"src/**/*.ts",
// "src/lib/xgene/migrations/*.js",
"src/**/*.json"
],
"exclude": [
"node_modules/**",
"node_modules",
"../../../xc-lib-private/**",
"../../../xc-lib-private"
],
"compileOnSave": false
}

30
packages/nocodb/src/__tests__/unit/rest/init/cleanupMeta.ts

@ -2,23 +2,25 @@ import Model from '../../../../lib/models/Model';
import Project from '../../../../lib/models/Project';
import { orderedMetaTables } from '../../../../lib/utils/globals';
const dropTablesAllProjects = async (knexClient) => {
const dropTablesAllNonExternalProjects = async (knexClient) => {
const projects = await Project.list({});
const userCreatedTableNames = [];
await Promise.all(
projects.map(async (project) => {
await project.getBases();
const base = project.bases && project.bases[0];
if (!base) return;
projects
.filter((project) => project.is_meta)
.map(async (project) => {
await project.getBases();
const base = project.bases && project.bases[0];
if (!base) return;
const models = await Model.list({
project_id: project.id,
base_id: base.id,
});
models.forEach((model) => {
userCreatedTableNames.push(model.table_name);
});
})
const models = await Model.list({
project_id: project.id,
base_id: base.id,
});
models.forEach((model) => {
userCreatedTableNames.push(model.table_name);
});
})
);
await Promise.all(
@ -40,7 +42,7 @@ const cleanupMetaTables = async (knexClient) => {
export default async function (knexClient) {
try {
await dropTablesAllProjects(knexClient);
await dropTablesAllNonExternalProjects(knexClient);
await cleanupMetaTables(knexClient);
} catch (e) {
console.error('cleanupMeta', e);

4
packages/nocodb/src/__tests__/unit/rest/tests/helpers/project.ts

@ -42,7 +42,7 @@ const createSharedBase = async (app, token, project, sharedBaseArgs = {}) => {
});
};
const createExternalProject = async (context) => {
const createSakilaProject = async (context) => {
const response = await request(context.app)
.post('/api/v1/db/meta/projects/')
.set('xc-auth', context.token)
@ -62,4 +62,4 @@ const createProject = async (context, projectArgs = defaultProjectValue) => {
return project;
};
export { createProject, createSharedBase, createExternalProject };
export { createProject, createSharedBase, createSakilaProject };

292
packages/nocodb/src/__tests__/unit/rest/tests/tableRow.test.ts

@ -1,147 +1,181 @@
// import { expect } from 'chai';
import 'mocha';
import { createExternalProject } from './helpers/project';
import { createSakilaProject } from './helpers/project';
import Model from '../../../../lib/models/Model';
import init from '../init';
import request from 'supertest';
import { ColumnType } from 'nocodb-sdk';
const isColumnsCorrectInResponse = (response, columns: ColumnType[]) => {
const responseColumnsListStr = Object.keys(response.body.list[0])
.sort()
.join(',');
const customerColumnsListStr = columns
.map((c) => c.title)
.sort()
.join(',');
return responseColumnsListStr === customerColumnsListStr;
};
function tableTest() {
let context;
let project;
let customerTable: Model;
let customerColumns;
beforeEach(async function () {
context = await init();
project = await createExternalProject(context);
});
project = await createSakilaProject(context);
// it('Get table data list', async function () {
// const rowCount = 10;
// await createRows(rowCount);
// const response = await request(app)
// .get(`/api/v1/db/data/noco/${project.id}/${table.id}`)
// .set('xc-auth', token)
// .send({})
// .expect(200);
// if (response.body.list.length !== rowCount) {
// throw new Error('Wrong number of rows');
// }
// });
// it('Get table data list with required columns', async function () {
// const rowCount = 10;
// await createRows(rowCount);
// const newTitleColumn = columns.find((col) => col.title === 'New Title');
// const visibleColumns = [newTitleColumn.title];
// const response = await request(app)
// .get(`/api/v1/db/data/noco/${project.id}/${table.id}`)
// .set('xc-auth', token)
// .query({
// fields: visibleColumns,
// })
// .expect(200);
// if (response.body.list.length !== rowCount) {
// throw new Error('Wrong number of rows');
// }
// const sameArrayContent = (a: Array<any>, b: Array<any>) => {
// return a.length === b.length && a.every((v, i) => v === b[i]);
// };
// if (!sameArrayContent(Object.keys(response.body.list[0]), visibleColumns)) {
// console.error(Object.keys(response.body.list[0]), visibleColumns);
// throw new Error('Wrong column value');
// }
// });
// it('Get desc sorted table data list with required columns', async function () {
// const rowCount = 10;
// await createRows(rowCount);
// const newTitleColumn = columns.find((col) => col.title === 'New Title');
// const visibleColumns = [newTitleColumn.title];
// const sortInfo = [{ fk_column_id: newTitleColumn.id, direction: 'desc' }];
// const response = await request(app)
// .get(`/api/v1/db/data/noco/${project.id}/${table.id}`)
// .set('xc-auth', token)
// .query({
// fields: visibleColumns,
// sortArrJson: JSON.stringify(sortInfo),
// })
// .expect(200);
// if (response.body.list.length !== rowCount) {
// throw new Error('Wrong number of rows');
// }
// const sameArrayContent = (a: Array<any>, b: Array<any>) => {
// return a.length === b.length && a.every((v, i) => v === b[i]);
// };
// if (!sameArrayContent(Object.keys(response.body.list[0]), visibleColumns)) {
// console.error(Object.keys(response.body.list[0]), visibleColumns);
// throw new Error('Wrong column value');
// }
// if (
// response.body.list[0][newTitleColumn.title] !== 'test-9' ||
// response.body.list[response.body.list.length - 1][
// newTitleColumn.title
// ] !== 'test-0'
// ) {
// throw new Error('Wrong sort');
// }
// });
// it('Get asc sorted table data list with required columns', async function () {
// const rowCount = 10;
// await createRows(rowCount);
// const newTitleColumn = columns.find((col) => col.title === 'New Title');
// const visibleColumns = [newTitleColumn.title];
// const sortInfo = [{ fk_column_id: newTitleColumn.id, direction: 'asc' }];
// const response = await request(app)
// .get(`/api/v1/db/data/noco/${project.id}/${table.id}`)
// .set('xc-auth', token)
// .query({
// fields: visibleColumns,
// sortArrJson: JSON.stringify(sortInfo),
// })
// .expect(200);
// if (response.body.list.length !== rowCount) {
// throw new Error('Wrong number of rows');
// }
// const sameArrayContent = (a: Array<any>, b: Array<any>) => {
// return a.length === b.length && a.every((v, i) => v === b[i]);
// };
// if (!sameArrayContent(Object.keys(response.body.list[0]), visibleColumns)) {
// console.error(Object.keys(response.body.list[0]), visibleColumns);
// throw new Error('Wrong column value');
// }
// if (
// response.body.list[0][newTitleColumn.title] !== 'test-0' ||
// response.body.list[response.body.list.length - 1][
// newTitleColumn.title
// ] !== 'test-9'
// ) {
// throw new Error('Wrong sort');
// }
// });
it('Get actors', async () => {
const actorTable = await Model.getByIdOrName({
customerTable = await Model.getByIdOrName({
project_id: project.id,
base_id: project.bases[0].id,
table_name: 'actor',
table_name: 'customer',
});
console.log(actorTable);
customerColumns = await customerTable.getColumns();
});
it('Get table data list', async function () {
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.send({})
.expect(200);
if (response.body.list.length !== 25) {
throw new Error('Wrong number of rows');
}
if (!isColumnsCorrectInResponse(response, customerColumns)) {
throw new Error('Wrong columns');
}
});
it('Get table data list with required columns', async function () {
const requiredColumns = customerColumns.filter((_, index) => index < 3);
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.query({
fields: requiredColumns.map((c) => c.title),
})
.expect(200);
if (response.body.list.length !== 25) {
throw new Error('Wrong number of rows');
}
if (!isColumnsCorrectInResponse(response, requiredColumns)) {
throw new Error('Wrong columns');
}
});
it('Get desc sorted table data list with required columns', async function () {
const firstNameColumn = customerColumns.find(
(col) => col.title === 'FirstName'
);
const visibleColumns = [firstNameColumn];
const sortInfo = [{ fk_column_id: firstNameColumn.id, direction: 'desc' }];
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.query({
fields: visibleColumns.map((c) => c.title),
sortArrJson: JSON.stringify(sortInfo),
})
.expect(200);
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== 25) {
throw new Error('Wrong number of rows');
}
if (!isColumnsCorrectInResponse(response, visibleColumns)) {
console.log(response.body.list);
throw new Error('Wrong columns');
}
if (response.body.list[0][firstNameColumn.title] !== 'ZACHARY') {
console.log(response.body.list);
throw new Error('Wrong sort');
}
const lastPageOffset =
Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize;
const lastPageResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.query({
fields: visibleColumns.map((c) => c.title),
sortArrJson: JSON.stringify(sortInfo),
offset: lastPageOffset,
})
.expect(200);
if (
lastPageResponse.body.list[lastPageResponse.body.list.length - 1][
firstNameColumn.title
] !== 'AARON'
) {
console.log(lastPageOffset, lastPageResponse.body.list);
throw new Error('Wrong sort on last page');
}
});
it('Get asc sorted table data list with required columns', async function () {
const firstNameColumn = customerColumns.find(
(col) => col.title === 'FirstName'
);
const visibleColumns = [firstNameColumn];
const sortInfo = [{ fk_column_id: firstNameColumn.id, direction: 'asc' }];
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.query({
fields: visibleColumns.map((c) => c.title),
sortArrJson: JSON.stringify(sortInfo),
})
.expect(200);
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== 25) {
throw new Error('Wrong number of rows');
}
if (!isColumnsCorrectInResponse(response, visibleColumns)) {
console.log(response.body.list);
throw new Error('Wrong columns');
}
if (response.body.list[0][firstNameColumn.title] !== 'AARON') {
console.log(response.body.list);
throw new Error('Wrong sort');
}
const lastPageOffset =
Math.trunc(pageInfo.totalRows / pageInfo.pageSize) * pageInfo.pageSize;
const lastPageResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${project.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.query({
fields: visibleColumns.map((c) => c.title),
sortArrJson: JSON.stringify(sortInfo),
offset: lastPageOffset,
})
.expect(200);
if (
lastPageResponse.body.list[lastPageResponse.body.list.length - 1][
firstNameColumn.title
] !== 'ZACHARY'
) {
console.log(lastPageOffset, lastPageResponse.body.list);
throw new Error('Wrong sort on last page');
}
});
}

Loading…
Cancel
Save