Browse Source

WIP, supertest testing

activeAddress
Matias Alejo Garcia 10 years ago
parent
commit
a6b797c092
  1. 250
      app.js
  2. 1
      lib/client/api.js
  3. 254
      lib/expressapp.js
  4. 3
      package.json
  5. 39
      test/integration/clientApi.js

250
app.js

@ -1,252 +1,10 @@
'use strict';
var _ = require('lodash');
var async = require('async');
var log = require('npmlog');
var express = require('express');
var querystring = require('querystring');
var bodyParser = require('body-parser')
var CopayServer = require('./lib/server');
log.debug = log.verbose;
log.level = 'debug';
CopayServer.initialize();
var app = express();
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,Authorization');
next();
});
var allowCORS = function(req, res, next) {
if ('OPTIONS' == req.method) {
res.send(200);
res.end();
return;
}
next();
}
app.use(allowCORS);
var POST_LIMIT = 1024 * 100 /* Max POST 100 kb */ ;
app.use(bodyParser.json({
limit: POST_LIMIT
}));
app.use(require('morgan')('dev'));
#!/usr/bin/env node
var ExpressApp = require('./lib/expressapp');
var port = process.env.COPAY_PORT || 3001;
var router = express.Router();
function returnError(err, res, req) {
if (err instanceof CopayServer.ClientError) {
var status = (err.code == 'NOTAUTHORIZED') ? 401 : 400;
log.error('Err: ' + status + ':' + req.url + ' :' + err.code + ':' + err.message);
res.status(status).json({
code: err.code,
error: err.message,
}).end();
} else {
var code, message;
if (_.isObject(err)) {
code = err.code;
message = err.message;
}
var m = message || err.toString();
log.error('Error: ' + req.url + ' :' + code + ':' + m);
res.status(code || 500).json({
error: m,
}).end();
}
};
function getCredentials(req) {
var identity = req.header('x-identity');
if (!identity) return;
return {
copayerId: identity,
signature: req.header('x-signature'),
};
};
function getServerWithAuth(req, res, cb) {
var credentials = getCredentials(req);
var auth = {
copayerId: credentials.copayerId,
message: req.method.toLowerCase() + '|' + req.url + '|' + JSON.stringify(req.body),
signature: credentials.signature,
};
CopayServer.getInstanceWithAuth(auth, function(err, server) {
if (err) return returnError(err, res, req);
return cb(server);
});
};
router.post('/v1/wallets/', function(req, res) {
var server = CopayServer.getInstance();
server.createWallet(req.body, function(err, walletId) {
if (err) return returnError(err, res, req);
res.json({
walletId: walletId,
});
});
});
router.post('/v1/wallets/:id/copayers/', function(req, res) {
req.body.walletId = req.params['id'];
var server = CopayServer.getInstance();
server.joinWallet(req.body, function(err, result) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
router.get('/v1/wallets/', function(req, res) {
getServerWithAuth(req, res, function(server) {
var result = {};
async.parallel([
function(next) {
server.getWallet({}, function(err, wallet) {
if (err) return next(err);
result.wallet = wallet;
next();
});
},
function(next) {
server.getBalance({}, function(err, balance) {
if (err) return next(err);
result.balance = balance;
next();
});
},
function(next) {
server.getPendingTxs({}, function(err, pendingTxps) {
if (err) return next(err);
result.pendingTxps = pendingTxps;
next();
});
},
], function(err) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
});
router.get('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getPendingTxs({}, function(err, pendings) {
if (err) return returnError(err, res, req);
res.json(pendings);
});
});
});
router.post('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
});
});
});
router.post('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createAddress(req.body, function(err, address) {
if (err) return returnError(err, res, req);
res.json(address);
});
});
});
router.get('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getAddresses({}, function(err, addresses) {
if (err) return returnError(err, res, req);
res.json(addresses);
});
});
});
router.get('/v1/balance/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getBalance({}, function(err, balance) {
if (err) return returnError(err, res, req);
res.json(balance);
});
});
});
router.post('/v1/txproposals/:id/signatures/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.signTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
// TODO Check HTTP verb and URL name
router.post('/v1/txproposals/:id/broadcast/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.broadcastTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.post('/v1/txproposals/:id/rejections', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.rejectTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.delete('/v1/txproposals/:id/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.removePendingTx(req.body, function(err) {
if (err) return returnError(err, res, req);
res.end();
});
});
});
// TODO: DEBUG only!
router.get('/v1/dump', function(req, res) {
var server = CopayServer.getInstance();
server.storage._dump(function() {
res.end();
});
});
app.use('/copay/api', router);
var app = ExpressApp.start();
app.listen(port);
console.log('Copay service running on port ' + port);

1
lib/client/api.js

