blob: f5182c25a0506f766afc5b4d8e1c96cdbba5797c [file] [log] [blame] [edit]
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
/**
* This implementation is still in beta, and may change.
*
* Wrapper for getting information from the Selenium Manager binaries
*/
const { platform } = require('process')
const path = require('path')
const fs = require('fs')
const spawnSync = require('child_process').spawnSync
const { Capability } = require('../lib/capabilities')
const logging = require('../lib/logging')
const log_ = logging.getLogger(logging.Type.DRIVER)
let debugMessagePrinted = false
/**
* Determines the path of the correct Selenium Manager binary
* @returns {string}
*/
function getBinary () {
const directory = {
darwin: 'macos',
win32: 'windows',
cygwin: 'windows',
linux: 'linux',
}[platform]
const file =
directory === 'windows' ? 'selenium-manager.exe' : 'selenium-manager'
let seleniumManagerBasePath = path.join(__dirname, '..', '/bin')
const filePath = process.env.SE_MANAGER_PATH || path.join(
seleniumManagerBasePath, directory, file)
if (!fs.existsSync(filePath)) {
throw new Error(`Unable to obtain Selenium Manager at ${filePath}`)
}
if (!debugMessagePrinted) {
log_.debug(`Selenium Manager binary found at ${filePath}`)
debugMessagePrinted = true // Set the flag to true after printing the debug message
}
return filePath
}
/**
* Determines the path of the correct driver
* @param {Capabilities} options browser options to fetch the driver
* @returns {{browserPath: string, driverPath: string}} path of the driver and
* browser location
*/
function driverLocation (options) {
let args = ['--browser', options.getBrowserName(), '--language-binding',
'javascript', '--output', 'json']
if (options.getBrowserVersion() && options.getBrowserVersion() !== '') {
args.push('--browser-version', options.getBrowserVersion())
}
const vendorOptions =
options.get('goog:chromeOptions') ||
options.get('ms:edgeOptions') ||
options.get('moz:firefoxOptions')
if (vendorOptions && vendorOptions.binary && vendorOptions.binary !== '') {
args.push('--browser-path', path.resolve(vendorOptions.binary))
}
const proxyOptions = options.getProxy()
// Check if proxyOptions exists and has properties
if (proxyOptions && Object.keys(proxyOptions).length > 0) {
const httpProxy = proxyOptions['httpProxy']
const sslProxy = proxyOptions['sslProxy']
if (httpProxy !== undefined) {
args.push('--proxy', httpProxy)
} else if (sslProxy !== undefined) {
args.push('--proxy', sslProxy)
}
}
const smBinary = getBinary()
const spawnResult = spawnSync(smBinary, args)
let output
if (spawnResult.status) {
let errorMessage
if (spawnResult.stderr.toString()) {
errorMessage = spawnResult.stderr.toString()
}
if (spawnResult.stdout.toString()) {
try {
output = JSON.parse(spawnResult.stdout.toString())
logOutput(output)
errorMessage = output.result.message
} catch (e) {
errorMessage = e.toString()
}
}
throw new Error(
`Error executing command for ${smBinary} with ${args}: ${errorMessage}`
)
}
try {
output = JSON.parse(spawnResult.stdout.toString())
} catch (e) {
throw new Error(
`Error executing command for ${smBinary} with ${args}: ${e.toString()}`
)
}
// Once driverPath is available, delete browserVersion from payload
if (output.result.driver_path) {
options.delete(Capability.BROWSER_VERSION)
}
logOutput(output)
return {
driverPath: output.result.driver_path,
browserPath: output.result.browser_path,
}
}
function logOutput (output) {
for (const key in output.logs) {
if (output.logs[key].level === 'WARN') {
log_.warning(`${output.logs[key].message}`)
}
if (['DEBUG', 'INFO'].includes(output.logs[key].level)) {
log_.debug(`${output.logs[key].message}`)
}
}
}
// PUBLIC API
module.exports = { driverLocation }