Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Side by Side Diff: pkg/webdriver/lib/webdriver.dart

Issue 12413012: Bring webdriver up to date with SDK changes, and a bit of refactoring. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library webdriver; 5 library webdriver;
6 6
7 import 'dart:json' as json; 7 import 'dart:json' as json;
8 import 'dart:uri'; 8 import 'dart:uri';
9 import 'dart:io'; 9 import 'dart:io';
10 import 'dart:async';
10 11
11 part 'src/base64decoder.dart'; 12 part 'src/base64decoder.dart';
12 13
13 /** 14 /**
14 * WebDriver bindings for Dart. 15 * WebDriver bindings for Dart.
15 * 16 *
16 * These bindings are based on the WebDriver JSON wire protocol spec 17 * These bindings are based on the WebDriver JSON wire protocol spec
17 * (http://code.google.com/p/selenium/wiki/JsonWireProtocol). Not 18 * (http://code.google.com/p/selenium/wiki/JsonWireProtocol). Not
18 * all of these commands are implemented yet by WebDriver itself. 19 * all of these commands are implemented yet by WebDriver itself.
19 * Nontheless this is a complete implementation of the spec as the 20 * Nontheless this is a complete implementation of the spec as the
20 * unsupported commands may be supported in the future. Currently, 21 * unsupported commands may be supported in the future. Currently,
21 * there are known issues with local and session storage, script 22 * there are known issues with local and session storage, script
22 * execution, and log access. 23 * execution, and log access.
23 * 24 *
24 * To use these bindings, the Selenium standalone server must be running. 25 * To use these bindings, the Selenium standalone server must be running.
25 * You can download it at http://code.google.com/p/selenium/downloads/list. 26 * You can download it at http://code.google.com/p/selenium/downloads/list.
26 * 27 *
27 * There are a number of commands that use ids to access page elements. 28 * There are a number of commands that use ids to access page elements.
28 * These ids are not the HTML ids; they are opaque ids internal to 29 * These ids are not the HTML ids; they are opaque ids internal to
29 * WebDriver. To get the id for an element you would first need to do 30 * WebDriver. To get the id for an element you would first need to do
30 * a search, get the results, and extract the WebDriver id from the returned 31 * a search, get the results, and extract the WebDriver id from the returned
31 * [Map] using the 'ELEMENT' key. For example: 32 * [Map] using the 'ELEMENT' key. For example:
32 * 33 *
33 * String id; 34 * String id;
34 * WebDriverSession session; 35 * WebDriverSession session;
35 * Future f = web_driver.newSession('chrome'); 36 * Future f = web_driver.newSession('chrome');
36 * f.chain((_session) { 37 * f.then((_session) {
37 * session = _session; 38 * session = _session;
38 * return session.setUrl('http://my.web.site.com'); 39 * return session.setUrl('http://my.web.site.com');
39 * }).chain((_) { 40 * }).then((_) {
40 * return session.findElement('id', 'username'); 41 * return session.findElement('id', 'username');
41 * }).chain((element) { 42 * }).then((element) {
42 * id = element['ELEMENT']; 43 * id = element['ELEMENT'];
43 * return session.sendKeyStrokesToElement(id, 44 * return session.sendKeyStrokesToElement(id,
44 * [ 'j', 'o', 'e', ' ', 'u', 's', 'e', 'r' ]); 45 * [ 'j', 'o', 'e', ' ', 'u', 's', 'e', 'r' ]);
45 * }).chain((_) { 46 * }).then((_) {
46 * return session.submit(id); 47 * return session.submit(id);
47 * }).chain((_) { 48 * }).then((_) {
48 * return session.close(); 49 * return session.close();
49 * }).then((_) { 50 * }).then((_) {
50 * session = null; 51 * session = null;
51 * }); 52 * });
52 */ 53 */
53 54
54 void writeStringToFile(String fileName, String contents) { 55 void writeStringToFile(String fileName, String contents) {
55 new File(fileName).writeAsStringSync(contents); 56 new File(fileName).writeAsStringSync(contents);
56 } 57 }
57 58
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 } 216 }
216 217
217 /** 218 /**
218 * Execute a request to the WebDriver server. [http_method] should be 219 * Execute a request to the WebDriver server. [http_method] should be
219 * one of 'GET', 'POST', or 'DELETE'. [command] is the text to append 220 * one of 'GET', 'POST', or 'DELETE'. [command] is the text to append
220 * to the base URL path to get the full URL. [params] are the additional 221 * to the base URL path to get the full URL. [params] are the additional
221 * parameters. If a [List] or [Map] they will be posted as JSON parameters. 222 * parameters. If a [List] or [Map] they will be posted as JSON parameters.
222 * If a number or string, "/params" is appended to the URL. 223 * If a number or string, "/params" is appended to the URL.
223 */ 224 */
224 void _serverRequest(String http_method, String command, Completer completer, 225 void _serverRequest(String http_method, String command, Completer completer,
225 [List successCodes, Map params, Function customHandler]) { 226 {List successCodes, Map params, Function customHandler}) {
226 var status = 0; 227 var status = 0;
227 var results = null; 228 var results = null;
228 var message = null; 229 var message = null;
229 if (successCodes == null) { 230 if (successCodes == null) {
230 successCodes = [ 200, 204 ]; 231 successCodes = [ 200, 204 ];
231 } 232 }
232 try { 233 try {
233 if (params != null && params is List && http_method != 'POST') {
234 throw new Exception(
235 'The http method called for ${command} is ${http_method} but it has '
236 'to be POST if you want to pass the JSON params '
237 '${json.stringify(params)}');
238 }
239
240 var path = command; 234 var path = command;
241 if (params != null && (params is num || params is String)) { 235 if (params != null) {
242 path = '$path/$params'; 236 if (params is num || params is String) {
237 path = '$path/$params';
238 params = null;
239 } else if (http_method != 'POST') {
240 throw new Exception(
241 'The http method called for ${command} is ${http_method} but it has '
242 'to be POST if you want to pass the JSON params '
243 '${json.stringify(params)}');
244 }
243 } 245 }
244 246
245 var client = new HttpClient(); 247 var client = new HttpClient();
246 var connection = client.open(http_method, _host, _port, path); 248 client.open(http_method, _host, _port, path).then((req) {
247 249 req.followRedirects = false;
248 connection.onRequest = (r) { 250 req.headers.add(HttpHeaders.ACCEPT, "application/json");
249 r.headers.add(HttpHeaders.ACCEPT, "application/json"); 251 req.headers.add(
250 r.headers.add(
251 HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8'); 252 HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8');
252 OutputStream s = r.outputStream; 253 if (params != null) {
253 if (params != null && params is Map) { 254 var body = json.stringify(params);
254 s.writeString(json.stringify(params)); 255 req.write(body);
255 } 256 }
256 s.close(); 257 req.close().then((rsp) {
257 }; 258 List<int> body = new List<int>();
258 connection.onError = (e) { 259 rsp.listen(body.addAll, onDone: () {
260 var value = null;
261 results = new String.fromCharCodes(body);
262 // For some reason we get a bunch of NULs on the end
263 // of the text and the json.parse blows up on these, so
264 // strip them.
265 // These NULs can be seen in the TCP packet, so it is not
266 // an issue with character encoding; it seems to be a bug
267 // in WebDriver stack.
268 for (var i = results.length; --i >= 0;) {
269 var code = results.codeUnitAt(i);
270 if (code != 0) {
271 results = results.substring(0, i + 1);
272 break;
273 }
274 }
275 if (successCodes.indexOf(rsp.statusCode) < 0) {
Siggi Cherem (dart-lang) 2013/03/09 00:04:59 weird indentation here?
gram 2013/03/09 00:12:36 Done.
276 throw 'Unexpected response ${rsp.statusCode}; $results';
277 }
278 if (status == 0 && results.length > 0) {
279 // 4xx responses send plain text; others send JSON.
280 if (rsp.statusCode < 400) {
281 results = json.parse(results);
282 status = results['status'];
283 }
284 if (results is Map && (results as Map).containsKey('value')) {
285 value = results['value'];
286 }
287 if (value is Map && value.containsKey('message')) {
288 message = value['message'];
289 }
290 }
291 if (status == 0) {
292 if (customHandler != null) {
293 customHandler(rsp, value);
294 } else if (completer != null) {
295 completer.complete(value);
296 }
297 } else {
Siggi Cherem (dart-lang) 2013/03/09 00:04:59 empty else?
gram 2013/03/09 00:12:36 Done.
298 }
299 });
300 })
301 .catchError((e) {
302 if (completer != null) {
303 completer.completeError(new WebDriverError(-1, e));
304 completer = null;
305 }
306 });
307 })
308 .catchError((e) {
259 if (completer != null) { 309 if (completer != null) {
260 completer.completeError(new WebDriverError(-1, e)); 310 completer.completeError(new WebDriverError(-1, e));
261 completer = null; 311 completer = null;
262 } 312 }
263 }; 313 });
264 connection.followRedirects = false;
265 connection.onResponse = (r) {
266 StringInputStream s = new StringInputStream(r.inputStream);
267 StringBuffer sbuf = new StringBuffer();
268 s.onData = () {
269 var data = s.read();
270 if (data != null) {
271 sbuf.write(data);
272 }
273 };
274 s.onClosed = () {
275 var value = null;
276 results = sbuf.toString().trim();
277 // For some reason we get a bunch of NULs on the end
278 // of the text and the json.parse blows up on these, so
279 // strip them.
280 // These NULs can be seen in the TCP packet, so it is not
281 // an issue with character encoding; it seems to be a bug
282 // in WebDriver stack.
283 for (var i = results.length; --i >= 0;) {
284 var code = results.codeUnitAt(i);
285 if (code != 0) {
286 results = results.substring(0, i + 1);
287 break;
288 }
289 }
290 if (successCodes.indexOf(r.statusCode) < 0) {
291 throw 'Unexpected response ${r.statusCode}';
292 }
293 if (status == 0 && results.length > 0) {
294 // 4xx responses send plain text; others send JSON.
295 if (r.statusCode < 400) {
296 results = json.parse(results);
297 status = results['status'];
298 }
299 if (results is Map && (results as Map).containsKey('value')) {
300 value = results['value'];
301 }
302 if (value is Map && value.containsKey('message')) {
303 message = value['message'];
304 }
305 }
306 if (status == 0) {
307 if (customHandler != null) {
308 customHandler(r, value);
309 } else if (completer != null) {
310 completer.complete(value);
311 }
312 }
313 };
314 };
315 } catch (e, s) { 314 } catch (e, s) {
316 completer.completeError( 315 completer.completeError(
317 new WebDriverError(-1, e), s); 316 new WebDriverError(-1, e), s);
318 completer = null; 317 completer = null;
319 } 318 }
320 } 319 }
321 320
322 Future _simpleCommand(method, extraPath, [successCodes, params]) { 321 Future _get(String extraPath) {
323 var completer = new Completer(); 322 var completer = new Completer();
324 _serverRequest(method, '${_path}/$extraPath', completer, 323 _serverRequest('GET', '${_path}/$extraPath', completer);
325 successCodes, params: params);
326 return completer.future; 324 return completer.future;
327 } 325 }
328 326
329 Future _get(extraPath, [successCodes]) => 327 Future _getCustom(String extraPath, Function customHandler) =>
330 _simpleCommand('GET', extraPath, successCodes); 328 _serverRequest('GET', '${_path}/$extraPath', null,
329 customHandler: customHandler);
331 330
332 Future _post(extraPath, [successCodes, params]) => 331 Future _post(String extraPath, [String params]) {
333 _simpleCommand('POST', extraPath, successCodes, params); 332 var completer = new Completer();
333 _serverRequest('POST', '${_path}/$extraPath', completer,
334 params: params);
335 return completer.future;
336 }
334 337
335 Future _delete(extraPath, [successCodes]) => 338 Future _delete(String extraPath) {
336 _simpleCommand('DELETE', extraPath, successCodes); 339 var completer = new Completer();
340 _serverRequest('DELETE', '${_path}/$extraPath', completer);
341 return completer.future;
342 }
337 } 343 }
338 344
339 class WebDriver extends WebDriverBase { 345 class WebDriver extends WebDriverBase {
340 346
341 WebDriver(host, port, path) : super(host, port, path); 347 WebDriver(host, port, path) : super(host, port, path);
342 348
343 /** 349 /**
344 * Create a new session. The server will attempt to create a session that 350 * Create a new session. The server will attempt to create a session that
345 * most closely matches the desired and required capabilities. Required 351 * most closely matches the desired and required capabilities. Required
346 * capabilities have higher priority than desired capabilities and must be 352 * capabilities have higher priority than desired capabilities and must be
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 */ 431 */
426 Future<WebDriverSession> newSession([ 432 Future<WebDriverSession> newSession([
427 browser = 'chrome', Map additional_capabilities]) { 433 browser = 'chrome', Map additional_capabilities]) {
428 var completer = new Completer(); 434 var completer = new Completer();
429 if (additional_capabilities == null) { 435 if (additional_capabilities == null) {
430 additional_capabilities = {}; 436 additional_capabilities = {};
431 } 437 }
432 438
433 additional_capabilities['browserName'] = browser; 439 additional_capabilities['browserName'] = browser;
434 440
435 _serverRequest('POST', '${_path}/session', null, [ 302 ], 441 _serverRequest('POST', '${_path}/session', null,
442 successCodes: [ 302 ],
436 customHandler: (r, v) { 443 customHandler: (r, v) {
437 var url = r.headers.value(HttpHeaders.LOCATION); 444 var url = r.headers.value(HttpHeaders.LOCATION);
438 var session = new WebDriverSession.fromUrl(url); 445 var session = new WebDriverSession.fromUrl(url);
439 completer.complete(session); 446 completer.complete(session);
440 }, params: { 'desiredCapabilities': additional_capabilities }); 447 },
448 params: { 'desiredCapabilities': additional_capabilities });
441 return completer.future; 449 return completer.future;
442 } 450 }
443 451
444 /** Get the set of currently active sessions. */ 452 /** Get the set of currently active sessions. */
445 Future<List<WebDriverSession>> getSessions() { 453 Future<List<WebDriverSession>> getSessions() {
446 var completer = new Completer(); 454 var completer = new Completer();
447 _get('sessions', (result) { 455 _getCustom('sessions', (r, v) {
448 var _sessions = []; 456 var _sessions = [];
449 for (var session in result) { 457 for (var session in v) {
450 _sessions.add(new WebDriverSession.fromUrl( 458 var url = 'http://${this._host}:${this._port}${this._path}/'
451 '${this._path}/session/${session["id"]}')); 459 'session/${session["id"]}';
460 _sessions.add(new WebDriverSession.fromUrl(url));
452 } 461 }
453 completer.complete(_sessions); 462 completer.complete(_sessions);
454 }); 463 });
455 return completer.future; 464 return completer.future;
456 } 465 }
457 466
458 /** Query the server's current status. */ 467 /** Query the server's current status. */
459 Future<Map> getStatus() => _get('status'); 468 Future<Map> getStatus() => _get('status');
460 } 469 }
461 470
462 class WebDriverWindow extends WebDriverBase { 471 class WebDriverWindow extends WebDriverBase {
463 WebDriverWindow.fromUrl(url) : super.fromUrl(url); 472 WebDriverWindow.fromUrl(url) : super.fromUrl(url);
464 473
465 /** Get the window size. */ 474 /** Get the window size. */
466 Future<Map> getSize() => _get('size'); 475 Future<Map> getSize() => _get('size');
467 476
468 /** 477 /**
469 * Set the window size. 478 * Set the window size.
470 * 479 *
471 * Potential Errors: 480 * Potential Errors:
472 * NoSuchWindow - If the specified window cannot be found. 481 * NoSuchWindow - If the specified window cannot be found.
473 */ 482 */
474 Future<String> setSize(int width, int height) => 483 Future<String> setSize(int width, int height) =>
475 _post('size', params: { 'width': width, 'height': height }); 484 _post('size', { 'width': width, 'height': height });
476 485
477 /** Get the window position. */ 486 /** Get the window position. */
478 Future<Map> getPosition() => _get('position'); 487 Future<Map> getPosition() => _get('position');
479 488
480 /** 489 /**
481 * Set the window position. 490 * Set the window position.
482 * 491 *
483 * Potential Errors: NoSuchWindow. 492 * Potential Errors: NoSuchWindow.
484 */ 493 */
485 Future setPosition(int x, int y) => 494 Future setPosition(int x, int y) =>
486 _post('position', params: { 'x': x, 'y': y }); 495 _post('position', { 'x': x, 'y': y });
487 496
488 /** Maximize the specified window if not already maximized. */ 497 /** Maximize the specified window if not already maximized. */
489 Future maximize() => _post('maximize'); 498 Future maximize() => _post('maximize');
490 } 499 }
491 500
492 class WebDriverSession extends WebDriverBase { 501 class WebDriverSession extends WebDriverBase {
493 WebDriverSession.fromUrl(url) : super.fromUrl(url); 502 WebDriverSession.fromUrl(url) : super.fromUrl(url);
494 503
495 /** Close the session. */ 504 /** Close the session. */
496 Future close() => _delete(''); 505 Future close() => _delete('');
497 506
498 /** Get the session capabilities. See [newSession] for details. */ 507 /** Get the session capabilities. See [newSession] for details. */
499 Future<Map> getCapabilities() => _get(''); 508 Future<Map> getCapabilities() => _get('');
500 509
501 /** 510 /**
502 * Configure the amount of time in milliseconds that a script can execute 511 * Configure the amount of time in milliseconds that a script can execute
503 * for before it is aborted and a Timeout error is returned to the client. 512 * for before it is aborted and a Timeout error is returned to the client.
504 */ 513 */
505 Future setScriptTimeout(t) => 514 Future setScriptTimeout(t) =>
506 _post('timeouts', params: { 'type': 'script', 'ms': t }); 515 _post('timeouts', { 'type': 'script', 'ms': t });
507 516
508 /*Future<String> setImplicitWaitTimeout(t) => 517 /*Future<String> setImplicitWaitTimeout(t) =>
509 simplePost('timeouts', { 'type': 'implicit', 'ms': t });*/ 518 simplePost('timeouts', { 'type': 'implicit', 'ms': t });*/
510 519
511 /** 520 /**
512 * Configure the amount of time in milliseconds that a page can load for 521 * Configure the amount of time in milliseconds that a page can load for
513 * before it is aborted and a Timeout error is returned to the client. 522 * before it is aborted and a Timeout error is returned to the client.
514 */ 523 */
515 Future setPageLoadTimeout(t) => 524 Future setPageLoadTimeout(t) =>
516 _post('timeouts', params: { 'type': 'page load', 'ms': t }); 525 _post('timeouts', { 'type': 'page load', 'ms': t });
517 526
518 /** 527 /**
519 * Set the amount of time, in milliseconds, that asynchronous scripts 528 * Set the amount of time, in milliseconds, that asynchronous scripts
520 * executed by /session/:sessionId/execute_async are permitted to run 529 * executed by /session/:sessionId/execute_async are permitted to run
521 * before they are aborted and a Timeout error is returned to the client. 530 * before they are aborted and a Timeout error is returned to the client.
522 */ 531 */
523 Future setAsyncScriptTimeout(t) => 532 Future setAsyncScriptTimeout(t) =>
524 _post('timeouts/async_script', params: { 'ms': t }); 533 _post('timeouts/async_script', { 'ms': t });
525 534
526 /** 535 /**
527 * Set the amount of time the driver should wait when searching for elements. 536 * Set the amount of time the driver should wait when searching for elements.
528 * When searching for a single element, the driver should poll the page until 537 * When searching for a single element, the driver should poll the page until
529 * an element is found or the timeout expires, whichever occurs first. When 538 * an element is found or the timeout expires, whichever occurs first. When
530 * searching for multiple elements, the driver should poll the page until at 539 * searching for multiple elements, the driver should poll the page until at
531 * least one element is found or the timeout expires, at which point it should 540 * least one element is found or the timeout expires, at which point it should
532 * return an empty list. 541 * return an empty list.
533 * 542 *
534 * If this command is never sent, the driver should default to an implicit 543 * If this command is never sent, the driver should default to an implicit
535 * wait of 0ms. 544 * wait of 0ms.
536 */ 545 */
537 Future setImplicitWaitTimeout(t) => 546 Future setImplicitWaitTimeout(t) =>
538 _post('timeouts/implicit_wait', params: { 'ms': t }); 547 _post('timeouts/implicit_wait', { 'ms': t });
539 548
540 /** 549 /**
541 * Retrieve the current window handle. 550 * Retrieve the current window handle.
542 * 551 *
543 * Potential Errors: NoSuchWindow. 552 * Potential Errors: NoSuchWindow.
544 */ 553 */
545 Future<String> getWindowHandle() => _get('window_handle'); 554 Future<String> getWindowHandle() => _get('window_handle');
546 555
547 /** 556 /**
548 * Retrieve a [WebDriverWindow] for the specified window. We don't 557 * Retrieve a [WebDriverWindow] for the specified window. We don't
(...skipping 13 matching lines...) Expand all
562 * 571 *
563 * Potential Errors: NoSuchWindow. 572 * Potential Errors: NoSuchWindow.
564 */ 573 */
565 Future<String> getUrl() => _get('url'); 574 Future<String> getUrl() => _get('url');
566 575
567 /** 576 /**
568 * Navigate to a new URL. 577 * Navigate to a new URL.
569 * 578 *
570 * Potential Errors: NoSuchWindow. 579 * Potential Errors: NoSuchWindow.
571 */ 580 */
572 Future setUrl(String url) => _post('url', params: { 'url': url }); 581 Future setUrl(String url) => _post('url', { 'url': url });
573 582
574 /** 583 /**
575 * Navigate forwards in the browser history, if possible. 584 * Navigate forwards in the browser history, if possible.
576 * 585 *
577 * Potential Errors: NoSuchWindow. 586 * Potential Errors: NoSuchWindow.
578 */ 587 */
579 Future navigateForward() => _post('forward'); 588 Future navigateForward() => _post('forward');
580 589
581 /** 590 /**
582 * Navigate backwards in the browser history, if possible. 591 * Navigate backwards in the browser history, if possible.
(...skipping 22 matching lines...) Expand all
605 * specified. 614 * specified.
606 * 615 *
607 * Arguments may be any JSON-primitive, array, or JSON object. JSON objects 616 * Arguments may be any JSON-primitive, array, or JSON object. JSON objects
608 * that define a WebElement reference will be converted to the corresponding 617 * that define a WebElement reference will be converted to the corresponding
609 * DOM element. Likewise, any WebElements in the script result will be 618 * DOM element. Likewise, any WebElements in the script result will be
610 * returned to the client as WebElement JSON objects. 619 * returned to the client as WebElement JSON objects.
611 * 620 *
612 * Potential Errors: NoSuchWindow, StaleElementReference, JavaScriptError. 621 * Potential Errors: NoSuchWindow, StaleElementReference, JavaScriptError.
613 */ 622 */
614 Future execute(String script, [List args]) => 623 Future execute(String script, [List args]) =>
615 _post('execute', params: { 'script': script, 'args': args }); 624 _post('execute', { 'script': script, 'args': args });
616 625
617 /** 626 /**
618 * Inject a snippet of JavaScript into the page for execution in the context 627 * Inject a snippet of JavaScript into the page for execution in the context
619 * of the currently selected frame. The executed script is assumed to be 628 * of the currently selected frame. The executed script is assumed to be
620 * asynchronous and must signal that it is done by invoking the provided 629 * asynchronous and must signal that it is done by invoking the provided
621 * callback, which is always provided as the final argument to the function. 630 * callback, which is always provided as the final argument to the function.
622 * The value to this callback will be returned to the client. 631 * The value to this callback will be returned to the client.
623 * 632 *
624 * Asynchronous script commands may not span page loads. If an unload event 633 * Asynchronous script commands may not span page loads. If an unload event
625 * is fired while waiting for a script result, an error should be returned 634 * is fired while waiting for a script result, an error should be returned
626 * to the client. 635 * to the client.
627 * 636 *
628 * The script argument defines the script to execute in the form of a function 637 * The script argument defines the script to execute in the form of a function
629 * body. The function will be invoked with the provided args array and the 638 * body. The function will be invoked with the provided args array and the
630 * values may be accessed via the arguments object in the order specified. 639 * values may be accessed via the arguments object in the order specified.
631 * The final argument will always be a callback function that must be invoked 640 * The final argument will always be a callback function that must be invoked
632 * to signal that the script has finished. 641 * to signal that the script has finished.
633 * 642 *
634 * Arguments may be any JSON-primitive, array, or JSON object. JSON objects 643 * Arguments may be any JSON-primitive, array, or JSON object. JSON objects
635 * that define a WebElement reference will be converted to the corresponding 644 * that define a WebElement reference will be converted to the corresponding
636 * DOM element. Likewise, any WebElements in the script result will be 645 * DOM element. Likewise, any WebElements in the script result will be
637 * returned to the client as WebElement JSON objects. 646 * returned to the client as WebElement JSON objects.
638 * 647 *
639 * Potential Errors: NoSuchWindow, StaleElementReference, Timeout (controlled 648 * Potential Errors: NoSuchWindow, StaleElementReference, Timeout (controlled
640 * by the [setAsyncScriptTimeout] command), JavaScriptError (if the script 649 * by the [setAsyncScriptTimeout] command), JavaScriptError (if the script
641 * callback is not invoked before the timout expires). 650 * callback is not invoked before the timout expires).
642 */ 651 */
643 Future executeAsync(String script, [List args]) => 652 Future executeAsync(String script, [List args]) =>
644 _post('execute_async', params: { 'script': script, 'args': args }); 653 _post('execute_async', { 'script': script, 'args': args });
645 654
646 /** 655 /**
647 * Take a screenshot of the current page (PNG). 656 * Take a screenshot of the current page (PNG).
648 * 657 *
649 * Potential Errors: NoSuchWindow. 658 * Potential Errors: NoSuchWindow.
650 */ 659 */
651 Future<List<int>> getScreenshot([fname]) { 660 Future<List<int>> getScreenshot([fname]) {
652 var completer = new Completer(); 661 var completer = new Completer();
653 var result = _serverRequest('GET', '$_path/screenshot', completer, 662 var result = _serverRequest('GET', '$_path/screenshot', completer,
654 customHandler: (r, v) { 663 customHandler: (r, v) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 * Make an engine that is available (appears on the list returned by 706 * Make an engine that is available (appears on the list returned by
698 * getAvailableEngines) active. After this call, the engine will be added 707 * getAvailableEngines) active. After this call, the engine will be added
699 * to the list of engines loaded in the IME daemon and the input sent using 708 * to the list of engines loaded in the IME daemon and the input sent using
700 * sendKeys will be converted by the active engine. Note that this is a 709 * sendKeys will be converted by the active engine. Note that this is a
701 * platform-independent method of activating IME (the platform-specific way 710 * platform-independent method of activating IME (the platform-specific way
702 * being using keyboard shortcuts). 711 * being using keyboard shortcuts).
703 * 712 *
704 * Potential Errors: ImeActivationFailedException, ImeNotAvailableException. 713 * Potential Errors: ImeActivationFailedException, ImeNotAvailableException.
705 */ 714 */
706 Future activateIme(String engine) => 715 Future activateIme(String engine) =>
707 _post('ime/activate', params: { 'engine': engine }); 716 _post('ime/activate', { 'engine': engine });
708 717
709 /** 718 /**
710 * Change focus to another frame on the page. If the frame id is null, 719 * Change focus to another frame on the page. If the frame id is null,
711 * the server should switch to the page's default content. 720 * the server should switch to the page's default content.
712 * [id] is the Identifier for the frame to change focus to, and can be 721 * [id] is the Identifier for the frame to change focus to, and can be
713 * a string, number, null, or JSON Object. 722 * a string, number, null, or JSON Object.
714 * 723 *
715 * Potential Errors: NoSuchWindow, NoSuchFrame. 724 * Potential Errors: NoSuchWindow, NoSuchFrame.
716 */ 725 */
717 Future setFrameFocus(id) => _post('frame', params: { 'id': id }); 726 Future setFrameFocus(id) => _post('frame', { 'id': id });
718 727
719 /** 728 /**
720 * Change focus to another window. The window to change focus to may be 729 * Change focus to another window. The window to change focus to may be
721 * specified by [name], which is its server assigned window handle, or 730 * specified by [name], which is its server assigned window handle, or
722 * the value of its name attribute. 731 * the value of its name attribute.
723 * 732 *
724 * Potential Errors: NoSuchWindow. 733 * Potential Errors: NoSuchWindow.
725 */ 734 */
726 Future setWindowFocus(name) => 735 Future setWindowFocus(name) => _post('window', { 'name': name });
727 _post('window', params: { 'name': name });
728 736
729 /** 737 /**
730 * Close the current window. 738 * Close the current window.
731 * 739 *
732 * Potential Errors: NoSuchWindow. 740 * Potential Errors: NoSuchWindow.
733 */ 741 */
734 Future closeWindow() => _delete('window'); 742 Future closeWindow() => _delete('window');
735 743
736 /** 744 /**
737 * Retrieve all cookies visible to the current page. 745 * Retrieve all cookies visible to the current page.
(...skipping 17 matching lines...) Expand all
755 * Potential Errors: NoSuchWindow. 763 * Potential Errors: NoSuchWindow.
756 */ 764 */
757 Future<List<Map>> getCookies() => _get('cookie'); 765 Future<List<Map>> getCookies() => _get('cookie');
758 766
759 /** 767 /**
760 * Set a cookie. If the cookie path is not specified, it should be set 768 * Set a cookie. If the cookie path is not specified, it should be set
761 * to "/". Likewise, if the domain is omitted, it should default to the 769 * to "/". Likewise, if the domain is omitted, it should default to the
762 * current page's domain. See [getCookies] for the structure of a cookie 770 * current page's domain. See [getCookies] for the structure of a cookie
763 * Map. 771 * Map.
764 */ 772 */
765 Future setCookie(Map cookie) => 773 Future setCookie(Map cookie) => _post('cookie', { 'cookie': cookie });
766 _post('cookie', params: { 'cookie': cookie });
767 774
768 /** 775 /**
769 * Delete all cookies visible to the current page. 776 * Delete all cookies visible to the current page.
770 * 777 *
771 * Potential Errors: InvalidCookieDomain (the cookie's domain is not 778 * Potential Errors: InvalidCookieDomain (the cookie's domain is not
772 * visible from the current page), NoSuchWindow, UnableToSetCookie (if 779 * visible from the current page), NoSuchWindow, UnableToSetCookie (if
773 * attempting to set a cookie on a page that does not support cookies, 780 * attempting to set a cookie on a page that does not support cookies,
774 * e.g. pages with mime-type text/plain). 781 * e.g. pages with mime-type text/plain).
775 */ 782 */
776 Future deleteCookies() => _delete('cookie'); 783 Future deleteCookies() => _delete('cookie');
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 * partially matches the search value. 827 * partially matches the search value.
821 * 828 *
822 * 'tag name' - Returns an element whose tag name matches the search value. 829 * 'tag name' - Returns an element whose tag name matches the search value.
823 * 830 *
824 * 'xpath' - Returns an element matching an XPath expression. 831 * 'xpath' - Returns an element matching an XPath expression.
825 * 832 *
826 * Potential Errors: NoSuchWindow, NoSuchElement, XPathLookupError (if 833 * Potential Errors: NoSuchWindow, NoSuchElement, XPathLookupError (if
827 * using XPath and the input expression is invalid). 834 * using XPath and the input expression is invalid).
828 */ 835 */
829 Future<String> findElement(String strategy, String searchValue) => 836 Future<String> findElement(String strategy, String searchValue) =>
830 _post('element', params: { 'using': strategy, 'value' : searchValue }); 837 _post('element', { 'using': strategy, 'value' : searchValue });
831 838
832 /** 839 /**
833 * Search for multiple elements on the page, starting from the document root. 840 * Search for multiple elements on the page, starting from the document root.
834 * The located elements will be returned as WebElement JSON objects. See 841 * The located elements will be returned as WebElement JSON objects. See
835 * [findElement] for the locator strategies that each server supports. 842 * [findElement] for the locator strategies that each server supports.
836 * Elements are be returned in the order located in the DOM. 843 * Elements are be returned in the order located in the DOM.
837 * 844 *
838 * Potential Errors: NoSuchWindow, XPathLookupError. 845 * Potential Errors: NoSuchWindow, XPathLookupError.
839 */ 846 */
840 Future<List<String>> findElements(String strategy, String searchValue) => 847 Future<List<String>> findElements(String strategy, String searchValue) =>
841 _post('elements', params: { 'using': strategy, 'value' : searchValue }); 848 _post('elements', { 'using': strategy, 'value' : searchValue });
842 849
843 /** 850 /**
844 * Get the element on the page that currently has focus. The element will 851 * Get the element on the page that currently has focus. The element will
845 * be returned as a WebElement JSON object. 852 * be returned as a WebElement JSON object.
846 * 853 *
847 * Potential Errors: NoSuchWindow. 854 * Potential Errors: NoSuchWindow.
848 */ 855 */
849 Future<String> getElementWithFocus() => _post('element/active'); 856 Future<String> getElementWithFocus() => _post('element/active');
850 857
851 /** 858 /**
852 * Search for an element on the page, starting from element with id [id]. 859 * Search for an element on the page, starting from element with id [id].
853 * The located element will be returned as WebElement JSON objects. See 860 * The located element will be returned as WebElement JSON objects. See
854 * [findElement] for the locator strategies that each server supports. 861 * [findElement] for the locator strategies that each server supports.
855 * 862 *
856 * Potential Errors: NoSuchWindow, XPathLookupError. 863 * Potential Errors: NoSuchWindow, XPathLookupError.
857 */ 864 */
858 Future<String> 865 Future<String>
859 findElementFromId(String id, String strategy, String searchValue) { 866 findElementFromId(String id, String strategy, String searchValue) {
860 _post('element/$id/element', 867 _post('element/$id/element', { 'using': strategy, 'value' : searchValue });
861 params: { 'using': strategy, 'value' : searchValue });
862 } 868 }
863 869
864 /** 870 /**
865 * Search for multiple elements on the page, starting from the element with 871 * Search for multiple elements on the page, starting from the element with
866 * id [id].The located elements will be returned as WebElement JSON objects. 872 * id [id].The located elements will be returned as WebElement JSON objects.
867 * See [findElement] for the locator strategies that each server supports. 873 * See [findElement] for the locator strategies that each server supports.
868 * Elements are be returned in the order located in the DOM. 874 * Elements are be returned in the order located in the DOM.
869 * 875 *
870 * Potential Errors: NoSuchWindow, XPathLookupError. 876 * Potential Errors: NoSuchWindow, XPathLookupError.
871 */ 877 */
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 * either the modifier is encountered again in the sequence, or the NULL 1001 * either the modifier is encountered again in the sequence, or the NULL
996 * (U+E000) key is encountered. 1002 * (U+E000) key is encountered.
997 * 1003 *
998 * - Each key sequence is terminated with an implicit NULL key. 1004 * - Each key sequence is terminated with an implicit NULL key.
999 * Subsequently, all depressed modifier keys are released (with 1005 * Subsequently, all depressed modifier keys are released (with
1000 * corresponding keyup events) at the end of the sequence. 1006 * corresponding keyup events) at the end of the sequence.
1001 * 1007 *
1002 * Potential Errors: NoSuchWindow, StaleElementReference, ElementNotVisible. 1008 * Potential Errors: NoSuchWindow, StaleElementReference, ElementNotVisible.
1003 */ 1009 */
1004 Future sendKeyStrokesToElement(String id, List<String> keys) => 1010 Future sendKeyStrokesToElement(String id, List<String> keys) =>
1005 _post('element/$id/value', params: { 'value': keys }); 1011 _post('element/$id/value', { 'value': keys });
1006 1012
1007 /** 1013 /**
1008 * Send a sequence of key strokes to the active element. This command is 1014 * Send a sequence of key strokes to the active element. This command is
1009 * similar to [sendKeyStrokesToElement] command in every aspect except the 1015 * similar to [sendKeyStrokesToElement] command in every aspect except the
1010 * implicit termination: The modifiers are not released at the end of the 1016 * implicit termination: The modifiers are not released at the end of the
1011 * call. Rather, the state of the modifier keys is kept between calls, 1017 * call. Rather, the state of the modifier keys is kept between calls,
1012 * so mouse interactions can be performed while modifier keys are depressed. 1018 * so mouse interactions can be performed while modifier keys are depressed.
1013 * 1019 *
1014 * Potential Errors: NoSuchWindow. 1020 * Potential Errors: NoSuchWindow.
1015 */ 1021 */
1016 Future sendKeyStrokes(List<String> keys) => 1022 Future sendKeyStrokes(List<String> keys) => _post('keys', { 'value': keys });
1017 _post('keys', params: { 'value': keys });
1018 1023
1019 /** 1024 /**
1020 * Query for an element's tag name, as a lower-case string. 1025 * Query for an element's tag name, as a lower-case string.
1021 * 1026 *
1022 * Potential Errors: NoSuchWindow, StaleElementReference. 1027 * Potential Errors: NoSuchWindow, StaleElementReference.
1023 */ 1028 */
1024 Future<String> getElementTagName(String id) => _get('element/$id/name'); 1029 Future<String> getElementTagName(String id) => _get('element/$id/name');
1025 1030
1026 /** 1031 /**
1027 * Clear a TEXTAREA or text INPUT element's value. 1032 * Clear a TEXTAREA or text INPUT element's value.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 * Potential Errors: NoAlertPresent. 1117 * Potential Errors: NoAlertPresent.
1113 */ 1118 */
1114 Future<String> getAlertText() => _get('alert_text'); 1119 Future<String> getAlertText() => _get('alert_text');
1115 1120
1116 /** 1121 /**
1117 * Sends keystrokes to a JavaScript prompt() dialog. 1122 * Sends keystrokes to a JavaScript prompt() dialog.
1118 * 1123 *
1119 * Potential Errors: NoAlertPresent. 1124 * Potential Errors: NoAlertPresent.
1120 */ 1125 */
1121 Future sendKeyStrokesToPrompt(String text) => 1126 Future sendKeyStrokesToPrompt(String text) =>
1122 _post('alert_text', params: { 'text': text }); 1127 _post('alert_text', { 'text': text });
1123 1128
1124 /** 1129 /**
1125 * Accepts the currently displayed alert dialog. Usually, this is equivalent 1130 * Accepts the currently displayed alert dialog. Usually, this is equivalent
1126 * to clicking on the 'OK' button in the dialog. 1131 * to clicking on the 'OK' button in the dialog.
1127 * 1132 *
1128 * Potential Errors: NoAlertPresent. 1133 * Potential Errors: NoAlertPresent.
1129 */ 1134 */
1130 Future acceptAlert() => _post('accept_alert'); 1135 Future acceptAlert() => _post('accept_alert');
1131 1136
1132 /** 1137 /**
1133 * Dismisses the currently displayed alert dialog. For confirm() and prompt() 1138 * Dismisses the currently displayed alert dialog. For confirm() and prompt()
1134 * dialogs, this is equivalent to clicking the 'Cancel' button. For alert() 1139 * dialogs, this is equivalent to clicking the 'Cancel' button. For alert()
1135 * dialogs, this is equivalent to clicking the 'OK' button. 1140 * dialogs, this is equivalent to clicking the 'OK' button.
1136 * 1141 *
1137 * Potential Errors: NoAlertPresent. 1142 * Potential Errors: NoAlertPresent.
1138 */ 1143 */
1139 Future dismissAlert() => _post('dismiss_alert'); 1144 Future dismissAlert() => _post('dismiss_alert');
1140 1145
1141 /** 1146 /**
1142 * Move the mouse by an offset of the specificed element. If no element is 1147 * Move the mouse by an offset of the specificed element. If no element is
1143 * specified, the move is relative to the current mouse cursor. If an 1148 * specified, the move is relative to the current mouse cursor. If an
1144 * element is provided but no offset, the mouse will be moved to the center 1149 * element is provided but no offset, the mouse will be moved to the center
1145 * of the element. If the element is not visible, it will be scrolled 1150 * of the element. If the element is not visible, it will be scrolled
1146 * into view. 1151 * into view.
1147 */ 1152 */
1148 Future moveTo(String id, int x, int y) => 1153 Future moveTo(String id, int x, int y) =>
1149 _post('moveto', params: { 'element': id, 'xoffset': x, 'yoffset' : y}); 1154 _post('moveto', { 'element': id, 'xoffset': x, 'yoffset' : y});
1150 1155
1151 /** 1156 /**
1152 * Click a mouse button (at the coordinates set by the last [moveTo] command). 1157 * Click a mouse button (at the coordinates set by the last [moveTo] command).
1153 * Note that calling this command after calling [buttonDown] and before 1158 * Note that calling this command after calling [buttonDown] and before
1154 * calling [buttonUp] (or any out-of-order interactions sequence) will yield 1159 * calling [buttonUp] (or any out-of-order interactions sequence) will yield
1155 * undefined behaviour). 1160 * undefined behaviour).
1156 * 1161 *
1157 * [button] should be 0 for left, 1 for middle, or 2 for right. 1162 * [button] should be 0 for left, 1 for middle, or 2 for right.
1158 */ 1163 */
1159 Future clickMouse([button = 0]) => 1164 Future clickMouse([button = 0]) => _post('click', { 'button' : button });
1160 _post('click', params: { 'button' : button });
1161 1165
1162 /** 1166 /**
1163 * Click and hold the left mouse button (at the coordinates set by the last 1167 * Click and hold the left mouse button (at the coordinates set by the last
1164 * [moveTo] command). Note that the next mouse-related command that should 1168 * [moveTo] command). Note that the next mouse-related command that should
1165 * follow is [buttonDown]. Any other mouse command (such as [click] or 1169 * follow is [buttonDown]. Any other mouse command (such as [click] or
1166 * another call to [buttonDown]) will yield undefined behaviour. 1170 * another call to [buttonDown]) will yield undefined behaviour.
1167 * 1171 *
1168 * [button] should be 0 for left, 1 for middle, or 2 for right. 1172 * [button] should be 0 for left, 1 for middle, or 2 for right.
1169 */ 1173 */
1170 Future buttonDown([button = 0]) => 1174 Future buttonDown([button = 0]) => _post('click', { 'button' : button });
1171 _post('click', params: { 'button' : button });
1172 1175
1173 /** 1176 /**
1174 * Releases the mouse button previously held (where the mouse is currently 1177 * Releases the mouse button previously held (where the mouse is currently
1175 * at). Must be called once for every [buttonDown] command issued. See the 1178 * at). Must be called once for every [buttonDown] command issued. See the
1176 * note in [click] and [buttonDown] about implications of out-of-order 1179 * note in [click] and [buttonDown] about implications of out-of-order
1177 * commands. 1180 * commands.
1178 * 1181 *
1179 * [button] should be 0 for left, 1 for middle, or 2 for right. 1182 * [button] should be 0 for left, 1 for middle, or 2 for right.
1180 */ 1183 */
1181 Future buttonUp([button = 0]) => 1184 Future buttonUp([button = 0]) => _post('click', { 'button' : button });
1182 _post('click', params: { 'button' : button });
1183 1185
1184 /** Double-clicks at the current mouse coordinates (set by [moveTo]). */ 1186 /** Double-clicks at the current mouse coordinates (set by [moveTo]). */
1185 Future doubleClick() => _post('doubleclick'); 1187 Future doubleClick() => _post('doubleclick');
1186 1188
1187 /** Single tap on the touch enabled device on the element with id [id]. */ 1189 /** Single tap on the touch enabled device on the element with id [id]. */
1188 Future touchClick(String id) => 1190 Future touchClick(String id) => _post('touch/click', { 'element': id });
1189 _post('touch/click', params: { 'element': id });
1190 1191
1191 /** Finger down on the screen. */ 1192 /** Finger down on the screen. */
1192 Future touchDown(int x, int y) => 1193 Future touchDown(int x, int y) => _post('touch/down', { 'x': x, 'y': y });
1193 _post('touch/down', params: { 'x': x, 'y': y });
1194 1194
1195 /** Finger up on the screen. */ 1195 /** Finger up on the screen. */
1196 Future touchUp(int x, int y) => 1196 Future touchUp(int x, int y) => _post('touch/up', { 'x': x, 'y': y });
1197 _post('touch/up', params: { 'x': x, 'y': y });
1198 1197
1199 /** Finger move on the screen. */ 1198 /** Finger move on the screen. */
1200 Future touchMove(int x, int y) => 1199 Future touchMove(int x, int y) => _post('touch/move', { 'x': x, 'y': y });
1201 _post('touch/move', params: { 'x': x, 'y': y });
1202 1200
1203 /** 1201 /**
1204 * Scroll on the touch screen using finger based motion events. If [id] is 1202 * Scroll on the touch screen using finger based motion events. If [id] is
1205 * specified, scrolling will start at a particular screen location. 1203 * specified, scrolling will start at a particular screen location.
1206 */ 1204 */
1207 Future touchScroll(int xOffset, int yOffset, [String id = null]) { 1205 Future touchScroll(int xOffset, int yOffset, [String id = null]) {
1208 if (id == null) { 1206 if (id == null) {
1209 return _post('touch/scroll', 1207 return _post('touch/scroll', { 'xoffset': xOffset, 'yoffset': yOffset });
1210 params: { 'xoffset': xOffset, 'yoffset': yOffset });
1211 } else { 1208 } else {
1212 return _post('touch/scroll', 1209 return _post('touch/scroll',
1213 params: { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset }); 1210 { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset });
1214 } 1211 }
1215 } 1212 }
1216 1213
1217 /** Double tap on the touch screen using finger motion events. */ 1214 /** Double tap on the touch screen using finger motion events. */
1218 Future touchDoubleClick(String id) => 1215 Future touchDoubleClick(String id) =>
1219 _post('touch/doubleclick', params: { 'element': id }); 1216 _post('touch/doubleclick', { 'element': id });
1220 1217
1221 /** Long press on the touch screen using finger motion events. */ 1218 /** Long press on the touch screen using finger motion events. */
1222 Future touchLongClick(String id) => 1219 Future touchLongClick(String id) =>
1223 _post('touch/longclick', params: { 'element': id }); 1220 _post('touch/longclick', { 'element': id });
1224 1221
1225 /** 1222 /**
1226 * Flick on the touch screen using finger based motion events, starting 1223 * Flick on the touch screen using finger based motion events, starting
1227 * at a particular screen location. [speed] is in pixels-per-second. 1224 * at a particular screen location. [speed] is in pixels-per-second.
1228 */ 1225 */
1229 Future touchFlickFrom(String id, int xOffset, int yOffset, int speed) => 1226 Future touchFlickFrom(String id, int xOffset, int yOffset, int speed) =>
1230 _post('touch/flick', 1227 _post('touch/flick',
1231 params: { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset, 1228 { 'element': id, 'xoffset': xOffset, 'yoffset': yOffset,
1232 'speed': speed }); 1229 'speed': speed });
1233 1230
1234 /** 1231 /**
1235 * Flick on the touch screen using finger based motion events. Use this 1232 * Flick on the touch screen using finger based motion events. Use this
1236 * instead of [touchFlickFrom] if you don'tr care where the flick starts. 1233 * instead of [touchFlickFrom] if you don'tr care where the flick starts.
1237 */ 1234 */
1238 Future touchFlick(int xSpeed, int ySpeed) => 1235 Future touchFlick(int xSpeed, int ySpeed) =>
1239 _post('touch/flick', params: { 'xSpeed': xSpeed, 'ySpeed': ySpeed }); 1236 _post('touch/flick', { 'xSpeed': xSpeed, 'ySpeed': ySpeed });
1240 1237
1241 /** 1238 /**
1242 * Get the current geo location. Returns a [Map] with latitude, 1239 * Get the current geo location. Returns a [Map] with latitude,
1243 * longitude and altitude properties. 1240 * longitude and altitude properties.
1244 */ 1241 */
1245 Future<Map> getGeolocation() => _get('location'); 1242 Future<Map> getGeolocation() => _get('location');
1246 1243
1247 /** Set the current geo location. */ 1244 /** Set the current geo location. */
1248 Future setLocation(double latitude, double longitude, double altitude) => 1245 Future setLocation(double latitude, double longitude, double altitude) =>
1249 _post('location', params: 1246 _post('location',
1250 { 'latitude': latitude, 1247 { 'latitude': latitude,
1251 'longitude': longitude, 1248 'longitude': longitude,
1252 'altitude': altitude }); 1249 'altitude': altitude });
1253 1250
1254 /** 1251 /**
1255 * Get all keys of the local storage. Completes with [null] if there 1252 * Get all keys of the local storage. Completes with [null] if there
1256 * are no keys or the keys could not be retrieved. 1253 * are no keys or the keys could not be retrieved.
1257 * 1254 *
1258 * Potential Errors: NoSuchWindow. 1255 * Potential Errors: NoSuchWindow.
1259 */ 1256 */
1260 Future<List<String>> getLocalStorageKeys() => _get('local_storage'); 1257 Future<List<String>> getLocalStorageKeys() => _get('local_storage');
1261 1258
1262 /** 1259 /**
1263 * Set the local storage item for the given key. 1260 * Set the local storage item for the given key.
1264 * 1261 *
1265 * Potential Errors: NoSuchWindow. 1262 * Potential Errors: NoSuchWindow.
1266 */ 1263 */
1267 Future setLocalStorageItem(String key, String value) => 1264 Future setLocalStorageItem(String key, String value) =>
1268 _post('local_storage', params: { 'key': key, 'value': value }); 1265 _post('local_storage', { 'key': key, 'value': value });
1269 1266
1270 /** 1267 /**
1271 * Clear the local storage. 1268 * Clear the local storage.
1272 * 1269 *
1273 * Potential Errors: NoSuchWindow. 1270 * Potential Errors: NoSuchWindow.
1274 */ 1271 */
1275 Future clearLocalStorage() => _delete('local_storage'); 1272 Future clearLocalStorage() => _delete('local_storage');
1276 1273
1277 /** 1274 /**
1278 * Get the local storage item for the given key. 1275 * Get the local storage item for the given key.
(...skipping 24 matching lines...) Expand all
1303 * Potential Errors: NoSuchWindow. 1300 * Potential Errors: NoSuchWindow.
1304 */ 1301 */
1305 Future<List<String>> getSessionStorageKeys() => _get('session_storage'); 1302 Future<List<String>> getSessionStorageKeys() => _get('session_storage');
1306 1303
1307 /** 1304 /**
1308 * Set the sessionstorage item for the given key. 1305 * Set the sessionstorage item for the given key.
1309 * 1306 *
1310 * Potential Errors: NoSuchWindow. 1307 * Potential Errors: NoSuchWindow.
1311 */ 1308 */
1312 Future setSessionStorageItem(String key, String value) => 1309 Future setSessionStorageItem(String key, String value) =>
1313 _post('session_storage', params: { 'key': key, 'value': value }); 1310 _post('session_storage', { 'key': key, 'value': value });
1314 1311
1315 /** 1312 /**
1316 * Clear the session storage. 1313 * Clear the session storage.
1317 * 1314 *
1318 * Potential Errors: NoSuchWindow. 1315 * Potential Errors: NoSuchWindow.
1319 */ 1316 */
1320 Future clearSessionStorage() => _delete('session_storage'); 1317 Future clearSessionStorage() => _delete('session_storage');
1321 1318
1322 /** 1319 /**
1323 * Get the session storage item for the given key. 1320 * Get the session storage item for the given key.
(...skipping 22 matching lines...) Expand all
1346 Future<List<String>> getLogTypes() => _get('log/types'); 1343 Future<List<String>> getLogTypes() => _get('log/types');
1347 1344
1348 /** 1345 /**
1349 * Get the log for a given log type. Log buffer is reset after each request. 1346 * Get the log for a given log type. Log buffer is reset after each request.
1350 * Each log entry is a [Map] with these fields: 1347 * Each log entry is a [Map] with these fields:
1351 * 1348 *
1352 * 'timestamp' (int) - The timestamp of the entry. 1349 * 'timestamp' (int) - The timestamp of the entry.
1353 * 'level' (String) - The log level of the entry, for example, "INFO". 1350 * 'level' (String) - The log level of the entry, for example, "INFO".
1354 * 'message' (String) - The log message. 1351 * 'message' (String) - The log message.
1355 */ 1352 */
1356 Future<List<Map>> getLogs(String type) => 1353 Future<List<Map>> getLogs(String type) => _post('log', { 'type': type });
1357 _post('log', params: { 'type': type });
1358 } 1354 }
OLDNEW
« no previous file with comments | « no previous file | pkg/webdriver/test/webdriver_test.dart » ('j') | pkg/webdriver/test/webdriver_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698