@ -127,6 +127,7 @@ API.prototype._doRequest = function(method, url, args, data, cb) {
var absUrl = this.baseUrl + url;
var args = {
relUrl: url,
headers: {
'x-identity': data.copayerId,
'x-signature': reqSignature,

254
lib/expressapp.js

@ -0,0 +1,254 @@
'use strict';
var _ = require('lodash');
var async = require('async');
var log = require('npmlog');
var express = require('express');
var querystring = require('querystring');
var bodyParser = require('body-parser')
var CopayServer = require('./server');
log.debug = log.verbose;
log.level = 'debug';
var ExpressApp = function() {};
ExpressApp.start = function(opts) {
opts = opts || {};
CopayServer.initialize(opts.CopayServer);
var app = express();
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,Authorization');
next();
});
var allowCORS = function(req, res, next) {
if ('OPTIONS' == req.method) {
res.send(200);
res.end();
return;
}
next();
}
app.use(allowCORS);
var POST_LIMIT = 1024 * 100 /* Max POST 100 kb */ ;
app.use(bodyParser.json({
limit: POST_LIMIT
}));
app.use(require('morgan')('dev'));
var router = express.Router();
function returnError(err, res, req) {
if (err instanceof CopayServer.ClientError) {
var status = (err.code == 'NOTAUTHORIZED') ? 401 : 400;
log.error('Err: ' + status + ':' + req.url + ' :' + err.code + ':' + err.message);
res.status(status).json({
code: err.code,
error: err.message,
}).end();
} else {
var code, message;
if (_.isObject(err)) {
code = err.code;
message = err.message;
}
var m = message || err.toString();
log.error('Error: ' + req.url + ' :' + code + ':' + m);
res.status(code || 500).json({
error: m,
}).end();
}
};
function getCredentials(req) {
var identity = req.header('x-identity');
if (!identity) return;
return {
copayerId: identity,
signature: req.header('x-signature'),
};
};
function getServerWithAuth(req, res, cb) {
var credentials = getCredentials(req);
var auth = {
copayerId: credentials.copayerId,
message: req.method.toLowerCase() + '|' + req.url + '|' + JSON.stringify(req.body),
signature: credentials.signature,
};
CopayServer.getInstanceWithAuth(auth, function(err, server) {
if (err) return returnError(err, res, req);
return cb(server);
});
};
router.post('/v1/wallets/', function(req, res) {
var server = CopayServer.getInstance();
server.createWallet(req.body, function(err, walletId) {
if (err) return returnError(err, res, req);
res.json({
walletId: walletId,
});
});
});
router.post('/v1/wallets/:id/copayers/', function(req, res) {
req.body.walletId = req.params['id'];
var server = CopayServer.getInstance();
server.joinWallet(req.body, function(err, result) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
router.get('/v1/wallets/', function(req, res) {
getServerWithAuth(req, res, function(server) {
var result = {};
async.parallel([
function(next) {
server.getWallet({}, function(err, wallet) {
if (err) return next(err);
result.wallet = wallet;
next();
});
},
function(next) {
server.getBalance({}, function(err, balance) {
if (err) return next(err);
result.balance = balance;
next();
});
},
function(next) {
server.getPendingTxs({}, function(err, pendingTxps) {
if (err) return next(err);
result.pendingTxps = pendingTxps;
next();
});
},
], function(err) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
});
router.get('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getPendingTxs({}, function(err, pendings) {
if (err) return returnError(err, res, req);
res.json(pendings);
});
});
});
router.post('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
});
});
});
router.post('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createAddress(req.body, function(err, address) {
if (err) return returnError(err, res, req);
res.json(address);
});
});
});
router.get('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getAddresses({}, function(err, addresses) {
if (err) return returnError(err, res, req);
res.json(addresses);
});
});
});
router.get('/v1/balance/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getBalance({}, function(err, balance) {
if (err) return returnError(err, res, req);
res.json(balance);
});
});
});
router.post('/v1/txproposals/:id/signatures/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.signTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
// TODO Check HTTP verb and URL name
router.post('/v1/txproposals/:id/broadcast/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.broadcastTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.post('/v1/txproposals/:id/rejections', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.rejectTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.delete('/v1/txproposals/:id/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.removePendingTx(req.body, function(err) {
if (err) return returnError(err, res, req);
res.end();
});
});
});
// TODO: DEBUG only!
router.get('/v1/dump', function(req, res) {
var server = CopayServer.getInstance();
server.storage._dump(function() {
res.end();
});
});
app.use(opts.base_path || '/copay/api', router);
return app;
};
module.exports = ExpressApp;

3
package.json

@ -40,7 +40,8 @@
"mocha": "^1.18.2",
"sinon": "^1.10.3",
"memdown": "^1.0.0",
"jsdoc": "^3.3.0"
"jsdoc": "^3.3.0",
"supertest": "*"
},
"scripts": {
"start": "node server.js"

39
test/integration/clientApi.js

@ -4,14 +4,19 @@ var _ = require('lodash');
var chai = require('chai');
var sinon = require('sinon');
var should = chai.should();
var levelup = require('levelup');
var memdown = require('memdown');
var request = require('supertest');
var Client = require('../../lib/client');
var API = Client.API;
var Bitcore = require('bitcore');
var TestData = require('./clienttestdata');
var WalletUtils = require('../../lib/walletutils');
var ExpressApp = require('../../lib/expressapp');
var Storage = require('../../lib/storage');
describe('client API ', function() {
var client;
var client, app;
beforeEach(function() {
var fsmock = {};;
@ -24,10 +29,40 @@ describe('client API ', function() {
client = new Client({
storage: storage
});
var db = levelup(memdown, {
valueEncoding: 'json'
});
var storage = new Storage({
db: db
});
app = ExpressApp.start({
CopayServer: {
storage: storage
}
});
});
var helpers = {};
helpers.request = function(args) {
if (args.method == 'get') {
request(app)
.get(relUrl)
.end(cb);
} else {
request(app)
.post(relUrl)
.send(body)
.end(function(err, res) {
console.log('[clientApi.js.59:err:]', err, res); //TODO
return cb(err, res);
});
}
};
describe('#_tryToComplete ', function() {
it('should complete a wallet ', function(done) {
it.only('should complete a wallet ', function(done) {
var request = sinon.stub();
// Wallet request

Loading…
Cancel
Save