Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Revamp getBrowserAndVersion to handle Safari iOS and Samsung Internet #565

Merged
merged 1 commit into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions unittest/unit/update-bcd.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const sinon = require('sinon');
const logger = require('../../logger');
const {
findEntry,
getMajorMinorVersion,
getBrowserAndVersion,
getSupportMap,
getSupportMatrix,
Expand Down Expand Up @@ -96,9 +97,9 @@ const bcd = {
chrome: {releases: {82: {}, 83: {}, 84: {}, 85: {}}},
chrome_android: {releases: {85: {}}},
edge: {releases: {16: {}, 84: {}}},
safari: {releases: {14: {}}},
safari_ios: {releases: {13.4: {}, 14: {}}},
samsunginternet_android: {releases: {'12.0': {}, 12.1: {}}}
safari: {releases: {13: {}, 13.1: {}, 14: {}}},
safari_ios: {releases: {13: {}, 13.3: {}, 13.4: {}, 14: {}}},
samsunginternet_android: {releases: {'10.0': {}, 10.2: {}, '11.0': {}, 11.2: {}, '12.0': {}, 12.1: {}}}
},
css: {
properties: {
Expand Down Expand Up @@ -368,11 +369,41 @@ describe('BCD updater', () => {
});
});

describe('getMajorMinorVersion', () => {
it('1.2.3', () => {
assert.strictEqual(getMajorMinorVersion('1.2.3'), '1.2');
});

it('10', () => {
assert.strictEqual(getMajorMinorVersion('10'), '10.0');
});

it('10.0', () => {
assert.strictEqual(getMajorMinorVersion('10.0'), '10.0');
});

it('10.01', () => {
assert.strictEqual(getMajorMinorVersion('10.01'), '10.01');
});

it('10.1', () => {
assert.strictEqual(getMajorMinorVersion('10.1'), '10.1');
});

it('58.0.3029.110', () => {
assert.strictEqual(getMajorMinorVersion('58.0.3029.110'), '58.0');
});
});

describe('getBrowserAndVersion', () => {
it('Chrome', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36', bcd.browsers), ['chrome', '85']);
});

it('Chrome 100 (not in BCD)', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4183.121 Safari/537.36', bcd.browsers), ['chrome', null]);
});

it('Chrome Android', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Linux; Android 11; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36', bcd.browsers), ['chrome_android', '85']);
});
Expand All @@ -385,16 +416,20 @@ describe('BCD updater', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59', bcd.browsers), ['edge', '84']);
});

it('Safari', () => {
it('Safari 14', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15', bcd.browsers), ['safari', '14']);
});

it('Safari 14.1 (not in BCD)', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15', bcd.browsers), ['safari', null]);
});

it('Safari iOS', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1', bcd.browsers), ['safari_ios', '']);
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1', bcd.browsers), ['safari_ios', '13.4']);
});

it('Samsung Internet (10.1)', () => {
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/10.1 Chrome/71.0.3578.99 Mobile Safari/537.36', bcd.browsers), ['samsunginternet_android', '']);
assert.deepEqual(getBrowserAndVersion('Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/10.1 Chrome/71.0.3578.99 Mobile Safari/537.36', bcd.browsers), ['samsunginternet_android', '10.0']);
});

it('Samsung Internet (12.0)', () => {
Expand Down Expand Up @@ -715,9 +750,9 @@ describe('BCD updater', () => {
chrome: {releases: {82: {}, 83: {}, 84: {}, 85: {}}},
chrome_android: {releases: {85: {}}},
edge: {releases: {16: {}, 84: {}}},
safari: {releases: {14: {}}},
safari_ios: {releases: {13.4: {}, 14: {}}},
samsunginternet_android: {releases: {'12.0': {}, 12.1: {}}}
safari: {releases: {13: {}, 13.1: {}, 14: {}}},
safari_ios: {releases: {13: {}, 13.3: {}, 13.4: {}, 14: {}}},
samsunginternet_android: {releases: {'10.0': {}, 10.2: {}, '11.0': {}, 11.2: {}, '12.0': {}, 12.1: {}}}
},
css: {
properties: {
Expand Down
43 changes: 35 additions & 8 deletions update-bcd.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ const findEntry = (bcd, path) => {
return entry;
};

const getMajorMinorVersion = (version) => {
const [major, minor] = version.split('.');
return `${major}.${minor || 0}`;
};

const getBrowserAndVersion = (userAgent, browsers) => {
const ua = uaParser(userAgent);

Expand All @@ -40,16 +45,37 @@ const getBrowserAndVersion = (userAgent, browsers) => {
return [null, null];
}

// Trim last component of the version until there's a match, if any.
// TODO: Doesn't work for Samsung Internet or Safari iOS versions
let version = ua.browser.version;
const parts = version.split('.');
while (parts.length && !(version in browsers[browser].releases)) {
parts.pop();
version = parts.join('.');
// https://github.com/mdn/browser-compat-data/blob/master/docs/data-guidelines.md#safari-for-ios-versioning
const version = browser === 'safari_ios' ?
ua.os.version : ua.browser.version;

const versions = Object.keys(browsers[browser].releases);
versions.sort(compareVersions);

// The |version| from the UA string is typically more precise than |versions|
// from BCD, and some "uninteresting" releases are missing from BCD. To deal
// with this, find the pair of versions in |versions| that sandwiches
// |version|, and use the first of this pair. For example, given |version|
// "10.1" and |versions| entries "10.0" and "10.2", return "10.0".
for (let i = 0; i < versions.length; i++) {
const current = versions[i];
const next = versions[i + 1];
if (next) {
if (compareVersions.compare(version, current, '>=') &&
compareVersions.compare(version, next, '<')) {
return [browser, current];
}
} else {
// This is the last entry in |versions|. With no |next| to compare against
// we have to match the version more conservatively, requiring major and
// minor versions to match. "10.0" and "10" are seen as equivalent.
if (getMajorMinorVersion(version) === getMajorMinorVersion(current)) {
return [browser, current];
}
}
}

return [browser, version];
return [browser, null];
};

// Get support map from BCD path to test result(null/true/false) for a single
Expand Down Expand Up @@ -377,6 +403,7 @@ if (require.main === module) {
} else {
module.exports = {
findEntry,
getMajorMinorVersion,
getBrowserAndVersion,
getSupportMap,
getSupportMatrix,
Expand Down