Make the WebDriver API more async/await-friendly.
Update all tests to use async/await.
Delete PageLoader.
Delete Touch APIs.
diff --git a/lib/src/alert.dart b/lib/src/alert.dart
index 796b78f..0dfd17f 100644
--- a/lib/src/alert.dart
+++ b/lib/src/alert.dart
@@ -8,8 +8,7 @@
*/
final String text;
- Alert._(this.text, driver)
- : super(driver, '');
+ Alert._(this.text, driver) : super(driver, '');
/**
* Accepts the currently displayed alert (may not be the alert for which
@@ -41,6 +40,6 @@
* alert.
*/
Future sendKeys(String keysToSend) async {
- await _post('alert_text', { 'text': keysToSend });
+ await _post('alert_text', {'text': keysToSend});
}
}
diff --git a/lib/src/capabilities.dart b/lib/src/capabilities.dart
index 85f910b..170993e 100644
--- a/lib/src/capabilities.dart
+++ b/lib/src/capabilities.dart
@@ -23,19 +23,19 @@
"webdriver.logging.profiler.enabled";
static Map<String, dynamic> get chrome => empty
- ..[BROWSER_NAME] = Browser.CHROME
- ..[VERSION] = ''
- ..[PLATFORM] = Platform.ANY;
+ ..[BROWSER_NAME] = Browser.CHROME
+ ..[VERSION] = ''
+ ..[PLATFORM] = Platform.ANY;
static Map<String, dynamic> get firefox => empty
- ..[BROWSER_NAME] = Browser.FIREFOX
- ..[VERSION] = ''
- ..[PLATFORM] = Platform.ANY;
+ ..[BROWSER_NAME] = Browser.FIREFOX
+ ..[VERSION] = ''
+ ..[PLATFORM] = Platform.ANY;
static Map<String, dynamic> get android => empty
- ..[BROWSER_NAME] = Browser.ANDROID
- ..[VERSION] = ''
- ..[PLATFORM] = Platform.ANDROID;
+ ..[BROWSER_NAME] = Browser.ANDROID
+ ..[VERSION] = ''
+ ..[PLATFORM] = Platform.ANDROID;
static Map<String, dynamic> get empty => new Map<String, dynamic>();
}
@@ -49,13 +49,13 @@
static const String GOOGLECHROME = "googlechrome";
static const String SAFARI = "safari";
static const String OPERA = "opera";
- static const String IEXPLORE= "iexplore";
- static const String IEXPLORE_PROXY= "iexploreproxy";
+ static const String IEXPLORE = "iexplore";
+ static const String IEXPLORE_PROXY = "iexploreproxy";
static const String SAFARI_PROXY = "safariproxy";
static const String CHROME = "chrome";
static const String KONQUEROR = "konqueror";
static const String MOCK = "mock";
- static const String IE_HTA="iehta";
+ static const String IE_HTA = "iehta";
static const String ANDROID = "android";
static const String HTMLUNIT = "htmlunit";
static const String IE = "internet explorer";
diff --git a/lib/src/command_processor.dart b/lib/src/command_processor.dart
index e8695ef..413a257 100644
--- a/lib/src/command_processor.dart
+++ b/lib/src/command_processor.dart
@@ -1,39 +1,53 @@
part of webdriver;
-final ContentType _contentTypeJson = new ContentType("application", "json", charset: "utf-8");
-const _defaultDecoder = const JsonDecoder();
+final ContentType _contentTypeJson =
+ new ContentType("application", "json", charset: "utf-8");
class _CommandProcessor {
-
final HttpClient client = new HttpClient();
- Future<Object> post(Uri uri, dynamic params, {Converter<String, dynamic> decoder: _defaultDecoder}) async {
+ Future<Object> post(Uri uri, dynamic params, {bool value: true}) async {
HttpClientRequest request = await client.postUrl(uri);
_setUpRequest(request);
request.headers.contentType = _contentTypeJson;
- request.encoding = UTF8;
- request.write(JSON.encode(params));
- return await _processResponse(await request.close(), decoder);
+ if (params != null) {
+ var body = UTF8.encode(JSON.encode(params));
+ request.contentLength = body.length;
+ request.add(body);
+ } else {
+ request.contentLength = 0;
+ }
+ return await _processResponse(await request.close(), value);
}
- Future<Object> get(Uri uri, {Converter<String, dynamic> decoder: _defaultDecoder}) async {
+ Future<Object> get(Uri uri, {bool value: true}) async {
HttpClientRequest request = await client.getUrl(uri);
_setUpRequest(request);
- return await _processResponse(await request.close(), decoder);
+ return await _processResponse(await request.close(), value);
}
- Future<Object> delete(Uri uri, {Converter<String, dynamic> decoder: _defaultDecoder}) async {
+ Future<Object> delete(Uri uri, {bool value: true}) async {
HttpClientRequest request = await client.deleteUrl(uri);
_setUpRequest(request);
- return await _processResponse(await request.close(), decoder);
+ return await _processResponse(await request.close(), value);
}
- _processResponse(HttpClientResponse response, Converter<String, dynamic> decoder) async {
- var respBody = decoder.convert(await UTF8.decodeStream(response));
- if (response.statusCode < 200 || response.statusCode > 299 || (respBody is Map && respBody['status'] != 0)) {
- throw new WebDriverException(httpStatusCode: response.statusCode, httpReasonPhrase: response.reasonPhrase, jsonResp: respBody);
+ _processResponse(HttpClientResponse response, bool value) async {
+ var respBody = await UTF8.decodeStream(response);
+
+ try {
+ respBody = JSON.decode(respBody);
+ } catch (e) {}
+
+ if (response.statusCode < 200 ||
+ response.statusCode > 299 ||
+ (respBody is Map && respBody['status'] != 0)) {
+ throw new WebDriverException(
+ httpStatusCode: response.statusCode,
+ httpReasonPhrase: response.reasonPhrase,
+ jsonResp: respBody);
}
- if (respBody is Map) {
+ if (value && respBody is Map) {
return respBody['value'];
}
return respBody;
@@ -46,4 +60,4 @@
request.headers.add(HttpHeaders.ACCEPT_CHARSET, UTF8.name);
request.headers.add(HttpHeaders.CACHE_CONTROL, "no-cache");
}
-}
\ No newline at end of file
+}
diff --git a/lib/src/common.dart b/lib/src/common.dart
index 04e2c79..bfce556 100644
--- a/lib/src/common.dart
+++ b/lib/src/common.dart
@@ -7,9 +7,7 @@
* attributes or css styles.
*/
class Attributes extends _WebDriverBase {
-
- Attributes._(driver, command)
- : super(driver, command);
+ Attributes._(driver, command) : super(driver, command);
Future<String> operator [](String name) => _get(name);
}
@@ -22,10 +20,7 @@
Size.fromJson(Map json) : this(json['height'], json['width']);
- Map<String, num> toJson() => {
- 'height': height,
- 'width': width
- };
+ Map<String, num> toJson() => {'height': height, 'width': width};
}
class Point {
@@ -36,10 +31,7 @@
Point.fromJson(Map json) : this(json['x'], json['y']);
- Map<String, num> toJson() => {
- 'x': x,
- 'y': y
- };
+ Map<String, num> toJson() => {'x': x, 'y': y};
}
abstract class SearchContext {
@@ -99,8 +91,8 @@
* Returns an anchor element whose visible text partially matches the search
* value.
*/
- const By.partialLinkText(String partialLinkText) :
- this._('partial link text', partialLinkText);
+ const By.partialLinkText(String partialLinkText)
+ : this._('partial link text', partialLinkText);
/// Returns an element whose NAME attribute matches the search value.
const By.name(String name) : this._('name', name);
@@ -115,97 +107,98 @@
const By.className(String className) : this._('class name', className);
/// Returns an element matching a CSS selector.
- const By.cssSelector(String cssSelector) :
- this._('css selector', cssSelector);
+ const By.cssSelector(String cssSelector)
+ : this._('css selector', cssSelector);
- Map<String, String> toJson() => { 'using': _using, 'value': _value};
+ Map<String, String> toJson() => {'using': _using, 'value': _value};
}
// TODO(DrMarcII): Create a better WebDriver exception hierarchy.
class WebDriverError {
static const List<String> _errorTypes = const [
- null,
- 'IndexOutOfBounds',
- 'NoCollection',
- 'NoString',
- 'NoStringLength',
- 'NoStringWrapper',
- 'NoSuchDriver',
- 'NoSuchElement',
- 'NoSuchFrame',
- 'UnknownCommand',
- 'ObsoleteElement',
- 'ElementNotDisplayed',
- 'InvalidElementState',
- 'Unknown',
- 'Expected',
- 'ElementNotSelectable',
- 'NoSuchDocument',
- 'UnexpectedJavascript',
- 'NoScriptResult',
- 'XPathLookup',
- 'NoSuchCollection',
- 'TimeOut',
- 'NullPointer',
- 'NoSuchWindow',
- 'InvalidCookieDomain',
- 'UnableToSetCookie',
- 'UnexpectedAlertOpen',
- 'NoAlertOpen',
- 'ScriptTimeout',
- 'InvalidElementCoordinates',
- 'IMENotAvailable',
- 'IMEEngineActivationFailed',
- 'InvalidSelector',
- 'SessionNotCreatedException',
- 'MoveTargetOutOfBounds'];
+ null,
+ 'IndexOutOfBounds',
+ 'NoCollection',
+ 'NoString',
+ 'NoStringLength',
+ 'NoStringWrapper',
+ 'NoSuchDriver',
+ 'NoSuchElement',
+ 'NoSuchFrame',
+ 'UnknownCommand',
+ 'ObsoleteElement',
+ 'ElementNotDisplayed',
+ 'InvalidElementState',
+ 'Unknown',
+ 'Expected',
+ 'ElementNotSelectable',
+ 'NoSuchDocument',
+ 'UnexpectedJavascript',
+ 'NoScriptResult',
+ 'XPathLookup',
+ 'NoSuchCollection',
+ 'TimeOut',
+ 'NullPointer',
+ 'NoSuchWindow',
+ 'InvalidCookieDomain',
+ 'UnableToSetCookie',
+ 'UnexpectedAlertOpen',
+ 'NoAlertOpen',
+ 'ScriptTimeout',
+ 'InvalidElementCoordinates',
+ 'IMENotAvailable',
+ 'IMEEngineActivationFailed',
+ 'InvalidSelector',
+ 'SessionNotCreatedException',
+ 'MoveTargetOutOfBounds'
+ ];
static const List<String> _errorDetails = const [
- null,
- 'IndexOutOfBounds',
- 'NoCollection',
- 'NoString',
- 'NoStringLength',
- 'NoStringWrapper',
- 'NoSuchDriver',
- 'An element could not be located on the page using the given '
- 'search parameters.',
- 'A request to switch to a frame could not be satisfied because the '
- 'frame could not be found.',
- 'The requested resource could not be found, or a request was '
- 'received using an HTTP method that is not supported by the '
- 'mapped resource.',
- 'An element command failed because the referenced element is no '
- 'longer attached to the DOM.',
- 'An element command could not be completed because the element '
- 'is not visible on the page.',
- 'An element command could not be completed because the element is in '
- 'an invalid state (e.g. attempting to click a disabled element).',
- 'An unknown server-side error occurred while processing the command.',
- 'Expected',
- 'An attempt was made to select an element that cannot be selected.',
- 'NoSuchDocument',
- 'An error occurred while executing user supplied JavaScript.',
- 'NoScriptResult',
- 'An error occurred while searching for an element by XPath.',
- 'NoSuchCollection',
- 'An operation did not complete before its timeout expired.',
- 'NullPointer',
- 'A request to switch to a different window could not be satisfied '
- 'because the window could not be found.',
- 'An illegal attempt was made to set a cookie under a different '
- 'domain than the current page.',
- 'A request to set a cookie\'s value could not be satisfied.',
- 'A modal dialog was open, blocking this operation.',
- 'An attempt was made to operate on a modal dialog when one was '
- 'not open.',
- 'A script did not complete before its timeout expired.',
- 'The coordinates provided to an interactions operation are invalid.',
- 'IME was not available.',
- 'An IME engine could not be started.',
- 'Argument was an invalid selector (e.g. XPath/CSS).',
- 'A new session could not be created.',
- 'Target provided for a move action is out of bounds.'
- ];
+ null,
+ 'IndexOutOfBounds',
+ 'NoCollection',
+ 'NoString',
+ 'NoStringLength',
+ 'NoStringWrapper',
+ 'NoSuchDriver',
+ 'An element could not be located on the page using the given '
+ 'search parameters.',
+ 'A request to switch to a frame could not be satisfied because the '
+ 'frame could not be found.',
+ 'The requested resource could not be found, or a request was '
+ 'received using an HTTP method that is not supported by the '
+ 'mapped resource.',
+ 'An element command failed because the referenced element is no '
+ 'longer attached to the DOM.',
+ 'An element command could not be completed because the element '
+ 'is not visible on the page.',
+ 'An element command could not be completed because the element is in '
+ 'an invalid state (e.g. attempting to click a disabled element).',
+ 'An unknown server-side error occurred while processing the command.',
+ 'Expected',
+ 'An attempt was made to select an element that cannot be selected.',
+ 'NoSuchDocument',
+ 'An error occurred while executing user supplied JavaScript.',
+ 'NoScriptResult',
+ 'An error occurred while searching for an element by XPath.',
+ 'NoSuchCollection',
+ 'An operation did not complete before its timeout expired.',
+ 'NullPointer',
+ 'A request to switch to a different window could not be satisfied '
+ 'because the window could not be found.',
+ 'An illegal attempt was made to set a cookie under a different '
+ 'domain than the current page.',
+ 'A request to set a cookie\'s value could not be satisfied.',
+ 'A modal dialog was open, blocking this operation.',
+ 'An attempt was made to operate on a modal dialog when one was '
+ 'not open.',
+ 'A script did not complete before its timeout expired.',
+ 'The coordinates provided to an interactions operation are invalid.',
+ 'IME was not available.',
+ 'An IME engine could not be started.',
+ 'Argument was an invalid selector (e.g. XPath/CSS).',
+ 'A new session could not be created.',
+ 'Target provided for a move action is out of bounds.'
+ ];
final int statusCode;
String type;
@@ -214,7 +207,6 @@
final String results;
WebDriverError(this.statusCode, this.message, [this.results = '']) {
-
if (statusCode < 0 || statusCode > 32) {
type = 'External';
details = '';
diff --git a/lib/src/keyboard.dart b/lib/src/keyboard.dart
index 7835a9e..3391a56 100644
--- a/lib/src/keyboard.dart
+++ b/lib/src/keyboard.dart
@@ -1,16 +1,12 @@
part of webdriver;
class Keyboard extends _WebDriverBase {
-
- Keyboard._(driver)
- : super(driver, '');
+ Keyboard._(driver) : super(driver, '');
/**
* Send [keysToSend] to the active element.
*/
Future sendKeys(String keysToSend) async {
- await _post(
- 'keys',
- { 'value' : [ keysToSend ]});
+ await _post('keys', {'value': [keysToSend]});
}
}
diff --git a/lib/src/mouse.dart b/lib/src/mouse.dart
index 7108e49..442d3fa 100644
--- a/lib/src/mouse.dart
+++ b/lib/src/mouse.dart
@@ -1,13 +1,11 @@
part of webdriver;
class Mouse extends _WebDriverBase {
-
static const int LEFT = 0;
static const int MIDDLE = 1;
static const int RIGHT = 2;
- Mouse._(driver)
- : super(driver, '');
+ Mouse._(driver) : super(driver, '');
/// Click any mouse button (at the coordinates set by the last moveTo).
Future click([int button]) async {
@@ -44,7 +42,7 @@
/// Double-clicks at the current mouse coordinates (set by moveTo).
Future doubleClick() async {
- await _post('doubleclick');
+ await _post('doubleclick');
}
/**
diff --git a/lib/src/navigation.dart b/lib/src/navigation.dart
index 407da8f..251aa8c 100644
--- a/lib/src/navigation.dart
+++ b/lib/src/navigation.dart
@@ -1,7 +1,6 @@
part of webdriver;
class Navigation extends _WebDriverBase {
-
Navigation._(driver) : super(driver, '');
/// Navigate forwards in the browser history, if possible.
diff --git a/lib/src/options.dart b/lib/src/options.dart
index 22da230..51e392e 100644
--- a/lib/src/options.dart
+++ b/lib/src/options.dart
@@ -1,13 +1,11 @@
part of webdriver;
class Cookies extends _WebDriverBase {
-
- Cookies._(driver)
- : super(driver, 'cookie');
+ Cookies._(driver) : super(driver, 'cookie');
/// Set a cookie.
Future add(Cookie cookie) async {
- await _post('', { 'cookie': cookie });
+ await _post('', {'cookie': cookie});
}
/// Delete the cookie with the given [name].
@@ -21,12 +19,29 @@
}
/// Retrieve all cookies visible to the current page.
- Stream<Cookie> get all async* {
- var cookies = await _get('');
- for (var cookie in cookies) {
- yield new Cookie.fromJson(cookie);
- }
+ Stream<Cookie> get all {
+ var controller = new StreamController<Cookie>();
+
+ () async {
+ var cookies = await _get('');
+ int i = 0;
+ for (var cookie in cookies) {
+ controller.add(new Cookie.fromJson(cookie));
+ i++;
+ }
+ await controller.close();
+ }();
+
+ return controller.stream;
}
+
+// TODO(DrMarcII): switch to this when async* is supported
+// async* {
+// var cookies = await _get('');
+// for (var cookie in cookies) {
+// yield new Cookie.fromJson(cookie);
+// }
+// }
}
class Cookie {
@@ -49,12 +64,10 @@
factory Cookie.fromJson(Map<String, dynamic> json) {
var expiry;
if (json['expiry'] is num) {
- expiry = new DateTime
- .fromMillisecondsSinceEpoch(json['expiry']*1000, isUtc: true);
+ expiry = new DateTime.fromMillisecondsSinceEpoch(json['expiry'] * 1000,
+ isUtc: true);
}
- return new Cookie(
- json['name'],
- json['value'],
+ return new Cookie(json['name'], json['value'],
path: json['path'],
domain: json['domain'],
secure: json['secure'],
@@ -62,10 +75,7 @@
}
Map<String, dynamic> toJson() {
- var json = {
- 'name': name,
- 'value': value
- };
+ var json = {'name': name, 'value': value};
if (path is String) {
json['path'] = path;
}
@@ -83,23 +93,18 @@
}
class Timeouts extends _WebDriverBase {
-
- Timeouts._(driver)
- : super(driver, 'timeouts');
+ Timeouts._(driver) : super(driver, 'timeouts');
Future _set(String type, Duration duration) async {
- await _post('', { 'type' : type, 'ms': duration.inMilliseconds});
+ await _post('', {'type': type, 'ms': duration.inMilliseconds});
}
/// Set the script timeout.
- Future setScriptTimeout(Duration duration) =>
- _set('script', duration);
+ Future setScriptTimeout(Duration duration) => _set('script', duration);
/// Set the implicit timeout.
- Future setImplicitTimeout(Duration duration) =>
- _set('implicit', duration);
+ Future setImplicitTimeout(Duration duration) => _set('implicit', duration);
/// Set the page load timeout.
- Future setPageLoadTimeout(Duration duration) =>
- _set('page load', duration);
+ Future setPageLoadTimeout(Duration duration) => _set('page load', duration);
}
diff --git a/lib/src/target_locator.dart b/lib/src/target_locator.dart
index e00ddac..02e5f32 100644
--- a/lib/src/target_locator.dart
+++ b/lib/src/target_locator.dart
@@ -1,7 +1,6 @@
part of webdriver;
class TargetLocator extends _WebDriverBase {
-
TargetLocator._(driver) : super(driver, '');
/**
@@ -19,7 +18,7 @@
* found.
*/
Future frame([frame]) async {
- await _post('frame', { 'id': frame});
+ await _post('frame', {'id': frame});
}
/**
@@ -31,9 +30,9 @@
*/
Future window(dynamic window) async {
if (window is Window) {
- await _post('window', { 'name': window.handle});
- } else if (window is String){
- await _post('window', { 'name': window });
+ await _post('window', {'name': window.handle});
+ } else if (window is String) {
+ await _post('window', {'name': window});
} else {
throw 'Unsupported type: ${window.runtimeType}';
}
diff --git a/lib/src/util.dart b/lib/src/util.dart
new file mode 100644
index 0000000..b8703c0
--- /dev/null
+++ b/lib/src/util.dart
@@ -0,0 +1,23 @@
+part of webdriver;
+
+const DEFAULT_TIMEOUT = const Duration(minutes: 1);
+const DEFAULT_INTERVAL = const Duration(milliseconds: 500);
+
+Future waitFor(Future predicate(), {Matcher matcher: isTrue,
+ Duration timeout: DEFAULT_TIMEOUT, Duration interval: DEFAULT_INTERVAL}) {
+ var endTime = new DateTime.now().add(timeout);
+ var function;
+ function = () async {
+ var value = await predicate();
+ try {
+ expect(value, matcher);
+ return value;
+ } catch (e) {
+ if (new DateTime.now().isAfter(endTime)) {
+ rethrow;
+ }
+ }
+ return await new Future.delayed(DEFAULT_INTERVAL, function);
+ };
+ return function();
+}
diff --git a/lib/src/web_driver.dart b/lib/src/web_driver.dart
index a9e0ae3..763dca2 100644
--- a/lib/src/web_driver.dart
+++ b/lib/src/web_driver.dart
@@ -1,20 +1,22 @@
part of webdriver;
class WebDriver implements SearchContext {
-
final _CommandProcessor _commandProcessor;
final Uri _prefix;
final Map<String, dynamic> capabilities;
+ final String id;
+ final Uri uri;
- WebDriver._(this._commandProcessor, this._prefix, this.capabilities);
+ WebDriver._(this._commandProcessor, Uri uri, String id, this.capabilities)
+ : this.uri = uri,
+ this.id = id,
+ this._prefix = uri.resolve('session/$id/');
/// Creates a WebDriver instance connected to the specified WebDriver server.
- static Future<WebDriver> createDriver({
- Uri uri,
- Map<String, dynamic> desiredCapabilities}) async {
-
+ static Future<WebDriver> createDriver(
+ {Uri uri, Map<String, dynamic> desiredCapabilities}) async {
if (uri == null) {
- uri = Uri.parse('http://localhost:4444/wd/hub');
+ uri = Uri.parse('http://127.0.0.1:4444/wd/hub/');
}
var commandProcessor = new _CommandProcessor();
@@ -23,8 +25,11 @@
desiredCapabilities = Capabilities.empty;
}
- var response = await commandProcessor.post(uri.resolve('session'), { 'desiredCapabilities' : desiredCapabilities });
- return new WebDriver._(commandProcessor, uri.resolve(response['id']), new UnmodifiableMapView(response['capabilities']));
+ var response = await commandProcessor.post(uri.resolve('session'), {
+ 'desiredCapabilities': desiredCapabilities
+ }, value: false);
+ return new WebDriver._(commandProcessor, uri, response['sessionId'],
+ new UnmodifiableMapView(response['value']));
}
/// Navigate to the specified url.
@@ -40,16 +45,32 @@
/// Search for multiple elements within the entire current page.
@override
- Stream<WebElement> findElements(By by) async* {
- var elements = await _post('elements', by);
- int i = 0;
+ Stream<WebElement> findElements(By by) {
+ var controller = new StreamController<WebElement>();
- for (var element in elements) {
- yield new WebElement._(this, element['ELEMENT'], this, by, i);
- i++;
- }
+ () async {
+ var elements = await _post('elements', by);
+ int i = 0;
+ for (var element in elements) {
+ controller.add(new WebElement._(this, element['ELEMENT'], this, by, i));
+ i++;
+ }
+ await controller.close();
+ }();
+
+ return controller.stream;
}
+// TODO(DrMarcII): switch to this when async* is supported
+// async* {
+// var elements = await _post('elements', by);
+// int i = 0;
+//
+// for (var element in elements) {
+// yield new WebElement._(this, element['ELEMENT'], this, by, i);
+// i++;
+// }
+// }
/**
* Search for an element within the entire current page.
@@ -58,28 +79,48 @@
*/
Future<WebElement> findElement(By by) async {
var element = await _post('element', by);
- return new WebElement._(this, element['ELEMENT'], this, by);
+ return new WebElement._(this, element['ELEMENT'], this, by);
}
-
/// An artist's rendition of the current page's source.
Future<String> get pageSource => _get('source');
/// Close the current window, quitting the browser if it is the last window.
- Future close() => _delete('window');
+ Future close() async {
+ await _delete('window');
+ }
/// Quit the browser.
- Future quit() => _delete('');
+ Future quit() async {
+ await _commandProcessor.delete(uri.resolve('session/$id'));
+ }
/// Handles for all of the currently displayed tabs/windows.
- Stream<Window> get windows async* {
- var handles = await _get('window_handles');
+ Stream<Window> get windows {
+ var controller = new StreamController<Window>();
- for (var handle in handles) {
- yield new Window._(this, handle);
- }
+ () async {
+ var handles = await _get('window_handles');
+ int i = 0;
+ for (var handle in handles) {
+ controller.add(new Window._(this, handle));
+ i++;
+ }
+ await controller.close();
+ }();
+
+ return controller.stream;
}
+// TODO(DrMarcII): switch to this when async* is supported
+// async* {
+// var handles = await _get('window_handles');
+//
+// for (var handle in handles) {
+// yield new Window._(this, handle);
+// }
+// }
+
/// Handle for the active tab/window.
Future<Window> get window async {
var handle = await _get('window_handle');
@@ -91,15 +132,14 @@
* element has focus.
*/
Future<WebElement> get activeElement async {
- var element = await _get('element/active');
+ var element = await _post('element/active');
if (element != null) {
return new WebElement._(this, element['ELEMENT'], this, 'activeElement');
}
return null;
}
- TargetLocator get switchTo =>
- new TargetLocator._(this);
+ TargetLocator get switchTo => new TargetLocator._(this);
Navigation get navigate => new Navigation._(this);
@@ -135,12 +175,10 @@
* the corresponding DOM element. Likewise, any DOM Elements in the script
* result will be converted to WebElements.
*/
- Future executeAsync(String script, List args) =>
- _post('execute_async', {
- 'script': script,
- 'args': args
- })
- .then(_recursiveElementify);
+ Future executeAsync(String script, List args) => _post('execute_async', {
+ 'script': script,
+ 'args': args
+ }).then(_recursiveElementify);
/**
* Inject a snippet of JavaScript into the page for execution in the context
@@ -156,12 +194,8 @@
* the corresponding DOM element. Likewise, any DOM Elements in the script
* result will be converted to WebElements.
*/
- Future execute(String script, List args) =>
- _post('execute', {
- 'script': script,
- 'args': args
- })
- .then(_recursiveElementify);
+ Future execute(String script, List args) => _post(
+ 'execute', {'script': script, 'args': args}).then(_recursiveElementify);
dynamic _recursiveElementify(result) {
if (result is Map) {
@@ -181,9 +215,12 @@
}
}
- Future _post(String command, [params]) => _commandProcessor.post(_prefix.resolve(command), params);
+ Future _post(String command, [params]) =>
+ _commandProcessor.post(_prefix.resolve(command), params);
- Future _get(String command) => _commandProcessor.get(_prefix.resolve(command));
+ Future _get(String command) =>
+ _commandProcessor.get(_prefix.resolve(command));
- Future _delete(String command) => _commandProcessor.delete(_prefix.resolve(command));
+ Future _delete(String command) =>
+ _commandProcessor.delete(_prefix.resolve(command));
}
diff --git a/lib/src/web_element.dart b/lib/src/web_element.dart
index ed0127a..3798b3a 100644
--- a/lib/src/web_element.dart
+++ b/lib/src/web_element.dart
@@ -24,7 +24,7 @@
/// Send [keysToSend] to this element.
Future sendKeys(String keysToSend) async {
- await _post('value', { 'value' : [ keysToSend ]});
+ await _post('value', {'value': [keysToSend]});
}
/// Clear the content of a text element.
@@ -70,22 +70,39 @@
}
/// Find multiple elements nested within this element.
- Stream<WebElement> findElements(By by) async* {
- var elements = await _post('elements', by);
- int i = 0;
- for (var element in elements) {
- yield new WebElement._(driver, element['ELEMENT'], this, by, i);
- i++;
- }
+ Stream<WebElement> findElements(By by) {
+ var controller = new StreamController<WebElement>();
+
+ () async {
+ var elements = await _post('elements', by);
+ int i = 0;
+ for (var element in elements) {
+ controller
+ .add(new WebElement._(driver, element['ELEMENT'], this, by, i));
+ i++;
+ }
+ await controller.close();
+ }();
+
+ return controller.stream;
}
+// TODO(DrMarcII): switch to this when async* is supported
+// async* {
+// var elements = await _post('elements', by);
+// int i = 0;
+// for (var element in elements) {
+// yield new WebElement._(driver, element['ELEMENT'], this, by, i);
+// i++;
+// }
+// }
+
/**
* Access to the HTML attributes of this tag.
*
* TODO(DrMarcII): consider special handling of boolean attributes.
*/
- Attributes get attributes =>
- new Attributes._(driver, '$_prefix/attribute');
+ Attributes get attributes => new Attributes._(driver, '$_prefix/attribute');
/**
* Access to the cssProperties of this element.
@@ -93,8 +110,7 @@
* TODO(DrMarcII): consider special handling of color and possibly other
* properties.
*/
- Attributes get cssProperties =>
- new Attributes._(driver, '$_prefix/css');
+ Attributes get cssProperties => new Attributes._(driver, '$_prefix/css');
/**
* Does this element represent the same element as another element?
diff --git a/lib/src/window.dart b/lib/src/window.dart
index d790a1e..90fac7f 100644
--- a/lib/src/window.dart
+++ b/lib/src/window.dart
@@ -1,12 +1,11 @@
part of webdriver;
class Window extends _WebDriverBase {
-
final String handle;
Window._(driver, handle)
: this.handle = handle,
- super(driver, 'window/$handle');
+ super(driver, 'window/$handle');
/// The size of this window.
Future<Size> get size async {
@@ -34,4 +33,12 @@
Future setLocation(Point point) async {
await _post('position', point);
}
+
+ @override
+ int get hashCode => handle.hashCode * 3 + driver.hashCode;
+
+ @override
+ bool operator ==(other) => other is Window &&
+ other.driver == this.driver &&
+ other.handle == this.handle;
}
diff --git a/lib/webdriver.dart b/lib/webdriver.dart
index aeb3aef..e9a96d2 100644
--- a/lib/webdriver.dart
+++ b/lib/webdriver.dart
@@ -10,6 +10,7 @@
import 'dart:io';
import 'package:crypto/crypto.dart';
+import 'package:matcher/matcher.dart';
part 'src/alert.dart';
part 'src/capabilities.dart';
@@ -25,3 +26,4 @@
part 'src/web_driver.dart';
part 'src/web_element.dart';
part 'src/window.dart';
+part 'src/util.dart';
diff --git a/pubspec.yaml b/pubspec.yaml
index ce2c791..95d1917 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,14 +1,15 @@
name: webdriver
-version: 0.8.8
+version: 0.9.0
author: Dart Team <misc@dartlang.org>
description: >
Provides WebDriver bindings for Dart. These use the WebDriver JSON interface,
and as such, require the use of the WebDriver remote server.
homepage: https://github.com/google/webdriver.dart
environment:
- sdk: '>=1.0.0 <2.0.0'
+ sdk: '>=1.9.0-dev.4.0 <2.0.0'
dependencies:
- crypto: '>=0.8.7 <0.10.0'
+ crypto: '^0.9.0'
+ matcher: '^0.11.4'
dev_dependencies:
- path: '>=1.0.0 <2.0.0'
- unittest: '>=0.8.7 <0.12.0'
+ path: '^1.3.1'
+ unittest: '^0.11.5'
diff --git a/test/src/alert_test.dart b/test/src/alert_test.dart
index 8d54b29..ac18eae 100644
--- a/test/src/alert_test.dart
+++ b/test/src/alert_test.dart
@@ -5,67 +5,52 @@
import '../test_util.dart';
void main() {
-
group('Alert', () {
-
WebDriver driver;
WebElement button;
WebElement output;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath))
- .then((_) => driver.findElement(new By.tagName('button')))
- .then((_element) => button = _element)
- .then((_) => driver.findElement(new By.id('settable')))
- .then((_element) => output = _element);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get(testPagePath);
+ button = await driver.findElement(const By.tagName('button'));
+ output = await driver.findElement(const By.id('settable'));
});
tearDown(() => driver.quit());
test('no alert', () {
- return driver.switchTo.alert.catchError((error) {
- expect(error, isWebDriverError);
- });
+ expect(driver.switchTo.alert, throws);
});
- test('text', () {
- return button.click().then((_) => driver.switchTo.alert)
- .then((alert) {
- expect(alert.text, 'button clicked');
- return alert.dismiss();
- });
+ test('text', () async {
+ await button.click();
+ var alert = await driver.switchTo.alert;
+ expect(alert.text, 'button clicked');
+ await alert.dismiss();
});
- test('accept', () {
- return button.click().then((_) => driver.switchTo.alert)
- .then((alert) => alert.accept())
- .then((_) => output.text)
- .then((text) {
- expect(text, startsWith('accepted'));
- });
+ test('accept', () async {
+ await button.click();
+ var alert = await driver.switchTo.alert;
+ await alert.accept();
+ expect(await output.text, startsWith('accepted'));
});
- test('dismiss', () {
- return button.click().then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss())
- .then((_) => output.text)
- .then((text) {
- expect(text, startsWith('dismissed'));
- });
+ test('dismiss', () async {
+ await button.click();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
+ expect(await output.text, startsWith('dismissed'));
});
- test('sendKeys', () {
- Alert alert;
- return button.click().then((_) => driver.switchTo.alert)
- .then((_alert) => alert = _alert)
- .then((_) => alert.sendKeys('some keys'))
- .then((_) => alert.accept())
- .then((_) => output.text)
- .then((text) {
- expect(text, endsWith('some keys'));
- });
+ test('sendKeys', () async {
+ await button.click();
+ Alert alert = await driver.switchTo.alert;
+ await alert.sendKeys('some keys');
+ await alert.accept();
+ expect(await output.text, endsWith('some keys'));
});
});
}
diff --git a/test/src/keyboard_test.dart b/test/src/keyboard_test.dart
index 442a1d9..e67aef4 100644
--- a/test/src/keyboard_test.dart
+++ b/test/src/keyboard_test.dart
@@ -5,56 +5,35 @@
import '../test_util.dart';
void main() {
-
group('Keyboard', () {
-
WebDriver driver;
WebElement textInput;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.firefox)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath))
- .then((_) =>
- driver.findElement(new By.cssSelector('input[type=text]')))
- .then((_element) => textInput = _element)
- .then((_) => driver.mouse.moveTo(element: textInput).click());
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.firefox);
+ await driver.get(testPagePath);
+ textInput =
+ await driver.findElement(new By.cssSelector('input[type=text]'));
+ await textInput.click();
});
tearDown(() => driver.quit());
- test('sendKeys -- once', () {
- return driver.keyboard.sendKeys('abcdef')
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, 'abcdef');
- });
+ test('sendKeys -- once', () async {
+ await driver.keyboard.sendKeys('abcdef');
+ expect(await textInput.attributes['value'], 'abcdef');
});
- test('sendKeys -- twice', () {
- return driver.keyboard.sendKeys('abc').sendKeys('def')
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, 'abcdef');
- });
+ test('sendKeys -- twice', () async {
+ await driver.keyboard.sendKeys('abc');
+ await driver.keyboard.sendKeys('def');
+ expect(await textInput.attributes['value'], 'abcdef');
});
- test('sendKeys -- list', () {
- return driver.keyboard.sendKeys(['a', 'b', 'c', 'd', 'e', 'f'])
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, 'abcdef');
- });
- });
-
- // doesn't work with chromedriver
- // https://code.google.com/p/chromedriver/issues/detail?id=443
- test('sendKeys -- with tab', () {
- return driver.keyboard.sendKeys(['abc', Keys.TAB, 'def'])
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, 'abc');
- });
+ test('sendKeys -- with tab', () async {
+ await driver.keyboard.sendKeys('abc${Keys.TAB}def');
+ expect(await textInput.attributes['value'], 'abc');
});
});
}
diff --git a/test/src/mouse_test.dart b/test/src/mouse_test.dart
index e4807d2..265253b 100644
--- a/test/src/mouse_test.dart
+++ b/test/src/mouse_test.dart
@@ -5,60 +5,56 @@
import '../test_util.dart';
void main() {
-
group('Mouse', () {
-
WebDriver driver;
WebElement button;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath))
- .then((_) => driver.findElement(new By.tagName('button')))
- .then((_e) => button = _e);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get(testPagePath);
+ button = await driver.findElement(new By.tagName('button'));
});
tearDown(() => driver.quit());
- test('moveTo element/click', () {
- return driver.mouse.moveTo(element: button)
- .click()
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss);
+ test('moveTo element/click', () async {
+ await driver.mouse.moveTo(element: button);
+ await driver.mouse.click();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
});
- test('moveTo coordinates/click', () {
- return button.location
- .then((pos) => driver.mouse
- .moveTo(xOffset: pos.x + 5, yOffset: pos.y + 5)
- .click())
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss);
+ test('moveTo coordinates/click', () async {
+ var pos = await button.location;
+ await driver.mouse.moveTo(xOffset: pos.x + 5, yOffset: pos.y + 5);
+ await driver.mouse.click();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
});
- test('moveTo element coordinates/click', () {
- return driver.mouse.moveTo(element: button, xOffset: 5, yOffset: 5)
- .click()
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss);
+ test('moveTo element coordinates/click', () async {
+ await driver.mouse.moveTo(element: button, xOffset: 5, yOffset: 5);
+ await driver.mouse.click();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
});
// TODO(DrMarcII): Better up/down tests
- test('down/up', () {
- return driver.mouse.moveTo(element: button)
- .down()
- .up()
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss);
+ test('down/up', () async {
+ await driver.mouse.moveTo(element: button);
+ await driver.mouse.down();
+ await driver.mouse.up();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
});
// TODO(DrMarcII): Better double click test
- test('doubleClick', () {
- return driver.mouse.moveTo(element: button)
- .doubleClick()
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.dismiss);
+ test('doubleClick', () async {
+ await driver.mouse.moveTo(element: button);
+ await driver.mouse.doubleClick();
+ var alert = await driver.switchTo.alert;
+ await alert.dismiss();
});
});
}
diff --git a/test/src/navigation_test.dart b/test/src/navigation_test.dart
index 217c7f4..2221977 100644
--- a/test/src/navigation_test.dart
+++ b/test/src/navigation_test.dart
@@ -2,46 +2,34 @@
import 'package:unittest/unittest.dart';
import 'package:webdriver/webdriver.dart';
-import '../test_util.dart';
void main() {
-
group('Navigation', () {
-
WebDriver driver;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get('http://www.google.com'));
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get('http://www.google.com/ncr');
});
tearDown(() => driver.quit());
- test('forward/back', () {
- return driver.get('http://www.yahoo.com')
- .then((_) => driver.navigate.back())
- .then((_) => driver.title)
- .then((title) {
- expect(title, contains('Google'));
- return driver.navigate.forward();
- })
- .then((_) => driver.title)
- .then((title) {
- expect(title, contains('Yahoo'));
- });
+ test('forward/back', () async {
+ await driver.get('http://www.yahoo.com');
+ await driver.navigate.back();
+ await waitFor(() => driver.title, matcher: contains('Google'));
+ await driver.navigate.forward();
+ await waitFor(() => driver.title, matcher: contains('Yahoo'));
});
- test('refresh', () {
- var element;
- return driver.findElement(new By.name('q'))
- .then((_e) => element = _e)
- .then((_) => driver.navigate.refresh())
- .then((_) => element.name)
- .catchError((error) {
- // search should be stale after refresh
- expect(error, isWebDriverError);
- });
+ test('refresh', () async {
+ var element = await driver.findElement(new By.name('q'));
+ await driver.navigate.refresh();
+ try {
+ await element.name;
+ throw 'Expected SERE';
+ } on StaleElementReferenceException {}
});
});
}
diff --git a/test/src/options_test.dart b/test/src/options_test.dart
index db289ce..d6aac52 100644
--- a/test/src/options_test.dart
+++ b/test/src/options_test.dart
@@ -4,103 +4,81 @@
import 'package:webdriver/webdriver.dart';
void main() {
-
group('Cookies', () {
-
WebDriver driver;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get('http://www.google.com'));
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get('http://www.google.com');
});
tearDown(() => driver.quit());
- test('add simple cookie', () {
- return driver.cookies.add(new Cookie('mycookie', 'myvalue'))
- .then((_) => driver.cookies.all)
- .then((cookies) {
- bool found = false;
- for (var cookie in cookies) {
- if (cookie.name == 'mycookie') {
- found = true;
- expect(cookie.value, 'myvalue');
- }
- }
- expect(found, isTrue);
- });
+ test('add simple cookie', () async {
+ await driver.cookies.add(new Cookie('mycookie', 'myvalue'));
+
+ bool found = false;
+ for (var cookie in driver.cookies.all) {
+ if (cookie.name == 'mycookie') {
+ found = true;
+ expect(cookie.value, 'myvalue');
+ break;
+ }
+ }
+ expect(found, isTrue);
});
- test('add complex cookie', () {
- var date = new DateTime.utc(2014);
- return driver.cookies
- .add(new Cookie(
- 'mycookie',
- 'myvalue',
- path: '/',
- domain: '.google.com',
- secure: false,
- expiry: date))
- .then((_) => driver.cookies.all)
- .then((cookies) {
- bool found = false;
- for (var cookie in cookies) {
- if (cookie.name == 'mycookie') {
- found = true;
- expect(cookie.value, 'myvalue');
- expect(cookie.expiry, date);
- }
- }
- expect(found, isTrue);
- });
+ test('add complex cookie', () async {
+ var date = new DateTime.utc(2020);
+ await driver.cookies.add(new Cookie('mycookie', 'myvalue',
+ path: '/', domain: '.google.com', secure: false, expiry: date));
+ bool found = false;
+ for (var cookie in driver.cookies.all) {
+ if (cookie.name == 'mycookie') {
+ found = true;
+ expect(cookie.value, 'myvalue');
+ expect(cookie.expiry, date);
+ break;
+ }
+ }
+ expect(found, isTrue);
});
- test('delete cookie', () {
- return driver.cookies.add(new Cookie('mycookie', 'myvalue'))
- .then((_) => driver.cookies.delete('mycookie'))
- .then((_) => driver.cookies.all)
- .then((cookies) {
- bool found = false;
- for (var cookie in cookies) {
- if (cookie.name == 'mycookie') {
- found = true;
- }
- }
- expect(found, isFalse);
- });
+ test('delete cookie', () async {
+ await driver.cookies.add(new Cookie('mycookie', 'myvalue'));
+ await driver.cookies.delete('mycookie');
+ bool found = false;
+ for (var cookie in driver.cookies.all) {
+ if (cookie.name == 'mycookie') {
+ found = true;
+ break;
+ }
+ }
+ expect(found, isFalse);
});
- test('delete all cookies', () {
- return driver.cookies.deleteAll()
- .then((_) => driver.cookies.all)
- .then((cookies) {
- expect(cookies, isEmpty);
- });
+ test('delete all cookies', () async {
+ await driver.cookies.deleteAll();
+ expect(await driver.cookies.all.toList(), isEmpty);
});
});
group('TimeOuts', () {
WebDriver driver;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
});
tearDown(() => driver.quit());
// TODO(DrMarcII): Figure out how to tell if timeouts are correctly set
- test('set all timeouts', () {
- return driver.timeouts.setScriptTimeout(new Duration(seconds: 5))
- .then((_) => driver.timeouts
- .setImplicitTimeout(new Duration(seconds: 1)))
- .then((_) => driver.timeouts
- .setPageLoadTimeout(new Duration(seconds: 10)))
- .then((_) => driver.timeouts
- .setAsyncScriptTimeout(new Duration(seconds: 7)))
- .then((_) => driver.timeouts
- .setImplicitWaitTimeout(new Duration(seconds: 2)));
+ test('set all timeouts', () async {
+ await driver.timeouts.setScriptTimeout(new Duration(seconds: 5));
+ await driver.timeouts.setImplicitTimeout(new Duration(seconds: 1));
+ await driver.timeouts.setPageLoadTimeout(new Duration(seconds: 10));
});
});
}
diff --git a/test/src/target_locator_test.dart b/test/src/target_locator_test.dart
index 3005c4d..85a349a 100644
--- a/test/src/target_locator_test.dart
+++ b/test/src/target_locator_test.dart
@@ -9,51 +9,38 @@
* in other classes.
*/
void main() {
-
group('TargetLocator', () {
-
WebDriver driver;
WebElement frame;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath))
- .then((_) => driver.findElement(new By.name('frame')))
- .then((_e) => frame = _e);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get(testPagePath);
+ frame = await driver.findElement(new By.name('frame'));
});
tearDown(() => driver.quit());
- test('frame index', () {
- return driver.switchTo.frame(0)
- .then((_) => driver.pageSource)
- .then((source) {
- expect(source, contains('this is a frame'));
- });
+ test('frame index', () async {
+ await driver.switchTo.frame(0);
+ expect(await driver.pageSource, contains('this is a frame'));
});
- test('frame name', () {
- return driver.switchTo.frame('frame')
- .then((_) => driver.pageSource)
- .then((source) {
- expect(source, contains('this is a frame'));
- });
+ test('frame name', () async {
+ await driver.switchTo.frame('frame');
+ expect(await driver.pageSource, contains('this is a frame'));
});
- test('frame element', () {
- return driver.switchTo.frame(frame)
- .then((_) => driver.pageSource)
- .then((source) {
- expect(source, contains('this is a frame'));
- });
+ test('frame element', () async {
+ await driver.switchTo.frame(frame);
+ expect(await driver.pageSource, contains('this is a frame'));
});
- test('root frame', () {
- return driver.switchTo.frame(frame)
- .then((_) => driver.switchTo.frame())
- .then((_) => driver.pageSource)
- .then((_) => driver.findElement(new By.tagName('button')));
+ test('root frame', () async {
+ await driver.switchTo.frame(frame);
+ await driver.switchTo.frame();
+ await driver.findElement(new By.tagName('button'));
});
});
}
diff --git a/test/src/web_driver_test.dart b/test/src/web_driver_test.dart
index 48ec114..4cc14da 100644
--- a/test/src/web_driver_test.dart
+++ b/test/src/web_driver_test.dart
@@ -5,222 +5,160 @@
import '../test_util.dart';
void main() {
-
group('WebDriver', () {
group('create', () {
- test('default', () {
- WebDriver driver;
- return WebDriver.createDriver()
- .then((_driver) {
- driver = _driver;
- })
- .then((_) => driver.get('http://www.google.com'))
- .then((_) => driver.findElement(new By.name('q')))
- .then((element) => element.name)
- .then((name) {
- expect(name, 'input');
- return driver.quit();
- });
+ test('default', () async {
+ WebDriver driver = await WebDriver.createDriver();
+ await driver.get('http://www.google.com');
+ var element = await driver.findElement(new By.name('q'));
+ expect(await element.name, 'input');
+ await driver.quit();
});
- test('chrome', () {
- WebDriver driver;
- return WebDriver
- .createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) {
- driver = _driver;
- })
- .then((_) => driver.get('http://www.google.com'))
- .then((_) => driver.findElement(new By.name('q')))
- .then((element) => element.name)
- .then((name) {
- expect(name, 'input');
- return driver.quit();
- });
+ test('chrome', () async {
+ WebDriver driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get('http://www.google.com');
+ var element = await driver.findElement(new By.name('q'));
+ expect(await element.name, 'input');
+ await driver.quit();
});
- test('firefox', () {
- WebDriver driver;
- return WebDriver
- .createDriver(desiredCapabilities: Capabilities.firefox)
- .then((_driver) {
- driver = _driver;
- })
- .then((_) => driver.get('http://www.google.com'))
- .then((_) => driver.findElement(new By.name('q')))
- .then((element) => element.name)
- .then((name) {
- expect(name, 'input');
- return driver.quit();
- });
+ test('firefox', () async {
+ WebDriver driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.firefox);
+ await driver.get('http://www.google.com');
+ var element = await driver.findElement(new By.name('q'));
+ expect(await element.name, 'input');
+ await driver.quit();
});
});
group('methods', () {
WebDriver driver;
- setUp(() {
- return WebDriver
- .createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath));
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get(testPagePath);
});
tearDown(() => driver.quit());
- test('get', () {
- return driver.get('http://www.google.com')
- .then((_) => driver.findElement(new By.name('q')))
- .then((_) => driver.get('http://www.yahoo.com'))
- .then((_) => driver.findElement(new By.name('p')));
+ test('get', () async {
+ await driver.get('http://www.google.com');
+ await driver.findElement(new By.name('q'));
+ await driver.get('http://www.yahoo.com');
+ await driver.findElement(new By.name('p'));
});
- test('currentUrl', () {
- return driver.currentUrl.then((url) {
- expect(url, startsWith('file:'));
- expect(url, endsWith('test_page.html'));
- return driver.get('http://www.google.com');
- })
- .then((_) => driver.currentUrl)
- .then((url) {
- expect(url, contains('www.google.com'));
- });
+ test('currentUrl', () async {
+ var url = await driver.currentUrl;
+ expect(url, startsWith('file:'));
+ expect(url, endsWith('test_page.html'));
+ await driver.get('http://www.google.com');
+ url = await driver.currentUrl;
+ expect(url, contains('www.google.com'));
});
- test('findElement -- success', () {
- return driver.findElement(new By.tagName('tr')) .then((element) {
- expect(element, isWebElement);
- });
+ test('findElement -- success', () async {
+ var element = await driver.findElement(new By.tagName('tr'));
+ expect(element, isWebElement);
});
- test('findElement -- failure', () {
- return driver.findElement(new By.id('non-existent-id'))
- .catchError((error) {
- expect(error, isWebDriverError);
- });
+ test('findElement -- failure', () async {
+ try {
+ await driver.findElement(new By.id('non-existent-id'));
+ throw 'expected NoSuchElementException';
+ } on NoSuchElementException {}
});
- test('findElements -- 1 found', () {
- return driver.findElements(new By.cssSelector('input[type=text]'))
- .then((elements) {
- expect(elements, hasLength(1));
- expect(elements, everyElement(isWebElement));
- });
+ test('findElements -- 1 found', () async {
+ var elements = await driver
+ .findElements(new By.cssSelector('input[type=text]'))
+ .toList();
+ expect(elements, hasLength(1));
+ expect(elements, everyElement(isWebElement));
});
- test('findElements -- 4 found', () {
- return driver.findElements(new By.tagName('td'))
- .then((elements) {
- expect(elements, hasLength(4));
- expect(elements, everyElement(isWebElement));
- });
+ test('findElements -- 4 found', () async {
+ var elements = await driver.findElements(new By.tagName('td')).toList();
+ expect(elements, hasLength(4));
+ expect(elements, everyElement(isWebElement));
});
- test('findElements -- 0 found', () {
- return driver.findElements(new By.id('non-existent-id'))
- .then((elements) {
- expect(elements, isEmpty);
- });
+ test('findElements -- 0 found', () async {
+ var elements =
+ await driver.findElements(new By.id('non-existent-id')).toList();
+ expect(elements, isEmpty);
});
- test('pageSource', () {
- return driver.pageSource.then((source) {
- expect(source, contains('<title>test_page</title>'));
- });
+ test('pageSource', () async {
+ expect(await driver.pageSource, contains('<title>test_page</title>'));
});
- test('close/windowHandles', () {
- int numHandles;
- return driver.windowHandles
- .then((handles) => numHandles = handles.length)
- .then((_) =>
- driver.findElement(new By.partialLinkText('Open copy')))
- .then((element) => element.click())
- .then((_) => driver.close())
- .then((_) => driver.windowHandles)
- .then((handles) {
- expect(handles, hasLength(numHandles));
- });
+ test('close/windows', () async {
+ int numHandles = (await driver.windows.toList()).length;
+ await (await driver.findElement(new By.partialLinkText('Open copy')))
+ .click();
+ expect(await driver.windows.toList(), hasLength(numHandles + 1));
+ await driver.close();
+ expect(await driver.windows.toList(), hasLength(numHandles));
});
- test('windowHandle', () {
- String origHandle;
- String newHandle;
- return driver.windowHandle
- .then((_handle) => origHandle = _handle)
- .then((_) =>
- driver.findElement(new By.partialLinkText('Open copy')))
- .then((element) => element.click())
- .then((_) => driver.windowHandles)
- .then((handles) {
- for (String aHandle in handles) {
- if (aHandle != origHandle) {
- newHandle = aHandle;
- return driver.switchTo.window(aHandle);
- }
- }
- })
- .then((_) => driver.windowHandle)
- .then((finalHandle) {
- expect(finalHandle, newHandle);
- });
+ test('window', () async {
+ Window orig = await driver.window;
+ Window next;
+ await (await driver.findElement(new By.partialLinkText('Open copy')))
+ .click();
+ for (Window window in driver.windows) {
+ if (window != orig) {
+ next = window;
+ await driver.switchTo.window(window);
+ break;
+ }
+ }
+ expect(await driver.window, equals(next));
+ await driver.close();
});
- // TODO(DrMarcII): Figure out why this doesn't pass
-// test('activeElement', () {
-// return driver.activeElement
-// .then((element) {
-// expect(element, isNull);
-// return driver
-// .findElement(new By.cssSelector('input[type=text]'));
-// })
-// .then((element) => element.click())
-// .then((_) => driver.activeElement)
-// .then((element) => element.name)
-// .then((name) {
-// expect(name, 'input');
-// });
-// });
-
- test('windows', () {
- return driver.windows.then((windows) {
- expect(windows, hasLength(isPositive));
- expect(windows, everyElement(new isInstanceOf<Window>()));
- });
+ test('activeElement', () async {
+ var element = await driver.activeElement;
+ expect(await element.name, 'body');
+ await (await driver.findElement(new By.cssSelector('input[type=text]')))
+ .click();
+ element = await driver.activeElement;
+ expect(await element.name, 'input');
});
- test('execute', () {
- WebElement button;
+ test('windows', () async {
+ var windows = await driver.windows.toList();
+ expect(windows, hasLength(isPositive));
+ expect(windows, everyElement(new isInstanceOf<Window>()));
+ });
+
+ test('execute', () async {
+ WebElement button = await driver.findElement(new By.tagName('button'));
String script = '''
arguments[1].textContent = arguments[0];
return arguments[1];''';
- return driver.findElement(new By.tagName('button'))
- .then((_e) => button = _e)
- .then((_) => driver.execute(script, ['new text', button]))
- .then((WebElement e) {
- expect(e.text, completion('new text'));
- });
+ var e = await driver.execute(script, ['new text', button]);
+ expect(await e.text, 'new text');
});
- test('executeAsync', () {
- WebElement button;
+ test('executeAsync', () async {
+ WebElement button = await driver.findElement(new By.tagName('button'));
String script = '''
arguments[1].textContent = arguments[0];
arguments[2](arguments[1]);''';
- return driver.findElement(new By.tagName('button'))
- .then((_e) => button = _e)
- .then((_) => driver.executeAsync(script, ['new text', button]))
- .then((WebElement e) {
- expect(e.text, completion('new text'));
- });
+ var e = await driver.executeAsync(script, ['new text', button]);
+ expect(await e.text, 'new text');
});
- test('captureScreenshot', () {
- return driver.captureScreenshot()
- .then((screenshot) {
- expect(screenshot, hasLength(isPositive));
- expect(screenshot, everyElement(new isInstanceOf<int>()));
- });
+ test('captureScreenshot', () async {
+ var screenshot = await driver.captureScreenshot();
+ expect(screenshot, hasLength(isPositive));
+ expect(screenshot, everyElement(new isInstanceOf<int>()));
});
});
});
diff --git a/test/src/web_element_test.dart b/test/src/web_element_test.dart
index e227155..59f0b52 100644
--- a/test/src/web_element_test.dart
+++ b/test/src/web_element_test.dart
@@ -5,9 +5,7 @@
import '../test_util.dart';
void main() {
-
group('WebElement', () {
-
WebDriver driver;
WebElement table;
WebElement button;
@@ -17,191 +15,158 @@
WebElement disabled;
WebElement invisible;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver)
- .then((_) => driver.get(testPagePath))
- .then((_) => driver.findElement(new By.tagName('table')))
- .then((_element) => table = _element)
- .then((_) => driver.findElement(new By.tagName('button')))
- .then((_element) => button = _element)
- .then((_) => driver.findElement(new By.tagName('form')))
- .then((_element) => form = _element)
- .then((_) =>
- driver.findElement(new By.cssSelector('input[type=text]')))
- .then((_element) => textInput = _element)
- .then((_) =>
- driver.findElement(new By.cssSelector('input[type=checkbox]')))
- .then((_element) => checkbox = _element)
- .then((_) =>
- driver.findElement(new By.cssSelector('input[type=password]')))
- .then((_element) => disabled = _element)
- .then((_) => driver.findElement(new By.tagName('div')))
- .then((_element) => invisible = _element);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
+ await driver.get(testPagePath);
+ table = await driver.findElement(new By.tagName('table'));
+ button = await driver.findElement(new By.tagName('button'));
+ form = await driver.findElement(new By.tagName('form'));
+ textInput =
+ await driver.findElement(new By.cssSelector('input[type=text]'));
+ checkbox =
+ await driver.findElement(new By.cssSelector('input[type=checkbox]'));
+ disabled =
+ await driver.findElement(new By.cssSelector('input[type=password]'));
+ invisible = await driver.findElement(new By.tagName('div'));
});
tearDown(() => driver.quit());
- test('click', () {
- return button.click()
- .then((_) => driver.switchTo.alert)
- .then((alert) => alert.accept());
+ test('click', () async {
+ await button.click();
+ var alert = await driver.switchTo.alert;
+ await alert.accept();
});
- test('submit', () {
- return form.submit()
- .then((_) => driver.switchTo.alert)
- .then((alert) {
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(alert.text, 'form submitted');
- return alert.accept();
- });
+ test('submit', () async {
+ await form.submit();
+ var alert = await driver.switchTo.alert;
+ expect(alert.text, 'form submitted');
+ await alert.accept();
});
- test('sendKeys', () {
- return textInput.sendKeys('some keys')
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, 'some keys');
- });
+ test('sendKeys', () async {
+ await textInput.sendKeys('some keys');
+ expect(await textInput.attributes['value'], 'some keys');
});
- test('clear', () {
- return textInput.sendKeys('some keys')
- .then((_) => textInput.clear())
- .then((_) => textInput.attributes['value'])
- .then((value) {
- expect(value, '');
- });
+ test('clear', () async {
+ await textInput.sendKeys('some keys');
+ await textInput.clear();
+ expect(await textInput.attributes['value'], '');
});
- test('enabled', () {
- expect(table.enabled, completion(isTrue));
- expect(button.enabled, completion(isTrue));
- expect(form.enabled, completion(isTrue));
- expect(textInput.enabled, completion(isTrue));
- expect(checkbox.enabled, completion(isTrue));
- expect(disabled.enabled, completion(isFalse));
+ test('enabled', () async {
+ expect(await table.enabled, isTrue);
+ expect(await button.enabled, isTrue);
+ expect(await form.enabled, isTrue);
+ expect(await textInput.enabled, isTrue);
+ expect(await checkbox.enabled, isTrue);
+ expect(await disabled.enabled, isFalse);
});
- test('displayed', () {
- expect(table.displayed, completion(isTrue));
- expect(button.displayed, completion(isTrue));
- expect(form.displayed, completion(isTrue));
- expect(textInput.displayed, completion(isTrue));
- expect(checkbox.displayed, completion(isTrue));
- expect(disabled.displayed, completion(isTrue));
- expect(invisible.displayed, completion(isFalse));
+ test('displayed', () async {
+ expect(await table.displayed, isTrue);
+ expect(await button.displayed, isTrue);
+ expect(await form.displayed, isTrue);
+ expect(await textInput.displayed, isTrue);
+ expect(await checkbox.displayed, isTrue);
+ expect(await disabled.displayed, isTrue);
+ expect(await invisible.displayed, isFalse);
});
- test('location -- table', () {
- return table.location.then((location) {
- expect(location, isPoint);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(location.x, isNonNegative);
- expect(location.y, isNonNegative);
- });
+ test('location -- table', () async {
+ var location = await table.location;
+ expect(location, isPoint);
+ expect(location.x, isNonNegative);
+ expect(location.y, isNonNegative);
});
- test('location -- invisible', () {
- return invisible.location.then((location) {
- expect(location, isPoint);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(location.x, 0);
- expect(location.y, 0);
- });
+ test('location -- invisible', () async {
+ var location = await invisible.location;
+ expect(location, isPoint);
+ expect(location.x, 0);
+ expect(location.y, 0);
});
- test('size -- table', () {
- return table.size.then((size) {
- expect(size, isSize);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(size.width, isNonNegative);
- expect(size.height, isNonNegative);
- });
+ test('size -- table', () async {
+ var size = await table.size;
+ expect(size, isSize);
+ expect(size.width, isNonNegative);
+ expect(size.height, isNonNegative);
});
- test('size -- invisible', () {
- return invisible.size.then((size) {
- expect(size, isSize);
- // TODO(DrMarcII): I thought these should be 0
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(size.width, isNonNegative);
- expect(size.height, isNonNegative);
- });
+ test('size -- invisible', () async {
+ var size = await invisible.size;
+ expect(size, isSize);
+ // TODO(DrMarcII): I thought these should be 0
+ expect(size.width, isNonNegative);
+ expect(size.height, isNonNegative);
});
- test('name', () {
- expect(table.name, completion('table'));
- expect(button.name, completion('button'));
- expect(form.name, completion('form'));
- expect(textInput.name, completion('input'));
+ test('name', () async {
+ expect(await table.name, 'table');
+ expect(await button.name, 'button');
+ expect(await form.name, 'form');
+ expect(await textInput.name, 'input');
});
- test('text', () {
- expect(table.text, completion('r1c1 r1c2\nr2c1 r2c2'));
- expect(button.text, completion('button'));
- expect(invisible.text, completion(''));
+ test('text', () async {
+ expect(await table.text, 'r1c1 r1c2\nr2c1 r2c2');
+ expect(await button.text, 'button');
+ expect(await invisible.text, '');
});
- test('findElement -- success', () {
- return table.findElement(new By.tagName('tr'))
- .then((element) {
- expect(element, isWebElement);
- });
+ test('findElement -- success', () async {
+ var element = await table.findElement(new By.tagName('tr'));
+ expect(element, isWebElement);
});
- test('findElement -- failure', () {
- return button.findElement(new By.tagName('tr'))
- .catchError((error) {
- expect(error, isWebDriverError);
- });
+ test('findElement -- failure', () async {
+ try {
+ await button.findElement(new By.tagName('tr'));
+ throw 'Expected NoSuchElementException';
+ } on NoSuchElementException {}
});
- test('findElements -- 1 found', () {
- return form.findElements(new By.cssSelector('input[type=text]'))
- .then((elements) {
- expect(elements, hasLength(1));
- expect(elements, everyElement(isWebElement));
- });
+ test('findElements -- 1 found', () async {
+ var elements = await form
+ .findElements(new By.cssSelector('input[type=text]'))
+ .toList();
+ expect(elements, hasLength(1));
+ expect(elements, everyElement(isWebElement));
});
- test('findElements -- 4 found', () {
- return table.findElements(new By.tagName('td'))
- .then((elements) {
- expect(elements, hasLength(4));
- expect(elements, everyElement(isWebElement));
- });
+ test('findElements -- 4 found', () async {
+ var elements = await table.findElements(new By.tagName('td')).toList();
+ expect(elements, hasLength(4));
+ expect(elements, everyElement(isWebElement));
});
- test('findElements -- 0 found', () {
- return form.findElements(new By.tagName('td'))
- .then((elements) {
- expect(elements, isEmpty);
- });
+ test('findElements -- 0 found', () async {
+ var elements = await form.findElements(new By.tagName('td')).toList();
+ expect(elements, isEmpty);
});
- test('attributes', () {
- expect(table.attributes['id'], completion('table1'));
- expect(table.attributes['non-standard'],
- completion('a non standard attr'));
- expect(table.attributes['disabled'], completion(isNull));
- expect(disabled.attributes['disabled'], completion('true'));
+ test('attributes', () async {
+ expect(await table.attributes['id'], 'table1');
+ expect(await table.attributes['non-standard'], 'a non standard attr');
+ expect(await table.attributes['disabled'], isNull);
+ expect(await disabled.attributes['disabled'], 'true');
});
- test('cssProperties', () {
- expect(invisible.cssProperties['display'], completion('none'));
- expect(invisible.cssProperties['background-color'],
- completion('rgba(255, 0, 0, 1)'));
- expect(invisible.cssProperties['direction'], completion('ltr'));
+ test('cssProperties', () async {
+ expect(await invisible.cssProperties['display'], 'none');
+ expect(await invisible.cssProperties['background-color'],
+ 'rgba(255, 0, 0, 1)');
+ expect(await invisible.cssProperties['direction'], 'ltr');
});
- test('equals', () {
- expect(invisible.equals(disabled), completion(isFalse));
- return driver.findElement(new By.cssSelector('table'))
- .then((element) {
- expect(element.equals(table), completion(isTrue));
- });
+ test('equals', () async {
+ expect(await invisible.equals(disabled), isFalse);
+ var element = await driver.findElement(new By.cssSelector('table'));
+ expect(await element.equals(table), isTrue);
});
});
}
diff --git a/test/src/window_test.dart b/test/src/window_test.dart
index 489ec0f..494c378 100644
--- a/test/src/window_test.dart
+++ b/test/src/window_test.dart
@@ -5,50 +5,43 @@
import '../test_util.dart';
void main() {
-
- group('Window', () {
-
+ solo_group('Window', () {
WebDriver driver;
- setUp(() {
- return WebDriver.createDriver(desiredCapabilities: Capabilities.chrome)
- .then((_driver) => driver = _driver);
+ setUp(() async {
+ driver = await WebDriver.createDriver(
+ desiredCapabilities: Capabilities.chrome);
});
tearDown(() => driver.quit());
- test('size', () {
- return driver.window.setSize(new Size(400, 600))
- .then((_) => driver.window.size)
- .then((size) {
- expect(size, isSize);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(size.height, 400);
- expect(size.width, 600);
- });
+ test('size', () async {
+ var window = await driver.window;
+ await window.setSize(new Size(400, 600));
+ var size = await window.size;
+ expect(size, isSize);
+ expect(size.height, 400);
+ expect(size.width, 600);
});
- test('location', () {
- return driver.window.setLocation(new Point(10, 20))
- .then((_) => driver.window.location)
- .then((point) {
- expect(point, isPoint);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(point.x, 10);
- expect(point.y, 20);
- });
+ test('location', () async {
+ var window = await driver.window;
+
+ await window.setLocation(new Point(10, 20));
+ var point = await window.location;
+ expect(point, isPoint);
+ expect(point.x, 10);
+ expect(point.y, 20);
});
// fails in some cases with multiple monitors
- test('maximize', () {
- return driver.window.maximize()
- .then((_) => driver.window.location)
- .then((point) {
- expect(point, isPoint);
- // TODO(DrMarcII): Switch to hasProperty matchers
- expect(point.x, 0);
- expect(point.y, 0);
- });
+ test('maximize', () async {
+ var window = await driver.window;
+ await window.maximize();
+ var point = await window.location;
+ expect(point, isPoint);
+ expect(point.x, 0);
+ expect(point.y, 0);
});
});
}
diff --git a/test/test_util.dart b/test/test_util.dart
index bfb02b7..8cc0c78 100644
--- a/test/test_util.dart
+++ b/test/test_util.dart
@@ -11,7 +11,7 @@
final Matcher isPoint = new isInstanceOf<Point>();
String get testPagePath {
- if(_testPagePath == null) {
+ if (_testPagePath == null) {
_testPagePath = _getTestPagePath();
}
return _testPagePath;
@@ -20,7 +20,7 @@
String _getTestPagePath() {
var testPagePath = path.join(path.current, 'test', 'test_page.html');
testPagePath = path.absolute(testPagePath);
- if(!FileSystemEntity.isFileSync(testPagePath)) {
+ if (!FileSystemEntity.isFileSync(testPagePath)) {
throw new Exception('Could not find the test file at "$testPagePath".'
' Make sure you are running tests from the root of the project.');
}
diff --git a/test/webdriver_test.dart b/test/webdriver_test.dart
index 858db1d..2e4b19f 100644
--- a/test/webdriver_test.dart
+++ b/test/webdriver_test.dart
@@ -1,6 +1,6 @@
library webdriver_test;
-import 'package:unittest/compact_vm_config.dart';
+import 'package:unittest/vm_config.dart';
import 'src/alert_test.dart' as alert;
import 'src/keyboard_test.dart' as keyboard;
@@ -17,7 +17,7 @@
* as they are slow and they have external dependencies.
*/
void main() {
- useCompactVMConfiguration();
+ useVMConfiguration();
alert.main();
keyboard.main();