Skip to content

Commit

Permalink
Adds logic to automatically infer specification type during WebDriver…
Browse files Browse the repository at this point in the history
… creation. (#172)

* Adds automated spec inference ability during WebDriver creation.

* Adds ability to define spec during WebDriver creation. Sets defaults to W3C for FireFox and JSONWire for Chrome.

* Adds test for spec inference. Updates logic for reusing exisiting sessions for W3C spec.

* Add error messages.

* Updates spec inference test with different exception types.
  • Loading branch information
staats-google authored Jun 27, 2017
1 parent 0045360 commit 45d8121
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 11 deletions.
2 changes: 1 addition & 1 deletion lib/src/sync/json_wire_spec/exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

library webdriver.exception;
library webdriver.json_exception;

import '../exception.dart';

Expand Down
51 changes: 51 additions & 0 deletions lib/src/sync/spec_inference_response_processor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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 'dart:convert' show JSON;

import 'package:sync_http/sync_http.dart';
import 'package:webdriver/sync_core.dart';

/// Inferred spec and sessionId from a session creation request.
class InferredResponse {
final String sessionId;

final WebDriverSpec spec;

InferredResponse(this.sessionId, this.spec);
}

/// Infers the spec during session creation.
dynamic inferSessionResponseSpec(SyncHttpClientResponse response, bool _) {
Map responseBody;
try {
responseBody = JSON.decode(response.body);
} catch (e) {}

// TODO(staats): create more description error messages.
if (response.statusCode < 200 || response.statusCode > 299) {
throw 'Response code: ${response.statusCode}';
}

// JSON responses have multiple keys.
if (responseBody.keys.length > 1) {
return new InferredResponse(
responseBody['sessionId'], WebDriverSpec.JsonWire);
// W3C responses have only one key, value.
} else if (responseBody.keys.length == 1) {
return new InferredResponse(
responseBody['value']['sessionId'], WebDriverSpec.W3c);
}
throw 'Could not infer spec type; number of keys: ${responseBody.keys}';
}
2 changes: 1 addition & 1 deletion lib/src/sync/w3c_spec/exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

library webdriver.exception;
library webdriver.w3c_exception;

import '../exception.dart';

Expand Down
14 changes: 9 additions & 5 deletions lib/sync_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'package:webdriver/src/sync/capabilities.dart' show Capabilities;
import 'package:webdriver/src/sync/web_driver.dart' show WebDriver;

import 'package:webdriver/src/sync/command_processor.dart';
import 'package:webdriver/src/sync/spec_inference_response_processor.dart';
import 'package:webdriver/src/sync/json_wire_spec/response_processor.dart';
import 'package:webdriver/src/sync/json_wire_spec/web_driver.dart' as jwire;
import 'package:webdriver/src/sync/w3c_spec/response_processor.dart';
Expand Down Expand Up @@ -79,7 +80,12 @@ WebDriver createDriver(
return new w3c.W3cWebDriver(processor, uri, response['sessionId'],
new UnmodifiableMapView(response['value'] as Map<String, dynamic>));
case WebDriverSpec.Auto:
throw 'Not yet supported!';
final response =
new SyncHttpCommandProcessor(processor: inferSessionResponseSpec)
.post(uri.resolve('session'), {'desiredCapabilities': desired},
value: true) as InferredResponse;
return fromExistingSession(response.sessionId,
uri: uri, spec: response.spec);
default:
throw 'Not yet supported!'; // Impossible.
}
Expand All @@ -102,12 +108,10 @@ WebDriver fromExistingSession(String sessionId,
case WebDriverSpec.W3c:
final processor =
new SyncHttpCommandProcessor(processor: processW3cResponse);
final response = processor.get(uri.resolve('session/$sessionId'))
as Map<String, dynamic>;
return new w3c.W3cWebDriver(
processor, uri, sessionId, new UnmodifiableMapView(response));
processor, uri, sessionId, new Map<String, dynamic>());
case WebDriverSpec.Auto:
throw 'Not yet supported!';
throw 'Not supported!';
default:
throw 'Not yet supported!'; // Impossible.
}
Expand Down
64 changes: 64 additions & 0 deletions test/sync/spec_inference_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// 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.

@TestOn("vm")
library webdriver.spec_inference_test;

import 'package:test/test.dart';
import 'package:webdriver/src/sync/json_wire_spec/exception.dart' as json;
import 'package:webdriver/src/sync/w3c_spec/exception.dart' as w3c;
import 'package:webdriver/sync_core.dart';

import 'sync_io_config.dart' as config;

void main() {
group('Spec inference', () {
WebDriver driver;

setUp(() {});

tearDown(() {
if (driver != null) {
driver.quit();
}
driver = null;
});

test('chrome works', () {
driver = config.createChromeTestDriver(spec: WebDriverSpec.Auto);
driver.get(config.testPagePath);
final button = driver.findElement(const By.tagName('button'));
try {
button.findElement(const By.tagName('tr'));
throw 'Expected NoSuchElementException';
} catch(e) {
expect(e, new isInstanceOf<json.NoSuchElementException>());
expect(e.toString(), contains('Unable to locate element'));
}
});

test('firefox work', () {
driver = config.createFirefoxTestDriver(spec: WebDriverSpec.Auto);
driver.get(config.testPagePath);
final button = driver.findElement(const By.tagName('button'));
try {
button.findElement(const By.tagName('tr'));
throw 'Expected W3cWebDriverException';
} catch(e) {
expect(e, new isInstanceOf<w3c.W3cWebDriverException>());
expect(e.toString(), contains('Unable to locate element'));
}
});
}, timeout: new Timeout(new Duration(minutes: 2)));
}
11 changes: 7 additions & 4 deletions test/sync/sync_io_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@ final Uri _defaultChromeUri = Uri.parse('http://127.0.0.1:4444/wd/hub/');
final Uri _defaultFirefoxUri = Uri.parse('http://127.0.0.1:4445/');

WebDriver createFirefoxTestDriver(
{Map<String, dynamic> additionalCapabilities}) {
{Map<String, dynamic> additionalCapabilities,
WebDriverSpec spec: WebDriverSpec.W3c}) {
final capabilities = Capabilities.firefox;

if (additionalCapabilities != null) {
capabilities.addAll(additionalCapabilities);
}
return createDriver(
uri: _defaultFirefoxUri, desired: capabilities, spec: WebDriverSpec.W3c);
uri: _defaultFirefoxUri, desired: capabilities, spec: spec);
}

WebDriver createChromeTestDriver(
{Map<String, dynamic> additionalCapabilities}) {
{Map<String, dynamic> additionalCapabilities,
WebDriverSpec spec: WebDriverSpec.JsonWire}) {
var capabilities = Capabilities.chrome;
Map env = Platform.environment;

Expand All @@ -62,5 +64,6 @@ WebDriver createChromeTestDriver(
capabilities.addAll(additionalCapabilities);
}

return createDriver(uri: _defaultChromeUri, desired: additionalCapabilities);
return createDriver(
uri: _defaultChromeUri, desired: additionalCapabilities, spec: spec);
}

0 comments on commit 45d8121

Please sign in to comment.