Skip to content

Commit

Permalink
Adds integration test.
Browse files Browse the repository at this point in the history
  • Loading branch information
conradoqg committed Apr 30, 2017
1 parent 56b8b99 commit bea8875
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 38 deletions.
File renamed without changes.
62 changes: 34 additions & 28 deletions lib/server/index.js → lib/httpServer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const ArgumentError = require('../util/argumentError');
const CryptoUtil = require('../util/cryptoUtil');

class HttpServer {
constructor(host, port, node, blockchain, operator, miner) {
const app = express();
constructor(node, blockchain, operator, miner) {
this.app = express();

const projectWallet = (wallet) => {
return {
Expand All @@ -24,22 +24,22 @@ class HttpServer {
};
};

app.use(bodyParser.json());
this.app.use(bodyParser.json());

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
this.app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

app.get('/blockchain/blocks', (req, res) => {
this.app.get('/blockchain/blocks', (req, res) => {
res.status(200).send(blockchain.getAllBlocks());
});

app.get('/blockchain/blocks/latest', (req, res) => {
this.app.get('/blockchain/blocks/latest', (req, res) => {
let lastBlock = blockchain.getLastBlock();
if (lastBlock == null) throw new HTTPError(404, 'Last block not found');

res.status(200).send(lastBlock);
});

app.put('/blockchain/blocks/latest', (req, res) => {
this.app.put('/blockchain/blocks/latest', (req, res) => {
let requestBlock = Block.fromJson(req.body);
let result = node.checkReceivedBlock(requestBlock);

Expand All @@ -48,32 +48,32 @@ class HttpServer {
else throw new HTTPError(409, 'Blockchain is update.');
});

app.get('/blockchain/blocks/:hash([a-zA-Z0-9]{64})', (req, res) => {
this.app.get('/blockchain/blocks/:hash([a-zA-Z0-9]{64})', (req, res) => {
let blockFound = blockchain.getBlockByHash(req.params.hash);
if (blockFound == null) throw new HTTPError(404, `Block not found with hash '${req.params.hash}'`);

res.status(200).send(blockFound);
});

app.get('/blockchain/blocks/:index', (req, res) => {
this.app.get('/blockchain/blocks/:index', (req, res) => {
let blockFound = blockchain.getBlockByIndex(req.params.index);
if (blockFound == null) throw new HTTPError(404, `Block not found with index '${req.params.index}'`);

res.status(200).send(blockFound);
});

app.get('/blockchain/blocks/transactions/:transactionId([a-zA-Z0-9]{64})', (req, res) => {
this.app.get('/blockchain/blocks/transactions/:transactionId([a-zA-Z0-9]{64})', (req, res) => {
let transactionFromBlock = blockchain.getTransactionFromBlocks(req.params.transactionId);
if (transactionFromBlock == null) throw new HTTPError(404, `Transaction '${req.params.transactionId}' not found in any block`);

res.status(200).send(transactionFromBlock);
});

app.get('/blockchain/transactions', (req, res) => {
this.app.get('/blockchain/transactions', (req, res) => {
res.status(200).send(blockchain.getAllTransactions());
});

app.post('/blockchain/transactions', (req, res) => {
this.app.post('/blockchain/transactions', (req, res) => {
let requestTransaction = Transaction.fromJson(req.body);
let transactionFound = blockchain.getTransactionById(requestTransaction.id);

Expand All @@ -88,19 +88,19 @@ class HttpServer {
}
});

app.get('/blockchain/transactions/unspent', (req, res) => {
this.app.get('/blockchain/transactions/unspent', (req, res) => {
res.status(200).send(blockchain.getUnspentTransactionsForAddress(req.query.address));
});

app.get('/operator/wallets', (req, res) => {
this.app.get('/operator/wallets', (req, res) => {
let wallets = operator.getWallets();

let projectedWallets = R.map(projectWallet, wallets);

res.status(200).send(projectedWallets);
});

app.post('/operator/wallets', (req, res) => {
this.app.post('/operator/wallets', (req, res) => {
let password = req.body.password;
if (R.match(/\w+/g, password).length <= 4) throw new HTTPError(400, 'Password must contain more than 4 words');

Expand All @@ -111,7 +111,7 @@ class HttpServer {
res.status(201).send(projectedWallet);
});

app.get('/operator/wallets/:walletId', (req, res) => {
this.app.get('/operator/wallets/:walletId', (req, res) => {
let walletFound = operator.getWalletById(req.params.walletId);
if (walletFound == null) throw new HTTPError(404, `Wallet not found with id '${req.params.walletId}'`);

Expand All @@ -120,7 +120,7 @@ class HttpServer {
res.status(200).send(projectedWallet);
});

app.post('/operator/wallets/:walletId/transactions', (req, res) => {
this.app.post('/operator/wallets/:walletId/transactions', (req, res) => {
let walletId = req.params.walletId;
let password = req.headers.password;

Expand All @@ -142,7 +142,7 @@ class HttpServer {
}
});

app.get('/operator/wallets/:walletId/addresses', (req, res) => {
this.app.get('/operator/wallets/:walletId/addresses', (req, res) => {
let walletId = req.params.walletId;
try {
let addresses = operator.getAddressesForWallet(walletId);
Expand All @@ -153,7 +153,7 @@ class HttpServer {
}
});

app.post('/operator/wallets/:walletId/addresses', (req, res) => {
this.app.post('/operator/wallets/:walletId/addresses', (req, res) => {
let walletId = req.params.walletId;
let password = req.headers.password;

Expand All @@ -171,7 +171,7 @@ class HttpServer {
}
});

app.get('/operator/wallets/:walletId/addresses/:addressId/balance', (req, res) => {
this.app.get('/operator/wallets/:walletId/addresses/:addressId/balance', (req, res) => {
let walletId = req.params.walletId;
let addressId = req.params.addressId;

Expand All @@ -184,23 +184,23 @@ class HttpServer {
}
});

app.get('/node/peers', (req, res) => {
this.app.get('/node/peers', (req, res) => {
res.status(200).send(node.peers);
});

app.post('/node/peers', (req, res) => {
this.app.post('/node/peers', (req, res) => {
let newPeer = node.connectToPeer(req.body);
res.status(201).send(newPeer);
});

app.get('/node/transactions/:transactionId([a-zA-Z0-9]{64})/confirmations', (req, res) => {
this.app.get('/node/transactions/:transactionId([a-zA-Z0-9]{64})/confirmations', (req, res) => {
node.getConfirmations(req.params.transactionId)
.then((confirmations) => {
res.status(200).send(confirmations.toString());
});
});

app.post('/miner/mine', (req, res, next) => {
this.app.post('/miner/mine', (req, res, next) => {
miner.mine(req.body.rewardAddress)
.then((newBlock) => {
newBlock = Block.fromJson(newBlock);
Expand All @@ -213,14 +213,20 @@ class HttpServer {
});
});

app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars
this.app.use(function (err, req, res, next) { // eslint-disable-line no-unused-vars
if (err instanceof HTTPError) res.status(err.status);
else res.status(500);
res.send(err.message + (err.cause ? ' - ' + err.cause.message : ''));
});
}

let server = app.listen(port, host, () => {
console.info(`Listening http on port: ${server.address().port}, to access the API documentation go to http://${host}:${server.address().port}/api-docs/`);
listen(host, port) {
return new Promise((resolve, reject) => {
this.server = this.app.listen(port, host, (err) => {
if (err) reject(err);
console.info(`Listening http on port: ${this.server.address().port}, to access the API documentation go to http://${host}:${this.server.address().port}/api-docs/`);
resolve();
});
});
}
}
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions lib/naivecoin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const HttpServer = require('./server');
const HttpServer = require('./httpServer');
const Blockchain = require('./blockchain');
const Operator = require('./operator');
const Miner = require('./miner');
Expand All @@ -20,6 +20,7 @@ module.exports = function naivecoin(host, port, peers, logLevel, name) {
let operator = new Operator(name, blockchain);
let miner = new Miner(blockchain, logLevel);
let node = new Node(host, port, peers, blockchain);
let httpServer = new HttpServer(node, blockchain, operator, miner);

new HttpServer(host, port, node, blockchain, operator, miner);
httpServer.listen(host, port);
};
3 changes: 2 additions & 1 deletion lib/util/consoleWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module.exports = (name, level = 6) => {
let origConsole = {};

let simpleWrapper = (typeDescriptor, ...args) => {
if (typeDescriptor.level <= level) origConsole.log(new Date().toISOString() + ' - ' + typeDescriptor.color(typeDescriptor.type) + ' - ' + name + ': ', ...args);
args[0] = new Date().toISOString() + ' - ' + typeDescriptor.color(typeDescriptor.type) + ' - ' + name + ': ' + (args[0] ? args[0] : '');
if (typeDescriptor.level <= level || typeDescriptor.type == 'log') origConsole.log(...args);
};

let methods = [
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@
"type": "git",
"url": "https://github.com/conradoqg/naivecoin.git"
},
"bin": {
"bin": {
"naivecoin": "bin/naivecoin.js"
},
"scripts": {
"start": "node bin/naivecoin.js",
"compose:up": "docker-compose up"
"start": "node bin/naivecoin.js",
"compose:up": "docker-compose up",
"test": "node node_modules/mocha/bin/_mocha -u tdd --colors test/"
},
"dependencies": {
"body-parser": "^1.17.1",
"cli-color": "^1.2.0",
"elliptic": "^6.4.0",
"es6-error": "^4.0.2",
"express": "~4.11.1",
"fs-extra": "^2.1.2",
"fs-extra": "^2.1.2",
"ramda": "^0.23.0",
"statuses": "^1.3.1",
"superagent": "^3.5.2",
Expand All @@ -33,8 +34,8 @@
"engines": {
"node": ">=6"
},
"devDependencies": {
"should": "^7.1.0",
"supertest": "^1.0.0"
"devDependencies": {
"supertest": "^1.0.0",
"mocha": "^3.3.0"
}
}
106 changes: 106 additions & 0 deletions test/integrationTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
const supertest = require('supertest');
const assert = require('assert');
const HttpServer = require('../lib/httpServer');
const Blockchain = require('../lib/blockchain');
const Operator = require('../lib/operator');
const Miner = require('../lib/miner');
const Node = require('../lib/node');
const fs = require('fs-extra');


describe('HTTP server', () => {
it('should create wallet, address, mine, create transaction and mine again', () => {
const name = 'integrationTest';

fs.removeSync('data/' + name + '/');

require('../lib/util/consoleWrapper.js')(name, 0);

let blockchain = new Blockchain(name);
let operator = new Operator(name, blockchain);
let miner = new Miner(blockchain, 0);
let node = new Node('localhost', 3001, [], blockchain);
let httpServer = new HttpServer(node, blockchain, operator, miner);

let context = {};
const walletPassword = 't t t t t';

return Promise.resolve()
.then(() => {
return supertest(httpServer.app)
.post('/operator/wallets')
.send({ password: walletPassword })
.expect(201);
})
.then((res) => {
context.walletId = res.body.id;
return supertest(httpServer.app)
.post(`/operator/wallets/${context.walletId}/addresses`)
.set({ password: walletPassword })
.expect(201);
})
.then((res) => {
context.address1 = res.text;
return supertest(httpServer.app)
.post(`/operator/wallets/${context.walletId}/addresses`)
.set({ password: walletPassword })
.expect(201);
})
.then((res) => {
context.address2 = res.text;
return supertest(httpServer.app)
.post(`/operator/wallets/${context.walletId}/addresses`)
.set({ password: walletPassword })
.expect(201);
})
.then(() => {
return supertest(httpServer.app)
.post('/miner/mine')
.send({ rewardAddress: context.address1 })
.expect(201);
})
.then(() => {
return supertest(httpServer.app)
.post(`/operator/wallets/${context.walletId}/transactions`)
.set({ password: walletPassword })
.send({
fromAddress: context.address1,
toAddress: context.address2,
amount: 1000000000,
changeAddress: context.address1
})
.expect(201);
})
.then((res) => {
context.transactionId = res.body.id;
return supertest(httpServer.app)
.post('/miner/mine')
.send({ rewardAddress: context.address1 })
.expect(201);
})
.then(() => {
return supertest(httpServer.app)
.get(`/node/transactions/${context.transactionId}/confirmations`)
.expect(200)
.expect((res) => {
assert(res.text == 1);
});
})
.then(() => {
return supertest(httpServer.app)
.get(`/operator/wallets/${context.walletId}/addresses/${context.address1}/balance`)
.expect(200)
.expect((res) => {
assert(res.text == 9000000000);
});
})
.then(() => {
return supertest(httpServer.app)
.get(`/operator/wallets/${context.walletId}/addresses/${context.address2}/balance`)
.expect(200)
.expect((res) => {
assert(res.text == 1000000000);
});
});
});
});

0 comments on commit bea8875

Please sign in to comment.