diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f0b73..16b5753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ ## Upcoming Release #### Breaking changes -- None yet +- Type `phantom` is now `phantomjs`, which is a little more consistent +- The property "name" is more descriptive for variant channels, e.g. "chrome-canary" #### User features - None yet diff --git a/index.js b/index.js index f81d529..44c2916 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ var path = require( 'path' ), - _ = require( 'lodash' ), + pick = require( 'lodash/pick' ), configModule = require( './lib/config' ), detect = require( './lib/detect' ), run = require( './lib/run' ), @@ -75,14 +75,14 @@ function getLauncher( configFile, callback ) { getLauncher.detect = function( callback ) { detect( function( browsers ) { callback( browsers.map( function( browser ) { - return _.pick( browser, [ 'name', 'version', 'type', 'command' ] ); + return pick( browser, [ 'name', 'version', 'type', 'command' ] ); } ) ); } ); }; /** * Update the browsers cache and create new profiles if necessary - * @param {String} configDir Path to the configuration file + * @param {String} configFile Path to the configuration file * @param {Function} callback Callback function */ getLauncher.update = function( configFile, callback ) { diff --git a/lib/darwin/canary.js b/lib/darwin/chrome-canary.js similarity index 100% rename from lib/darwin/canary.js rename to lib/darwin/chrome-canary.js diff --git a/lib/darwin/index.js b/lib/darwin/index.js index c92c4ca..d83a3b7 100644 --- a/lib/darwin/index.js +++ b/lib/darwin/index.js @@ -1,7 +1,7 @@ exports.safari = require( './safari' ); exports.firefox = require( './firefox' ); -exports.chrome = exports[ 'google-chrome' ] = require( './chrome' ); +exports.chrome = require( './chrome' ); exports.chromium = require( './chromium' ); -exports.canary = exports[ 'chrome-canary' ] = exports[ 'google-chrome-canary' ] = require( './canary' ); +exports[ 'chrome-canary' ] = require( './chrome-canary' ); exports.opera = require( './opera' ); exports.phantomjs = require( './phantomjs' ); diff --git a/lib/detect.js b/lib/detect.js index 6fdf258..e32a67d 100644 --- a/lib/detect.js +++ b/lib/detect.js @@ -1,66 +1,48 @@ var spawn = require( 'child_process' ).spawn, winDetect = require( 'win-detect-browsers' ), darwin = require( './darwin' ), - extend = require( 'lodash' ).extend, + assign = require('lodash/assign'), + omit = require('lodash/omit'), browsers = { - 'google-chrome': { - name: 'chrome', - re: /Google Chrome (\S+)/, - type: 'chrome', - profile: true - }, - 'google-chrome-canary': { - name: 'canary', - re: /Google Chrome (\S+)/, - type: 'chrome', - profile: true - }, - 'chromium': { - name: 'chromium', - re: /Chromium (\S+)/, - type: 'chrome', - profile: true + chrome: { + regex: /Google Chrome (\S+)/, + profile: true, + variants: { + 'chrome': ['google-chrome', 'google-chrome-stable'], + 'chrome-beta': ['google-chrome-beta'], + 'chrome-canary': ['google-chrome-canary'] + } }, - 'chromium-browser': { - name: 'chromium', - re: /Chromium (\S+)/, - type: 'chrome', - profile: true + chromium: { + regex: /Chromium (\S+)/, + profile: true, + variants: { + 'chromium': ['chromium', 'chromium-browser'] + } }, - 'firefox': { - name: 'firefox', - re: /Mozilla Firefox (\S+)/, - type: 'firefox', - profile: true + firefox: { + regex: /Mozilla Firefox (\S+)/, + profile: true, + variants: { + 'firefox': ['firefox'], + 'firefox-developer': ['firefox-developer'] + } }, - 'phantomjs': { - name: 'phantomjs', - re: /(\S+)/, - type: 'phantom', - headless: true, - profile: false + phantomjs: { + regex: /(\S+)/, + profile: false, + headless: true }, - 'safari': { - name: 'safari', - type: 'safari', + safari: { profile: false }, - 'ie': { - name: 'ie', - type: 'ie', + ie: { profile: false }, - 'opera': { - name: 'opera', - re: /Opera (\S+)/, - type: 'opera', - image: 'opera.exe', + opera: { + regex: /Opera (\S+)/, profile: true } - }, - winDetectMap = { - chrome: 'google-chrome', - chromium: 'chromium-browser' }; /** @@ -68,20 +50,21 @@ var spawn = require( 'child_process' ).spawn, * Pass an array of detected browsers to the callback function when done. * @param {Function} callback Callback function */ -function detectWindows( callback ) { - winDetect( function( found ) { - var available = found.map( function( browser ) { - var br = browsers[ winDetectMap[ browser.name ] || browser.name ]; +function detectWindows(callback) { + winDetect(function (found) { + var available = found.map(function (browser) { + var br = omit(browsers[browser.name], 'variants'); - return extend( {}, { + return assign({ + type: browser.name, name: browser.name, command: browser.path, version: browser.version - }, br || {} ); - } ); + }, br); + }); - callback( available ); - } ); + callback(available); + }); } /** @@ -90,45 +73,41 @@ function detectWindows( callback ) { * @param {String} name Name of a browser * @param {Function} callback Callback function */ -function checkDarwin( name, callback ) { - if ( darwin[ name ] ) { - if ( darwin[ name ].all ) { - darwin[ name ].all( function( err, available ) { - if ( err ) { - callback( 'failed to get version for ' + name ); - } else { - callback( err, available ); - } - } ); - } else { - darwin[ name ].version( function( err, version ) { - if ( version ) { - darwin[ name ].path( function( err, p ) { - if ( err ) { - return callback( 'failed to get path for ' + name ); - } - - callback( null, version, p ); - } ); - } else { - callback( 'failed to get version for ' + name ); - } - } ); - } - } else { - checkOthers( name, callback ); +function checkDarwin(name, callback) { + if (darwin[name].all) { + darwin[name].all(function (err, available) { + if (err) { + return callback('failed to get version for ' + name); + } + callback(null, available); + }); + return; } + + darwin[name].version(function (err, version) { + if (err) { + return callback('failed to get version for ' + name); + } + + darwin[name].path(function (err, path) { + if (err) { + return callback('failed to get path for ' + name); + } + + callback(null, version, path); + }); + }); } /** * Check if the given browser is available (on Unix systems). * Pass its version to the callback function if found. * @param {String} name Name of a browser + * @param {RegExp} regex Extracts version from command output * @param {Function} callback Callback function */ -function checkOthers( name, callback ) { +function checkOthers( name, regex, callback ) { var process = spawn( name, [ '--version' ] ), - re = browsers[ name ].re, data = ''; process.stdout.on( 'data', function( buf ) { @@ -149,14 +128,35 @@ function checkOthers( name, callback ) { return callback( 'not installed' ); } - var m = re.exec( data ); + var match = regex.exec( data ); + var version = match ? match[1] : data.trim(); + callback(null, version); + } ); +} + +function flattenBrowsers(shouldUseDarwinDetector) { + var flatBrowsers = []; - if ( m ) { - callback( null, m[ 1 ] ); - } else { - callback( null, data.trim() ); + Object.keys(browsers).forEach(function(type) { + var variants = browsers[type].variants; + var config = omit(browsers[type], 'variants'); + + if (!variants) { + return flatBrowsers.push(assign({type: type, name: type, command: type}, config)); } - } ); + + Object.keys(variants).map(function(name) { + if (shouldUseDarwinDetector(name)) { + return flatBrowsers.push(assign({type: type, name: name, command: command}, config)); + } + + return variants[name].map(function(command) { + flatBrowsers.push(assign({type: type, name: name, command: command}, config)); + }); + }); + }); + + return flatBrowsers; } /** @@ -164,50 +164,42 @@ function checkOthers( name, callback ) { * Pass an array of available browsers to the callback function when done. * @param {Function} callback Callback function */ -module.exports = function detect( callback ) { - var available = [], - names, - check; - - if ( process.platform === 'win32' ) { - return detectWindows( callback ); - } else if ( process.platform === 'darwin' ) { - check = checkDarwin; - } else { - check = checkOthers; +module.exports = function detect(callback) { + if (process.platform === 'win32') { + return detectWindows(callback); } - names = Object.keys( browsers ); - - function next() { - var name = names.shift(); - - if ( !name ) { - return callback( available ); - } + function shouldUseDarwinDetector(browserName) { + return process.platform === 'darwin' && darwin[browserName]; + } - var br = browsers[ name ]; - - check( name, function( err, v, p ) { - if ( err === null ) { - if ( Array.isArray( v ) ) { - v.forEach( function( item ) { - available.push( extend( {}, br, { - command: item.path, - version: item.version - } ) ); - } ); - } else { - available.push( extend( {}, br, { - command: p || name, - version: v - } ) ); + var available = [], + detectAttempts = 0, + flattened = flattenBrowsers(shouldUseDarwinDetector); + flattened.forEach(function(flatBrowser) { + function cb(err, version, path) { + detectAttempts++; + if (!err) { + if (!Array.isArray(version)) { + version = [{path: path, version: version}]; } + + version.forEach(function(item) { + available.push(assign({}, flatBrowser, { + command: item.path || flatBrowser.command, + version: item.version + })); + }); } - next(); - } ); - } + if (detectAttempts === flattened.length) { + callback(available); + } + } - next(); + if (shouldUseDarwinDetector(flatBrowser.name)) { + return checkDarwin(flatBrowser.name, cb); + } + checkOthers(flatBrowser.command, flatBrowser.regex, cb); + }); };