Wallet/test/test.Identity.js
2014-10-24 10:51:04 -03:00

451 lines
13 KiB
JavaScript

'use strict';
var _ = require('underscore');
var chai = chai || require('chai');
var should = chai.should();
var copay = copay || require('../copay');
var sinon = require('sinon');
var FakeNetwork = require('./mocks/FakeNetwork');
var FakeBlockchain = require('./mocks/FakeBlockchain');
var FakeStorage = function FakeStorage() {};
var Identity = require('../js/models/Identity');
var Passphrase = require('../js/models/Passphrase');
var mockLocalStorage = require('./mocks/FakeLocalStorage');
var mockSessionStorage = require('./mocks/FakeLocalStorage');
var PERSISTED_PROPERTIES = (copay.Wallet || require('../js/models/Wallet')).PERSISTED_PROPERTIES;
function assertObjectEqual(a, b) {
PERSISTED_PROPERTIES.forEach(function(k) {
if (a[k] && b[k]) {
_.omit(a[k], 'name').should.be.deep.equal(b[k], k + ' differs');
}
})
}
describe('Identity model', function() {
var iden, storage, wallet, profile;
beforeEach(function() {
storage = sinon.stub();
storage.getItem = sinon.stub();
storage.setPassphrase = sinon.spy();
storage.getSessionId = sinon.spy();
storage.setFromObj = sinon.spy();
storage.setLastOpened = sinon.stub().yields(null);
storage.deletePrefix = sinon.stub().yields(null);
Identity._newStorage = sinon.stub().returns(storage);
wallet = sinon.stub();
wallet.store = sinon.stub().yields(null);
wallet.getId = sinon.stub().returns('wid:123');
Identity._newWallet = sinon.stub().returns(wallet);
profile = sinon.stub();
profile.addWallet = sinon.stub().yields(null);;
profile.deleteWallet = sinon.stub().yields(null);;
profile.listWallets = sinon.stub().returns([]);
profile.setLastOpenedTs = sinon.stub().yields(null);;
profile.store = sinon.stub().yields(null);;
Identity._newProfile = sinon.stub().returns(profile);
iden = new Identity(email, password, config);
});
afterEach(function() {
iden = storage = wallet = profile = undefined;
});
var email = 'hola@hola.com';
var password = 'password';
var config = {
wallet: {
requiredCopayers: 3,
totalCopayers: 5,
spendUnconfirmed: 1,
reconnectDelay: 100,
},
blockchain: {
host: 'test.insight.is',
port: 80,
schema: 'https'
},
networkName: 'testnet',
passphrase: {
iterations: 100,
storageSalt: 'mjuBtGybi/4=',
},
// network layer config
network: {
testnet: {
url: 'https://test-insight.bitpay.com:443'
},
livenet: {
url: 'https://insight.bitpay.com:443'
},
},
version: '0.0.1',
};
describe('#constructors', function() {
describe('#new', function() {
it('should create an identity', function() {
var iden = new Identity(email, password, config);
should.exist(iden);
iden.walletDefaults.should.deep.equal(config.wallet);
iden.version.should.equal('0.0.1');
should.exist(iden.profile.addWallet);
Identity._newProfile.getCall(0).args[0].should.deep.equal({
email: email
});
Identity._newProfile.getCall(0).args[1].should.equal(password);
Identity._newProfile.getCall(0).args[2].should.equal(iden.storage);
});
});
describe('#create', function(done) {
it('should call .store', function(done) {
Identity.create(email, password, config, function(err, iden) {
should.not.exist(err);
should.exist(iden.profile.addWallet);
iden.profile.store.getCall(0).args[0].should.deep.equal({
overwrite: false
});
done();
});
});
});
describe('#open', function(done) {
beforeEach(function() {
Identity._profileOpen = sinon.stub().callsArgWith(3, null, 'kk');
});
it('should call ._profileOpen', function(done) {
Identity.open(email, password, config, function(err, iden) {
should.not.exist(err);
iden.profile.should.equal('kk');
Identity._profileOpen.calledOnce.should.equal(true);
done();
});
});
});
});
describe('#store', function() {
it('should call .store from profile and no wallets', function(done) {
profile.store = sinon.stub().yields(null);
iden.wallets = [];
iden.store({}, function(err) {
should.not.exist(err);
profile.store.calledOnce.should.equal(true);
done();
});
});
it('should call .store from profile and wallets (2)', function(done) {
iden.profile.store = sinon.stub().yields(null);
iden.wallets = [{
store: sinon.stub().yields(null)
}, {
store: sinon.stub().yields(null)
}];
iden.store({}, function(err) {
should.not.exist(err);
iden.profile.store.calledOnce.should.equal(true);
iden.wallets[0].store.calledOnce.should.equal(true);
iden.wallets[1].store.calledOnce.should.equal(true);
done();
});
});
});
describe('#createWallet', function() {
it('should create wallet', function(done) {
iden.createWallet(null, function(err, w) {
should.exist(w);
should.not.exist(err);
done();
});
});
it('should add wallet to profile', function(done) {
iden.createWallet(null, function(err, w) {
profile.addWallet.getCall(0).args[0].should.contain('spy#');
done();
});
});
it('should be able to create wallets with given pk', function(done) {
var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m';
iden.createWallet({
privateKeyHex: priv,
}, function(err, w) {
Identity._newWallet.getCall(0).args[0].privateKey.toObj().extendedPrivateKeyString.should.equal(priv);
should.not.exist(err);
done();
});
});
it('should be able to create wallets with random pk', function(done) {
iden.createWallet(null, function(err, w1) {
iden.createWallet(null, function(err, w2) {
Identity._newWallet.getCall(0).args[0].privateKey.toObj().extendedPrivateKeyString.should.not.equal(
Identity._newWallet.getCall(1).args[0].privateKey.toObj().extendedPrivateKeyString
);
done();
});
});
});
});
describe('#deleteWallet', function() {
it('should call profile and wallet', function(done) {
iden.createWallet(null, function(err, w) {
iden.deleteWallet(w.id, function(err) {
should.not.exist(err);
done();
});
});
});
});
describe('#openWallet', function() {
beforeEach(function() {
iden.migrateWallet = sinon.stub().yields(null);
iden.profile.setLastOpened = sinon.stub().yields(null);
iden.storage.setPassphrase = sinon.spy();
storage.getFirst = sinon.stub().yields('wallet1234');
var wallet = sinon.stub();
wallet.store = sinon.stub().yields(null);
Identity._walletRead = sinon.stub().callsArgWith(5, null, wallet);
});
it('should call setPassphrase', function(done) {
var s1 = sinon.stub();
s1.store = sinon.stub().yields(null);
iden.openWallet('id123', 'xxx', function(err, w) {
iden.storage.setPassphrase.calledOnce.should.equal(true);
iden.storage.setPassphrase.getCall(0).args[0].should.equal('xxx');
done();
});
});
it('should return wallet and call .store, .setLastOpenedTs & .migrateWallet', function(done) {
iden.openWallet('dummy', 'xxx', function(err, w) {
should.not.exist(err);
w.store.calledOnce.should.equal(true);
iden.profile.setLastOpenedTs.calledOnce.should.equal(true);
iden.migrateWallet.calledOnce.should.equal(true);
done();
});
});
});
describe('#importWallet', function() {
beforeEach(function() {
iden.migrateWallet = sinon.stub().yields(null);
});
it('should create wallet from encrypted object', function(done) {
iden.storage.setPassphrase = sinon.spy();
iden.storage.decrypt = sinon.stub().withArgs('base64').returns({
networkName: 'testnet'
});
wallet.getId = sinon.stub().returns('ID123');
Identity._walletFromObj = sinon.stub().returns(wallet);
iden.importWallet("encrypted object", "xxx", [], function(err) {
iden.openWallet('ID123', 'xxx', function(err, w) {
should.not.exist(err);
should.exist(w);
done();
});
});
});
it('should import and update indexes', function() {
var wallet = {
id: "fake wallet",
updateIndexes: function(cb) {
cb();
}
};
iden.fromEncryptedObj = sinon.stub().returns(wallet);
var w = iden.fromEncryptedObj("encrypted", "password");
should.exist(w);
wallet.should.equal(w);
});
it('should import with a wrong password', function() {
iden.fromEncryptedObj = sinon.stub().returns(null);
var w = iden.fromEncryptedObj("encrypted", "passwordasdfasdf");
should.not.exist(w);
});
});
describe('#listWallets', function() {
it('should return empty array if no wallets', function() {
iden.listWallets();
iden.profile.listWallets.calledOnce.should.equal(true);
});
});
describe('#deleteWallet', function() {
Identity._walletDelete = sinon.stub().callsArgWith(2, null);
it('should call Profile deleteWallet', function(done) {
iden.profile.deleteWallet = sinon.stub().yields(null);
iden.deleteWallet('xxx', function() {
iden.profile.deleteWallet.getCall(0).args[0].should.equal('xxx');
done();
});
});
});
describe('#joinWallet', function() {
var opts = {
secret: '8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM',
nickname: 'test',
passphrase: 'pass'
};
it('should yield bad network error', function(done) {
var net = iden.networks['testnet'];
net.greet = sinon.stub();
net.cleanUp = sinon.stub();
net.start = sinon.stub().yields(null);
net.on = sinon.stub();
net.on.withArgs('data').yields('senderId', {
type: 'walletId',
networkName: 'aWeirdNetworkName',
opts: {},
});
opts.privHex = undefined;
iden.joinWallet(opts, function(err, w) {
err.should.equal('badNetwork');
done();
});
});
it('should yield to join error', function(done) {
opts.privHex = undefined;
var net = iden.networks['testnet'];
net.greet = sinon.stub();
net.cleanUp = sinon.stub();
net.start = sinon.stub().yields(null);
net.on = sinon.stub();
net.on.withArgs('serverError').yields(null);
net.on.withArgs('data').yields('senderId', {
type: 'walletId',
networkName: iden.networkName,
});
iden.joinWallet(opts, function(err, w) {
err.should.equal('joinError');
done();
});
});
it('should call network.start / create', function(done) {
opts.privHex = undefined;
var net = iden.networks['testnet'];
net.cleanUp = sinon.spy();
net.greet = sinon.spy();
net.start = sinon.stub().yields(null);
net.on = sinon.stub();
net.on.withArgs('connected').yields(null);
net.on.withArgs('data').yields('senderId', {
type: 'walletId',
networkName: 'testnet',
opts: {},
});
var w = sinon.stub();
w.sendWalletReady = sinon.spy();
iden.createWallet = sinon.stub().yields(null, w);
iden.joinWallet(opts, function(err, w) {
net.start.calledOnce.should.equal(true);
iden.createWallet.calledOnce.should.equal(true);
iden.createWallet.calledOnce.should.equal(true);
w.sendWalletReady.calledOnce.should.equal(true);
w.sendWalletReady.getCall(0).args[0].should.equal('03ddbc4711534bc62ccf576ab05f2a0afd11f9e2f4016781f3f5a88de9543a229a');
done();
});
});
it('should return walletFull', function(done) {
opts.privHex = undefined;
var net = iden.networks['testnet'];
net.cleanUp = sinon.spy();
net.greet = sinon.spy();
net.start = sinon.stub().yields(null);
net.on = sinon.stub();
net.on.withArgs('connected').yields(null);
net.on.withArgs('data').yields('senderId', {
type: 'walletId',
networkName: 'testnet',
opts: {},
});
iden.createWallet = sinon.stub().yields(null, null);
iden.joinWallet(opts, function(err, w) {
err.should.equal('walletFull');
done();
});
});
it('should accept a priv key a input', function() {
opts.privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd';
var net = iden.networks['testnet'];
net.cleanUp = sinon.spy();
net.start = sinon.spy();
iden.joinWallet(opts, function(err, w) {
net.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d');
});
});
it('should call network.start with private key', function() {
opts.privHex = undefined;
var net = iden.networks['testnet'];
net.cleanUp = sinon.spy();
net.start = sinon.spy();
iden.joinWallet(opts, function(err, w) {
net.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer
});
});
});