diff --git a/lib/cli.ts b/lib/cli.ts index 225dd728f..f38d822f0 100644 --- a/lib/cli.ts +++ b/lib/cli.ts @@ -48,6 +48,8 @@ let allowedNames = [ 'sauceBuild', 'sauceSeleniumUseHttp', 'sauceSeleniumAddress', + 'experitestKey', + 'experitestCloudAddress', 'browserstackUser', 'browserstackKey', 'browserstackProxy', diff --git a/lib/config.ts b/lib/config.ts index c04849088..7224218a3 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -122,6 +122,21 @@ export interface Config { */ blockingProxyUrl?: string; + // ---- 3. To use remote browsers via Experitest ----------------------------- + + /** + * If the experitestKey is specified, seleniumServerJar will be + * ignored. The tests will be run remotely using Experitest Cloud. + */ + experitestKey?: string; + + /** + * Use experitestCloudAddress to customize the URL Protractor + * uses to connect to Experitest Cloud. + * For example 'http://192.168.1.1:8080' + */ + experitestCloudAddress?: string; + // ---- 3. To use remote browsers via Sauce Labs ----------------------------- /** diff --git a/lib/driverProviders/experitest.ts b/lib/driverProviders/experitest.ts new file mode 100644 index 000000000..530bef70c --- /dev/null +++ b/lib/driverProviders/experitest.ts @@ -0,0 +1,57 @@ +/* + * This is an implementation of the Experitest Driver Provider. + * It is responsible for setting up the account object, tearing + * it down, and setting up the driver correctly. + */ + +import {Session, WebDriver} from 'selenium-webdriver'; +import * as util from 'util'; + +import {Config} from '../config'; +import {Logger} from '../logger'; + +import {DriverProvider} from './driverProvider'; + +let logger = new Logger('experitest'); + +export class Experitest extends DriverProvider { + experitestServer_: any; + + constructor(config: Config) { + super(config); + } + + /** + * Hook to update the experitest test result + * @public + * @param {Object} update + * @return {q.promise} A promise that will resolve when the update is complete. + */ + updateJob(update: any): Promise { + let mappedDrivers = this.drivers_.map(async (driver: WebDriver) => { + const session = await driver.getSession(); + if (!update.passed) { + try { + driver.executeScript( + 'seetest:client.setReportStatus("Failed", "Failed","No stack trace")'); + } catch (e) { + logger.info('Error updating Experitest cloud with test status'); + } + } + }); + return Promise.all(mappedDrivers); + } + + /** + * Configure and launch (if applicable) the object's environment. + * @public + * @return {q.promise} A promise which will resolve when the environment is + * ready to test. + */ + protected async setupDriverEnv(): Promise { + this.config_.capabilities['accessKey'] = this.config_.experitestKey; + this.config_.seleniumAddress = this.config_.experitestCloudAddress + '/wd/hub'; + + logger.info('Using Experitest cloud server at ' + this.config_.seleniumAddress); + } +} diff --git a/lib/driverProviders/index.ts b/lib/driverProviders/index.ts index 25fcabcf6..e8df53a03 100644 --- a/lib/driverProviders/index.ts +++ b/lib/driverProviders/index.ts @@ -6,6 +6,7 @@ export * from './hosted'; export * from './local'; export * from './mock'; export * from './sauce'; +export * from './experitest'; export * from './testObject'; export * from './kobiton'; @@ -18,6 +19,7 @@ import {Hosted} from './hosted'; import {Local} from './local'; import {Mock} from './mock'; import {Sauce} from './sauce'; +import {Experitest} from './experitest'; import {TestObject} from './testObject'; import {Kobiton} from './kobiton'; @@ -52,6 +54,9 @@ export let buildDriverProvider = (config: Config): DriverProvider => { } else if (config.sauceUser && config.sauceKey) { driverProvider = new Sauce(config); logWarnings('sauce', config); + } else if (config.experitestKey && config.experitestCloudAddress) { + driverProvider = new Experitest(config); + logWarnings('experitest', config); } else if (config.seleniumServerJar) { driverProvider = new Local(config); logWarnings('local', config); @@ -103,6 +108,12 @@ export let logWarnings = (providerType: string, config: Config): void => { if ('sauce' !== providerType && config.sauceKey) { warnList.push('sauceKey'); } + if ('experitest' !== providerType && config.experitestKey) { + warnList.push('experitestKey'); + } + if ('experitest' !== providerType && config.experitestCloudAddress) { + warnList.push('experitestCloudAddress'); + } if ('local' !== providerType && config.seleniumServerJar) { warnList.push('seleniumServerJar'); } diff --git a/spec/driverProviderTest.js b/spec/driverProviderTest.js index a10237869..bdfe4ed58 100644 --- a/spec/driverProviderTest.js +++ b/spec/driverProviderTest.js @@ -8,6 +8,7 @@ * - if you want to test saucelabs, test with --sauceUser and --sauceKey * - if you want to test browserstack driverProvider, test with --browserstackUser and --browserstackKey + * - if you want to test experitest, test with --experitestKey and --experitestCloudAddress * You should verify that there are no lingering processes when these tests * complete. */ @@ -20,6 +21,7 @@ const Hosted = require('../built/driverProviders/hosted').Hosted; const Local = require('../built/driverProviders/local').Local; const Sauce = require('../built/driverProviders/sauce').Sauce; const BrowserStack = require('../built/driverProviders/browserStack').BrowserStack; +const Experitest = require('../built/driverProviders/experitest').Experitest; const testDriverProvider = async (driverProvider) => { await driverProvider.setupEnv(); @@ -143,3 +145,20 @@ if (argv.browserstackUser && argv.browserstackKey) { throw err; }); } + +if (argv.experitestKey && argv.experitestCloudAddress) { + const experitestConfig = { + experitestKey: argv.experitestKey, + experitestCloudAddress: argv.experitestCloudAddress, + capabilities: { + 'browserName': 'chrome', + } + }; + testDriverProvider(new Experitest(experitestConfig)). + then(function() { + console.log('experitest.dp working!'); + }, function(err) { + console.log('experitest.dp failed with ' + err); + throw err; + }); +}