Browse Source

refactor/Improve db config management of test env

pull/3358/head
Muhammed Mustafa 2 years ago
parent
commit
8b42ef15f6
  1. 2
      packages/nocodb/.gitignore
  2. 230
      packages/nocodb/tests/unit/TestDbMngr.ts
  3. 79
      packages/nocodb/tests/unit/factory/column.ts
  4. 19
      packages/nocodb/tests/unit/factory/row.ts
  5. 9
      packages/nocodb/tests/unit/factory/table.ts
  6. 14
      packages/nocodb/tests/unit/index.test.ts
  7. 25
      packages/nocodb/tests/unit/init/cleanupMeta.ts
  8. 36
      packages/nocodb/tests/unit/init/cleanupSakila.ts
  9. 6
      packages/nocodb/tests/unit/init/db.ts
  10. 65
      packages/nocodb/tests/unit/init/index.ts
  11. 2
      packages/nocodb/tests/unit/model/tests/baseModelSql.test.ts
  12. 14
      packages/nocodb/tests/unit/rest/tests/table.test.ts
  13. 124
      packages/nocodb/tests/unit/rest/tests/tableRow.test.ts

2
packages/nocodb/.gitignore vendored

@ -16,3 +16,5 @@ xc.db*
noco.db*
/nc/
/docker/main.js
test_meta.db
test_sakila.db

230
packages/nocodb/tests/unit/TestDbMngr.ts

