Add mouse.hide() in dart:webdriver.

PiperOrigin-RevId: 254260141
diff --git a/lib/src/async/mouse.dart b/lib/src/async/mouse.dart
index 9c57146..67d3882 100644
--- a/lib/src/async/mouse.dart
+++ b/lib/src/async/mouse.dart
@@ -109,6 +109,17 @@
     }
   }
 
+  /// Moves the mouse away to hide its effect, like hover over element.
+  ///
+  /// For W3C, the mouse cannot move out of the screen, the workaround would be
+  /// to move to somewhere on edge where it's not on any element. You can
+  /// configure the location with [w3cXOffset] and [w3cYOffset]. By default,
+  /// it's at (1000, 0).
+  Future<void> hide({int w3cXOffset = 1000, int w3cYOffset = 0}) =>
+      _handler is W3cWebDriverHandler
+          ? moveTo(xOffset: w3cXOffset, yOffset: w3cYOffset, absolute: true)
+          : moveTo(xOffset: -10000, yOffset: -10000);
+
   @override
   String toString() => '$_handler.mouse($_client)';
 
diff --git a/lib/src/sync/mouse.dart b/lib/src/sync/mouse.dart
index d858d43..fd3db71 100644
--- a/lib/src/sync/mouse.dart
+++ b/lib/src/sync/mouse.dart
@@ -113,6 +113,17 @@
     }
   }
 
+  /// Moves the mouse away to hide its effect, like hover over element.
+  ///
+  /// For W3C, the mouse cannot move out of the screen, the workaround would be
+  /// to move to somewhere on edge where it's not on any element. You can
+  /// configure the location with [w3cXOffset] and [w3cYOffset]. By default,
+  /// it's at (1000, 0).
+  void hide({int w3cXOffset = 1000, int w3cYOffset = 0}) =>
+      _handler is W3cWebDriverHandler
+          ? moveTo(xOffset: w3cXOffset, yOffset: w3cYOffset, absolute: true)
+          : moveTo(xOffset: -10000, yOffset: -10000);
+
   @override
   String toString() => '$_handler.mouse($_client)';
 
diff --git a/test/async_mouse_test.dart b/test/async_mouse_test.dart
index 1f092b7..0706b32 100644
--- a/test/async_mouse_test.dart
+++ b/test/async_mouse_test.dart
@@ -90,6 +90,25 @@
       expect(await mouseOnButton(), true);
     });
 
+    test('hide moves away from the current location', () async {
+      await driver.mouse.moveTo(element: button);
+      expect(await mouseOnButton(), true);
+      await driver.mouse.hide();
+      expect(await mouseOnButton(), false);
+    });
+
+    test('hide moves to given location in w3c.', () async {
+      if (driver.spec == WebDriverSpec.W3c) {
+        var pos = await button.location;
+        await driver.mouse.moveTo(element: button);
+        expect(await mouseOnButton(), true);
+        await driver.mouse.moveTo(xOffset: 0, yOffset: 0, absolute: true);
+        expect(await mouseOnButton(), false);
+        await driver.mouse.hide(w3cXOffset: pos.x + 5, w3cYOffset: pos.y + 5);
+        expect(await mouseOnButton(), true);
+      }
+    });
+
     // TODO(DrMarcII): Better up/down tests
     test('down/up', () async {
       await driver.mouse.moveTo(element: button);
diff --git a/test/sync/mouse.dart b/test/sync/mouse.dart
index a8a67a8..fe95015 100644
--- a/test/sync/mouse.dart
+++ b/test/sync/mouse.dart
@@ -112,6 +112,25 @@
       expect(mouseOnButton(), true);
     });
 
+    test('hide moves away from the current location', () {
+      driver.mouse.moveTo(element: button);
+      expect(mouseOnButton(), true);
+      driver.mouse.hide();
+      expect(mouseOnButton(), false);
+    });
+
+    test('hide moves to given location in w3c.', () {
+      if (driver.spec == WebDriverSpec.W3c) {
+        var pos = button.location;
+        driver.mouse.moveTo(element: button);
+        expect(mouseOnButton(), true);
+        driver.mouse.moveTo(xOffset: 0, yOffset: 0, absolute: true);
+        expect(mouseOnButton(), false);
+        driver.mouse.hide(w3cXOffset: pos.x + 5, w3cYOffset: pos.y + 5);
+        expect(mouseOnButton(), true);
+      }
+    });
+
     // TODO(DrMarcII): Better up/down tests
     test('down/up', () {
       driver.mouse.moveTo(element: button);