From 1c02e7302283ba99830ed86a650287889aeab07a Mon Sep 17 00:00:00 2001 From: Ryan Lovelett Date: Thu, 2 Mar 2017 16:53:43 -0500 Subject: [PATCH] Use the Safari 10 WebDriver to run tests For all the reasons addressed in a WebKit blog post, https://webkit.org/blog/6901/webdriver-support-in-safari-10/, this method should be preferred over the previous method. --- index.js | 122 ++++++++++++++++++++++++++++++++++++++++++++++++--- package.json | 4 +- safari.html | 13 ------ 3 files changed, 118 insertions(+), 21 deletions(-) delete mode 100644 safari.html diff --git a/index.js b/index.js index d7337bc..bf3a0e2 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,116 @@ -var fs = require('fs'); -var path = require('path'); +var wd = require('wd'); +var url = require('url'); +var Safari = function(baseBrowserDecorator, args, logger) { + baseBrowserDecorator(this); + + var config = Object.assign({ + protocol: 'http:', + hostname: '127.0.0.1', + port: 4444, + pathname: '/' + }, args.config); + + var webDriver = url.format(config); + this.name = 'Safari via WebDriver at ' + webDriver; + var log = logger.create(this.name); + + log.debug(JSON.stringify(args)); + log.debug(JSON.stringify(config)); + + this.driver = wd.remote(config); + + this.driver.on('status', (info) => { + log.debug('Status: ' + info); + }); + + this.driver.on('command', (eventType, command, response) => { + log.debug('[command] ' + eventType + ' ' + command + ' ' + (response || '')); + }); + + this.driver.on('http', (meth, path, data) => { + log.debug('[http] ' + meth + ' ' + path + ' ' + (data || '')); + }); + + this._getOptions = function() { + return [ + "-p", config.port.toString() + ]; + } + + const superStart = this._start; + // Stop the default start from occuring + this._start = () => {}; + + /** + * This launcher works by checking to see if there is a `/usr/bin/safaridriver` instance running. + * It is determined to be running if the web driver API can be reached on the configured host and port. + * If it is then it it launches the Karma test runner in a new session. If it is not, it then attempts + * to start its own new instance of `/usr/bin/safaridriver` and then connect the Karma test runner in + * a new session. + * + * @param {string} url The URL that the Karma server is listening on. + */ + this.on('start', function(url) { + var self = this; + + var attempts = 0; + // TODO: It would be nice if this was configurable + const MAX_ATTEMPTS = 10; + // TODO: It would be nice if this was configurable + const SLEEP_DURATION = 500; + + function attachKarma(error) { + attempts += 1; + if (error && error.code === 'ECONNREFUSED' && attempts === 1) { + log.debug('attachKarma ' + attempts + ' of ' + MAX_ATTEMPTS); + log.debug(self._getCommand() + ' is not running.'); + log.debug('Attempting to start ' + self._getCommand() + ' ' + self._getOptions(url).join(' ')); + superStart(url); + self.driver.init({ browserName: 'safari' }, attachKarma); + } else if (error && error.code === 'ECONNREFUSED' && attempts <= MAX_ATTEMPTS) { + log.debug('attachKarma ' + attempts + ' of ' + MAX_ATTEMPTS); + log.debug('Going to give the driver time to start-up. Sleeping for ' + SLEEP_DURATION + 'ms.'); + setTimeout(function() { + log.debug('Awoke to retry.'); + self.driver.init({ browserName: 'safari' }, attachKarma); + }, SLEEP_DURATION); + } else if (error) { + log.error('Could not connect to Safari.'); + log.error(error); + } else { + log.debug('Connected to Safari WebDriver'); + log.debug('Connecting to ' + url); + self.driver.get(url); + } + } -var SafariBrowser = function(baseBrowserDecorator) { + self.driver.init({ browserName: 'safari' }, attachKarma); + }); + + this.on('kill', (done) => { + if (this.driver) { + this.driver.quit(function() { + done(); + }); + } else { + done(); + } + }); +}; + +Safari.prototype = { + name: 'Safari', + + DEFAULT_CMD: { + darwin: '/usr/bin/safaridriver' + }, + ENV_CMD: 'SAFARI_BIN' +}; + +Safari.$inject = ['baseBrowserDecorator', 'args', 'logger']; + +var SafariLegacy = function(baseBrowserDecorator) { baseBrowserDecorator(this); this._start = function(url) { @@ -20,7 +128,7 @@ var SafariBrowser = function(baseBrowserDecorator) { }; }; -SafariBrowser.prototype = { +SafariLegacy.prototype = { name: 'Safari', DEFAULT_CMD: { @@ -30,10 +138,10 @@ SafariBrowser.prototype = { ENV_CMD: 'SAFARI_BIN' }; -SafariBrowser.$inject = ['baseBrowserDecorator']; - +SafariLegacy.$inject = ['baseBrowserDecorator']; // PUBLISH DI MODULE module.exports = { - 'launcher:Safari': ['type', SafariBrowser] + 'launcher:Safari': ['type', Safari], + 'launcher:SafariLegacy': ['type', SafariLegacy] }; diff --git a/package.json b/package.json index 75d3ecc..9d9c2e7 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "safari" ], "author": "Vojta Jina ", - "dependencies": {}, + "dependencies": { + "wd": "^1.10.3" + }, "peerDependencies": { "karma": ">=0.9" }, diff --git a/safari.html b/safari.html deleted file mode 100644 index ad0355f..0000000 --- a/safari.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Safari REDIRECTS to Testacular - - - - - - -