@ -2,23 +2,28 @@ import { DbConfig } from "../../src/interface/config";
import { NcConfigFactory } from "../../src/lib";
import SqlMgrv2 from "../../src/lib/db/sql-mgr/v2/SqlMgrv2";
import fs from 'fs';
import knex from "knex";
import process from "process";
export default class TestDbMngr {
public static readonly dbName = 'test_meta';
public static readonly sakilaDbName = 'test_sakila';
public static metaKnex: knex;
public static sakilaKnex: knex;
public static dbConfig: DbConfig;
static switchToSqlite() {
process.env[`DATABASE_URL`] = `sqlite:///${TestDbMngr.dbName}.sqlite`;
TestDbMngr.dbConfig = NcConfigFactory.urlToDbConfig(
NcConfigFactory.extractXcUrlFromJdbc(process.env[`DATABASE_URL`])
);
public static defaultConnection = {
user: process.env['DB_USER'] || 'root',
password: process.env['DB_PASSWORD'] || 'password',
host: process.env['DB_HOST'] || 'localhost',
port: Number(process.env['DB_PORT']) || 3306,
client: 'mysql2',
}
static async testConnection() {
public static dbConfig: DbConfig;
static async testConnection(config: DbConfig) {
try {
return await SqlMgrv2.testConnection(TestDbMngr.dbConfig);
return await SqlMgrv2.testConnection(config);
} catch (e) {
console.log(e);
return { code: -1, message: 'Connection invalid' };
@ -26,12 +31,50 @@ export default class TestDbMngr {
}
static async init({
user = 'root',
password = 'password',
host = 'localhost',
port = 3306,
client = 'mysql2',
user = TestDbMngr.defaultConnection.user,
password = TestDbMngr.defaultConnection.password,
host = TestDbMngr.defaultConnection.host,
port = TestDbMngr.defaultConnection.port,
client = TestDbMngr.defaultConnection.client,
} = {}) {
if(await TestDbMngr.isMysqlConfigured({ user, password, host, port, client })){
await TestDbMngr.connectMysql({ user, password, host, port, client });
} else {
await TestDbMngr.switchToSqlite();
}
}
static async isMysqlConfigured({
user,
password,
host,
port,
client,
}: {
user: string,
password: string,
host: string,
port: number,
client: string,
}) {
const config = NcConfigFactory.urlToDbConfig(`${client}://${user}:${password}@${host}:${port}`);
config.connection = {
user,
password,
host,
port,
}
const result = await TestDbMngr.testConnection(config);
return result.code !== -1;
}
static async connectMysql({
user = TestDbMngr.defaultConnection.user,
password = TestDbMngr.defaultConnection.password,
host = TestDbMngr.defaultConnection.host,
port = TestDbMngr.defaultConnection.port,
client = TestDbMngr.defaultConnection.client,
}) {
if(!process.env[`DATABASE_URL`]){
process.env[`DATABASE_URL`] = `${client}://${user}:${password}@${host}:${port}/${TestDbMngr.dbName}`;
}
@ -53,31 +96,170 @@ export default class TestDbMngr {
},
}
const result = await TestDbMngr.testConnection()
if(result.code === -1){
TestDbMngr.switchToSqlite();
await TestDbMngr.setupMeta();
await TestDbMngr.setupSakila();
}
static async setupMeta() {
if(TestDbMngr.metaKnex){
await TestDbMngr.metaKnex.destroy();
}
if(TestDbMngr.isSqlite()){
await TestDbMngr.resetMetaSqlite();
TestDbMngr.metaKnex = knex(TestDbMngr.getMetaDbConfig());
return
}
TestDbMngr.metaKnex = knex(TestDbMngr.getDbConfigWithNoDb());
await TestDbMngr.resetDatabase(TestDbMngr.metaKnex, TestDbMngr.dbName);
await TestDbMngr.metaKnex.destroy();
TestDbMngr.metaKnex = knex(TestDbMngr.getMetaDbConfig());
await TestDbMngr.useDatabase(TestDbMngr.metaKnex, TestDbMngr.dbName);
}
static async setupSakila () {
if(TestDbMngr.sakilaKnex) {
await TestDbMngr.sakilaKnex.destroy();
}
if(TestDbMngr.isSqlite()){
await TestDbMngr.seedSakila();
TestDbMngr.sakilaKnex = knex(TestDbMngr.getSakilaDbConfig());
return
}
TestDbMngr.sakilaKnex = knex(TestDbMngr.getDbConfigWithNoDb());
await TestDbMngr.resetDatabase(TestDbMngr.sakilaKnex, TestDbMngr.sakilaDbName);
await TestDbMngr.sakilaKnex.destroy();
TestDbMngr.sakilaKnex = knex(TestDbMngr.getSakilaDbConfig());
await TestDbMngr.useDatabase(TestDbMngr.sakilaKnex, TestDbMngr.sakilaDbName);
}
static async switchToSqlite() {
// process.env[`DATABASE_URL`] = `sqlite3:///?database=${__dirname}/${TestDbMngr.dbName}.sqlite`;
TestDbMngr.dbConfig = {
client: 'sqlite3',
connection: {
filename: `${__dirname}/${TestDbMngr.dbName}.db`,
database: TestDbMngr.dbName,
},
useNullAsDefault: true,
meta: {
tn: 'nc_evolutions',
dbAlias: 'db',
api: {
type: 'rest',
prefix: '',
graphqlDepthLimit: 10,
},
inflection: {
tn: 'camelize',
cn: 'camelize',
},
},
}
process.env[`NC_DB`] = `sqlite3:///?database=${__dirname}/${TestDbMngr.dbName}.db`;
await TestDbMngr.setupMeta();
await TestDbMngr.setupSakila();
}
private static async resetDatabase(knexClient, dbName) {
if(TestDbMngr.isSqlite()){
// return knexClient.raw(`DELETE FROM sqlite_sequence`);
} else {
try {
await knexClient.raw(`DROP DATABASE ${dbName}`);
} catch(e) {}
await knexClient.raw(`CREATE DATABASE ${dbName}`);
console.log(`Database ${dbName} created`);
await knexClient.raw(`USE ${dbName}`);
}
}
static isSqlite() {
return TestDbMngr.dbConfig.client === 'sqlite3';
}
private static async useDatabase(knexClient, dbName) {
if(!TestDbMngr.isSqlite()){
await knexClient.raw(`USE ${dbName}`);
}
}
static getDbConfigWithNoDb() {
const dbConfig =JSON.parse(JSON.stringify(TestDbMngr.dbConfig));
delete dbConfig.connection.database;
return dbConfig;
}
static getMetaDbConfig() {
return TestDbMngr.dbConfig;
}
private static resetMetaSqlite() {
if(fs.existsSync(`${__dirname}/test_meta.db`)){
fs.unlinkSync(`${__dirname}/test_meta.db`);
}
}
static getSakilaDbConfig() {
const sakilaDbConfig = { ...TestDbMngr.dbConfig };
const sakilaDbConfig = JSON.parse(JSON.stringify(TestDbMngr.dbConfig));
sakilaDbConfig.connection.database = TestDbMngr.sakilaDbName;
sakilaDbConfig.connection.multipleStatements = true
if(TestDbMngr.isSqlite()){
sakilaDbConfig.connection.filename = `${__dirname}/test_sakila.db`;
}
return sakilaDbConfig;
}
static async seedSakila(sakilaKnexClient) {
static async seedSakila() {
const testsDir = __dirname.replace('tests/unit', 'tests');
const schemaFile = fs.readFileSync(`${testsDir}/mysql-sakila-db/03-test-sakila-schema.sql`).toString();
const dataFile = fs.readFileSync(`${testsDir}/mysql-sakila-db/04-test-sakila-data.sql`).toString();
await sakilaKnexClient.raw(schemaFile);
await sakilaKnexClient.raw(dataFile);
if(TestDbMngr.isSqlite()){
if(fs.existsSync(`${__dirname}/test_sakila.db`)){
fs.unlinkSync(`${__dirname}/test_sakila.db`);
}
fs.copyFileSync(`${testsDir}/sqlite-sakila-db/sakila.db`, `${__dirname}/test_sakila.db`);
} else {
const schemaFile = fs.readFileSync(`${testsDir}/mysql-sakila-db/03-test-sakila-schema.sql`).toString();
const dataFile = fs.readFileSync(`${testsDir}/mysql-sakila-db/04-test-sakila-data.sql`).toString();
await TestDbMngr.sakilaKnex.raw(schemaFile);
await TestDbMngr.sakilaKnex.raw(dataFile);
}
}
static async disableForeignKeyChecks(knexClient) {
if(TestDbMngr.isSqlite()){
await knexClient.raw("PRAGMA foreign_keys = OFF");
}
else {
await knexClient.raw(`SET FOREIGN_KEY_CHECKS = 0`);
}
}
static async enableForeignKeyChecks(knexClient) {
if(TestDbMngr.isSqlite()){
await knexClient.raw(`PRAGMA foreign_keys = ON;`);
}
else {
await knexClient.raw(`SET FOREIGN_KEY_CHECKS = 1`);
}
}
static async showAllTables(knexClient) {
if(TestDbMngr.isSqlite()){
const tables = await knexClient.raw(`SELECT name FROM sqlite_master WHERE type='table'`);
return tables.filter(t => t.name !== 'sqlite_sequence' && t.name !== '_evolutions').map(t => t.name);
}
else {
const response = await knexClient.raw(`SHOW TABLES`);
return response[0].map(
(table) => Object.values(table)[0]
);
}
}
}

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

@ -7,101 +7,38 @@ import GridViewColumn from '../../../src/lib/models/GridViewColumn';
import Model from '../../../src/lib/models/Model';
import Project from '../../../src/lib/models/Project';
import View from '../../../src/lib/models/View';
import { isSqlite } from '../init/db';
const defaultColumns = [
const defaultColumns = function(context) {
return [
{
ai: true,
altered: 1,
cdf: null,
ck: false,
clen: null,
column_name: 'id',
ct: 'int(11)',
dt: 'int',
dtx: 'integer',
dtxp: '11',
dtxs: '',
np: 11,
nrqd: false,
ns: 0,
pk: true,
rqd: true,
title: 'Id',
uicn: '',
uidt: 'ID',
uip: '',
un: true,
},
{
ai: false,
altered: 1,
cdf: null,
ck: false,
clen: 45,
column_name: 'title',
ct: 'varchar(45)',
dt: 'varchar',
dtx: 'specificType',
dtxp: '45',
dtxs: '',
np: null,
nrqd: true,
ns: null,
pk: false,
rqd: false,
title: 'Title',
uicn: '',
uidt: 'SingleLineText',
uip: '',
un: false,
},
{
ai: false,
altered: 1,
cdf: 'CURRENT_TIMESTAMP',
ck: false,
clen: 45,
column_name: 'created_at',
ct: 'varchar(45)',
dt: 'timestamp',
dtx: 'specificType',
title: 'CreatedAt',
dtxp: '',
dtxs: '',
np: null,
nrqd: true,
ns: null,
pk: false,
rqd: false,
title: 'CreatedAt',
uicn: '',
uidt: 'DateTime',
uip: '',
un: false,
},
{
ai: false,
altered: 1,
cdf: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
ck: false,
clen: 45,
cdf: isSqlite(context) ? 'CURRENT_TIMESTAMP': 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
column_name: 'updated_at',
ct: 'varchar(45)',
dt: 'timestamp',
dtx: 'specificType',
title: 'UpdatedAt',
dtxp: '',
dtxs: '',
np: null,
nrqd: true,
ns: null,
pk: false,
rqd: false,
title: 'UpdatedAt',
uicn: '',
uidt: 'DateTime',
uip: '',
un: false,
},
];
]
};
const createColumn = async (context, table, columnAttr) => {
await request(context.app)

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

@ -110,6 +110,24 @@ const createRow = async (
return response.body;
};
const createBulkRows = async (
context,
{
project,
table,
values
}: {
project: Project;
table: Model;
values: any[];
}) => {
await request(context.app)
.post(`/api/v1/db/data/bulk/noco/${project.id}/${table.id}`)
.set('xc-auth', context.token)
.send(values)
.expect(200);
}
// Links 2 table rows together. Will create rows if ids are not provided
const createChildRow = async (
context,
@ -159,4 +177,5 @@ export {
getOneRow,
listRow,
generateDefaultRowAttributes,
createBulkRows
};

9
packages/nocodb/tests/unit/factory/table.ts

@ -3,17 +3,18 @@ import Model from '../../../src/lib/models/Model';
import Project from '../../../src/lib/models/Project';
import { defaultColumns } from './column';
const defaultTableValue = {
const defaultTableValue = (context) => ({
table_name: 'Table1',
title: 'Table1_Title',
columns: defaultColumns,
};
columns: defaultColumns(context),
});
const createTable = async (context, project, args = {}) => {
const defaultValue = defaultTableValue(context);
const response = await request(context.app)
.post(`/api/v1/db/meta/projects/${project.id}/tables`)
.set('xc-auth', context.token)
.send({ ...defaultTableValue, ...args });
.send({ ...defaultValue, ...args });
const table: Model = await Model.get(response.body.id);
return table;

14
packages/nocodb/tests/unit/index.test.ts

@ -1,7 +1,5 @@
import 'mocha';
import knex from 'knex';
import restTests from './rest/index.test';
import modelTests from './model/index.test';
import TestDbMngr from './TestDbMngr'
@ -11,22 +9,10 @@ process.env.TEST = 'test';
process.env.NC_DISABLE_CACHE = 'true';
process.env.NC_DISABLE_TELE = 'true';
const setupTestMetaDb = async () => {
const knexClient = knex(TestDbMngr.getMetaDbConfig());
const dbName = TestDbMngr.dbName;
try {
await knexClient.raw(`DROP DATABASE ${dbName}`);
} catch (e) {}
await knexClient.raw(`CREATE DATABASE ${dbName}`);
}
(async function() {
await TestDbMngr.init();
await setupTestMetaDb();
modelTests();
restTests();

25
packages/nocodb/tests/unit/init/cleanupMeta.ts

@ -2,8 +2,9 @@ import Model from "../../../src/lib/models/Model";
import Project from "../../../src/lib/models/Project";
import NcConnectionMgrv2 from "../../../src/lib/utils/common/NcConnectionMgrv2";
import { orderedMetaTables } from "../../../src/lib/utils/globals";
import TestDbMngr from "../TestDbMngr";
const dropTablesAllNonExternalProjects = async (knexClient) => {
const dropTablesAllNonExternalProjects = async () => {
const projects = await Project.list({});
const userCreatedTableNames: string[] = [];
await Promise.all(
@ -24,29 +25,31 @@ const dropTablesAllNonExternalProjects = async (knexClient) => {
})
);
await knexClient.raw('SET FOREIGN_KEY_CHECKS = 0');
await TestDbMngr.disableForeignKeyChecks(TestDbMngr.metaKnex);
for (const tableName of userCreatedTableNames) {
await knexClient.raw(`DROP TABLE ${tableName}`);
await TestDbMngr.metaKnex.raw(`DROP TABLE ${tableName}`);
}
await knexClient.raw('SET FOREIGN_KEY_CHECKS = 1');
await TestDbMngr.enableForeignKeyChecks(TestDbMngr.metaKnex);
};
const cleanupMetaTables = async (knexClient) => {
await knexClient.raw('SET FOREIGN_KEY_CHECKS = 0');
const cleanupMetaTables = async () => {
await TestDbMngr.disableForeignKeyChecks(TestDbMngr.metaKnex);
for (const tableName of orderedMetaTables) {
try {
await knexClient.raw(`DELETE FROM ${tableName}`);
await TestDbMngr.metaKnex.raw(`DELETE FROM ${tableName}`);
} catch (e) {}
}
await knexClient.raw('SET FOREIGN_KEY_CHECKS = 1');
await TestDbMngr.enableForeignKeyChecks(TestDbMngr.metaKnex);
};
export default async function (knexClient) {
export default async function () {
try {
await NcConnectionMgrv2.destroyAll();
await dropTablesAllNonExternalProjects(knexClient);
await cleanupMetaTables(knexClient);
await dropTablesAllNonExternalProjects();
await cleanupMetaTables();
} catch (e) {
console.error('cleanupMeta', e);
}

36
packages/nocodb/tests/unit/init/cleanupSakila.ts

@ -3,51 +3,45 @@ import Project from '../../../src/lib/models/Project';
import TestDbMngr from '../TestDbMngr';
const dropTablesOfSakila = async (sakilaKnexClient) => {
await sakilaKnexClient.raw('SET FOREIGN_KEY_CHECKS = 0');
try{
for(const tableName of sakilaTableNames){
await sakilaKnexClient.raw(`DROP TABLE ${tableName}`);
}
} catch (e) {
const dropTablesOfSakila = async () => {
await TestDbMngr.disableForeignKeyChecks(TestDbMngr.sakilaKnex);
for(const tableName of sakilaTableNames){
try {
await TestDbMngr.sakilaKnex.raw(`DROP TABLE ${tableName}`);
} catch(e){}
}
await sakilaKnexClient.raw('SET FOREIGN_KEY_CHECKS = 1');
await TestDbMngr.enableForeignKeyChecks(TestDbMngr.sakilaKnex);
}
const resetAndSeedSakila = async (sakilaKnexClient) => {
const resetAndSeedSakila = async () => {
try {
await dropTablesOfSakila(sakilaKnexClient);
await TestDbMngr.seedSakila(sakilaKnexClient);
await sakilaKnexClient.raw(`USE ${TestDbMngr.sakilaDbName}`);
await dropTablesOfSakila();
await TestDbMngr.seedSakila();
} catch (e) {
console.error('resetSakila', e);
throw e
}
}
const cleanUpSakila = async (sakilaKnexClient) => {
const cleanUpSakila = async () => {
try {
const sakilaProject = await Project.getByTitle('sakila');
const audits = sakilaProject && await Audit.projectAuditList(sakilaProject.id, {});
if(audits?.length > 0) {
return await resetAndSeedSakila(sakilaKnexClient);
return await resetAndSeedSakila();
}
const tablesInSakilaQueryRes = await sakilaKnexClient.raw(`SHOW TABLES;`);
const tablesInSakila = tablesInSakilaQueryRes[0].map(
(table) => Object.values(table)[0]
);
const tablesInSakila = await TestDbMngr.showAllTables(TestDbMngr.sakilaKnex);
await Promise.all(
tablesInSakila
.filter((tableName) => !sakilaTableNames.includes(tableName))
.map(async (tableName) => {
try {
await sakilaKnexClient.raw(`DROP TABLE ${tableName}`);
await TestDbMngr.sakilaKnex.raw(`DROP TABLE ${tableName}`);
} catch (e) {
console.error(e);
}

6
packages/nocodb/tests/unit/init/db.ts

@ -1,8 +1,10 @@
import { DbConfig } from "../../../src/interface/config";
const isSqlite = (context) =>
(context.dbConfig as DbConfig).client === 'sqlite';
const isSqlite = (context) =>{
console.log(context.dbConfig, (context.dbConfig as DbConfig).client === 'sqlite' || (context.dbConfig as DbConfig).client === 'sqlite3');
return (context.dbConfig as DbConfig).client === 'sqlite' || (context.dbConfig as DbConfig).client === 'sqlite3';
}
const isMysql = (context) =>
(context.dbConfig as DbConfig).client === 'mysql' ||

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

@ -1,77 +1,40 @@
import express from 'express';
import knex from 'knex';
import { Noco } from '../../../src/lib';
import cleanupMeta from './cleanupMeta';
import {cleanUpSakila, resetAndSeedSakila} from './cleanupSakila';
import { createUser } from '../factory/user';
import TestDbMngr from '../TestDbMngr';
let server;
let knexClient;
let sakilaKnexClient;
const serverInit = async () => {
const serverInstance = express();
serverInstance.enable('trust proxy');
serverInstance.use(await Noco.init());
serverInstance.use(function(req, res, next){
// 50 sec timeout
req.setTimeout(500000, function(){
console.log('Request has timed out.');
res.send(408);
});
next();
});
return serverInstance;
};
const resetDatabase = async () => {
try {
if (!Noco.initialized) {
try {
await knexClient.raw(`DROP DATABASE ${TestDbMngr.dbName}`);
} catch (e) {}
await knexClient.raw(`CREATE DATABASE ${TestDbMngr.dbName}`);
}
} catch (e) {
console.error('resetDatabase', e);
}
};
const cleanupAllTables = async () => {
try {
await cleanUpSakila(sakilaKnexClient);
await cleanupMeta(knexClient);
} catch (e) {
console.error('cleanupAllTables', e);
}
};
const setupSakila = async () => {
try {
await knexClient.raw(`DROP DATABASE ${TestDbMngr.sakilaDbName}`);
} catch(e) {
console.log('setupSakila',e)
}
await knexClient.raw(`CREATE DATABASE ${TestDbMngr.sakilaDbName}`);
await knexClient.raw(`USE ${TestDbMngr.dbName}`);
sakilaKnexClient = knex(TestDbMngr.getSakilaDbConfig());
await sakilaKnexClient.raw(`USE ${TestDbMngr.sakilaDbName}`);
await resetAndSeedSakila(sakilaKnexClient);
}
const isFirstTimeRun = () => !server
export default async function () {
if(!knexClient) {
knexClient = knex(TestDbMngr.dbConfig);
}
await knexClient.raw(`USE ${TestDbMngr.dbName}`);
await resetDatabase();
export default async function () {
const {default: TestDbMngr} = await import('../TestDbMngr');
if (isFirstTimeRun()) {
await setupSakila();
await resetAndSeedSakila();
server = await serverInit();
}
await cleanupAllTables();
await cleanUpSakila();
await cleanupMeta();
const { token } = await createUser({ app: server }, { roles: 'editor' });

2
packages/nocodb/tests/unit/model/tests/baseModelSql.test.ts

@ -26,7 +26,7 @@ function baseModelSqlTests() {
context = await init();
project = await createProject(context);
table = await createTable(context, project);
view = table.getViews()[0];
view = await table.getViews()[0];
const base = await Base.get(table.base_id);
baseModelSql = new BaseModelSqlv2({

14
packages/nocodb/tests/unit/rest/tests/table.test.ts

@ -36,7 +36,7 @@ function tableTest() {
.send({
table_name: 'table2',
title: 'new_title_2',
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(200);
@ -45,7 +45,7 @@ function tableTest() {
return new Error('Tables is not be created');
}
if (response.body.columns.length !== defaultColumns.length) {
if (response.body.columns.length !== (defaultColumns(context))) {
return new Error('Columns not saved properly');
}
@ -66,7 +66,7 @@ function tableTest() {
.send({
table_name: undefined,
title: 'new_title',
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(400);
@ -95,7 +95,7 @@ function tableTest() {
.send({
table_name: table.table_name,
title: 'New_title',
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(400);
@ -117,7 +117,7 @@ function tableTest() {
.send({
table_name: 'New_table_name',
title: table.title,
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(400);
@ -139,7 +139,7 @@ function tableTest() {
.send({
table_name: 'a'.repeat(256),
title: 'new_title',
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(400);
@ -162,7 +162,7 @@ function tableTest() {
.send({
table_name: 'table_name_with_whitespace ',
title: 'new_title',
columns: defaultColumns,
columns: defaultColumns(context),
})
.expect(400);

124
packages/nocodb/tests/unit/rest/tests/tableRow.test.ts

@ -17,6 +17,7 @@ import {
getOneRow,
getRow,
listRow,
createBulkRows,
} from '../../factory/row';
import { isMysql, isSqlite } from '../../init/db';
import Model from '../../../../src/lib/models/Model';
@ -58,6 +59,7 @@ function tableTest() {
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== pageInfo.pageSize) {
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
@ -79,6 +81,7 @@ function tableTest() {
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== pageInfo.pageSize) {
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
@ -105,6 +108,7 @@ function tableTest() {
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== pageInfo.pageSize) {
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
@ -158,6 +162,7 @@ function tableTest() {
const pageInfo = response.body.pageInfo;
if (response.body.list.length !== pageInfo.pageSize) {
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
@ -292,8 +297,10 @@ function tableTest() {
})
.expect(200);
if (response.body.pageInfo.totalRows !== 24)
if (response.body.pageInfo.totalRows !== 24){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
response.body.list.forEach((row) => {
if (row[lookupColumn.title] !== 'AARON') throw new Error('Wrong filter');
@ -325,8 +332,10 @@ function tableTest() {
})
.expect(200);
if (response.body.pageInfo.totalRows !== 158)
if (response.body.pageInfo.totalRows !== 158){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
});
it('Get nested sorted filtered table data list with a lookup column', async function () {
@ -391,8 +400,10 @@ function tableTest() {
})
.expect(200);
if (response.body.pageInfo.totalRows !== 9133)
if (response.body.pageInfo.totalRows !== 9133){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (response.body.list[0][lookupColumn.title] !== 'ANDREW')
throw new Error('Wrong filter');
@ -411,8 +422,10 @@ function tableTest() {
})
.expect(200);
if (ascResponse.body.pageInfo.totalRows !== 9133)
if (ascResponse.body.pageInfo.totalRows !== 9133){
console.log(ascResponse.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (ascResponse.body.list[0][lookupColumn.title] !== 'AARON') {
console.log(ascResponse.body.list[0][lookupColumn.title]);
@ -433,8 +446,10 @@ function tableTest() {
})
.expect(200);
if (descResponse.body.pageInfo.totalRows !== 9133)
if (descResponse.body.pageInfo.totalRows !== 9133){
console.log(descResponse.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (descResponse.body.list[0][lookupColumn.title] !== 'ZACHARY')
throw new Error('Wrong filter');
@ -513,11 +528,15 @@ function tableTest() {
})
.expect(200);
if (response.body.pageInfo.totalRows !== 594)
if (response.body.pageInfo.totalRows !== 594){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (response.body.list[0][rollupColumn.title] !== 32)
throw new Error('Wrong filter');
if (response.body.list[0][rollupColumn.title] !== 32){
console.log(response.body.list[0])
throw new Error('Wrong filter response 0');
}
const ascResponse = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}`)
@ -537,12 +556,14 @@ function tableTest() {
})
.expect(200);
if (ascResponse.body.pageInfo.totalRows !== 594)
if (ascResponse.body.pageInfo.totalRows !== 594){
console.log(ascResponse.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (ascResponse.body.list[0][rollupColumn.title] !== 12) {
console.log(ascResponse.body.list[0][rollupColumn.title]);
throw new Error('Wrong filter');
throw new Error('Wrong filter ascResponse 0');
}
if (
@ -550,7 +571,7 @@ function tableTest() {
'1308 Sumy Loop'
) {
console.log(ascResponse.body.list[1]);
throw new Error('Wrong filter');
throw new Error('Wrong filter ascResponse 1');
}
const descResponse = await request(context.app)
@ -571,18 +592,22 @@ function tableTest() {
})
.expect(200);
if (descResponse.body.pageInfo.totalRows !== 594)
if (descResponse.body.pageInfo.totalRows !== 594){
console.log(descResponse.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (descResponse.body.list[0][rollupColumn.title] !== 46)
throw new Error('Wrong filter');
if (descResponse.body.list[0][rollupColumn.title] !== 46){
console.log(descResponse.body.list[0]);
throw new Error('Wrong filter descResponse 0');
}
if (
descResponse.body.list[2][addressColumn.title]['Address'] !==
'1479 Rustenburg Boulevard'
) {
console.log(descResponse.body.list[2]);
throw new Error('Wrong filter');
throw new Error('Wrong filter descResponse 2');
}
});
@ -666,8 +691,10 @@ function tableTest() {
})
.expect(200);
if (ascResponse.body.pageInfo.totalRows !== 594)
if (ascResponse.body.pageInfo.totalRows !== 594){
console.log(ascResponse.body.pageInfo)
throw new Error('Wrong number of rows');
}
if (ascResponse.body.list[0][rollupColumn.title] !== 12) {
throw new Error('Wrong filter');
@ -1268,7 +1295,7 @@ function tableTest() {
}
// Max 10 rows will be inserted in sqlite
if (isSqlite(context) && response.body.length !== 10) {
if ((isSqlite(context) && rows.length !== rowAttributes.length)) {
throw new Error('Wrong number of rows inserted');
}
} else {
@ -1293,21 +1320,21 @@ function tableTest() {
.expect(200);
const rows = await listRow({ project, table });
// Mysql will not return the batched inserted rows
if (!isMysql(context)) {
if (
!isSqlite(context) &&
response.body.length !== rowAttributes.length &&
rows.length !== rowAttributes.length
) {
throw new Error('Wrong number of rows inserted');
}
// Max 10 rows will be inserted in sqlite
if (isSqlite(context) && response.body.length !== 10) {
throw new Error('Wrong number of rows inserted');
}
) {
throw new Error('Wrong number of rows inserted');
}
// Max 10 rows will be inserted in sqlite
if (isSqlite(context) && rows.length !== rowAttributes.length) {
console.log(response.body)
throw new Error('Wrong number of rows inserted');
}
} else {
if (rows.length !== rowAttributes.length) {
throw new Error('Wrong number of rows inserted');
@ -1316,17 +1343,24 @@ function tableTest() {
});
it('Bulk update', async function () {
// todo: Find why bulk update in sqlite is hanging
if(isSqlite(context)) {
return
}
const table = await createTable(context, project);
const columns = await table.getColumns();
const arr = Array(120)
const rowAttributes = Array(400)
.fill(0)
.map((_, index) => index);
for (const index of arr) {
await createRow(context, { project, table, index });
}
.map((index) => generateDefaultRowAttributes({ columns, index }));
await createBulkRows(context, {
project,
table,
values: rowAttributes
});
const rows = await listRow({ project, table });
await request(context.app)
.patch(`/api/v1/db/data/bulk/noco/${project.id}/${table.id}`)
.set('xc-auth', context.token)
@ -1334,7 +1368,6 @@ function tableTest() {
rows.map((row) => ({ title: `new-${row['Title']}`, id: row['Id'] }))
)
.expect(200);
const updatedRows: Array<any> = await listRow({ project, table });
if (!updatedRows.every((row) => row['Title'].startsWith('new-'))) {
throw new Error('Wrong number of rows updated');
@ -1342,14 +1375,23 @@ function tableTest() {
});
it('Bulk delete', async function () {
// todo: Find why bulk delete in sqlite is hanging
if(isSqlite(context)) {
return
}
const table = await createTable(context, project);
const columns = await table.getColumns();
const arr = Array(120)
const rowAttributes = Array(400)
.fill(0)
.map((_, index) => index);
for (const index of arr) {
await createRow(context, { project, table, index });
}
.map((index) => generateDefaultRowAttributes({ columns, index }));
await createBulkRows(context, {
project,
table,
values: rowAttributes
});
const rows = await listRow({ project, table });
@ -1856,6 +1898,10 @@ function tableTest() {
})
it('Exclude list hm', async () => {
// todo: Find why sqlite not working with this
if(isSqlite(context)) {
return
}
const rowId = 1;
const rentalListColumn = (await customerTable.getColumns()).find(
(column) => column.title === 'Rental List'
@ -1867,6 +1913,7 @@ function tableTest() {
.expect(200);
if(response.body.pageInfo.totalRows !== 16012){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows')
}
})
@ -1887,6 +1934,7 @@ function tableTest() {
.expect(200);
if(response.body.pageInfo.totalRows !== 16012 ){
console.log(response.body.pageInfo)
throw new Error('Wrong number of rows')
}

Loading…
Cancel
Save