Merge find element logic for W3C spec. (#159)
* Refactor command_processor to be defined at driver creation time. Allows separate command processors for different specs.
* Refactors out element finder logic for WebDriver and WebElement to common location for W3C spec.
* Dartfmt.
diff --git a/lib/src/sync/w3c_spec/by.dart b/lib/src/sync/w3c_spec/by.dart
deleted file mode 100644
index 74bca6a..0000000
--- a/lib/src/sync/w3c_spec/by.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import '../common.dart' show By;
-
-/// Here we massage [By] instances into viable W3C /element requests.
-///
-/// In principle, W3C spec implementations should be nearly the same as
-/// the existing JSON wire spec. In practice compliance is uneven.
-Map<String, String> byToJson(By by) {
- var using;
- var value;
-
- switch (by.using) {
- case 'id': // This doesn't exist in the W3C spec.
- using = 'css selector';
- value = '#${by.value}';
- break;
- case 'tag name': // This is in the W3C spec, but not in geckodriver.
- using = 'css selector';
- value = by.value;
- break;
- // xpath, css selector, link text, partial link text, seem fine.
- default:
- using = by.using;
- value = by.value;
- }
-
- return {'using': using, 'value': value};
-}
diff --git a/lib/src/sync/w3c_spec/element_finder.dart b/lib/src/sync/w3c_spec/element_finder.dart
new file mode 100644
index 0000000..5d18062
--- /dev/null
+++ b/lib/src/sync/w3c_spec/element_finder.dart
@@ -0,0 +1,71 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'web_element.dart';
+
+import '../common.dart';
+import '../web_driver.dart';
+import '../web_element.dart';
+
+/// Handles logic for finding elements in both WebDriver and element contexts.
+class ElementFinder {
+ final WebDriver _driver;
+ final SearchContext _context;
+ final Resolver _resolver;
+
+ ElementFinder(this._driver, this._resolver, this._context);
+
+ /// Here we massage [By] instances into viable W3C /element requests.
+ ///
+ /// In principle, W3C spec implementations should be nearly the same as
+ /// the existing JSON wire spec. In practice compliance is uneven.
+ Map<String, String> _byToJson(By by) {
+ var using;
+ var value;
+
+ switch (by.using) {
+ case 'id': // This doesn't exist in the W3C spec.
+ using = 'css selector';
+ value = '#${by.value}';
+ break;
+ case 'tag name': // This is in the W3C spec, but not in geckodriver.
+ using = 'css selector';
+ value = by.value;
+ break;
+ // xpath, css selector, link text, partial link text, seem fine.
+ default:
+ using = by.using;
+ value = by.value;
+ }
+
+ return {'using': using, 'value': value};
+ }
+
+ List<WebElement> findElements(By by) => _findElements(by, 'elements');
+
+ WebElement findElement(By by) => _findElements(by, 'element')[0];
+
+ List<String> _unwrapReponse(Map<String, String> response) => response.values;
+
+ List<WebElement> _findElements(By by, String command) {
+ final elements = _unwrapReponse(_resolver.post(command, _byToJson(by)));
+ int i = 0;
+
+ final webElements = new List<W3cWebElement>();
+ for (final element in elements) {
+ webElements.add(new W3cWebElement(_driver, element, _context, by, i++));
+ }
+ return webElements;
+ }
+}
diff --git a/lib/src/sync/w3c_spec/web_driver.dart b/lib/src/sync/w3c_spec/web_driver.dart
index 4efa539..62e6eb2 100644
--- a/lib/src/sync/w3c_spec/web_driver.dart
+++ b/lib/src/sync/w3c_spec/web_driver.dart
@@ -15,7 +15,7 @@
import 'dart:convert' show BASE64;
import 'package:stack_trace/stack_trace.dart' show Chain;
-import 'by.dart' show byToJson;
+import 'element_finder.dart';
import 'target_locator.dart';
import 'timeouts.dart';
import 'web_element.dart';
@@ -45,6 +45,7 @@
final String id;
final Uri uri;
final bool filterStackTraces;
+ ElementFinder _finder;
@override
bool notifyListeners = true;
@@ -55,7 +56,9 @@
{this.filterStackTraces: true})
: this.uri = uri,
this.id = id,
- this._prefix = uri.resolve('session/$id/');
+ this._prefix = uri.resolve('session/$id/') {
+ _finder = new ElementFinder(this, new Resolver(driver, ''), this);
+ }
@override
void addEventListener(WebDriverListener listener) =>
@@ -73,25 +76,11 @@
@override
String get title => getRequest('title') as String;
- // TODO(staats): unify find logic with that in web_element.
@override
- List<WebElement> findElements(By by) {
- final elements = postRequest('elements', byToJson(by));
- int i = 0;
-
- final webElements = new List<W3cWebElement>();
- for (final element in elements) {
- webElements
- .add(new W3cWebElement(this, element[elementStr], this, by, i++));
- }
- return webElements;
- }
+ List<WebElement> findElements(By by) => _finder.findElements(by);
@override
- WebElement findElement(By by) {
- final element = postRequest('element', byToJson(by));
- return new W3cWebElement(this, element[elementStr], this, by);
- }
+ WebElement findElement(By by) => _finder.findElement(by);
@override
String get pageSource => getRequest('source') as String;
diff --git a/lib/src/sync/w3c_spec/web_element.dart b/lib/src/sync/w3c_spec/web_element.dart
index 764d415..ac90fcb 100644
--- a/lib/src/sync/w3c_spec/web_element.dart
+++ b/lib/src/sync/w3c_spec/web_element.dart
@@ -14,7 +14,7 @@
import 'dart:math' show Point, Rectangle;
-import 'by.dart' show byToJson;
+import 'element_finder.dart';
import '../common.dart';
import '../web_driver.dart';
@@ -23,6 +23,7 @@
class W3cWebElement implements WebElement, SearchContext {
final String _elementPrefix;
final Resolver _resolver;
+ ElementFinder _finder;
@override
final String id;
@@ -42,7 +43,9 @@
W3cWebElement(this.driver, id, [this.context, this.locator, this.index])
: this.id = id,
_elementPrefix = 'element/$id',
- _resolver = new Resolver(driver, 'element/$id');
+ _resolver = new Resolver(driver, 'element/$id') {
+ _finder = new ElementFinder(driver, _resolver, this);
+ }
@override
void click() => _resolver.post('click');
@@ -98,22 +101,10 @@
String get text => _resolver.get('text') as String;
@override
- WebElement findElement(By by) {
- final element = _resolver.post('element', byToJson(by));
- return new W3cWebElement(driver, element[elementStr], this, by);
- }
+ WebElement findElement(By by) => _finder.findElement(by);
@override
- List<WebElement> findElements(By by) {
- final elements = _resolver.post('elements', byToJson(by)) as Iterable;
- int i = 0;
- final webElements = new List<WebElement>();
- for (final element in elements) {
- webElements
- .add(new W3cWebElement(driver, element[elementStr], this, by, i++));
- }
- return webElements;
- }
+ List<WebElement> findElements(By by) => _finder.findElements(by);
@override
Attributes get attributes =>