1
0
mirror of https://github.com/lancedikson/bowser synced 2024-10-27 20:34:22 +00:00

Merge pull request #241 from udivankin/develop

Adds loose comparison support
This commit is contained in:
Denis Demchenko 2018-08-18 13:59:52 +03:00 committed by GitHub
commit 6434c76184
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 15 deletions

View File

@ -111,6 +111,13 @@ const isValidBrowser = browser.satisfies({
chrome: ">20.1.1432", chrome: ">20.1.1432",
firefox: ">31", firefox: ">31",
opera: ">22" opera: ">22"
// also supports equality operator
chrome: "=20.1.1432", // will match particular build only
// and loose-equality operator
chrome: "~20" // will match any 20.* sub-version
chrome: "~20.1" // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
}); });
``` ```

View File

@ -397,6 +397,7 @@ class Parser {
compareVersion(version) { compareVersion(version) {
let expectedResult = 0; let expectedResult = 0;
let comparableVersion = version; let comparableVersion = version;
let isLoose = false;
if (version[0] === '>') { if (version[0] === '>') {
expectedResult = 1; expectedResult = 1;
@ -406,8 +407,12 @@ class Parser {
comparableVersion = version.substr(1); comparableVersion = version.substr(1);
} else if (version[0] === '=') { } else if (version[0] === '=') {
comparableVersion = version.substr(1); comparableVersion = version.substr(1);
} else if (version[0] === '~') {
isLoose = true;
comparableVersion = version.substr(1);
} }
return compareVersions(this.getBrowserVersion(), comparableVersion) === expectedResult;
return compareVersions(this.getBrowserVersion(), comparableVersion, isLoose) === expectedResult;
} }
isOS(osName) { isOS(osName) {

View File

@ -68,23 +68,26 @@ class Utils {
* Calculate browser version weight * Calculate browser version weight
* *
* @example * @example
* compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1 * compareVersions('1.10.2.1', '1.8.2.1.90') // 1
* compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1 * compareVersions('1.010.2.1', '1.09.2.1.90'); // 1
* compareVersions(['1.10.2.1', '1.10.2.1']); // 0 * compareVersions('1.10.2.1', '1.10.2.1'); // 0
* compareVersions(['1.10.2.1', '1.0800.2']); // -1 * compareVersions('1.10.2.1', '1.0800.2'); // -1
* compareVersions('1.10.2.1', '1.10', true); // 0
* *
* @param {String} versionA versions versions to compare * @param {String} versionA versions versions to compare
* @param {String} versionB versions versions to compare * @param {String} versionB versions versions to compare
* @param {boolean} [isLoose] enable loose comparison
* @return {Number} comparison result: -1 when versionA is lower, * @return {Number} comparison result: -1 when versionA is lower,
* 1 when versionA is bigger, 0 when both equal * 1 when versionA is bigger, 0 when both equal
*/ */
/* eslint consistent-return: 1 */ /* eslint consistent-return: 1 */
static compareVersions(versionA, versionB) { static compareVersions(versionA, versionB, isLoose = false) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2 // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
let precision = Math.max( const versionAPrecision = Utils.getVersionPrecision(versionA);
Utils.getVersionPrecision(versionA), const versionBPrecision = Utils.getVersionPrecision(versionB);
Utils.getVersionPrecision(versionB),
); let precision = Math.max(versionAPrecision, versionBPrecision);
let lastPrecision = 0;
const chunks = Utils.map([versionA, versionB], (version) => { const chunks = Utils.map([versionA, versionB], (version) => {
const delta = precision - Utils.getVersionPrecision(version); const delta = precision - Utils.getVersionPrecision(version);
@ -96,14 +99,19 @@ class Utils {
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse(); return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
}); });
// adjust precision for loose comparison
if (isLoose) {
lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
}
// iterate in reverse order by reversed chunks array // iterate in reverse order by reversed chunks array
precision -= 1; precision -= 1;
while (precision >= 0) { while (precision >= lastPrecision) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true) // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) { if (chunks[0][precision] > chunks[1][precision]) {
return 1; return 1;
} else if (chunks[0][precision] === chunks[1][precision]) { } else if (chunks[0][precision] === chunks[1][precision]) {
if (precision === 0) { if (precision === lastPrecision) {
// all version chunks are same // all version chunks are same
return 0; return 0;
} }

View File

@ -57,8 +57,13 @@ test('Skip parsing shouldn\'t parse', (t) => {
t.deepEqual((new Parser(UA, true)).getResult(), {}); t.deepEqual((new Parser(UA, true)).getResult(), {});
}); });
test('Parser.check should make simple comparison', (t) => { test('Parser.check should make simple comparisons', (t) => {
// also covers Parser.compareVersion() method
t.is(parser.satisfies({ opera: '>42' }), true); t.is(parser.satisfies({ opera: '>42' }), true);
t.is(parser.satisfies({ opera: '<44' }), true);
t.is(parser.satisfies({ opera: '=43.0.2442.1165' }), true);
t.is(parser.satisfies({ opera: '~43.0' }), true);
t.is(parser.satisfies({ opera: '~43' }), true);
}); });
test('Parser.check should make complex comparison', (t) => { test('Parser.check should make complex comparison', (t) => {

View File

@ -22,6 +22,9 @@ test('compareVersions', (t) => {
['1.10.2.1', '1.8.2.1.90', 1], ['1.10.2.1', '1.8.2.1.90', 1],
['1.010.2.1', '1.08.2.1.90', 1], ['1.010.2.1', '1.08.2.1.90', 1],
['1.10.2.1', '1.10.2.1', 0], ['1.10.2.1', '1.10.2.1', 0],
['1.10.2.1', '1.10.2', 0, true],
['1.10.2.1', '1.10', 0, true],
['1.10.2.1', '1', 0, true],
['1.10.2.1', '1.0800.2', -1], ['1.10.2.1', '1.0800.2', -1],
['1.0.0-alpha', '1.0.0-alpha.1', -1], ['1.0.0-alpha', '1.0.0-alpha.1', -1],
['1.0.0-alpha.1', '1.0.0-alpha.beta', -1], ['1.0.0-alpha.1', '1.0.0-alpha.beta', -1],
@ -35,7 +38,8 @@ test('compareVersions', (t) => {
const versionA = testingParams[0]; const versionA = testingParams[0];
const versionB = testingParams[1]; const versionB = testingParams[1];
const result = testingParams[2]; const result = testingParams[2];
let matching = ' == '; const isLoose = testingParams.length > 3 ? testingParams[3] : false;
let matching = isLoose ? '~' : ' == ';
if (result > 0) { if (result > 0) {
matching = ' > '; matching = ' > ';
@ -43,6 +47,6 @@ test('compareVersions', (t) => {
matching = ' < '; matching = ' < ';
} }
t.is(compareVersions(versionA, versionB), result, `version ${versionA} should be ${matching} version ${versionB}`); t.is(compareVersions(versionA, versionB, isLoose), result, `version ${versionA} should be ${matching} version ${versionB}`);
}); });
}); });