diff --git a/__tests__/auth.spec.js b/__tests__/auth.spec.js deleted file mode 100644 index 2290db04..00000000 --- a/__tests__/auth.spec.js +++ /dev/null @@ -1,48 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -chai.use(require('chai-uuid')); - -describe('Authentication', () => { - before(async () => { - await seed.clear(); - await seed.seed(); - }); - - beforeEach(async () => { - sinon.restore(); - }); - - // Auth path - it(`[POST /auth] login with ${seed.wallet.name}`, (done) => { - request(server) - .post('/auth') - .set('treetracker-api-key', seed.apiKey) - .send({ wallet: seed.wallet.name, password: seed.wallet.password }) - .expect('Content-Type', /application\/json/) - .expect(200) - .end((err, res) => { - if (err) done(err); - expect(res.body).to.have.property('token'); - done(); - }); - }); - - it(`[POST /auth] login with using wallet id: ${seed.wallet.id}`, (done) => { - request(server) - .post('/auth') - .set('treetracker-api-key', seed.apiKey) - .send({ wallet: seed.wallet.id, password: seed.wallet.password }) - .expect('Content-Type', /application\/json/) - .expect(200) - .end((err, res) => { - if (err) done(err); - expect(res.body).to.have.property('token'); - done(); - }); - }); -}); diff --git a/__tests__/bundle-transfer-cancel.spec.js b/__tests__/bundle-transfer-cancel.spec.js deleted file mode 100644 index 060c2ec1..00000000 --- a/__tests__/bundle-transfer-cancel.spec.js +++ /dev/null @@ -1,97 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -const TransferEnums = require('../server/utils/transfer-enum'); -chai.use(require('chai-uuid')); - -const { apiKey } = seed; - -describe('Create and cancel a bundle transfer', () => { - let bearerToken; - let bearerTokenB; - let pendingTransfer; - - before(async () => { - await seed.clear(); - await seed.seed(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - beforeEach(async () => { - sinon.restore(); - }); - - it(`create Bundle transfer tokens from ${seed.wallet.name} to ${seed.walletB.name}`, async () => { - const res = await request(server) - .post('/transfers') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`) - .send({ - bundle: { - bundle_size: 1, - }, - sender_wallet: seed.wallet.name, - receiver_wallet: seed.walletB.name, - claim: false, - }); - expect(res).property('statusCode').to.eq(202); - pendingTransfer = res.body; - expect(res) - .property('body') - .property('parameters') - .property('bundle') - .property('bundleSize') - .eq(1); - }); - - it('Delete/cancel the pending transfer', async () => { - const res = await request(server) - .del(`/transfers/${pendingTransfer.id}`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - }); - - it(`Wallet:${seed.wallet.name} should be able to find the transfer, it should be cancelled`, async () => { - const res = await request(server) - .get(`/transfers?limit=1000`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.transfers).lengthOf(1); - expect(res.body.transfers[0]) - .property('state') - .eq(TransferEnums.STATE.cancelled); - }); -}); diff --git a/__tests__/bundle-transfer-create-accept.spec.js b/__tests__/bundle-transfer-create-accept.spec.js deleted file mode 100644 index 1d6b5dac..00000000 --- a/__tests__/bundle-transfer-create-accept.spec.js +++ /dev/null @@ -1,119 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -const TransferEnums = require('../server/utils/transfer-enum'); -chai.use(require('chai-uuid')); - -const { apiKey } = seed; - -describe('Create and accept a bundle transfer', () => { - let bearerToken; - let bearerTokenB; - let pendingTransfer; - - before(async () => { - await seed.clear(); - await seed.seed(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - beforeEach(async () => { - sinon.restore(); - }); - - it(`create Bundle transfer tokens from ${seed.wallet.name} to ${seed.walletB.name}`, async () => { - const res = await request(server) - .post('/transfers') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`) - .send({ - bundle: { - bundle_size: 1, - }, - sender_wallet: seed.wallet.name, - receiver_wallet: seed.walletB.name, - claim: false, - }); - expect(res).property('statusCode').to.eq(202); - expect(res) - .property('body') - .property('parameters') - .property('bundle') - .property('bundleSize') - .eq(1); - }); - - it('get all pending transfers belongs to walletB, should have one', async () => { - const res = await request(server) - .get('/transfers?state=pending&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.transfers).lengthOf(1); - [pendingTransfer] = res.body.transfers; - expect(pendingTransfer) - .property('destination_wallet') - .eq(seed.walletB.name); - }); - - it('Accept the pending bundle transfer', async () => { - const res = await request(server) - .post(`/transfers/${pendingTransfer.id}/accept`) - .set('Content-Type', 'application/json') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - }); - - it(`Wallet:${seed.wallet.name} should be able to find the transfer, it should be completed 2`, async () => { - const res = await request(server) - .get(`/transfers?limit=1000`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.transfers).lengthOf(1); - expect(res.body.transfers[0]) - .property('state') - .eq(TransferEnums.STATE.completed); - }); - - it(`Token:#${seed.token.id} now should belong to ${seed.walletB.name}`, async () => { - const res = await request(server) - .get(`/tokens/${seed.token.id}`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.wallet_id).eq(seed.walletB.id); - }); -}); diff --git a/__tests__/bundle-transfer-decline.spec.js b/__tests__/bundle-transfer-decline.spec.js deleted file mode 100644 index 34598fee..00000000 --- a/__tests__/bundle-transfer-decline.spec.js +++ /dev/null @@ -1,119 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -const TransferEnums = require('../server/utils/transfer-enum'); -chai.use(require('chai-uuid')); - -const { apiKey } = seed; - -describe('Create and decline a bundle transfer', () => { - let bearerToken; - let bearerTokenB; - let pendingTransfer; - - before(async () => { - await seed.clear(); - await seed.seed(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - beforeEach(async () => { - sinon.restore(); - }); - - it(`create Bundle transfer tokens from ${seed.wallet.name} to ${seed.walletB.name}`, async () => { - const res = await request(server) - .post('/transfers') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`) - .send({ - bundle: { - bundle_size: 1, - }, - sender_wallet: seed.wallet.name, - receiver_wallet: seed.walletB.name, - claim: false, - }); - expect(res).property('statusCode').to.eq(202); - expect(res) - .property('body') - .property('parameters') - .property('bundle') - .property('bundleSize') - .eq(1); - }); - - it('get all pending transfers belongs to walletB, should have one', async () => { - const res = await request(server) - .get('/transfers?state=pending&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.transfers).lengthOf(1); - [pendingTransfer] = res.body.transfers; - expect(pendingTransfer) - .property('destination_wallet') - .eq(seed.walletB.name); - }); - - it('Decline the pending transfer', async () => { - const res = await request(server) - .post(`/transfers/${pendingTransfer.id}/decline`) - .set('Content-Type', 'application/json') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - }); - - it(`Wallet:${seed.wallet.name} should be able to find the transfer, it should be cancelled`, async () => { - const res = await request(server) - .get(`/transfers?limit=1000`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.transfers).lengthOf(1); - expect(res.body.transfers[0]) - .property('state') - .eq(TransferEnums.STATE.cancelled); - }); - - it(`Token:#${seed.token.id} now should still belong to ${seed.wallet.name}`, async () => { - const res = await request(server) - .get(`/tokens/${seed.token.id}`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.wallet_id).eq(seed.wallet.id); - }); -}); diff --git a/__tests__/fulfill-bundle-transfer-request.spec.js b/__tests__/fulfill-bundle-transfer-request.spec.js deleted file mode 100644 index 0758f40d..00000000 --- a/__tests__/fulfill-bundle-transfer-request.spec.js +++ /dev/null @@ -1,112 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -chai.use(require('chai-uuid')); - -const { apiKey } = seed; - -describe('Request and fulfill a bundle transfer', () => { - let bearerToken; - let bearerTokenB; - let requestedTransferId; - - before(async () => { - await seed.clear(); - await seed.seed(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - beforeEach(async () => { - sinon.restore(); - }); - - it(`WalletB:${seed.walletB.name} request a bundle of token from ${seed.wallet.name}, should get 202`, async () => { - const res = await request(server) - .post('/transfers') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`) - .send({ - bundle: { - bundle_size: 1, - }, - sender_wallet: seed.wallet.name, - receiver_wallet: seed.walletB.name, - claim: false, - }); - expect(res).property('statusCode').to.eq(202); - }); - - it(`${seed.wallet.name} should find a requested transfer sent to it`, async () => { - const res = await request(server) - .get('/transfers?state=requested&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).property('statusCode').to.eq(200); - expect(res.body).property('transfers').lengthOf(1); - expect(res.body.transfers[0]).property('state').eq('requested'); - expect(res.body.transfers[0]).property('id').to.be.a.uuid('v4'); - requestedTransferId = res.body.transfers[0].id; - }); - - it(`${seed.wallet.name} fulfill this requested transfer with tokens`, async () => { - const res = await request(server) - .post(`/transfers/${requestedTransferId}/fulfill`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`) - .send({ - tokens: [seed.token.id], - }); - expect(res).property('statusCode').to.eq(200); - }); - - it(`${seed.walletB.name} should be able to find requested transfer has been completed`, async () => { - const res = await request(server) - .get('/transfers?state=completed&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).property('statusCode').to.eq(200); - expect(res.body).property('transfers').lengthOf(1); - expect(res.body.transfers[0]).property('state').eq('completed'); - expect(res.body.transfers[0]).property('id').eq(requestedTransferId); - }); - - it(`Token:#${seed.token.id} now should still belong to ${seed.walletB.name}`, async () => { - const res = await request(server) - .get(`/tokens/${seed.token.id}`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.wallet_id).eq(seed.walletB.id); - }); -}); diff --git a/__tests__/fulfill-explicity-transfer-request.spec.js b/__tests__/fulfill-explicity-transfer-request.spec.js deleted file mode 100644 index fc2faca4..00000000 --- a/__tests__/fulfill-explicity-transfer-request.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const server = require('../server/app'); -const seed = require('./seed'); -chai.use(require('chai-uuid')); - -const { apiKey } = seed; - -describe('Request and fulfill an explicit transfer', () => { - let bearerToken; - let bearerTokenB; - let requestedTransferId; - - before(async () => { - await seed.clear(); - await seed.seed(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - beforeEach(async () => { - sinon.restore(); - }); - - it(`WalletB:${seed.walletB.name} request a token from ${seed.wallet.name}, should get 202`, async () => { - const res = await request(server) - .post('/transfers') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`) - .send({ - tokens: [seed.token.id], - sender_wallet: seed.wallet.name, - receiver_wallet: seed.walletB.name, - }); - expect(res).property('statusCode').to.eq(202); - }); - - it(`${seed.wallet.name} should find a requested transfer sent to him`, async () => { - const res = await request(server) - .get('/transfers?state=requested&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).property('statusCode').to.eq(200); - expect(res.body).property('transfers').lengthOf(1); - expect(res.body.transfers[0]).property('state').eq('requested'); - expect(res.body.transfers[0]).property('id').to.be.a.uuid('v4'); - requestedTransferId = res.body.transfers[0].id; - }); - - it(`${seed.wallet.name} fulfill this requested transfer`, async () => { - const res = await request(server) - .post(`/transfers/${requestedTransferId}/fulfill`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerToken}`) - .send({ - implicit: true, - }); - expect(res).property('statusCode').to.eq(200); - }); - - it(`${seed.walletB.name} should be able to find requested transfer has been completed`, async () => { - const res = await request(server) - .get('/transfers?state=completed&limit=1000') - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).property('statusCode').to.eq(200); - expect(res.body).property('transfers').lengthOf(1); - expect(res.body.transfers[0]).property('state').eq('completed'); - expect(res.body.transfers[0]).property('id').eq(requestedTransferId); - }); - - it(`Token:#${seed.token.id} now should still belong to ${seed.walletB.name}`, async () => { - const res = await request(server) - .get(`/tokens/${seed.token.id}`) - .set('treetracker-api-key', apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.wallet_id).eq(seed.walletB.id); - }); -}); diff --git a/__tests__/get-tokens.spec.js b/__tests__/get-tokens.spec.js index 545171a4..e69de29b 100644 --- a/__tests__/get-tokens.spec.js +++ b/__tests__/get-tokens.spec.js @@ -1,117 +0,0 @@ -/* - * The integration test to test the whole business, with DB - */ -require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const chai = require('chai'); -const seed = require('./seed'); -const server = require('../server/app'); -chai.use(require('chai-uuid')); - -describe('GET tokens', () => { - let bearerToken; - let bearerTokenB; - - beforeEach(async () => { - await seed.clear(); - await seed.seed(); - sinon.restore(); - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', seed.apiKey) - .send({ - wallet: seed.wallet.name, - password: seed.wallet.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerToken = res.body.token; - expect(bearerToken).to.match(/\S+/); - } - - { - // Authorizes before each of the follow tests - const res = await request(server) - .post('/auth') - .set('treetracker-api-key', seed.apiKey) - .send({ - wallet: seed.walletB.name, - password: seed.walletB.password, - }); - expect(res).to.have.property('statusCode', 200); - bearerTokenB = res.body.token; - expect(bearerTokenB).to.match(/\S+/); - } - }); - - it(`walletA, GET /tokens/${seed.token.id} Should be able to get a token `, async () => { - const res = await request(server) - .get(`/tokens/${seed.token.id}`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body).to.have.property('id').eq(seed.token.id); - }); - - it(`walletA, GET /tokens/${seed.tokenB.id} Should be forbidden`, async () => { - const res = await request(server) - .get(`/tokens/${seed.tokenB.id}`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 403); - }); - - it(`walletA, GET /tokens Should be able to get a token `, async () => { - const res = await request(server) - .get(`/tokens?limit=10`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.tokens[0]).to.have.property('id').eq(seed.token.id); - }); - - it(`walletB, GET /tokens Should be able to get a token, which actually belongs to walletC`, async () => { - const res = await request(server) - .get(`/tokens?limit=10&wallet=walletC`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body.tokens[0]).to.have.property('id').eq(seed.tokenB.id); - }); - - it(`walletB, GET /tokens/${seed.tokenB.id} Should be able to get a token `, async () => { - const res = await request(server) - .get(`/tokens/${seed.tokenB.id}`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerTokenB}`); - expect(res).to.have.property('statusCode', 200); - expect(res.body).to.have.property('id').eq(seed.tokenB.id); - }); - it(`GET /tokens/ should return correct limit`, async () => { - await seed.addTokenToWallet(seed.wallet.id); - const res = await request(server) - .get(`/tokens?limit=1`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - - expect(res).to.have.property('statusCode', 200); - expect(res.body.tokens.length).to.eq(1); - expect(res.body.tokens[0].id).eq(seed.token.id); - }); - - it(`GET /tokens/ should return correct offset`, async () => { - const insertedId = (await seed.addTokenToWallet(seed.wallet.id))[0].id; - const res = await request(server) - .get(`/tokens?offset=1&limit=10`) - .set('treetracker-api-key', seed.apiKey) - .set('Authorization', `Bearer ${bearerToken}`); - - expect(res).to.have.property('statusCode', 200); - expect(res.body.tokens.length).to.eq(1); - expect(res.body.tokens[0].id).eq(insertedId); - }); -}); diff --git a/__tests__/integration/auth.spec.js b/__tests__/integration/auth.spec.js index 9d5bd046..bcdb2afd 100644 --- a/__tests__/integration/auth.spec.js +++ b/__tests__/integration/auth.spec.js @@ -1,49 +1,45 @@ require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); -const chai = require('chai'); -const server = require('../../server/app'); -chai.use(require('chai-uuid')); -const Zaven = require('../mock-data/Zaven.json'); -const testUtils = require('./testUtils'); +const {expect} = require('chai'); +const {post} = require('../utils/sendReq'); +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const {clear, register} = require('../utils/testUtils'); describe('Authentication', () => { - let registeredUser; - - beforeEach(async () => { - await testUtils.clear(); - registeredUser = await testUtils.register(Zaven); - }); - - // Authorization path - it(`[POST /auth] login with ${Zaven.name}`, (done) => { - request(server) - .post('/auth') - .set('treetracker-api-key', registeredUser.apiKey) - .send({ - wallet: registeredUser.name, - password: registeredUser.password, - }) - .expect('Content-Type', /application\/json/) - .expect(200) - .end((err, res) => { - if (err) done(err); + let walletA; + + before(clear) + + beforeEach(async () => { + walletA = await register(walletAInfo); + }); + + afterEach(clear) + + it(`Login with valid username and password`, async () => { + const res = await post('/auth', walletA, null, {wallet: walletA.name, password: walletA.password}); expect(res.body).to.have.property('token'); - done(); - }); - }); - - it(`[POST /auth] login with using wallet id of ${Zaven.name}`, (done) => { - request(server) - .post('/auth') - .set('treetracker-api-key', registeredUser.apiKey) - .send({ wallet: registeredUser.id, password: registeredUser.password }) - .expect('Content-Type', /application\/json/) - .expect(200) - .end((err, res) => { - if (err) done(err); + expect(res).to.have.property('statusCode', 200); + }); + + it(`Login with valid wallet id and password`, async () => { + const res = await post('/auth', walletA, null, {wallet: walletA.id, password: walletA.password}); expect(res.body).to.have.property('token'); - done(); - }); - }); + expect(res).to.have.property('statusCode', 200); + }); + + it(`Login with invalid password`, async () => { + const res = await post('/auth', walletA, null, {wallet: walletA.id, password: 'abcabc123'}); + expect(res.body).to.not.have.property('token'); + expect(res).to.have.property('statusCode', 401); + }); + + it(`Login with invalid wallet name/id`, async () => { + const res = await post('/auth', walletA, null, {wallet: 'walletB', password: walletA.password}); + expect(res.body).to.not.have.property('token'); + expect(res).to.have.property('statusCode', 404); + + const resB = await post('/auth', walletA, null, {wallet: '553c9d69-dcdf-48db-86ac-ed13380c62dc', password: walletA.password}); + expect(resB.body).to.not.have.property('token'); + expect(resB).to.have.property('statusCode', 404); + }); }); diff --git a/__tests__/integration/bundle-transfer-cancel.spec.js b/__tests__/integration/bundle-transfer-cancel.spec.js new file mode 100644 index 00000000..5b679619 --- /dev/null +++ b/__tests__/integration/bundle-transfer-cancel.spec.js @@ -0,0 +1,61 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +chai.use(require('chai-uuid')); +const {registerAndLogin, clear, sendBundleTransfer, getTransfer} = require('../utils/testUtils'); +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const walletBInfo = require('../mock-data/wallet/walletB.json'); +const {del} = require('../utils/sendReq'); + +describe('Cancel pending transfer', () => { + let walletA; + let walletB; + let transfer; + before(async () => { + await clear(); + }) + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + }) + + afterEach(async () => { + await clear(); + }) + + it('Cancel the pending transfer by sender', async () => { + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.pending, 1); + + const res = await del(`/transfers/${transfer.id}`, walletA); + expect(res).to.have.property('statusCode', 200); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); + }); + + it('Cancel the pending transfer by receiver', async () => { + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.pending, 1); + + const res = await del(`/transfers/${transfer.id}`, walletB); + expect(res).to.have.property('statusCode', 403); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.pending); + }); + + it('Cancel the pending transfer which already canceled', async () => { + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.cancelled, 1); + + const res = await del(`/transfers/${transfer.id}`, walletA) + expect(res).to.have.property('statusCode', 409); + }) + + it('Cancel the pending transfer which is belong to other wallet', async () => { + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.pending, 1); + + const walletC = await registerAndLogin({name: 'walletCCC', password: 'test1234'}); + const res = await del(`/transfers/${transfer.id}`, walletC) + expect(res).to.have.property('statusCode', 403); + }) +}); diff --git a/__tests__/integration/bundle-transfer-create-accept.spec.js b/__tests__/integration/bundle-transfer-create-accept.spec.js new file mode 100644 index 00000000..cfb11674 --- /dev/null +++ b/__tests__/integration/bundle-transfer-create-accept.spec.js @@ -0,0 +1,80 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +chai.use(require('chai-uuid')); +const {post} = require('../utils/sendReq'); +const { + clear, registerAndLogin, sendBundleTransfer, + completePending, getTransfer, getToken + , cancelPending, deleteToken, feedTokens +} = require('../utils/testUtils'); +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const walletBInfo = require('../mock-data/wallet/walletB.json'); + +describe('Create and accept a bundle transfer', () => { + let walletA; + let walletB; + let transfer; + let tokens = []; + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + + tokens = await feedTokens(walletA, 5); + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.pending, 5); + }); + + afterEach(async () => { + await clear(); + tokens = []; + }) + + it('Accept the pending bundle transfer', async () => { + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + expect(res).to.have.property('statusCode', 200); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.completed); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(5); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(0); + }); + + it('Accept the transfer which already canceled', async () => { + await cancelPending(transfer); + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + expect(res).to.have.property('statusCode', 409); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(0); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(5); + }) + + it('Accept the transfer which already accepted', async () => { + await completePending(transfer); + + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + expect(res).to.have.property('statusCode', 409); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(0); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(5); + }) + + it('Accept the transfer, but sender wallet does NOT have enough tokens', async () => { + await deleteToken(tokens[0]); + + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + expect(res).to.have.property('statusCode', 409); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(0); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(4); + }) +}); diff --git a/__tests__/integration/bundle-transfer-decline.spec.js b/__tests__/integration/bundle-transfer-decline.spec.js index cfe936c7..e6038796 100644 --- a/__tests__/integration/bundle-transfer-decline.spec.js +++ b/__tests__/integration/bundle-transfer-decline.spec.js @@ -1,66 +1,60 @@ require('dotenv').config(); -const request = require('supertest'); -const { expect } = require('chai'); +const {expect} = require('chai'); const chai = require('chai'); -const server = require('../../server/app'); -chai.use(require('chai-uuid')); -const Zaven = require('../mock-data/Zaven.json'); -const Meisze = require('../mock-data/Meisze.json'); -const testUtils = require('./testUtils'); -const TokenA = require('../mock-data/TokenA'); const TransferEnums = require('../../server/utils/transfer-enum'); +const { + clear, registerAndLogin, getTransfer, feedTokens, cancelPending, sendBundleTransfer +} = require("../utils/testUtils"); +const {post} = require('../utils/sendReq'); +const walletAInfo = require("../mock-data/wallet/walletA.json"); +const walletBInfo = require("../mock-data/wallet/walletB.json"); +chai.use(require('chai-uuid')); -describe('Zaven request to send 1 token to Meisze', () => { - let registeredZaven; - let registeredMeisze; - let transfer; +describe('Create and decline a pending transfer', () => { + let walletA; + let walletB; + let transfer; - beforeEach(async () => { - await testUtils.clear(); - registeredZaven = await testUtils.registerAndLogin(Zaven); - await testUtils.addToken(registeredZaven, TokenA); - expect(registeredZaven).property('id').a('string'); - registeredMeisze = await testUtils.registerAndLogin(Meisze); - transfer = await testUtils.sendAndPend( - registeredZaven, - registeredMeisze, - 1, - ); - }); + before(async () => { + await clear(); + }); + afterEach(async () => { + await clear(); + }); - describe('Meisze decline the request', () => { beforeEach(async () => { - await request(server) - .post(`/transfers/${transfer.id}/decline`) - .set('Content-Type', 'application/json') - .set('treetracker-api-key', registeredMeisze.apiKey) - .set('Authorization', `Bearer ${registeredMeisze.token}`) - .expect(200); - }); + await clear(); + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); - it('The transfer status should be cancelled', async () => { - await request(server) - .get(`/transfers?limit=1000`) - .set('treetracker-api-key', registeredMeisze.apiKey) - .set('Authorization', `Bearer ${registeredMeisze.token}`) - .expect(200) - .then((res) => { - expect(res.body.transfers).lengthOf(1); - expect(res.body.transfers[0]) - .property('state') - .eq(TransferEnums.STATE.cancelled); - }); + await feedTokens(walletA, 5); + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.pending, 5); }); - it('Zaven should still have 1 token', async () => { - await request(server) - .get(`/tokens?limit=10`) - .set('treetracker-api-key', registeredZaven.apiKey) - .set('Authorization', `Bearer ${registeredZaven.token}`) - .expect(200) - .then((res) => { - expect(res.body.tokens).lengthOf(1); - }); + it('Decline a pending transfer', async () => { + const res = await post(`/transfers/${transfer.id}/decline`, walletB); + expect(res).to.have.property('statusCode', 200); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); }); - }); + + it('Decline a pending transfer which already declined/canceled', async () => { + await cancelPending(transfer); + + const res = await post(`/transfers/${transfer.id}/decline`, walletB); + expect(res).to.have.property('statusCode', 409); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); + }) + + it('Decline a pending transfer which is belong to others', async () => { + const walletC = await registerAndLogin({name: 'fdgjsgfhsa', password: 'fhdjsgfhjds12'}); + const res = await post(`/transfers/${transfer.id}/decline`, walletC); + expect(res).to.have.property('statusCode', 403); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.pending); + }) }); diff --git a/__tests__/integration/fulfill-bundle-transfer-request.spec.js b/__tests__/integration/fulfill-bundle-transfer-request.spec.js new file mode 100644 index 00000000..e724c3d8 --- /dev/null +++ b/__tests__/integration/fulfill-bundle-transfer-request.spec.js @@ -0,0 +1,91 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const {post} = require('../utils/sendReq'); +const { + clear, registerAndLogin, + getRandomToken, sendBundleTransfer, + getToken, deleteToken, getTransfer, feedTokens +} = require('../utils/testUtils'); +const TransferEnums = require('../../server/utils/transfer-enum'); + +describe('Request and fulfill a bundle transfer', () => { + let walletA; + let walletB + let tokens = []; + let transfer; + + before(async () => { + await clear() + }); + + afterEach(async () => { + await clear(); + tokens = []; + }) + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'abc13'}); + walletB = await registerAndLogin({name: 'walletB', password: 'abc12'}); + + tokens = await feedTokens(walletA, 5); + transfer = await sendBundleTransfer(walletA, walletB, TransferEnums.STATE.requested, 5); + }); + + it('Fulfill a requested transfer', async () => { + const res = await post(`/transfers/${transfer.id}/fulfill`, walletA, null, {tokens: tokens.map(token => token.id)}) + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(TransferEnums.STATE.completed); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletBTokens.length).to.eq(tokens.length); + expect(walletATokens.length).to.eq(0); + }) + + it('Fulfill a requested transfer, but sender wallet dont have enough tokens', async () => { + // delete one token from walletA, so that walletA do not have enough tokens to fulfill + const result = await deleteToken(tokens[0]); + expect(result).to.eq(1); + tokens = await getToken(walletA); + + const res = await post(`/transfers/${transfer.id}/fulfill`, walletA, null, {tokens: tokens.map(token => token.id)}) + expect(res).property('statusCode').to.eq(409); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletATokens.length).to.eq(tokens.length); + expect(walletBTokens.length).to.eq(0); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.requested); + }) + + it('Fulfill a requested transfer, but there is one token do not exist', async () => { + tokens[0] = getRandomToken(); + const res = await post(`/transfers/${transfer.id}/fulfill`, walletA, null, {tokens: tokens.map(token => token.id)}) + expect(res).property('statusCode').to.eq(404); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletATokens.length).to.eq(tokens.length); + expect(walletBTokens.length).to.eq(0); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.requested); + }) + + it('Fulfill a requested transfer, but the transfer belong to other account', async () => { + const walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + + const res = await post(`/transfers/${transfer.id}/fulfill`, walletC, null, {tokens: tokens.map(token => token.id)}); + expect(res).property('statusCode').to.eq(403); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletATokens.length).to.eq(tokens.length); + expect(walletBTokens.length).to.eq(0); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.requested); + }) +}); diff --git a/__tests__/integration/fulfill-explicity-transfer-request.spec.js b/__tests__/integration/fulfill-explicity-transfer-request.spec.js new file mode 100644 index 00000000..e1c70612 --- /dev/null +++ b/__tests__/integration/fulfill-explicity-transfer-request.spec.js @@ -0,0 +1,78 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const {post} = require('../utils/sendReq'); +const { + clear, registerAndLogin, sendTokensTransfer, + getToken, deleteToken, getTransfer, feedTokens +} = require('../utils/testUtils'); +const TransferEnums = require('../../server/utils/transfer-enum'); + +describe('Request and fulfill an explicit transfer', () => { + let walletA; + let walletB; + let transfer; + let tokens = [] + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'abc13'}); + walletB = await registerAndLogin({name: 'walletB', password: 'abc12'}); + + tokens = await feedTokens(walletA, 5); + transfer = await sendTokensTransfer(walletA, walletB, TransferEnums.STATE.requested, tokens.map(token => token.id)) // I request 5 tokens before test + }); + + afterEach(async () => { + await clear(); + tokens = []; + }) + + it('Fulfill a requested transfer', async () => { + const res = await post(`/transfers/${transfer.id}/fulfill`, walletA, null, {implicit: true}) + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(TransferEnums.STATE.completed); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletBTokens.length).to.eq(tokens.length); + expect(walletATokens.length).to.eq(0); + }) + + // todo: fix this bug + // considering there is a bug here, normally expect to get 403, not 200 + it('Fulfill a requested transfer, but sender wallet dont have enough tokens', async () => { + // delete one token from walletA, so that walletA do not have enough tokens to fulfill + const result = await deleteToken(tokens[0]); // delete one token form db + expect(result).to.eq(1); + tokens = await getToken(walletA); // now tokens array just have 4 + + const res = await post(`/transfers/${transfer.id}/fulfill`, walletA, null, {implicit: true}) + expect(res).property('statusCode').to.eq(200); // success + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletATokens.length).to.eq(0); + expect(walletBTokens.length).to.eq(4); // I only 4 tokens successfully, although I actually requested 5 tokens + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.completed); + }) + + it('Fulfill a requested transfer, but the transfer belong to other account', async () => { + const walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + + const res = await post(`/transfers/${transfer.id}/fulfill`, walletC, null, {implicit: true}) + expect(res).property('statusCode').to.eq(403); + + const walletBTokens = await getToken(walletB); + const walletATokens = await getToken(walletA); + expect(walletATokens.length).to.eq(tokens.length); + expect(walletBTokens.length).to.eq(0); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.requested); + }) +}); diff --git a/__tests__/integration/get-tokens.spec.js b/__tests__/integration/get-tokens.spec.js new file mode 100644 index 00000000..b54542df --- /dev/null +++ b/__tests__/integration/get-tokens.spec.js @@ -0,0 +1,64 @@ +/* + * The integration test to test the whole business, with DB + */ +require('dotenv').config(); +const {expect} = require('chai'); +const {registerAndLogin, getRandomToken, clear, feedTokens} = require('../utils/testUtils'); +const {get} = require('../utils/sendReq') +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const walletBInfo = require('../mock-data/wallet/walletB.json'); + +describe('GET tokens', () => { + let walletA; + let walletB; + let tokens = []; + + before(clear) + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + + tokens = await feedTokens(walletA, 5); + }); + + afterEach(async () => { + await clear(); + tokens = []; + }) + + + it('Get tokens from a wallet', async () => { + const res = await get(`/tokens/${tokens[0].id}`, walletA); + expect(res).to.have.property('statusCode', 200); + expect(res.body.id).to.eq(tokens[0].id); + }) + + it('Get tokens from a wallet, but the token do not exist', async () => { + + const res = await get(`/tokens/${getRandomToken().id}`, walletA); + expect(res).to.have.property('statusCode', 404); + }) + + it('Get tokens from a wallet, but the token belong to another wallet', async () => { + const res = await get(`/tokens/${tokens[0].id}`, walletB); + expect(res).to.have.property('statusCode', 403); + }) + + it('Get a set of tokens from a wallet', async () => { + const res = await get('/tokens', walletA, {limit: 10, offset: 0}); + expect(res).to.have.property('statusCode', 200); + expect(res.body.tokens.length).to.eq(tokens.length); + + const resB = await get('/tokens', walletB, {limit: 10, offset: 0}); + expect(resB).to.have.property('statusCode', 200); + expect(resB.body.tokens.length).to.eq(0); + }) + + it('Get tokens by paginate', async () => { + const res = await get(`/tokens`, walletA, {limit: 1, offset: 2}); + expect(res).to.have.property('statusCode', 200); + + expect(res.body.tokens[0].id).to.eq(tokens[2].id); + }) +}); diff --git a/__tests__/integration/pending-transfer-accepted.spec.js b/__tests__/integration/pending-transfer-accepted.spec.js new file mode 100644 index 00000000..7f32e8a3 --- /dev/null +++ b/__tests__/integration/pending-transfer-accepted.spec.js @@ -0,0 +1,88 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +const {clear, registerAndLogin, + sendTokensTransfer, getTransfer, getToken, + completePending, feedTokens, deleteToken +} = require("../utils/testUtils"); +const {post} = require("../utils/sendReq"); +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const walletBInfo = require('../mock-data/wallet/walletB.json'); +chai.use(require('chai-uuid')); + +describe('Create and accept a pending transfer', () => { + let walletA; + let walletB; + let transfer; + let tokens = []; + + before(async () => { + await clear(); + }); + afterEach(async () => { + tokens = []; + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + + tokens = await feedTokens(walletA, 5); + transfer = await sendTokensTransfer(walletA, walletB, TransferEnums.STATE.pending, tokens.map(token => token.id)); + }); + + it('Accept a pending transfer', async () => { + const res = await post(`/transfers/${transfer.id}/accept`, walletB); + expect(res).to.have.property('statusCode', 200); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.completed); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(5); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(0); + }); + + it('Accept the transfer which already accepted', async () => { + await completePending(transfer); + + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + expect(res).to.have.property('statusCode', 409); + const walletBToken = await getToken(walletB); + expect(walletBToken.length).to.eq(0); + const walletAToken = await getToken(walletA); + expect(walletAToken.length).to.eq(5); + }) + + it('Accept the transfer which is belong to other account', async () => { + const weiyu = await registerAndLogin({name: 'weiyu', password: 'test1234'}); + + const res = await post(`/transfers/${transfer.id}/accept`, weiyu) + expect(res).to.have.property('statusCode', 403); + + getToken(weiyu).then((result) => { + expect(result.length).to.eq(0); + }) + + getToken(walletA).then((result) => { + expect(result.length).to.eq(5); + }) + }) + + it('Accept the transfer, the tokens are not enough', async () => { + await deleteToken(tokens[0]); + const res = await post(`/transfers/${transfer.id}/accept`, walletB) + + expect(res).to.have.property('statusCode', 200); + + getToken(walletB).then((result) => { + expect(result.length).to.eq(4); // the request token are 5, but get 4 now, before of some unknown deleting operation + // we expect to get a 4XX response. and fail this transfer. + }) + + getToken(walletA).then((result) => { + expect(result.length).to.eq(0); + }) + }) +}); diff --git a/__tests__/integration/pending-transfer-cancel.spec.js b/__tests__/integration/pending-transfer-cancel.spec.js new file mode 100644 index 00000000..b8162fc3 --- /dev/null +++ b/__tests__/integration/pending-transfer-cancel.spec.js @@ -0,0 +1,58 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const { + clear, + registerAndLogin, + getTransfer, sendTokensTransfer, feedTokens +} = require('../utils/testUtils') +const {del} = require('../utils/sendReq'); +const TransferEnums = require('../../server/utils/transfer-enum'); +const walletAInfo = require("../mock-data/wallet/walletA.json"); +const walletBInfo = require("../mock-data/wallet/walletB.json"); +chai.use(require('chai-uuid')); + +describe('Create and cancel a pending transfer', () => { + let walletA; + let walletB; + let transfer; + let tokens = []; + + before(clear); + + afterEach(async () => { + tokens = []; + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + + tokens = await feedTokens(walletA, 5); + transfer = await sendTokensTransfer(walletA, walletB, TransferEnums.STATE.pending, tokens.map(token => token.id)); + }); + + it('Cancel a pending transfer', async () => { + const res = await del(`/transfers/${transfer.id}`, walletA); + expect(res).to.have.property('statusCode', 200); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); + }) + + it('Cancel a pending transfer by receiver', async () => { + const res = await del(`/transfers/${transfer.id}`, walletB); + expect(res).to.have.property('statusCode', 403); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.pending); + }) + + it('Cancel a pending transfer, which belong to other account', async () => { + const walletC = await registerAndLogin({name: 'walletC', password: 'test12'}); + + const res = await del(`/transfers/${transfer.id}`, walletC); + expect(res).to.have.property('statusCode', 403); + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.pending); + }) +}); diff --git a/__tests__/integration/pending-transfer-decline.spec.js b/__tests__/integration/pending-transfer-decline.spec.js new file mode 100644 index 00000000..0d6d3235 --- /dev/null +++ b/__tests__/integration/pending-transfer-decline.spec.js @@ -0,0 +1,63 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +const { + clear, registerAndLogin, getTransfer, + sendTokensTransfer, feedTokens, cancelPending +} = require("../utils/testUtils"); +const {post} = require('../utils/sendReq'); +const walletAInfo = require("../mock-data/wallet/walletA.json"); +const walletBInfo = require("../mock-data/wallet/walletB.json"); +chai.use(require('chai-uuid')); + +describe('Create and decline a pending transfer', () => { + let walletA; + let walletB; + let transfer; + let tokens = []; + + before(async () => { + await clear(); + }); + afterEach(async () => { + tokens = []; + await clear(); + }); + + beforeEach(async () => { + await clear(); + walletA = await registerAndLogin(walletAInfo); + walletB = await registerAndLogin(walletBInfo); + + tokens = await feedTokens(walletA, 5); + transfer = await sendTokensTransfer(walletA, walletB, TransferEnums.STATE.pending, tokens.map(token => token.id)); + }); + + it('Decline a pending transfer', async () => { + const res = await post(`/transfers/${transfer.id}/decline`, walletB); + expect(res).to.have.property('statusCode', 200); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); + }); + + it('Decline a pending transfer which already declined/canceled', async () => { + await cancelPending(transfer); + + const res = await post(`/transfers/${transfer.id}/decline`, walletB); + expect(res).to.have.property('statusCode', 409); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.cancelled); + }) + + it('Decline a pending transfer which is belong to others', async () => { + const walletC = await registerAndLogin({name: 'fdgjsgfhsa', password: 'fhdjsgfhjds12'}); + const res = await post(`/transfers/${transfer.id}/decline`, walletC); + expect(res).to.have.property('statusCode', 403); + + const updatedTransfer = await getTransfer(transfer); + expect(updatedTransfer.state).to.eq(TransferEnums.STATE.pending); + }) +}); diff --git a/__tests__/seed.spec.js b/__tests__/integration/seed.spec.js similarity index 93% rename from __tests__/seed.spec.js rename to __tests__/integration/seed.spec.js index e374329d..302b45ed 100644 --- a/__tests__/seed.spec.js +++ b/__tests__/integration/seed.spec.js @@ -1,6 +1,6 @@ const { expect } = require('chai'); -const seed = require('./seed'); -const knex = require('../server/infra/database/knex'); +const seed = require('../utils/seed'); +const knex = require('../../server/infra/database/knex'); describe('Seed data into DB', () => { let token; diff --git a/__tests__/session.spec.js b/__tests__/integration/session.spec.js similarity index 93% rename from __tests__/session.spec.js rename to __tests__/integration/session.spec.js index b85e6d80..da456b23 100644 --- a/__tests__/session.spec.js +++ b/__tests__/integration/session.spec.js @@ -4,8 +4,8 @@ const jestExpect = require('expect'); const chai = require('chai'); const sinonChai = require('sinon-chai'); -const Session = require('../server/infra/database/Session'); -const seed = require('./seed'); +const Session = require('../../server/infra/database/Session'); +const seed = require('../utils/seed'); chai.use(sinonChai); const { expect } = chai; diff --git a/__tests__/integration/testUtils.js b/__tests__/integration/testUtils.js deleted file mode 100644 index e1839551..00000000 --- a/__tests__/integration/testUtils.js +++ /dev/null @@ -1,123 +0,0 @@ -const uuid = require('uuid'); -const log = require('loglevel'); -const Crypto = require('crypto'); -const generator = require('generate-password'); -const { expect } = require('chai'); -const JWTService = require('../../server/services/JWTService'); -const TransferEnum = require('../../server/utils/transfer-enum'); -const knex = require('../../server/infra/database/knex'); - -/* - * register the user, create password hash, and apiKey - */ -async function register(user) { - const sha512 = function (password, salt) { - const hash = Crypto.createHmac( - 'sha512', - salt, - ); /** Hashing algorithm sha512 */ - hash.update(password); - const value = hash.digest('hex'); - return value; - }; - - const salt = Crypto.randomBytes(32).toString('base64'); // create a secure salt - const passwordHash = sha512(user.password, salt); - - const apiKey = generator.generate({ - length: 32, - numbers: true, - }); - - await knex('api_key').insert({ - key: apiKey, - tree_token_api_access: true, - hash: 'test', - salt: 'test', - name: 'test', - }); - - // wallet - const result = await knex('wallet') - .insert({ - id: uuid.v4(), - name: user.name, - password: passwordHash, - salt, - }) - .returning('*'); - log.info('registered wallet:', result); - return { - ...result[0], - apiKey, - // restore password - password: user.password, - }; -} - -/* - * create the user, apiKey, then login, return - * token - */ -async function registerAndLogin(user) { - const userRegistered = await register(user); - const token = JWTService.sign(userRegistered); - userRegistered.token = token; - expect(userRegistered).property('apiKey').a('string'); - return userRegistered; -} - -async function clear() { - log.debug('clear tables'); - await knex('api_key').del(); - await knex('transaction').del(); - await knex('token').del(); - await knex('wallet').del(); - await knex('wallet_trust').del(); - await knex('transfer').del(); -} - -/* - * Add a token to a wallet - */ -async function addToken(wallet, token) { - const result = await knex('token') - .insert({ - ...token, - wallet_id: wallet.id, - }) - .returning('*'); - expect(result[0]).property('id').eq(token.id); - expect(result[0]).property('wallet_id').eq(wallet.id); - return result[0]; -} - -/* - * Directly pending a token send request - */ -async function sendAndPend(walletSender, walletReceiver, bundleSize) { - const result = await knex('transfer') - .insert({ - id: uuid.v4(), - originator_wallet_id: walletSender.id, - source_wallet_id: walletSender.id, - destination_wallet_id: walletReceiver.id, - type: TransferEnum.TYPE.send, - parameters: { - bundleSize, - }, - state: TransferEnum.STATE.pending, - active: true, - }) - .returning('*'); - expect(result[0]).property('id').a('string'); - return result[0]; -} - -module.exports = { - register, - registerAndLogin, - clear, - sendAndPend, - addToken, -}; diff --git a/__tests__/integration/trust-relationship-accept-request.spec.js b/__tests__/integration/trust-relationship-accept-request.spec.js new file mode 100644 index 00000000..0d76811d --- /dev/null +++ b/__tests__/integration/trust-relationship-accept-request.spec.js @@ -0,0 +1,85 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const {clear, registerAndLogin, createTrustRelation, getTrustRelationship} = require('../utils/testUtils'); +const {post} = require('../utils/sendReq'); + +describe('Accept trust relationship requests', () => { + let walletA; + let walletB; + const relations = ['receive', 'manage', 'send', 'yield']; + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'test123'}); + walletB = await registerAndLogin({name: 'walletB', password: 'test123'}); + }); + + afterEach(clear); + + it('Accept trust relationship requests', async () => { + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const request = await createTrustRelation(walletA, walletA, walletB, relation, 'requested'); + + // {baseUrl}}/trust_relationships/:trust_relationship_id/accept + const res = await post(`/trust_relationships/${request.id}/accept`, walletB); + + expect(res).property('statusCode').to.eq(200); + expect(res.body.id).to.eq(request.id); + expect(res.body.actor_wallet_id).to.eq(walletA.id); + expect(res.body.target_wallet_id).to.eq(walletB.id); + expect(res.body.request_type).to.eq(relation); + expect(res.body.state).to.eq('trusted'); + + // create an empty wallet for next loop test + walletA = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + walletB = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + } + }) + + it('Accept trust relationship requests, but the requests belong to other wallets', async () => { + const walletC = await registerAndLogin({name: 'walletC', password: 'test1243'}); + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const request = await createTrustRelation(walletA,walletA, walletB, relation, 'requested'); + const res = await post(`/trust_relationships/${request.id}/accept`, walletC); + + expect(res).property('statusCode').to.eq(404); + + const updatedRequest = await getTrustRelationship(request); + expect(updatedRequest.id).to.eq(request.id); + expect(updatedRequest.state).to.eq('requested'); + + // create an empty wallet for next loop test + walletA = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + walletB = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + } + }) + + + it('Accept trust relationship requests, but the request has been accepted', async () => { + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const request = await createTrustRelation(walletA,walletA, walletB, relation, 'trusted'); + const res = await post(`/trust_relationships/${request.id}/accept`, walletB); + + expect(res).property('statusCode').to.eq(200); + expect(res.body.id).to.eq(request.id); + expect(res.body.actor_wallet_id).to.eq(walletA.id); + expect(res.body.target_wallet_id).to.eq(walletB.id); + expect(res.body.request_type).to.eq(relation); + expect(res.body.state).to.eq('trusted'); + + // create an empty wallet for next loop test + walletA = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + walletB = await registerAndLogin({name: Date.now().toString(), password: 'test123'}) + } + }) + + it('Accept trust relationship requests, but the ID is invalid', async () => { + const res = await post(`/trust_relationships/f4b20216-6d8e-44f1-9b96-1f9e42a9b4d5/accept`, walletB); + expect(res).property('statusCode').to.eq(404); + }) +}) \ No newline at end of file diff --git a/__tests__/integration/trust-relationship-cancel.spec.js b/__tests__/integration/trust-relationship-cancel.spec.js new file mode 100644 index 00000000..6b2198ba --- /dev/null +++ b/__tests__/integration/trust-relationship-cancel.spec.js @@ -0,0 +1,96 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const {clear, registerAndLogin, createTrustRelation, getTrustRelationship, updateTrustRelation} = require('../utils/testUtils') +chai.use(require('chai-uuid')); +const {del} = require('../utils/sendReq'); +const {send, manage} = require('../../server/utils/trust-enums').ENTITY_TRUST_REQUEST_TYPE; +const {requested, trusted,cancelled_by_originator} = require('../../server/utils/trust-enums').ENTITY_TRUST_STATE_TYPE; + +describe('Cancel the requested trust relationship', () => { + let walletA; + let walletB; + let walletC; + + let relationship; + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + // wallet A 'manage' walletB + // wallet B request to 'send' walletC + walletA = await registerAndLogin({name: 'waleltA', password: 'test123'}); + walletB = await registerAndLogin({name: 'waleltB', password: 'test123'}); + walletC = await registerAndLogin({name: 'walletC', password: 'test134'}) + + await createTrustRelation(walletA, walletA, walletB, manage, trusted); + relationship = await createTrustRelation(walletA, walletB, walletC, send, requested); + }); + + afterEach(clear); + + it(`Cancel the trust relationship by originator wallet`, async () => { + const res = await del(`/trust_relationships/${relationship.id}`, walletA); + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(cancelled_by_originator); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(cancelled_by_originator); + }); + + it(`Cancel the trust relationship by actor wallet`, async () => { + // originator => walletA + // actor => walletB + // target => walletC + + // walletA 'trusted manage' walletB + // walletB 'requested send' walletC + const res = await del(`/trust_relationships/${relationship.id}`, walletB); + expect(res).property('statusCode').to.eq(403); // msg: Have no permission to cancel this relationship + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(requested); // the state is still 'requested' + }); + + // same response with 1st 'it' bracket + it(`Cancel the trust relationship, but it has already be canceled`, async () => { + await updateTrustRelation(relationship, {state: cancelled_by_originator}) + + const res = await del(`/trust_relationships/${relationship.id}`, walletA); + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(cancelled_by_originator); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(cancelled_by_originator); + }); + + it(`Cancel the trust relationship, but the state is "trusted"`, async () => { + const res = await del(`/trust_relationships/${relationship.id}`, walletA); + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(cancelled_by_originator); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(cancelled_by_originator); + + }); + + it('Cancel the trust relationship, but it belongs to other account', async () => { + const walletD = await registerAndLogin({name: 'walletD', password: 'test123'}); + + const res = await del(`/trust_relationships/${relationship.id}`, walletD); + expect(res).property('statusCode').to.eq(403); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(requested); + }) + + it('Cancel the trust relationship by target wallet', async ()=> { + const res = await del(`/trust_relationships/${relationship.id}`, walletC); + expect(res).property('statusCode').to.eq(403); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(requested); + }) +}); diff --git a/__tests__/integration/trust-relationship-decline.spec.js b/__tests__/integration/trust-relationship-decline.spec.js new file mode 100644 index 00000000..8f7276c6 --- /dev/null +++ b/__tests__/integration/trust-relationship-decline.spec.js @@ -0,0 +1,77 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const chai = require('chai'); +const { + clear, + registerAndLogin, + createTrustRelation, getTrustRelationship, updateTrustRelation +} = require('../utils/testUtils') +chai.use(require('chai-uuid')); +const { post} = require('../utils/sendReq'); +const {send, manage} = require('../../server/utils/trust-enums').ENTITY_TRUST_REQUEST_TYPE; +const {requested, trusted, canceled_by_target, cancelled_by_originator} = require('../../server/utils/trust-enums').ENTITY_TRUST_STATE_TYPE; + + +describe('Decline the trust relationship', () => { + let walletA; + let walletB; + let walletC; + let relationship; + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'test123'}); + walletB = await registerAndLogin({name: 'walletB', password: 'test123'}); + walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + + // walletC 'trusted manage' walletB, wallet A 'requested send' wallet B + await createTrustRelation(walletC, walletC, walletB, manage, trusted); + relationship = await createTrustRelation(walletA, walletA, walletB, send, requested); + }); + + afterEach(clear); + + it(`Decline the trust relationship by target wallet`, async () => { + const res = await post(`/trust_relationships/${relationship.id}/decline`, walletB); + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(canceled_by_target); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(canceled_by_target); + }); + + it('Decline the trust relationship by the wallet which manage the target wallet', async () => { + const res = await post(`/trust_relationships/${relationship.id}/decline`, walletC); + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(canceled_by_target); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(canceled_by_target); + }); + + // the state success to updated, although the relationship already canceled/declined before this request + it('Decline the trust relationship which has already canceled/declined', async () => { + await updateTrustRelation(relationship, {state: cancelled_by_originator}) + const res = await post(`/trust_relationships/${relationship.id}/decline`, walletB); + + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(canceled_by_target); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(canceled_by_target); + }); + + it('Decline the trust relationship, but the state is "trusted"', async () => { + await updateTrustRelation(relationship, {state: trusted}); + const res = await post(`/trust_relationships/${relationship.id}/decline`, walletB); + + expect(res).property('statusCode').to.eq(200); + expect(res.body.state).to.eq(canceled_by_target); + + const updatedRelationship = await getTrustRelationship(relationship); + expect(updatedRelationship.state).to.eq(canceled_by_target); + }) +}); diff --git a/__tests__/integration/trust-relationship-manage.spec.js b/__tests__/integration/trust-relationship-manage.spec.js new file mode 100644 index 00000000..a56d89b4 --- /dev/null +++ b/__tests__/integration/trust-relationship-manage.spec.js @@ -0,0 +1,115 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +const { + clear, + registerAndLogin, + createTrustRelation, + feedTokens, + getToken, updateTrustRelation +} = require('../utils/testUtils'); +const {post} = require("../utils/sendReq"); + +describe('Send tokens to "manage" trust relationship wallet', () => { + let walletA; // walletA 'manage' walletB + let walletB; + let walletC; // walletC 'yield' walletD + let walletD; + + let relationshipA; + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'test123'}); + walletB = await registerAndLogin({name: 'walletB', password: 'test123'}); + walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + walletD = await registerAndLogin({name: 'walletD', password: 'test123'}); + + // each wallet has one token + await feedTokens(walletA, 1); + await feedTokens(walletB, 1); + await feedTokens(walletC, 1); + await feedTokens(walletD, 1); + // walletA 'send' walletB, and walletC 'receive' walletD + relationshipA = await createTrustRelation(walletA, walletA, walletB, 'manage', 'trusted'); + await createTrustRelation(walletC, walletC, walletD, 'yield', 'trusted'); + }); + + afterEach(async () => { + await clear(); + }); + + it('send token transfers to "manage" relationship wallet', async () => { + let reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletB.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + const resA = await post('/transfers', walletA, null, reqBody); + expect(resA).property('statusCode').to.eq(201); + expect(resA.body.state).to.eq('completed'); + expect((await getToken(walletA)).length).to.eq(0); + expect((await getToken(walletB)).length).to.eq(2); + + // walletC 'yield' walletD ====> walletD 'manage' walletC + reqBody = { + sender_wallet: walletD.name, + receiver_wallet: walletC.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const resB = await post('/transfers', walletD, null, reqBody); + expect(resB).property('statusCode').to.eq(201); + expect(resB.body.state).to.eq(TransferEnums.STATE.completed); + expect((await getToken(walletD)).length).to.eq(0); + expect((await getToken(walletC)).length).to.eq(2); + }) + + it('walletA send tokens to walletE, but the walletE has not accept the "manage" trust relationship', async () => { + const walletE = await registerAndLogin({name: 'walletE', password: 'abcabc1'}); + await createTrustRelation(walletA, walletA, walletE, 'manage', 'requested'); + + const reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletE.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const res = await post('/transfers', walletA, null, reqBody); + expect(res).property('statusCode').to.eq(202); + expect(res.body.state).to.eq(TransferEnums.STATE.pending); + expect((await getToken(walletA)).length).to.eq(1); + expect((await getToken(walletE)).length).to.eq(0); + }) + + it('send tokens to other wallet, but the trust relationship has canceled', async () => { + await updateTrustRelation(relationshipA, {state: 'cancelled_by_originator'}); + + const reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletB.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const res = await post('/transfers', walletA, null, reqBody); + expect(res).property('statusCode').to.eq(202); + expect(res.body.state).to.eq(TransferEnums.STATE.pending); + expect((await getToken(walletA)).length).to.eq(1); + expect((await getToken(walletB)).length).to.eq(1); + }) +}); \ No newline at end of file diff --git a/__tests__/integration/trust-relationship-request.spec.js b/__tests__/integration/trust-relationship-request.spec.js new file mode 100644 index 00000000..1ddde704 --- /dev/null +++ b/__tests__/integration/trust-relationship-request.spec.js @@ -0,0 +1,98 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const {clear, registerAndLogin, getTrustRelationship, feedSubWallets} = require('../utils/testUtils'); +const {post} = require('../utils/sendReq'); + +describe('Send trust requests to another wallet', () => { + let walletA; + let walletB; + const relations = ['receive', 'manage', 'send', 'yield']; + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'test123'}); + walletB = await registerAndLogin({name: 'walletB', password: 'test123'}); + }); + + afterEach(clear); + + it('send 4 type of relationship requests', async () => { + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const res = await post('/trust_relationships', walletA, null, { + trust_request_type: relation, + requestee_wallet: walletB.name + }); + expect(res).property('statusCode').to.eq(201); + expect(res.body.actor_wallet).to.eq(walletA.name); + expect(res.body.originator_wallet).to.eq(walletA.name); + expect(res.body.target_wallet).to.eq(walletB.name); + expect(res.body.request_type).to.eq(relation); + expect(res.body.state).to.eq('requested'); + + const relationship = await getTrustRelationship(res.body); + expect(res.body.id).to.eq(relationship.id); + } + }) + + it('send 4 type of relationship request, but target wallet do not exist', async () => { + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const res = await post('/trust_relationships', walletA, null, { + trust_request_type: relation, + requestee_wallet: 'walletC' + }); + expect(res).property('statusCode').to.eq(404); + const updatedRelation = await getTrustRelationship({actorId: walletA.id}); + expect(updatedRelation).to.eq(undefined); + } + }) + + + it('send 4 type of relationship request, but requester is other account', async () => { + const walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const res = await post('/trust_relationships', walletA, null, + { + requester_wallet: walletC.name, + requestee_wallet: walletB.name, + trust_request_type: relation, + }); + expect(res).property('statusCode').to.eq(403); + const relationship = await getTrustRelationship({ + originatorId: walletA.id, + requesterId: walletC.id, + requesteeId: walletB.id + }); + expect(relationship).to.eq(undefined); + } + }) + + it('send 4 type of relationship request, but originator is its managed wallet', async () => { + const walletC = {name: 'walletC'} + await feedSubWallets(walletA, [walletC]); + + // eslint-disable-next-line no-restricted-syntax + for (const relation of relations) { + const res = await post('/trust_relationships', walletA, null, + { + requester_wallet: walletC.name, + requestee_wallet: walletB.name, + trust_request_type: relation, + }); + + expect(res).property('statusCode').to.eq(201); + expect(res.body.actor_wallet).to.eq(walletC.name); + expect(res.body.originator_wallet).to.eq(walletA.name); + expect(res.body.target_wallet).to.eq(walletB.name); + expect(res.body.request_type).to.eq(relation); + expect(res.body.state).to.eq('requested'); + + const relationship = await getTrustRelationship(res.body); + expect(res.body.id).to.eq(relationship.id); + } + }) +}); diff --git a/__tests__/integration/trust-relationship-send.spec.js b/__tests__/integration/trust-relationship-send.spec.js new file mode 100644 index 00000000..647fc6be --- /dev/null +++ b/__tests__/integration/trust-relationship-send.spec.js @@ -0,0 +1,115 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const TransferEnums = require('../../server/utils/transfer-enum'); +const { + clear, + registerAndLogin, + createTrustRelation, + feedTokens, + getToken, updateTrustRelation +} = require('../utils/testUtils'); +const {post} = require("../utils/sendReq"); + +describe('Send tokens to \'send\' trust relationship', () => { + let walletA; // walletA 'send' walletB + let walletB; + let walletC; // walletC 'receive' walletD + let walletD; + + let relationshipA; + + before(async () => { + await clear(); + }); + + beforeEach(async () => { + walletA = await registerAndLogin({name: 'walletA', password: 'test123'}); + walletB = await registerAndLogin({name: 'walletB', password: 'test123'}); + walletC = await registerAndLogin({name: 'walletC', password: 'test123'}); + walletD = await registerAndLogin({name: 'walletD', password: 'test123'}); + + // each wallet has one token + await feedTokens(walletA, 1); + await feedTokens(walletB, 1); + await feedTokens(walletC, 1); + await feedTokens(walletD, 1); + // walletA 'send' walletB, and walletC 'receive' walletD + relationshipA = await createTrustRelation(walletA, walletA, walletB, 'send', 'trusted'); + await createTrustRelation(walletC, walletC, walletD, 'receive', 'trusted'); + }); + + afterEach(async () => { + await clear(); + }); + + it('send tokens to "send" relationship wallet', async () => { + let reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletB.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + const resA = await post('/transfers', walletA, null, reqBody); + expect(resA).property('statusCode').to.eq(201); + expect(resA.body.state).to.eq('completed'); + expect((await getToken(walletA)).length).to.eq(0); + expect((await getToken(walletB)).length).to.eq(2); + + // walletC 'receive' walletD ====> walletD 'send' walletC + reqBody = { + sender_wallet: walletD.name, + receiver_wallet: walletC.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const resB = await post('/transfers', walletD, null, reqBody); + expect(resB).property('statusCode').to.eq(201); + expect(resB.body.state).to.eq(TransferEnums.STATE.completed); + expect((await getToken(walletD)).length).to.eq(0); + expect((await getToken(walletC)).length).to.eq(2); + }) + + it('walletA send tokens to walletE, but the walletE has not accept the "send" trust relationship', async () => { + const walletE = await registerAndLogin({name: 'walletE', password: 'abcabc1'}); + await createTrustRelation(walletA, walletA, walletE, 'send', 'requested'); + + const reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletE.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const res = await post('/transfers', walletA, null, reqBody); + expect(res).property('statusCode').to.eq(202); + expect(res.body.state).to.eq(TransferEnums.STATE.pending); + expect((await getToken(walletA)).length).to.eq(1); + expect((await getToken(walletE)).length).to.eq(0); + }) + + it('send tokens to other wallet, but the trust relationship has canceled', async () => { + await updateTrustRelation(relationshipA, {state: 'cancelled_by_originator'}); + + const reqBody = { + sender_wallet: walletA.name, + receiver_wallet: walletB.name, + bundle: { + bundle_size: 1 + }, + claim: false + } + + const res = await post('/transfers', walletA, null, reqBody); + expect(res).property('statusCode').to.eq(202); + expect(res.body.state).to.eq(TransferEnums.STATE.pending); + expect((await getToken(walletA)).length).to.eq(1); + expect((await getToken(walletB)).length).to.eq(1); + }) +}) \ No newline at end of file diff --git a/__tests__/integration/wallet-get.spec.js b/__tests__/integration/wallet-get.spec.js new file mode 100644 index 00000000..c169a5de --- /dev/null +++ b/__tests__/integration/wallet-get.spec.js @@ -0,0 +1,91 @@ +require('dotenv').config(); +const {expect} = require('chai'); +const sinon = require('sinon'); +const chai = require('chai'); +chai.use(require('chai-uuid')); +const {registerAndLogin, clear, feedSubWallets} = require('../utils/testUtils'); +const {get} = require('../utils/sendReq') +const walletAInfo = require('../mock-data/wallet/walletA.json'); +const walletBInfo = require('../mock-data/wallet/walletB.json'); +const wallets = require('../mock-data/wallet/wallets.json'); + + +describe('Wallet: Get wallets of an account', () => { + let walletA; + let walletB; + + before(async () => { + await clear(); + }) + + beforeEach(async () => { + walletA = await registerAndLogin(walletAInfo); + // what registerAndLogin returned? + // walletA = { + // name: , + // password: , + // salt: , + // logo_url: null, + // created_at: