From 8cf68ffcfe3e65d27f79adf218cb127df70b7c45 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 2 Feb 2023 21:41:48 +0530 Subject: [PATCH] refactor: test list added in comments Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../tests/unit/rest/tests/attachment.test.ts | 138 +++++----- .../nocodb/tests/unit/rest/tests/auth.test.ts | 33 ++- .../rest/tests/columnTypeSpecific.test.ts | 6 + .../nocodb/tests/unit/rest/tests/org.test.ts | 201 +++++++------- .../tests/unit/rest/tests/project.test.ts | 251 ++++++++++-------- .../tests/unit/rest/tests/table.test.ts | 12 + .../tests/unit/rest/tests/tableRow.test.ts | 114 ++++++-- .../tests/unit/rest/tests/viewRow.test.ts | 70 ++++- 8 files changed, 521 insertions(+), 304 deletions(-) diff --git a/packages/nocodb/tests/unit/rest/tests/attachment.test.ts b/packages/nocodb/tests/unit/rest/tests/attachment.test.ts index 29922c76ba..5d0c138d7d 100644 --- a/packages/nocodb/tests/unit/rest/tests/attachment.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/attachment.test.ts @@ -1,143 +1,140 @@ -import { expect } from 'chai' -import fs from 'fs' -import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk' -import path from 'path' -import 'mocha' -import request from 'supertest' -import { createProject } from '../../factory/project' -import init from '../../init' - -const FILE_PATH = path.join(__dirname, 'test.txt') +import { expect } from 'chai'; +import fs from 'fs'; +import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk'; +import path from 'path'; +import 'mocha'; +import request from 'supertest'; +import { createProject } from '../../factory/project'; +import init from '../../init'; + +const FILE_PATH = path.join(__dirname, 'test.txt'); + +// Test case list +// 1. Upload file - Super admin +// 2. Upload file - Without token +// 3. Upload file - Org level viewer +// 4. Upload file - Org level creator +// 5. Upload file - Org level viewer with editor role in a project function attachmentTests() { - let context - - - beforeEach(async function() { - context = await init() - fs.writeFileSync(FILE_PATH, 'test', `utf-8`) - context = await init() - }) - + let context; - afterEach(function() { - fs.unlinkSync(FILE_PATH) - }) + beforeEach(async function () { + context = await init(); + fs.writeFileSync(FILE_PATH, 'test', `utf-8`); + context = await init(); + }); + afterEach(function () { + fs.unlinkSync(FILE_PATH); + }); it('Upload file - Super admin', async () => { const response = await request(context.app) .post('/api/v1/db/storage/upload') .attach('files', FILE_PATH) .set('xc-auth', context.token) - .expect(200) + .expect(200); - - const attachments = response.body - expect(attachments).to.be.an('array') - expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)) - }) + const attachments = response.body; + expect(attachments).to.be.an('array'); + expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)); + }); it('Upload file - Without token', async () => { const response = await request(context.app) .post('/api/v1/db/storage/upload') .attach('files', FILE_PATH) - .expect(401) + .expect(401); - const msg = response.body.msg - expect(msg).to.be.eq('Unauthorized') - }) + const msg = response.body.msg; + expect(msg).to.be.eq('Unauthorized'); + }); it('Upload file - Org level viewer', async () => { - // signup a user const args = { email: 'dummyuser@example.com', password: 'A1234abh2@dsad', - } + }; const signupResponse = await request(context.app) .post('/api/v1/auth/user/signup') .send(args) - .expect(200) + .expect(200); const response = await request(context.app) .post('/api/v1/db/storage/upload') .attach('files', FILE_PATH) .set('xc-auth', signupResponse.body.token) - .expect(400) - - const msg = response.body.msg - expect(msg).to.be.eq('Upload not allowed') - }) + .expect(400); + const msg = response.body.msg; + expect(msg).to.be.eq('Upload not allowed'); + }); it('Upload file - Org level creator', async () => { - // signup a user const args = { email: 'dummyuser@example.com', password: 'A1234abh2@dsad', - } - + }; await request(context.app) .post('/api/v1/auth/user/signup') .send(args) - .expect(200) + .expect(200); // update user role to creator const usersListResponse = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) + .expect(200); - const user = usersListResponse.body.list.find(u => u.email === args.email) - - expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER) + const user = usersListResponse.body.list.find( + (u) => u.email === args.email + ); + expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER); await request(context.app) .patch('/api/v1/users/' + user.id) .set('xc-auth', context.token) .send({ roles: OrgUserRoles.CREATOR }) - .expect(200) - + .expect(200); const signinResponse = await request(context.app) .post('/api/v1/auth/user/signin') // pass empty data in await request .send(args) - .expect(200) + .expect(200); const response = await request(context.app) .post('/api/v1/db/storage/upload') .attach('files', FILE_PATH) .set('xc-auth', signinResponse.body.token) - .expect(200) - - const attachments = response.body - expect(attachments).to.be.an('array') - expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)) - }) + .expect(200); + const attachments = response.body; + expect(attachments).to.be.an('array'); + expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)); + }); it('Upload file - Org level viewer with editor role in a project', async () => { - // signup a new user const args = { email: 'dummyuser@example.com', password: 'A1234abh2@dsad', - } + }; await request(context.app) .post('/api/v1/auth/user/signup') .send(args) - .expect(200) + .expect(200); const newProject = await createProject(context, { title: 'NewTitle1', - }) + }); // invite user to project with editor role await request(context.app) @@ -149,28 +146,27 @@ function attachmentTests() { project_id: newProject.id, projectName: newProject.title, }) - .expect(200) + .expect(200); // signin to get user token const signinResponse = await request(context.app) .post('/api/v1/auth/user/signin') // pass empty data in await request .send(args) - .expect(200) + .expect(200); const response = await request(context.app) .post('/api/v1/db/storage/upload') .attach('files', FILE_PATH) .set('xc-auth', signinResponse.body.token) - .expect(200) - - const attachments = response.body - expect(attachments).to.be.an('array') - expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)) - }) + .expect(200); + const attachments = response.body; + expect(attachments).to.be.an('array'); + expect(attachments[0].title).to.be.eq(path.basename(FILE_PATH)); + }); } -export default function() { - describe('Attachment', attachmentTests) +export default function () { + describe('Attachment', attachmentTests); } diff --git a/packages/nocodb/tests/unit/rest/tests/auth.test.ts b/packages/nocodb/tests/unit/rest/tests/auth.test.ts index f7bbd59988..eb0deae67e 100644 --- a/packages/nocodb/tests/unit/rest/tests/auth.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/auth.test.ts @@ -4,6 +4,27 @@ import request from 'supertest'; import init from '../../init'; import { defaultUserArgs } from '../../factory/user'; +// Test case list +// 1. Signup with valid email +// 2. Signup with invalid email +// 3. Signup with invalid password +// 4. Signin with valid credentials +// 5. Signin without email and password +// 6. Signin with invalid credentials +// 7. Signin with invalid password +// 8. me without token +// 9. me with token +// 10. forgot password with non-existing email id +// 11. TBD: forgot password with existing email id +// 12. Change password +// 13. Change password - after logout +// 14. TBD: Reset Password with an invalid token +// 15. TBD: Email validate with an invalid token +// 16. TBD: Email validate with a valid token +// 17. TBD: Forgot password validate with a valid token +// 18. TBD: Reset Password with an valid token +// 19. TBD: refresh token api + function authTests() { let context; @@ -15,7 +36,7 @@ function authTests() { const response = await request(context.app) .post('/api/v1/auth/user/signup') .send({ email: 'new@example.com', password: defaultUserArgs.password }) - .expect(200) + .expect(200); const token = response.body.token; expect(token).to.be.a('string'); @@ -43,8 +64,8 @@ function authTests() { password: defaultUserArgs.password, }) .expect(200); - const token = response.body.token; - expect(token).to.be.a('string'); + const token = response.body.token; + expect(token).to.be.a('string'); }); it('Signup without email and password', async () => { @@ -75,9 +96,9 @@ function authTests() { .unset('xc-auth') .expect(200); - if (!response.body?.roles?.guest) { - return new Error('User should be guest'); - } + if (!response.body?.roles?.guest) { + return new Error('User should be guest'); + } }); it('me with token', async () => { diff --git a/packages/nocodb/tests/unit/rest/tests/columnTypeSpecific.test.ts b/packages/nocodb/tests/unit/rest/tests/columnTypeSpecific.test.ts index ab24ffe70c..1c033b6ada 100644 --- a/packages/nocodb/tests/unit/rest/tests/columnTypeSpecific.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/columnTypeSpecific.test.ts @@ -11,6 +11,12 @@ import { expect } from 'chai'; import Column from '../../../../src/lib/models/Column'; import { title } from 'process'; +// Test case list +// 1. Qr Code Column +// a. adding a QR code column which references another column +// - delivers the same cell values as the referenced column +// - gets deleted if the referenced column gets deleted + function columnTypeSpecificTests() { let context; let project: Project; diff --git a/packages/nocodb/tests/unit/rest/tests/org.test.ts b/packages/nocodb/tests/unit/rest/tests/org.test.ts index ef286ba343..6fbe9aee5c 100644 --- a/packages/nocodb/tests/unit/rest/tests/org.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/org.test.ts @@ -1,170 +1,174 @@ -import { expect } from 'chai' -import 'mocha' -import request from 'supertest' -import { OrgUserRoles } from 'nocodb-sdk' -import init from '../../init' +import { expect } from 'chai'; +import 'mocha'; +import request from 'supertest'; +import { OrgUserRoles } from 'nocodb-sdk'; +import init from '../../init'; + +// Test case list in this file +// 1. Get users list +// 2. Invite a new user +// 3. Update user role +// 4. Remove user +// 5. Get token list +// 6. Generate token +// 7. Delete token +// 8. Disable/Enable signup function authTests() { - let context + let context; - beforeEach(async function() { - context = await init() - }) + beforeEach(async function () { + context = await init(); + }); it('Get users list', async () => { const response = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) + .expect(200); - expect(response.body).to.have.keys(['list', 'pageInfo']) - expect(response.body.list).to.have.length(1) - - }) + expect(response.body).to.have.keys(['list', 'pageInfo']); + expect(response.body.list).to.have.length(1); + }); it('Invite a new user', async () => { - const response = await request(context.app) .post('/api/v1/users') - .set('xc-auth', context.token).send({ email: 'a@nocodb.com' }) - .expect(200) + .set('xc-auth', context.token) + .send({ email: 'a@nocodb.com' }) + .expect(200); - console.log(response.body) + console.log(response.body); - expect(response.body).to.have.property('invite_token').to.be.a('string') -// todo: verify invite token - }) + expect(response.body).to.have.property('invite_token').to.be.a('string'); + // todo: verify invite token + }); it('Update user role', async () => { - const email = 'a@nocodb.com' + const email = 'a@nocodb.com'; // invite a user await request(context.app) .post('/api/v1/users') - .set('xc-auth', context.token).send({ email }) - .expect(200) + .set('xc-auth', context.token) + .send({ email }) + .expect(200); const response = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) - expect(response.body.list).to.have.length(2) + .expect(200); + expect(response.body.list).to.have.length(2); - const user = response.body.list.find(u => u.email === email) - - expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER) + const user = response.body.list.find((u) => u.email === email); + expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER); await request(context.app) .patch('/api/v1/users/' + user.id) .set('xc-auth', context.token) .send({ roles: OrgUserRoles.CREATOR }) - .expect(200) - + .expect(200); const response2 = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) - expect(response2.body.list).to.have.length(2) + .expect(200); + expect(response2.body.list).to.have.length(2); - const user2 = response2.body.list.find(u => u.email === email) + const user2 = response2.body.list.find((u) => u.email === email); - expect(user2).to.have.property('roles').to.be.equal(OrgUserRoles.CREATOR) - }) + expect(user2).to.have.property('roles').to.be.equal(OrgUserRoles.CREATOR); + }); it('Remove user', async () => { - const email = 'a@nocodb.com' + const email = 'a@nocodb.com'; // invite a user await request(context.app) .post('/api/v1/users') - .set('xc-auth', context.token).send({ email }) - .expect(200) + .set('xc-auth', context.token) + .send({ email }) + .expect(200); const response = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) - expect(response.body.list).to.have.length(2) + .expect(200); + expect(response.body.list).to.have.length(2); - const user = response.body.list.find(u => u.email === email) - - expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER) + const user = response.body.list.find((u) => u.email === email); + expect(user).to.have.property('roles').to.be.equal(OrgUserRoles.VIEWER); await request(context.app) .delete('/api/v1/users/' + user.id) .set('xc-auth', context.token) - .expect(200) - + .expect(200); const response2 = await request(context.app) .get('/api/v1/users') .set('xc-auth', context.token) - .expect(200) - expect(response2.body.list).to.have.length(1) - - }) - + .expect(200); + expect(response2.body.list).to.have.length(1); + }); it('Get token list', async () => { const response = await request(context.app) .get('/api/v1/tokens') .set('xc-auth', context.token) - .expect(200) - - expect(response.body).to.have.keys(['list', 'pageInfo']) - expect(response.body.list).to.have.length(0) + .expect(200); - }) + expect(response.body).to.have.keys(['list', 'pageInfo']); + expect(response.body.list).to.have.length(0); + }); it('Generate token', async () => { const r = await request(context.app) .post('/api/v1/tokens') .set('xc-auth', context.token) .send({ description: 'test' }) - .expect(200) + .expect(200); const response = await request(context.app) .get('/api/v1/tokens') .set('xc-auth', context.token) - .expect(200) - - expect(response.body).to.have.keys(['list', 'pageInfo']) - expect(response.body.list).to.have.length(1) - expect(response.body.list[0]).to.have.property('token').to.be.a('string') - expect(response.body.list[0]).to.have.property('description').to.be.a('string').to.be.eq('test') + .expect(200); - }) + expect(response.body).to.have.keys(['list', 'pageInfo']); + expect(response.body.list).to.have.length(1); + expect(response.body.list[0]).to.have.property('token').to.be.a('string'); + expect(response.body.list[0]) + .to.have.property('description') + .to.be.a('string') + .to.be.eq('test'); + }); it('Delete token', async () => { const r = await request(context.app) .post('/api/v1/tokens') .set('xc-auth', context.token) .send({ description: 'test' }) - .expect(200) + .expect(200); let response = await request(context.app) .get('/api/v1/tokens') .set('xc-auth', context.token) - .expect(200) + .expect(200); - expect(response.body).to.have.keys(['list', 'pageInfo']) - expect(response.body.list).to.have.length(1) + expect(response.body).to.have.keys(['list', 'pageInfo']); + expect(response.body.list).to.have.length(1); await request(context.app) .delete('/api/v1/tokens/' + r.body.token) .set('xc-auth', context.token) - .expect(200) - + .expect(200); response = await request(context.app) .get('/api/v1/tokens') .set('xc-auth', context.token) - .expect(200) - - expect(response.body).to.have.keys(['list', 'pageInfo']) - expect(response.body.list).to.have.length(0) + .expect(200); - }) + expect(response.body).to.have.keys(['list', 'pageInfo']); + expect(response.body.list).to.have.length(0); + }); it.only('Disable/Enable signup', async () => { const args = { @@ -172,51 +176,48 @@ function authTests() { password: 'A1234abh2@dsad', }; - await request(context.app) .post('/api/v1/app-settings') .set('xc-auth', context.token) .send({ invite_only_signup: true }) - .expect(200) - + .expect(200); - const failedRes = await request(context.app) - .post('/api/v1/auth/user/signup') - .send(args) - .expect(400) + const failedRes = await request(context.app) + .post('/api/v1/auth/user/signup') + .send(args) + .expect(400); - expect(failedRes.body).to.be.an('object') - .to.have.property('msg') - .to.be.equal('Not allowed to signup, contact super admin.') + expect(failedRes.body) + .to.be.an('object') + .to.have.property('msg') + .to.be.equal('Not allowed to signup, contact super admin.'); await request(context.app) .post('/api/v1/app-settings') .set('xc-auth', context.token) .send({ invite_only_signup: false }) - .expect(200) - + .expect(200); - const successRes = await request(context.app) + const successRes = await request(context.app) .post('/api/v1/auth/user/signup') .send(args) - .expect(200) + .expect(200); - expect(successRes.body).to.be.an('object') + expect(successRes.body) + .to.be.an('object') .to.have.property('token') - .to.be.a('string') + .to.be.a('string'); - - const userMeRes = await request(context.app) + const userMeRes = await request(context.app) .get('/api/v1/auth/user/me') .set('xc-auth', successRes.body.token) - .expect(200) + .expect(200); - expect(userMeRes.body).to.be.an('object') + expect(userMeRes.body) + .to.be.an('object') .to.have.property('email') - .to.be.eq(args.email) - }) - + .to.be.eq(args.email); + }); } -export default function() { -} +export default function () {} diff --git a/packages/nocodb/tests/unit/rest/tests/project.test.ts b/packages/nocodb/tests/unit/rest/tests/project.test.ts index 17c6f49345..b2d955565b 100644 --- a/packages/nocodb/tests/unit/rest/tests/project.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/project.test.ts @@ -1,30 +1,48 @@ -import 'mocha' -import request from 'supertest' -import { createTable } from '../../factory/table' -import init from '../../init/index' -import { createProject, createSharedBase } from '../../factory/project' -import { beforeEach } from 'mocha' -import { Exception } from 'handlebars' -import Project from '../../../../src/lib/models/Project' -import { expect } from 'chai' +import 'mocha'; +import request from 'supertest'; +import { createTable } from '../../factory/table'; +import init from '../../init/index'; +import { createProject, createSharedBase } from '../../factory/project'; +import { beforeEach } from 'mocha'; +import { Exception } from 'handlebars'; +import Project from '../../../../src/lib/models/Project'; +import { expect } from 'chai'; + +// Test case list +// 1. Get project info +// 2. UI ACL +// 3. Create project +// 4. Create project with existing title +// 5. Update project +// 6. Update project with existing title +// 7. Create project shared base +// 8. Created project shared base should have only editor or viewer role +// 9. Updated project shared base should have only editor or viewer role +// 10. Updated project shared base +// 11. Get project shared base +// 12. Delete project shared base +// 13. Meta diff sync +// 14. Meta diff sync +// 15. Meta diff sync +// 16. Get all projects meta function projectTest() { - let context - let project + let context; + let project; - beforeEach(async function() { - context = await init() + beforeEach(async function () { + context = await init(); - project = await createProject(context) - }) + project = await createProject(context); + }); it('Get project info', async () => { await request(context.app) .get(`/api/v1/db/meta/projects/${project.id}/info`) .set('xc-auth', context.token) .send({}) - .expect(200) - }) + .expect(200); + }); // todo: Test by creating models under project and check if the UCL is working it('UI ACL', async () => { @@ -32,8 +50,8 @@ function projectTest() { .get(`/api/v1/db/meta/projects/${project.id}/visibility-rules`) .set('xc-auth', context.token) .send({}) - .expect(200) - }) + .expect(200); + }); // todo: Test creating visibility set it('List projects', async () => { @@ -41,11 +59,12 @@ function projectTest() { .get('/api/v1/db/meta/projects/') .set('xc-auth', context.token) .send({}) - .expect(200) + .expect(200); - if (response.body.list.length !== 1) new Error('Should list only 1 project') - if (!response.body.pageInfo) new Error('Should have pagination info') - }) + if (response.body.list.length !== 1) + new Error('Should list only 1 project'); + if (!response.body.pageInfo) new Error('Should have pagination info'); + }); it('Create project', async () => { const response = await request(context.app) @@ -54,11 +73,11 @@ function projectTest() { .send({ title: 'Title1', }) - .expect(200) + .expect(200); - const newProject = await Project.getByTitleOrId(response.body.id) - if (!newProject) return new Error('Project not created') - }) + const newProject = await Project.getByTitleOrId(response.body.id); + if (!newProject) return new Error('Project not created'); + }); it('Create projects with existing title', async () => { await request(context.app) @@ -67,8 +86,8 @@ function projectTest() { .send({ title: project.title, }) - .expect(400) - }) + .expect(400); + }); // todo: fix passport user role popluation bug // it('Delete project', async async () => { @@ -99,10 +118,11 @@ function projectTest() { .get(`/api/v1/db/meta/projects/${project.id}`) .set('xc-auth', context.token) .send() - .expect(200) + .expect(200); - if (response.body.id !== project.id) return new Error('Got the wrong project') - }) + if (response.body.id !== project.id) + return new Error('Got the wrong project'); + }); it('Update projects', async () => { await request(context.app) @@ -111,18 +131,18 @@ function projectTest() { .send({ title: 'NewTitle', }) - .expect(200) + .expect(200); - const newProject = await Project.getByTitleOrId(project.id) + const newProject = await Project.getByTitleOrId(project.id); if (newProject.title !== 'NewTitle') { - return new Error('Project not updated') + return new Error('Project not updated'); } - }) + }); - it('Update projects with existing title', async function() { + it('Update projects with existing title', async function () { const newProject = await createProject(context, { title: 'NewTitle1', - }) + }); await request(context.app) .patch(`/api/v1/db/meta/projects/${project.id}`) @@ -130,8 +150,8 @@ function projectTest() { .send({ title: newProject.title, }) - .expect(400) - }) + .expect(400); + }); it('Create project shared base', async () => { await request(context.app) @@ -141,18 +161,18 @@ function projectTest() { roles: 'viewer', password: 'test', }) - .expect(200) + .expect(200); - const updatedProject = await Project.getByTitleOrId(project.id) + const updatedProject = await Project.getByTitleOrId(project.id); if ( !updatedProject.uuid || updatedProject.roles !== 'viewer' || updatedProject.password !== 'test' ) { - return new Error('Shared base not configured properly') + return new Error('Shared base not configured properly'); } - }) + }); it('Created project shared base should have only editor or viewer role', async () => { await request(context.app) @@ -162,17 +182,17 @@ function projectTest() { roles: 'commenter', password: 'test', }) - .expect(200) + .expect(200); - const updatedProject = await Project.getByTitleOrId(project.id) + const updatedProject = await Project.getByTitleOrId(project.id); if (updatedProject.roles === 'commenter') { - return new Error('Shared base not configured properly') + return new Error('Shared base not configured properly'); } - }) + }); it('Updated project shared base should have only editor or viewer role', async () => { - await createSharedBase(context.app, context.token, project) + await createSharedBase(context.app, context.token, project); await request(context.app) .patch(`/api/v1/db/meta/projects/${project.id}/shared`) @@ -181,17 +201,17 @@ function projectTest() { roles: 'commenter', password: 'test', }) - .expect(200) + .expect(200); - const updatedProject = await Project.getByTitleOrId(project.id) + const updatedProject = await Project.getByTitleOrId(project.id); if (updatedProject.roles === 'commenter') { - throw new Exception('Shared base not updated properly') + throw new Exception('Shared base not updated properly'); } - }) + }); it('Updated project shared base', async () => { - await createSharedBase(context.app, context.token, project) + await createSharedBase(context.app, context.token, project); await request(context.app) .patch(`/api/v1/db/meta/projects/${project.id}/shared`) @@ -200,42 +220,42 @@ function projectTest() { roles: 'editor', password: 'test', }) - .expect(200) - const updatedProject = await Project.getByTitleOrId(project.id) + .expect(200); + const updatedProject = await Project.getByTitleOrId(project.id); if (updatedProject.roles !== 'editor') { - throw new Exception('Shared base not updated properly') + throw new Exception('Shared base not updated properly'); } - }) + }); it('Get project shared base', async () => { - await createSharedBase(context.app, context.token, project) + await createSharedBase(context.app, context.token, project); await request(context.app) .get(`/api/v1/db/meta/projects/${project.id}/shared`) .set('xc-auth', context.token) .send() - .expect(200) + .expect(200); - const updatedProject = await Project.getByTitleOrId(project.id) + const updatedProject = await Project.getByTitleOrId(project.id); if (!updatedProject.uuid) { - throw new Exception('Shared base not created') + throw new Exception('Shared base not created'); } - }) + }); it('Delete project shared base', async () => { - await createSharedBase(context.app, context.token, project) + await createSharedBase(context.app, context.token, project); await request(context.app) .delete(`/api/v1/db/meta/projects/${project.id}/shared`) .set('xc-auth', context.token) .send() - .expect(200) - const updatedProject = await Project.getByTitleOrId(project.id) + .expect(200); + const updatedProject = await Project.getByTitleOrId(project.id); if (updatedProject.uuid) { - throw new Exception('Shared base not deleted') + throw new Exception('Shared base not deleted'); } - }) + }); // todo: Do compare api test @@ -244,16 +264,16 @@ function projectTest() { .get(`/api/v1/db/meta/projects/${project.id}/meta-diff`) .set('xc-auth', context.token) .send() - .expect(200) - }) + .expect(200); + }); it('Meta diff sync', async () => { await request(context.app) .post(`/api/v1/db/meta/projects/${project.id}/meta-diff`) .set('xc-auth', context.token) .send() - .expect(200) - }) + .expect(200); + }); // todo: improve test. Check whether the all the actions are present in the response and correct as well it('Meta diff sync', async () => { @@ -261,45 +281,60 @@ function projectTest() { .get(`/api/v1/db/meta/projects/${project.id}/audits`) .set('xc-auth', context.token) .send() - .expect(200) - }) - + .expect(200); + }); it('Get all projects meta', async () => { - await createTable(context, project, { table_name: 'table1', title: 'table1' }) - await createTable(context, project, { table_name: 'table2', title: 'table2' }) - await createTable(context, project, { table_name: 'table3', title: 'table3' }) + await createTable(context, project, { + table_name: 'table1', + title: 'table1', + }); + await createTable(context, project, { + table_name: 'table2', + title: 'table2', + }); + await createTable(context, project, { + table_name: 'table3', + title: 'table3', + }); await request(context.app) .get(`/api/v1/aggregated-meta-info`) .set('xc-auth', context.token) .send({}) .expect(200) - .then(res => { + .then((res) => { expect(res.body).to.have.all.keys( 'userCount', 'sharedBaseCount', 'projectCount', - 'projects', - ) - expect(res.body).to.have.property('projectCount').to.eq(1) - expect(res.body).to.have.property('projects').to.be.an('array') - expect(res.body.projects[0].tableCount.table).to.be.eq(3) - expect(res.body).to.have.nested.property('projects[0].tableCount.table').to.be.a('number') - expect(res.body).to.have.nested.property('projects[0].tableCount.view').to.be.a('number') - expect(res.body).to.have.nested.property('projects[0].viewCount').to.be.an('object') + 'projects' + ); + expect(res.body).to.have.property('projectCount').to.eq(1); + expect(res.body).to.have.property('projects').to.be.an('array'); + expect(res.body.projects[0].tableCount.table).to.be.eq(3); + expect(res.body) + .to.have.nested.property('projects[0].tableCount.table') + .to.be.a('number'); + expect(res.body) + .to.have.nested.property('projects[0].tableCount.view') + .to.be.a('number'); + expect(res.body) + .to.have.nested.property('projects[0].viewCount') + .to.be.an('object') .have.keys( - 'formCount', - 'gridCount', - 'galleryCount', - 'kanbanCount', - 'total', - 'sharedFormCount', - 'sharedGridCount', - 'sharedGalleryCount', - 'sharedKanbanCount', - 'sharedTotal', - 'sharedLockedCount') + 'formCount', + 'gridCount', + 'galleryCount', + 'kanbanCount', + 'total', + 'sharedFormCount', + 'sharedGridCount', + 'sharedGalleryCount', + 'sharedKanbanCount', + 'sharedTotal', + 'sharedLockedCount' + ); expect(res.body.projects[0]).have.keys( 'external', 'webhookCount', @@ -308,14 +343,18 @@ function projectTest() { 'userCount', 'rowCount', 'tableCount', - 'viewCount', - ) - expect(res.body).to.have.nested.property('projects[0].rowCount').to.be.an('array') - expect(res.body).to.have.nested.property('projects[0].external').to.be.an('boolean') - }) - }) + 'viewCount' + ); + expect(res.body) + .to.have.nested.property('projects[0].rowCount') + .to.be.an('array'); + expect(res.body) + .to.have.nested.property('projects[0].external') + .to.be.an('boolean'); + }); + }); } -export default function() { - describe('Project', projectTest) +export default function () { + describe('Project', projectTest); } diff --git a/packages/nocodb/tests/unit/rest/tests/table.test.ts b/packages/nocodb/tests/unit/rest/tests/table.test.ts index bcc4d0e284..b6341fffcb 100644 --- a/packages/nocodb/tests/unit/rest/tests/table.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/table.test.ts @@ -7,6 +7,18 @@ import { defaultColumns } from '../../factory/column'; import Model from '../../../../src/lib/models/Model'; import { expect } from 'chai'; +// Test case list +// 1. Get table list +// 2. Create table +// 3. Create table with same table name +// 4. Create table with same title +// 5. Create table with title length more than the limit +// 6. Create table with title having leading white space +// 7. Update table +// 8. Delete table +// 9. Get table +// 10. Reorder table + function tableTest() { let context; let project; diff --git a/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts b/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts index 7c089867f1..640b2dab22 100644 --- a/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts @@ -34,6 +34,70 @@ const isColumnsCorrectInResponse = (row, columns: ColumnType[]) => { return responseColumnsListStr === customerColumnsListStr; }; +// Test case list +// 1. Get table data list +// 2. Get table data list with required columns +// 3. Get desc sorted table data list with required columns +// 4. Get asc sorted table data list with required columns +// 5. Get sorted table data list with a rollup column +// 6. Get sorted table data list with a lookup column +// 7. Get filtered table data list with a lookup column +// 8. Get filtered table data list with a (hm)lookup column +// 9. Get nested sorted filtered table data list with a lookup column +// 10. Get nested sorted filtered table data list with a lookup column with date comparison +// 11. Get nested sorted filtered table data list with a rollup column in customer table +// 12. Get nested sorted filtered table with nested fields data list with a rollup column in customer table +// 13. Sorted Formula column on rollup customer table +// 14. Create table row +// 15. Create table row with wrong table id +// 16. Find one sorted table data list with required columns +// 17. Find one desc sorted and with rollup table data list with required columns +// 18. Find one sorted filtered table with nested fields data list with a rollup column in customer table +// 19. Groupby desc sorted and with rollup table data list with required columns +// 20. Groupby desc sorted and with rollup table data list with required columns +// 21. Read table row +// 22. Update table row +// 23. Update table row with validation and invalid data +// 24. Update table row with validation and valid data +// 25. Delete table row +// 26. Delete table row with foreign key contraint +// 27. Exist should be true table row when it exists +// 28. Exist should be false table row when it does not exists +// 29. Bulk insert +// 30. Bulk insert 400 records +// 31. Bulk update +// 32. Bulk delete +// 33. Export csv +// 34. Export excel +// 35. Nested row list hm +// 36. Nested row list hm with limit and offset +// 37. Row list hm with invalid table id +// 38. Nested row list mm +// 39. Nested row list mm with limit and offset +// 40. Row list mm with invalid table id +// 41. Create hm relation with invalid table id +// 42. Create hm relation with non ltar column +// 43. Create list hm wrong column id +// 44. Create list hm +// 45. Create list mm wrong column id +// 46. Create mm relation with non ltar column +// 47. Create list mm existing ref row id +// 48. Create list mm +// 49. List hm with non ltar column +// 50. List mm with non ltar column +// 51. Delete mm existing ref row id +// 52. Delete list hm with existing ref row id with non nullable clause +// 53. Delete list hm with existing ref row id +// 54. Exclude list hm +// 55. Exclude list hm with limit and offset +// 56. Exclude list mm +// 57. Exclude list mm with offset +// 58. Exclude list bt +// 59. Exclude list bt with offset +// 60. Create nested hm relation with invalid table id +// 61. Create nested mm relation with invalid table id +// 62. Get grouped data list + function tableTest() { let context; let project: Project; @@ -730,7 +794,7 @@ function tableTest() { ); const nestedFields = { - 'Rental List': { fields : ['RentalDate', 'ReturnDate'] }, + 'Rental List': { fields: ['RentalDate', 'ReturnDate'] }, }; const nestedFilter = [ @@ -2218,39 +2282,49 @@ function tableTest() { it('Exclude list bt', async () => { const rowId = 1; - const addressTable = await getTable({project: sakilaProject, name: 'address'}); + const addressTable = await getTable({ + project: sakilaProject, + name: 'address', + }); const cityColumn = (await addressTable.getColumns()).find( (column) => column.title === 'City' )!; const response = await request(context.app) - .get(`/api/v1/db/data/noco/${sakilaProject.id}/${addressTable.id}/${rowId}/bt/${cityColumn.id}/exclude`) - .set('xc-auth', context.token) - .expect(200); + .get( + `/api/v1/db/data/noco/${sakilaProject.id}/${addressTable.id}/${rowId}/bt/${cityColumn.id}/exclude` + ) + .set('xc-auth', context.token) + .expect(200); - expect(response.body.pageInfo.totalRows).equal(599) - expect(response.body.list[0]['City']).equal('A Corua (La Corua)') - }) + expect(response.body.pageInfo.totalRows).equal(599); + expect(response.body.list[0]['City']).equal('A Corua (La Corua)'); + }); it('Exclude list bt with offset', async () => { const rowId = 1; - const addressTable = await getTable({project: sakilaProject, name: 'address'}); + const addressTable = await getTable({ + project: sakilaProject, + name: 'address', + }); const cityColumn = (await addressTable.getColumns()).find( (column) => column.title === 'City' )!; const response = await request(context.app) - .get(`/api/v1/db/data/noco/${sakilaProject.id}/${addressTable.id}/${rowId}/bt/${cityColumn.id}/exclude`) - .set('xc-auth', context.token) - .query({ - limit: 40, - offset: 60 - }) - .expect(200); - - expect(response.body.pageInfo.totalRows).equal(599) - expect(response.body.list[0]['City']).equal('Baybay') - }) + .get( + `/api/v1/db/data/noco/${sakilaProject.id}/${addressTable.id}/${rowId}/bt/${cityColumn.id}/exclude` + ) + .set('xc-auth', context.token) + .query({ + limit: 40, + offset: 60, + }) + .expect(200); + + expect(response.body.pageInfo.totalRows).equal(599); + expect(response.body.list[0]['City']).equal('Baybay'); + }); it('Create nested hm relation with invalid table id', async () => { const rowId = 1; diff --git a/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts b/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts index 520f97a8ad..ea2961422e 100644 --- a/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts @@ -23,6 +23,74 @@ import { } from '../../factory/row'; import { expect } from 'chai'; +// Test case list +// 1. Get view row list g +// 2. Get view row list +// 3. Get view row lis +// 4. Get view row lis +// 5. Get view data list with required columns g +// 6. Get view data list with required column +// 7. Get view data list with required column +// 8. Get grouped view data list with required columns +// 9. Get desc sorted table data list with required columns gallery +// 10. Get desc sorted table data list with required columns form +// 11. Get desc sorted table data list with required columns grid +// 12. Get desc sorted table data list with required columns kanban +// 13. Get asc sorted view data list with required columns gallery +// 14. Get asc sorted view data list with required columns form +// 15. Get asc sorted view data list with required columns grid +// 16. Get asc sorted table data list with required columns kanban +// 17. Get nested sorted filtered table data list with a lookup column gallery +// 18. Get nested sorted filtered table data list with a lookup column grid +// 19. Get nested sorted filtered table with nested fields data list with a rollup column in customer table vie +// 20. Create table row grid +// 21. Create table row gallery +// 22. Create table row form +// 23. Create table row kanban +// 24. Create table row grid wrong grid id +// 25. Create table row wrong gallery id +// 26. Create table row wrong form id +// 27. Create table row wrong kanban id +// 28. Find one sorted data list with required columns gallery +// 29. Find one sorted data list with required columns form +// 30. Find one sorted data list with required columns grid +// 31. Find one view sorted filtered view with nested fields data list with a rollup column in customer table GRID +// 32. Groupby desc sorted and with rollup view data list with required columns GRID +// 33. Groupby desc sorted and with rollup view data list with required columns FORM +// 34. Groupby desc sorted and with rollup view data list with required columns GALLERY +// 35. Groupby desc sorted and with rollup view data list with required columns GALLERY +// 36. Groupby desc sorted and with rollup view data list with required columns FORM +// 37. Groupby desc sorted and with rollup view data list with required columns GRID +// 38. Count view data list with required columns GRID +// 39. Count view data list with required columns FORM +// 40. Count view data list with required columns GALLERY +// 41. Read view row GALLERY +// 42. Read view row FORM +// 43. Read view row GRID +// 44. Update view row GALLERY +// 45. Update view row GRID +// 46. Update view row FORM +// 47. Update view row with validation and invalid data GALLERY +// 48. Update view row with validation and invalid data GRID +// 49. Update view row with validation and invalid data FORM +// 50. Update view row with validation and valid data GALLERY +// 51. Update view row with validation and valid data GRID +// 52. Update view row with validation and valid data FORM +// 53. Delete view row GALLERY +// 54. Delete view row GRID +// 55. Delete view row FORM +// 56. Delete view row with ltar foreign key constraint GALLERY +// 57. Delete view row with ltar foreign key constraint GRID +// 58. Delete view row with ltar foreign key constraint FORM +// 59. Exist should be true view row when it exists GALLERY +// 60. Exist should be true view row when it exists GRID +// 61. Exist should be true view row when it exists FORM +// 62. Exist should be false view row when it does not exist GALLERY +// 63. Exist should be false view row when it does not exist GRID +// 64. Exist should be false view row when it does not exist FORM +// 65. Export csv GRID +// 66. Export excel GRID + const isColumnsCorrectInResponse = (row, columns: ColumnType[]) => { const responseColumnsListStr = Object.keys(row).sort().join(','); const customerColumnsListStr = columns @@ -562,7 +630,7 @@ function viewRowTests() { ); const nestedFields = { - 'Rental List': { fields : ['RentalDate', 'ReturnDate'] }, + 'Rental List': { fields: ['RentalDate', 'ReturnDate'] }, }; const nestedFilter = [