Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/lambdatest grid #5260

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 13 additions & 6 deletions docs/server-setup.md
Expand Up @@ -55,37 +55,37 @@ To connect to a running instance of a standalone Selenium Server, set this optio

- `seleniumAddress` - Connect to a running instance of a standalone Selenium Server. The address will be a URL.

Please note that if you set seleniumAddress, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `browserstackUser`, `browserstackKey`, `sauceUser` and `sauceKey` will be ignored.
Please note that if you set seleniumAddress, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `browserstackUser`, `browserstackKey`, `sauceUser`, `sauceKey`, `lambdaUsername` and `lambdaAccessKey` will be ignored.


Remote Selenium Server
----------------------

To run your tests against a remote Selenium Server, you will need an account with a service that hosts the server (and the browser drivers). Protractor has built in support for [BrowserStack](https://www.browserstack.com) , [Sauce Labs](http://www.saucelabs.com) and [TestObject](https://www.testobject.com).
To run your tests against a remote Selenium Server, you will need an account with a service that hosts the server (and the browser drivers). Protractor has built in support for [BrowserStack](https://www.browserstack.com) , [Sauce Labs](http://www.saucelabs.com) and [TestObject](https://www.testobject.com) , [TestObject](https://www.testobject.com) and [LambdaTest](https://www.lambdatest.com).

**Using TestObject as remote Selenium Server**

In your config file, set these options:
- `testobjectUser` - The username for your TestObject account.
- `testobjectKey` - The key for your TestObject account.

Please note that if you set `testobjectUser` and `testobjectKey`, the settings for `kobitonUser`, `kobitonKey`, `browserstackUser`, `browserstackKey`, `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser` and `sauceKey` will be ignored.
Please note that if you set `testobjectUser` and `testobjectKey`, the settings for `kobitonUser`, `kobitonKey`, `browserstackUser`, `browserstackKey`, `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser`, `sauceKey`, `lambdaUsername` and `lambdaAccessKey` will be ignored.

**Using Kobiton as remote Selenium Server**

In your config file, set these options:
- `kobitonUser` - The username for your Kobiton account.
- `kobitonKey` - The API key from your Kobiton account.

Please note that if you set `kobitonUser` and `kobitonKey`, the settings for `browserstackUser`, `browserstackKey`, `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser` and `sauceKey` will be ignored.
Please note that if you set `kobitonUser` and `kobitonKey`, the settings for `browserstackUser`, `browserstackKey`, `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser`, `sauceKey`, `lambdaUsername` and `lambdaAccessKey` will be ignored.

**Using BrowserStack as remote Selenium Server**

In your config file, set these options:
- `browserstackUser` - The username for your BrowserStack account.
- `browserstackKey` - The key for your BrowserStack account.

Please note that if you set `browserstackUser` and `browserstackKey`, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser` and `sauceKey` will be ignored.
Please note that if you set `browserstackUser` and `browserstackKey`, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `sauceUser`, `sauceKey`, `lambdaUsername` and `lambdaAccessKey` will be ignored.

You can optionally set the `name` property in a capability in order to give the jobs a name on the server. Otherwise they will just be allotted a random hash.

Expand All @@ -95,10 +95,17 @@ In your config file, set these options:
- `sauceUser` - The username for your Sauce Labs account.
- `sauceKey` - The key for your Sauce Labs account.

Please note that if you set `sauceUser` and `sauceKey`, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `browserstackUser` and `browserstackKey` will be ignored.
Please note that if you set `sauceUser` and `sauceKey`, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `browserstackUser`, `browserstackKey`, `lambdaUsername` and `lambdaAccessKey` will be ignored.

You can optionally set the `name` property in a capability in order to give the jobs a name on the server. Otherwise they will just be called `Unnamed Job`.

**Using LambdaTest as remote Selenium Server**

In your config file, set these options:
- `lambdaUsername` - The username for your LambdaTest account.
- `lambdaAccessKey` - The access key for your LambdaTest account.

Please note that if you set `lambdaUsername` and `lambdaAccessKey`, the settings for `seleniumServerJar`, `seleniumPort`, `seleniumArgs`, `testobjectUser`, `testobjectKey`, `sauceUser`, `sauceKey`, `browserstackUser`, `browserstackKey`, `kobitonUser` and `kobitonKey` will be ignored.

Connecting Directly to Browser Drivers
--------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions lib/cli.ts
Expand Up @@ -55,6 +55,8 @@ let allowedNames = [
'kobitonKey',
'testobjectUser',
'testobjectKey',
'lambdaUsername',
'lambdaAccessKey',
'directConnect',
'firefoxPath',
'noGlobals',
Expand Down
21 changes: 19 additions & 2 deletions lib/config.ts
Expand Up @@ -17,7 +17,9 @@ export interface Config {
// 3. sauceUser/sauceKey - to use remote Selenium Servers via Sauce Labs.
// 4. browserstackUser/browserstackKey - to use remote Selenium Servers via
// BrowserStack.
// 5. directConnect - to connect directly to the browser Drivers.
// 5. lambdaUsername/lambdaAccessKey - to use remote Selenium Servers via
// Lambdatest.
// 6. directConnect - to connect directly to the browser Drivers.
// This option is only available for Firefox and Chrome.
//
// ---- 1. To start a standalone Selenium Server locally ---------------------
Expand Down Expand Up @@ -220,7 +222,22 @@ export interface Config {
*/
browserstackProxy?: string;

// ---- 7. To connect directly to Drivers ------------------------------------
// ---- 7. To use remote browsers via LambdaTest ---------------------------

/**
* If lambdaUsername and lambdaAccessKey are specified, kobitonUser, kobitonKey, testobjectUser,
* testojbectKey, browserstackUser, browserStackKey and seleniumServerJar will be ignored. The
* tests will be run remotely using LambdaTest.
*/
lambdaUsername?: string;
/**
* If lambdaUsername and lambdaAccessKey are specified, kobitonUser, kobitonKey, testobjectUser,
* testojbectKey, browserStackUser, browserStackKey and seleniumServerJar will be ignored. The
* tests will be run remotely using LambdaTest.
*/
lambdaAccessKey?: string;

// ---- 8. To connect directly to Drivers ------------------------------------

/**
* If true, Protractor will connect directly to the browser Drivers
Expand Down
11 changes: 11 additions & 0 deletions lib/driverProviders/index.ts
Expand Up @@ -8,6 +8,7 @@ export * from './mock';
export * from './sauce';
export * from './testObject';
export * from './kobiton';
export * from './lambdaTest';


import {AttachSession} from './attachSession';
Expand All @@ -20,6 +21,7 @@ import {Mock} from './mock';
import {Sauce} from './sauce';
import {TestObject} from './testObject';
import {Kobiton} from './kobiton';
import {LambdaTest} from './lambdaTest';

import {Config} from '../config';
import {Logger} from '../logger';
Expand Down Expand Up @@ -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.lambdaUsername && config.lambdaAccessKey) {
driverProvider = new LambdaTest(config);
logWarnings('lambdaTest', config);
} else if (config.seleniumServerJar) {
driverProvider = new Local(config);
logWarnings('local', config);
Expand Down Expand Up @@ -103,6 +108,12 @@ export let logWarnings = (providerType: string, config: Config): void => {
if ('sauce' !== providerType && config.sauceKey) {
warnList.push('sauceKey');
}
if ('lambdaTest' !== providerType && config.lambdaUsername) {
warnList.push('lambdaUsername');
}
if ('lambdaTest' !== providerType && config.lambdaAccessKey) {
warnList.push('lambdaAccessKey');
}
if ('local' !== providerType && config.seleniumServerJar) {
warnList.push('seleniumServerJar');
}
Expand Down
64 changes: 64 additions & 0 deletions lib/driverProviders/lambdaTest.ts
@@ -0,0 +1,64 @@
/*
* This is an implementation of the LambdaTest Driver Provider.
* It is responsible for setting up the account object, tearing
* it down, and setting up the driver correctly.
*/
import {WebDriver} from 'selenium-webdriver';
import * as util from 'util';

import {Config} from '../config';
import {Logger} from '../logger';

import {DriverProvider} from './driverProvider';

Logger.setWrite(2, 'lambda_protractor.log');
const lambdaRestClient = require('@lambdatest/node-rest-client');
let logger = new Logger('lambdatest');

export class LambdaTest extends DriverProvider {
lambdaAutomationClient: any;

constructor(config: Config) {
super(config);
}

/**
* Hook to update the LambdaTest job status.
* @public
* @param {Object} update
* @return {Promise} A promise that will resolve when the update is complete.
*/
updateJob(update: any): Promise<any> {
let mappedDrivers = this.drivers_.map(async (driver: WebDriver) => {
const session = await driver.getSession();
const statusObj = {status_ind: update.passed ? 'passed' : 'failed'};
this.lambdaAutomationClient.updateSessionById(session.getId(), statusObj, (error: Error) => {
if (error) {
throw new Error(
'Error while updating LambdaTest passed/failed status: ' + util.inspect(error));
}
});
});
return Promise.all(mappedDrivers);
}

/**
* Configure and launch (if applicable) the object's environment.
* @return {promise} A promise which will resolve when the environment is
* ready to test.
*/
protected async setupDriverEnv(): Promise<any> {
this.config_.capabilities['user'] = this.config_.lambdaUsername;
this.config_.capabilities['accessKey'] = this.config_.lambdaAccessKey;
this.config_.seleniumAddress = 'https://hub.lambdatest.com/wd/hub';
this.lambdaAutomationClient = lambdaRestClient.AutomationClient(
{username: this.config_.lambdaUsername, accessKey: this.config_.lambdaAccessKey});

// Append filename to capabilities.name so that it's easier to identify
// tests.
this.config_.capabilities.name = this.config_.capabilities.name || '';
this.config_.capabilities.name += ':' + this.config_.specs.toString().replace(/^.*[\\\/]/, '');

logger.info(`Using LambdaTest selenium server at ${this.config_.seleniumAddress}`);
}
}