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

feat(config): Support setting SELENIUM_PROMISE_MANAGER flag via the… #4023

Merged
merged 1 commit into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ selenium/
# Build artifacts

built/
spec/built/
node_modules/
website/bower_components/
website/build/
Expand Down
1 change: 1 addition & 0 deletions .jshintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./spec/built/*
11 changes: 7 additions & 4 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ gulp.task('checkVersion', function(done) {
});

gulp.task('built:copy', function(done) {
return gulp.src(['lib/**/*.js','lib/index.d.ts'])
return gulp.src(['lib/**/*.js'])
.pipe(gulp.dest('built/'));
done();
});
Expand Down Expand Up @@ -94,14 +94,17 @@ gulp.task('tsc', function(done) {
runSpawn(done, 'node', ['node_modules/typescript/bin/tsc']);
});

gulp.task('tsc:spec', function(done) {
runSpawn(done, 'node', ['node_modules/typescript/bin/tsc', '-p', 'ts_spec_config.json']);
});

gulp.task('prepublish', function(done) {
runSequence('checkVersion', 'jshint', 'tsc',
'built:copy', done);
runSequence('checkVersion', 'jshint', 'tsc', 'built:copy', 'tsc:spec', done);
});

gulp.task('pretest', function(done) {
runSequence('checkVersion',
['webdriver:update', 'jshint', 'tslint', 'format'], 'tsc', 'built:copy', done);
['webdriver:update', 'jshint', 'tslint', 'format'], 'tsc', 'built:copy', 'tsc:spec', done);
});

