UNPKG

@shackijj/karma-cbt-launcher

Version:

Custom launcher for Karma that allows testing remotely through CrossBrowserTesting.

184 lines (151 loc) 5.68 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* This code was originally taken and modified from Actano/Marcus Mennemeier's karma-cbt-launcher. The original code can be found at http://github.com/actano/karma-cbt-launcher */ const webdriver = require("selenium-webdriver"); const url = require('url'); const consoleLogger = require('./console-logger'); const cbtTunnel = require('./tunnel'); const session = require('./session'); let log = consoleLogger('karma-cbt-launcher'); let karmaLogger = false; // Handle x-ua-compatible option same as karma-ie-launcher(copy&paste): // // Usage : // customLaunchers: { // IE9: { // base: 'WebDriver', // config: webdriverConfig, // 'x-ua-compatible': 'IE=EmulateIE9' // } // } // // This is done by passing the option on the url, in response the Karma server will // set the following meta in the page. // <meta http-equiv="X-UA-Compatible" content="[VALUE]"/> const XUA = 'x-ua-compatible'; function handleXUaCompatible(args, urlObj) { if (args[XUA]) { const q = urlObj.query || {}; const query = _extends({}, q, { [XUA]: args[XUA] }); return _extends({}, urlObj, { query }); } return urlObj; } function handleTunnelHost(urlObj) { // use special hostname for tunnel const result = _extends({}, urlObj, { hostname: 'local' }); delete result.host; delete result.search; // url.format does not want search attribute return result; } const factory = (logger, baseBrowserDecorator, args, config) => { if (!karmaLogger) { karmaLogger = true; log = logger.create('karma-cbt'); session.setLogger(logger); } let cbtConfig = config.cbtConfig; const username = cbtConfig.username || process.env.CBT_USERNAME; const authkey = cbtConfig.authkey || process.env.CBT_AUTHKEY; cbtTunnel.username = username; cbtTunnel.authkey = authkey; // allows for webdriver to run tests concurrently for versions < 4 process.env.SELENIUM_PROMISE_MANAGER = 0; const spec = _extends({ name: 'Karma test', build: '' }, args); spec.name = spec.name || 'Karma test'; spec.build = spec.build || ''; const pseudoActivityInterval = spec.pseudoActivityInterval; delete spec.base; delete spec.config; delete spec.pseudoActivityInterval; let kill = null; const browser = {}; baseBrowserDecorator(browser); // The next three blocks of if statements build the string depending on what caps the user is defining. // get browser from browser_api_name or browserName and version from caps if (spec.browser_api_name) { browser.name = `${spec.browser_api_name} `; } else if (spec.browserName) { browser.name = `${spec.browserName} `; if (spec.version) { browser.name += `${spec.version} `; } } // get OS from os_api_name or platform caps if (spec.os_api_name) { browser.name += `on ${spec.os_api_name} `; } else if (spec.platform) { browser.name += `on ${spec.platform} `; } // get resolution from caps if it was defined if (spec.screen_resolution) { browser.name += `(${spec.screen_resolution}) `; } else if (spec.screenResolution) { browser.name += `(${spec.screenResolution}) `; } browser.name += 'via CrossBrowserTesting'; session.register(browser.id); const start = async (id, url) => { let cbtSession = null; let driver = null; let interval = false; const stop = async () => { const promises = []; if (cbtSession) { promises.push(cbtSession.stop()); } if (interval) { clearInterval(interval); } if (driver && driver.getSession()) { log.debug('Quitting selenium'); promises.push(driver.quit()); } await Promise.all(promises); }; try { cbtSession = await session.create(id); driver = cbtSession.configureBuilder(new webdriver.Builder().withCapabilities(spec)).build(); driver.getSession().then(seleniumSession => { cbtSession.setSeleniumId(seleniumSession.getId()); }); interval = pseudoActivityInterval && setInterval(() => { log.debug('Imitate activity'); driver.getTitle(); }, pseudoActivityInterval); driver.get(url); return stop; } catch (e) { log.error('Error starting %s', browser.name, e); await stop(); return async () => {}; } }; browser._start = myurl => { log.info('Connecting to %s', browser.name); const _url = url.format(handleTunnelHost(handleXUaCompatible(spec, url.parse(myurl, true)))); kill = start(browser.id, _url); }; browser.on('kill', async done => { if (!kill) { done(); return; } try { log.debug('Killing %s', browser.name); const stop = await kill; await stop(); browser._done(); done(); log.info('Killed %s.', browser.name); } catch (e) { done(e); } }); return browser; }; factory.$inject = ['logger', 'baseBrowserDecorator', 'args', 'config']; module.exports = factory;