From e884f5f6bb2def226bc0f529f8438e2dec8014c9 Mon Sep 17 00:00:00 2001 From: Peter Arrenbrecht Date: Mon, 25 Sep 2023 15:31:11 +0000 Subject: [PATCH 1/4] Support getting current timeouts in sync w3c drivers. Uses the W3C "Get Timeouts" API: https://www.w3.org/TR/webdriver1/#get-timeouts There is no such API in the JSON API: https://www.selenium.dev/documentation/legacy/json_wire_protocol/#command-summary Rationale: Allows sync clients to temporarily change a timeout and then restore it back to what it was before (which doesn't work for async clients anyway). Tested: Against geckodriver, and internally against Chrome. --- lib/src/common/timeouts.dart | 22 ++++++++++++ lib/src/common/webdriver_handler.dart | 7 ++++ lib/src/handler/json_wire/timeouts.dart | 13 +++++++ lib/src/handler/w3c/timeouts.dart | 15 +++++++++ lib/src/sync/timeouts.dart | 8 ++++- test/firefox_timeouts_test.dart | 2 +- test/sync/timeouts_w3c.dart | 45 +++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 lib/src/common/timeouts.dart create mode 100644 test/sync/timeouts_w3c.dart diff --git a/lib/src/common/timeouts.dart b/lib/src/common/timeouts.dart new file mode 100644 index 0000000..eaf988f --- /dev/null +++ b/lib/src/common/timeouts.dart @@ -0,0 +1,22 @@ +class TimeoutValues { + final Duration script; + final Duration implicit; + final Duration pageLoad; + + TimeoutValues( + {required this.script, required this.implicit, required this.pageLoad}); + + @override + String toString() => + 'TimeoutValues(script: $script, implicit: $implicit, pageLoad: $pageLoad)'; + + @override + int get hashCode => Object.hashAll([script, implicit, pageLoad]); + + @override + bool operator ==(Object other) => + other is TimeoutValues && + script == other.script && + implicit == other.implicit && + pageLoad == other.pageLoad; +} diff --git a/lib/src/common/webdriver_handler.dart b/lib/src/common/webdriver_handler.dart index ce1a25f..38eab4c 100644 --- a/lib/src/common/webdriver_handler.dart +++ b/lib/src/common/webdriver_handler.dart @@ -3,6 +3,7 @@ import 'dart:math'; import '../../async_core.dart'; import 'request.dart'; import 'session.dart'; +import 'timeouts.dart'; /// Handler for spec related request building and response parsing. /// @@ -502,6 +503,12 @@ abstract class TimeoutsHandler { /// Parses response for 'Set Page Load Timeout'. void parseSetPageLoadTimeoutResponse(WebDriverResponse response); + + /// Builds request for 'Get Timeouts'. + WebDriverRequest buildGetTimeoutsRequest(); + + /// Parses response for 'Get Timeouts'. + TimeoutValues parseGetTimeoutsResponse(WebDriverResponse response); } /// Handler for retrieving logs. diff --git a/lib/src/handler/json_wire/timeouts.dart b/lib/src/handler/json_wire/timeouts.dart index ee3b7e4..f4a40da 100644 --- a/lib/src/handler/json_wire/timeouts.dart +++ b/lib/src/handler/json_wire/timeouts.dart @@ -13,6 +13,7 @@ // limitations under the License. import '../../common/request.dart'; +import '../../common/timeouts.dart'; import '../../common/webdriver_handler.dart'; import 'utils.dart'; @@ -47,4 +48,16 @@ class JsonWireTimeoutsHandler extends TimeoutsHandler { void parseSetPageLoadTimeoutResponse(WebDriverResponse response) { parseJsonWireResponse(response); } + + @override + WebDriverRequest buildGetTimeoutsRequest() { + // Not supported by JSON protocol: + // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#command-summary + throw UnimplementedError(); + } + + @override + TimeoutValues parseGetTimeoutsResponse(WebDriverResponse response) { + throw UnimplementedError(); + } } diff --git a/lib/src/handler/w3c/timeouts.dart b/lib/src/handler/w3c/timeouts.dart index 724d277..df0702d 100644 --- a/lib/src/handler/w3c/timeouts.dart +++ b/lib/src/handler/w3c/timeouts.dart @@ -13,6 +13,7 @@ // limitations under the License. import '../../common/request.dart'; +import '../../common/timeouts.dart'; import '../../common/webdriver_handler.dart'; import 'utils.dart'; @@ -46,4 +47,18 @@ class W3cTimeoutsHandler extends TimeoutsHandler { void parseSetPageLoadTimeoutResponse(WebDriverResponse response) { parseW3cResponse(response); } + + @override + WebDriverRequest buildGetTimeoutsRequest() => + WebDriverRequest.getRequest('timeouts'); + + @override + TimeoutValues parseGetTimeoutsResponse(WebDriverResponse response) { + final timeouts = parseW3cResponse(response) as Map; + return TimeoutValues( + script: Duration(milliseconds: timeouts['script'] as int), + implicit: Duration(milliseconds: timeouts['implicit'] as int), + pageLoad: Duration(milliseconds: timeouts['pageLoad'] as int), + ); + } } diff --git a/lib/src/sync/timeouts.dart b/lib/src/sync/timeouts.dart index 945c941..e896f22 100644 --- a/lib/src/sync/timeouts.dart +++ b/lib/src/sync/timeouts.dart @@ -13,9 +13,10 @@ // limitations under the License. import '../common/request_client.dart'; +import '../common/timeouts.dart'; import '../common/webdriver_handler.dart'; -/// Sets WebDriver timeouts. +/// Sets or gets WebDriver timeouts. class Timeouts { final SyncRequestClient _client; final WebDriverHandler _handler; @@ -40,6 +41,11 @@ class Timeouts { _handler.timeouts.parseSetPageLoadTimeoutResponse); } + /// Gets the current timeout values. + TimeoutValues getAllTimeouts() => _client.send( + _handler.timeouts.buildGetTimeoutsRequest(), + _handler.timeouts.parseGetTimeoutsResponse); + @override String toString() => '$_handler.timeouts($_client)'; diff --git a/test/firefox_timeouts_test.dart b/test/firefox_timeouts_test.dart index a86d475..a27e312 100644 --- a/test/firefox_timeouts_test.dart +++ b/test/firefox_timeouts_test.dart @@ -16,7 +16,7 @@ import 'package:test/test.dart'; import 'package:webdriver/sync_core.dart'; -import 'sync/timeouts.dart'; +import 'sync/timeouts_w3c.dart'; void main() { runTests(spec: WebDriverSpec.W3c); diff --git a/test/sync/timeouts_w3c.dart b/test/sync/timeouts_w3c.dart new file mode 100644 index 0000000..189f888 --- /dev/null +++ b/test/sync/timeouts_w3c.dart @@ -0,0 +1,45 @@ +// Copyright 2015 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.options_test; + +import 'package:test/test.dart'; +import 'package:webdriver/src/common/timeouts.dart'; +import 'package:webdriver/sync_core.dart'; + +import '../configs/sync_io_config.dart' as config; + +void runTests({WebDriverSpec spec = WebDriverSpec.Auto}) { + group('TimeOuts', () { + late WebDriver driver; + + setUp(() { + driver = config.createTestDriver(spec: spec); + }); + + test('set all timeouts', () { + const five = Duration(seconds: 5); + const one = Duration(seconds: 1); + const ten = Duration(seconds: 10); + + driver.timeouts.setScriptTimeout(five); + driver.timeouts.setImplicitTimeout(one); + driver.timeouts.setPageLoadTimeout(ten); + + expect(driver.timeouts.getAllTimeouts(), + TimeoutValues(script: five, implicit: one, pageLoad: ten)); + }); + }, timeout: const Timeout(Duration(minutes: 2))); +} From b8f8bda130125dab91778e0fbf706e5369e53e1f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Oct 2023 18:17:53 +0000 Subject: [PATCH 2/4] Add changelog entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c031d4f..a85497e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.0.4-wip -* Require Dart 3.0. +* Add support for reading and setting webdriver timeouts with the sync client. +* Require Dart 3.0.0 ## 3.0.3 From 04f88312525af8e7beda4d51deea7e7957494633 Mon Sep 17 00:00:00 2001 From: Peter Arrenbrecht Date: Thu, 18 Jan 2024 08:04:33 +0000 Subject: [PATCH 3/4] use UnsupportedError --- lib/src/handler/json_wire/timeouts.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/src/handler/json_wire/timeouts.dart b/lib/src/handler/json_wire/timeouts.dart index f4a40da..d9aeee7 100644 --- a/lib/src/handler/json_wire/timeouts.dart +++ b/lib/src/handler/json_wire/timeouts.dart @@ -51,13 +51,15 @@ class JsonWireTimeoutsHandler extends TimeoutsHandler { @override WebDriverRequest buildGetTimeoutsRequest() { - // Not supported by JSON protocol: - // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#command-summary - throw UnimplementedError(); + throw UnsupportedError(_timeoutsUnsupportedMsg); } @override TimeoutValues parseGetTimeoutsResponse(WebDriverResponse response) { - throw UnimplementedError(); + throw UnsupportedError(_timeoutsUnsupportedMsg); } } + +// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#command-summary +const _timeoutsUnsupportedMsg = + 'The JSON wire protocol does not support setting timeouts'; From f1ebd9082e02e036b5f951b32c0230e45b0521ba Mon Sep 17 00:00:00 2001 From: Peter Arrenbrecht Date: Thu, 18 Jan 2024 08:04:50 +0000 Subject: [PATCH 4/4] add test for default timeouts --- test/sync/timeouts_w3c.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/sync/timeouts_w3c.dart b/test/sync/timeouts_w3c.dart index 189f888..aacdb8f 100644 --- a/test/sync/timeouts_w3c.dart +++ b/test/sync/timeouts_w3c.dart @@ -41,5 +41,14 @@ void runTests({WebDriverSpec spec = WebDriverSpec.Auto}) { expect(driver.timeouts.getAllTimeouts(), TimeoutValues(script: five, implicit: one, pageLoad: ten)); }); + + test('get default timeouts', () { + expect( + driver.timeouts.getAllTimeouts(), + TimeoutValues( + script: const Duration(seconds: 30), + implicit: Duration.zero, + pageLoad: const Duration(minutes: 5))); + }); }, timeout: const Timeout(Duration(minutes: 2))); }