import type { Capabilities, Options } from '@wdio/types'
const DEFAULT_HOSTNAME = '127.0.0.1'
const DEFAULT_PORT = 4444
const DEFAULT_PROTOCOL = 'http'
const DEFAULT_PATH = '/'
const LEGACY_PATH = '/wd/hub'
const REGION_MAPPING = {
'us': 'us-west-1.',
'eu': 'eu-central-1.',
'eu-central-1': 'eu-central-1.',
'us-east-4': 'us-east-4.',
}
interface BackendConfigurations {
port?: number
hostname?: string
user?: string
key?: string
protocol?: string
region?: Options.SauceRegions
path?: string
capabilities?: Capabilities.RequestedStandaloneCapabilities
}
function getSauceEndpoint (
region: keyof typeof REGION_MAPPING,
{ isRDC, isVisual }: { isRDC?: boolean, isVisual?: boolean } = {}
) {
const shortRegion = REGION_MAPPING[region] ? region : 'us'
if (isRDC) {
return `${shortRegion}1.appium.testobject.com`
} else if (isVisual) {
return 'hub.screener.io'
}
return `ondemand.${REGION_MAPPING[shortRegion]}saucelabs.com`
}
* helper to detect the Selenium backend according to given capabilities
*/
export default function detectBackend(options: BackendConfigurations = {}) {
const { port, hostname, user, key, protocol, region, path, capabilities } = options
* browserstack
* e.g. zHcv9sZ39ip8ZPsxBVJ2
*/
if (typeof user === 'string' && typeof key === 'string' && key.length === 20) {
return {
protocol: protocol || 'https',
hostname: hostname || 'hub-cloud.browserstack.com',
port: port || 443,
path: path || LEGACY_PATH
}
}
* testingbot
* e.g. ec337d7b677720a4dde7bd72be0bfc67
*/
if (typeof user === 'string' && typeof key === 'string' && key.length === 32) {
return {
protocol: protocol || 'https',
hostname: hostname || 'hub.testingbot.com',
port: port || 443,
path: path || LEGACY_PATH
}
}
* Sauce Labs
* e.g. 50aa152c-1932-B2f0-9707-18z46q2n1mb0
*
* For Sauce Labs Legacy RDC we only need to determine if the sauce option has a `testobject_api_key`.
* Same for Sauce Visual where an apiKey can be passed in through the capabilities (soon to be legacy too).
*/
const isVisual = Boolean(!Array.isArray(capabilities) && capabilities && (capabilities as WebdriverIO.Capabilities)['sauce:visual']?.apiKey)
if ((typeof user === 'string' && typeof key === 'string' && key.length === 36) ||
isVisual
) {
const sauceRegion = region as keyof typeof REGION_MAPPING
return {
protocol: protocol || 'https',
hostname: hostname || getSauceEndpoint(sauceRegion, { isVisual }),
port: port || 443,
path: path || LEGACY_PATH
}
}
* Lambdatest
* e.g. cYAjKrqGwyPjPQv41ICDF4C5OjlxzA9epZsnugVJJxqOReWRWU
*/
if (typeof user === 'string' && typeof key === 'string' && key.length === 50) {
return {
protocol: protocol || DEFAULT_PROTOCOL,
hostname: hostname || 'hub.lambdatest.com',
port: port || 80,
path: path || LEGACY_PATH
}
}
if (
* user and key are set in config
*/
(typeof user === 'string' || typeof key === 'string') &&
* but no custom WebDriver endpoint was configured
*/
!hostname
) {
throw new Error(
'A "user" or "key" was provided but could not be connected to a ' +
'known cloud service (Sauce Labs, Browerstack, Testingbot or Lambdatest). ' +
'Please check if given user and key properties are correct!'
)
}
* default values if on of the WebDriver criticial options is set
*/
if (hostname || port || protocol || path) {
return {
hostname: hostname || DEFAULT_HOSTNAME,
port: port || DEFAULT_PORT,
protocol: protocol || DEFAULT_PROTOCOL,
path: path || DEFAULT_PATH
}
}
* no cloud provider detected, pass on provided params and eventually
* fallback to DevTools protocol
*/
return { hostname, port, protocol, path }
}