Skip to content

Commit dcaf7b2

Browse files
committed
[js] The http.Executor class now accepts a promised client. The builder will now
use this instead of command.DeferredExecutor when creating WebDriver instances, so http.Executors.prototype.defineCommand is exposed for users to define additional commands. The executors module and command.DeferredExecutor class are no longer used anywhere, so they have been removed.
1 parent 7e144bb commit dcaf7b2

File tree

12 files changed

+96
-124
lines changed

12 files changed

+96
-124
lines changed

javascript/node/selenium-webdriver/CHANGES.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
* Fixed timeouts' URL
1212
* Properly send HTTP requests when using a WebDriver server proxy
1313
* Properly configure proxies when using the geckodriver
14+
* `http.Executor` now accepts a promised client. The `builder.Builder` class
15+
will now use this over a `command.DeferredExecutor` when creating WebDriver
16+
instances.
1417

1518
### API Changes
1619

@@ -21,13 +24,18 @@
2124
* When adding cookies, the desired expiry must be provided as a Date or in
2225
_seconds_ since epoch. When retrieving cookies, the expiration is always
2326
returned in seconds.
24-
* Renamed `firefox.Options#useMarionette` to `firefox.Options#useGeckoDriver`
27+
* Renamed `firefox.Options#useMarionette` to `firefox.Options#useGeckoDriver`
2528
* Removed deprecated modules:
2629
- `selenium-webdriver/error` (use `selenium-webdriver/lib/error`,\
2730
or the `error` property exported by `selenium-webdriver`)
31+
- `selenium-webdriver/executors` — this was not previously deprecated, but
32+
is no longer used.
2833
* Removed deprecated types:
34+
- `command.DeferredExecutor` — this was not previously deprecated, but is no
35+
longer used. It can be trivially implemented by clients should it be
36+
needed.
2937
- `error.InvalidSessionIdError` (use `error.NoSuchSessionError`)
30-
- `executors.DeferredExecutor` (use `command.DeferredExecutor`)
38+
- `executors.DeferredExecutor`
3139
- `until.Condition` (use `webdriver.Condition`)
3240
- `until.WebElementCondition` (use `webdriver.WebElementCondition`)
3341
- `webdriver.UnhandledAlertError` (use `error.UnexpectedAlertOpenError`)

javascript/node/selenium-webdriver/builder.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
const chrome = require('./chrome');
2121
const edge = require('./edge');
22-
const executors = require('./executors');
2322
const firefox = require('./firefox');
23+
const _http = require('./http');
2424
const ie = require('./ie');
2525
const capabilities = require('./lib/capabilities');
2626
const webdriver = require('./lib/webdriver');
@@ -483,7 +483,9 @@ class Builder {
483483
}
484484

485485
if (url) {
486-
var executor = executors.createExecutor(url, this.agent_, this.proxy_);
486+
let client = Promise.resolve(url)
487+
.then(url => new _http.HttpClient(url, this.agent_, this.proxy_));
488+
let executor = new _http.Executor(client);
487489
return WebDriver.createSession(executor, capabilities, this.flow_);
488490
}
489491

javascript/node/selenium-webdriver/chrome.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@
117117
const fs = require('fs'),
118118
util = require('util');
119119

