From d032d595841c5bde8dbec0e1be35eef8d7623292 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 12 Apr 2021 02:00:19 +0100 Subject: [PATCH] Fix crash from property 'browser_version' undefined When no match is found, the process would just crash. Instead, recognise this as a normal end-user scenario and point them to the list of available workers. In my experience the most common way to encounter this issue is when additional decimal places are required by the API, e.g. "safari" "9" results in a crash, because the available workers are described as "9.1" instead. Given that most browers are described without a decimal place, this is an easy mistake to make. Another way to get this is when there is a misspelled browser name. Before: ``` TypeError: Cannot read property 'browser_version' of undefined at browserstack-runner/bin/cli.js ``` After: ``` Error: No desktop match found for {"browser":"safari","browser_version":"9"} Check https://www.browserstack.com/list-of-browsers-and-platforms/js_testing at populateOsAndOsVersion (browserstack-runner/lib/configParser.js) ``` Fixes https://github.com/browserstack/browserstack-runner/issues/243. --- lib/configParser.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/configParser.js b/lib/configParser.js index 7e440f7..b88995c 100644 --- a/lib/configParser.js +++ b/lib/configParser.js @@ -3,6 +3,8 @@ var Log = require('./logger'), logger = new Log(global.logLevel || 'info'); +var BROWSER_LIST_URL = 'https://www.browserstack.com/list-of-browsers-and-platforms/js_testing'; + var ConfigParser = { finalBrowsers: [], @@ -54,10 +56,12 @@ var ConfigParser = { var mobileFiltered = ConfigParser.bsBrowsers.filter(function(currentValue) { return currentValue.browser.toLowerCase() === browserObject.browser && parseFloat(currentValue.os_version).toPrecision(4) === parseFloat(browserObject.os_version).toPrecision(4); }); + if (!mobileFiltered.length) { + throw new Error('No mobile match found for ' + JSON.stringify(browserObject) + '\nCheck ' + BROWSER_LIST_URL); + } browserObject = mobileFiltered[Math.floor(Math.random() * mobileFiltered.length)]; - } - else { + } else { var windowsFiltered = ConfigParser.bsBrowsers.filter(function(currentValue) { return currentValue.os === 'Windows' && currentValue.browser_version.match(/metro/i) == null && currentValue.browser === browserObject.browser && ((browserObject.browser_version && browserObject.browser_version.indexOf('latest') > -1) || parseFloat(currentValue.browser_version).toPrecision(4) === parseFloat(browserObject.browser_version).toPrecision(4)); @@ -66,8 +70,13 @@ var ConfigParser = { var osxFiltered = ConfigParser.bsBrowsers.filter(function(currentValue) { return currentValue.os === 'OS X' && currentValue.browser === browserObject.browser && ((browserObject.browser_version && browserObject.browser_version.indexOf('latest')) > -1 || parseFloat(currentValue.browser_version).toPrecision(4) === parseFloat(browserObject.browser_version).toPrecision(4)); }); + // Use Windows VMs if no OS specified + var desktopFiltered = windowsFiltered.length > 0 ? windowsFiltered : osxFiltered; - let filteredObject = windowsFiltered.length > 0 ? windowsFiltered[Math.floor(Math.random() * windowsFiltered.length)] : osxFiltered[Math.floor(Math.random() * osxFiltered.length)]; + if (!desktopFiltered.length) { + throw new Error('No desktop match found for ' + JSON.stringify(browserObject) + '\nCheck ' + BROWSER_LIST_URL); + } + var filteredObject = desktopFiltered[Math.floor(Math.random() * desktopFiltered.length)]; if (browserObject.browser_version.indexOf('latest') > -1) { filteredObject.browser_version = browserObject.browser_version; } @@ -82,15 +91,14 @@ var ConfigParser = { var browserObject = {}; var version = null; var sliceStart = 1; - if (typeof(entry) === 'string') { + if (typeof entry === 'string') { var browserData = entry.split('_'); var lindex = browserData.length - 1; if (browserData[0] === 'mobile' || browserData[0] === 'android' || (browserData[0] === 'opera' && browserData[1] === 'browser')) { browserObject.browser = browserData[0] + ' ' + browserData[1]; browserObject.mobile = true; sliceStart = 2; - } - else { + } else { browserObject.browser = browserData[0]; } if (browserData[lindex] && browserData[lindex].indexOf('+') === -1) { @@ -100,15 +108,13 @@ var ConfigParser = { else { version = browserData.slice(sliceStart, lindex + 1).join('.'); } - } - else { + } else { version = browserData.slice(sliceStart, lindex + 1).join('.'); } if (browserObject.mobile) { browserObject.os_version = version; browserObject.browser_version = null; - } - else { + } else { browserObject.browser_version = version; } } else {