Skip to content

Commit 36ae4e0

Browse files
committed
Introduce a new serializable type.
This is used for types that cannot be synchronously converted to their JSON wire format (synchronous types may continue using the standard toJSON() function)
1 parent c085132 commit 36ae4e0

File tree

10 files changed

+205
-21
lines changed

10 files changed

+205
-21
lines changed

javascript/node/selenium-webdriver/chrome.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,18 @@ var OPTIONS_CAPABILITY_KEY = 'chromeOptions';
229229
/**
230230
* Class for managing ChromeDriver specific options.
231231
* @constructor
232+
* @extends {webdriver.Serializable}
232233
*/
233234
var Options = function() {
235+
webdriver.Serializable.call(this);
236+
234237
/** @private {!Array.<string>} */
235238
this.args_ = [];
236239

237240
/** @private {!Array.<(string|!Buffer)>} */
238241
this.extensions_ = [];
239242
};
243+
util.inherits(Options, webdriver.Serializable);
240244

241245

242246
/**
@@ -415,21 +419,23 @@ Options.prototype.toCapabilities = function(opt_capabilities) {
415419
* @return {{args: !Array.<string>,
416420
* binary: (string|undefined),
417421
* detach: boolean,
418-
* extensions: !Array.<string>,
422+
* extensions: !Array.<(string|!webdriver.promise.Promise.<string>))>,
419423
* localState: (Object|undefined),
420424
* logPath: (string|undefined),
421425
* prefs: (Object|undefined)}} The JSON wire protocol representation
422426
* of this instance.
427+
* @override
423428
*/
424-
Options.prototype.toJSON = function() {
429+
Options.prototype.serialize = function() {
425430
var json = {
426431
args: this.args_,
427432
detach: !!this.detach_,
428433
extensions: this.extensions_.map(function(extension) {
429434
if (Buffer.isBuffer(extension)) {
430435
return extension.toString('base64');
431436
}
432-
return fs.readFileSync(extension, 'base64');
437+
return webdriver.promise.checkedNodeCall(
438+
fs.readFile, extension, 'base64');
433439
})
434440
};
435441

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

+22-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ var child = require('child_process'),
2020
path = require('path'),
2121
util = require('util');
2222

23-
var promise = require('..').promise,
23+
var Serializable = require('..').Serializable,
24+
promise = require('..').promise,
2425
_base = require('../_base'),
2526
io = require('../io'),
2627
exec = require('../io/exec');
@@ -148,11 +149,15 @@ function installProfile(firefox, env) {
148149

149150
/**
150151
* Manages a Firefox subprocess configured for use with WebDriver.
152+
*
151153
* @param {string=} opt_exe Path to the Firefox binary to use. If not
152154
* specified, will attempt to locate Firefox on the current system.
153155
* @constructor
156+
* @extends {Serializable.<string>}
154157
*/
155158
var Binary = function(opt_exe) {
159+
Serializable.call(this);
160+
156161
/** @private {(string|undefined)} */
157162
this.exe_ = opt_exe;
158163

@@ -171,6 +176,7 @@ var Binary = function(opt_exe) {
171176
/** @private {promise.Promise.<!exec.Command>} */
172177
this.command_ = null;
173178
};
179+
util.inherits(Binary, Serializable);
174180

175181

176182
/**
@@ -254,6 +260,21 @@ Binary.prototype.kill = function() {
254260
};
255261

256262

263+
/**
264+
* Returns a promise for the wire representation of this binary. Note: the
265+
* FirefoxDriver only supports passing the path to the binary executable over
266+
* the wire; all command line arguments and environment variables will be
267+
* discarded.
268+
*
269+
* @return {!promise.Promise.<string>} A promise for this binary's wire
270+
* representation.
271+
* @override
272+
*/
273+
Binary.prototype.serialize = function() {
274+
return promise.when(this.exe_ || findFirefox());
275+
};
276+
277+
257278
// PUBLIC API
258279

259280

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

+17-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
var AdmZip = require('adm-zip'),
1919
fs = require('fs'),
2020
path = require('path'),
21+
util = require('util'),
2122
vm = require('vm');
2223

23-
var promise = require('..').promise,
24+
var Serializable = require('..').Serializable,
25+
promise = require('..').promise,
2426
_base = require('../_base'),
2527
io = require('../io'),
2628
extension = require('./extension');
@@ -213,8 +215,11 @@ function decode(data) {
213215
* use a template for this profile. If not specified, a blank profile will
214216
* be used.
215217
* @constructor
218+
* @extends {Serializable.<string>}
216219
*/
217220
var Profile = function(opt_dir) {
221+
Serializable.call(this);
222+
218223
/** @private {!Object} */
219224
this.preferences_ = {};
220225

@@ -233,6 +238,7 @@ var Profile = function(opt_dir) {
233238
/** @private {!Array.<string>} */
234239
this.extensions_ = [];
235240
};
241+
util.inherits(Profile, Serializable);
236242

237243

238244
/**
@@ -400,6 +406,16 @@ Profile.prototype.encode = function() {
400406
};
401407

402408

409+
/**
410+
* Encodes this profile as a zipped, base64 encoded directory.
411+
* @return {!promise.Promise.<string>} A promise for the encoded profile.
412+
* @override
413+
*/
414+
Profile.prototype.serialize = function() {
415+
return this.encode();
416+
};
417+
418+
403419
// PUBLIC API
404420

405421

javascript/node/selenium-webdriver/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ exports.Command = base.require('webdriver.Command');
5252
exports.EventEmitter = base.require('webdriver.EventEmitter');
5353

5454

55+
/** @type {function(new: webdriver.Serializable)} */
56+
exports.Serializable = base.require('webdriver.Serializable');
57+
58+
5559
/** @type {function(new: webdriver.Session)} */
5660
exports.Session = base.require('webdriver.Session');
5761

javascript/node/selenium-webdriver/test/chrome/options_test.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('chrome.Options', function() {
7676
});
7777

7878
var options = chrome.Options.fromCapabilities(caps);
79-
var json = options.toJSON();
79+
var json = options.serialize();
8080

8181
assert(json.args.length).equalTo(0);
8282
assert(json.binary).isUndefined();
@@ -152,10 +152,10 @@ describe('chrome.Options', function() {
152152
});
153153
});
154154

155-
describe('toJSON', function() {
155+
describe('serialize', function() {
156156
it('base64 encodes extensions', function() {
157157
var expected = fs.readFileSync(__filename, 'base64');
158-
var wire = new chrome.Options().addExtensions(__filename).toJSON();
158+
var wire = new chrome.Options().addExtensions(__filename).serialize();
159159
assert(wire.extensions.length).equalTo(1);
160160
assert(wire.extensions[0]).equalTo(expected);
161161
});
@@ -194,12 +194,14 @@ describe('chrome.Options', function() {
194194
test.suite(function(env) {
195195
env.autoCreateDriver = false;
196196

197-
describe('options', function() {
197+
describe('Chrome options', function() {
198198
test.it('can start Chrome with custom args', function() {
199199
var options = new chrome.Options().
200200
addArguments('user-agent=foo;bar');
201201

202-
var driver = env.driver = new chrome.Driver(options);
202+
var driver = env.builder().
203+
setChromeOptions(options).
204+
build();
203205

204206
driver.get(test.Pages.ajaxyPage);
205207

javascript/node/selenium-webdriver/test/firefox/firefox_test.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ test.suite(function(env) {
4343

4444
var options = new firefox.Options().setProfile(profile);
4545

46-
var driver = env.driver = new firefox.Driver(options);
46+
var driver = env.builder().
47+
setFirefoxOptions(options).
48+
build();
49+
4750
driver.get('data:text/html,<html><div>content</div></html>');
4851

4952
var userAgent = driver.executeScript(
@@ -57,7 +60,10 @@ test.suite(function(env) {
5760

5861
var options = new firefox.Options().setProfile(profile);
5962

60-
var driver = env.driver = new firefox.Driver(options);
63+
var driver = env.builder().
64+
setFirefoxOptions(options).
65+
build();
66+
6167
loadJetpackPage(driver,
6268
'data:text/html;charset=UTF-8,<html><div>content</div></html>');
6369
assert(driver.findElement({id: 'jetpack-sample-banner'}).getText())
@@ -70,7 +76,10 @@ test.suite(function(env) {
7076

7177
var options = new firefox.Options().setProfile(profile);
7278

73-
var driver = env.driver = new firefox.Driver(options);
79+
var driver = env.builder().
80+
setFirefoxOptions(options).
81+
build();
82+
7483
driver.get('data:text/html,<html><div>content</div></html>');
7584
assert(driver.findElement({id: 'sample-extension-footer'}).getText())
7685
.equalTo('Goodbye');
@@ -83,7 +92,9 @@ test.suite(function(env) {
8392

8493
var options = new firefox.Options().setProfile(profile);
8594

86-
var driver = env.driver = new firefox.Driver(options);
95+
var driver = env.builder().
96+
setFirefoxOptions(options).
97+
build();
8798

8899
loadJetpackPage(driver,
89100
'data:text/html;charset=UTF-8,<html><div>content</div></html>');

javascript/webdriver/capabilities.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ goog.provide('webdriver.Capabilities');
2121
goog.provide('webdriver.Capability');
2222
goog.provide('webdriver.ProxyConfig');
2323

24+
goog.require('webdriver.Serializable');
2425
goog.require('webdriver.logging.Preferences');
2526

2627

@@ -161,16 +162,19 @@ webdriver.Capability = {
161162
* @param {(webdriver.Capabilities|Object)=} opt_other Another set of
162163
* capabilities to merge into this instance.
163164
* @constructor
165+
* @extends {webdriver.Serializable.<!Object.<string, ?>>}
164166
*/
165167
webdriver.Capabilities = function(opt_other) {
168+
webdriver.Serializable.call(this);
166169

167-
/** @private {!Object} */
170+
/** @private {!Object.<string, ?>} */
168171
this.caps_ = {};
169172

170173
if (opt_other) {
171174
this.merge(opt_other);
172175
}
173176
};
177+
goog.inherits(webdriver.Capabilities, webdriver.Serializable);
174178

175179

176180
/**
@@ -281,12 +285,26 @@ webdriver.Capabilities.htmlunitwithjs = function() {
281285
};
282286

283287

284-
/** @return {!Object} The JSON representation of this instance. */
288+
/**
289+
* @return {!Object} The JSON representation of this instance.
290+
* @deprecated Use {@link #serialize} since a component capability may be a
291+
* promised value.
292+
*/
285293
webdriver.Capabilities.prototype.toJSON = function() {
286294
return this.caps_;
287295
};
288296

289297

298+
/**
299+
* @return {!Object.<string, ?>} The JSON representation of this instance. Note,
300+
* the returned object may contain nested promises that are promised values.
301+
* @override
302+
*/
303+
webdriver.Capabilities.prototype.serialize = function() {
304+
return this.caps_;
305+
};
306+
307+
290308
/**
291309
* Merges another set of capabilities into this instance. Any duplicates in
292310
* the provided set will override those already set on this instance.

javascript/webdriver/serializable.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2014 Selenium comitters
2+
// Copyright 2014 Software Freedom Conservancy
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
goog.provide('webdriver.Serializable');
17+
18+
19+
20+
/**
21+
* Defines an object that can be asynchronously serialized to its WebDriver
22+
* wire representation.
23+
*
24+
* @constructor
25+
* @template T
26+
*/
27+
webdriver.Serializable = function() {};
28+
29+
30+
/**
31+
* Returns either this instance's serialized represention, if immediately
32+
* available, or a promise for its serialized representation. This function is
33+
* conceptually equivalent to objects that have a {@code toJSON()} property,
34+
* except the serialize() result may be a promise or an object containing a
35+
* promise (which are not directly JSON friendly).
36+
*
37+
* @return {!(T|IThenable.<!T>)} This instance's serialized wire format.
38+
*/
39+
webdriver.Serializable.prototype.serialize = goog.abstractMethod;

0 commit comments

Comments
 (0)