Merge pull request #2 from metaraine/master

Add mocha tests. Add support for caret (^).
This commit is contained in:
AJ ONeal 2015-10-21 10:05:38 -07:00
commit 361e1dd788
6 changed files with 247 additions and 154 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

View File

@ -4,7 +4,7 @@
"description": "Tools for manipulating semver strings and objects",
"main": "semver-utils.js",
"scripts": {
"test": "node semver-utils-test.js"
"test": "mocha"
},
"repository": {
"type": "git",
@ -18,5 +18,9 @@
],
"author": "AJ ONeal",
"license": "APACHEv2",
"readmeFilename": "README.md"
"readmeFilename": "README.md",
"devDependencies": {
"chai": "^3.0.0",
"mocha": "^2.2.5"
}
}

View File

@ -1,131 +0,0 @@
(function () {
var semverutils = require('./semver-utils')
;
function testParseRange() {
console.info('testParseRange');
var good =
[ 'v1.0.0'
, '< v2.0.0'
, '~v2.0.0'
, '~1.0.0'
, '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848'
, '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848 || v1.1.3'
, '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848 || v1.1.3 || 2.0.1-alpha.1227'
, '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848 || v1.1.3 || 2.0.1-alpha.1227 || 1.0.0 - 1.0.x'
, '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848 || v1.1.3 || 2.0.1-alpha.1227 || 1.0.0 - 1.0.x || 1.*'
]
;
good.every(function (range) {
var result = semverutils.parseRange(range)
;
if (!result || 0 === result.length) {
throw new Error("didn't parse something that should be parseable: " + range);
}
return true;
});
console.log(good[good.length - 1]);
console.log(semverutils.stringifyRange(semverutils.parseRange(good[good.length - 1])));
}
function testParse() {
console.info('testParse');
var good
, bad
;
good = [
"1.0.8"
, "1.23.7"
, "2.0.0-alpha.123.abc"
, "2.0.0-alpha.123.abc+build.acebfde1284"
, "1.0.0-alpha"
, "1.0.0-alpha.1"
, "1.0.0-0.3.7"
, "1.0.0-x.7.z.92"
, "1.0.0-alpha"
, "1.0.0-alpha.1"
, "1.0.0-beta.2"
, "1.0.0-beta.11"
, "1.0.0-rc.1"
, "1.0.0-rc.1+build.1"
, "1.0.0-rc.1+build.1-b"
, "1.0.0"
, "1.0.0+0.3.7"
, "1.3.7+build"
, "1.3.7+build.2.b8f12d7"
, "1.3.7+build.11.e0f985a"
, "1.3.7+build.11.e0f9-85a"
, "1.0.0+build-acbe"
, "2.0.0+build.acebfde1284-alpha.123.abc"
];
bad = [
// "v1.0.0" now allows optional 'v'
, "a.b.c"
, "1"
, "1.0.0b"
, "1.0"
, "1.0.0+b[\\]^_`uild" // [,\,],^,_,` are between A-z, but not A-Za-z
, "1.0.0+build-acbe." // trailing period
, "1.0.0+build.!@#$%"
];
good.every(function (version) {
var result = semverutils.parse(version)
;
if (!result) {
throw new Error("didn't parse something that should be parseable: " + version);
}
return true;
});
bad.every(function (version) {
var result = semverutils.parse(version)
;
if (result) {
throw new Error("parsed something that should not be parseable: " + version);
}
return true;
});
console.log(semverutils.parse("a.b.c")); // null
console.log(semverutils.parse("1.0.3"));
/*
{
semver: 1.0.3
, major: 1
, minor: 0
, patch: 3
}
*/
console.log(semverutils.parse("1.0.3-rc.1+build.aef312"));
/*
{
semver: v1.0.3-rc.1+build.aef312
, major: 1
, minor: 0
, patch: 3
, build: build.aef312
, release: rc.1
}
*/
console.log(semverutils.parse("1.0.0-rc.1-1"));
console.log(semverutils.parse("1.0.0-rc.1+build.1-b"));
console.log(semverutils.parse("1.0.0-rc.1-1+build.1-b"));
console.log(semverutils.parse("2.0.0+build.acebfde1284-alpha.123.abc"));
}
testParse();
testParseRange();
}());

View File

@ -8,9 +8,20 @@
// | | | |optional build prefixed by '+'
var reSemver = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/
//, reSemverRange = /\s*((\|\||\-)|(([<>~]?=?)\s*(v)?([0-9]+)(\.(x|[0-9]+))?(\.(x|[0-9]+))?(([\-+])([a-zA-Z0-9\.]+))?))\s*/g
, reSemverRange = /\s*((\|\||\-)|(([<>~]?=?)\s*(v)?([0-9]+)(\.(x|\*|[0-9]+))?(\.(x|\*|[0-9]+))?(([\-+])([a-zA-Z0-9\.]+))?))\s*/g
, reSemverRange = /\s*((\|\||\-)|(([<>~^]?=?)\s*(v)?([0-9]+)(\.(x|\*|[0-9]+))?(\.(x|\*|[0-9]+))?(([\-+])([a-zA-Z0-9\.-]+))?))\s*/g
;
// Returns a new object with all of the undefined properties removed from the given object
function pruned(obj) {
var o = {};
for(var key in obj) {
if ('undefined' !== typeof obj[key]) {
o[key] = obj[key];
}
}
return o;
}
function stringifySemver(obj) {
var str = ''
;
@ -43,7 +54,7 @@
}
arr.forEach(stringify);
return str.trim();
}
@ -86,7 +97,7 @@
// https://github.com/isaacs/node-semver/issues/10
// optional v
var m = reSemver.exec(version) || []
, ver = new SemVer({
, ver = new SemVer(pruned({
semver: m[0]
, version: m[1]
, major: m[2]
@ -94,13 +105,13 @@
, patch: m[4]
, release: m[5]
, build: m[6]
})
}))
;
if (0 === m.length) {
ver = null;
}
return ver;
}
@ -109,18 +120,9 @@
, arr = []
, obj
;
function prune(key) {
if ('undefined' === typeof obj[key]) {
delete obj[key];
}
}
while (true) {
m = reSemverRange.exec(str);
if (!m) {
break;
}
while (m = reSemverRange.exec(str)) {
obj = {
semver: m[3]
, operator: m[4] || m[2]
@ -134,11 +136,10 @@
if ('-' === m[12]) {
obj.release = m[13];
}
Object.keys(obj).forEach(prune);
arr.push(new SemVer(obj));
arr.push(new SemVer(pruned(obj)));
//console.log(m);
}
//return new SemVerRange(arr);
return arr;
}

26
test/deepOwnEqual.js Normal file
View File

@ -0,0 +1,26 @@
var assert = require('chai').assert;
// we need to define our own deepEqual function that ignores properties that are not hasOwnProperty. Not supported in chai.assert.deepEqual as of v3.0.0.
function deepOwnEqual(a, b) {
// if arrays of objects, recurse down to the objects
if(Array.isArray(a) && Array.isArray(b)) {
assert.deepEqual(a.length, b.length, 'Arrays have different lengths')
for(var i=0; i<a.length; i++) {
deepOwnEqual(a[i], b[i])
}
}
// compare all the object properties
else {
var aKeys = Object.keys(a);
var bKeys = Object.keys(b);
assert.deepEqual(aKeys, bKeys, 'Objects have different keys');
aKeys.forEach(function(key) {
assert.deepEqual(a[key], b[key], 'Expected values of "' + key + '" property to be equal in each object')
});
}
}
module.exports = deepOwnEqual

192
test/spec.js Normal file
View File

@ -0,0 +1,192 @@
var assert = require('chai').assert;
var semverutils = require('../semver-utils');
var deepOwnEqual = require('./deepOwnEqual');
describe('parse', function() {
it('should parse a simple 3-part version', function() {
deepOwnEqual(semverutils.parse('1.0.0'), {
semver: '1.0.0',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0'
});
});
it('should parse pre-release versions', function() {
deepOwnEqual(semverutils.parse('1.0.0-alpha1'), {
semver: '1.0.0-alpha1',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0',
release: 'alpha1'
});
});
it('should parse build numbers', function() {
deepOwnEqual(semverutils.parse('1.0.0+build-123'), {
semver: '1.0.0+build-123',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0',
build: 'build-123'
});
});
it('should not parse invalid versions', function() {
assert.equal(semverutils.parse('a.b.c'), null);
assert.equal(semverutils.parse('1'), null);
assert.equal(semverutils.parse('1.0'), null);
assert.equal(semverutils.parse('1.0.0b'), null);
assert.equal(semverutils.parse('1.0.0+build-abc.'), null, 'trailing period');
});
});
describe('parseRange', function() {
it('should parse an exact version as a range', function() {
deepOwnEqual(semverutils.parseRange('1.0.0'), [{
semver: '1.0.0',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should ignore the v- prefix', function() {
deepOwnEqual(semverutils.parseRange('v1.0.0'), [{
semver: 'v1.0.0',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse a comparison operator', function() {
deepOwnEqual(semverutils.parseRange('< v2.0.0'), [{
semver: '< v2.0.0',
operator: '<',
major: '2',
minor: '0',
patch: '0'
}]);
});
it('should parse tilde', function() {
deepOwnEqual(semverutils.parseRange('~1.0.0'), [{
semver: '~1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse caret', function() {
deepOwnEqual(semverutils.parseRange('^1.0.0'), [{
semver: '^1.0.0',
operator: '^',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse tilde and v- prefix', function() {
deepOwnEqual(semverutils.parseRange('~v1.0.0'), [{
semver: '~v1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse ||', function() {
deepOwnEqual(semverutils.parseRange('~1.0.0 || ~2.0.0'), [{
semver: '~1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}, {
operator: '||'
}, {
semver: '~2.0.0',
operator: '~',
major: '2',
minor: '0',
patch: '0'
}]);
});
it('should parse build numbers', function() {
deepOwnEqual(semverutils.parseRange('2.0.0+build.1848'), [{
semver: '2.0.0+build.1848',
major: '2',
minor: '0',
patch: '0',
build: 'build.1848'
}]);
});
it('should parse pre-release versions', function() {
deepOwnEqual(semverutils.parseRange('1.0.0-rc1'), [{
semver: '1.0.0-rc1',
major: '1',
minor: '0',
patch: '0',
release: 'rc1'
}]);
});
it('should parse pre-release versions with hyphens', function() {
deepOwnEqual(semverutils.parseRange('1.0.0-rc-2'), [{
semver: '1.0.0-rc-2',
major: '1',
minor: '0',
patch: '0',
release: 'rc-2'
}]);
});
it('should parse hyphen ranges', function() {
deepOwnEqual(semverutils.parseRange('1.0.0 - 1.0.x'), [{
semver: '1.0.0',
major: '1',
minor: '0',
patch: '0'
}, {
operator: '-'
}, {
semver: '1.0.x',
major: '1',
minor: '0',
patch: 'x'
}]);
});
it('should parse constrained * ranges', function() {
deepOwnEqual(semverutils.parseRange('1.*'), [{
semver: '1.*',
major: '1',
minor: '*',
}]);
});
it('should parse constrained .x', function() {
deepOwnEqual(semverutils.parseRange('1.x'), [{
semver: '1.x',
major: '1',
minor: 'x',
}]);
});
});