webdriver-manager
Advanced tools
Comparing version 10.2.10 to 10.3.0
{ | ||
"webdriverVersions": { | ||
"selenium": "2.53.1", | ||
"chromedriver": "2.25", | ||
"chromedriver": "2.26", | ||
"geckodriver": "v0.11.1", | ||
@@ -6,0 +6,0 @@ "iedriver": "2.53.1", |
@@ -14,2 +14,5 @@ import { Binary, OS } from './binary'; | ||
static DEFAULT_PLATFORMS: string; | ||
static VERSIONS: { | ||
[api_level: number]: string; | ||
}; | ||
constructor(alternateCDN?: string); | ||
@@ -16,0 +19,0 @@ id(): string; |
@@ -12,2 +12,22 @@ "use strict"; | ||
var binary_1 = require("./binary"); | ||
function getAndroidArch() { | ||
switch (config_1.Config.osArch()) { | ||
case 'arm': | ||
return 'armeabi-v7a'; | ||
case 'arm64': | ||
return 'arm64-v8a'; | ||
case 'x86': | ||
case 'x32': | ||
case 'ia32': | ||
case 'ppc': | ||
return 'x86'; | ||
case 'x86-64': | ||
case 'x64': | ||
case 'ia64': | ||
case 'ppc64': | ||
return 'x86_64'; | ||
default: | ||
return config_1.Config.osArch(); | ||
} | ||
} | ||
/** | ||
@@ -62,6 +82,6 @@ * The android sdk binary. | ||
try { | ||
var avds = require(path.join(sdkPath, 'available_avds.json')); | ||
var avds = require(path.resolve(sdkPath, 'available_avds.json')); | ||
var version_1 = path.basename(sdkPath).slice(this.prefixDefault.length); | ||
avds.forEach(function (avd) { | ||
utils_1.spawnSync(path.join(sdkPath, 'tools', 'android'), ['delete', 'avd', '-n', avd + '-v' + version_1 + '-wd-manager']); | ||
utils_1.spawnSync(path.resolve(sdkPath, 'tools', 'android'), ['delete', 'avd', '-n', avd + '-v' + version_1 + '-wd-manager']); | ||
}); | ||
@@ -75,3 +95,2 @@ } | ||
}(binary_1.Binary)); | ||
exports.AndroidSDK = AndroidSDK; | ||
AndroidSDK.os = [binary_1.OS.Windows_NT, binary_1.OS.Linux, binary_1.OS.Darwin]; | ||
@@ -83,4 +102,10 @@ AndroidSDK.id = 'android'; | ||
AndroidSDK.DEFAULT_API_LEVELS = '24'; | ||
AndroidSDK.DEFAULT_ARCHITECTURES = 'x86_64'; | ||
AndroidSDK.DEFAULT_ARCHITECTURES = getAndroidArch(); | ||
AndroidSDK.DEFAULT_PLATFORMS = 'google_apis'; | ||
AndroidSDK.VERSIONS = { | ||
// Before 24 is not supported | ||
24: '7.0', | ||
25: '7.1' | ||
}; | ||
exports.AndroidSDK = AndroidSDK; | ||
//# sourceMappingURL=android_sdk.js.map |
@@ -37,3 +37,2 @@ "use strict"; | ||
}(binary_1.Binary)); | ||
exports.Appium = Appium; | ||
Appium.os = [binary_1.OS.Windows_NT, binary_1.OS.Linux, binary_1.OS.Darwin]; | ||
@@ -44,2 +43,3 @@ Appium.id = 'appium'; | ||
Appium.shortName = ['appium']; | ||
exports.Appium = Appium; | ||
//# sourceMappingURL=appium.js.map |
@@ -6,2 +6,3 @@ "use strict"; | ||
*/ | ||
var OS; | ||
(function (OS) { | ||
@@ -11,4 +12,3 @@ OS[OS["Windows_NT"] = 0] = "Windows_NT"; | ||
OS[OS["Darwin"] = 2] = "Darwin"; | ||
})(exports.OS || (exports.OS = {})); | ||
var OS = exports.OS; | ||
})(OS = exports.OS || (exports.OS = {})); | ||
/** | ||
@@ -15,0 +15,0 @@ * The binary object base class |
@@ -64,3 +64,2 @@ "use strict"; | ||
}(binary_1.Binary)); | ||
exports.ChromeDriver = ChromeDriver; | ||
ChromeDriver.os = [binary_1.OS.Windows_NT, binary_1.OS.Linux, binary_1.OS.Darwin]; | ||
@@ -71,2 +70,3 @@ ChromeDriver.id = 'chrome'; | ||
ChromeDriver.shortName = ['chrome']; | ||
exports.ChromeDriver = ChromeDriver; | ||
//# sourceMappingURL=chrome_driver.js.map |
@@ -57,3 +57,2 @@ "use strict"; | ||
}(binary_1.Binary)); | ||
exports.GeckoDriver = GeckoDriver; | ||
GeckoDriver.os = [binary_1.OS.Windows_NT, binary_1.OS.Linux, binary_1.OS.Darwin]; | ||
@@ -72,2 +71,3 @@ GeckoDriver.id = 'gecko'; | ||
}; | ||
exports.GeckoDriver = GeckoDriver; | ||
//# sourceMappingURL=gecko_driver.js.map |
@@ -7,3 +7,2 @@ "use strict"; | ||
}; | ||
var os = require("os"); | ||
var config_1 = require("../config"); | ||
@@ -22,3 +21,3 @@ var binary_1 = require("./binary"); | ||
_this.suffixDefault = '.zip'; | ||
_this.arch = os.arch(); | ||
_this.arch = config_1.Config.osArch(); | ||
return _this; | ||
@@ -33,3 +32,3 @@ } | ||
IEDriver.prototype.version = function () { | ||
if (os.type() == 'Windows_NT') { | ||
if (config_1.Config.osType() == 'Windows_NT') { | ||
if (this.arch == 'x64') { | ||
@@ -51,3 +50,2 @@ return '_x64_' + this.versionCustom; | ||
}(binary_1.Binary)); | ||
exports.IEDriver = IEDriver; | ||
IEDriver.os = [binary_1.OS.Windows_NT]; | ||
@@ -58,2 +56,3 @@ IEDriver.id = 'ie'; | ||
IEDriver.shortName = ['ie', 'ie32']; | ||
exports.IEDriver = IEDriver; | ||
//# sourceMappingURL=ie_driver.js.map |
@@ -38,3 +38,2 @@ "use strict"; | ||
}(binary_1.Binary)); | ||
exports.StandAlone = StandAlone; | ||
StandAlone.os = [binary_1.OS.Windows_NT, binary_1.OS.Linux, binary_1.OS.Darwin]; | ||
@@ -45,2 +44,3 @@ StandAlone.id = 'standalone'; | ||
StandAlone.shortName = ['standalone']; | ||
exports.StandAlone = StandAlone; | ||
//# sourceMappingURL=stand_alone.js.map |
@@ -20,2 +20,3 @@ "use strict"; | ||
} | ||
var LogLevel; | ||
(function (LogLevel) { | ||
@@ -26,4 +27,4 @@ LogLevel[LogLevel["ERROR"] = 0] = "ERROR"; | ||
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG"; | ||
})(exports.LogLevel || (exports.LogLevel = {})); | ||
var LogLevel = exports.LogLevel; | ||
})(LogLevel = exports.LogLevel || (exports.LogLevel = {})); | ||
var WriteTo; | ||
(function (WriteTo) { | ||
@@ -34,4 +35,3 @@ WriteTo[WriteTo["CONSOLE"] = 0] = "CONSOLE"; | ||
WriteTo[WriteTo["NONE"] = 3] = "NONE"; | ||
})(exports.WriteTo || (exports.WriteTo = {})); | ||
var WriteTo = exports.WriteTo; | ||
})(WriteTo = exports.WriteTo || (exports.WriteTo = {})); | ||
var logFile = 'webdriver.log'; // the default log file name | ||
@@ -72,3 +72,3 @@ /** | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
msgs[_i - 0] = arguments[_i]; | ||
msgs[_i] = arguments[_i]; | ||
} | ||
@@ -84,3 +84,3 @@ this.log_(LogLevel.INFO, msgs); | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
msgs[_i - 0] = arguments[_i]; | ||
msgs[_i] = arguments[_i]; | ||
} | ||
@@ -96,3 +96,3 @@ this.log_(LogLevel.DEBUG, msgs); | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
msgs[_i - 0] = arguments[_i]; | ||
msgs[_i] = arguments[_i]; | ||
} | ||
@@ -108,3 +108,3 @@ this.log_(LogLevel.WARN, msgs); | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
msgs[_i - 0] = arguments[_i]; | ||
msgs[_i] = arguments[_i]; | ||
} | ||
@@ -281,3 +281,2 @@ this.log_(LogLevel.ERROR, msgs); | ||
}()); | ||
exports.Logger = Logger; | ||
Logger.logLevel = LogLevel.INFO; | ||
@@ -288,2 +287,3 @@ Logger.showTimestamp = true; | ||
Logger.firstWrite = false; | ||
exports.Logger = Logger; | ||
//# sourceMappingURL=logger.js.map |
@@ -224,4 +224,4 @@ "use strict"; | ||
}()); | ||
Program.MIN_SPACING = 4; | ||
exports.Program = Program; | ||
Program.MIN_SPACING = 4; | ||
//# sourceMappingURL=programs.js.map |
import { Logger } from '../cli'; | ||
export declare function android(sdkPath: string, apiLevels: string[], architectures: string[], platforms: string[], acceptLicenses: boolean, version: string, oldAVDs: string[], logger: Logger): void; | ||
export declare function android(sdkPath: string, apiLevels: string[], architectures: string[], platforms: string[], acceptLicenses: boolean, version: string, oldAVDs: string[], logger: Logger, verbose: boolean): void; | ||
export declare function iOS(logger: Logger): void; |
@@ -6,5 +6,5 @@ "use strict"; | ||
var ini = require("ini"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
var q = require("q"); | ||
var config_1 = require("../config"); | ||
var utils_1 = require("../utils"); | ||
@@ -14,3 +14,3 @@ var noop = function () { }; | ||
// to a certain question | ||
function respondFactory(question, answer) { | ||
function respondFactory(question, answer, verbose) { | ||
return function (child) { | ||
@@ -20,2 +20,5 @@ child.stdin.setDefaultEncoding('utf-8'); | ||
if (data != null) { | ||
if (verbose) { | ||
process.stdout.write(data); | ||
} | ||
if (data.toString().indexOf(question) != -1) { | ||
@@ -30,3 +33,3 @@ child.stdin.write(answer + '\n'); | ||
function runAndroidSDKCommand(sdkPath, cmd, args, stdio, config_fun) { | ||
var child = utils_1.spawn(path.join(sdkPath, 'tools', 'android'), [cmd].concat(args), stdio); | ||
var child = utils_1.spawn(path.resolve(sdkPath, 'tools', 'android'), [cmd].concat(args), stdio); | ||
if (config_fun) { | ||
@@ -57,20 +60,18 @@ config_fun(child); | ||
// Download updates via the android SDK | ||
function downloadAndroidUpdates(sdkPath, targets, search_all, auto_accept) { | ||
return runAndroidSDKCommand(sdkPath, 'update', ['sdk', '-u'].concat(search_all ? ['-a'] : []).concat(['-t', targets.join(',')]), auto_accept ? 'pipe' : 'inherit', auto_accept ? respondFactory('Do you accept the license', 'y') : noop); | ||
function downloadAndroidUpdates(sdkPath, targets, search_all, auto_accept, verbose) { | ||
return runAndroidSDKCommand(sdkPath, 'update', ['sdk', '-u'].concat(search_all ? ['-a'] : []).concat(['-t', targets.join(',')]), auto_accept ? 'pipe' : 'inherit', auto_accept ? respondFactory('Do you accept the license', 'y', verbose) : noop); | ||
} | ||
// Setup hardware acceleration for x86-64 emulation | ||
function setupHardwareAcceleration(sdkPath) { | ||
// TODO(sjelin): check that the BIOS option is set properly on linux | ||
if (os.type() == 'Darwin') { | ||
// TODO(sjelin): linux setup | ||
var toolDir = path.resolve(sdkPath, 'extras', 'intel', 'Hardware_Accelerated_Execution_Manager'); | ||
if (config_1.Config.osType() == 'Darwin') { | ||
console.log('Enabling hardware acceleration (requires root access)'); | ||
// We don't need the wrapped spawnSync because we know we're on OSX | ||
child_process_1.spawnSync('sudo', [path.join(sdkPath, 'extras', 'intel', 'Hardware_Accelerated_Execution_Manager', 'silent_install.sh')], { stdio: 'inherit' }); | ||
child_process_1.spawnSync('sudo', ['silent_install.sh'], { stdio: 'inherit', cwd: toolDir }); | ||
} | ||
else if (os.type() == 'Windows_NT') { | ||
else if (config_1.Config.osType() == 'Windows_NT') { | ||
console.log('Enabling hardware acceleration (requires admin access)'); | ||
// We don't need the wrapped spawnSync because we know we're on Windows | ||
child_process_1.spawnSync('cmd', [ | ||
'/c', 'runas', '/noprofile', '/user:Administrator', | ||
path.join(sdkPath, 'extras', 'intel', 'Hardware_Accelerated_Execution_Manager', 'silent_install.bat') | ||
], { stdio: 'inherit' }); | ||
// We don't need the wrapped spawnSync because we know we're on windows | ||
child_process_1.spawnSync('silent_install.bat', [], { stdio: 'inherit', cwd: toolDir }); | ||
} | ||
@@ -142,3 +143,4 @@ } | ||
var deferred = q.defer(); | ||
glob(path.join(sdkPath, 'system-images', '*', '*', '*'), function (err, files) { | ||
// `glob` package always prefers patterns to use `/` | ||
glob('system-images/*/*/*', { cwd: sdkPath }, function (err, files) { | ||
if (err) { | ||
@@ -149,3 +151,4 @@ deferred.reject(err); | ||
deferred.resolve(files.map(function (file) { | ||
var info = file.split(path.sep).slice(-3); | ||
// `file` could use `/` or `\`, so we use `path.normalize` | ||
var info = path.normalize(file).split(path.sep).slice(-3); | ||
return new AVDDescriptor(info[0], info[1], info[2]); | ||
@@ -168,3 +171,3 @@ })); | ||
function configureAVDHardware(sdkPath, desc) { | ||
var file = path.join(sdkPath, 'system-images', desc.api, desc.platform, desc.architecture, 'hardware.ini'); | ||
var file = path.resolve(sdkPath, 'system-images', desc.api, desc.platform, desc.architecture, 'hardware.ini'); | ||
return q.nfcall(fs.stat, file) | ||
@@ -185,18 +188,18 @@ .then(function (stats) { | ||
// Make an android virtual device | ||
function makeAVD(sdkPath, desc, version) { | ||
function makeAVD(sdkPath, desc, version, verbose) { | ||
return runAndroidSDKCommand(sdkPath, 'delete', ['avd', '--name', desc.avdName(version)]) | ||
.then(noop, noop) | ||
.then(function () { | ||
return runAndroidSDKCommand(sdkPath, 'create', ['avd', '--name', desc.avdName(version), '--target', desc.api, '--abi', desc.abi], 'pipe', respondFactory('Do you wish to create a custom hardware profile', 'no')); | ||
return runAndroidSDKCommand(sdkPath, 'create', ['avd', '--name', desc.avdName(version), '--target', desc.api, '--abi', desc.abi], 'pipe', respondFactory('Do you wish to create a custom hardware profile', 'no', verbose)); | ||
}); | ||
} | ||
// Initialize the android SDK | ||
function android(sdkPath, apiLevels, architectures, platforms, acceptLicenses, version, oldAVDs, logger) { | ||
function android(sdkPath, apiLevels, architectures, platforms, acceptLicenses, version, oldAVDs, logger, verbose) { | ||
var avdDescriptors; | ||
var tools = ['platform-tool', 'tool']; | ||
if ((os.type() == 'Darwin') || (os.type() == 'Windows_NT')) { | ||
if ((config_1.Config.osType() == 'Darwin') || (config_1.Config.osType() == 'Windows_NT')) { | ||
tools.push('extra-intel-Hardware_Accelerated_Execution_Manager'); | ||
} | ||
logger.info('android-sdk: Downloading additional SDK updates'); | ||
downloadAndroidUpdates(sdkPath, tools, false, acceptLicenses) | ||
downloadAndroidUpdates(sdkPath, tools, false, acceptLicenses, verbose) | ||
.then(function () { | ||
@@ -208,3 +211,3 @@ return setupHardwareAcceleration(sdkPath); | ||
'(this may take a while)'); | ||
return downloadAndroidUpdates(sdkPath, ['build-tools-24.0.0'].concat(getAndroidSDKTargets(apiLevels, architectures, platforms, oldAVDs)), true, acceptLicenses); | ||
return downloadAndroidUpdates(sdkPath, ['build-tools-24.0.0'].concat(getAndroidSDKTargets(apiLevels, architectures, platforms, oldAVDs)), true, acceptLicenses, verbose); | ||
}) | ||
@@ -224,7 +227,7 @@ .then(function () { | ||
logger.info('android-sdk: Setting up virtual device "' + descriptor.name + '"'); | ||
return makeAVD(sdkPath, descriptor, version); | ||
return makeAVD(sdkPath, descriptor, version, verbose); | ||
}); | ||
}) | ||
.then(function () { | ||
return q.nfcall(fs.writeFile, path.join(sdkPath, 'available_avds.json'), JSON.stringify(avdDescriptors.map(function (descriptor) { | ||
return q.nfcall(fs.writeFile, path.resolve(sdkPath, 'available_avds.json'), JSON.stringify(avdDescriptors.map(function (descriptor) { | ||
return descriptor.name; | ||
@@ -241,3 +244,3 @@ }))); | ||
function iOS(logger) { | ||
if (os.type() != 'Darwin') { | ||
if (config_1.Config.osType() != 'Darwin') { | ||
throw new Error('Must be on a Mac to simulate iOS devices.'); | ||
@@ -244,0 +247,0 @@ } |
@@ -26,3 +26,3 @@ import { Options } from '../cli'; | ||
export declare const ANDROID_API_LEVELS = "android-api-levels"; | ||
export declare const ANDROID_ARCHITECTURES = "android-architectures"; | ||
export declare const ANDROID_ARCHITECTURES = "android-archs"; | ||
export declare const ANDROID_PLATFORMS = "android-platorms"; | ||
@@ -35,2 +35,5 @@ export declare const ANDROID_ACCEPT_LICENSES = "android-accept-licenses"; | ||
export declare const DETACH = "detach"; | ||
export declare const QUIET = "quiet"; | ||
export declare const VERBOSE = "verbose"; | ||
export declare const ALREADY_OFF_ERROR = "already-off-error"; | ||
export declare var Opts: Options; |
@@ -29,3 +29,3 @@ "use strict"; | ||
exports.ANDROID_API_LEVELS = 'android-api-levels'; | ||
exports.ANDROID_ARCHITECTURES = 'android-architectures'; | ||
exports.ANDROID_ARCHITECTURES = 'android-archs'; | ||
exports.ANDROID_PLATFORMS = 'android-platorms'; | ||
@@ -38,2 +38,5 @@ exports.ANDROID_ACCEPT_LICENSES = 'android-accept-licenses'; | ||
exports.DETACH = 'detach'; | ||
exports.QUIET = 'quiet'; | ||
exports.VERBOSE = 'verbose'; | ||
exports.ALREADY_OFF_ERROR = 'already-off-error'; | ||
/** | ||
@@ -46,4 +49,5 @@ * The options used by the commands. | ||
new cli_1.Option(exports.SELENIUM_PORT, 'Optional port for the selenium standalone server', 'string', '4444'); | ||
opts[exports.APPIUM_PORT] = new cli_1.Option(exports.APPIUM_PORT, 'Optional port for the appium server', 'string'); | ||
opts[exports.AVD_PORT] = new cli_1.Option(exports.AVD_PORT, 'Optional port for android virtual devices. See mobile.md for details', 'string'); | ||
opts[exports.APPIUM_PORT] = | ||
new cli_1.Option(exports.APPIUM_PORT, 'Optional port for the appium server', 'string', '4723'); | ||
opts[exports.AVD_PORT] = new cli_1.Option(exports.AVD_PORT, 'Optional port for android virtual devices. See mobile.md for details', 'number', 5554); | ||
opts[exports.IGNORE_SSL] = new cli_1.Option(exports.IGNORE_SSL, 'Ignore SSL certificates', 'boolean', false); | ||
@@ -71,3 +75,3 @@ opts[exports.PROXY] = new cli_1.Option(exports.PROXY, 'Proxy to use for the install or update command', 'string'); | ||
opts[exports.ANDROID_API_LEVELS] = new cli_1.Option(exports.ANDROID_API_LEVELS, 'Which versions of the android API you want to emulate', 'string', binaries_1.AndroidSDK.DEFAULT_API_LEVELS); | ||
opts[exports.ANDROID_ARCHITECTURES] = new cli_1.Option(exports.ANDROID_ARCHITECTURES, 'Which architectures you want to use in android emulation', 'string', binaries_1.AndroidSDK.DEFAULT_ARCHITECTURES); | ||
opts[exports.ANDROID_ARCHITECTURES] = new cli_1.Option(exports.ANDROID_ARCHITECTURES, 'Which architectures you want to use in android emulation. By default it will try to match os.arch()', 'string', binaries_1.AndroidSDK.DEFAULT_ARCHITECTURES); | ||
opts[exports.ANDROID_PLATFORMS] = new cli_1.Option(exports.ANDROID_PLATFORMS, 'Which platforms you want to use in android emulation', 'string', binaries_1.AndroidSDK.DEFAULT_PLATFORMS); | ||
@@ -82,3 +86,6 @@ opts[exports.ANDROID_ACCEPT_LICENSES] = | ||
opts[exports.DETACH] = new cli_1.Option(exports.DETACH, 'Once the selenium server is up and running, return control to the parent process and continue running the server in the background.', 'boolean', false); | ||
opts[exports.VERBOSE] = new cli_1.Option(exports.VERBOSE, 'Extra console output', 'boolean', false); | ||
opts[exports.QUIET] = new cli_1.Option(exports.QUIET, 'Minimal console output', 'boolean', false); | ||
opts[exports.ALREADY_OFF_ERROR] = new cli_1.Option(exports.ALREADY_OFF_ERROR, 'Normally if you try to shut down a selenium which is not running, you will get a warning. This turns it into an error', 'boolean', false); | ||
exports.Opts = opts; | ||
//# sourceMappingURL=opts.js.map |
@@ -11,3 +11,4 @@ "use strict"; | ||
.action(shutdown) | ||
.addOption(opts_1.Opts[Opt.SELENIUM_PORT]); | ||
.addOption(opts_1.Opts[Opt.SELENIUM_PORT]) | ||
.addOption(opts_1.Opts[Opt.ALREADY_OFF_ERROR]); | ||
exports.program = prog; | ||
@@ -29,4 +30,18 @@ // stand alone runner | ||
http.get('http://localhost:' + options[Opt.SELENIUM_PORT].getString() + | ||
'/selenium-server/driver/?cmd=shutDownSeleniumServer'); | ||
'/selenium-server/driver/?cmd=shutDownSeleniumServer') | ||
.on('error', function (e) { | ||
if ((e.code == 'ECONNREFUSED') && (e.syscall == 'connect')) { | ||
if (!options[Opt.ALREADY_OFF_ERROR].getBoolean()) { | ||
logger.warn('Server does not appear to be on'); | ||
} | ||
else { | ||
logger.error('Server unreachable, probably not running'); | ||
throw e; | ||
} | ||
} | ||
else { | ||
throw e; | ||
} | ||
}); | ||
} | ||
//# sourceMappingURL=shutdown.js.map |
@@ -5,4 +5,4 @@ "use strict"; | ||
var minimist = require("minimist"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
var q = require("q"); | ||
var binaries_1 = require("../binaries"); | ||
@@ -36,7 +36,8 @@ var gecko_driver_1 = require("../binaries/gecko_driver"); | ||
.addOption(opts_1.Opts[Opt.SIGNAL_VIA_IPC]) | ||
.addOption(opts_1.Opts[Opt.QUIET]) | ||
.addOption(opts_1.Opts[Opt.DETACH]); | ||
if (os.type() === 'Darwin') { | ||
if (config_1.Config.osType() === 'Darwin') { | ||
prog.addOption(opts_1.Opts[Opt.IOS]); | ||
} | ||
if (os.type() === 'Windows_NT') { | ||
if (config_1.Config.osType() === 'Windows_NT') { | ||
prog.addOption(opts_1.Opts[Opt.VERSIONS_IE]) | ||
@@ -56,2 +57,5 @@ .addOption(opts_1.Opts[Opt.IE32]) | ||
} | ||
// Manage processes used in android emulation | ||
var androidProcesses = []; | ||
var androidActiveAVDs = []; | ||
/** | ||
@@ -65,5 +69,9 @@ * Parses the options and starts the selenium standalone server. | ||
} | ||
var osType = os.type(); | ||
var osType = config_1.Config.osType(); | ||
var stdio = options[Opt.QUIET].getBoolean() ? 'pipe' : 'inherit'; | ||
var binaries = files_1.FileManager.setupBinaries(); | ||
var seleniumPort = options[Opt.SELENIUM_PORT].getString(); | ||
var appiumPort = options[Opt.APPIUM_PORT].getString(); | ||
var avdPort = options[Opt.AVD_PORT].getNumber(); | ||
var android = options[Opt.ANDROID].getBoolean(); | ||
var outputDir = config_1.Config.getSeleniumDir(); | ||
@@ -130,3 +138,3 @@ if (options[Opt.OUT_DIR].getString()) { | ||
args.push('-Dwebdriver.chrome.driver=' + | ||
path.join(outputDir, binaries[binaries_1.ChromeDriver.id].executableFilename(osType))); | ||
path.resolve(outputDir, binaries[binaries_1.ChromeDriver.id].executableFilename(osType))); | ||
if (chromeLogs != null) { | ||
@@ -138,12 +146,12 @@ args.push('-Dwebdriver.chrome.logfile=' + chromeLogs); | ||
args.push('-Dwebdriver.gecko.driver=' + | ||
path.join(outputDir, binaries[gecko_driver_1.GeckoDriver.id].executableFilename(osType))); | ||
path.resolve(outputDir, binaries[gecko_driver_1.GeckoDriver.id].executableFilename(osType))); | ||
} | ||
if (downloadedBinaries[binaries_1.IEDriver.id] != null) { | ||
if (options[Opt.IE32]) { | ||
if (options[Opt.IE32].getBoolean()) { | ||
binaries[binaries_1.IEDriver.id].arch = 'Win32'; | ||
} | ||
args.push('-Dwebdriver.ie.driver=' + | ||
path.join(outputDir, binaries[binaries_1.IEDriver.id].executableFilename(osType))); | ||
path.resolve(outputDir, binaries[binaries_1.IEDriver.id].executableFilename(osType))); | ||
} | ||
if (options[Opt.EDGE]) { | ||
if (options[Opt.EDGE] && options[Opt.EDGE].getString()) { | ||
// validate that the file exists prior to adding it to args | ||
@@ -159,6 +167,6 @@ try { | ||
} | ||
if (options[Opt.ANDROID].getBoolean()) { | ||
if (android) { | ||
if (downloadedBinaries[binaries_1.AndroidSDK.id] != null) { | ||
var avds = options[Opt.AVDS].getString(); | ||
startAndroid(outputDir, binaries[binaries_1.AndroidSDK.id], avds.split(','), options[Opt.AVD_USE_SNAPSHOTS].getBoolean(), options[Opt.AVD_PORT].getString()); | ||
startAndroid(outputDir, binaries[binaries_1.AndroidSDK.id], avds.split(','), options[Opt.AVD_USE_SNAPSHOTS].getBoolean(), avdPort, stdio); | ||
} | ||
@@ -170,7 +178,7 @@ else { | ||
if (downloadedBinaries[binaries_1.Appium.id] != null) { | ||
startAppium(outputDir, binaries[binaries_1.Appium.id], binaries[binaries_1.AndroidSDK.id], options[Opt.APPIUM_PORT].getString()); | ||
startAppium(outputDir, binaries[binaries_1.Appium.id], binaries[binaries_1.AndroidSDK.id], appiumPort, stdio); | ||
} | ||
// log the command to launch selenium server | ||
args.push('-jar'); | ||
args.push(path.join(outputDir, binaries[binaries_1.StandAlone.id].filename())); | ||
args.push(path.resolve(outputDir, binaries[binaries_1.StandAlone.id].filename())); | ||
// Add the port parameter, has to declared after the jar file | ||
@@ -185,6 +193,5 @@ if (seleniumPort) { | ||
logger.info('java' + argsToString); | ||
var seleniumProcess = utils_1.spawn('java', args, 'inherit'); | ||
var seleniumProcess = utils_1.spawn('java', args, stdio); | ||
if (options[Opt.STARTED_SIGNIFIER].getString()) { | ||
// TODO(sjelin): check android too once it's working signalWhenReady( | ||
signalWhenReady(options[Opt.STARTED_SIGNIFIER].getString(), options[Opt.SIGNAL_VIA_IPC].getBoolean(), seleniumPort); | ||
signalWhenReady(options[Opt.STARTED_SIGNIFIER].getString(), options[Opt.SIGNAL_VIA_IPC].getBoolean(), outputDir, seleniumPort, downloadedBinaries[binaries_1.Appium.id] ? appiumPort : '', binaries[binaries_1.AndroidSDK.id], avdPort, androidActiveAVDs); | ||
} | ||
@@ -195,4 +202,7 @@ logger.info('seleniumProcess.pid: ' + seleniumProcess.pid); | ||
shutdownEverything(); | ||
process.exit(code); | ||
process.exit(process.exitCode || code); | ||
}); | ||
seleniumProcess.on('error', function (error) { | ||
logger.warn('Selenium Standalone server encountered an error: ' + error); | ||
}); | ||
process.stdin.resume(); | ||
@@ -208,8 +218,6 @@ process.stdin.on('data', function (chunk) { | ||
} | ||
// Manage processes used in android emulation | ||
var androidProcesses = []; | ||
function startAndroid(outputDir, sdk, avds, useSnapshots, port) { | ||
var sdkPath = path.join(outputDir, sdk.executableFilename(os.type())); | ||
function startAndroid(outputDir, sdk, avds, useSnapshots, port, stdio) { | ||
var sdkPath = path.resolve(outputDir, sdk.executableFilename(config_1.Config.osType())); | ||
if (avds[0] == 'all') { | ||
avds = require(path.join(sdkPath, 'available_avds.json')); | ||
avds = require(path.resolve(sdkPath, 'available_avds.json')); | ||
} | ||
@@ -219,4 +227,9 @@ else if (avds[0] == 'none') { | ||
} | ||
var minAVDPort = 5554; | ||
var maxAVDPort = 5586 - 2 * avds.length; | ||
if (avds.length && ((port < minAVDPort) || (port > maxAVDPort))) { | ||
throw new RangeError('AVD Port must be between ' + minAVDPort + ' and ' + maxAVDPort + ' to emulate ' + | ||
avds.length + ' android devices'); | ||
} | ||
avds.forEach(function (avd, i) { | ||
logger.info('Booting up AVD ' + avd); | ||
// Credit to appium-ci, which this code was adapted from | ||
@@ -229,2 +242,3 @@ var emuBin = 'emulator'; // TODO(sjelin): get the 64bit linux version working | ||
]; | ||
var portArg = null; | ||
if (!useSnapshots) { | ||
@@ -234,3 +248,4 @@ emuArgs = emuArgs.concat(['-no-snapshot-load', '-no-snapshot-save']); | ||
if (port) { | ||
emuArgs = emuArgs.concat(['-ports', (port + 2 * i) + ',' + (port + 2 * i + 1)]); | ||
portArg = port + i * 2; | ||
emuArgs = emuArgs.concat(['-port', '' + portArg]); | ||
} | ||
@@ -240,19 +255,27 @@ if (emuBin !== 'emulator') { | ||
} | ||
androidProcesses.push(utils_1.spawn(path.join(sdkPath, 'tools', emuBin), emuArgs, 'inherit')); | ||
logger.info('Starting ' + avd + ' on ' + (portArg == null ? 'default port' : 'port ' + portArg)); | ||
var child = utils_1.spawn(path.resolve(sdkPath, 'tools', emuBin), emuArgs, stdio); | ||
child.on('error', function (error) { | ||
logger.warn(avd + ' encountered an error: ' + error); | ||
}); | ||
androidProcesses.push(child); | ||
androidActiveAVDs.push(avd); | ||
}); | ||
} | ||
function killAndroid() { | ||
androidProcesses.forEach(function (androidProcess) { | ||
androidProcess.kill(); | ||
}); | ||
androidProcesses.length = 0; | ||
for (var i = 0; i < androidProcesses.length; i++) { | ||
logger.info('Shutting down ' + androidActiveAVDs[i]); | ||
androidProcesses[i].kill(); | ||
} | ||
androidProcesses.length = androidActiveAVDs.length = 0; | ||
} | ||
// Manage appium process | ||
var appiumProcess; | ||
function startAppium(outputDir, binary, android_sdk, port) { | ||
function startAppium(outputDir, binary, androidSDK, port, stdio) { | ||
logger.info('Starting appium server'); | ||
if (android_sdk) { | ||
process.env.ANDROID_HOME = path.join(outputDir, android_sdk.executableFilename(os.type())); | ||
if (androidSDK) { | ||
process.env.ANDROID_HOME = | ||
path.resolve(outputDir, androidSDK.executableFilename(config_1.Config.osType())); | ||
} | ||
appiumProcess = utils_1.spawn(path.join(outputDir, binary.filename(), 'node_modules', '.bin', 'appium'), port ? ['--port', port] : []); | ||
appiumProcess = utils_1.spawn('npm', ['run', 'appium'].concat(port ? ['--', '--port', port] : []), stdio, { cwd: path.resolve(outputDir, binary.filename()) }); | ||
} | ||
@@ -265,32 +288,100 @@ function killAppium() { | ||
} | ||
function signalWhenReady(signal, viaIPC, seleniumPort) { | ||
function check(callback) { | ||
http.get('http://localhost:' + seleniumPort + '/selenium-server/driver/?cmd=getLogMessages', function (res) { | ||
if (res.statusCode !== 200) { | ||
return callback(false); | ||
} | ||
var logs = ''; | ||
res.on('data', function (chunk) { | ||
logs += chunk; | ||
function signalWhenReady(signal, viaIPC, outputDir, seleniumPort, appiumPort, androidSDK, avdPort, avdNames) { | ||
var maxWait = 60 * 1000; | ||
function waitFor(getStatus, testStatus, desc) { | ||
var checkInterval = 100; | ||
return q.Promise(function (resolve, reject) { | ||
var waited = 0; | ||
(function recursiveCheck() { | ||
setTimeout(function () { | ||
getStatus() | ||
.then(function (status) { | ||
if (!testStatus(status)) { | ||
return q.reject('Invalid status' + (desc ? ' for ' + desc : '') + ': ' + status); | ||
} | ||
}) | ||
.then(function () { | ||
resolve(undefined); | ||
}, function (error) { | ||
waited += checkInterval; | ||
if (waited < maxWait) { | ||
recursiveCheck(); | ||
} | ||
else { | ||
reject('Timed out' + (desc ? ' wating for' + desc : '') + | ||
'. Final rejection reason: ' + JSON.stringify(error)); | ||
} | ||
}); | ||
}, checkInterval); | ||
})(); | ||
}); | ||
} | ||
; | ||
function waitForAndroid(avdPort, avdName, appiumPort) { | ||
var sdkPath = path.resolve(outputDir, androidSDK.executableFilename(config_1.Config.osType())); | ||
logger.info('Waiting for ' + avdName + '\'s emulator to start'); | ||
return utils_1.adb(sdkPath, avdPort, 'wait-for-device', maxWait) | ||
.then(function () { | ||
logger.info('Waiting for ' + avdName + '\'s OS to boot up'); | ||
return waitFor(function () { | ||
return utils_1.adb(sdkPath, avdPort, 'shell', maxWait, ['getprop', 'sys.boot_completed']); | ||
}, function (status) { | ||
return status.trim() == '1'; | ||
}, avdName + '\'s OS'); | ||
}, function (error) { | ||
return q.reject('Failed to wait for ' + avdName + '\'s emulator to start (' + error.code + ': ' + | ||
error.message + ')'); | ||
}) | ||
.then(function () { | ||
logger.info('Waiting for ' + avdName + ' to be ready to launch chrome'); | ||
var version = binaries_1.AndroidSDK.VERSIONS[parseInt(avdName.slice('android-'.length))]; | ||
return utils_1.request('POST', appiumPort, '/wd/hub/session', maxWait, { | ||
desiredCapabilities: { | ||
browserName: 'chrome', | ||
platformName: 'Android', | ||
platformVersion: version, | ||
deviceName: 'Android Emulator' | ||
} | ||
}) | ||
.then(function (data) { | ||
return JSON.parse(data)['sessionId']; | ||
}, function (error) { | ||
return q.reject('Could not start chrome on ' + avdName + ' (' + error.code + ': ' + | ||
error.message + ')'); | ||
}); | ||
res.on('end', function () { | ||
callback(logs.toUpperCase().indexOf('OK') != -1); | ||
}) | ||
.then(function (sessionId) { | ||
logger.info('Shutting down dummy chrome instance for ' + avdName); | ||
return utils_1.request('DELETE', appiumPort, '/wd/hub/session/' + sessionId) | ||
.then(function () { }, function (error) { | ||
return q.reject('Could not close chrome on ' + avdName + ' (' + error.code + ': ' + | ||
error.message + ')'); | ||
}); | ||
}) | ||
.on('error', function () { | ||
callback(false); | ||
}); | ||
} | ||
(function recursiveCheck(triesRemaining) { | ||
setTimeout(function () { | ||
check(function (ready) { | ||
if (ready) { | ||
sendStartedSignal(signal, viaIPC); | ||
} | ||
else if (triesRemaining) { | ||
recursiveCheck(triesRemaining--); | ||
} | ||
}); | ||
}, 100); | ||
})(100); | ||
var pending = [waitFor(function () { | ||
return utils_1.request('GET', seleniumPort, '/selenium-server/driver/?cmd=getLogMessages', maxWait); | ||
}, function (logs) { | ||
return logs.toUpperCase().indexOf('OK') != -1; | ||
}, 'selenium server')]; | ||
if (appiumPort) { | ||
pending.push(waitFor(function () { | ||
return utils_1.request('GET', appiumPort, '/wd/hub/status', maxWait); | ||
}, function (status) { | ||
return JSON.parse(status).status == 0; | ||
}, 'appium server')); | ||
} | ||
if (androidSDK && avdPort) { | ||
for (var i = 0; i < avdNames.length; i++) { | ||
pending.push(waitForAndroid(avdPort + 2 * i, avdNames[i], appiumPort)); | ||
} | ||
} | ||
q.all(pending).then(function () { | ||
logger.info('Everything started'); | ||
sendStartedSignal(signal, viaIPC); | ||
}, function (error) { | ||
logger.error(error); | ||
shutdownEverything(seleniumPort); | ||
process.exitCode = 1; | ||
}); | ||
} | ||
@@ -306,2 +397,3 @@ function sendStartedSignal(signal, viaIPC) { | ||
} | ||
console.log(signal); | ||
} | ||
@@ -308,0 +400,0 @@ function shutdownEverything(seleniumPort) { |
@@ -6,3 +6,2 @@ "use strict"; | ||
var minimist = require("minimist"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
@@ -24,2 +23,3 @@ var q = require("q"); | ||
.addOption(opts_1.Opts[Opt.OUT_DIR]) | ||
.addOption(opts_1.Opts[Opt.VERBOSE]) | ||
.addOption(opts_1.Opts[Opt.IGNORE_SSL]) | ||
@@ -36,6 +36,6 @@ .addOption(opts_1.Opts[Opt.PROXY]) | ||
.addOption(opts_1.Opts[Opt.ANDROID_ACCEPT_LICENSES]); | ||
if (os.type() === 'Darwin') { | ||
if (config_1.Config.osType() === 'Darwin') { | ||
prog.addOption(opts_1.Opts[Opt.IOS]); | ||
} | ||
if (os.type() === 'Windows_NT') { | ||
if (config_1.Config.osType() === 'Windows_NT') { | ||
prog.addOption(opts_1.Opts[Opt.IE]).addOption(opts_1.Opts[Opt.IE32]); | ||
@@ -48,3 +48,3 @@ } | ||
.addOption(opts_1.Opts[Opt.VERSIONS_GECKO]); | ||
if (os.type() === 'Windows_NT') { | ||
if (config_1.Config.osType() === 'Windows_NT') { | ||
prog.addOption(opts_1.Opts[Opt.VERSIONS_IE]); | ||
@@ -98,2 +98,3 @@ } | ||
var proxy = options[Opt.PROXY].getString(); | ||
var verbose = options[Opt.VERBOSE].getBoolean(); | ||
// setup versions for binaries | ||
@@ -122,3 +123,3 @@ var binaries = files_1.FileManager.setupBinaries(options[Opt.ALTERNATE_CDN].getString()); | ||
logger.info(binary_1.name + ': file exists ' + | ||
path.resolve(outputDir, binary_1.filename(os.type(), os.arch()))); | ||
path.resolve(outputDir, binary_1.filename(config_1.Config.osType(), config_1.Config.osArch()))); | ||
logger.info(binary_1.name + ': v' + binary_1.versionCustom + ' up to date'); | ||
@@ -130,12 +131,12 @@ } | ||
var binary = binaries[binaries_1.ChromeDriver.id]; | ||
updateBinary(binary, outputDir, proxy, ignoreSSL); | ||
updateBinary(binary, outputDir, proxy, ignoreSSL).done(); | ||
} | ||
if (gecko) { | ||
var binary = binaries[binaries_1.GeckoDriver.id]; | ||
updateBinary(binary, outputDir, proxy, ignoreSSL); | ||
updateBinary(binary, outputDir, proxy, ignoreSSL).done(); | ||
} | ||
if (ie) { | ||
var binary = binaries[binaries_1.IEDriver.id]; | ||
binary.arch = os.arch(); // Win32 or x64 | ||
updateBinary(binary, outputDir, proxy, ignoreSSL); | ||
binary.arch = config_1.Config.osArch(); // Win32 or x64 | ||
updateBinary(binary, outputDir, proxy, ignoreSSL).done(); | ||
} | ||
@@ -145,9 +146,9 @@ if (ie32) { | ||
binary.arch = 'Win32'; | ||
updateBinary(binary, outputDir, proxy, ignoreSSL); | ||
updateBinary(binary, outputDir, proxy, ignoreSSL).done(); | ||
} | ||
if (android) { | ||
var binary_2 = binaries[binaries_1.AndroidSDK.id]; | ||
var sdk_path = path.join(outputDir, binary_2.executableFilename(os.type())); | ||
var sdk_path = path.resolve(outputDir, binary_2.executableFilename(config_1.Config.osType())); | ||
var oldAVDList_1; | ||
q.nfcall(fs.readFile, path.join(sdk_path, 'available_avds.json')) | ||
q.nfcall(fs.readFile, path.resolve(sdk_path, 'available_avds.json')) | ||
.then(function (oldAVDs) { | ||
@@ -162,4 +163,5 @@ oldAVDList_1 = oldAVDs; | ||
.then(function () { | ||
initialize_1.android(path.join(outputDir, binary_2.executableFilename(os.type())), android_api_levels, android_architectures, android_platforms, android_accept_licenses, binaries[binaries_1.AndroidSDK.id].versionCustom, JSON.parse(oldAVDList_1), logger); | ||
}); | ||
initialize_1.android(path.resolve(outputDir, binary_2.executableFilename(config_1.Config.osType())), android_api_levels, android_architectures, android_platforms, android_accept_licenses, binaries[binaries_1.AndroidSDK.id].versionCustom, JSON.parse(oldAVDList_1), logger, verbose); | ||
}) | ||
.done(); | ||
} | ||
@@ -185,4 +187,4 @@ if (ios) { | ||
logger.info(binary.name + ': file exists ' + | ||
path.resolve(outputDir, binary.filename(os.type(), os.arch()))); | ||
var fileName = binary.filename(os.type(), os.arch()); | ||
path.resolve(outputDir, binary.filename(config_1.Config.osType(), config_1.Config.osArch()))); | ||
var fileName = binary.filename(config_1.Config.osType(), config_1.Config.osArch()); | ||
unzip(binary, outputDir, fileName); | ||
@@ -195,4 +197,4 @@ logger.info(binary.name + ': v' + binary.versionCustom + ' up to date'); | ||
// remove the previously saved file and unzip it | ||
var osType = os.type(); | ||
var mv = path.join(outputDir, binary.executableFilename(osType)); | ||
var osType = config_1.Config.osType(); | ||
var mv = path.resolve(outputDir, binary.executableFilename(osType)); | ||
try { | ||
@@ -219,3 +221,3 @@ fs.unlinkSync(mv); | ||
// rename | ||
fs.renameSync(path.join(outputDir, binary.zipContentName(osType)), mv); | ||
fs.renameSync(path.resolve(outputDir, binary.zipContentName(osType)), mv); | ||
// set permissions | ||
@@ -228,4 +230,4 @@ if (osType !== 'Windows_NT') { | ||
else { | ||
fs.chmodSync(path.join(mv, 'tools', 'android'), '0755'); | ||
fs.chmodSync(path.join(mv, 'tools', 'emulator'), '0755'); | ||
fs.chmodSync(path.resolve(mv, 'tools', 'android'), '0755'); | ||
fs.chmodSync(path.resolve(mv, 'tools', 'emulator'), '0755'); | ||
} | ||
@@ -236,3 +238,3 @@ } | ||
logger.info('appium: installing appium'); | ||
var folder = path.join(outputDir, binary.filename()); | ||
var folder = path.resolve(outputDir, binary.filename()); | ||
try { | ||
@@ -243,6 +245,42 @@ rimraf.sync(folder); | ||
} | ||
var appiumVersion = binary.version(); | ||
fs.mkdirSync(folder); | ||
fs.writeFileSync(path.join(folder, 'package.json'), '{}'); | ||
utils_1.spawn('npm', ['install', 'appium@' + binary.version()], null, { cwd: folder }); | ||
fs.writeFileSync(path.resolve(folder, 'package.json'), JSON.stringify({ scripts: { appium: 'appium' } })); | ||
utils_1.spawn('npm', ['install', 'appium@' + appiumVersion], null, { cwd: folder }); | ||
// Check versions and output warnings/errors | ||
function checkVersion(actual_semver, minimum_semver) { | ||
if (actual_semver[0] == 'v') { | ||
actual_semver = actual_semver.slice(1); | ||
} | ||
var actualVersions = actual_semver.toString().split('.'); | ||
var minimumVersions = minimum_semver.toString().split('.'); | ||
for (var i = 0; i < minimumVersions.length; i++) { | ||
var actual = parseInt(actualVersions[i] || '0'); | ||
var min = parseInt(minimumVersions[i] || '0'); | ||
if (!min) { | ||
return true; | ||
} | ||
else if (!actual || (actual < min)) { | ||
return false; | ||
} | ||
else if (actual > min) { | ||
return true; | ||
} | ||
} | ||
return true; | ||
} | ||
if (!checkVersion(appiumVersion, '1.6')) { | ||
logger.warn('Intalling appium@' + appiumVersion + ', which is not supported'); | ||
logger.warn('appium < 1.6 cannot run android >= 7, ' + | ||
'which is required to have chrome bundled with the `google_apis` image'); | ||
} | ||
else if (!checkVersion(process.version, '6')) { | ||
var npmVersion = utils_1.spawnSync('npm', ['-v']).stdout; | ||
if (!checkVersion(npmVersion, '3')) { | ||
logger.error('Using npm@' + npmVersion + ', which will almost certainly cause the ' + | ||
'installation of appium@' + appiumVersion + ' to fail silently.' + | ||
'Please upgrade to npm >= 3'); | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=update.js.map |
@@ -28,2 +28,12 @@ export interface ConfigFile { | ||
static isLocalVersion: boolean; | ||
static osArch_: string; | ||
static osType_: string; | ||
static noProxy_: any; | ||
static httpsProxy_: any; | ||
static httpProxy_: any; | ||
static osArch(): string; | ||
static osType(): string; | ||
static noProxy(): string; | ||
static httpProxy(): string; | ||
static httpsProxy(): string; | ||
static getConfigFile_(): string; | ||
@@ -30,0 +40,0 @@ static getPackageFile_(): string; |
"use strict"; | ||
var os = require("os"); | ||
var path = require("path"); | ||
@@ -15,2 +16,17 @@ var cli_1 = require("./cli"); | ||
} | ||
Config.osArch = function () { | ||
return Config.osArch_; | ||
}; | ||
Config.osType = function () { | ||
return Config.osType_; | ||
}; | ||
Config.noProxy = function () { | ||
return Config.noProxy_; | ||
}; | ||
Config.httpProxy = function () { | ||
return Config.httpProxy_; | ||
}; | ||
Config.httpsProxy = function () { | ||
return Config.httpsProxy_; | ||
}; | ||
Config.getConfigFile_ = function () { | ||
@@ -66,3 +82,2 @@ return path.resolve(Config.dir, '..', Config.configFile); | ||
}()); | ||
exports.Config = Config; | ||
Config.configFile = 'config.json'; | ||
@@ -77,2 +92,8 @@ Config.packageFile = 'package.json'; | ||
Config.isLocalVersion = false; | ||
Config.osArch_ = os.arch(); | ||
Config.osType_ = os.type(); | ||
Config.noProxy_ = process.env.NO_PROXY || process.env.no_proxy; | ||
Config.httpsProxy_ = process.env.HTTPS_PROXY || process.env.https_proxy; | ||
Config.httpProxy_ = process.env.HTTP_PROXY || process.env.http_proxy; | ||
exports.Config = Config; | ||
//# sourceMappingURL=config.js.map |
"use strict"; | ||
var fs = require("fs"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
@@ -9,2 +8,3 @@ var q = require("q"); | ||
var cli_1 = require("../cli"); | ||
var config_1 = require("../config"); | ||
var logger = new cli_1.Logger('downloader'); | ||
@@ -27,3 +27,3 @@ /** | ||
logger.info(binary.name + ': downloading version ' + binary.version()); | ||
var url = binary.url(os.type(), os.arch()); | ||
var url = binary.url(config_1.Config.osType(), config_1.Config.osArch()); | ||
if (!url) { | ||
@@ -33,3 +33,3 @@ logger.error(binary.name + ' v' + binary.version() + ' is not available for your system.'); | ||
} | ||
Downloader.httpGetFile_(url, binary.filename(os.type(), os.arch()), outputDir, opt_proxy, opt_ignoreSSL, function (filePath) { | ||
Downloader.httpGetFile_(url, binary.filename(config_1.Config.osType(), config_1.Config.osArch()), outputDir, opt_proxy, opt_ignoreSSL, function (filePath) { | ||
if (opt_callback) { | ||
@@ -56,3 +56,3 @@ opt_callback(binary, outputDir, filePath); | ||
// the checks to see if it exists and equal to empty string is to help with testing | ||
var noProxy = process.env.NO_PROXY || process.env.no_proxy; | ||
var noProxy = config_1.Config.noProxy(); | ||
if (noProxy) { | ||
@@ -72,10 +72,9 @@ // array of hostnames/domain names listed in the NO_PROXY environment variable | ||
if (protocol === 'https:') { | ||
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || | ||
process.env.http_proxy; | ||
return config_1.Config.httpsProxy() || config_1.Config.httpProxy(); | ||
} | ||
else if (protocol === 'http:') { | ||
return process.env.HTTP_PROXY || process.env.http_proxy; | ||
return config_1.Config.httpProxy(); | ||
} | ||
} | ||
return null; | ||
return undefined; | ||
}; | ||
@@ -103,2 +102,3 @@ Downloader.httpHeadContentLength = function (fileUrl, opt_proxy, opt_ignoreSSL) { | ||
} | ||
response.destroy(); | ||
}); | ||
@@ -116,3 +116,3 @@ return deferred.promise; | ||
logger.info('curl -o ' + outputDir + '/' + fileName + ' ' + fileUrl); | ||
var filePath = path.join(outputDir, fileName); | ||
var filePath = path.resolve(outputDir, fileName); | ||
var file = fs.createWriteStream(filePath); | ||
@@ -119,0 +119,0 @@ var contentLength = 0; |
"use strict"; | ||
var fs = require("fs"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
var q = require("q"); | ||
var binaries_1 = require("../binaries"); | ||
var config_1 = require("../config"); | ||
var downloaded_binary_1 = require("./downloaded_binary"); | ||
@@ -41,4 +41,4 @@ var downloader_1 = require("./downloader"); | ||
FileManager.checkOS_ = function (osType, binary) { | ||
for (var os_1 in binary.os) { | ||
if (binaries_1.OS[os_1] == osType) { | ||
for (var os in binary.os) { | ||
if (binaries_1.OS[os] == osType) { | ||
return true; | ||
@@ -85,3 +85,3 @@ } | ||
FileManager.setupBinaries = function (alternateCDN) { | ||
return FileManager.compileBinaries_(os.type(), alternateCDN); | ||
return FileManager.compileBinaries_(config_1.Config.osType(), alternateCDN); | ||
}; | ||
@@ -142,4 +142,4 @@ /** | ||
FileManager.downloadedBinaries = function (outputDir) { | ||
var ostype = os.type(); | ||
var arch = os.arch(); | ||
var ostype = config_1.Config.osType(); | ||
var arch = config_1.Config.osArch(); | ||
var binaries = FileManager.setupBinaries(); | ||
@@ -163,4 +163,4 @@ var existingFiles = FileManager.getExistingFiles(outputDir); | ||
FileManager.toDownload = function (binary, outputDir, proxy, ignoreSSL) { | ||
var osType = os.type(); | ||
var osArch = os.arch(); | ||
var osType = config_1.Config.osType(); | ||
var osArch = config_1.Config.osArch(); | ||
var filePath; | ||
@@ -221,3 +221,3 @@ var readData; | ||
if (file.indexOf(bin.prefix()) !== -1) { | ||
bin.remove(path.join(outputDir, file)); | ||
bin.remove(path.resolve(outputDir, file)); | ||
logger.info('removed ' + file); | ||
@@ -224,0 +224,0 @@ } |
/// <reference types="node" /> | ||
/// <reference types="q" /> | ||
import * as child_process from 'child_process'; | ||
import * as q from 'q'; | ||
export declare let spawn: (cmd: string, args: string[], stdio?: any, opts?: child_process.SpawnOptions) => child_process.ChildProcess; | ||
export declare let spawnSync: (cmd: string, args: string[], stdio?: any, opts?: child_process.SpawnSyncOptions) => child_process.SpawnSyncReturns<any>; | ||
export declare function request(method: string, port: string, path: string, timeout?: number, data?: any): q.Promise<string>; | ||
export declare function adb(sdkPath: string, port: number, command: string, timeout: number, args?: string[]): q.Promise<string>; |
"use strict"; | ||
var child_process = require("child_process"); | ||
var fs = require("fs"); | ||
var os = require("os"); | ||
var http = require("http"); | ||
var path = require("path"); | ||
var q = require("q"); | ||
var config_1 = require("./config"); | ||
function spawnFactory(sync) { | ||
return function (cmd, args, stdio, opts) { | ||
if ((os.type() === 'Windows_NT') && (cmd.slice(-4) !== '.exe')) { | ||
if ((config_1.Config.osType() === 'Windows_NT') && (cmd.slice(-4) !== '.exe')) { | ||
if (fs.existsSync(cmd + '.exe')) { | ||
@@ -30,2 +33,84 @@ cmd += '.exe'; | ||
exports.spawnSync = spawnFactory(true); | ||
function request(method, port, path, timeout, data) { | ||
var headers = {}; | ||
var hasContent = data && ((method == 'POST') || (method == 'PUT')); | ||
if (hasContent) { | ||
data = data ? JSON.stringify(data) : ''; | ||
headers['Content-Length'] = data.length; | ||
headers['Content-Type'] = 'application/json;charset=UTF-8'; | ||
} | ||
return q.Promise(function (resolve, reject) { | ||
var unexpectedEnd = function () { | ||
reject({ code: 'UNKNOWN', message: 'Request ended unexpectedly' }); | ||
}; | ||
var req = http.request({ port: parseInt(port), method: method, path: path, headers: headers }, function (res) { | ||
req.removeListener('end', unexpectedEnd); | ||
if (res.statusCode !== 200) { | ||
reject({ code: res.statusCode, message: res.statusMessage }); | ||
} | ||
else { | ||
var buffer_1 = []; | ||
res.on('data', buffer_1.push.bind(buffer_1)); | ||
res.on('end', function () { | ||
resolve(buffer_1.join('').replace(/\0/g, '')); | ||
}); | ||
} | ||
}); | ||
if (timeout) { | ||
req.setTimeout(timeout, function () { | ||
reject({ code: 'TIMEOUT', message: 'Request timed out' }); | ||
}); | ||
} | ||
req.on('error', reject); | ||
req.on('end', unexpectedEnd); | ||
if (hasContent) { | ||
req.write(data); | ||
} | ||
req.end(); | ||
}); | ||
} | ||
exports.request = request; | ||
function adb(sdkPath, port, command, timeout, args) { | ||
return q.Promise(function (resolve, reject) { | ||
var child = exports.spawn(path.resolve(sdkPath, 'platform-tools', 'adb'), ['-s', 'emulator-' + port, command].concat(args || []), 'pipe'); | ||
var done = false; | ||
var buffer = []; | ||
child.stdout.on('data', buffer.push.bind(buffer)); | ||
child.on('error', function (err) { | ||
if (!done) { | ||
done = true; | ||
reject(err); | ||
} | ||
}); | ||
child.on('exit', function (code, signal) { | ||
if (!done) { | ||
done = true; | ||
if (code === 0) { | ||
resolve(buffer.join('')); | ||
} | ||
else { | ||
reject({ | ||
code: code, | ||
message: 'abd command "' + command + '" ' + | ||
(signal ? 'received signal ' + signal : 'returned with a non-zero exit code') + | ||
'for emulator-' + port | ||
}); | ||
} | ||
} | ||
}); | ||
if (timeout) { | ||
setTimeout(function () { | ||
if (!done) { | ||
done = true; | ||
child.kill(); | ||
reject({ | ||
code: 'TIMEOUT', | ||
message: 'adb command "' + command + '" timed out for emulator-' + port | ||
}); | ||
} | ||
}, timeout); | ||
} | ||
}); | ||
} | ||
exports.adb = adb; | ||
//# sourceMappingURL=utils.js.map |
{ | ||
"name": "webdriver-manager", | ||
"version": "10.2.10", | ||
"version": "10.3.0", | ||
"description": "A selenium server and browser driver manager for your end to end tests.", | ||
@@ -9,3 +9,4 @@ "scripts": { | ||
"prepublish": "gulp prepublish", | ||
"test": "gulp test" | ||
"test": "gulp test", | ||
"test_travis": "gulp test:headless" | ||
}, | ||
@@ -47,3 +48,3 @@ "keywords": [ | ||
"@types/chalk": "^0.4.28", | ||
"@types/form-data": "^0.0.32", | ||
"@types/form-data": "^0.0.33", | ||
"@types/glob": "^5.0.29", | ||
@@ -56,4 +57,5 @@ "@types/ini": "^1.3.28", | ||
"@types/q": "^0.0.32", | ||
"@types/request": "^0.0.33", | ||
"@types/request": "^0.0.36", | ||
"@types/rimraf": "^0.0.28", | ||
"@types/selenium-webdriver": "^2.53.35", | ||
"@types/semver": "^5.3.30", | ||
@@ -65,4 +67,9 @@ "clang-format": "^1.0.35", | ||
"run-sequence": "^1.1.5", | ||
"selenium-webdriver": "2.53.1", | ||
"typescript": "^2.1.1" | ||
}, | ||
"engines": { | ||
"node": ">=4", | ||
"npm": ">=3" | ||
} | ||
} |
116
CHANGELOG.md
@@ -0,1 +1,117 @@ | ||
# 11.0.0 | ||
## Breaking Change: | ||
- Requires node 6 since node 6 is in long term support. See (node LTS Schedule)[https://github.com/nodejs/LTS#lts-schedule]. | ||
## Features | ||
- ([b5638ef](https://github.com/angular/webdriver-manager/commit/b5638ef0861843e1d42220af515adc3e03a2b65a)) | ||
feat(update): on update, write full binary paths to file (#140) | ||
- Adding back in curl calls, these were removed on the new | ||
`Downloader.getFile`. Add curl call to reflect proxies. | ||
- Fix output dir to read from update's options instead of Config | ||
- Feature will help directConnect users for Protractor. The file | ||
will keep track of the last binary version as well as all other | ||
binaries downloaded. | ||
The file will be created in the output directory. By default this is | ||
`selenium/update-config.json`. On `clean` this file will be removed. | ||
``` | ||
webdriver-manager update --versions.chrome=2.20 --standalone=false | ||
--gecko=false | ||
``` | ||
file created: | ||
``` | ||
{ | ||
"chrome": { | ||
"last": "/opt/src/webdriver-manager/selenium/chromedriver_2.20", | ||
"all": ["/opt/src/webdriver-manager/selenium/chromedriver_2.20"] | ||
} | ||
} | ||
``` | ||
then the user wants to use 2.25: | ||
``` | ||
webdriver-manager update --versions.chrome=2.25 --standalone=false | ||
--gecko=false | ||
``` | ||
file created: | ||
``` | ||
{ | ||
"chrome": { | ||
"last": "/opt/src/webdriver-manager/selenium/chromedriver_2.25", | ||
"all": ["/opt/src/webdriver-manager/selenium/chromedriver_2.20", | ||
"/opt/src/webdriver-manager/selenium/chromedriver_2.25"] | ||
} | ||
} | ||
``` | ||
- ([473ab3e](https://github.com/angular/webdriver-manager/commit/473ab3e40c44468bb79e2a23d7b12753cf6e2b4d)) | ||
feat(android): match android arch to os.arch (#164) | ||
The default was x86-64, but x86 cannot be emulated on ARM. This makes more sense | ||
- ([c864c9a](https://github.com/angular/webdriver-manager/commit/c864c9af35514a4b5bf8a1d82b4339b39e5ac574)) | ||
feat(shutdown): do not error if you try to shutdown a server which is already off (#162) | ||
When scripting, you might want to defensively run a `shutdown` command. If the shutdown fails | ||
because the server is already off, you don't care. If it fails for another reason, you do care. | ||
So I made trying to shutdown a server which is already off just a warning. I added a flag in case | ||
you want the old behavior though. | ||
- ([338fffd](https://github.com/angular/webdriver-manager/commit/338fffddf68ac2767aa5c226ba5374451b9e5308)) | ||
feat(quiet/verbose): add `--quiet` and `--verbose` flags to control the level of output (#156) | ||
I added the `--quiet` flag for cases like: | ||
where currently the start --detach; ./tests.sh; webdriver-manager shutdown` | ||
selenium server output will get mixed in with other output. | ||
I also added the `--verbose` flag for `webdriver-manager update` in case you *really* wanted to | ||
see all the output which gets eaten by using `--android-accept-licenses`. | ||
- ([91e36a3](https://github.com/angular/webdriver-manager/commit/91e36a3e56e712af2c104eafc45eeeba5997ad6a)) | ||
feat(android on windows): Support android VMs on windows (#154) | ||
Closes https://github.com/angular/webdriver-manager/issues/51 | ||
- ([d533b03](https://github.com/angular/webdriver-manager/commit/d533b0389ac8a43b815890a644fdb9aa403ec769)) | ||
feat(start android): extend the --detach flag to wait for appium/android (#141) | ||
## Bug fixes | ||
- ([26586f1](https://github.com/angular/webdriver-manager/commit/26586f1b341e02229d73d40827a9c1af2197ebb3)) | ||
fix(start): wait for emulated android to really be ready before signaling (#161) | ||
Before, we were just waiting for the emulator to be running, rather than waiting for the OS to be | ||
booted up and ready to instance chrome. | ||
While I was doing that I moved some stuff into `lib/utils.ts` since I felt like too much of | ||
`lib/cmds/start.ts` was being devoted to this one feature. | ||
Also closes https://github.com/angular/webdriver-manager/issues/166 | ||
- ([a7c6eb5](https://github.com/angular/webdriver-manager/commit/a7c6eb5d3d1caed2afea1ef896753d53f4ea14ed)) | ||
fix(update/android): 2a1505f broke android | ||
- ([3ee3e1a](https://github.com/angular/webdriver-manager/commit/3ee3e1a328087cb8c5bf869e00a325cfdeb80f6d)) | ||
fix(fs): path.join does not handle absolute paths as desired (#152) | ||
- ([deead0f](https://github.com/angular/webdriver-manager/commit/deead0fc55ecd00b282aedc234592181746a307c)) | ||
fix(downloader): destroy the request after receiving the header (#144) | ||
Otherwise we’ll won’t terminate until the whole file was downloaded, even though we don’t need it. | ||
- ([c16bf90](https://github.com/angular/webdriver-manager/commit/c16bf9053fc90e4b5e89ab867c514d0622ab0716)) | ||
chore(es6): allow to use es6 promises (#160) | ||
- with node 6 on LTS, we can update the tsconfig to es6 | ||
- update travis tests to use node 6 and 7 | ||
# 10.3.0 | ||
- Rebase some (but not all) of the changes from v11 into a 10.x release (see | ||
https://github.com/angular/webdriver-manager/pull/179) | ||
# 10.2.10 | ||
@@ -2,0 +118,0 @@ |
{ | ||
"webdriverVersions": { | ||
"selenium": "2.53.1", | ||
"chromedriver": "2.25", | ||
"chromedriver": "2.26", | ||
"geckodriver": "v0.11.1", | ||
@@ -6,0 +6,0 @@ "iedriver": "2.53.1", |
'use strict'; | ||
var path = require('path'); | ||
var gulp = require('gulp'); | ||
@@ -7,21 +8,23 @@ var runSequence = require('run-sequence'); | ||
var runSpawn = function(done, task, opt_arg) { | ||
opt_arg = typeof opt_arg !== 'undefined' ? opt_arg : []; | ||
var child = spawn(task, opt_arg, {stdio: 'inherit'}); | ||
var runSpawn = function(task, args, done) { | ||
done = done || function() {}; | ||
var child = spawn(task, args, {stdio: 'inherit'}); | ||
var running = false; | ||
child.on('close', function() { | ||
child.on('close', function(code) { | ||
if (!running) { | ||
running = true; | ||
done(); | ||
done(code); | ||
} | ||
}); | ||
child.on('error', function() { | ||
child.on('error', function(err) { | ||
if (!running) { | ||
console.error('gulp encountered a child error'); | ||
running = true; | ||
done(); | ||
done(err || 1); | ||
} | ||
}); | ||
return child; | ||
}; | ||
// Build | ||
gulp.task('copy', function() { | ||
@@ -32,3 +35,3 @@ return gulp.src(['config.json', 'package.json']) | ||
var tsGlobs = ['lib/**/*.ts', 'spec/**/*.ts']; | ||
var tsGlobs = ['lib/**/*.ts', '*spec/**/*.ts']; | ||
@@ -50,3 +53,3 @@ gulp.task('format:enforce', () => { | ||
gulp.task('tsc', function(done) { | ||
runSpawn(done, process.execPath, ['node_modules/typescript/bin/tsc']); | ||
runSpawn(process.execPath, ['node_modules/typescript/bin/tsc'], done); | ||
}); | ||
@@ -58,9 +61,48 @@ | ||
gulp.task('default',['prepublish']); | ||
gulp.task('build',['prepublish']); | ||
gulp.task('default', ['prepublish']); | ||
gulp.task('build', ['prepublish']); | ||
gulp.task('test', ['format', 'build'], function(done) { | ||
var opt_arg = []; | ||
opt_arg.push('node_modules/jasmine/bin/jasmine.js'); | ||
runSpawn(done, process.execPath, opt_arg); | ||
// Command line commands | ||
gulp.task('update', ['build'], function(done) { | ||
runSpawn(process.execPath, ['bin/webdriver-manager', 'update', '--android', | ||
'--android-accept-licenses'], done); | ||
}); | ||
gulp.task('start', ['build', 'shutdown'], function(done) { | ||
runSpawn(process.execPath, ['bin/webdriver-manager', 'start', '--detach', '--seleniumPort', | ||
'4444', '--android', '--appium-port', '4723', '--quiet'], done); | ||
}); | ||
gulp.task('start:headless', ['build', 'shutdown'], function(done) { | ||
runSpawn(process.execPath, ['bin/webdriver-manager', 'start', '--detach', '--seleniumPort', | ||
'4444', '--android', '--appium-port', '4723', '--quiet', '--avds', 'none'], done); | ||
}); | ||
gulp.task('shutdown', ['build'], function(done) { | ||
runSpawn(process.execPath, ['bin/webdriver-manager', 'shutdown'], done); | ||
}); | ||
// Test | ||
gulp.task('test:unit', ['build'], function(done) { | ||
runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js'], done); | ||
}); | ||
gulp.task('test:e2e:inner', ['build'], function(done) { | ||
runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js', 'JASMINE_CONFIG_PATH=' + | ||
path.join('e2e_spec', 'support', 'jasmine.json')], done); | ||
}); | ||
gulp.task('test:e2e:inner:headless', ['build'], function(done) { | ||
runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js', 'JASMINE_CONFIG_PATH=' + | ||
path.join('e2e_spec', 'support', 'headless.json')], done); | ||
}); | ||
gulp.task('test:e2e:no_update', function(done) { | ||
runSequence('start', 'test:e2e:inner', 'shutdown', done); | ||
}); | ||
gulp.task('test:e2e', function(done) { | ||
runSequence('update', 'test:e2e:no_update', done); | ||
}); | ||
gulp.task('test:e2e:headless', function(done) { | ||
runSequence('update', 'start:headless', 'test:e2e:inner:headless', 'shutdown', done); | ||
}); | ||
gulp.task('test', ['format', 'test:unit', 'test:e2e']); | ||
gulp.task('test:no_update', ['format', 'test:unit', 'test:e2e:no_update']); | ||
gulp.task('test:headless', ['format', 'test:unit', 'test:e2e:headless']); |
{ | ||
"name": "webdriver-manager", | ||
"version": "10.2.10", | ||
"version": "10.3.0", | ||
"description": "A selenium server and browser driver manager for your end to end tests.", | ||
@@ -9,3 +9,4 @@ "scripts": { | ||
"prepublish": "gulp prepublish", | ||
"test": "gulp test" | ||
"test": "gulp test", | ||
"test_travis": "gulp test:headless" | ||
}, | ||
@@ -47,3 +48,3 @@ "keywords": [ | ||
"@types/chalk": "^0.4.28", | ||
"@types/form-data": "^0.0.32", | ||
"@types/form-data": "^0.0.33", | ||
"@types/glob": "^5.0.29", | ||
@@ -56,4 +57,5 @@ "@types/ini": "^1.3.28", | ||
"@types/q": "^0.0.32", | ||
"@types/request": "^0.0.33", | ||
"@types/request": "^0.0.36", | ||
"@types/rimraf": "^0.0.28", | ||
"@types/selenium-webdriver": "^2.53.35", | ||
"@types/semver": "^5.3.30", | ||
@@ -65,4 +67,9 @@ "clang-format": "^1.0.35", | ||
"run-sequence": "^1.1.5", | ||
"selenium-webdriver": "2.53.1", | ||
"typescript": "^2.1.1" | ||
}, | ||
"engines": { | ||
"node": ">=4", | ||
"npm": ">=3" | ||
} | ||
} |
Webdriver Manager [![Build Status](https://travis-ci.org/angular/webdriver-manager.png?branch=master)](https://travis-ci.org/angular/webdriver-manager) [![Join the chat at https://gitter.im/angular/webdriver-manager](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular/webdriver-manager?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
Webdriver Manager [![Build Status](https://travis-ci.org/angular/webdriver-manager.svg?branch=master)](https://travis-ci.org/angular/webdriver-manager) [![Join the chat at https://gitter.im/angular/webdriver-manager](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular/webdriver-manager?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
================= | ||
@@ -50,5 +50,6 @@ | ||
Mobile Support | ||
Other topics: | ||
-------------- | ||
See [`mobile.md`](mobile.md). | ||
- [mobile browser support](docs/mobile.md) | ||
- [protractor support](docs/protractor.md) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
284473
103
3873
55
21
21
7