gulp.task('default',['prepublish']);
23 changes: 23 additions & 0 deletions lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,29 @@ export interface Config {
*/
disableChecks?: boolean;

/**
* Enable/disable the WebDriver Control Flow.
*
* WebDriverJS (and by extention, Protractor) uses a Control Flow to manage the order in which
* commands are executed and promises are resolved (see docs/control-flow.md for details).
* However, as syntax like `async`/`await` are being introduced, WebDriverJS has decided to
* deprecate the control flow, and have users manage the asynchronous activity themselves
* (details here: https://github.com/SeleniumHQ/selenium/issues/2969).
*
* At the moment, the WebDriver Control Flow is still enabled by default. You can disable it by
* setting the environment variable `SELENIUM_PROMISE_MANAGER` to `0`. In a webdriver release in
* Q4 2017, the Control Flow will be disabled by default, but you will be able to re-enable it by
* setting `SELENIUM_PROMISE_MANAGER` to `1`. At a later point, the control flow will be removed
* for good.
*
* If you don't like managing environment variables, you can set this option in your config file,
* and Protractor will handle enabling/disabling the control flow for you. Setting this option
* is higher priority than the `SELENIUM_PROMISE_MANAGER` environment variable.
*
* @type {boolean=}
*/
SELENIUM_PROMISE_MANAGER?: boolean;

seleniumArgs?: any[];
jvmArgs?: string[];
configDir?: string;
Expand Down
4 changes: 4 additions & 0 deletions lib/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ export class Runner extends EventEmitter {
throw new Error('Spec patterns did not match any files.');
}

if (this.config_.SELENIUM_PROMISE_MANAGER != null) {
(wdpromise as any).USE_PROMISE_MANAGER = this.config_.SELENIUM_PROMISE_MANAGER;
}

// 0) Wait for debugger
return q(this.ready_)
.then(() => {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@types/chalk": "^0.4.28",
"@types/glob": "^5.0.29",
"@types/jasmine": "^2.5.38",
"@types/jasminewd2": "^2.0.0",
"@types/minimatch": "^2.0.28",
"@types/minimist": "^1.1.28",
"@types/optimist": "^0.0.29",
Expand Down
1 change: 1 addition & 0 deletions scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var passingTests = [
'node built/cli.js spec/noGlobalsConf.js',
'node built/cli.js spec/angular2Conf.js',
'node built/cli.js spec/hybridConf.js',
'node built/cli.js spec/built/noCFSmokeConf.js',
'node scripts/driverProviderAttachSession.js',
'node scripts/errorTest.js',
// Interactive Element Explorer tasks
Expand Down
157 changes: 157 additions & 0 deletions spec/ts/noCF/smoke_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Based off of spec/basic/elements_spec.js
import {promise as ppromise, browser, element, by, By, $, $$, ExpectedConditions, ElementFinder} from '../../..';

describe('ElementFinder', function() {
it('should return the same result as browser.findElement', async function() {
await browser.get('index.html#/form');
const nameByElement = element(by.binding('username'));

await expect(nameByElement.getText()).toEqual(
browser.findElement(by.binding('username')).getText());
});

it('should wait to grab the WebElement until a method is called', async function() {
// These should throw no error before a page is loaded.
const usernameInput = element(by.model('username'));
const name = element(by.binding('username'));

await browser.get('index.html#/form');

await expect(name.getText()).toEqual('Anon');

await usernameInput.clear();
await usernameInput.sendKeys('Jane');
await expect(name.getText()).toEqual('Jane');
});

it('should chain element actions', async function() {
await browser.get('index.html#/form');

const usernameInput = element(by.model('username'));
const name = element(by.binding('username'));

await expect(name.getText()).toEqual('Anon');

await ((usernameInput.clear() as any) as ElementFinder).sendKeys('Jane');
await expect(name.getText()).toEqual('Jane');
});

it('chained call should wait to grab the WebElement until a method is called',
async function() {
// These should throw no error before a page is loaded.
const reused = element(by.id('baz')).
element(by.binding('item.reusedBinding'));

await browser.get('index.html#/conflict');

await expect(reused.getText()).toEqual('Inner: inner');
await expect(reused.isPresent()).toBe(true);
});

it('should differentiate elements with the same binding by chaining',
async function() {
await browser.get('index.html#/conflict');

const outerReused = element(by.binding('item.reusedBinding'));
const innerReused =
element(by.id('baz')).element(by.binding('item.reusedBinding'));

await expect(outerReused.getText()).toEqual('Outer: outer');
await expect(innerReused.getText()).toEqual('Inner: inner');
});

it('should chain deeper than 2', async function() {
// These should throw no error before a page is loaded.
const reused = element(by.css('body')).element(by.id('baz')).
element(by.binding('item.reusedBinding'));

await browser.get('index.html#/conflict');

await expect(reused.getText()).toEqual('Inner: inner');
});

it('should allow handling errors', async function() {
await browser.get('index.html#/form');
try {
await $('.nopenopenope').getText();

// The above line should have throw an error. Fail.
await expect(true).toEqual(false);
} catch (e) {
await expect(true).toEqual(true);
}
});

it('should allow handling chained errors', async function() {
await browser.get('index.html#/form');
try {
await $('.nopenopenope').$('furthernope').getText();

// The above line should have throw an error. Fail.
await expect(true).toEqual(false);
} catch (e) {
await expect(true).toEqual(true);
}
});

it('should keep a reference to the original locator', async function() {
await browser.get('index.html#/form');

const byCss = by.css('body');
const byBinding = by.binding('greet');

await expect(element(byCss).locator()).toEqual(byCss);
await expect(element(byBinding).locator()).toEqual(byBinding);
});

it('should propagate exceptions', async function() {
await browser.get('index.html#/form');

const invalidElement = element(by.binding('INVALID'));
const successful = invalidElement.getText().then(function() {
return true;
} as any as (() => ppromise.Promise<void>), function() {
return false;
} as any as (() => ppromise.Promise<void>));
await expect(successful).toEqual(false);
});

it('should be returned from a helper without infinite loops', async function() {
await browser.get('index.html#/form');
const helperPromise = ppromise.when(true).then(function() {
return element(by.binding('greeting'));
});

await helperPromise.then(async function(finalResult: ElementFinder) {
await expect(finalResult.getText()).toEqual('Hiya');
} as any as (() => ppromise.Promise<void>));
});

it('should be usable in WebDriver functions', async function() {
await browser.get('index.html#/form');
const greeting = element(by.binding('greeting'));
await browser.executeScript('arguments[0].scrollIntoView', greeting);
});

it('should allow null as success handler', async function() {
await browser.get('index.html#/form');

const name = element(by.binding('username'));

await expect(name.getText()).toEqual('Anon');
await expect(
name.getText().then(null, function() {})
).toEqual('Anon');

});

it('should check equality correctly', async function() {
await browser.get('index.html#/form');

const usernameInput = element(by.model('username'));
const name = element(by.binding('username'));

await expect(usernameInput.equals(usernameInput)).toEqual(true);
await expect(usernameInput.equals(name)).toEqual(false);
});
});
18 changes: 18 additions & 0 deletions spec/ts/noCFSmokeConf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Config} from '../..';
const env = require('../environment.js');

export let config: Config = {
seleniumAddress: env.seleniumAddress,

framework: 'jasmine',

specs: [
'noCF/smoke_spec.js'
],

capabilities: env.capabilities,

baseUrl: env.baseUrl + '/ng1/',

SELENIUM_PROMISE_MANAGER: false
};
21 changes: 21 additions & 0 deletions ts_spec_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"declaration": true,
"removeComments": false,
"noImplicitAny": true,
"outDir": "spec/built",
"types": [
"jasmine", "jasminewd2", "node",
"chalk", "glob", "minimatch",
"minimist", "optimist", "q",
"selenium-webdriver"
]
},
"include": [
"spec/ts"
]
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"noImplicitAny": true,
"outDir": "built/",
"types": [
"jasmine", "node",
"jasmine", "jasminewd2", "node",
"chalk", "glob", "minimatch",
"minimist", "optimist", "q",
"selenium-webdriver"
Expand Down