selenium-webdriver 3.0.0-beta-1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +109 -0
- package/LICENSE +1 -1
- package/README.md +7 -6
- package/chrome.js +31 -128
- package/edge.js +13 -91
- package/example/chrome_android.js +18 -13
- package/example/chrome_mobile_emulation.js +19 -15
- package/example/google_search.js +11 -11
- package/example/google_search_generator.js +23 -18
- package/example/google_search_test.js +31 -17
- package/example/logging.js +9 -17
- package/example/parallel_flows.js +3 -0
- package/firefox/binary.js +17 -0
- package/firefox/index.js +198 -101
- package/firefox/profile.js +24 -3
- package/http/util.js +95 -59
- package/ie.js +6 -10
- package/index.js +636 -2
- package/lib/actions.js +18 -10
- package/lib/atoms/getAttribute.js +11 -0
- package/lib/atoms/isDisplayed.js +106 -0
- package/lib/firefox/amd64/libnoblur64.so +0 -0
- package/lib/firefox/i386/libnoblur.so +0 -0
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/http.js +159 -46
- package/lib/logging.js +7 -1
- package/lib/promise.js +602 -358
- package/lib/proxy.js +28 -0
- package/lib/session.js +1 -1
- package/lib/test/build.js +26 -28
- package/lib/test/data/formPage.html +1 -0
- package/lib/test/fileserver.js +12 -10
- package/lib/test/httpserver.js +4 -6
- package/lib/test/index.js +18 -11
- package/lib/test/promise.js +79 -0
- package/lib/webdriver.js +587 -479
- package/opera.js +12 -88
- package/package.json +13 -14
- package/phantomjs.js +7 -14
- package/remote/index.js +201 -30
- package/safari.js +62 -416
- package/test/actions_test.js +9 -11
- package/test/chrome/options_test.js +8 -8
- package/test/chrome/service_test.js +2 -2
- package/test/cookie_test.js +57 -57
- package/test/element_finding_test.js +201 -185
- package/test/execute_script_test.js +108 -111
- package/test/fingerprint_test.js +16 -11
- package/test/firefox/firefox_test.js +75 -49
- package/test/firefox/profile_test.js +1 -3
- package/test/http/util_test.js +21 -27
- package/test/io_test.js +2 -5
- package/test/lib/http_test.js +8 -6
- package/test/lib/promise_aplus_test.js +48 -44
- package/test/lib/promise_error_test.js +687 -611
- package/test/lib/promise_flow_test.js +1810 -1806
- package/test/lib/promise_generator_test.js +227 -225
- package/test/lib/promise_test.js +864 -835
- package/test/lib/until_test.js +1 -1
- package/test/lib/webdriver_test.js +520 -424
- package/test/logging_test.js +43 -45
- package/test/net/portprober_test.js +23 -24
- package/test/page_loading_test.js +84 -78
- package/test/phantomjs/execute_phantomjs_test.js +11 -25
- package/test/proxy_test.js +23 -23
- package/test/remote_test.js +22 -22
- package/test/safari_test.js +108 -0
- package/test/session_test.js +11 -10
- package/test/stale_element_test.js +18 -16
- package/test/tag_name_test.js +7 -5
- package/test/testing/assert_test.js +2 -3
- package/test/testing/index_test.js +163 -117
- package/test/upload_test.js +13 -13
- package/test/window_test.js +94 -70
- package/testing/index.js +176 -37
- package/builder.js +0 -553
- package/lib/safari/client.js +0 -56
package/safari.js
CHANGED
|
@@ -16,445 +16,60 @@
|
|
|
16
16
|
// under the License.
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @fileoverview Defines a WebDriver client for Safari.
|
|
20
|
-
* module, you must install the
|
|
21
|
-
* [latest version](http://selenium-release.storage.googleapis.com/index.html)
|
|
22
|
-
* of the SafariDriver browser extension; using Safari for normal browsing is
|
|
23
|
-
* not recommended once the extension has been installed. You can, and should,
|
|
24
|
-
* disable the extension when the browser is not being used with WebDriver.
|
|
19
|
+
* @fileoverview Defines a WebDriver client for Safari.
|
|
25
20
|
*/
|
|
26
21
|
|
|
27
22
|
'use strict';
|
|
28
23
|
|
|
29
|
-
const
|
|
30
|
-
const fs = require('fs');
|
|
31
|
-
const http = require('http');
|
|
32
|
-
const path = require('path');
|
|
33
|
-
const url = require('url');
|
|
34
|
-
const util = require('util');
|
|
35
|
-
const ws = require('ws');
|
|
36
|
-
|
|
24
|
+
const http = require('./http');
|
|
37
25
|
const io = require('./io');
|
|
38
|
-
const
|
|
39
|
-
const isDevMode = require('./lib/devmode');
|
|
40
|
-
const Capabilities = require('./lib/capabilities').Capabilities;
|
|
41
|
-
const Capability = require('./lib/capabilities').Capability;
|
|
26
|
+
const {Capabilities, Capability} = require('./lib/capabilities');
|
|
42
27
|
const command = require('./lib/command');
|
|
43
28
|
const error = require('./lib/error');
|
|
44
29
|
const logging = require('./lib/logging');
|
|
45
30
|
const promise = require('./lib/promise');
|
|
46
|
-
const Session = require('./lib/session').Session;
|
|
47
31
|
const Symbols = require('./lib/symbols');
|
|
48
32
|
const webdriver = require('./lib/webdriver');
|
|
49
33
|
const portprober = require('./net/portprober');
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/** @const */
|
|
53
|
-
const CLIENT_PATH = isDevMode
|
|
54
|
-
? path.join(__dirname,
|
|
55
|
-
'../../../buck-out/gen/javascript/safari-driver/client.js')
|
|
56
|
-
: path.join(__dirname, 'lib/safari/client.js');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/** @const */
|
|
60
|
-
const LIBRARY_DIR = (function() {
|
|
61
|
-
if (process.platform === 'darwin') {
|
|
62
|
-
return path.join('/Users', process.env['USER'], 'Library/Safari');
|
|
63
|
-
} else if (process.platform === 'win32') {
|
|
64
|
-
return path.join(process.env['APPDATA'], 'Apple Computer', 'Safari');
|
|
65
|
-
} else {
|
|
66
|
-
return '/dev/null';
|
|
67
|
-
}
|
|
68
|
-
})();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/** @const */
|
|
72
|
-
const SESSION_DATA_FILES = (function() {
|
|
73
|
-
if (process.platform === 'darwin') {
|
|
74
|
-
var libraryDir = path.join('/Users', process.env['USER'], 'Library');
|
|
75
|
-
return [
|
|
76
|
-
path.join(libraryDir, 'Caches/com.apple.Safari/Cache.db'),
|
|
77
|
-
path.join(libraryDir, 'Cookies/Cookies.binarycookies'),
|
|
78
|
-
path.join(libraryDir, 'Cookies/Cookies.plist'),
|
|
79
|
-
path.join(libraryDir, 'Safari/History.plist'),
|
|
80
|
-
path.join(libraryDir, 'Safari/LastSession.plist'),
|
|
81
|
-
path.join(libraryDir, 'Safari/LocalStorage'),
|
|
82
|
-
path.join(libraryDir, 'Safari/Databases')
|
|
83
|
-
];
|
|
84
|
-
} else if (process.platform === 'win32') {
|
|
85
|
-
var appDataDir = path.join(process.env['APPDATA'],
|
|
86
|
-
'Apple Computer', 'Safari');
|
|
87
|
-
var localDataDir = path.join(process.env['LOCALAPPDATA'],
|
|
88
|
-
'Apple Computer', 'Safari');
|
|
89
|
-
return [
|
|
90
|
-
path.join(appDataDir, 'History.plist'),
|
|
91
|
-
path.join(appDataDir, 'LastSession.plist'),
|
|
92
|
-
path.join(appDataDir, 'Cookies/Cookies.plist'),
|
|
93
|
-
path.join(appDataDir, 'Cookies/Cookies.binarycookies'),
|
|
94
|
-
path.join(localDataDir, 'Cache.db'),
|
|
95
|
-
path.join(localDataDir, 'Databases'),
|
|
96
|
-
path.join(localDataDir, 'LocalStorage')
|
|
97
|
-
];
|
|
98
|
-
} else {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
})();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/** @typedef {{port: number, address: string, family: string}} */
|
|
105
|
-
var Host;
|
|
34
|
+
const remote = require('./remote');
|
|
106
35
|
|
|
107
36
|
|
|
108
37
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
38
|
+
* @return {string} .
|
|
39
|
+
* @throws {Error}
|
|
111
40
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
var query = url.parse(/** @type {string} */(req.url)).query || '';
|
|
123
|
-
if (query.indexOf('url=') == -1) {
|
|
124
|
-
var address = server.address()
|
|
125
|
-
var host = address.address + ':' + address.port;
|
|
126
|
-
res.writeHead(
|
|
127
|
-
302, {'Location': 'http://' + host + '?url=ws://' + host});
|
|
128
|
-
res.end();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
fs.readFile(CLIENT_PATH, 'utf8', function(err, data) {
|
|
132
|
-
if (err) {
|
|
133
|
-
res.writeHead(500, {'Content-Type': 'text/plain'});
|
|
134
|
-
res.end(err.stack);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
var content = '<!DOCTYPE html><body><script>' + data + '</script>';
|
|
138
|
-
res.writeHead(200, {
|
|
139
|
-
'Content-Type': 'text/html; charset=utf-8',
|
|
140
|
-
'Content-Length': Buffer.byteLength(content, 'utf8'),
|
|
141
|
-
});
|
|
142
|
-
res.end(content);
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
var wss = new ws.Server({server: server});
|
|
147
|
-
wss.on('connection', this.emit.bind(this, 'connection'));
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Starts the server on a random port.
|
|
151
|
-
* @return {!Promise<Host>} A promise that will resolve with the server host
|
|
152
|
-
* when it has fully started.
|
|
153
|
-
*/
|
|
154
|
-
this.start = function() {
|
|
155
|
-
if (server.address()) {
|
|
156
|
-
return Promise.resolve(server.address());
|
|
157
|
-
}
|
|
158
|
-
return portprober.findFreePort('localhost').then(function(port) {
|
|
159
|
-
return promise.checkedNodeCall(
|
|
160
|
-
server.listen.bind(server, port, 'localhost'));
|
|
161
|
-
}).then(function() {
|
|
162
|
-
return server.address();
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Stops the server.
|
|
168
|
-
* @return {!Promise} A promise that will resolve when the server has closed
|
|
169
|
-
* all connections.
|
|
170
|
-
*/
|
|
171
|
-
this.stop = function() {
|
|
172
|
-
return new Promise(fulfill => server.close(fulfill));
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* @return {Host} This server's host info.
|
|
177
|
-
* @throws {Error} If the server is not running.
|
|
178
|
-
*/
|
|
179
|
-
this.address = function() {
|
|
180
|
-
var addr = server.address();
|
|
181
|
-
if (!addr) {
|
|
182
|
-
throw Error('There server is not running!');
|
|
183
|
-
}
|
|
184
|
-
return addr;
|
|
185
|
-
};
|
|
186
|
-
}
|
|
41
|
+
function findSafariDriver() {
|
|
42
|
+
let exe = io.findInPath('safaridriver', true);
|
|
43
|
+
if (!exe) {
|
|
44
|
+
throw Error(
|
|
45
|
+
`The safaridriver executable could not be found on the current PATH.
|
|
46
|
+
Please ensure you are using Safari 10.0 or above.`);
|
|
47
|
+
}
|
|
48
|
+
return exe;
|
|
187
49
|
}
|
|
188
50
|
|
|
189
51
|
|
|
190
52
|
/**
|
|
191
|
-
* @
|
|
192
|
-
*
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
switch (process.platform) {
|
|
196
|
-
case 'darwin':
|
|
197
|
-
return Promise.resolve('/Applications/Safari.app/Contents/MacOS/Safari');
|
|
198
|
-
|
|
199
|
-
case 'win32':
|
|
200
|
-
var files = [
|
|
201
|
-
process.env['PROGRAMFILES'] || '\\Program Files',
|
|
202
|
-
process.env['PROGRAMFILES(X86)'] || '\\Program Files (x86)'
|
|
203
|
-
].map(function(prefix) {
|
|
204
|
-
return path.join(prefix, 'Safari\\Safari.exe');
|
|
205
|
-
});
|
|
206
|
-
return io.exists(files[0]).then(function(exists) {
|
|
207
|
-
return exists ? files[0] : io.exists(files[1]).then(function(exists) {
|
|
208
|
-
if (exists) {
|
|
209
|
-
return files[1];
|
|
210
|
-
}
|
|
211
|
-
throw Error('Unable to find Safari on the current system');
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
default:
|
|
216
|
-
return Promise.reject(
|
|
217
|
-
Error('Safari is not supported on the current platform: ' +
|
|
218
|
-
process.platform));
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* @param {string} serverUrl The URL to connect to.
|
|
225
|
-
* @return {!Promise<string>} A promise for the path to a file that Safari can
|
|
226
|
-
* open on start-up to trigger a new connection to the WebSocket server.
|
|
227
|
-
*/
|
|
228
|
-
function createConnectFile(serverUrl) {
|
|
229
|
-
return io.tmpFile({postfix: '.html'}).then(function(f) {
|
|
230
|
-
let contents =
|
|
231
|
-
`<!DOCTYPE html><script>window.location = "${serverUrl}";</script>`;
|
|
232
|
-
return io.write(f, contents).then(() => f);
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Deletes all session data files if so desired.
|
|
239
|
-
* @param {!Object} desiredCapabilities .
|
|
240
|
-
* @return {!Array<!Promise>} A list of promises for the deleted files.
|
|
241
|
-
*/
|
|
242
|
-
function cleanSession(desiredCapabilities) {
|
|
243
|
-
if (!desiredCapabilities) {
|
|
244
|
-
return [];
|
|
245
|
-
}
|
|
246
|
-
var options = desiredCapabilities[OPTIONS_CAPABILITY_KEY];
|
|
247
|
-
if (!options) {
|
|
248
|
-
return [];
|
|
249
|
-
}
|
|
250
|
-
if (!options['cleanSession']) {
|
|
251
|
-
return [];
|
|
252
|
-
}
|
|
253
|
-
return SESSION_DATA_FILES.map(function(file) {
|
|
254
|
-
return io.unlink(file);
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
/** @return {string} . */
|
|
260
|
-
function getRandomString() {
|
|
261
|
-
let seed = Date.now();
|
|
262
|
-
return Math.floor(Math.random() * seed).toString(36)
|
|
263
|
-
+ Math.abs(Math.floor(Math.random() * seed) ^ Date.now()).toString(36);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* @implements {command.Executor}
|
|
53
|
+
* Creates {@link selenium-webdriver/remote.DriverService} instances that manage
|
|
54
|
+
* a [safaridriver] server in a child process.
|
|
55
|
+
*
|
|
56
|
+
* [safaridriver]: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html#//apple_ref/doc/uid/TP40014305-CH11-DontLinkElementID_28
|
|
269
57
|
*/
|
|
270
|
-
class
|
|
271
|
-
constructor() {
|
|
272
|
-
this.server_ = null;
|
|
273
|
-
|
|
274
|
-
/** @private {ws.WebSocket} */
|
|
275
|
-
this.socket_ = null;
|
|
276
|
-
|
|
277
|
-
/** @private {?string} 8*/
|
|
278
|
-
this.sessionId_ = null;
|
|
279
|
-
|
|
280
|
-
/** @private {Promise<!exec.Command>} */
|
|
281
|
-
this.safari_ = null;
|
|
282
|
-
|
|
283
|
-
/** @private {!logging.Logger} */
|
|
284
|
-
this.log_ = logging.getLogger('webdriver.safari');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/** @override */
|
|
288
|
-
execute(cmd) {
|
|
289
|
-
var self = this;
|
|
290
|
-
return new promise.Promise(function(fulfill, reject) {
|
|
291
|
-
var safariCommand = JSON.stringify({
|
|
292
|
-
'origin': 'webdriver',
|
|
293
|
-
'type': 'command',
|
|
294
|
-
'command': {
|
|
295
|
-
'id': getRandomString(),
|
|
296
|
-
'name': cmd.getName(),
|
|
297
|
-
'parameters': cmd.getParameters()
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
switch (cmd.getName()) {
|
|
302
|
-
case command.Name.NEW_SESSION:
|
|
303
|
-
self.startSafari_(cmd)
|
|
304
|
-
.then(() => self.sendCommand_(safariCommand))
|
|
305
|
-
.then(caps => new Session(self.sessionId(), caps))
|
|
306
|
-
.then(fulfill, reject);
|
|
307
|
-
break;
|
|
308
|
-
|
|
309
|
-
case command.Name.DESCRIBE_SESSION:
|
|
310
|
-
self.sendCommand_(safariCommand)
|
|
311
|
-
.then(caps => new Session(self.sessionId(), caps))
|
|
312
|
-
.then(fulfill, reject);
|
|
313
|
-
break;
|
|
314
|
-
|
|
315
|
-
case command.Name.QUIT:
|
|
316
|
-
self.destroySession_().then(() => fulfill(null), reject);
|
|
317
|
-
break;
|
|
318
|
-
|
|
319
|
-
default:
|
|
320
|
-
self.sendCommand_(safariCommand).then(fulfill, reject);
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* @return {string} The static session ID for this executor's current
|
|
328
|
-
* connection.
|
|
329
|
-
*/
|
|
330
|
-
sessionId() {
|
|
331
|
-
if (!this.sessionId_) {
|
|
332
|
-
throw Error('not currently connected')
|
|
333
|
-
}
|
|
334
|
-
return this.sessionId_;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* @param {string} data .
|
|
339
|
-
* @return {!promise.Promise} .
|
|
340
|
-
* @private
|
|
341
|
-
*/
|
|
342
|
-
sendCommand_(data) {
|
|
343
|
-
let self = this;
|
|
344
|
-
return new promise.Promise(function(fulfill, reject) {
|
|
345
|
-
// TODO: support reconnecting with the extension.
|
|
346
|
-
if (!self.socket_) {
|
|
347
|
-
self.destroySession_().finally(function() {
|
|
348
|
-
reject(Error('The connection to the SafariDriver was closed'));
|
|
349
|
-
});
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
self.log_.fine(() => '>>> ' + data);
|
|
354
|
-
self.socket_.send(data, function(err) {
|
|
355
|
-
if (err) {
|
|
356
|
-
reject(err);
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
self.socket_.once('message', function(data) {
|
|
362
|
-
try {
|
|
363
|
-
self.log_.fine(() => '<<< ' + data);
|
|
364
|
-
data = JSON.parse(data);
|
|
365
|
-
} catch (ex) {
|
|
366
|
-
reject(Error('Failed to parse driver message: ' + data));
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
try {
|
|
371
|
-
error.checkLegacyResponse(data['response']);
|
|
372
|
-
fulfill(data['response']['value']);
|
|
373
|
-
} catch (ex) {
|
|
374
|
-
reject(ex);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* @param {!command.Command} command .
|
|
382
|
-
* @private
|
|
383
|
-
*/
|
|
384
|
-
startSafari_(command) {
|
|
385
|
-
this.server_ = new Server();
|
|
386
|
-
|
|
387
|
-
this.safari_ = this.server_.start().then(function(address) {
|
|
388
|
-
var tasks = cleanSession(
|
|
389
|
-
/** @type {!Object} */(
|
|
390
|
-
command.getParameters()['desiredCapabilities']));
|
|
391
|
-
tasks.push(
|
|
392
|
-
findSafariExecutable(),
|
|
393
|
-
createConnectFile(
|
|
394
|
-
'http://' + address.address + ':' + address.port));
|
|
395
|
-
|
|
396
|
-
return Promise.all(tasks).then(function(/** !Array<string> */tasks) {
|
|
397
|
-
var exe = tasks[tasks.length - 2];
|
|
398
|
-
var html = tasks[tasks.length - 1];
|
|
399
|
-
return exec(exe, {args: [html]});
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
return new Promise((resolve, reject) => {
|
|
404
|
-
let start = Date.now();
|
|
405
|
-
let timer = setTimeout(function() {
|
|
406
|
-
let elapsed = Date.now() - start;
|
|
407
|
-
reject(Error(
|
|
408
|
-
'Failed to connect to the SafariDriver after ' + elapsed +
|
|
409
|
-
' ms; Have you installed the latest extension from ' +
|
|
410
|
-
'http://selenium-release.storage.googleapis.com/index.html?'));
|
|
411
|
-
}, 10 * 1000);
|
|
412
|
-
|
|
413
|
-
this.server_.once('connection', socket => {
|
|
414
|
-
clearTimeout(timer);
|
|
415
|
-
this.socket_ = socket;
|
|
416
|
-
this.sessionId_ = getRandomString();
|
|
417
|
-
socket.once('close', () => {
|
|
418
|
-
this.socket_ = null;
|
|
419
|
-
this.sessionId_ = null;
|
|
420
|
-
});
|
|
421
|
-
resolve();
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
|
|
58
|
+
class ServiceBuilder extends remote.DriverService.Builder {
|
|
426
59
|
/**
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* @private
|
|
60
|
+
* @param {string=} opt_exe Path to the server executable to use. If omitted,
|
|
61
|
+
* the builder will attempt to locate the safaridriver on the system PATH.
|
|
430
62
|
*/
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
tasks.push(this.server_.stop());
|
|
435
|
-
}
|
|
436
|
-
if (this.safari_) {
|
|
437
|
-
tasks.push(this.safari_.then(function(safari) {
|
|
438
|
-
safari.kill();
|
|
439
|
-
return safari.result();
|
|
440
|
-
}));
|
|
441
|
-
}
|
|
442
|
-
var self = this;
|
|
443
|
-
return promise.all(tasks).finally(function() {
|
|
444
|
-
self.server_ = null;
|
|
445
|
-
self.socket_ = null;
|
|
446
|
-
self.safari_ = null;
|
|
447
|
-
});
|
|
63
|
+
constructor(opt_exe) {
|
|
64
|
+
super(opt_exe || findSafariDriver());
|
|
65
|
+
this.setLoopback(true); // Required.
|
|
448
66
|
}
|
|
449
67
|
}
|
|
450
68
|
|
|
451
69
|
|
|
452
|
-
|
|
453
|
-
/** @const */
|
|
454
70
|
const OPTIONS_CAPABILITY_KEY = 'safari.options';
|
|
455
71
|
|
|
456
72
|
|
|
457
|
-
|
|
458
73
|
/**
|
|
459
74
|
* Configuration options specific to the {@link Driver SafariDriver}.
|
|
460
75
|
*/
|
|
@@ -465,6 +80,9 @@ class Options {
|
|
|
465
80
|
|
|
466
81
|
/** @private {./lib/logging.Preferences} */
|
|
467
82
|
this.logPrefs_ = null;
|
|
83
|
+
|
|
84
|
+
/** @private {?./lib/capabilities.ProxyConfig} */
|
|
85
|
+
this.proxy_ = null;
|
|
468
86
|
}
|
|
469
87
|
|
|
470
88
|
/**
|
|
@@ -483,6 +101,10 @@ class Options {
|
|
|
483
101
|
options.setCleanSession(o.cleanSession);
|
|
484
102
|
}
|
|
485
103
|
|
|
104
|
+
if (capabilities.has(Capability.PROXY)) {
|
|
105
|
+
options.setProxy(capabilities.get(Capability.PROXY));
|
|
106
|
+
}
|
|
107
|
+
|
|
486
108
|
if (capabilities.has(Capability.LOGGING_PREFS)) {
|
|
487
109
|
options.setLoggingPrefs(capabilities.get(Capability.LOGGING_PREFS));
|
|
488
110
|
}
|
|
@@ -515,6 +137,17 @@ class Options {
|
|
|
515
137
|
return this;
|
|
516
138
|
}
|
|
517
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Sets the proxy to use.
|
|
142
|
+
*
|
|
143
|
+
* @param {./lib/capabilities.ProxyConfig} proxy The proxy configuration to use.
|
|
144
|
+
* @return {!Options} A self reference.
|
|
145
|
+
*/
|
|
146
|
+
setProxy(proxy) {
|
|
147
|
+
this.proxy_ = proxy;
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
|
|
518
151
|
/**
|
|
519
152
|
* Converts this options instance to a {@link Capabilities} object.
|
|
520
153
|
* @param {Capabilities=} opt_capabilities The capabilities to
|
|
@@ -526,6 +159,9 @@ class Options {
|
|
|
526
159
|
if (this.logPrefs_) {
|
|
527
160
|
caps.set(Capability.LOGGING_PREFS, this.logPrefs_);
|
|
528
161
|
}
|
|
162
|
+
if (this.proxy_) {
|
|
163
|
+
caps.set(Capability.PROXY, this.proxy_);
|
|
164
|
+
}
|
|
529
165
|
if (this.options_) {
|
|
530
166
|
caps.set(OPTIONS_CAPABILITY_KEY, this);
|
|
531
167
|
}
|
|
@@ -555,19 +191,28 @@ class Options {
|
|
|
555
191
|
*/
|
|
556
192
|
class Driver extends webdriver.WebDriver {
|
|
557
193
|
/**
|
|
194
|
+
* Creates a new Safari session.
|
|
195
|
+
*
|
|
558
196
|
* @param {(Options|Capabilities)=} opt_config The configuration
|
|
559
197
|
* options for the new session.
|
|
560
198
|
* @param {promise.ControlFlow=} opt_flow The control flow to create
|
|
561
199
|
* the driver under.
|
|
200
|
+
* @return {!Driver} A new driver instance.
|
|
562
201
|
*/
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
202
|
+
static createSession(opt_config, opt_flow) {
|
|
203
|
+
let caps;
|
|
204
|
+
if (opt_config instanceof Options) {
|
|
205
|
+
caps = opt_config.toCapabilities();
|
|
206
|
+
} else {
|
|
207
|
+
caps = opt_config || Capabilities.safari()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let service = new ServiceBuilder().build();
|
|
211
|
+
let executor = new http.Executor(
|
|
212
|
+
service.start().then(url => new http.HttpClient(url)));
|
|
568
213
|
|
|
569
|
-
|
|
570
|
-
|
|
214
|
+
return /** @type {!Driver} */(webdriver.WebDriver.createSession(
|
|
215
|
+
executor, caps, opt_flow, this, () => service.kill()));
|
|
571
216
|
}
|
|
572
217
|
}
|
|
573
218
|
|
|
@@ -577,3 +222,4 @@ class Driver extends webdriver.WebDriver {
|
|
|
577
222
|
|
|
578
223
|
exports.Driver = Driver;
|
|
579
224
|
exports.Options = Options;
|
|
225
|
+
exports.ServiceBuilder = ServiceBuilder;
|
package/test/actions_test.js
CHANGED
|
@@ -26,28 +26,26 @@ var Browser = require('..').Browser,
|
|
|
26
26
|
|
|
27
27
|
test.suite(function(env) {
|
|
28
28
|
var driver;
|
|
29
|
-
test.beforeEach(function() { driver = env.builder().build(); });
|
|
30
|
-
test.afterEach(function() { driver.quit(); });
|
|
29
|
+
test.beforeEach(function*() { driver = yield env.builder().build(); });
|
|
30
|
+
test.afterEach(function() { return driver.quit(); });
|
|
31
31
|
|
|
32
32
|
test.ignore(
|
|
33
33
|
env.browsers(Browser.FIREFOX, Browser.PHANTOM_JS, Browser.SAFARI)).
|
|
34
34
|
describe('WebDriver.actions()', function() {
|
|
35
35
|
|
|
36
|
-
test.it('can move to and click element in an iframe', function() {
|
|
37
|
-
driver.get(fileServer.whereIs('click_tests/click_in_iframe.html'));
|
|
36
|
+
test.it('can move to and click element in an iframe', function*() {
|
|
37
|
+
yield driver.get(fileServer.whereIs('click_tests/click_in_iframe.html'));
|
|
38
38
|
|
|
39
|
-
driver.wait(until.elementLocated(By.id('ifr')), 5000)
|
|
40
|
-
.then(
|
|
41
|
-
driver.switchTo().frame(frame);
|
|
42
|
-
});
|
|
39
|
+
yield driver.wait(until.elementLocated(By.id('ifr')), 5000)
|
|
40
|
+
.then(frame => driver.switchTo().frame(frame));
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
driver.actions()
|
|
42
|
+
let link = yield driver.findElement(By.id('link'));
|
|
43
|
+
yield driver.actions()
|
|
46
44
|
.mouseMove(link)
|
|
47
45
|
.click()
|
|
48
46
|
.perform();
|
|
49
47
|
|
|
50
|
-
driver.wait(until.titleIs('Submitted Successfully!'), 5000);
|
|
48
|
+
return driver.wait(until.titleIs('Submitted Successfully!'), 5000);
|
|
51
49
|
});
|
|
52
50
|
|
|
53
51
|
});
|
|
@@ -205,22 +205,22 @@ test.suite(function(env) {
|
|
|
205
205
|
var driver;
|
|
206
206
|
|
|
207
207
|
test.afterEach(function() {
|
|
208
|
-
driver.quit();
|
|
208
|
+
return driver.quit();
|
|
209
209
|
});
|
|
210
210
|
|
|
211
211
|
describe('Chrome options', function() {
|
|
212
|
-
test.it('can start Chrome with custom args', function() {
|
|
212
|
+
test.it('can start Chrome with custom args', function*() {
|
|
213
213
|
var options = new chrome.Options().
|
|
214
214
|
addArguments('user-agent=foo;bar');
|
|
215
215
|
|
|
216
|
-
driver = env.builder()
|
|
217
|
-
setChromeOptions(options)
|
|
218
|
-
build();
|
|
216
|
+
driver = yield env.builder()
|
|
217
|
+
.setChromeOptions(options)
|
|
218
|
+
.build();
|
|
219
219
|
|
|
220
|
-
driver.get(test.Pages.ajaxyPage);
|
|
220
|
+
yield driver.get(test.Pages.ajaxyPage);
|
|
221
221
|
|
|
222
|
-
var userAgent =
|
|
223
|
-
'return window.navigator.userAgent');
|
|
222
|
+
var userAgent =
|
|
223
|
+
yield driver.executeScript('return window.navigator.userAgent');
|
|
224
224
|
assert(userAgent).equalTo('foo;bar');
|
|
225
225
|
});
|
|
226
226
|
});
|
|
@@ -35,11 +35,11 @@ test.suite(function(env) {
|
|
|
35
35
|
|
|
36
36
|
test.it('can be started on a custom path', function() {
|
|
37
37
|
service = new chrome.ServiceBuilder()
|
|
38
|
-
.
|
|
38
|
+
.setPath('/foo/bar/baz')
|
|
39
39
|
.build();
|
|
40
40
|
return service.start().then(function(url) {
|
|
41
41
|
assert(url).endsWith('/foo/bar/baz');
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
|
-
}, {browsers: ['chrome']});
|
|
45
|
+
}, {browsers: ['chrome']});
|