Merge pull request #824 from eordano/review/jsdoc-uri
Lint and cover URI completely
This commit is contained in:
commit
bd2e326708
17
lib/uri.js
17
lib/uri.js
|
@ -59,7 +59,7 @@ var URI = function(data, knownParams) {
|
||||||
*/
|
*/
|
||||||
URI.fromString = function fromString(str) {
|
URI.fromString = function fromString(str) {
|
||||||
if (typeof(str) !== 'string') {
|
if (typeof(str) !== 'string') {
|
||||||
throw TypeError('Expected a string');
|
throw new TypeError('Expected a string');
|
||||||
}
|
}
|
||||||
return new URI(str);
|
return new URI(str);
|
||||||
};
|
};
|
||||||
|
@ -93,11 +93,11 @@ URI.fromJSON = function fromJSON(json) {
|
||||||
*/
|
*/
|
||||||
URI.isValid = function(arg, knownParams) {
|
URI.isValid = function(arg, knownParams) {
|
||||||
try {
|
try {
|
||||||
var uri = new URI(arg, knownParams);
|
new URI(arg, knownParams);
|
||||||
return true;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +110,7 @@ URI.isValid = function(arg, knownParams) {
|
||||||
URI.parse = function(uri) {
|
URI.parse = function(uri) {
|
||||||
var info = URL.parse(uri, true);
|
var info = URL.parse(uri, true);
|
||||||
|
|
||||||
if (info.protocol != 'bitcoin:') {
|
if (info.protocol !== 'bitcoin:') {
|
||||||
throw new TypeError('Invalid bitcoin URI');
|
throw new TypeError('Invalid bitcoin URI');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ URI.Members = ['address', 'amount', 'message', 'label', 'r'];
|
||||||
* @throws {Error} Unknown required argument
|
* @throws {Error} Unknown required argument
|
||||||
*/
|
*/
|
||||||
URI.prototype._fromObject = function(obj) {
|
URI.prototype._fromObject = function(obj) {
|
||||||
|
/* jshint maxcomplexity: 10 */
|
||||||
|
|
||||||
if (!Address.isValid(obj.address)) {
|
if (!Address.isValid(obj.address)) {
|
||||||
throw new TypeError('Invalid bitcoin address');
|
throw new TypeError('Invalid bitcoin address');
|
||||||
|
@ -142,7 +143,9 @@ URI.prototype._fromObject = function(obj) {
|
||||||
this.amount = obj.amount;
|
this.amount = obj.amount;
|
||||||
|
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
if (key === 'address' || key === 'amount') continue;
|
if (key === 'address' || key === 'amount') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (/^req-/.exec(key) && this.knownParams.indexOf(key) === -1) {
|
if (/^req-/.exec(key) && this.knownParams.indexOf(key) === -1) {
|
||||||
throw Error('Unknown required argument ' + key);
|
throw Error('Unknown required argument ' + key);
|
||||||
|
@ -173,11 +176,7 @@ URI.prototype.toObject = function toObject() {
|
||||||
for (var i = 0; i < URI.Members.length; i++) {
|
for (var i = 0; i < URI.Members.length; i++) {
|
||||||
var m = URI.Members[i];
|
var m = URI.Members[i];
|
||||||
if (this.hasOwnProperty(m) && typeof(this[m]) !== 'undefined') {
|
if (this.hasOwnProperty(m) && typeof(this[m]) !== 'undefined') {
|
||||||
if (typeof(this[m].toString) === 'function') {
|
|
||||||
json[m] = this[m].toString();
|
json[m] = this[m].toString();
|
||||||
} else {
|
|
||||||
json[m] = this[m];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_.extend(json, this.extras);
|
_.extend(json, this.extras);
|
||||||
|
|
118
test/uri.js
118
test/uri.js
|
@ -8,90 +8,115 @@ var should = chai.should();
|
||||||
var URI = bitcore.URI;
|
var URI = bitcore.URI;
|
||||||
|
|
||||||
describe('URI', function() {
|
describe('URI', function() {
|
||||||
|
/* jshint maxstatements: 30 */
|
||||||
|
|
||||||
it('should parse uris strings', function() {
|
// TODO: Split this and explain tests
|
||||||
|
it('parses uri strings correctly (test vector)', function() {
|
||||||
var uri;
|
var uri;
|
||||||
|
|
||||||
URI.parse.bind(URI, 'badURI').should.throw(TypeError);
|
URI.parse.bind(URI, 'badURI').should.throw(TypeError);
|
||||||
|
|
||||||
uri = URI.parse('bitcoin:');
|
uri = URI.parse('bitcoin:');
|
||||||
expect(uri.address).to.be.undefined;
|
expect(uri.address).to.be.undefined();
|
||||||
expect(uri.amount).to.be.undefined;
|
expect(uri.amount).to.be.undefined();
|
||||||
expect(uri.otherParam).to.be.undefined;
|
expect(uri.otherParam).to.be.undefined();
|
||||||
|
|
||||||
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
expect(uri.amount).to.be.undefined;
|
expect(uri.amount).to.be.undefined();
|
||||||
expect(uri.otherParam).to.be.undefined;
|
expect(uri.otherParam).to.be.undefined();
|
||||||
|
|
||||||
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22');
|
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22');
|
||||||
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
uri.amount.should.equal('123.22');
|
uri.amount.should.equal('123.22');
|
||||||
expect(uri.otherParam).to.be.undefined;
|
expect(uri.otherParam).to.be.undefined();
|
||||||
|
|
||||||
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22&other-param=something&req-extra=param');
|
uri = URI.parse('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22' +
|
||||||
|
'&other-param=something&req-extra=param');
|
||||||
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri.address.should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
uri.amount.should.equal('123.22');
|
uri.amount.should.equal('123.22');
|
||||||
uri['other-param'].should.equal('something');
|
uri['other-param'].should.equal('something');
|
||||||
uri['req-extra'].should.equal('param');
|
uri['req-extra'].should.equal('param');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should statically validate uris', function() {
|
// TODO: Split this and explain tests
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj').should.be.true;
|
it('URIs can be validated statically (test vector)', function() {
|
||||||
URI.isValid('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw').should.be.true;
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj').should.equal(true);
|
||||||
|
URI.isValid('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw').should.equal(true);
|
||||||
|
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2').should.be.true;
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2')
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param').should.be.true;
|
.should.equal(true);
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&req-other=param', ['req-other']).should.be.true;
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param')
|
||||||
URI.isValid('bitcoin:mmrqEBJxUCf42vdb3oozZtyz5mKr3Vb2Em?amount=0.1&r=https%3A%2F%2Ftest.bitpay.com%2Fi%2F6DKgf8cnJC388irbXk5hHu').should.be.true;
|
.should.equal(true);
|
||||||
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&req-other=param',
|
||||||
|
['req-other']).should.equal(true);
|
||||||
|
URI.isValid('bitcoin:mmrqEBJxUCf42vdb3oozZtyz5mKr3Vb2Em?amount=0.1&' +
|
||||||
|
'r=https%3A%2F%2Ftest.bitpay.com%2Fi%2F6DKgf8cnJC388irbXk5hHu').should.equal(true);
|
||||||
|
|
||||||
URI.isValid('bitcoin:').should.be.false;
|
URI.isValid('bitcoin:').should.equal(false);
|
||||||
URI.isValid('bitcoin:badUri').should.be.false;
|
URI.isValid('bitcoin:badUri').should.equal(false);
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfk?amount=bad').should.be.false;
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfk?amount=bad').should.equal(false);
|
||||||
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfk?amount=1.2&req-other=param').should.be.false;
|
URI.isValid('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfk?amount=1.2&req-other=param')
|
||||||
URI.isValid('bitcoin:?r=https%3A%2F%2Ftest.bitpay.com%2Fi%2F6DKgf8cnJC388irbXk5hHu').should.be.false;
|
.should.equal(false);
|
||||||
|
URI.isValid('bitcoin:?r=https%3A%2F%2Ftest.bitpay.com%2Fi%2F6DKgf8cnJC388irbXk5hHu')
|
||||||
|
.should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail creation with no params', function() {
|
it('fails on creation with no params', function() {
|
||||||
(function(){
|
(function(){
|
||||||
new URI();
|
return new URI();
|
||||||
}).should.throw(TypeError);
|
}).should.throw(TypeError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create instance from bitcoin uri', function() {
|
describe('instantiation from bitcoin uri', function() {
|
||||||
|
/* jshint maxstatements: 25 */
|
||||||
var uri;
|
var uri;
|
||||||
|
|
||||||
|
it('parses address', function() {
|
||||||
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
uri.address.should.be.instanceof(bitcore.Address);
|
uri.address.should.be.instanceof(bitcore.Address);
|
||||||
uri.network.should.equal(Networks.livenet);
|
uri.network.should.equal(Networks.livenet);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses amount', function() {
|
||||||
uri = URI.fromString('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22');
|
uri = URI.fromString('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22');
|
||||||
uri.address.toString().should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
uri.address.toString().should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj');
|
||||||
uri.amount.should.equal(12322000000);
|
uri.amount.should.equal(12322000000);
|
||||||
expect(uri.otherParam).to.be.undefined;
|
expect(uri.otherParam).to.be.undefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses a testnet address', function() {
|
||||||
uri = new URI('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw');
|
uri = new URI('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw');
|
||||||
uri.address.should.be.instanceof(bitcore.Address);
|
uri.address.should.be.instanceof(bitcore.Address);
|
||||||
uri.network.should.equal(Networks.testnet);
|
uri.network.should.equal(Networks.testnet);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stores unknown parameters as "extras"', function() {
|
||||||
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param');
|
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param');
|
||||||
uri.address.should.be.instanceof(bitcore.Address);
|
uri.address.should.be.instanceof(bitcore.Address);
|
||||||
uri.amount.should.equal(120000000);
|
expect(uri.other).to.be.undefined();
|
||||||
expect(uri.other).to.be.undefined;
|
|
||||||
uri.extras.other.should.equal('param');
|
uri.extras.other.should.equal('param');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws error when a required feature is not supported', function() {
|
||||||
(function() {
|
(function() {
|
||||||
new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param&req-required=param');
|
return new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param&req-required=param');
|
||||||
}).should.throw(Error);
|
}).should.throw(Error);
|
||||||
|
});
|
||||||
|
|
||||||
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param&req-required=param', ['req-required']);
|
it('has no false negative when checking supported features', function() {
|
||||||
|
uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.2&other=param&' +
|
||||||
|
'req-required=param', ['req-required']);
|
||||||
uri.address.should.be.instanceof(bitcore.Address);
|
uri.address.should.be.instanceof(bitcore.Address);
|
||||||
uri.amount.should.equal(120000000);
|
uri.amount.should.equal(120000000);
|
||||||
uri.extras.other.should.equal('param');
|
uri.extras.other.should.equal('param');
|
||||||
uri.extras['req-required'].should.equal('param');
|
uri.extras['req-required'].should.equal('param');
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Split this and explain tests
|
||||||
it('should create instance from object', function() {
|
it('should create instance from object', function() {
|
||||||
|
/* jshint maxstatements: 25 */
|
||||||
var uri;
|
var uri;
|
||||||
|
|
||||||
uri = new URI({
|
uri = new URI({
|
||||||
|
@ -113,13 +138,13 @@ describe('URI', function() {
|
||||||
});
|
});
|
||||||
uri.address.should.be.instanceof(bitcore.Address);
|
uri.address.should.be.instanceof(bitcore.Address);
|
||||||
uri.amount.should.equal(120000000);
|
uri.amount.should.equal(120000000);
|
||||||
expect(uri.other).to.be.undefined;
|
expect(uri.other).to.be.undefined();
|
||||||
uri.extras.other.should.equal('param');
|
uri.extras.other.should.equal('param');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
new URI({
|
return new URI({
|
||||||
address: '1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj',
|
address: '1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj',
|
||||||
'req-required': param
|
'req-required': 'param'
|
||||||
});
|
});
|
||||||
}).should.throw(Error);
|
}).should.throw(Error);
|
||||||
|
|
||||||
|
@ -141,7 +166,8 @@ describe('URI', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should input/output String', function() {
|
it('should input/output String', function() {
|
||||||
var str = 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?message=Donation%20for%20project%20xyz&label=myLabel&other=xD';
|
var str = 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?' +
|
||||||
|
'message=Donation%20for%20project%20xyz&label=myLabel&other=xD';
|
||||||
URI.fromString(str).toString().should.equal(str);
|
URI.fromString(str).toString().should.equal(str);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -161,7 +187,8 @@ describe('URI', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support extra arguments', function() {
|
it('should support extra arguments', function() {
|
||||||
var uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?message=Donation%20for%20project%20xyz&label=myLabel&other=xD');
|
var uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?' +
|
||||||
|
'message=Donation%20for%20project%20xyz&label=myLabel&other=xD');
|
||||||
|
|
||||||
should.exist(uri.message);
|
should.exist(uri.message);
|
||||||
uri.message.should.equal('Donation for project xyz');
|
uri.message.should.equal('Donation for project xyz');
|
||||||
|
@ -197,4 +224,29 @@ describe('URI', function() {
|
||||||
|
|
||||||
uri1.address.toString().should.equal(uri2.address.toString());
|
uri1.address.toString().should.equal(uri2.address.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('writes correctly the "r" parameter on string serialization', function() {
|
||||||
|
var originalString = 'bitcoin:mmrqEBJxUCf42vdb3oozZtyz5mKr3Vb2Em?amount=0.1&' +
|
||||||
|
'r=https%3A%2F%2Ftest.bitpay.com%2Fi%2F6DKgf8cnJC388irbXk5hHu';
|
||||||
|
var uri = new URI(originalString);
|
||||||
|
uri.toString().should.equal(originalString);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays nicely on the console (#inspect)', function() {
|
||||||
|
var uri = 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj';
|
||||||
|
var instance = new URI(uri);
|
||||||
|
instance.inspect().should.equal('<URI: ' + uri + '>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails early when fromString isn\'t provided a string', function() {
|
||||||
|
expect(function() {
|
||||||
|
return URI.fromString(1);
|
||||||
|
}).to.throw();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails early when fromJSON isn\'t provided a valid JSON string', function() {
|
||||||
|
expect(function() {
|
||||||
|
return URI.fromJSON('¹');
|
||||||
|
}).to.throw();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue