diff --git a/classes/comparator.js b/classes/comparator.js index 54ce1394..2146c884 100644 --- a/classes/comparator.js +++ b/classes/comparator.js @@ -90,32 +90,43 @@ class Comparator { return new Range(this.value, options).test(comp.semver) } - const sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - const sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - const sameSemVer = this.semver.version === comp.semver.version - const differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - const oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<') - const oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>') - - return ( - sameDirectionIncreasing || - sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || - oppositeDirectionsGreaterThan - ) + options = parseOptions(options) + + // Special cases where nothing can possibly be lower + if (options.includePrerelease && + (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) { + return false + } + if (!options.includePrerelease && + (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) { + return false + } + + // Same direction increasing (> or >=) + if (this.operator.startsWith('>') && comp.operator.startsWith('>')) { + return true + } + // Same direction decreasing (< or <=) + if (this.operator.startsWith('<') && comp.operator.startsWith('<')) { + return true + } + // same SemVer and both sides are inclusive (<= or >=) + if ( + (this.semver.version === comp.semver.version) && + this.operator.includes('=') && comp.operator.includes('=')) { + return true + } + // opposite directions less than + if (cmp(this.semver, '<', comp.semver, options) && + this.operator.startsWith('>') && comp.operator.startsWith('<')) { + return true + } + // opposite directions greater than + if (cmp(this.semver, '>', comp.semver, options) && + this.operator.startsWith('<') && comp.operator.startsWith('>')) { + return true + } + return false } } diff --git a/ranges/intersects.js b/ranges/intersects.js index 3d1a6f31..e0e9b7ce 100644 --- a/ranges/intersects.js +++ b/ranges/intersects.js @@ -2,6 +2,6 @@ const Range = require('../classes/range') const intersects = (r1, r2, options) => { r1 = new Range(r1, options) r2 = new Range(r2, options) - return r1.intersects(r2) + return r1.intersects(r2, options) } module.exports = intersects diff --git a/test/classes/comparator.js b/test/classes/comparator.js index 6c2e1215..209a024b 100644 --- a/test/classes/comparator.js +++ b/test/classes/comparator.js @@ -22,17 +22,18 @@ test('tostrings', (t) => { test('intersect comparators', (t) => { t.plan(comparatorIntersection.length) - comparatorIntersection.forEach(([c0, c1, expect]) => t.test(`${c0} ${c1} ${expect}`, t => { - const comp0 = new Comparator(c0) - const comp1 = new Comparator(c1) - - t.equal(comp0.intersects(comp1, false), expect, - `${c0} intersects ${c1}`) - - t.equal(comp1.intersects(comp0, { loose: false }), expect, - `${c1} intersects ${c0}`) - t.end() - })) + comparatorIntersection.forEach(([c0, c1, expect, includePrerelease]) => + t.test(`${c0} ${c1} ${expect}`, t => { + const comp0 = new Comparator(c0) + const comp1 = new Comparator(c1) + + t.equal(comp0.intersects(comp1, { includePrerelease }), expect, + `${c0} intersects ${c1}`) + + t.equal(comp1.intersects(comp0, { includePrerelease }), expect, + `${c1} intersects ${c0}`) + t.end() + })) }) test('intersect demands another comparator', t => { diff --git a/test/fixtures/comparator-intersection.js b/test/fixtures/comparator-intersection.js index 5f24acce..1d777d38 100644 --- a/test/fixtures/comparator-intersection.js +++ b/test/fixtures/comparator-intersection.js @@ -1,4 +1,4 @@ -// c0, c1, expected intersection +// c0, c1, expected intersection, includePrerelease module.exports = [ // One is a Version ['1.3.0', '>=1.3.0', true], @@ -33,4 +33,10 @@ module.exports = [ ['', '', true], ['', '>1.0.0', true], ['<=2.0.0', '', true], + ['<0.0.0', '<0.1.0', false], + ['<0.1.0', '<0.0.0', false], + ['<0.0.0-0', '<0.1.0', false], + ['<0.1.0', '<0.0.0-0', false], + ['<0.0.0-0', '<0.1.0', false, true], + ['<0.1.0', '<0.0.0-0', false, true], ] diff --git a/test/ranges/intersects.js b/test/ranges/intersects.js index e93492b7..b23ad03d 100644 --- a/test/ranges/intersects.js +++ b/test/ranges/intersects.js @@ -7,24 +7,24 @@ const rangeIntersection = require('../fixtures/range-intersection.js') test('intersect comparators', t => { t.plan(comparatorIntersection.length) - comparatorIntersection.forEach(([c0, c1, expect]) => t.test(`${c0} ${c1} ${expect}`, t => { - const comp0 = new Comparator(c0) - const comp1 = new Comparator(c1) + comparatorIntersection.forEach(([c0, c1, expect, includePrerelease]) => + t.test(`${c0} ${c1} ${expect}`, t => { + const opts = { loose: false, includePrerelease } + const comp0 = new Comparator(c0) + const comp1 = new Comparator(c1) - t.equal(intersects(comp0, comp1), expect, `${c0} intersects ${c1} objects`) - t.equal(intersects(comp1, comp0), expect, `${c1} intersects ${c0} objects`) - t.equal(intersects(comp0, comp1, true), expect, - `${c0} intersects ${c1} loose, objects`) - t.equal(intersects(comp1, comp0, true), expect, - `${c1} intersects ${c0} loose, objects`) - t.equal(intersects(c0, c1), expect, `${c0} intersects ${c1}`) - t.equal(intersects(c1, c0), expect, `${c1} intersects ${c0}`) - t.equal(intersects(c0, c1, true), expect, - `${c0} intersects ${c1} loose`) - t.equal(intersects(c1, c0, true), expect, - `${c1} intersects ${c0} loose`) - t.end() - })) + t.equal(intersects(comp0, comp1, opts), expect, `${c0} intersects ${c1} objects`) + t.equal(intersects(comp1, comp0, opts), expect, `${c1} intersects ${c0} objects`) + t.equal(intersects(c0, c1, opts), expect, `${c0} intersects ${c1}`) + t.equal(intersects(c1, c0, opts), expect, `${c1} intersects ${c0}`) + + opts.loose = true + t.equal(intersects(comp0, comp1, opts), expect, `${c0} intersects ${c1} loose, objects`) + t.equal(intersects(comp1, comp0, opts), expect, `${c1} intersects ${c0} loose, objects`) + t.equal(intersects(c0, c1, opts), expect, `${c0} intersects ${c1} loose`) + t.equal(intersects(c1, c0, opts), expect, `${c1} intersects ${c0} loose`) + t.end() + })) }) test('ranges intersect', (t) => {