Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(driverProvider): Add useExistingWebDriver driver provider (#4756)
Browse files Browse the repository at this point in the history
  • Loading branch information
andyjack authored and qiyigg committed Aug 16, 2018
1 parent 249e657 commit 7b08083
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 0 deletions.
34 changes: 34 additions & 0 deletions docs/server-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,37 @@ Protractor can test directly against Chrome and Firefox without using a Selenium
- `directConnect: true` - Your test script communicates directly Chrome Driver or Firefox Driver, bypassing any Selenium Server. If this is true, settings for `seleniumAddress` and `seleniumServerJar` will be ignored. If you attempt to use a browser other than Chrome or Firefox an error will be thrown.

The advantage of directly connecting to browser drivers is that your test scripts may start up and run faster.

Re-using an Existing WebDriver
------------------------------

The use case for re-using an existing WebDriver is when you have existing
`selenium-webdriver` code and are already in control of how the WebDriver is
created, but would also like Protractor to use the same browser, so you can
use protractor's element locators and the rest of its API. This could be
done with the `attachSession` driver provider, but the `attachSession` API is
being removed in `selenium-webdriver` 4.0.0.

Instead of a protractor config file, you create a config object in your test
setup code, and add your already-created WebDriver object and base URL.

```javascript
const ProtractorConfigParser = require('protractor/built/configParser').ConfigParser;
const ProtractorRunner = require('protractor/built/runner').Runner;

const ptorConfig = new ProtractorConfigParser().config_;
ptorConfig.baseUrl = myExistingBaseUrl;
ptorConfig.seleniumWebDriver = myExistingWebDriver;
ptorConfig.noGlobals = true; // local preference

// looks similar to protractor/built/runner.js run()
const ptorRunner = new ProtractorRunner(ptorConfig);
ptorRunner.driverProvider_.setupEnv();
const browser = ptorRunner.createBrowser();
ptorRunner.setupGlobals_(browser); // now you can access protractor.$, etc.
```

Note that this driver provider leaves you in control of quitting the driver,
but that also means Protractor API calls that expect the driver to properly
quit and/or restart the browser, e.g. `restart`, `restartSync`, and
`forkNewDriverInstance`, will not behave as documented.
8 changes: 8 additions & 0 deletions lib/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {WebDriver} from 'selenium-webdriver';

import {PluginConfig} from './plugins';

export interface Config {
Expand Down Expand Up @@ -228,6 +230,12 @@ export interface Config {
*/
firefoxPath?: string;

// ---- 8. To re-use an existing WebDriver object ---------------------------

// This would not appear in a configuration file. Instead a configuration
// object would be created that includes an existing webdriver.
seleniumWebDriver?: WebDriver;

// ---------------------------------------------------------------------------
// ----- What tests to run ---------------------------------------------------
// ---------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions lib/driverProviders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './mock';
export * from './sauce';
export * from './testObject';
export * from './kobiton';
export * from './useExistingWebDriver';


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 {UseExistingWebDriver} from './useExistingWebDriver';

import {Config} from '../config';
import {Logger} from '../logger';
Expand All @@ -32,6 +34,9 @@ export let buildDriverProvider = (config: Config): DriverProvider => {
if (config.directConnect) {
driverProvider = new Direct(config);
logWarnings('directConnect', config);
} else if (config.seleniumWebDriver) {
driverProvider = new UseExistingWebDriver(config);
logWarnings('useExistingWebDriver', config);
} else if (config.seleniumAddress) {
if (config.seleniumSessionId) {
driverProvider = new AttachSession(config);
Expand Down Expand Up @@ -109,6 +114,9 @@ export let logWarnings = (providerType: string, config: Config): void => {
if ('mock' !== providerType && config.mockSelenium) {
warnList.push('mockSelenium');
}
if ('useExistingWebDriver' !== providerType && config.seleniumWebDriver) {
warnList.push('seleniumWebDriver');
}
if (warnList.length !== 0) {
logger.warn(warnInto + warnList.join(', '));
}
Expand Down
57 changes: 57 additions & 0 deletions lib/driverProviders/useExistingWebDriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* This is an implementation of the Use Existing WebDriver Driver Provider.
* It is responsible for setting up the account object, tearing it down, and
* setting up the driver correctly.
*/
import * as q from 'q';
import {promise as wdpromise, WebDriver} from 'selenium-webdriver';

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

import {DriverProvider} from './driverProvider';

const http = require('selenium-webdriver/http');

let logger = new Logger('useExistingWebDriver');

export class UseExistingWebDriver extends DriverProvider {
constructor(config: Config) {
super(config);
}

/**
* Configure and launch (if applicable) the object's environment.
* @return {q.promise} A promise which will resolve when the environment is
* ready to test.
*/
protected setupDriverEnv(): q.Promise<any> {
const defer = q.defer();
this.config_.seleniumWebDriver.getSession().then((session) => {
logger.info('Using session id - ' + session.getId());
return defer.resolve();
});
return q(undefined);
}

/**
* Getting a new driver by attaching an existing session.
*
* @public
* @return {WebDriver} webdriver instance
*/
getNewDriver(): WebDriver {
const newDriver = this.config_.seleniumWebDriver;
this.drivers_.push(newDriver);
return newDriver;
}

/**
* Maintains the existing session and does not quit the driver.
*
* @public
*/
quitDriver(): wdpromise.Promise<void> {
return wdpromise.when(undefined);
}
}
2 changes: 2 additions & 0 deletions scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ var passingTests = [
'node built/cli.js spec/built/noCFBasicConf.js --useBlockingProxy',
'node built/cli.js spec/built/noCFPluginConf.js',
//'node scripts/driverProviderAttachSession.js',
'node built/cli.js spec/driverProviderUseExistingWebDriver.js',
'node built/cli.js spec/driverProviderUseExistingWebDriver.js --useBlockingProxy',
'node scripts/errorTest.js',
// Interactive Element Explorer tasks
'node scripts/interactive_tests/interactive_test.js',
Expand Down
22 changes: 22 additions & 0 deletions spec/driverProviderUseExistingWebDriver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var env = require('./environment');
var webdriver = require('selenium-webdriver');

var existingDriver = new webdriver.Builder()
.usingServer(env.seleniumAddress)
.withCapabilities(env.capabilities)
.build();

exports.config = {

framework: 'jasmine',

specs: [
'driverProviders/useExistingWebDriver/*_spec.js'
],

capabilities: env.capabilities,

baseUrl: env.baseUrl,

seleniumWebDriver: existingDriver,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
describe('uses existing webdriver', function() {
var URL = '/ng2/#/async';

beforeEach(function() {
browser.get(URL);
});
it('should be able to use an existing session', function() {
var increment = $('#increment');
expect(increment).toBeDefined();
});
// the driverProvider is set up to ignore the quitDriver() call;
// so we call quit() ourselves to tidy up when testing is done.
afterEach(function() {
browser.quit();
});
});

0 comments on commit 7b08083

Please sign in to comment.