UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

333 lines (239 loc) 12.4 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Class('Siesta.Launcher.Runner.WebDriverNodeJS', { isa : Siesta.Launcher.Runner.BaseRunner, does : [ Siesta.Launcher.Runner.WebDriverNodeJS.CanLockXvfbDisplayFile ], has : { pagePollInterval : 1000, resolutionCapName : 'resolution', maxWorkers : 1, capabilities : { lazy : 'this.buildCapabilities' } }, methods : { // this the proxy to be used by the browser getBrowserProxyStr : function () { var options = this.dispatcher.options if (options.coverage && (options.sl || options.bs)) { // for cloud setup with coverage enabled proxy configuration is passed as tunnel binary // options, not set in Selenium return null } else { return options.coverage ? '127.0.0.1:' + this.dispatcher.instrumentationProxyPort : this.launcher.optionsWrapper.getProxyHostPort() } }, buildWebDriverBuilder : function (xvfbLockResult) { var launcher = this.launcher var builder = new selenium.Builder().withCapabilities(this.getCapabilities()) var options = this.dispatcher.options var displayNum = xvfbLockResult && xvfbLockResult.displayNum var isHeadless = options.headless && options.headless != 'false' if (options[ 'host' ]) { // prepend potentially missing "http://" prefix in "constructURL" var url = this.launcher.constructUrl(options[ 'host' ]) if (!/\/wd\/hub\s*$/i.test(url)) url += ':' + (options[ 'port' ] || 4444) + '/wd/hub' builder.usingServer(url) } var browserArgs = options[ 'browser-arg' ] if (options.browser == 'chrome') { var chrome = require('selenium-webdriver/chrome') var chromeOptions = new chrome.Options() if (options.xvfb && launcher.isLinux) { chromeOptions.setChromeBinaryPath(launcher.binDir + 'xvfb/chrome') chromeOptions.addArguments('DISPLAY_NUM=' + displayNum) } if (options[ 'touch-events' ]) chromeOptions.addArguments('touch-events') // chromeOptions.addArguments('disable-dev-shm-usage') // chromeOptions.addArguments('no-sandbox') if (isHeadless) chromeOptions.headless() if (this.launcher.isWindows) chromeOptions.addArguments('disable-gpu') for (var i = 0; i < browserArgs.length; i++) { chromeOptions.addArguments(browserArgs[ i ]) } var proxyStr = this.getBrowserProxyStr() if (proxyStr) { // proxy settings on the capabilities object are ignored by Chrome driver, // should be set on ChromeOptions instead chromeOptions.setProxy({ proxyType : 'manual', ftpProxy : proxyStr, httpProxy : proxyStr, sslProxy : proxyStr, noProxy : '' }); } builder.setChromeOptions(chromeOptions) } if (options.browser == 'firefox') { var firefox = require('selenium-webdriver/firefox') var firefoxOptions = new firefox.Options() if (options.xvfb && launcher.isLinux) { firefoxOptions.addArguments('DISPLAY_NUM=' + displayNum) firefoxOptions.setBinary(launcher.binDir + 'xvfb/firefox') } for (i = 0; i < browserArgs.length; i++) { firefoxOptions.addArguments(browserArgs[ i ]) } if (isHeadless) firefoxOptions.headless() if (options[ 'firefox-profile' ]) firefoxOptions.setProfile(options[ 'firefox-profile' ]) var prefs = options[ 'ff-pref'] || [] for (i = 0; i < prefs.length; i++) { var match = /(.*?)=(.*)/.exec(prefs[ i ]) if (match) { var value try { value = JSON.parse(match[ 2 ]) } catch (e) { value = match[ 2 ] } firefoxOptions.setPreference(match[ 1 ], value) } } firefoxOptions.setPreference('security.insecure_password.ui.enabled', false) firefoxOptions.setPreference('security.insecure_field_warning.contextual.enabled', false) builder.setFirefoxOptions(firefoxOptions) } if (options.browser == 'internet explorer') { // the call to "setIeOptions" changes the "platform" capability to "WINDOWS" // (as implemented in the "selenium-webdriver") // this breaks the SL testing (which requires "platform" to be set to "WINDOWS 7") // only supporting for local testing for now, until someone complains if (!options.host && browserArgs.length) { var ie = require('selenium-webdriver/ie') var ieOptions = new ie.Options() if (browserArgs.length) ieOptions.forceCreateProcessApi(true) for (i = 0; i < browserArgs.length; i++) { ieOptions.addArguments(browserArgs[ i ]) } // this call changes the "platform" capability to "WINDOWS" (as implemented in the "selenium-webdriver") builder.setIeOptions(ieOptions) } } if (options.browser == 'MicrosoftEdge') { // var edge = require('selenium-webdriver/edge') // var edgeOptions = new edge.Options() // // edgeOptions.setPageLoadStrategy('normal') // // // this call changes the "platform" capability to "WINDOWS" (as implemented in the "selenium-webdriver") // builder.setEdgeOptions(edgeOptions) } var proxyStr = this.launcher.optionsWrapper.getProxyHostPort() if (proxyStr) { // this is a proxy to use for connection to the remote WebDriver instance, // NOT the proxy, which will be used by the browser builder.usingWebDriverProxy('http://' + proxyStr) } return builder }, buildCapabilities : function () { var options = this.dispatcher.options var capabilities = new selenium.Capabilities() var width = options.width || Siesta.Launcher.Page.WebDriverNodeJS.prototype.width var height = options.height || Siesta.Launcher.Page.WebDriverNodeJS.prototype.height capabilities.set(this.resolutionCapName, width + 'x' + height) // MS Edge driver chokes on the `acceptInsecureCerts` capability if (options.browser != 'MicrosoftEdge' && options.browser != 'internet explorer' && options.browser != 'safari') { // accept invalid /untrusted certificates, which is common thing during development capabilities.set(selenium.Capability.ACCEPT_INSECURE_TLS_CERTS, true) // generic webdriver // some backward-compat name? required for browserstack capabilities.set('acceptSslCerts', true) } var caps = options.cap for (var i = 0; i < caps.length; i++) { var match = /(.*?)=(.*)/.exec(caps[ i ]) if (match) { var value var valueStr = match[ 2 ] || '' try { value = valueStr == '' ? '' : JSON.parse(valueStr) } catch (e) { value = valueStr } capabilities.set(match[ 1 ] || '', value) } } // intentially overwrite any user-provided "browserName" which has been normalized capabilities.set('browserName', options.browser) var proxyStr = this.getBrowserProxyStr() if (proxyStr) { // oddly enough this setting is ignored by Chrome driver, instead the one from the ChromeOptions is used capabilities.setProxy({ proxyType : 'manual', ftpProxy : proxyStr, httpProxy : proxyStr, sslProxy : proxyStr }); } return capabilities }, // promised method createDriverInstance : function (builder, capabilities, xvfbLockResult, level) { level = level || 0 var options = this.dispatcher.options var me = this this.debug("Trying to create a WebDriver instance for browser: " + options.browser) var driver = builder.build() return driver.getSession().then(function () { me.debug("WebDriver instantiated successfully") var config = { runner : me, launcher : me.launcher, dispatcher : me.dispatcher, pollInterval : me.pagePollInterval, driver : driver, xvfbLockResult : xvfbLockResult } if (options.width) config.width = options.width if (options.height) config.height = options.height return new Siesta.Launcher.Page.WebDriverNodeJS(config) }, function (e) { me.debug("WebDriver instantiation failed: " + options.browser + ", level : " + level) me.debug("Failed with: " + e) var canTryToRepeat = me.onWebDriverInstatiationException(e, builder, capabilities) // try to instantiate the driver 3 times, then throw exception if (level < 2 && canTryToRepeat) { me.debug("Trying again") return me.createDriverInstance(builder, capabilities, xvfbLockResult, level + 1) } else { xvfbLockResult && xvfbLockResult.release() throw e } }) }, onWebDriverInstatiationException : function (e, builder, capabilities) { if (/required parameter 'capabilities'/.test(e)) { const safari = require('selenium-webdriver/safari') builder.usingServer(new safari.ServiceBuilder().addArguments('--legacy').build().start()) } return true }, createPage : function (callback) { var me = this var options = this.dispatcher.options var cont if (options.xvfb) { cont = this.lockXvfbFile() } else cont = Promise.resolve() cont.then(function (xvfbLockResult) { var capabilities = me.getCapabilities() var builder = me.buildWebDriverBuilder(xvfbLockResult) me.createDriverInstance(builder, capabilities, xvfbLockResult).then(function (page) { callback(null, page) }, function (e) { callback(e, null) }) }, function (e) { callback(e, null) }) } } })