120-
const executors = require('./executors'),
121-
http = require('./http'),
120+
const http = require('./http'),
122121
io = require('./io'),
123122
Capabilities = require('./lib/capabilities').Capabilities,
124123
Capability = require('./lib/capabilities').Capability,
@@ -155,14 +154,12 @@ const Command = {
155154
* @return {!command.Executor} The new command executor.
156155
*/
157156
function createExecutor(url) {
158-
return new command.DeferredExecutor(url.then(url => {
159-
let client = new http.HttpClient(url);
160-
let executor = new http.Executor(client);
161-
executor.defineCommand(
162-
Command.LAUNCH_APP,
163-
'POST', '/session/:sessionId/chromium/launch_app');
164-
return executor;
165-
}));
157+
let client = url.then(url => new http.HttpClient(url));
158+
let executor = new http.Executor(client);
159+
executor.defineCommand(
160+
Command.LAUNCH_APP,
161+
'POST', '/session/:sessionId/chromium/launch_app');
162+
return executor;
166163
}
167164

168165

javascript/node/selenium-webdriver/edge.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
const fs = require('fs'),
7474
util = require('util');
7575

76-
const executors = require('./executors'),
76+
const http = require('./http'),
7777
io = require('./io'),
7878
capabilities = require('./lib/capabilities'),
7979
promise = require('./lib/promise'),
@@ -342,7 +342,8 @@ class Driver extends webdriver.WebDriver {
342342
*/
343343
constructor(opt_config, opt_service, opt_flow) {
344344
var service = opt_service || getDefaultService();
345-
var executor = executors.createExecutor(service.start());
345+
var client = service.start().then(url => new http.HttpClient(url));
346+
var executor = new http.Executor(client);
346347

347348
var caps =
348349
opt_config instanceof Options ? opt_config.toCapabilities() :

javascript/node/selenium-webdriver/executors.js

-49
This file was deleted.

javascript/node/selenium-webdriver/firefox/index.js

+15-18
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ const url = require('url');
116116
const Binary = require('./binary').Binary,
117117
Profile = require('./profile').Profile,
118118
decodeProfile = require('./profile').decode,
119-
executors = require('../executors'),
120119
http = require('../http'),
121120
httpUtil = require('../http/util'),
122121
io = require('../io'),
@@ -393,25 +392,23 @@ const ExtensionCommand = {
393392

394393
/**
395394
* Creates a command executor with support for Marionette's custom commands.
396-
* @param {!Promise<string>} url The server's URL.
395+
* @param {!Promise<string>} serverUrl The server's URL.
397396
* @return {!command.Executor} The new command executor.
398397
*/
399-
function createExecutor(url) {
400-
return new command.DeferredExecutor(url.then(url => {
401-
let client = new http.HttpClient(url);
402-
let executor = new http.Executor(client);
403-
404-
executor.defineCommand(
405-
ExtensionCommand.GET_CONTEXT,
406-
'GET',
407-
'/session/:sessionId/moz/context');
408-
executor.defineCommand(
409-
ExtensionCommand.SET_CONTEXT,
410-
'POST',
411-
'/session/:sessionId/moz/context');
412-
413-
return executor;
414-
}));
398+
function createExecutor(serverUrl) {
399+
let client = serverUrl.then(url => new http.HttpClient(url));
400+
let executor = new http.Executor(client);
401+
402+
executor.defineCommand(
403+
ExtensionCommand.GET_CONTEXT,
404+
'GET',
405+
'/session/:sessionId/moz/context');
406+
executor.defineCommand(
407+
ExtensionCommand.SET_CONTEXT,
408+
'POST',
409+
'/session/:sessionId/moz/context');
410+
411+
return executor;
415412
}
416413

417414
/**

javascript/node/selenium-webdriver/ie.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
const fs = require('fs'),
3131
util = require('util');
3232

33-
const executors = require('./executors'),
33+
const http = require('./http'),
3434
io = require('./io'),
3535
capabilities = require('./lib/capabilities'),
3636
promise = require('./lib/promise'),
@@ -414,7 +414,8 @@ class Driver extends webdriver.WebDriver {
414414
(opt_config || capabilities.Capabilities.ie());
415415

416416
var service = createServiceFromCapabilities(caps);
417-
var executor = executors.createExecutor(service.start());
417+
var client = service.start().then(url => new http.HttpClient(url));
418+
var executor = new http.Executor(client);
418419
var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow);
419420

420421
super(driver.getSession(), executor, driver.controlFlow());

javascript/node/selenium-webdriver/lib/command.js

+1-22
Original file line numberDiff line numberDiff line change
@@ -232,33 +232,12 @@ class Executor {
232232
}
233233

234234

235-
/**
236-
* Wraps a promised {@link Executor}, ensuring no commands are executed until
237-
* the wrapped executor has been fully resolved.
238-
* @implements {Executor}
239-
*/
240-
class DeferredExecutor {
241-
/**
242-
* @param {!Promise<Executor>} delegate The promised delegate, which
243-
* may be provided by any promise-like thenable object.
244-
*/
245-
constructor(delegate) {
246-
247-
/** @override */
248-
this.execute = function(command) {
249-
return delegate.then(executor => executor.execute(command));
250-
};
251-
}
252-
}
253-
254-
255235

256236
// PUBLIC API
257237

258238

259239
module.exports = {
260240
Command: Command,
261241
Name: Name,
262-
Executor: Executor,
263-
DeferredExecutor: DeferredExecutor
242+
Executor: Executor
264243
};

javascript/node/selenium-webdriver/lib/http.js

+29-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
const cmd = require('./command');
2929
const error = require('./error');
3030
const logging = require('./logging');
31+
const promise = require('./promise');
3132
const Session = require('./session').Session;
3233
const WebElement = require('./webdriver').WebElement;
3334

@@ -222,6 +223,29 @@ class Client {
222223
}
223224

224225

226+
const CLIENTS =
227+
/** !WeakMap<!Executor, !(Client|IThenable<!Client>)> */new WeakMap;
228+
229+
230+
/**
231+
* Sends a request using the given executor.
232+
* @param {!Executor} executor
233+
* @param {!Request} request
234+
* @return {!Promise<Response>}
235+
*/
236+
function doSend(executor, request) {
237+
const client = CLIENTS.get(executor);
238+
if (promise.isPromise(client)) {
239+
return client.then(client => {
240+
CLIENTS.set(executor, client);
241+
return client.send(request);
242+
});
243+
} else {
244+
return client.send(request);
245+
}
246+
}
247+
248+
225249
/**
226250
* A command executor that communicates with the server using JSON over HTTP.
227251
*
@@ -237,12 +261,12 @@ class Client {
237261
*/
238262
class Executor {
239263
/**
240-
* @param {!Client} client The client to use for sending requests to the
241-
* server.
264+
* @param {!(Client|IThenable<!Client>)} client The client to use for sending
265+
* requests to the server, or a promise-like object that will resolve to
266+
* to the client.
242267
*/
243268
constructor(client) {
244-
/** @private {!Client} */
245-
this.client_ = client;
269+
CLIENTS.set(this, client);
246270

247271
/**
248272
* Whether this executor should use the W3C wire protocol. The executor
@@ -297,7 +321,7 @@ class Executor {
297321

298322
let log = this.log_;
299323
log.finer(() => '>>>\n' + request);
300-
return this.client_.send(request).then(response => {
324+
return doSend(this, request).then(response => {
301325
log.finer(() => '<<<\n' + response);
302326

303327
let parsed =

javascript/node/selenium-webdriver/opera.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474

7575
const fs = require('fs');
7676

77-
const executors = require('./executors'),
77+
const http = require('./http'),
7878
io = require('./io'),
7979
capabilities = require('./lib/capabilities'),
8080
promise = require('./lib/promise'),
@@ -436,7 +436,8 @@ class Driver extends webdriver.WebDriver {
436436
*/
437437
constructor(opt_config, opt_service, opt_flow) {
438438
var service = opt_service || getDefaultService();
439-
var executor = executors.createExecutor(service.start());
439+
var client = service.start().then(url => new http.HttpClient(url));
440+
var executor = new http.Executor(client);
440441

441442
var caps =
442443
opt_config instanceof Options ? opt_config.toCapabilities() :

javascript/node/selenium-webdriver/phantomjs.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@
4646

4747
const fs = require('fs');
4848

49-
const executors = require('./executors'),
50-
http = require('./http'),
49+
const http = require('./http'),
5150
io = require('./io'),
5251
capabilities = require('./lib/capabilities'),
5352
command = require('./lib/command'),
@@ -134,16 +133,14 @@ const WEBDRIVER_TO_PHANTOMJS_LEVEL = new Map([
134133
* @return {!command.Executor} The new command executor.
135134
*/
136135
function createExecutor(url) {
137-
return new command.DeferredExecutor(url.then(url => {
138-
var client = new http.HttpClient(url);
139-
var executor = new http.Executor(client);
136+
let client = url.then(url => new http.HttpClient(url));
137+
let executor = new http.Executor(client);
140138

141-
executor.defineCommand(
142-
Command.EXECUTE_PHANTOM_SCRIPT,
143-
'POST', '/session/:sessionId/phantom/execute');
139+
executor.defineCommand(
140+
Command.EXECUTE_PHANTOM_SCRIPT,
141+
'POST', '/session/:sessionId/phantom/execute');
144142

145-
return executor;
146-
}));
143+
return executor;
147144
}
148145

149146
/**

javascript/node/selenium-webdriver/test/lib/http_test.js

+14
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,20 @@ describe('http', function() {
598598
});
599599
});
600600

601+
it('accepts promised http clients', function() {
602+
executor = new http.Executor(Promise.resolve(client));
603+
604+
var resp = JSON.stringify({sessionId: 'abc123'});
605+
send.returns(Promise.resolve(new http.Response(200, {}, resp)));
606+
607+
let command = new Command(CommandName.NEW_SESSION);
608+
return executor.execute(command).then(response => {
609+
assertSent(
610+
'POST', '/session', {},
611+
[['Accept', 'application/json; charset=utf-8']]);
612+
});
613+
});
614+
601615
function entries(map) {
602616
let entries = [];
603617
for (let e of map.entries()) {

0 commit comments

Comments
 (0)