Add moveToElementCenter and moveToElementTopLeft to declare the origin for offset explicitly.
Explicitly include JsonWire Chrome in tests.
PiperOrigin-RevId: 254157910
diff --git a/lib/src/async/mouse.dart b/lib/src/async/mouse.dart
index 4529e49..9c57146 100644
--- a/lib/src/async/mouse.dart
+++ b/lib/src/async/mouse.dart
@@ -18,6 +18,8 @@
import 'package:webdriver/src/common/mouse.dart';
import 'package:webdriver/src/common/request_client.dart';
import 'package:webdriver/src/common/webdriver_handler.dart';
+import 'package:webdriver/src/handler/json_wire_handler.dart';
+import 'package:webdriver/src/handler/w3c_handler.dart';
class Mouse {
final AsyncRequestClient _client;
@@ -53,8 +55,12 @@
/// If [xOffset] and [yOffset] are specified, will move the mouse that distance
/// from its current location.
///
- /// If all three are specified, will move the mouse to the offset relative to
- /// the top-left corner of the [element].
+ /// If all three are specified, the behavior will be different
+ /// for W3C and JsonWire. For W3C, it will use [element] center as the
+ /// origin, while for JsonWire, it will use [element] top left corner.
+ /// To get a consistent behavior across browsers, you can try
+ /// [moveToElementCenter] and [moveToElementTopLeft] to specify the origin you
+ /// would like to use.
///
/// All other combinations of parameters are illegal.
///
@@ -73,6 +79,36 @@
absolute: absolute),
_handler.mouse.parseMoveToResponse);
+ /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
+ /// center of [element].
+ Future<void> moveToElementCenter(WebElement element,
+ {int xOffset, int yOffset}) async {
+ if (_handler is JsonWireWebDriverHandler) {
+ final size = await element.size;
+ await moveTo(
+ element: element,
+ xOffset: (xOffset ?? 0) + size.width ~/ 2,
+ yOffset: (yOffset ?? 0) + size.height ~/ 2);
+ } else {
+ await moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
+ }
+ }
+
+ /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
+ /// top left corner of [element].
+ Future<void> moveToElementTopLeft(WebElement element,
+ {int xOffset, int yOffset}) async {
+ if (_handler is W3cWebDriverHandler) {
+ final size = await element.size;
+ await moveTo(
+ element: element,
+ xOffset: (xOffset ?? 0) - size.width ~/ 2,
+ yOffset: (yOffset ?? 0) - size.height ~/ 2);
+ } else {
+ await moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
+ }
+ }
+
@override
String toString() => '$_handler.mouse($_client)';
diff --git a/lib/src/sync/mouse.dart b/lib/src/sync/mouse.dart
index 51a2582..d858d43 100644
--- a/lib/src/sync/mouse.dart
+++ b/lib/src/sync/mouse.dart
@@ -15,6 +15,8 @@
import 'package:webdriver/src/common/mouse.dart';
import 'package:webdriver/src/common/request_client.dart';
import 'package:webdriver/src/common/webdriver_handler.dart';
+import 'package:webdriver/src/handler/json_wire_handler.dart';
+import 'package:webdriver/src/handler/w3c_handler.dart';
import 'web_element.dart';
@@ -61,8 +63,12 @@
/// If [xOffset] and [yOffset] are specified, will move the mouse that
/// distance from its current location.
///
- /// If all three are specified, will move the mouse to the offset relative to
- /// the top-left corner of the [element].
+ /// If all three are specified, the behavior will be different
+ /// for W3C and JsonWire. For W3C, it will use [element] center as the
+ /// origin, while for JsonWire, it will use [element] top left corner.
+ /// To get a consistent behavior across browsers, you can try
+ /// [moveToElementCenter] and [moveToElementTopLeft] to specify the origin you
+ /// would like to use.
///
/// All other combinations of parameters are illegal.
///
@@ -79,6 +85,34 @@
_handler.mouse.parseMoveToResponse);
}
+ /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
+ /// center of [element].
+ void moveToElementCenter(WebElement element, {int xOffset, int yOffset}) {
+ if (_handler is JsonWireWebDriverHandler) {
+ final size = element.size;
+ moveTo(
+ element: element,
+ xOffset: (xOffset ?? 0) + size.width ~/ 2,
+ yOffset: (yOffset ?? 0) + size.height ~/ 2);
+ } else {
+ moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
+ }
+ }
+
+ /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
+ /// top left corner of [element].
+ void moveToElementTopLeft(WebElement element, {int xOffset, int yOffset}) {
+ if (_handler is W3cWebDriverHandler) {
+ final size = element.size;
+ moveTo(
+ element: element,
+ xOffset: (xOffset ?? 0) - size.width ~/ 2,
+ yOffset: (yOffset ?? 0) - size.height ~/ 2);
+ } else {
+ moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
+ }
+ }
+
@override
String toString() => '$_handler.mouse($_client)';
diff --git a/test/async_mouse_test.dart b/test/async_mouse_test.dart
index a5f4e41..1f092b7 100644
--- a/test/async_mouse_test.dart
+++ b/test/async_mouse_test.dart
@@ -28,6 +28,20 @@
WebElement button;
HttpServer server;
+ Future<bool> hasAlert() async {
+ try {
+ await driver.switchTo.alert.dismiss();
+ return true;
+ } on NoSuchAlertException {
+ return false;
+ }
+ }
+
+ Future<bool> mouseOnButton() async {
+ await driver.mouse.click();
+ return await hasAlert();
+ }
+
setUp(() async {
driver = await config.createTestDriver();
server = await config.createTestServerAndGoToTestPage(driver);
@@ -41,24 +55,39 @@
test('moveTo element/click', () async {
await driver.mouse.moveTo(element: button);
- await driver.mouse.click();
- var alert = await driver.switchTo.alert;
- await alert.dismiss();
+ expect(await mouseOnButton(), true);
});
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();
+ expect(await mouseOnButton(), true);
});
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();
+ await driver.mouse.moveTo(element: button, xOffset: 15, yOffset: 15);
+ // W3C uses center and JsonWire uses top left corner.
+ expect(await mouseOnButton(), driver.spec == WebDriverSpec.JsonWire);
+ });
+
+ test('moveTo element coordinates outside of element/click', () async {
+ await driver.mouse.moveTo(element: button, xOffset: -5, yOffset: -5);
+ // W3C uses center and JsonWire uses top left corner.
+ expect(await mouseOnButton(), driver.spec == WebDriverSpec.W3c);
+ });
+
+ test('moveToElementCenter moves to correct positions', () async {
+ await driver.mouse.moveToElementCenter(button, xOffset: -5, yOffset: -5);
+ expect(await mouseOnButton(), true);
+ await driver.mouse.moveToElementCenter(button, xOffset: 15, yOffset: 15);
+ expect(await mouseOnButton(), false);
+ });
+
+ test('moveToElementTopLeft moves to correct positions', () async {
+ await driver.mouse.moveToElementTopLeft(button, xOffset: -5, yOffset: -5);
+ expect(await mouseOnButton(), false);
+ await driver.mouse.moveToElementTopLeft(button, xOffset: 15, yOffset: 15);
+ expect(await mouseOnButton(), true);
});
// TODO(DrMarcII): Better up/down tests
@@ -66,16 +95,14 @@
await driver.mouse.moveTo(element: button);
await driver.mouse.down();
await driver.mouse.up();
- var alert = await driver.switchTo.alert;
- await alert.dismiss();
+ expect(await hasAlert(), true);
});
// TODO(DrMarcII): Better double click test
test('doubleClick', () async {
await driver.mouse.moveTo(element: button);
await driver.mouse.doubleClick();
- var alert = await driver.switchTo.alert;
- await alert.dismiss();
+ expect(await hasAlert(), true);
});
}, timeout: const Timeout(Duration(minutes: 2)));
}
diff --git a/test/sync/mouse.dart b/test/sync/mouse.dart
index 4f3b3f8..a8a67a8 100644
--- a/test/sync/mouse.dart
+++ b/test/sync/mouse.dart
@@ -28,6 +28,20 @@
WebElement button;
HttpServer server;
+ bool hasAlert() {
+ try {
+ driver.switchTo.alert.dismiss();
+ return true;
+ } on NoSuchAlertException {
+ return false;
+ }
+ }
+
+ bool mouseOnButton() {
+ driver.mouse.click();
+ return hasAlert();
+ }
+
setUp(() async {
driver = config.createTestDriver(spec: spec);
server = await config.createTestServerAndGoToTestPage(driver);
@@ -41,30 +55,23 @@
test('moveTo element/click', () {
driver.mouse.moveTo(element: button);
- driver.mouse.click();
- var alert = driver.switchTo.alert;
- alert.dismiss();
+ expect(mouseOnButton(), true);
});
test('moveTo coordinates/click', () {
var pos = button.location;
driver.mouse.moveTo(xOffset: pos.x + 5, yOffset: pos.y + 5);
- driver.mouse.click();
- var alert = driver.switchTo.alert;
- alert.dismiss();
+ expect(mouseOnButton(), true);
});
test('moveTo absolute coordinates/click', () {
if (driver.spec == WebDriverSpec.W3c) {
var pos = button.location;
driver.mouse.moveTo(xOffset: pos.x + 200, yOffset: pos.y + 200);
- driver.mouse.click();
- // Should have no alert
+ expect(mouseOnButton(), false);
driver.mouse
.moveTo(xOffset: pos.x + 5, yOffset: pos.y + 5, absolute: true);
- driver.mouse.click();
- var alert = driver.switchTo.alert;
- alert.dismiss();
+ expect(mouseOnButton(), true);
}
});
@@ -80,10 +87,29 @@
});
test('moveTo element coordinates/click', () {
- driver.mouse.moveTo(element: button, xOffset: 5, yOffset: 5);
- driver.mouse.click();
- var alert = driver.switchTo.alert;
- alert.dismiss();
+ driver.mouse.moveTo(element: button, xOffset: 15, yOffset: 15);
+ // W3C uses center and JsonWire uses top left corner.
+ expect(mouseOnButton(), driver.spec == WebDriverSpec.JsonWire);
+ });
+
+ test('moveTo element coordinates outside of element/click', () {
+ driver.mouse.moveTo(element: button, xOffset: -5, yOffset: -5);
+ // W3C uses center and JsonWire uses top left corner.
+ expect(mouseOnButton(), driver.spec == WebDriverSpec.W3c);
+ });
+
+ test('moveToElementCenter moves to correct positions', () {
+ driver.mouse.moveToElementCenter(button, xOffset: -5, yOffset: -5);
+ expect(mouseOnButton(), true);
+ driver.mouse.moveToElementCenter(button, xOffset: 15, yOffset: 15);
+ expect(mouseOnButton(), false);
+ });
+
+ test('moveToElementTopLeft moves to correct positions', () {
+ driver.mouse.moveToElementTopLeft(button, xOffset: -5, yOffset: -5);
+ expect(mouseOnButton(), false);
+ driver.mouse.moveToElementTopLeft(button, xOffset: 15, yOffset: 15);
+ expect(mouseOnButton(), true);
});
// TODO(DrMarcII): Better up/down tests