diff --git a/examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs b/examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs new file mode 100644 index 000000000000..a2d6984c9069 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs @@ -0,0 +1,53 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; + +namespace SeleniumDocs.ActionsAPI +{ + [TestClass] + public class ActionsTest : BaseTest + { + [TestMethod] + public void Pause() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + DateTime start = DateTime.Now; + + IWebElement clickable = driver.FindElement(By.Id("clickable")); + new Actions(driver) + .MoveToElement(clickable) + .Pause(TimeSpan.FromSeconds(1)) + .ClickAndHold() + .Pause(TimeSpan.FromSeconds(1)) + .SendKeys("abc") + .Perform(); + + TimeSpan duration = DateTime.Now - start; + Assert.IsTrue(duration > TimeSpan.FromSeconds(2)); + Assert.IsTrue(duration < TimeSpan.FromSeconds(3)); + } + + [TestMethod] + public void ReleaseAll() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement clickable = driver.FindElement(By.Id("clickable")); + var actions = new Actions(driver); + actions.ClickAndHold(clickable) + .KeyDown(Keys.Shift) + .KeyDown(Keys.Alt) + .SendKeys("a") + .Perform(); + + ((WebDriver)driver).ResetInputState(); + + actions.SendKeys("a").Perform(); + var value = clickable.GetAttribute("value"); + Assert.AreEqual("Å", value[..1]); + Assert.AreEqual("a", value.Substring(1, 1)); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs b/examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs new file mode 100644 index 000000000000..fc71810c9cb8 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs @@ -0,0 +1,93 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; + +namespace SeleniumDocs.ActionsAPI +{ + [TestClass] + public class KeysTest : BaseTest + { + [TestMethod] + public void KeyDown() + { + driver.Url = "https://selenium.dev/selenium/web/single_text_input.html"; + + new Actions(driver) + .KeyDown(Keys.Shift) + .SendKeys("a") + .Perform(); + + IWebElement textField = driver.FindElement(By.Id("textInput")); + Assert.AreEqual("A", textField.GetAttribute("value")); + } + + [TestMethod] + public void KeyUp() + { + driver.Url = "https://selenium.dev/selenium/web/single_text_input.html"; + + new Actions(driver) + .KeyDown(Keys.Shift) + .SendKeys("a") + .KeyUp(Keys.Shift) + .SendKeys("b") + .Perform(); + + IWebElement textField = driver.FindElement(By.Id("textInput")); + Assert.AreEqual("Ab", textField.GetAttribute("value")); + } + + [TestMethod] + public void SendKeysToActiveElement() + { + driver.Url = "https://selenium.dev/selenium/web/single_text_input.html"; + + new Actions(driver) + .SendKeys("abc") + .Perform(); + + IWebElement textField = driver.FindElement(By.Id("textInput")); + Assert.AreEqual("abc", textField.GetAttribute("value")); + } + + [TestMethod] + public void SendKeysToDesignatedElement() + { + driver.Url = "https://selenium.dev/selenium/web/single_text_input.html"; + driver.FindElement(By.TagName("body")).Click(); + + IWebElement textField = driver.FindElement(By.Id("textInput")); + new Actions(driver) + .SendKeys(textField, "abc") + .Perform(); + + Assert.AreEqual("abc", textField.GetAttribute("value")); + } + + [TestMethod] + public void CopyAndPaste() + { + driver.Url = "https://selenium.dev/selenium/web/single_text_input.html"; + + var capabilities = ((WebDriver)driver).Capabilities; + String platformName = (string)capabilities.GetCapability("platformName"); + + String cmdCtrl = platformName.Contains("mac") ? Keys.Command : Keys.Control; + + new Actions(driver) + .SendKeys("Selenium!") + .SendKeys(Keys.ArrowLeft) + .KeyDown(Keys.Shift) + .SendKeys(Keys.ArrowUp) + .KeyUp(Keys.Shift) + .KeyDown(cmdCtrl) + .SendKeys("xvv") + .KeyUp(cmdCtrl) + .Perform(); + + IWebElement textField = driver.FindElement(By.Id("textInput")); + Assert.AreEqual("SeleniumSelenium!", textField.GetAttribute("value")); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs b/examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs new file mode 100644 index 000000000000..71785a8a1586 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs @@ -0,0 +1,208 @@ +using System; +using System.Drawing; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; + +namespace SeleniumDocs.ActionsAPI +{ + [TestClass] + public class MouseTest : BaseTest + { + [TestMethod] + public void ClickAndHold() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement clickable = driver.FindElement(By.Id("clickable")); + new Actions(driver) + .ClickAndHold(clickable) + .Perform(); + + Assert.AreEqual("focused", driver.FindElement(By.Id("click-status")).Text); + } + + [TestMethod] + public void ClickAndRelease() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement clickable = driver.FindElement(By.Id("click")); + new Actions(driver) + .Click(clickable) + .Perform(); + + Assert.IsTrue(driver.Url.Contains("resultPage.html")); + } + + [TestMethod] + public void RightClick() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement clickable = driver.FindElement(By.Id("clickable")); + new Actions(driver) + .ContextClick(clickable) + .Perform(); + + Assert.AreEqual("context-clicked", driver.FindElement(By.Id("click-status")).Text); + } + + [TestMethod] + public void BackClick() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + driver.FindElement(By.Id("click")).Click(); + Assert.AreEqual("We Arrive Here", driver.Title); + + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse"); + actionBuilder.AddAction(mouse.CreatePointerDown(MouseButton.Back)); + actionBuilder.AddAction(mouse.CreatePointerUp(MouseButton.Back)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + Assert.AreEqual("BasicMouseInterfaceTest", driver.Title); + } + + [TestMethod] + public void ForwardClick() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + driver.FindElement(By.Id("click")).Click(); + driver.Navigate().Back(); + Assert.AreEqual("BasicMouseInterfaceTest", driver.Title); + + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse"); + actionBuilder.AddAction(mouse.CreatePointerDown(MouseButton.Forward)); + actionBuilder.AddAction(mouse.CreatePointerUp(MouseButton.Forward)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + Assert.AreEqual("We Arrive Here", driver.Title); + } + + [TestMethod] + public void DoubleClick() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement clickable = driver.FindElement(By.Id("clickable")); + new Actions(driver) + .DoubleClick(clickable) + .Perform(); + + Assert.AreEqual("double-clicked", driver.FindElement(By.Id("click-status")).Text); + } + + [TestMethod] + public void Hovers() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement hoverable = driver.FindElement(By.Id("hover")); + new Actions(driver) + .MoveToElement(hoverable) + .Perform(); + + Assert.AreEqual("hovered", driver.FindElement(By.Id("move-status")).Text); + } + + [TestMethod] + [Obsolete("Obsolete")] + public void MoveByOffsetFromTopLeftOfElement() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement tracker = driver.FindElement(By.Id("mouse-tracker")); + new Actions(driver) + .MoveToElement(tracker, 8, 11, MoveToElementOffsetOrigin.TopLeft) + .Perform(); + + string[] result = driver.FindElement(By.Id("relative-location")).Text.Split(", "); + Assert.IsTrue(Math.Abs(int.Parse(result[0]) - 8) < 2); + Assert.IsTrue(Math.Abs(int.Parse(result[1]) - 11) < 2); + } + + [TestMethod] + public void MoveByOffsetFromCenterOfElement() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement tracker = driver.FindElement(By.Id("mouse-tracker")); + new Actions(driver) + .MoveToElement(tracker, 8, 11, MoveToElementOffsetOrigin.Center) + .Perform(); + + string[] result = driver.FindElement(By.Id("relative-location")).Text.Split(", "); + Assert.IsTrue(Math.Abs(int.Parse(result[0]) - 100 - 8) < 2); + Assert.IsTrue(Math.Abs(int.Parse(result[1]) - 100 - 11) < 2); + } + + [TestMethod] + public void MoveByOffsetFromViewport() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse"); + actionBuilder.AddAction(mouse.CreatePointerMove(CoordinateOrigin.Viewport, + 8, 12, TimeSpan.Zero)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + string[] result = driver.FindElement(By.Id("absolute-location")).Text.Split(", "); + Assert.IsTrue(Math.Abs(int.Parse(result[0]) - 8) < 2); + Assert.IsTrue(Math.Abs(int.Parse(result[1]) - 12) < 2); + } + + [TestMethod] + public void MoveByOffsetFromCurrentPointerLocation() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice mouse = new PointerInputDevice(PointerKind.Mouse, "default mouse"); + actionBuilder.AddAction(mouse.CreatePointerMove(CoordinateOrigin.Viewport, + 8, 12, TimeSpan.Zero)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + new Actions(driver) + .MoveByOffset(13, 15) + .Perform(); + + string[] result = driver.FindElement(By.Id("absolute-location")).Text.Split(", "); + Assert.IsTrue(Math.Abs(int.Parse(result[0]) - 8 - 13) < 2); + Assert.IsTrue(Math.Abs(int.Parse(result[1]) - 12 - 15) < 2); + } + + [TestMethod] + public void DragToElement() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement draggable = driver.FindElement(By.Id("draggable")); + IWebElement droppable = driver.FindElement(By.Id("droppable")); + new Actions(driver) + .DragAndDrop(draggable, droppable) + .Perform(); + + Assert.AreEqual("dropped", driver.FindElement(By.Id("drop-status")).Text); + } + + [TestMethod] + public void DragByOffset() + { + driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html"; + + IWebElement draggable = driver.FindElement(By.Id("draggable")); + Point start = draggable.Location; + Point finish = driver.FindElement(By.Id("droppable")).Location; + new Actions(driver) + .DragAndDropToOffset(draggable, finish.X - start.X, finish.Y - start.Y) + .Perform(); + + Assert.AreEqual("dropped", driver.FindElement(By.Id("drop-status")).Text); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs b/examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs new file mode 100644 index 000000000000..9866f569114f --- /dev/null +++ b/examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; + +namespace SeleniumDocs.ActionsAPI +{ + [TestClass] + public class PenTest : BaseTest + { + [TestMethod] + public void UsePen() + { + driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html"; + + IWebElement pointerArea = driver.FindElement(By.Id("pointerArea")); + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen"); + + actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800))); + actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left)); + actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer, + 2, 2, TimeSpan.Zero)); + actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + var moves = driver.FindElements(By.ClassName("pointermove")); + var moveTo = getProperties(moves.ElementAt(0)); + var down = getProperties(driver.FindElement(By.ClassName("pointerdown"))); + var moveBy = getProperties(moves.ElementAt(1)); + var up = getProperties(driver.FindElement(By.ClassName("pointerup"))); + + Point location = pointerArea.Location; + Size size = pointerArea.Size; + int centerX = location.X + size.Width / 2; + int centerY = location.Y + size.Height / 2; + + Assert.AreEqual("-1", moveTo["button"]); + Assert.AreEqual("pen", moveTo["pointerType"]); + Assert.AreEqual((centerX).ToString(), moveTo["pageX"]); + Assert.AreEqual((centerY).ToString(), moveTo["pageY"]); + Assert.AreEqual("0", down["button"]); + Assert.AreEqual("pen", down["pointerType"]); + Assert.AreEqual((centerX).ToString(), down["pageX"]); + Assert.AreEqual((centerY).ToString(), down["pageY"]); + Assert.AreEqual("-1", moveBy["button"]); + Assert.AreEqual("pen", moveBy["pointerType"]); + Assert.AreEqual((centerX + 2).ToString(), moveBy["pageX"]); + Assert.AreEqual((centerY + 2).ToString(), moveBy["pageY"]); + Assert.AreEqual("0", up["button"]); + Assert.AreEqual("pen", up["pointerType"]); + Assert.AreEqual((centerX + 2).ToString(), up["pageX"]); + Assert.AreEqual((centerY + 2).ToString(), up["pageY"]); + } + + [TestMethod] + public void SetPointerEventProperties() + { + driver.Url = "https://selenium.dev/selenium/web/pointerActionsPage.html"; + + IWebElement pointerArea = driver.FindElement(By.Id("pointerArea")); + ActionBuilder actionBuilder = new ActionBuilder(); + PointerInputDevice pen = new PointerInputDevice(PointerKind.Pen, "default pen"); + PointerInputDevice.PointerEventProperties properties = new PointerInputDevice.PointerEventProperties() { + TiltX = -72, + TiltY = 9, + Twist = 86, + }; + actionBuilder.AddAction(pen.CreatePointerMove(pointerArea, 0, 0, TimeSpan.FromMilliseconds(800))); + actionBuilder.AddAction(pen.CreatePointerDown(MouseButton.Left)); + actionBuilder.AddAction(pen.CreatePointerMove(CoordinateOrigin.Pointer, + 2, 2, TimeSpan.Zero, properties)); + actionBuilder.AddAction(pen.CreatePointerUp(MouseButton.Left)); + ((IActionExecutor)driver).PerformActions(actionBuilder.ToActionSequenceList()); + + var moves = driver.FindElements(By.ClassName("pointermove")); + var moveTo = getProperties(moves.ElementAt(0)); + var down = getProperties(driver.FindElement(By.ClassName("pointerdown"))); + var moveBy = getProperties(moves.ElementAt(1)); + var up = getProperties(driver.FindElement(By.ClassName("pointerup"))); + + Point location = pointerArea.Location; + Size size = pointerArea.Size; + int centerX = location.X + size.Width / 2; + int centerY = location.Y + size.Height / 2; + + Assert.AreEqual("-1", moveTo["button"]); + Assert.AreEqual("pen", moveTo["pointerType"]); + Assert.AreEqual((centerX).ToString(), moveTo["pageX"]); + Assert.AreEqual((centerY).ToString(), moveTo["pageY"]); + Assert.AreEqual("0", down["button"]); + Assert.AreEqual("pen", down["pointerType"]); + Assert.AreEqual((centerX).ToString(), down["pageX"]); + Assert.AreEqual((centerY).ToString(), down["pageY"]); + Assert.AreEqual("-1", moveBy["button"]); + Assert.AreEqual("pen", moveBy["pointerType"]); + Assert.AreEqual((centerX + 2).ToString(), moveBy["pageX"]); + Assert.AreEqual((centerY + 2).ToString(), moveBy["pageY"]); + Assert.AreEqual((-72).ToString(), moveBy["tiltX"]); + Assert.AreEqual((9).ToString(), moveBy["tiltY"]); + Assert.AreEqual((86).ToString(), moveBy["twist"]); + Assert.AreEqual("0", up["button"]); + Assert.AreEqual("pen", up["pointerType"]); + Assert.AreEqual((centerX + 2).ToString(), up["pageX"]); + Assert.AreEqual((centerY + 2).ToString(), up["pageY"]); + } + + private Dictionary getProperties(IWebElement element) + { + var str = element.Text; + str = str[(str.Split()[0].Length + 1)..]; + IEnumerable keyValue = str.Split(", ").Select(part => part.Split(":")); + return keyValue.ToDictionary(split => split[0].Trim(), split => split[1].Trim()); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs b/examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs new file mode 100644 index 000000000000..86e5ad934335 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs @@ -0,0 +1,117 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; + +namespace SeleniumDocs.ActionsAPI +{ + [TestClass] + public class WheelTest : BaseTest + { + [TestMethod] + public void ShouldAllowScrollingToAnElement() + { + driver.Url = + "https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"; + + IWebElement iframe = driver.FindElement(By.TagName("iframe")); + new Actions(driver) + .ScrollToElement(iframe) + .Perform(); + + Assert.IsTrue(IsInViewport(iframe)); + } + + [TestMethod] + public void ShouldAllowScrollingFromViewportByGivenAmount() + { + driver.Url = + "https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"; + + IWebElement footer = driver.FindElement(By.TagName("footer")); + int deltaY = footer.Location.Y; + new Actions(driver) + .ScrollByAmount(0, deltaY) + .Perform(); + + Assert.IsTrue(IsInViewport(footer)); + } + + [TestMethod] + public void ShouldScrollFromElementByGivenAmount() + { + driver.Url = + "https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"; + + IWebElement iframe = driver.FindElement(By.TagName("iframe")); + WheelInputDevice.ScrollOrigin scrollOrigin = new WheelInputDevice.ScrollOrigin + { + Element = iframe + }; + new Actions(driver) + .ScrollFromOrigin(scrollOrigin, 0, 200) + .Perform(); + + driver.SwitchTo().Frame(iframe); + IWebElement checkbox = driver.FindElement(By.Name("scroll_checkbox")); + Assert.IsTrue(IsInViewport(checkbox)); + } + + [TestMethod] + public void ShouldAllowScrollingFromElementByGivenAmountWithOffset() + { + driver.Url = + "https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"; + + IWebElement footer = driver.FindElement(By.TagName("footer")); + var scrollOrigin = new WheelInputDevice.ScrollOrigin + { + Element = footer, + XOffset = 0, + YOffset = -50 + }; + new Actions(driver) + .ScrollFromOrigin(scrollOrigin, 0, 200) + .Perform(); + + IWebElement iframe = driver.FindElement(By.TagName("iframe")); + driver.SwitchTo().Frame(iframe); + IWebElement checkbox = driver.FindElement(By.Name("scroll_checkbox")); + Assert.IsTrue(IsInViewport(checkbox)); + } + + [TestMethod] + public void ShouldAllowScrollingFromViewportByGivenAmountFromOrigin() + { + driver.Url = + "https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame.html"; + + var scrollOrigin = new WheelInputDevice.ScrollOrigin + { + Viewport = true, + XOffset = 10, + YOffset = 10 + }; + new Actions(driver) + .ScrollFromOrigin(scrollOrigin, 0, 200) + .Perform(); + + IWebElement iframe = driver.FindElement(By.TagName("iframe")); + driver.SwitchTo().Frame(iframe); + IWebElement checkbox = driver.FindElement(By.Name("scroll_checkbox")); + Assert.IsTrue(IsInViewport(checkbox)); + } + + private bool IsInViewport(IWebElement element) + { + String script = + "for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n" + + "e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n" + + "return f\n" + + "window.pageYOffset&&t+o>window.pageXOffset"; + IJavaScriptExecutor javascriptDriver = this.driver as IJavaScriptExecutor; + + return (bool)javascriptDriver.ExecuteScript(script, element); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/BaseTest.cs b/examples/dotnet/SeleniumDocs/BaseTest.cs new file mode 100644 index 000000000000..ec1bdc3e8c3a --- /dev/null +++ b/examples/dotnet/SeleniumDocs/BaseTest.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using WebDriverManager; +using WebDriverManager.DriverConfigs.Impl; + +namespace SeleniumDocs +{ + public class BaseTest + { + protected IWebDriver driver; + + [TestInitialize] + public void CreateDriver() + { + new DriverManager().SetUpDriver(new ChromeConfig()); + driver = new ChromeDriver(); + } + + [TestCleanup] + public void QuitDriver() + { + driver.Quit(); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj b/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj index 3143af15b2f9..9d142416aa0e 100644 --- a/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj +++ b/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj @@ -9,7 +9,7 @@ - + diff --git a/examples/java/pom.xml b/examples/java/pom.xml index c264885700ba..8e5b34843787 100644 --- a/examples/java/pom.xml +++ b/examples/java/pom.xml @@ -12,7 +12,7 @@ org.seleniumhq.selenium selenium-java - 4.1.2 + 4.2.1 org.junit.jupiter diff --git a/examples/java/src/test/java/dev/selenium/BaseTest.java b/examples/java/src/test/java/dev/selenium/BaseTest.java new file mode 100644 index 000000000000..914e7c0183f0 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/BaseTest.java @@ -0,0 +1,25 @@ +package dev.selenium; + +import io.github.bonigarcia.wdm.WebDriverManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.chrome.ChromeDriver; +public class BaseTest { + public WebDriver driver; + + @BeforeAll static void setDriver() { + WebDriverManager.chromedriver().setup(); + } + + @BeforeEach + public void setup() { + driver = new ChromeDriver(); + } + + @AfterEach + public void quit() { + driver.quit(); + } +} diff --git a/examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java b/examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java new file mode 100644 index 000000000000..36f803e4ecf8 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java @@ -0,0 +1,53 @@ +package dev.selenium.actions_api; + +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.RemoteWebDriver; + +import java.time.Duration; + +public class ActionsTest extends BaseTest { + @Test + public void pause() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + long start = System.currentTimeMillis(); + + WebElement clickable = driver.findElement(By.id("clickable")); + new Actions(driver) + .moveToElement(clickable) + .pause(Duration.ofSeconds(1)) + .clickAndHold() + .pause(Duration.ofSeconds(1)) + .sendKeys("abc") + .perform(); + + long duration = System.currentTimeMillis() - start; + Assertions.assertTrue(duration > 2000); + Assertions.assertTrue(duration < 3000); + } + + @Test + public void releasesAll() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement clickable = driver.findElement(By.id("clickable")); + Actions actions = new Actions(driver); + actions.clickAndHold(clickable) + .keyDown(Keys.SHIFT) + .keyDown(Keys.ALT) + .sendKeys("a") + .perform(); + + ((RemoteWebDriver) driver).resetInputState(); + + actions.sendKeys("a").perform(); + Assertions.assertEquals("Å", String.valueOf(clickable.getAttribute("value").charAt(0))); + Assertions.assertEquals("a", String.valueOf(clickable.getAttribute("value").charAt(1))); + } +} diff --git a/examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java b/examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java new file mode 100644 index 000000000000..368c73273b6b --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java @@ -0,0 +1,89 @@ +package dev.selenium.actions_api; + +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.HasCapabilities; +import org.openqa.selenium.Keys; +import org.openqa.selenium.Platform; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +public class KeysTest extends BaseTest { + @Test + public void keyDown() { + driver.get("https://www.selenium.dev/selenium/web/single_text_input.html"); + + new Actions(driver) + .keyDown(Keys.SHIFT) + .sendKeys("a") + .perform(); + + WebElement textField = driver.findElement(By.id("textInput")); + Assertions.assertEquals("A", textField.getAttribute("value")); + } + + @Test + public void keyUp() { + driver.get("https://www.selenium.dev/selenium/web/single_text_input.html"); + + new Actions(driver) + .keyDown(Keys.SHIFT) + .sendKeys("a") + .keyUp(Keys.SHIFT) + .sendKeys("b") + .perform(); + + WebElement textField = driver.findElement(By.id("textInput")); + Assertions.assertEquals("Ab", textField.getAttribute("value")); + } + + @Test + public void sendKeysToActiveElement() { + driver.get("https://www.selenium.dev/selenium/web/single_text_input.html"); + + new Actions(driver) + .sendKeys("abc") + .perform(); + + WebElement textField = driver.findElement(By.id("textInput")); + Assertions.assertEquals("abc", textField.getAttribute("value")); + } + + @Test + public void sendKeysToDesignatedElement() { + driver.get("https://www.selenium.dev/selenium/web/single_text_input.html"); + driver.findElement(By.tagName("body")).click(); + + WebElement textField = driver.findElement(By.id("textInput")); + new Actions(driver) + .sendKeys(textField, "Selenium!") + .perform(); + + Assertions.assertEquals("Selenium!", textField.getAttribute("value")); + } + + @Test + public void copyAndPaste() { + driver.get("https://www.selenium.dev/selenium/web/single_text_input.html"); + + Platform platformName = ((HasCapabilities) driver).getCapabilities().getPlatformName(); + + Keys cmdCtrl = platformName.is(Platform.MAC) ? Keys.COMMAND : Keys.CONTROL; + + WebElement textField = driver.findElement(By.id("textInput")); + new Actions(driver) + .sendKeys(textField, "Selenium!") + .sendKeys(Keys.ARROW_LEFT) + .keyDown(Keys.SHIFT) + .sendKeys(Keys.ARROW_UP) + .keyUp(Keys.SHIFT) + .keyDown(cmdCtrl) + .sendKeys("xvv") + .keyUp(cmdCtrl) + .perform(); + + Assertions.assertEquals("SeleniumSelenium!", textField.getAttribute("value")); + } +} diff --git a/examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java b/examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java new file mode 100644 index 000000000000..f085c4053a87 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java @@ -0,0 +1,188 @@ +package dev.selenium.actions_api; + +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Rectangle; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.PointerInput; +import org.openqa.selenium.interactions.Sequence; +import org.openqa.selenium.remote.RemoteWebDriver; + +import java.time.Duration; +import java.util.Collections; + +public class MouseTest extends BaseTest { + @Test + public void clickAndHold() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement clickable = driver.findElement(By.id("clickable")); + new Actions(driver) + .clickAndHold(clickable) + .perform(); + + Assertions.assertEquals("focused", driver.findElement(By.id("click-status")).getText()); + } + + @Test + public void clickAndRelease() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement clickable = driver.findElement(By.id("click")); + new Actions(driver) + .click(clickable) + .perform(); + + Assertions.assertTrue(driver.getCurrentUrl().contains("resultPage.html")); + } + + @Test + public void rightClick() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement clickable = driver.findElement(By.id("clickable")); + new Actions(driver) + .contextClick(clickable) + .perform(); + + Assertions.assertEquals("context-clicked", driver.findElement(By.id("click-status")).getText()); + } + + @Test + public void backClick() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + driver.findElement(By.id("click")).click(); + Assertions.assertEquals(driver.getTitle(), "We Arrive Here"); + + PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse"); + + Sequence actions = new Sequence(mouse, 0) + .addAction(mouse.createPointerDown(PointerInput.MouseButton.BACK.asArg())) + .addAction(mouse.createPointerUp(PointerInput.MouseButton.BACK.asArg())); + + ((RemoteWebDriver) driver).perform(Collections.singletonList(actions)); + + Assertions.assertEquals("BasicMouseInterfaceTest", driver.getTitle()); + } + + @Test + public void forwardClick() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + driver.findElement(By.id("click")).click(); + driver.navigate().back(); + Assertions.assertEquals(driver.getTitle(), "BasicMouseInterfaceTest"); + + PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse"); + + Sequence actions = new Sequence(mouse, 0) + .addAction(mouse.createPointerDown(PointerInput.MouseButton.FORWARD.asArg())) + .addAction(mouse.createPointerUp(PointerInput.MouseButton.FORWARD.asArg())); + + ((RemoteWebDriver) driver).perform(Collections.singletonList(actions)); + + Assertions.assertEquals("We Arrive Here", driver.getTitle()); + } + + @Test + public void doubleClick() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement clickable = driver.findElement(By.id("clickable")); + new Actions(driver) + .doubleClick(clickable) + .perform(); + + Assertions.assertEquals("double-clicked", driver.findElement(By.id("click-status")).getText()); + } + + @Test + public void hovers() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement hoverable = driver.findElement(By.id("hover")); + new Actions(driver) + .moveToElement(hoverable) + .perform(); + + Assertions.assertEquals("hovered", driver.findElement(By.id("move-status")).getText()); + } + + @Test + public void moveByOffsetFromElement() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement tracker = driver.findElement(By.id("mouse-tracker")); + new Actions(driver) + .moveToElement(tracker, 8, 11) + .perform(); + + String[] result = driver.findElement(By.id("relative-location")).getText().split(", "); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[0]) - 100 - 8) < 2); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[1]) - 100 - 11) < 2); + } + + @Test + public void moveByOffsetFromViewport() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse"); + + Sequence actions = new Sequence(mouse, 0) + .addAction(mouse.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), 8, 12)); + + ((RemoteWebDriver) driver).perform(Collections.singletonList(actions)); + + String[] result = driver.findElement(By.id("absolute-location")).getText().split(", "); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[0]) - 8) < 2); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[1]) - 12) < 2); + } + + @Test + public void moveByOffsetFromCurrentPointer() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + PointerInput mouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse"); + + Sequence actions = new Sequence(mouse, 0) + .addAction(mouse.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), 8, 11)); + ((RemoteWebDriver) driver).perform(Collections.singletonList(actions)); + + new Actions(driver) + .moveByOffset(13, 15) + .perform(); + + String[] result = driver.findElement(By.id("absolute-location")).getText().split(", "); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[0]) - 8 - 13) < 2); + Assertions.assertTrue(Math.abs(Integer.parseInt(result[1]) - 11 - 15) < 2); + } + + @Test + public void dragsToElement() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement draggable = driver.findElement(By.id("draggable")); + WebElement droppable = driver.findElement(By.id("droppable")); + new Actions(driver) + .dragAndDrop(draggable, droppable) + .perform(); + + Assertions.assertEquals("dropped", driver.findElement(By.id("drop-status")).getText()); + } + + @Test + public void dragsByOffset() { + driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html"); + + WebElement draggable = driver.findElement(By.id("draggable")); + Rectangle start = draggable.getRect(); + Rectangle finish = driver.findElement(By.id("droppable")).getRect(); + new Actions(driver) + .dragAndDropBy(draggable, finish.getX() - start.getX(), finish.getY() - start.getY()) + .perform(); + + Assertions.assertEquals("dropped", driver.findElement(By.id("drop-status")).getText()); + } +} diff --git a/examples/java/src/test/java/dev/selenium/actions_api/PenTest.java b/examples/java/src/test/java/dev/selenium/actions_api/PenTest.java new file mode 100644 index 000000000000..fc8dd1458ee2 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/actions_api/PenTest.java @@ -0,0 +1,124 @@ +package dev.selenium.actions_api; + +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Rectangle; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.PointerInput; +import org.openqa.selenium.interactions.Sequence; +import org.openqa.selenium.remote.RemoteWebDriver; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PenTest extends BaseTest { + @Test + public void usePen() { + driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html"); + + WebElement pointerArea = driver.findElement(By.id("pointerArea")); + new Actions(driver) + .setActivePointer(PointerInput.Kind.PEN, "default pen") + .moveToElement(pointerArea) + .clickAndHold() + .moveByOffset(2, 2) + .release() + .perform(); + + List moves = driver.findElements(By.className("pointermove")); + Map moveTo = getPropertyInfo(moves.get(0)); + Map down = getPropertyInfo(driver.findElement(By.className("pointerdown"))); + Map moveBy = getPropertyInfo(moves.get(1)); + Map up = getPropertyInfo(driver.findElement(By.className("pointerup"))); + + Rectangle rect = pointerArea.getRect(); + + int centerX = (int) Math.floor(rect.width / 2 + rect.getX()); + int centerY = (int) Math.floor(rect.height / 2 + rect.getY()); + Assertions.assertEquals("-1", moveTo.get("button")); + Assertions.assertEquals("pen", moveTo.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY")); + Assertions.assertEquals("0", down.get("button")); + Assertions.assertEquals("pen", down.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX), down.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY), down.get("pageY")); + Assertions.assertEquals("-1", moveBy.get("button")); + Assertions.assertEquals("pen", moveBy.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY")); + Assertions.assertEquals("0", up.get("button")); + Assertions.assertEquals("pen", up.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY")); + } + + @Test + public void setPointerEventProperties() { + driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html"); + + WebElement pointerArea = driver.findElement(By.id("pointerArea")); + PointerInput pen = new PointerInput(PointerInput.Kind.PEN, "default pen"); + PointerInput.PointerEventProperties eventProperties = PointerInput.eventProperties() + .setTiltX(-72) + .setTiltY(9) + .setTwist(86); + PointerInput.Origin origin = PointerInput.Origin.fromElement(pointerArea); + + Sequence actionListPen = new Sequence(pen, 0) + .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0)) + .addAction(pen.createPointerDown(0)) + .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties)) + .addAction(pen.createPointerUp(0)); + + ((RemoteWebDriver) driver).perform(Collections.singletonList(actionListPen)); + + List moves = driver.findElements(By.className("pointermove")); + Map moveTo = getPropertyInfo(moves.get(0)); + Map down = getPropertyInfo(driver.findElement(By.className("pointerdown"))); + Map moveBy = getPropertyInfo(moves.get(1)); + Map up = getPropertyInfo(driver.findElement(By.className("pointerup"))); + + Rectangle rect = pointerArea.getRect(); + int centerX = (int) Math.floor(rect.width / 2 + rect.getX()); + int centerY = (int) Math.floor(rect.height / 2 + rect.getY()); + Assertions.assertEquals("-1", moveTo.get("button")); + Assertions.assertEquals("pen", moveTo.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX), moveTo.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY), moveTo.get("pageY")); + Assertions.assertEquals("0", down.get("button")); + Assertions.assertEquals("pen", down.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX), down.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY), down.get("pageY")); + Assertions.assertEquals("-1", moveBy.get("button")); + Assertions.assertEquals("pen", moveBy.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX + 2), moveBy.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY + 2), moveBy.get("pageY")); + Assertions.assertEquals("-72", moveBy.get("tiltX")); + Assertions.assertEquals("9", moveBy.get("tiltY")); + Assertions.assertEquals("86", moveBy.get("twist")); + Assertions.assertEquals("0", up.get("button")); + Assertions.assertEquals("pen", up.get("pointerType")); + Assertions.assertEquals(String.valueOf(centerX + 2), up.get("pageX")); + Assertions.assertEquals(String.valueOf(centerY + 2), up.get("pageY")); + } + + private Map getPropertyInfo(WebElement element) { + String text = element.getText(); + text = text.substring(text.indexOf(' ') + 1); + + return Arrays.stream(text.split(", ")) + .map(s -> s.split(": ")) + .collect(Collectors.toMap( + a -> a[0], + a -> a[1] + )); + } +} diff --git a/examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java b/examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java new file mode 100644 index 000000000000..eb79ca310088 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java @@ -0,0 +1,94 @@ +package dev.selenium.actions_api; + +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.WheelInput; + +public class WheelTest extends BaseTest { + @Test + public void shouldScrollToElement() { + driver.get("https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"); + + WebElement iframe = driver.findElement(By.tagName("iframe")); + new Actions(driver) + .scrollToElement(iframe) + .perform(); + + Assertions.assertTrue(inViewport(iframe)); + } + + @Test + public void shouldScrollFromViewportByGivenAmount() { + driver.get("https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"); + + WebElement footer = driver.findElement(By.tagName("footer")); + int deltaY = footer.getRect().y; + new Actions(driver) + .scrollByAmount(0, deltaY) + .perform(); + + Assertions.assertTrue(inViewport(footer)); + } + + @Test + public void shouldScrollFromElementByGivenAmount() { + driver.get("https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"); + + WebElement iframe = driver.findElement(By.tagName("iframe")); + WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(iframe); + new Actions(driver) + .scrollFromOrigin(scrollOrigin, 0, 200) + .perform(); + + driver.switchTo().frame(iframe); + WebElement checkbox = driver.findElement(By.name("scroll_checkbox")); + Assertions.assertTrue(inViewport(checkbox)); + } + + @Test + public void shouldScrollFromElementByGivenAmountWithOffset() { + driver.get("https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"); + + WebElement footer = driver.findElement(By.tagName("footer")); + WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(footer, 0, -50); + new Actions(driver) + .scrollFromOrigin(scrollOrigin,0, 200) + .perform(); + + WebElement iframe = driver.findElement(By.tagName("iframe")); + driver.switchTo().frame(iframe); + WebElement checkbox = driver.findElement(By.name("scroll_checkbox")); + Assertions.assertTrue(inViewport(checkbox)); + } + + @Test + public void shouldScrollFromViewportByGivenAmountFromOrigin() { + driver.get("https://www.selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame.html"); + + WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromViewport(10, 10); + new Actions(driver) + .scrollFromOrigin(scrollOrigin, 0, 200) + .perform(); + + WebElement iframe = driver.findElement(By.tagName("iframe")); + driver.switchTo().frame(iframe); + WebElement checkbox = driver.findElement(By.name("scroll_checkbox")); + Assertions.assertTrue(inViewport(checkbox)); + } + + private boolean inViewport(WebElement element) { + + String script = + "for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n" + + "e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n" + + "return f\n" + + "window.pageYOffset&&t+o>window.pageXOffset"; + + return (boolean) ((JavascriptExecutor) driver).executeScript(script, element); + } +} diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index 1408b5c0c5dc..5d844bdecaf0 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,4 +1,4 @@ -selenium==4.1.3 +selenium==4.2.0 pytest flake8 webdriver_manager diff --git a/examples/python/tests/actions_api/test_actions.py b/examples/python/tests/actions_api/test_actions.py new file mode 100644 index 000000000000..8618e11c735f --- /dev/null +++ b/examples/python/tests/actions_api/test_actions.py @@ -0,0 +1,43 @@ +from time import time + +from selenium.webdriver import Keys, ActionChains +from selenium.webdriver.common.actions.action_builder import ActionBuilder +from selenium.webdriver.common.by import By + + +def test_pauses(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + start = time() + + clickable = driver.find_element(By.ID, "clickable") + ActionChains(driver)\ + .move_to_element(clickable)\ + .pause(1)\ + .click_and_hold()\ + .pause(1)\ + .send_keys("abc")\ + .perform() + + duration = time() - start + assert duration > 2 + assert duration < 3 + + +def test_releases_all(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + clickable = driver.find_element(By.ID, "clickable") + ActionChains(driver)\ + .click_and_hold(clickable)\ + .key_down(Keys.SHIFT)\ + .key_down(Keys.ALT)\ + .key_down("a")\ + .perform() + + ActionBuilder(driver).clear_actions() + + ActionChains(driver).key_down('a').perform() + + assert clickable.get_attribute('value')[0] == "Å" + assert clickable.get_attribute('value')[1] == "a" diff --git a/examples/python/tests/actions_api/test_keys.py b/examples/python/tests/actions_api/test_keys.py new file mode 100644 index 000000000000..66c8aeafcde8 --- /dev/null +++ b/examples/python/tests/actions_api/test_keys.py @@ -0,0 +1,68 @@ +import sys + +from selenium.webdriver import Keys, ActionChains +from selenium.webdriver.common.by import By + + +def test_key_down(driver): + driver.get('https://selenium.dev/selenium/web/single_text_input.html') + + ActionChains(driver)\ + .key_down(Keys.SHIFT)\ + .send_keys("abc")\ + .perform() + + assert driver.find_element(By.ID, "textInput").get_attribute('value') == "ABC" + + +def test_key_up(driver): + driver.get('https://selenium.dev/selenium/web/single_text_input.html') + + ActionChains(driver)\ + .key_down(Keys.SHIFT)\ + .send_keys("a")\ + .key_up(Keys.SHIFT)\ + .send_keys("b")\ + .perform() + + assert driver.find_element(By.ID, "textInput").get_attribute('value') == "Ab" + + +def test_send_keys_to_active_element(driver): + driver.get('https://selenium.dev/selenium/web/single_text_input.html') + + ActionChains(driver)\ + .send_keys("abc")\ + .perform() + + assert driver.find_element(By.ID, "textInput").get_attribute('value') == "abc" + + +def test_send_keys_to_designated_element(driver): + driver.get('https://selenium.dev/selenium/web/single_text_input.html') + driver.find_element(By.TAG_NAME, "body").click() + + text_input = driver.find_element(By.ID, "textInput") + ActionChains(driver)\ + .send_keys_to_element(text_input, "abc")\ + .perform() + + assert driver.find_element(By.ID, "textInput").get_attribute('value') == "abc" + + +def test_copy_and_paste(driver): + driver.get('https://selenium.dev/selenium/web/single_text_input.html') + cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL + + ActionChains(driver)\ + .send_keys("Selenium!")\ + .send_keys(Keys.ARROW_LEFT)\ + .key_down(Keys.SHIFT)\ + .send_keys(Keys.ARROW_UP)\ + .key_up(Keys.SHIFT)\ + .key_down(cmd_ctrl)\ + .send_keys("xvv")\ + .key_up(cmd_ctrl)\ + .perform() + + assert driver.find_element(By.ID, "textInput").get_attribute('value') == "SeleniumSelenium!" diff --git a/examples/python/tests/actions_api/test_mouse.py b/examples/python/tests/actions_api/test_mouse.py new file mode 100644 index 000000000000..d6929c9ee881 --- /dev/null +++ b/examples/python/tests/actions_api/test_mouse.py @@ -0,0 +1,165 @@ +from time import sleep + +from selenium.webdriver import ActionChains +from selenium.webdriver.common.actions.action_builder import ActionBuilder +from selenium.webdriver.common.actions.mouse_button import MouseButton +from selenium.webdriver.common.by import By + + +def test_click_and_hold(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + clickable = driver.find_element(By.ID, "clickable") + ActionChains(driver)\ + .click_and_hold(clickable)\ + .perform() + + sleep(0.5) + assert driver.find_element(By.ID, "click-status").text == "focused" + + +def test_click_and_release(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + clickable = driver.find_element(By.ID, "click") + ActionChains(driver)\ + .click(clickable)\ + .perform() + + assert "resultPage.html" in driver.current_url + + +def test_right_click(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + clickable = driver.find_element(By.ID, "clickable") + ActionChains(driver)\ + .context_click(clickable)\ + .perform() + + sleep(0.5) + assert driver.find_element(By.ID, "click-status").text == "context-clicked" + + +def test_back_click_ab(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + driver.find_element(By.ID, "click").click() + assert driver.title == "We Arrive Here" + + action = ActionBuilder(driver) + action.pointer_action.pointer_down(MouseButton.BACK) + action.pointer_action.pointer_up(MouseButton.BACK) + action.perform() + + assert driver.title == "BasicMouseInterfaceTest" + + +def test_forward_click_ab(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + driver.find_element(By.ID, "click").click() + driver.back() + assert driver.title == "BasicMouseInterfaceTest" + + action = ActionBuilder(driver) + action.pointer_action.pointer_down(MouseButton.FORWARD) + action.pointer_action.pointer_up(MouseButton.FORWARD) + action.perform() + + assert driver.title == "We Arrive Here" + + +def test_double_click(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + clickable = driver.find_element(By.ID, "clickable") + ActionChains(driver)\ + .double_click(clickable)\ + .perform() + + assert driver.find_element(By.ID, "click-status").text == "double-clicked" + + +def test_hover(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + hoverable = driver.find_element(By.ID, "hover") + ActionChains(driver)\ + .move_to_element(hoverable)\ + .perform() + + assert driver.find_element(By.ID, "move-status").text == "hovered" + + +def test_move_by_offset_from_element(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + mouse_tracker = driver.find_element(By.ID, "mouse-tracker") + ActionChains(driver)\ + .move_to_element_with_offset(mouse_tracker, 8, 11)\ + .perform() + + coordinates = driver.find_element(By.ID, "relative-location").text.split(", ") + assert abs(int(coordinates[0]) - 8) < 2 + assert abs(int(coordinates[1]) - 11) < 2 + + +def test_move_by_offset_from_viewport_origin_ab(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + action = ActionBuilder(driver) + action.pointer_action.move_to_location(8, 12) + action.perform() + + coordinates = driver.find_element(By.ID, "absolute-location").text.split(", ") + + assert abs(int(coordinates[0]) - 8) < 2 + assert abs(int(coordinates[1]) - 11) < 2 + + +def test_move_by_offset_from_current_pointer_ab(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + action = ActionBuilder(driver) + action.pointer_action.move_to_location(6, 3) + action.perform() + + ActionChains(driver)\ + .move_by_offset( 13, 15)\ + .perform() + + coordinates = driver.find_element(By.ID, "absolute-location").text.split(", ") + + assert abs(int(coordinates[0]) - 6 - 13) < 2 + assert abs(int(coordinates[1]) - 3 - 15) < 2 + + +def test_drag_and_drop_onto_element(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + draggable = driver.find_element(By.ID, "draggable") + droppable = driver.find_element(By.ID, "droppable") + ActionChains(driver)\ + .drag_and_drop(draggable, droppable)\ + .perform() + + assert driver.find_element(By.ID, "drop-status").text == "dropped" + + +def test_drag_and_drop_by_offset(driver): + driver.get('https://selenium.dev/selenium/web/mouse_interaction.html') + + draggable = driver.find_element(By.ID, "draggable") + start = draggable.location + finish = driver.find_element(By.ID, "droppable").location + ActionChains(driver)\ + .drag_and_drop_by_offset(draggable, finish['x'] - start['x'], finish['y'] - start['y'])\ + .perform() + + assert driver.find_element(By.ID, "drop-status").text == "dropped" + + + + + + + diff --git a/examples/python/tests/actions_api/test_pen.py b/examples/python/tests/actions_api/test_pen.py new file mode 100644 index 000000000000..0b80c0b16d97 --- /dev/null +++ b/examples/python/tests/actions_api/test_pen.py @@ -0,0 +1,98 @@ +import math + +from selenium.webdriver.common.actions.action_builder import ActionBuilder +from selenium.webdriver.common.actions.interaction import POINTER_PEN +from selenium.webdriver.common.actions.pointer_input import PointerInput +from selenium.webdriver.common.by import By + + +def test_use_pen(driver): + driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html') + + pointer_area = driver.find_element(By.ID, "pointerArea") + pen_input = PointerInput(POINTER_PEN, "default pen") + action = ActionBuilder(driver, mouse=pen_input) + action.pointer_action\ + .move_to(pointer_area)\ + .pointer_down()\ + .move_by(2, 2)\ + .pointer_up() + action.perform() + + moves = driver.find_elements(By.CLASS_NAME, "pointermove") + move_to = properties(moves[0]) + down = properties(driver.find_element(By.CLASS_NAME, "pointerdown")) + move_by = properties(moves[1]) + up = properties(driver.find_element(By.CLASS_NAME, "pointerup")) + + rect = pointer_area.rect + center_x = rect["x"] + rect["width"] / 2 + center_y = rect["y"] + rect["height"] / 2 + + assert move_to["button"] == "-1" + assert move_to["pointerType"] == "pen" + assert move_to["pageX"] == str(math.floor(center_x)) + assert move_to["pageY"] == str(math.floor(center_y)) + assert down["button"] == "0" + assert down["pointerType"] == "pen" + assert down["pageX"] == str(math.floor(center_x)) + assert down["pageY"] == str(math.floor(center_y)) + assert move_by["button"] == "-1" + assert move_by["pointerType"] == "pen" + assert move_by["pageX"] == str(math.floor(center_x + 2)) + assert move_by["pageY"] == str(math.floor(center_y + 2)) + assert up["button"] == "0" + assert up["pointerType"] == "pen" + assert up["pageX"] == str(math.floor(center_x + 2)) + assert up["pageY"] == str(math.floor(center_y + 2)) + + +def test_set_pointer_event_properties(driver): + driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html') + + pointer_area = driver.find_element(By.ID, "pointerArea") + pen_input = PointerInput(POINTER_PEN, "default pen") + action = ActionBuilder(driver, mouse=pen_input) + action.pointer_action\ + .move_to(pointer_area)\ + .pointer_down()\ + .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\ + .pointer_up(0) + action.perform() + + moves = driver.find_elements(By.CLASS_NAME, "pointermove") + move_to = properties(moves[0]) + down = properties(driver.find_element(By.CLASS_NAME, "pointerdown")) + move_by = properties(moves[1]) + up = properties(driver.find_element(By.CLASS_NAME, "pointerup")) + + rect = pointer_area.rect + center_x = rect["x"] + rect["width"] / 2 + center_y = rect["y"] + rect["height"] / 2 + + assert move_to["button"] == "-1" + assert move_to["pointerType"] == "pen" + assert move_to["pageX"] == str(math.floor(center_x)) + assert move_to["pageY"] == str(math.floor(center_y)) + assert down["button"] == "0" + assert down["pointerType"] == "pen" + assert down["pageX"] == str(math.floor(center_x)) + assert down["pageY"] == str(math.floor(center_y)) + assert move_by["button"] == "-1" + assert move_by["pointerType"] == "pen" + assert move_by["pageX"] == str(math.floor(center_x + 2)) + assert move_by["pageY"] == str(math.floor(center_y + 2)) + assert move_by["tiltX"] == "-72" + assert move_by["tiltY"] == "9" + assert move_by["twist"] == "86" + assert up["button"] == "0" + assert up["pointerType"] == "pen" + assert up["pageX"] == str(math.floor(center_x + 2)) + assert up["pageY"] == str(math.floor(center_y + 2)) + + +def properties(element): + kv = element.text.split(' ', 1)[1].split(', ') + return {x[0]:x[1] for x in list(map(lambda item: item.split(': '), kv))} + + diff --git a/examples/python/tests/actions_api/test_wheel.py b/examples/python/tests/actions_api/test_wheel.py new file mode 100644 index 000000000000..6080e16cae24 --- /dev/null +++ b/examples/python/tests/actions_api/test_wheel.py @@ -0,0 +1,85 @@ +from time import sleep + +from selenium.webdriver import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.common.actions.wheel_input import ScrollOrigin + + +def test_can_scroll_to_element(driver): + driver.get("https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html") + + iframe = driver.find_element(By.TAG_NAME, "iframe") + ActionChains(driver)\ + .scroll_to_element(iframe)\ + .perform() + + assert _in_viewport(driver, iframe) + + +def test_can_scroll_from_viewport_by_amount(driver): + driver.get("https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html") + + footer = driver.find_element(By.TAG_NAME, "footer") + delta_y = footer.rect['y'] + ActionChains(driver)\ + .scroll_by_amount(0, delta_y)\ + .perform() + + sleep(0.5) + assert _in_viewport(driver, footer) + + +def test_can_scroll_from_element_by_amount(driver): + driver.get("https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html") + + iframe = driver.find_element(By.TAG_NAME, "iframe") + scroll_origin = ScrollOrigin.from_element(iframe) + ActionChains(driver)\ + .scroll_from_origin(scroll_origin, 0, 200)\ + .perform() + + sleep(0.5) + driver.switch_to.frame(iframe) + checkbox = driver.find_element(By.NAME, "scroll_checkbox") + assert _in_viewport(driver, checkbox) + + +def test_can_scroll_from_element_with_offset_by_amount(driver): + driver.get("https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html") + + footer = driver.find_element(By.TAG_NAME, "footer") + scroll_origin = ScrollOrigin.from_element(footer, 0, -50) + ActionChains(driver)\ + .scroll_from_origin(scroll_origin, 0, 200)\ + .perform() + + sleep(0.5) + iframe = driver.find_element(By.TAG_NAME, "iframe") + driver.switch_to.frame(iframe) + checkbox = driver.find_element(By.NAME, "scroll_checkbox") + assert _in_viewport(driver, checkbox) + + +def test_can_scroll_from_viewport_with_offset_by_amount(driver): + driver.get("https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame.html") + + scroll_origin = ScrollOrigin.from_viewport(10, 10) + + ActionChains(driver)\ + .scroll_from_origin(scroll_origin, 0, 200)\ + .perform() + + iframe = driver.find_element(By.TAG_NAME, "iframe") + driver.switch_to.frame(iframe) + checkbox = driver.find_element(By.NAME, "scroll_checkbox") + assert _in_viewport(driver, checkbox) + + +def _in_viewport(driver, element): + script = ( + "for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n" + "e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n" + "return f\n" + "window.pageYOffset&&t+o>window.pageXOffset" + ) + return driver.execute_script(script, element) diff --git a/examples/python/tests/conftest.py b/examples/python/tests/conftest.py new file mode 100644 index 000000000000..0e4553f11a56 --- /dev/null +++ b/examples/python/tests/conftest.py @@ -0,0 +1,14 @@ +import pytest +from selenium import webdriver +from selenium.webdriver.chrome.service import Service as ChromeService +from webdriver_manager.chrome import ChromeDriverManager + + +@pytest.fixture(scope='function') +def driver(): + service = ChromeService(executable_path=ChromeDriverManager().install()) + driver = webdriver.Chrome(service=service) + + yield driver + + driver.quit() diff --git a/examples/ruby/Gemfile b/examples/ruby/Gemfile index 3d4a25c60f57..b7461e9d55e0 100644 --- a/examples/ruby/Gemfile +++ b/examples/ruby/Gemfile @@ -4,6 +4,5 @@ source 'https://rubygems.org' gem 'rake', '~> 13.0' gem 'rspec', '~> 3.0' -gem 'selenium-webdriver', '~> 4.1' +gem 'selenium-webdriver', '~> 4.2.1' gem 'webdrivers', '~> 5.0' -gem 'nokogiri', '~> 1.13' diff --git a/examples/ruby/Gemfile.lock b/examples/ruby/Gemfile.lock index 699aa6f5cbdb..aab5824ac349 100644 --- a/examples/ruby/Gemfile.lock +++ b/examples/ruby/Gemfile.lock @@ -19,29 +19,31 @@ GEM rspec-expectations (3.11.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.11.0) - rspec-mocks (3.11.0) + rspec-mocks (3.11.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.11.0) rspec-support (3.11.0) rubyzip (2.3.2) - selenium-webdriver (4.1.0) + selenium-webdriver (4.2.1) childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) - rubyzip (>= 1.2.2) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) webdrivers (5.0.0) nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) + websocket (1.2.9) PLATFORMS x86_64-darwin-19 + x86_64-darwin-20 x86_64-linux DEPENDENCIES - nokogiri (~> 1.13) rake (~> 13.0) rspec (~> 3.0) - selenium-webdriver (~> 4.1) + selenium-webdriver (~> 4.2.1) webdrivers (~> 5.0) BUNDLED WITH diff --git a/examples/ruby/spec/actions_api/actions_spec.rb b/examples/ruby/spec/actions_api/actions_spec.rb new file mode 100644 index 000000000000..2bac0815d3a5 --- /dev/null +++ b/examples/ruby/spec/actions_api/actions_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Actions' do + it 'pauses' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + start = Time.now + + clickable = @driver.find_element(id: 'clickable') + @driver.action + .move_to(clickable) + .pause(duration: 1) + .click_and_hold + .pause(duration: 1) + .send_keys("abc") + .perform + + duration = Time.now - start + expect(duration).to be > 2 + expect(duration).to be < 3 + end + + it 'releases all' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + clickable = @driver.find_element(id: 'clickable') + action = @driver.action + .click_and_hold(clickable) + .key_down(:shift) + .key_down(:alt) + .key_down("a") + action.perform + + @driver.action.release_actions + + action.key_down('a').perform + expect(clickable.attribute('value')[0]).to eq "Å" + expect(clickable.attribute('value')[-1]).to eq "a" + end +end diff --git a/examples/ruby/spec/actions_api/keys_spec.rb b/examples/ruby/spec/actions_api/keys_spec.rb new file mode 100644 index 000000000000..1a772d64e0d1 --- /dev/null +++ b/examples/ruby/spec/actions_api/keys_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Keys' do + it 'key down' do + @driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' + @wait.until { @driver.find_element(id: 'textInput').attribute('autofocus') } + + @driver.action + .key_down(:shift) + .send_keys('a') + .perform + + expect(@driver.find_element(id: 'textInput').attribute('value')).to eq "A" + end + + it 'key up' do + @driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' + @wait.until { @driver.find_element(id: 'textInput').attribute('autofocus') } + + @driver.action + .key_down(:shift) + .send_keys('a') + .key_up(:shift) + .send_keys('b') + .perform + + expect(@driver.find_element(id: 'textInput').attribute('value')).to eq "Ab" + end + + it 'sends keys to active element' do + @driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' + @wait.until { @driver.find_element(id: 'textInput').attribute('autofocus') } + + @driver.action + .send_keys('abc') + .perform + + expect(@driver.find_element(id: 'textInput').attribute('value')).to eq "abc" + end + + it 'sends keys to designated element' do + @driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' + @driver.find_element(tag_name: 'body').click + @wait.until { @driver.find_element(id: 'textInput').attribute('autofocus') } + + text_field = @driver.find_element(id: 'textInput') + @driver.action + .send_keys(text_field, 'Selenium!') + .perform + + expect(text_field.attribute('value')).to eq "Selenium!" + end + + it 'copy and paste' do + @driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' + @wait.until { @driver.find_element(id: 'textInput').attribute('autofocus') } + + @cmd_ctrl = @driver.capabilities.platform_name.include?('mac') ? :command : :control + @driver.action + .send_keys('Selenium!') + .send_keys(:arrow_left) + .key_down(:shift) + .send_keys(:arrow_up) + .key_up(:shift) + .key_down(@cmd_ctrl) + .send_keys('xvv') + .key_up(@cmd_ctrl) + .perform + + expect(@driver.find_element(id: 'textInput').attribute('value')).to eq "SeleniumSelenium!" + end +end diff --git a/examples/ruby/spec/actions_api/mouse_spec.rb b/examples/ruby/spec/actions_api/mouse_spec.rb new file mode 100644 index 000000000000..8ddfff708caa --- /dev/null +++ b/examples/ruby/spec/actions_api/mouse_spec.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Mouse' do + it 'click and hold' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + clickable = @driver.find_element(id: 'clickable') + @driver.action + .click_and_hold(clickable) + .perform + + expect(@driver.find_element(id: 'click-status').text).to eq 'focused' + end + + it 'click and release' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + clickable = @driver.find_element(id: 'click') + @driver.action + .click(clickable) + .perform + + expect(@driver.current_url).to include 'resultPage.html' + end + + it 'right click' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + clickable = @driver.find_element(id: 'clickable') + @driver.action + .context_click(clickable) + .perform + + expect(@driver.find_element(id: 'click-status').text).to eq 'context-clicked' + end + + it 'back click' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + @driver.find_element(id: 'click').click + expect(@driver.title).to eq("We Arrive Here") + + @driver.action + .pointer_down(:back) + .pointer_up(:back) + .perform + + expect(@driver.title).to eq("BasicMouseInterfaceTest") + end + + it 'forward click' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + @driver.find_element(id: 'click').click + @driver.navigate.back + expect(@driver.title).to eq("BasicMouseInterfaceTest") + + @driver.action + .pointer_down(:forward) + .pointer_up(:forward) + .perform + + expect(@driver.title).to eq("We Arrive Here") + end + + it 'double click' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + clickable = @driver.find_element(id: 'clickable') + @driver.action + .double_click(clickable) + .perform + + expect(@driver.find_element(id: 'click-status').text).to eq 'double-clicked' + end + + it 'hovers' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + hoverable = @driver.find_element(id: 'hover') + @driver.action + .move_to(hoverable) + .perform + + expect(@driver.find_element(id: 'move-status').text).to eq 'hovered' + end + + it 'moves mouse by offset' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + mouse_tracker = @driver.find_element(id: 'mouse-tracker') + @driver.action + .move_to(mouse_tracker, 8, 11) + .perform + + sleep 0.5 + x_coord, y_coord = @driver.find_element(id: 'relative-location').text.split(',').map(&:to_i) + expect(x_coord).to be_within(1).of(8) + expect(y_coord).to be_within(1).of(11) + end + + it 'moves mouse by offset from viewport origin' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + @driver.action + .move_to_location(8, 12) + .perform + + x_coord, y_coord = @driver.find_element(id: 'absolute-location').text.split(',').map(&:to_i) + expect(x_coord).to be_within(1).of(8) + expect(y_coord).to be_within(1).of(12) + end + + it 'moves mouse by offset from current pointer location' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + @driver.action.move_to_location(8, 11).perform + + @driver.action + .move_by(13, 15) + .perform + + x_coord, y_coord = @driver.find_element(id: 'absolute-location').text.split(',').map(&:to_i) + expect(x_coord).to be_within(1).of(8 + 13) + expect(y_coord).to be_within(1).of(11 + 15) + end + + it 'drags to another element' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + draggable = @driver.find_element(id: 'draggable') + droppable = @driver.find_element(id: 'droppable') + @driver.action + .drag_and_drop(draggable, droppable) + .perform + + expect(@driver.find_element(id: 'drop-status').text).to include("dropped") + end + + it 'drags by an offset' do + @driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html' + + draggable = @driver.find_element(id: 'draggable') + start = draggable.rect + finish = @driver.find_element(id: 'droppable').rect + @driver.action + .drag_and_drop_by(draggable, finish.x - start.x, finish.y - start.y) + .perform + + expect(@driver.find_element(id: 'drop-status').text).to include("dropped") + end +end diff --git a/examples/ruby/spec/actions_api/pen_spec.rb b/examples/ruby/spec/actions_api/pen_spec.rb new file mode 100644 index 000000000000..312bce69319d --- /dev/null +++ b/examples/ruby/spec/actions_api/pen_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Pen' do + it 'uses a pen' do + @driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html' + + pointer_area = @driver.find_element(id: 'pointerArea') + @driver.action(devices: :pen) + .move_to(pointer_area) + .pointer_down + .move_by(2, 2) + .pointer_up + .perform + + moves = @driver.find_elements(class: 'pointermove') + move_to = properties(moves[0]) + down = properties(@driver.find_element(class: 'pointerdown')) + move_by = properties(moves[1]) + up = properties(@driver.find_element(class: 'pointerup')) + + rect = pointer_area.rect + center_x = rect.x + rect.width / 2 + center_y = rect.y + rect.height / 2 + + expect(move_to).to include("button" => "-1", + "pointerType" => "pen", + "pageX" => (center_x).to_s, + "pageY" => (center_y).floor.to_s) + expect(down).to include("button" => "0", + "pointerType" => "pen", + "pageX" => (center_x).to_s, + "pageY" => (center_y).floor.to_s) + expect(move_by).to include("button" => "-1", + "pointerType" => "pen", + "pageX" => (center_x + 2).to_s, + "pageY" => (center_y + 2).floor.to_s) + expect(up).to include("button" => "0", + "pointerType" => "pen", + "pageX" => (center_x + 2).to_s, + "pageY" => (center_y + 2).floor.to_s) + end + + it 'sets pointer event attributes' do + @driver.get 'https://www.selenium.dev/selenium/web/pointerActionsPage.html' + + pointer_area = @driver.find_element(id: 'pointerArea') + @driver.action(devices: :pen) + .move_to(pointer_area) + .pointer_down + .move_by(2, 2, tilt_x: -72, tilt_y: 9, twist: 86) + .pointer_up + .perform + + moves = @driver.find_elements(class: 'pointermove') + move_to = properties(moves[0]) + down = properties(@driver.find_element(class: 'pointerdown')) + move_by = properties(moves[1]) + up = properties(@driver.find_element(class: 'pointerup')) + + rect = pointer_area.rect + center_x = rect.x + rect.width / 2 + center_y = rect.y + rect.height / 2 + + expect(move_to).to include("button" => "-1", + "pointerType" => "pen", + "pageX" => (center_x).to_s, + "pageY" => (center_y).floor.to_s) + expect(down).to include("button" => "0", + "pointerType" => "pen", + "pageX" => (center_x).to_s, + "pageY" => (center_y).floor.to_s) + expect(move_by).to include("button" => "-1", + "pointerType" => "pen", + "pageX" => (center_x + 2).to_s, + "pageY" => (center_y + 2).floor.to_s, + "tiltX" => (-72).floor.to_s, + "tiltY" => (9).floor.to_s, + "twist" => (86).floor.to_s) + expect(up).to include("button" => "0", + "pointerType" => "pen", + "pageX" => (center_x + 2).to_s, + "pageY" => (center_y + 2).floor.to_s) + end + + def properties(element) + element.text.sub(/.*?\s/, '').split(',').map { |item| item.lstrip.split /\s*:\s*/ }.to_h + end +end diff --git a/examples/ruby/spec/actions_api/wheel_spec.rb b/examples/ruby/spec/actions_api/wheel_spec.rb new file mode 100644 index 000000000000..87a03aaa5c90 --- /dev/null +++ b/examples/ruby/spec/actions_api/wheel_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Scrolling' do + it 'scrolls to element' do + @driver.get('https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html') + + iframe = @driver.find_element(tag_name: 'iframe') + @driver.action + .scroll_to(iframe) + .perform + + expect(in_viewport?(iframe)).to eq true + end + + it 'scrolls by given amount' do + @driver.get('https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html') + + footer = @driver.find_element(tag_name: 'footer') + delta_y = footer.rect.y + @driver.action + .scroll_by(0, delta_y) + .perform + + expect(in_viewport?(footer)).to eq true + end + + it 'scrolls from element by given amount' do + @driver.get('https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html') + + iframe = @driver.find_element(tag_name: 'iframe') + scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(iframe) + @driver.action + .scroll_from(scroll_origin, 0, 200) + .perform + + @driver.switch_to.frame(iframe) + checkbox = @driver.find_element(name: 'scroll_checkbox') + expect(in_viewport?(checkbox)).to eq true + end + + it 'scrolls from element by given amount with offset' do + @driver.get('https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html') + + footer = @driver.find_element(tag_name: 'footer') + scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(footer, 0, -50) + @driver.action + .scroll_from(scroll_origin, 0, 200) + .perform + + iframe = @driver.find_element(tag_name: 'iframe') + @driver.switch_to.frame(iframe) + checkbox = @driver.find_element(name: 'scroll_checkbox') + expect(in_viewport?(checkbox)).to eq true + end + + it 'scrolls by given amount with offset' do + @driver.get('https://selenium.dev/selenium/web/scrolling_tests/frame_with_nested_scrolling_frame.html') + + scroll_origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(10, 10) + @driver.action + .scroll_from(scroll_origin, 0, 200) + .perform + + iframe = @driver.find_element(tag_name: 'iframe') + @driver.switch_to.frame(iframe) + checkbox = @driver.find_element(name: 'scroll_checkbox') + expect(in_viewport?(checkbox)).to eq true + end +end + +def in_viewport?(element) + in_viewport = <<~IN_VIEWPORT + for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight; + e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft; + return f + window.pageYOffset&&t+o>window.pageXOffset + IN_VIEWPORT + + @driver.execute_script(in_viewport, element) +end diff --git a/examples/ruby/spec/getting_started/open_browser_spec.rb b/examples/ruby/spec/getting_started/open_browser_spec.rb index 37850f27e128..8075b3bf0d11 100644 --- a/examples/ruby/spec/getting_started/open_browser_spec.rb +++ b/examples/ruby/spec/getting_started/open_browser_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'spec_helper' +require 'selenium-webdriver' RSpec.describe 'Open Browser' do it 'chrome session' do diff --git a/examples/ruby/spec/spec_helper.rb b/examples/ruby/spec/spec_helper.rb index 1444d9a1af38..21f1fffcc185 100644 --- a/examples/ruby/spec/spec_helper.rb +++ b/examples/ruby/spec/spec_helper.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "selenium-webdriver" +require "webdrivers" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure @@ -12,4 +13,10 @@ config.expect_with :rspec do |c| c.syntax = :expect end + + config.before do + @driver = Selenium::WebDriver.for :chrome + @wait = Selenium::WebDriver::Wait.new(timeout: 2) + end + config.after { @driver.quit } end diff --git a/website_and_docs/assets/scss/_badges.scss b/website_and_docs/assets/scss/_badges.scss new file mode 100644 index 000000000000..d9bd095b12c8 --- /dev/null +++ b/website_and_docs/assets/scss/_badges.scss @@ -0,0 +1,16 @@ + +.selenium-badge-version { + background:green; + color:white; + padding:.2rem; + font-weight:750; +} + +.selenium-badge-browser { + background:blue; + color:white; + padding:.2rem; + font-weight:750; +} + + diff --git a/website_and_docs/assets/scss/_tabs.scss b/website_and_docs/assets/scss/_tabs.scss new file mode 100644 index 000000000000..fa74badcede5 --- /dev/null +++ b/website_and_docs/assets/scss/_tabs.scss @@ -0,0 +1,67 @@ +.height-auto { + height: auto; +} + +.height-1 { + height: 100px; +} + +.height-2 { + height: 125px; +} + +.height-3 { + height: 150px; +} + +.height-4 { + height: 175px; +} + +.height-5 { + height: 200px; +} + +.height-6 { + height: 225px; +} + +.height-7 { + height: 250px; +} + +.height-8 { + height: 275px; +} + +.height-9 { + height: 300px; +} + +.height-10 { + height: 325px; +} + +.height-11 { + height: 350px; +} + +.height-12 { + height: 375px; +} + +.height-13 { + height: 400px; +} + +.height-14 { + height: 425px; +} + +.height-15 { + height: 450px; +} + +.my-3 .highlight { + margin: 0; +} diff --git a/website_and_docs/assets/scss/main.scss b/website_and_docs/assets/scss/main.scss index 730283578e87..4603824a2168 100644 --- a/website_and_docs/assets/scss/main.scss +++ b/website_and_docs/assets/scss/main.scss @@ -2,9 +2,11 @@ @import "../../themes/docsy/assets/scss/main.scss"; @import "alerts"; @import "backgrounds"; +@import "badges"; @import "buttons"; @import "colors"; @import "images"; @import "links"; @import "logo"; @import "screen"; +@import "tabs"; diff --git a/website_and_docs/content/documentation/about/style.en.md b/website_and_docs/content/documentation/about/style.en.md index 1826938db8d1..7cd4fdf2483a 100644 --- a/website_and_docs/content/documentation/about/style.en.md +++ b/website_and_docs/content/documentation/about/style.en.md @@ -210,7 +210,8 @@ Maybe you want something like this: For this you need to use `disableCodeBlock=true` instead of `langEqualsHeader=true` -You need to specify which parts are code and which are not yourself now, like this: +You need to be explicit about which parts are code and which are not, +do not indent plain text or it will still be treated like a codeblock: {{}} {{}} @@ -246,6 +247,17 @@ Which looks like this: {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/getting_started/FirstScriptTest.java#L15-L37" >}} +### Consistent Heights + +Typically, a user will pick their language and not switch tabs again. If they do, however, +the entire page will shift because the height of the block is based on the amount of code in the tab. +This can get especially jarring at the bottom of a page with a lot of tabs. + +You can add a "height" value to the `tabpane` that corresponds to the lines of code or some +equivalent for text: + + {{}} + ### Code Comments Minimize code comments because they are difficult to translate. diff --git a/website_and_docs/content/documentation/webdriver/actions_api/_index.en.md b/website_and_docs/content/documentation/webdriver/actions_api/_index.en.md index b8a8d78dc1c9..01953a497939 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/_index.en.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/_index.en.md @@ -3,12 +3,84 @@ title: "Actions API" linkTitle: "Actions API" weight: 14 description: > - A low-level interface for providing virtualised device input to the web browser. + A low-level interface for providing virtualized device input actions to the web browser. --- -Unlike the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), -which conducts additional validations, -the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over input devices. +In addition to the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), +the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over +exactly what designated input devices can do. Selenium provides an interface for 3 kinds of input sources: +a key input for keyboard devices, a pointer input for a mouse, pen or touch devices, +and wheel inputs for scroll wheel devices (introduced in Selenium 4.2). +Selenium allows you to construct individual action commands assigned to specific +inputs and chain them together and call the associated perform method to execute them all at once. -Selenium provides access to 3 input sources: key inputs for keyboard devices, pointer inputs for a mouse, pen or -touch device, and a wheel inputs for scroll wheel support. +## Action Builder + +In the move from the legacy JSON Wire Protocol to the new W3C WebDriver Protocol, +the low level building blocks of actions became especially detailed. It is extremely +powerful, but each input device has a number of ways to use it and if you need to +manage more than one device, you are responsible for ensuring proper synchronization between them. + +Thankfully, you likely do not need to learn how to use the low level commands directly, since +almost everything you might want to do has been given a convenience method that combines the +lower level commands for you. These are all documented in +[keyboard]({{< ref "keyboard" >}}), [mouse]({{< ref "mouse" >}}), [pen]({{< ref "pen" >}}), and [wheel]({{< ref "wheel" >}}) pages. + +## Pause + +Pointer movements and Wheel scrolling allow the user to set a duration for the action, but sometimes you just need +to wait a beat between actions for things to work correctly. + +{{< tabpane disableCodeBlock=true height="9">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L21-L28" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L13-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L18-L25" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L10-L17" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Release All Actions + +An important thing to note is that the driver remembers the state of all the input +items throughout a session. Even if you create a new instance of an actions class, the depressed keys and +the location of the pointer will be in whatever state a previously performed action left them. + +There is a special method to release all currently depressed keys and pointer buttons. +This method is implemented differently in each of the languages because +it does not get executed with the perform method. + +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L47" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L45" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L35" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/_index.ja.md b/website_and_docs/content/documentation/webdriver/actions_api/_index.ja.md index 573ade4fa5d5..01953a497939 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/_index.ja.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/_index.ja.md @@ -1,15 +1,86 @@ --- title: "Actions API" linkTitle: "Actions API" -needsTranslation: true weight: 14 description: > - A low-level interface for providing virtualised device input to the web browser. + A low-level interface for providing virtualized device input actions to the web browser. --- -Unlike the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), -which conducts additional validations, -the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over input devices. +In addition to the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), +the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over +exactly what designated input devices can do. Selenium provides an interface for 3 kinds of input sources: +a key input for keyboard devices, a pointer input for a mouse, pen or touch devices, +and wheel inputs for scroll wheel devices (introduced in Selenium 4.2). +Selenium allows you to construct individual action commands assigned to specific +inputs and chain them together and call the associated perform method to execute them all at once. -Selenium provides access to 3 input sources: key inputs for keyboard devices, pointer inputs for a mouse, pen or -touch device, and a wheel inputs for scroll wheel support. +## Action Builder + +In the move from the legacy JSON Wire Protocol to the new W3C WebDriver Protocol, +the low level building blocks of actions became especially detailed. It is extremely +powerful, but each input device has a number of ways to use it and if you need to +manage more than one device, you are responsible for ensuring proper synchronization between them. + +Thankfully, you likely do not need to learn how to use the low level commands directly, since +almost everything you might want to do has been given a convenience method that combines the +lower level commands for you. These are all documented in +[keyboard]({{< ref "keyboard" >}}), [mouse]({{< ref "mouse" >}}), [pen]({{< ref "pen" >}}), and [wheel]({{< ref "wheel" >}}) pages. + +## Pause + +Pointer movements and Wheel scrolling allow the user to set a duration for the action, but sometimes you just need +to wait a beat between actions for things to work correctly. + +{{< tabpane disableCodeBlock=true height="9">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L21-L28" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L13-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L18-L25" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L10-L17" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Release All Actions + +An important thing to note is that the driver remembers the state of all the input +items throughout a session. Even if you create a new instance of an actions class, the depressed keys and +the location of the pointer will be in whatever state a previously performed action left them. + +There is a special method to release all currently depressed keys and pointer buttons. +This method is implemented differently in each of the languages because +it does not get executed with the perform method. + +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L47" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L45" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L35" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/actions_api/_index.pt-br.md index 573ade4fa5d5..01953a497939 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/_index.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/_index.pt-br.md @@ -1,15 +1,86 @@ --- title: "Actions API" linkTitle: "Actions API" -needsTranslation: true weight: 14 description: > - A low-level interface for providing virtualised device input to the web browser. + A low-level interface for providing virtualized device input actions to the web browser. --- -Unlike the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), -which conducts additional validations, -the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over input devices. +In addition to the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), +the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over +exactly what designated input devices can do. Selenium provides an interface for 3 kinds of input sources: +a key input for keyboard devices, a pointer input for a mouse, pen or touch devices, +and wheel inputs for scroll wheel devices (introduced in Selenium 4.2). +Selenium allows you to construct individual action commands assigned to specific +inputs and chain them together and call the associated perform method to execute them all at once. -Selenium provides access to 3 input sources: key inputs for keyboard devices, pointer inputs for a mouse, pen or -touch device, and a wheel inputs for scroll wheel support. +## Action Builder + +In the move from the legacy JSON Wire Protocol to the new W3C WebDriver Protocol, +the low level building blocks of actions became especially detailed. It is extremely +powerful, but each input device has a number of ways to use it and if you need to +manage more than one device, you are responsible for ensuring proper synchronization between them. + +Thankfully, you likely do not need to learn how to use the low level commands directly, since +almost everything you might want to do has been given a convenience method that combines the +lower level commands for you. These are all documented in +[keyboard]({{< ref "keyboard" >}}), [mouse]({{< ref "mouse" >}}), [pen]({{< ref "pen" >}}), and [wheel]({{< ref "wheel" >}}) pages. + +## Pause + +Pointer movements and Wheel scrolling allow the user to set a duration for the action, but sometimes you just need +to wait a beat between actions for things to work correctly. + +{{< tabpane disableCodeBlock=true height="9">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L21-L28" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L13-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L18-L25" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L10-L17" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Release All Actions + +An important thing to note is that the driver remembers the state of all the input +items throughout a session. Even if you create a new instance of an actions class, the depressed keys and +the location of the pointer will be in whatever state a previously performed action left them. + +There is a special method to release all currently depressed keys and pointer buttons. +This method is implemented differently in each of the languages because +it does not get executed with the perform method. + +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L47" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L45" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L35" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/actions_api/_index.zh-cn.md index c3465092b373..01953a497939 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/_index.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/_index.zh-cn.md @@ -1,17 +1,86 @@ --- -title: "Actions接口" -linkTitle: "Actions接口" +title: "Actions API" +linkTitle: "Actions API" weight: 14 description: > - 用于向web浏览器提供虚拟设备输入的底层接口. + A low-level interface for providing virtualized device input actions to the web browser. --- -与执行额外验证的高级 -[元素交互]({{< ref "/documentation/webdriver/elements/interactions.md" >}}) 不同, -[Actions接口](https://w3c.github.io/webdriver/#dfn-actions) -提供了对输入设备的细粒度控制. +In addition to the high-level [element interactions]({{< ref "/documentation/webdriver/elements/interactions.md" >}}), +the [Actions API](https://w3c.github.io/webdriver/#dfn-actions) provides granular control over +exactly what designated input devices can do. Selenium provides an interface for 3 kinds of input sources: +a key input for keyboard devices, a pointer input for a mouse, pen or touch devices, +and wheel inputs for scroll wheel devices (introduced in Selenium 4.2). +Selenium allows you to construct individual action commands assigned to specific +inputs and chain them together and call the associated perform method to execute them all at once. -Selenium提供3种输入源: -键盘设备的键位输入, -鼠标、笔或触摸设备的指针输入, -以及支持滚轮的滚轮输入. +## Action Builder + +In the move from the legacy JSON Wire Protocol to the new W3C WebDriver Protocol, +the low level building blocks of actions became especially detailed. It is extremely +powerful, but each input device has a number of ways to use it and if you need to +manage more than one device, you are responsible for ensuring proper synchronization between them. + +Thankfully, you likely do not need to learn how to use the low level commands directly, since +almost everything you might want to do has been given a convenience method that combines the +lower level commands for you. These are all documented in +[keyboard]({{< ref "keyboard" >}}), [mouse]({{< ref "mouse" >}}), [pen]({{< ref "pen" >}}), and [wheel]({{< ref "wheel" >}}) pages. + +## Pause + +Pointer movements and Wheel scrolling allow the user to set a duration for the action, but sometimes you just need +to wait a beat between actions for things to work correctly. + +{{< tabpane disableCodeBlock=true height="9">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L21-L28" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L13-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L18-L25" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L10-L17" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Release All Actions + +An important thing to note is that the driver remembers the state of all the input +items throughout a session. Even if you create a new instance of an actions class, the depressed keys and +the location of the pointer will be in whatever state a previously performed action left them. + +There is a special method to release all currently depressed keys and pointer buttons. +This method is implemented differently in each of the languages because +it does not get executed with the perform method. + +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/ActionsTest.java#L47" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_actions.py#L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/ActionsTest.cs#L45" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/actions_spec.rb#L35" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.en.md b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.en.md index 103056074c47..ecb25bad2bb7 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.en.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.en.md @@ -10,8 +10,10 @@ aliases: [ ] --- -Keyboard represents a KeyBoard event. KeyBoard actions are performed by using low-level -interface which allows us to provide virtualized device input to the web browser. +There are only 2 actions that can be accomplished with a keyboard: +pressing down on a key, and releasing a pressed key. +In addition to supporting ASCII characters, each keyboard key has +a representation that can be pressed or released in designated sequences. ## Keys @@ -20,343 +22,149 @@ unicode values have been assigned to other keyboard keys for use with Selenium. Each language has its own way to reference these keys; the full list can be found [here](https://www.w3.org/TR/webdriver/#keyboard-actions). -## Key down - -The keyDown is used to simulate action of depressing a key - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -WebDriver driver = new ChromeDriver(); -try { - // Navigate to Url - driver.get("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER); - - Actions actionProvider = new Actions(driver); - Action keydown = actionProvider.keyDown(Keys.CONTROL).sendKeys("a").build(); - keydown.perform(); -} finally { - driver.quit(); -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Enter "webdriver" text and perform "ENTER" keyboard action -driver.find_element(By.NAME, "q").send_keys("webdriver" + Keys.ENTER) - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page -webdriver.ActionChains(driver).key_down(Keys.CONTROL).send_keys("a").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -IWebDriver driver = new ChromeDriver(); -try -{ - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.FindElement(By.Name("q")).SendKeys("webdriver" + Keys.Enter); - - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - Actions actionProvider = new Actions(driver); - IAction keydown = actionProvider.KeyDown(Keys.Control).SendKeys("a").Build(); - keydown.Perform(); -} -finally -{ - driver.Quit(); -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Enter "webdriver" text and perform "ENTER" keyboard action - driver.find_element(name: 'q').send_keys 'webdriver', :return - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - driver.action.key_down(:control).send_keys('a').perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyDown.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} + {{< tab header="Python" >}} +Use the [Python Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/py/selenium/webdriver/common/keys.py#L23) + {{< /tab >}} + {{< tab header="CSharp" >}} +Use the [.NET static Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/dotnet/src/webdriver/Keys.cs#L28) + {{< /tab >}} + {{< tab header="Ruby" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/rb/lib/selenium/webdriver/common/keys.rb#L28) + {{< /tab >}} + {{< tab header="JavaScript" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/javascript/node/selenium-webdriver/lib/input.js#L44) + {{< /tab >}} + {{< tab header="Kotlin" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} +{{< /tabpane >}} - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER) - val action = Actions(driver) +## Key down - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - action.keyDown(Keys.CONTROL).sendKeys("a").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L18-L21" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L10-L13" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L16-L19" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L10-L13" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Key up -The keyUp is used to simulate key-up (or) key-release action - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.interactions.Actions; - -public class HelloSelenium { - public static void main(String[] args) { - WebDriver driver = new FirefoxDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - Actions action = new Actions(driver); - - // Store google search box WebElement - WebElement search = driver.findElement(By.name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search,"qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store google search box WebElement -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) -action.key_down(Keys.SHIFT).send_keys_to_element(search, "qwerty").key_up(Keys.SHIFT).send_keys("qwerty").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace HelloSelenium -{ - class HelloSelenium - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - Actions action = new Actions(driver); - // Store google search box WebElement - IWebElement search = driver.FindElement(By.Name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.KeyDown(Keys.Shift).SendKeys(search, "qwerty").KeyUp(Keys.Shift).SendKeys("qwerty").Perform(); - - } - finally { - driver.Quit(); - } - } - } -} - - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Store google search box WebElement - search = driver.find_element(name: 'q') - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - driver.action.key_down(:shift).send_keys(search,'qwerty').key_up(:shift).send_keys("qwerty").perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyUp.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - - // Store google search box WebElement - val search = driver.findElement(By.name("q")) - val action = Actions(driver) - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search, "qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L31-L36" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L21-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L30-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L22-L27" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Send keys This is a convenience method in the Actions API that combines keyDown and keyUp commands in one action. -Executing this command differs slightly from using the element method. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -WebDriver driver = new FirefoxDriver(); -try { - -// Navigate to the url -driver.get("https://google.com"); - -// Create an object of Action class -Actions action = new Actions(driver); - -// Find google search box element -WebElement search = driver.findElement(By.name("q")); - -// Send value by action class to the search box -action.sendKeys(search, "Selenium").perform(); - -// Perform Keyboard action by Action class -action.sendKeys(Keys.ENTER).perform(); - -} finally { -driver.quit(); -} - -{{< /tab >}} -{{< tab header="Python" >}} - -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.chrome.service import Service -from webdriver_manager.chrome import ChromeDriverManager - -driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) -driver.get("https://www.selenium.dev/selenium/docs/api/py/genindex.html") - -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) -action.move_to_element(search).click().send_keys("send_keys", Keys.ENTER).perform() - -{{< /tab >}} -{{< tab header="CSharp" >}} - -IWebDriver driver = new ChromeDriver(); -// Navigate to the url -driver.Url = "https://www.google.com"; -// Create an object of Action class -Actions action = new Actions(driver); -// Find google search box element -IWebElement search = driver.FindElement(By.Name("q")); -// Send value by action class to the search box -action.SendKeys(search, "Selenium").Perform(); -// Perform Keyboard action by Action class -action.SendKeys(Keys.Enter).Perform(); - - -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to URL - driver.get 'https://google.com' - # Store google search box WebElement - search = driver.find_element(name: 'q') - # Get focus on Search - driver.execute_script('arguments[0].focus()', search) - # Send value by action class to the search box - driver.action.send_keys('Selenium').perform - # Perform Keyboard action by Action class - driver.action.send_keys(:enter).perform -ensure - driver.quit -end -{{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/sendKeysAction.js">}} - {{< /tab >}} -{{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://www.selenium.dev/selenium/docs/api/java/overview-summary.html") +Executing this command differs slightly from using the element method, but +primarily this gets used when needing to type multiple characters in the middle of other actions. + +### Active Element + +{{< tabpane disableCodeBlock=true height="3">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L46-L48" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L34-L36" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L46-L48" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L36-L38" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Store search box WebElement - val search = driver.findElement(By.id("search")) - val action = Actions(driver) - // Send value by action class to the search box - action.sendKeys(search, "devtools").perform(); +### Designated Element + +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L59-L62" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L45-L48" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L60-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L48-L51" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Perform Keyboard action by Action class - action.sendKeys(search, Keys.ENTER).perform(); - } finally { - driver.quit() - } -} -{{< /tab >}} +## Copy and Paste + +Here's an example of using all of the above methods to conduct a copy / paste action. +Note that the key to use for this operation will be different depending on if it is a Mac OS or not. +This code will end up with the text: `SeleniumSelenium!` + +{{< tabpane disableCodeBlock=true height="13">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L73-L85" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L55-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L76-L87" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L60-L70" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.ja.md b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.ja.md index 84e43d571899..ecb25bad2bb7 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.ja.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.ja.md @@ -1,364 +1,170 @@ --- -title: "キーボード" -linkTitle: "キーボード" +title: "Keyboard actions" +linkTitle: "Keyboard" weight: 2 -needsTranslation: true description: > A representation of any key input device for interacting with a web page. aliases: [ -"/documentation/ja/webdriver/keyboard/", -"/ja/documentation/webdriver/keyboard/" +"/documentation/en/webdriver/keyboard/", +"/documentation/webdriver/keyboard/" ] --- -キーボードはキーボードイベントを表します。 -キーボードアクションは、仮想化されたデバイス入力をWebブラウザーに提供できる低レベルインターフェイスを使用して実行されます。 +There are only 2 actions that can be accomplished with a keyboard: +pressing down on a key, and releasing a pressed key. +In addition to supporting ASCII characters, each keyboard key has +a representation that can be pressed or released in designated sequences. ## Keys -In addition to the keys represented by regular unicode, -unicode values have been assigned to other keyboard keys for use with Selenium. +In addition to the keys represented by regular unicode, +unicode values have been assigned to other keyboard keys for use with Selenium. Each language has its own way to reference these keys; the full list can be found [here](https://www.w3.org/TR/webdriver/#keyboard-actions). -## Key down - -keyDownは、修飾キー(CONTROL、SHIFT、ALT)を押す動作をシミュレートするために使用します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -WebDriver driver = new ChromeDriver(); -try { - // Navigate to Url - driver.get("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER); - - Actions actionProvider = new Actions(driver); - Action keydown = actionProvider.keyDown(Keys.CONTROL).sendKeys("a").build(); - keydown.perform(); -} finally { - driver.quit(); -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Enter "webdriver" text and perform "ENTER" keyboard action -driver.find_element(By.NAME, "q").send_keys("webdriver" + Keys.ENTER) - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page -webdriver.ActionChains(driver).key_down(Keys.CONTROL).send_keys("a").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -IWebDriver driver = new ChromeDriver(); -try -{ - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.FindElement(By.Name("q")).SendKeys("webdriver" + Keys.Enter); - - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - Actions actionProvider = new Actions(driver); - IAction keydown = actionProvider.KeyDown(Keys.Control).SendKeys("a").Build(); - keydown.Perform(); -} -finally -{ - driver.Quit(); -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Enter "webdriver" text and perform "ENTER" keyboard action - driver.find_element(name: 'q').send_keys 'webdriver', :return - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - driver.action.key_down(:control).send_keys('a').perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyDown.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} + {{< tab header="Python" >}} +Use the [Python Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/py/selenium/webdriver/common/keys.py#L23) + {{< /tab >}} + {{< tab header="CSharp" >}} +Use the [.NET static Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/dotnet/src/webdriver/Keys.cs#L28) + {{< /tab >}} + {{< tab header="Ruby" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/rb/lib/selenium/webdriver/common/keys.rb#L28) + {{< /tab >}} + {{< tab header="JavaScript" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/javascript/node/selenium-webdriver/lib/input.js#L44) + {{< /tab >}} + {{< tab header="Kotlin" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} +{{< /tabpane >}} - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER) - val action = Actions(driver) +## Key down - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - action.keyDown(Keys.CONTROL).sendKeys("a").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L18-L21" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L10-L13" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L16-L19" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L10-L13" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Key up -keyUpは、修飾キー(CONTROL、SHIFT、ALT)のキーアップ(または)キーリリース操作をシミュレートするために使用します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.interactions.Actions; - -public class HelloSelenium { - public static void main(String[] args) { - WebDriver driver = new FirefoxDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - Actions action = new Actions(driver); - - // Store google search box WebElement - WebElement search = driver.findElement(By.name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search,"qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store google search box WebElement -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) -action.key_down(Keys.SHIFT).send_keys_to_element(search, "qwerty").key_up(Keys.SHIFT).send_keys("qwerty").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace HelloSelenium -{ - class HelloSelenium - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - Actions action = new Actions(driver); - // Store google search box WebElement - IWebElement search = driver.FindElement(By.Name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.KeyDown(Keys.Shift).SendKeys(search, "qwerty").KeyUp(Keys.Shift).SendKeys("qwerty").Perform(); - - } - finally { - driver.Quit(); - } - } - } -} - - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Store google search box WebElement - search = driver.find_element(name: 'q') - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - driver.action.key_down(:shift).send_keys(search,'qwerty').key_up(:shift).send_keys("qwerty").perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyUp.js">}} +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L31-L36" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L21-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L30-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L22-L27" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - - // Store google search box WebElement - val search = driver.findElement(By.name("q")) - val action = Actions(driver) - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search, "qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} {{< /tabpane >}} ## Send keys This is a convenience method in the Actions API that combines keyDown and keyUp commands in one action. -Executing this command differs slightly from using the element method. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -WebDriver driver = new FirefoxDriver(); -try { - -// Navigate to the url -driver.get("https://google.com"); - -// Create an object of Action class -Actions action = new Actions(driver); - -// Find google search box element -WebElement search = driver.findElement(By.name("q")); - -// Send value by action class to the search box -action.sendKeys(search, "Selenium").perform(); - -// Perform Keyboard action by Action class -action.sendKeys(Keys.ENTER).perform(); - -} finally { -driver.quit(); -} - -{{< /tab >}} -{{< tab header="Python" >}} - -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.chrome.service import Service -from webdriver_manager.chrome import ChromeDriverManager - -driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) -driver.get("https://www.selenium.dev/selenium/docs/api/py/genindex.html") - -search = driver.find_element(By.NAME, "q") +Executing this command differs slightly from using the element method, but +primarily this gets used when needing to type multiple characters in the middle of other actions. -action = webdriver.ActionChains(driver) -action.move_to_element(search).click().send_keys("send_keys", Keys.ENTER).perform() +### Active Element -{{< /tab >}} -{{< tab header="CSharp" >}} - - -IWebDriver driver = new ChromeDriver(); -// Navigate to the url -driver.Url = "https://www.google.com"; -// Create an object of Action class -Actions action = new Actions(driver); -// Find google search box element -IWebElement search = driver.FindElement(By.Name("q")); -// Send value by action class to the search box -action.SendKeys(search, "Selenium").Perform(); -// Perform Keyboard action by Action class -action.SendKeys(Keys.Enter).Perform(); +{{< tabpane disableCodeBlock=true height="3">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L46-L48" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L34-L36" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L46-L48" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L36-L38" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - # Store google search box WebElement - search = driver.find_element(name: 'q') - # Get focus on Search - driver.execute_script('arguments[0].focus()', search) - # Send value by action class to the search box - driver.action.send_keys('Selenium').perform - # Perform Keyboard action by Action class - driver.action.send_keys(:enter).perform -ensure - driver.quit -end -{{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/sendKeysAction.js">}} - {{< /tab >}} -{{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +### Designated Element -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://www.selenium.dev/selenium/docs/api/java/overview-summary.html") +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L59-L62" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L45-L48" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L60-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L48-L51" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Store search box WebElement - val search = driver.findElement(By.id("search")) - val action = Actions(driver) +## Copy and Paste - // Send value by action class to the search box - action.sendKeys(search, "devtools").perform(); +Here's an example of using all of the above methods to conduct a copy / paste action. +Note that the key to use for this operation will be different depending on if it is a Mac OS or not. +This code will end up with the text: `SeleniumSelenium!` - // Perform Keyboard action by Action class - action.sendKeys(search, Keys.ENTER).perform(); - } finally { - driver.quit() - } -} -{{< /tab >}} +{{< tabpane disableCodeBlock=true height="13">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L73-L85" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L55-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L76-L87" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L60-L70" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.pt-br.md b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.pt-br.md index cb1419f16878..ecb25bad2bb7 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.pt-br.md @@ -1,363 +1,170 @@ --- -title: "Teclado" -linkTitle: "Teclado" +title: "Keyboard actions" +linkTitle: "Keyboard" weight: 2 -needsTranslation: true description: > A representation of any key input device for interacting with a web page. aliases: [ -"/documentation/pt-br/webdriver/keyboard/", -"/pt-br/documentation/webdriver/keyboard/" +"/documentation/en/webdriver/keyboard/", +"/documentation/webdriver/keyboard/" ] --- -Keyboard representa um evento do teclado. As ações do teclado são -executadas usando uma interface de baixo nível que nos permite fornecer -entrada de dispositivo virtualizado para o navegador da web. +There are only 2 actions that can be accomplished with a keyboard: +pressing down on a key, and releasing a pressed key. +In addition to supporting ASCII characters, each keyboard key has +a representation that can be pressed or released in designated sequences. ## Keys -In addition to the keys represented by regular unicode, -unicode values have been assigned to other keyboard keys for use with Selenium. +In addition to the keys represented by regular unicode, +unicode values have been assigned to other keyboard keys for use with Selenium. Each language has its own way to reference these keys; the full list can be found [here](https://www.w3.org/TR/webdriver/#keyboard-actions). -## Key down - -O keyDown é usado para simular a ação de pressionar uma tecla modificadora (CONTROL, SHIFT, ALT) - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -WebDriver driver = new ChromeDriver(); -try { - // Navigate to Url - driver.get("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER); - - Actions actionProvider = new Actions(driver); - Action keydown = actionProvider.keyDown(Keys.CONTROL).sendKeys("a").build(); - keydown.perform(); -} finally { - driver.quit(); -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Enter "webdriver" text and perform "ENTER" keyboard action -driver.find_element(By.NAME, "q").send_keys("webdriver" + Keys.ENTER) - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page -webdriver.ActionChains(driver).key_down(Keys.CONTROL).send_keys("a").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -IWebDriver driver = new ChromeDriver(); -try -{ - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.FindElement(By.Name("q")).SendKeys("webdriver" + Keys.Enter); - - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - Actions actionProvider = new Actions(driver); - IAction keydown = actionProvider.KeyDown(Keys.Control).SendKeys("a").Build(); - keydown.Perform(); -} -finally -{ - driver.Quit(); -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Enter "webdriver" text and perform "ENTER" keyboard action - driver.find_element(name: 'q').send_keys 'webdriver', :return - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - driver.action.key_down(:control).send_keys('a').perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyDown.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} + {{< tab header="Python" >}} +Use the [Python Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/py/selenium/webdriver/common/keys.py#L23) + {{< /tab >}} + {{< tab header="CSharp" >}} +Use the [.NET static Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/dotnet/src/webdriver/Keys.cs#L28) + {{< /tab >}} + {{< tab header="Ruby" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/rb/lib/selenium/webdriver/common/keys.rb#L28) + {{< /tab >}} + {{< tab header="JavaScript" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/javascript/node/selenium-webdriver/lib/input.js#L44) + {{< /tab >}} + {{< tab header="Kotlin" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} +{{< /tabpane >}} - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER) - val action = Actions(driver) +## Key down - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - action.keyDown(Keys.CONTROL).sendKeys("a").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L18-L21" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L10-L13" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L16-L19" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L10-L13" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Key up -O keyUp é usado para simular a liberação de uma tecla (ou) de uma tecla modificadora (CONTROL, SHIFT, ALT) - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.interactions.Actions; - -public class HelloSelenium { - public static void main(String[] args) { - WebDriver driver = new FirefoxDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - Actions action = new Actions(driver); - - // Store google search box WebElement - WebElement search = driver.findElement(By.name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search,"qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store google search box WebElement -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) -action.key_down(Keys.SHIFT).send_keys_to_element(search, "qwerty").key_up(Keys.SHIFT).send_keys("qwerty").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace HelloSelenium -{ - class HelloSelenium - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - Actions action = new Actions(driver); - // Store google search box WebElement - IWebElement search = driver.FindElement(By.Name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.KeyDown(Keys.Shift).SendKeys(search, "qwerty").KeyUp(Keys.Shift).SendKeys("qwerty").Perform(); - - } - finally { - driver.Quit(); - } - } - } -} - - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Store google search box WebElement - search = driver.find_element(name: 'q') - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - driver.action.key_down(:shift).send_keys(search,'qwerty').key_up(:shift).send_keys("qwerty").perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyUp.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - - // Store google search box WebElement - val search = driver.findElement(By.name("q")) - val action = Actions(driver) - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search, "qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L31-L36" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L21-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L30-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L22-L27" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Send keys This is a convenience method in the Actions API that combines keyDown and keyUp commands in one action. -Executing this command differs slightly from using the element method. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -WebDriver driver = new FirefoxDriver(); -try { - -// Navigate to the url -driver.get("https://google.com"); - -// Create an object of Action class -Actions action = new Actions(driver); - -// Find google search box element -WebElement search = driver.findElement(By.name("q")); - -// Send value by action class to the search box -action.sendKeys(search, "Selenium").perform(); - -// Perform Keyboard action by Action class -action.sendKeys(Keys.ENTER).perform(); - -} finally { -driver.quit(); -} - -{{< /tab >}} -{{< tab header="Python" >}} - -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.chrome.service import Service -from webdriver_manager.chrome import ChromeDriverManager - -driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) -driver.get("https://www.selenium.dev/selenium/docs/api/py/genindex.html") - -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) -action.move_to_element(search).click().send_keys("send_keys", Keys.ENTER).perform() - -{{< /tab >}} -{{< tab header="CSharp" >}} - -IWebDriver driver = new ChromeDriver(); -// Navigate to the url -driver.Url = "https://www.google.com"; -// Create an object of Action class -Actions action = new Actions(driver); -// Find google search box element -IWebElement search = driver.FindElement(By.Name("q")); -// Send value by action class to the search box -action.SendKeys(search, "Selenium").Perform(); -// Perform Keyboard action by Action class -action.SendKeys(Keys.Enter).Perform(); - -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to URL - driver.get 'https://google.com' - # Store google search box WebElement - search = driver.find_element(name: 'q') - # Get focus on Search - driver.execute_script('arguments[0].focus()', search) - # Send value by action class to the search box - driver.action.send_keys('Selenium').perform - # Perform Keyboard action by Action class - driver.action.send_keys(:enter).perform -ensure - driver.quit -end -{{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/sendKeysAction.js">}} - {{< /tab >}} -{{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://www.selenium.dev/selenium/docs/api/java/overview-summary.html") +Executing this command differs slightly from using the element method, but +primarily this gets used when needing to type multiple characters in the middle of other actions. + +### Active Element + +{{< tabpane disableCodeBlock=true height="3">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L46-L48" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L34-L36" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L46-L48" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L36-L38" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Store search box WebElement - val search = driver.findElement(By.id("search")) - val action = Actions(driver) - // Send value by action class to the search box - action.sendKeys(search, "devtools").perform(); +### Designated Element + +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L59-L62" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L45-L48" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L60-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L48-L51" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Perform Keyboard action by Action class - action.sendKeys(search, Keys.ENTER).perform(); - } finally { - driver.quit() - } -} -{{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +## Copy and Paste + +Here's an example of using all of the above methods to conduct a copy / paste action. +Note that the key to use for this operation will be different depending on if it is a Mac OS or not. +This code will end up with the text: `SeleniumSelenium!` + +{{< tabpane disableCodeBlock=true height="13">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L73-L85" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L55-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L76-L87" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L60-L70" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.zh-cn.md b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.zh-cn.md index 11d4e4fbfa7c..ecb25bad2bb7 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/keyboard.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/keyboard.zh-cn.md @@ -1,365 +1,170 @@ --- -title: "键盘Actions" -linkTitle: "键盘" +title: "Keyboard actions" +linkTitle: "Keyboard" weight: 2 description: > - 用于与网页交互的任何输入设备的呈现. + A representation of any key input device for interacting with a web page. aliases: [ -"/documentation/zh-cn/webdriver/keyboard/", -"/zh-cn/documentation/webdriver/keyboard/" +"/documentation/en/webdriver/keyboard/", +"/documentation/webdriver/keyboard/" ] --- -Keyboard代表一个键盘事件. Keyboard操作通过使用底层接口允许我们向web浏览器提供虚拟设备输入. +There are only 2 actions that can be accomplished with a keyboard: +pressing down on a key, and releasing a pressed key. +In addition to supporting ASCII characters, each keyboard key has +a representation that can be pressed or released in designated sequences. ## Keys -除了由常规unicode表示的按键, -unicode值已指派给其他键盘按键, -以便于Selenium一起使用. -每种语言都有自己的方式来引用这些键; -[在此](https://www.w3.org/TR/webdriver/#keyboard-actions) -可以找到完整的列表. +In addition to the keys represented by regular unicode, +unicode values have been assigned to other keyboard keys for use with Selenium. +Each language has its own way to reference these keys; the full list can be found +[here](https://www.w3.org/TR/webdriver/#keyboard-actions). + +{{< tabpane disableCodeBlock=true height="1">}} + {{< tab header="Java" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} + {{< tab header="Python" >}} +Use the [Python Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/py/selenium/webdriver/common/keys.py#L23) + {{< /tab >}} + {{< tab header="CSharp" >}} +Use the [.NET static Keys class](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/dotnet/src/webdriver/Keys.cs#L28) + {{< /tab >}} + {{< tab header="Ruby" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/rb/lib/selenium/webdriver/common/keys.rb#L28) + {{< /tab >}} + {{< tab header="JavaScript" >}} +Use the [Ruby KEYS constant](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/javascript/node/selenium-webdriver/lib/input.js#L44) + {{< /tab >}} + {{< tab header="Kotlin" >}} +Use the [Java Keys enum](https://github.com/SeleniumHQ/selenium/blob/selenium-4.2.0/java/src/org/openqa/selenium/Keys.java#L28) + {{< /tab >}} +{{< /tabpane >}} ## Key down -keyDown用于模拟按下辅助按键(CONTROL, SHIFT, ALT)的动作. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -WebDriver driver = new ChromeDriver(); -try { - // Navigate to Url - driver.get("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER); - - Actions actionProvider = new Actions(driver); - Action keydown = actionProvider.keyDown(Keys.CONTROL).sendKeys("a").build(); - keydown.perform(); -} finally { - driver.quit(); -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Enter "webdriver" text and perform "ENTER" keyboard action -driver.find_element(By.NAME, "q").send_keys("webdriver" + Keys.ENTER) - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page -webdriver.ActionChains(driver).key_down(Keys.CONTROL).send_keys("a").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -IWebDriver driver = new ChromeDriver(); -try -{ - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.FindElement(By.Name("q")).SendKeys("webdriver" + Keys.Enter); - - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - Actions actionProvider = new Actions(driver); - IAction keydown = actionProvider.KeyDown(Keys.Control).SendKeys("a").Build(); - keydown.Perform(); -} -finally -{ - driver.Quit(); -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Enter "webdriver" text and perform "ENTER" keyboard action - driver.find_element(name: 'q').send_keys 'webdriver', :return - - # Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - driver.action.key_down(:control).send_keys('a').perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyDown.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - - // Enter "webdriver" text and perform "ENTER" keyboard action - driver.findElement(By.name("q")).sendKeys("webdriver" + Keys.ENTER) - val action = Actions(driver) - - // Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page - action.keyDown(Keys.CONTROL).sendKeys("a").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L18-L21" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L10-L13" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L16-L19" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L10-L13" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Key up -keyUp用于模拟辅助按键(CONTROL, SHIFT, ALT)弹起或释放的操作. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.interactions.Actions; - -public class HelloSelenium { - public static void main(String[] args) { - WebDriver driver = new FirefoxDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - Actions action = new Actions(driver); - - // Store google search box WebElement - WebElement search = driver.findElement(By.name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search,"qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store google search box WebElement -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) -action.key_down(Keys.SHIFT).send_keys_to_element(search, "qwerty").key_up(Keys.SHIFT).send_keys("qwerty").perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace HelloSelenium -{ - class HelloSelenium - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - - Actions action = new Actions(driver); - // Store google search box WebElement - IWebElement search = driver.FindElement(By.Name("q")); - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.KeyDown(Keys.Shift).SendKeys(search, "qwerty").KeyUp(Keys.Shift).SendKeys("qwerty").Perform(); - - } - finally { - driver.Quit(); - } - } - } -} - - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - # Navigate to URL - driver.get 'https://google.com' - - # Store google search box WebElement - search = driver.find_element(name: 'q') - - # Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - driver.action.key_down(:shift).send_keys(search,'qwerty').key_up(:shift).send_keys("qwerty").perform - -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/keyUp.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - - // Store google search box WebElement - val search = driver.findElement(By.name("q")) - val action = Actions(driver) - - // Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty) - action.keyDown(Keys.SHIFT).sendKeys(search, "qwerty").keyUp(Keys.SHIFT).sendKeys("qwerty").build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L31-L36" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L21-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L30-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L22-L27" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Send keys -这是Actions API中的一种简便方法, -它将keyDown和keyUp命令组合在一个操作中. -执行此命令与使用元素方法略有不同. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -WebDriver driver = new FirefoxDriver(); -try { - -// Navigate to the url -driver.get("https://google.com"); - -// Create an object of Action class -Actions action = new Actions(driver); - -// Find google search box element -WebElement search = driver.findElement(By.name("q")); - -// Send value by action class to the search box -action.sendKeys(search, "Selenium").perform(); - -// Perform Keyboard action by Action class -action.sendKeys(Keys.ENTER).perform(); - -} finally { -driver.quit(); -} - -{{< /tab >}} -{{< tab header="Python" >}} - -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.chrome.service import Service -from webdriver_manager.chrome import ChromeDriverManager - -driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) -driver.get("https://www.selenium.dev/selenium/docs/api/py/genindex.html") - -search = driver.find_element(By.NAME, "q") - -action = webdriver.ActionChains(driver) -action.move_to_element(search).click().send_keys("send_keys", Keys.ENTER).perform() - -{{< /tab >}} -{{< tab header="CSharp" >}} - - -IWebDriver driver = new ChromeDriver(); -// Navigate to the url -driver.Url = "https://www.google.com"; -// Create an object of Action class -Actions action = new Actions(driver); -// Find google search box element -IWebElement search = driver.FindElement(By.Name("q")); -// Send value by action class to the search box -action.SendKeys(search, "Selenium").Perform(); -// Perform Keyboard action by Action class -action.SendKeys(Keys.Enter).Perform(); - -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to URL - driver.get 'https://google.com' - # Store google search box WebElement - search = driver.find_element(name: 'q') - # Get focus on Search - driver.execute_script('arguments[0].focus()', search) - # Send value by action class to the search box - driver.action.send_keys('Selenium').perform - # Perform Keyboard action by Action class - driver.action.send_keys(:enter).perform -ensure - driver.quit -end -{{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/keyboard/sendKeysAction.js">}} - {{< /tab >}} - -{{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Keys -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://www.selenium.dev/selenium/docs/api/java/overview-summary.html") +This is a convenience method in the Actions API that combines keyDown and keyUp commands in one action. +Executing this command differs slightly from using the element method, but +primarily this gets used when needing to type multiple characters in the middle of other actions. + +### Active Element + +{{< tabpane disableCodeBlock=true height="3">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L46-L48" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L34-L36" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L46-L48" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L36-L38" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Store search box WebElement - val search = driver.findElement(By.id("search")) - val action = Actions(driver) - // Send value by action class to the search box - action.sendKeys(search, "devtools").perform(); +### Designated Element + +{{< tabpane disableCodeBlock=true height="4">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L59-L62" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L45-L48" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L60-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L48-L51" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} - // Perform Keyboard action by Action class - action.sendKeys(search, Keys.ENTER).perform(); - } finally { - driver.quit() - } -} -{{< /tab >}} +## Copy and Paste + +Here's an example of using all of the above methods to conduct a copy / paste action. +Note that the key to use for this operation will be different depending on if it is a Mac OS or not. +This code will end up with the text: `SeleniumSelenium!` + +{{< tabpane disableCodeBlock=true height="13">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/KeysTest.java#L73-L85" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_keys.py#L55-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/KeysTest.cs#L76-L87" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/keys_spec.rb#L60-L70" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/mouse.en.md b/website_and_docs/content/documentation/webdriver/actions_api/mouse.en.md index 75abf0a0e95d..94bf789cf4a9 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/mouse.en.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/mouse.en.md @@ -11,1056 +11,373 @@ aliases: [ ] --- -## Click and hold - -It will move to the element and clicks (without releasing) in the middle of the given element. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class clickAndHold { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -driver = webdriver.Chrome() +There are only 3 actions that can be accomplished with a mouse: +pressing down on a button, releasing a pressed button, and moving the mouse. +Selenium provides convenience methods that combine these actions in the most common ways. -# Navigate to url -driver.get("http://www.google.com") - -# Store 'Sign In' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform click-and-hold action on the element -webdriver.ActionChains(driver).click_and_hold(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ClickAndHold - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'Sign In' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.ClickAndHold(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform click-and-hold action on the element - driver.action.click_and_hold(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/clickAndHold.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +## Click and hold -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Sign In' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +This method combines moving the mouse to the center of an element with pressing the left mouse button. +This is useful for focusing a specific element: + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L22-L25" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L12-L15" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## Context click -This method firstly performs a mouse-move to the location of the element and performs the context-click (right click) on the given element. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class contextClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform context-click action on the element -webdriver.ActionChains(driver).context_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ContextClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.ContextClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome +## Click and release + +This method combines moving to the center of an element with pressing and releasing the left mouse button. +This is otherwise known as "clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L34-L37" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L24-L27" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L30-L33" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L20-L23" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform context-click action on the element - driver.action.context_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); +## Alternate Button Clicks + +There are a total of 5 defined buttons for a Mouse: +* 0 — Left Button (the default) +* 1 — Middle Button (currently unsupported) +* 2 — Right Button +* 3 — X1 (Back) Button +* 4 — X2 (Forward) Button + +### Context Click + +This method combines moving to the center of an element with pressing and releasing the right mouse button (button 2). +This is otherwise known as "right-clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L46-L49" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L35-L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L43-L46" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L31-L34" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -(async function contextClick() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'signIn' button web element - let signIn = driver.findElement(By.linkText("Sign in")); - const actions = driver.actions({async: true}); - // Perform context-click action on the element - await actions.contextClick(signIn).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +### Back Click + +There is no convenience method for this, it is just pressing and releasing mouse button 3 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L60-L66" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L49-L52" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L59-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L44-L47" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Forward Click + +There is no convenience method for this, it is just pressing and releasing mouse button 4 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L78-L84" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L63-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L77-L81" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L58-L61" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Double click -It will move to the element and performs a double-click in the middle of the given element. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class doubleClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform double-click action on the element -webdriver.ActionChains(driver).double_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DoubleClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.DoubleClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform double-click action on the element - driver.action.double_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/doubleClick.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +This method combines moving to the center of an element with pressing and releasing the left mouse button twice. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L93-L96" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L74-L77" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L91-L94" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L69-L72" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Move to element -This method moves the mouse to the middle of the element. The element is also scrolled into the view on performing this action. -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveToElement { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") - - # Performs mouse move action onto the element -webdriver.ActionChains(driver).move_to_element(gmailLink).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveToElement - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.MoveToElement(gmailLink).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Performs mouse move action onto the element - driver.action.move_to(gmail_link).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/moveToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +This method moves the mouse to the in-view center point of the element. +This is otherwise known as "hovering." +Note that the element must be in the viewport or else the command will error. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L105-L108" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L85-L88" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L104-L107" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L80-L83" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} ## Move by offset -This method moves the mouse from its current position (or 0,0) by the given offset. If the coordinates are outside the view window, then the mouse will end up outside the browser window. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveByOffset { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture x and y offset positions of element - int xOffset = gmailLink.getRect().getX(); - int yOffset = gmailLink.getRect().getY(); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.moveByOffset(xOffset, yOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - - # Navigate to url -driver.get("http://www.google.com") - - # Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") - # Set x and y offset positions of element -xOffset = 100 -yOffset = 100 - # Performs mouse move action onto the element -webdriver.ActionChains(driver).move_by_offset(xOffset,yOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveByOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - // Set x and y offset positions of element - int xOffset = 100; - int yOffset = 100; - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.MoveByOffset(xOffset, yOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome +These methods first move the mouse to the designated origin and then +by the number of pixels in the provided offset. +Note that the position of the mouse must be in the viewport or else the command will error. + +### Offset from Element (Top Left Origin) + +This method moves the mouse to the in-view center point of the element +then attempts to move to the upper left corner of the element and then moves by the +provided offset. + +This will be removed as an option in Selenium 4.3, and only an offset from center of the element +will be supported. As of Selenium 4.2, this is the default behavior for Ruby, .NET and Python in order +to be backwards compatible with previous versions of Selenium. +This approach does not work correctly when the element is not entirely inside the viewport. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} +**Not Implemented in Selenium 4** + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L96-L99" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L118-L121" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L91-L94" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Capture x and y offset positions of element - x_offset = gmail_link.rect.x - y_offset = gmail_link.rect.y - # Performs mouse move action onto the offset position - driver.action.move_to_location(x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); +### Offset from Element (Center Origin) + +This method moves to the in-view center point of the element, +then moves the mouse by the provided offset + +This is the default behavior in Java as of Selenium 4.0, and will be the default +for the remaining languages as of Selenium 4.3. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L117-L120" >}} + {{< /tab >}} + {{< tab header="Python" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L133-L136" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -(async function moveByOffset() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'Gmail' anchor web element - let gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture offset positions of element - let offset = await gmailLink.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs mouse move action onto the element - await actions.move({x:parseInt(x),y:parseInt(y)}).pause(3000).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +### Offset from Viewport + +This method moves the mouse from the upper left corner of the current viewport by the provided +offset. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L131-L136" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L109-L111" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L148-L152" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L105-L107" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - // Capture x and y offset positions of element - val xOffset = gmailLink.rect.getX() - val yOffset = gmailLink.rect.getY() - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveByOffset(xOffset, yOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Offset from Current Pointer Location + +This method moves the mouse from its current position by the offset provided by the user. +If the mouse has not previously been moved, the position will be in the upper left +corner of the viewport. +Note that the pointer position does not change when the page is scrolled. + +{{< tabpane disableCodeBlock=true height="3" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L153-L155" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L126-L128" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L170-L172" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L119-L121" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDrop +## Drag and Drop on Element This method firstly performs a click-and-hold on the source element, moves to the location of the target element and then releases the mouse. -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDrop { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -driver = webdriver.Chrome() - - # Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - - # Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") - # Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") - # Performs drag and drop action of sourceEle onto the targetEle -webdriver.ActionChains(driver).drag_and_drop(sourceEle,targetEle).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDrop - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDrop(sourceEle, targetEle).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - # Store 'box B' as source element - target_ele = driver.find_element(id: 'droppable') - # Performs drag and drop action of sourceEle onto the targetEle - driver.action.drag_and_drop(source_ele, target_ele).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDrop() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - // Performs drag and drop action of sourceEle onto the targetEle - await actions.dragAndDrop(sourceEle, targetEle).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="5" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L166-L170" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L139-L143" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L184-L188" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L131-L135" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDropBy +## Drag and Drop by Offset This method firstly performs a click-and-hold on the source element, moves to the given offset and then releases the mouse. -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDropBy { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - int targetEleXOffset = targetEle.getLocation().getX(); - int targetEleYOffset = targetEle.getLocation().getY(); - Actions actionProvider = new Actions(driver); - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - - # Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - - # Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") - # Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -targetEleXOffset = targetEle.location.get("x") -targetEleYOffset = targetEle.location.get("y") - - # Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).drag_and_drop_by_offset(sourceEle, targetEleXOffset, targetEleYOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDropToOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - int targetEleXOffset = targetEle.Location.X; - int targetEleYOffset = targetEle.Location.Y; - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDropToOffset(sourceEle, targetEleXOffset, targetEleYOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - # Capture x and y offset positions of element - x_offset = target_ele.rect.x - y_offset = target_ele.rect.y - # Performs dragAndDropBy onto the target element offset position - driver.action.drag_and_drop_by(source_ele, x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDropBy() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - let offset = await targetEle.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs dragAndDropBy onto the target element offset position - await actions.dragAndDrop(sourceEle, {x:parseInt(x), y:parseInt(y)}).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val targetEleXOffset = targetEle.location.getX() - val targetEleYOffset = targetEle.location.getY() - val actionProvider = Actions(driver) - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} -{{< /tabpane >}} - -## release - -This action releases the depressed left mouse button. If WebElement is passed, -it will release depressed left mouse button on the given WebElement - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class release { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform(); - // Performs release event - actionProvider.release().build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - - # Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - - # Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") - # Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") - - # Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).click_and_hold(sourceEle).move_to_element(targetEle).perform() - # Performs release event -webdriver.ActionChains(driver).release().perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class Release - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.ClickAndHold(sourceEle).MoveToElement(targetEle).Build().Perform(); - // Performs release event - actionProvider.Release().Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - driver.action.click_and_hold(source_ele).move_to(target_ele).perform - # Performs release event - driver.action.release.perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function release() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - await actions.move({origin:sourceEle}).press().perform(); - // Performs release event on target element - await actions.move({origin:targetEle}).release().perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform() - // Performs release event - actionProvider.release().build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L179-L184" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L151-L156" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L198-L203" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L143-L148" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/actions_api/mouse.ja.md b/website_and_docs/content/documentation/webdriver/actions_api/mouse.ja.md index 898ee62a618d..94bf789cf4a9 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/mouse.ja.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/mouse.ja.md @@ -1,1066 +1,383 @@ --- -title: "マウスアクションの詳細" -linkTitle: "マウスアクションの詳細" +title: "Mouse actions" +linkTitle: "Mouse" weight: 4 needsTranslation: true description: > - マウスは、マウスイベントを表します。 - マウスアクションは低レベルインターフェイスを使用して実行され、仮想化されたデバイス入力アクションをWebブラウザーに提供できます。 + A representation of any pointer device for interacting with a web page. aliases: [ -"/documentation/ja/support_packages/mouse_and_keyboard_actions_in_detail/", -"/ja/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" +"/documentation/en/support_packages/mouse_and_keyboard_actions_in_detail/", +"/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" ] --- - -## クリックとホールド - -要素に移動し、指定された要素の中央で(解放せずに)クリックします。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class clickAndHold { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Sign In' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'Sign In' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform click-and-hold action on the element -webdriver.ActionChains(driver).click_and_hold(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ClickAndHold - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'Sign In' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.ClickAndHold(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform click-and-hold action on the element - driver.action.click_and_hold(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/clickAndHold.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Sign In' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +There are only 3 actions that can be accomplished with a mouse: +pressing down on a button, releasing a pressed button, and moving the mouse. +Selenium provides convenience methods that combine these actions in the most common ways. + +## Click and hold + +This method combines moving the mouse to the center of an element with pressing the left mouse button. +This is useful for focusing a specific element: + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L22-L25" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L12-L15" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## コンテキストクリック(右クリック) -このメソッドは、最初に要素の位置へのマウス移動を実行し、指定された要素でコンテキストクリック(右クリック)を実行します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class contextClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform context-click action on the element -webdriver.ActionChains(driver).context_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ContextClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.ContextClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform context-click action on the element - driver.action.context_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function contextClick() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'signIn' button web element - let signIn = driver.findElement(By.linkText("Sign in")); - const actions = driver.actions({async: true}); - // Perform context-click action on the element - await actions.contextClick(signIn).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Click and release + +This method combines moving to the center of an element with pressing and releasing the left mouse button. +This is otherwise known as "clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L34-L37" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L24-L27" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L30-L33" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L20-L23" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## ダブルクリック -要素に移動し、指定された要素の中央でダブルクリックを実行します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class doubleClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform double-click action on the element -webdriver.ActionChains(driver).double_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DoubleClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.DoubleClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform double-click action on the element - driver.action.double_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/doubleClick.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Alternate Button Clicks + +There are a total of 5 defined buttons for a Mouse: +* 0 — Left Button (the default) +* 1 — Middle Button (currently unsupported) +* 2 — Right Button +* 3 — X1 (Back) Button +* 4 — X2 (Forward) Button + +### Context Click + +This method combines moving to the center of an element with pressing and releasing the right mouse button (button 2). +This is otherwise known as "right-clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L46-L49" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L35-L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L43-L46" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L31-L34" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## 要素への移動 -このメソッドは、マウスを要素の中央に移動します。 -このアクションを実行すると、要素もビューにスクロールされます。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveToElement { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") - -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_to_element(gmailLink).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveToElement - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.MoveToElement(gmailLink).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Performs mouse move action onto the element - driver.action.move_to(gmail_link).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/moveToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Back Click + +There is no convenience method for this, it is just pressing and releasing mouse button 3 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L60-L66" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L49-L52" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L59-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L44-L47" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## オフセットによる移動 - -このメソッドは、マウスを現在の位置(または0,0)から指定したオフセットだけ移動します。 -座標がビューウィンドウの外側にある場合、マウスはブラウザウィンドウの外側になります。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveByOffset { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture x and y offset positions of element - int xOffset = gmailLink.getRect().getX(); - int yOffset = gmailLink.getRect().getY(); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.moveByOffset(xOffset, yOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") -#Set x and y offset positions of element -xOffset = 100 -yOffset = 100 -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_by_offset(xOffset,yOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveByOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - // Set x and y offset positions of element - int xOffset = 100; - int yOffset = 100; - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.MoveByOffset(xOffset, yOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Capture x and y offset positions of element - x_offset = gmail_link.rect.x - y_offset = gmail_link.rect.y - # Performs mouse move action onto the offset position - driver.action.move_to_location(x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function moveByOffset() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'Gmail' anchor web element - let gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture offset positions of element - let offset = await gmailLink.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs mouse move action onto the element - await actions.move({x:parseInt(x),y:parseInt(y)}).pause(3000).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - // Capture x and y offset positions of element - val xOffset = gmailLink.rect.getX() - val yOffset = gmailLink.rect.getY() - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveByOffset(xOffset, yOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Forward Click + +There is no convenience method for this, it is just pressing and releasing mouse button 4 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L78-L84" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L63-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L77-L81" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L58-L61" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## ドラッグアンドドロップ - -このメソッドは、最初にソース要素でクリックアンドホールドを実行し、ターゲット要素の位置に移動してからマウスを離します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDrop { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -# Performs drag and drop action of sourceEle onto the targetEle -webdriver.ActionChains(driver).drag_and_drop(sourceEle,targetEle).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDrop - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDrop(sourceEle, targetEle).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - # Store 'box B' as source element - target_ele = driver.find_element(id: 'droppable') - # Performs drag and drop action of sourceEle onto the targetEle - driver.action.drag_and_drop(source_ele, target_ele).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDrop() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - // Performs drag and drop action of sourceEle onto the targetEle - await actions.dragAndDrop(sourceEle, targetEle).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Double click + +This method combines moving to the center of an element with pressing and releasing the left mouse button twice. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L93-L96" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L74-L77" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L91-L94" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L69-L72" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## オフセット分のドラッグアンドドロップ - -このメソッドは、まずソース要素でクリックアンドホールドを実行し、指定されたオフセットに移動してからマウスを離します。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDropBy { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - int targetEleXOffset = targetEle.getLocation().getX(); - int targetEleYOffset = targetEle.getLocation().getY(); - Actions actionProvider = new Actions(driver); - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -targetEleXOffset = targetEle.location.get("x") -targetEleYOffset = targetEle.location.get("y") - -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).drag_and_drop_by_offset(sourceEle, targetEleXOffset, targetEleYOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDropToOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - int targetEleXOffset = targetEle.Location.X; - int targetEleYOffset = targetEle.Location.Y; - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDropToOffset(sourceEle, targetEleXOffset, targetEleYOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - # Capture x and y offset positions of element - x_offset = target_ele.rect.x - y_offset = target_ele.rect.y - # Performs dragAndDropBy onto the target element offset position - driver.action.drag_and_drop_by(source_ele, x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDropBy() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - let offset = await targetEle.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs dragAndDropBy onto the target element offset position - await actions.dragAndDrop(sourceEle, {x:parseInt(x), y:parseInt(y)}).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val targetEleXOffset = targetEle.location.getX() - val targetEleYOffset = targetEle.location.getY() - val actionProvider = Actions(driver) - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Move to element + +This method moves the mouse to the in-view center point of the element. +This is otherwise known as "hovering." +Note that the element must be in the viewport or else the command will error. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L105-L108" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L85-L88" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L104-L107" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L80-L83" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## リリース - -このアクションは、押し下げられたマウスの左ボタンをリリースします。 -WebElementが渡されると、指定されたWebElementでマウスの左ボタンが押された状態でリリースされます。 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class release { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform(); - // Performs release event - actionProvider.release().build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") +## Move by offset + +These methods first move the mouse to the designated origin and then +by the number of pixels in the provided offset. +Note that the position of the mouse must be in the viewport or else the command will error. + +### Offset from Element (Top Left Origin) + +This method moves the mouse to the in-view center point of the element +then attempts to move to the upper left corner of the element and then moves by the +provided offset. + +This will be removed as an option in Selenium 4.3, and only an offset from center of the element +will be supported. As of Selenium 4.2, this is the default behavior for Ruby, .NET and Python in order +to be backwards compatible with previous versions of Selenium. +This approach does not work correctly when the element is not entirely inside the viewport. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} +**Not Implemented in Selenium 4** + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L96-L99" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L118-L121" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L91-L94" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).click_and_hold(sourceEle).move_to_element(targetEle).perform() -#Performs release event -webdriver.ActionChains(driver).release().perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; +### Offset from Element (Center Origin) + +This method moves to the in-view center point of the element, +then moves the mouse by the provided offset + +This is the default behavior in Java as of Selenium 4.0, and will be the default +for the remaining languages as of Selenium 4.3. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L117-L120" >}} + {{< /tab >}} + {{< tab header="Python" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L133-L136" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -namespace SeleniumApp -{ - public class Release - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.ClickAndHold(sourceEle).MoveToElement(targetEle).Build().Perform(); - // Performs release event - actionProvider.Release().Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome +### Offset from Viewport + +This method moves the mouse from the upper left corner of the current viewport by the provided +offset. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L131-L136" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L109-L111" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L148-L152" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L105-L107" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - driver.action.click_and_hold(source_ele).move_to(target_ele).perform - # Performs release event - driver.action.release.perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); +### Offset from Current Pointer Location + +This method moves the mouse from its current position by the offset provided by the user. +If the mouse has not previously been moved, the position will be in the upper left +corner of the viewport. +Note that the pointer position does not change when the page is scrolled. + +{{< tabpane disableCodeBlock=true height="3" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L153-L155" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L126-L128" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L170-L172" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L119-L121" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -(async function release() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - await actions.move({origin:sourceEle}).press().perform(); - // Performs release event on target element - await actions.move({origin:targetEle}).release().perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +## Drag and Drop on Element + +This method firstly performs a click-and-hold on the source element, +moves to the location of the target element and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="5" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L166-L170" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L139-L143" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L184-L188" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L131-L135" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform() - // Performs release event - actionProvider.release().build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Drag and Drop by Offset + +This method firstly performs a click-and-hold on the source element, moves to the given offset and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L179-L184" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L151-L156" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L198-L203" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L143-L148" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/mouse.pt-br.md b/website_and_docs/content/documentation/webdriver/actions_api/mouse.pt-br.md index aa886bbaa77f..94bf789cf4a9 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/mouse.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/mouse.pt-br.md @@ -1,1068 +1,383 @@ --- -title: "Ações do mouse em detalhe" -linkTitle: "Ações do mouse em detalhe" +title: "Mouse actions" +linkTitle: "Mouse" weight: 4 needsTranslation: true description: > - Mouse representa um evento do mouse. Ações do mouse são realizadas - usando interface de baixo nível que nos permite - fornecer ação de entrada de dispositivo virtualizado para o navegador da web. + A representation of any pointer device for interacting with a web page. aliases: [ -"/documentation/pt-br/support_packages/mouse_and_keyboard_actions_in_detail/", -"/pt-br/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" +"/documentation/en/support_packages/mouse_and_keyboard_actions_in_detail/", +"/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" ] --- -## clickAndHold - -Ele se moverá para o elemento e clicar (sem soltar) no meio do elemento fornecido. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class clickAndHold { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Sign In' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'Sign In' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform click-and-hold action on the element -webdriver.ActionChains(driver).click_and_hold(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ClickAndHold - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'Sign In' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.ClickAndHold(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform click-and-hold action on the element - driver.action.click_and_hold(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/clickAndHold.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Sign In' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +There are only 3 actions that can be accomplished with a mouse: +pressing down on a button, releasing a pressed button, and moving the mouse. +Selenium provides convenience methods that combine these actions in the most common ways. + +## Click and hold + +This method combines moving the mouse to the center of an element with pressing the left mouse button. +This is useful for focusing a specific element: + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L22-L25" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L12-L15" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## contextClick -Este método primeiro executa um movimento do mouse para a localização do elemento e executa o clique de contexto (clique com o botão direito) no elemento fornecido. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class contextClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform context-click action on the element -webdriver.ActionChains(driver).context_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ContextClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.ContextClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform context-click action on the element - driver.action.context_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function contextClick() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'signIn' button web element - let signIn = driver.findElement(By.linkText("Sign in")); - const actions = driver.actions({async: true}); - // Perform context-click action on the element - await actions.contextClick(signIn).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Click and release + +This method combines moving to the center of an element with pressing and releasing the left mouse button. +This is otherwise known as "clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L34-L37" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L24-L27" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L30-L33" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L20-L23" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## doubleClick -Ele se moverá para o elemento e executará um clique duplo no meio do elemento fornecido. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class doubleClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform double-click action on the element -webdriver.ActionChains(driver).double_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DoubleClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.DoubleClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform double-click action on the element - driver.action.double_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/doubleClick.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Alternate Button Clicks + +There are a total of 5 defined buttons for a Mouse: +* 0 — Left Button (the default) +* 1 — Middle Button (currently unsupported) +* 2 — Right Button +* 3 — X1 (Back) Button +* 4 — X2 (Forward) Button + +### Context Click + +This method combines moving to the center of an element with pressing and releasing the right mouse button (button 2). +This is otherwise known as "right-clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L46-L49" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L35-L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L43-L46" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L31-L34" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## moveToElement -Este método move o mouse para o meio do elemento. O elemento também é rolado para a exibição ao executar esta ação. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveToElement { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") - -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_to_element(gmailLink).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveToElement - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.MoveToElement(gmailLink).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Performs mouse move action onto the element - driver.action.move_to(gmail_link).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/moveToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Back Click + +There is no convenience method for this, it is just pressing and releasing mouse button 3 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L60-L66" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L49-L52" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L59-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L44-L47" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## moveByOffset: - -Este método move o mouse de sua posição atual (ou 0,0) pelo deslocamento fornecido. Se as coordenadas estiverem fora da janela de visualização, o mouse ficará fora da janela do navegador. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveByOffset { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture x and y offset positions of element - int xOffset = gmailLink.getRect().getX(); - int yOffset = gmailLink.getRect().getY(); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.moveByOffset(xOffset, yOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") -#Set x and y offset positions of element -xOffset = 100 -yOffset = 100 -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_by_offset(xOffset,yOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveByOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - // Set x and y offset positions of element - int xOffset = 100; - int yOffset = 100; - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.MoveByOffset(xOffset, yOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Capture x and y offset positions of element - x_offset = gmail_link.rect.x - y_offset = gmail_link.rect.y - # Performs mouse move action onto the offset position - driver.action.move_to_location(x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function moveByOffset() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'Gmail' anchor web element - let gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture offset positions of element - let offset = await gmailLink.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs mouse move action onto the element - await actions.move({x:parseInt(x),y:parseInt(y)}).pause(3000).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - // Capture x and y offset positions of element - val xOffset = gmailLink.rect.getX() - val yOffset = gmailLink.rect.getY() - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveByOffset(xOffset, yOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Forward Click + +There is no convenience method for this, it is just pressing and releasing mouse button 4 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L78-L84" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L63-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L77-L81" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L58-L61" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDrop - -Este método primeiro executa um clique e segura no elemento de origem, -move-se para o local do elemento de destino e, em seguida, libera o mouse. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDrop { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -# Performs drag and drop action of sourceEle onto the targetEle -webdriver.ActionChains(driver).drag_and_drop(sourceEle,targetEle).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDrop - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDrop(sourceEle, targetEle).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - # Store 'box B' as source element - target_ele = driver.find_element(id: 'droppable') - # Performs drag and drop action of sourceEle onto the targetEle - driver.action.drag_and_drop(source_ele, target_ele).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDrop() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - // Performs drag and drop action of sourceEle onto the targetEle - await actions.dragAndDrop(sourceEle, targetEle).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Double click + +This method combines moving to the center of an element with pressing and releasing the left mouse button twice. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L93-L96" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L74-L77" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L91-L94" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L69-L72" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDropBy - -Este método primeiro executa um clique e segura no elemento de origem, move-se para o deslocamento fornecido e, em seguida, libera o mouse. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDropBy { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - int targetEleXOffset = targetEle.getLocation().getX(); - int targetEleYOffset = targetEle.getLocation().getY(); - Actions actionProvider = new Actions(driver); - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -targetEleXOffset = targetEle.location.get("x") -targetEleYOffset = targetEle.location.get("y") - -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).drag_and_drop_by_offset(sourceEle, targetEleXOffset, targetEleYOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDropToOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - int targetEleXOffset = targetEle.Location.X; - int targetEleYOffset = targetEle.Location.Y; - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDropToOffset(sourceEle, targetEleXOffset, targetEleYOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - # Capture x and y offset positions of element - x_offset = target_ele.rect.x - y_offset = target_ele.rect.y - # Performs dragAndDropBy onto the target element offset position - driver.action.drag_and_drop_by(source_ele, x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDropBy() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - let offset = await targetEle.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs dragAndDropBy onto the target element offset position - await actions.dragAndDrop(sourceEle, {x:parseInt(x), y:parseInt(y)}).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val targetEleXOffset = targetEle.location.getX() - val targetEleYOffset = targetEle.location.getY() - val actionProvider = Actions(driver) - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Move to element + +This method moves the mouse to the in-view center point of the element. +This is otherwise known as "hovering." +Note that the element must be in the viewport or else the command will error. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L105-L108" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L85-L88" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L104-L107" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L80-L83" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## release - -Esta ação libera o botão esquerdo do mouse pressionado. Se WebElement for aprovado, -ele irá liberar o botão esquerdo do mouse pressionado no WebElement fornecido - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class release { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform(); - // Performs release event - actionProvider.release().build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") - -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).click_and_hold(sourceEle).move_to_element(targetEle).perform() -#Performs release event -webdriver.ActionChains(driver).release().perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; +## Move by offset + +These methods first move the mouse to the designated origin and then +by the number of pixels in the provided offset. +Note that the position of the mouse must be in the viewport or else the command will error. + +### Offset from Element (Top Left Origin) + +This method moves the mouse to the in-view center point of the element +then attempts to move to the upper left corner of the element and then moves by the +provided offset. + +This will be removed as an option in Selenium 4.3, and only an offset from center of the element +will be supported. As of Selenium 4.2, this is the default behavior for Ruby, .NET and Python in order +to be backwards compatible with previous versions of Selenium. +This approach does not work correctly when the element is not entirely inside the viewport. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} +**Not Implemented in Selenium 4** + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L96-L99" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L118-L121" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L91-L94" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -namespace SeleniumApp -{ - public class Release - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.ClickAndHold(sourceEle).MoveToElement(targetEle).Build().Perform(); - // Performs release event - actionProvider.Release().Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome +### Offset from Element (Center Origin) + +This method moves to the in-view center point of the element, +then moves the mouse by the provided offset + +This is the default behavior in Java as of Selenium 4.0, and will be the default +for the remaining languages as of Selenium 4.3. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L117-L120" >}} + {{< /tab >}} + {{< tab header="Python" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L133-L136" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - driver.action.click_and_hold(source_ele).move_to(target_ele).perform - # Performs release event - driver.action.release.perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); +### Offset from Viewport + +This method moves the mouse from the upper left corner of the current viewport by the provided +offset. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L131-L136" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L109-L111" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L148-L152" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L105-L107" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -(async function release() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - await actions.move({origin:sourceEle}).press().perform(); - // Performs release event on target element - await actions.move({origin:targetEle}).release().perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +### Offset from Current Pointer Location + +This method moves the mouse from its current position by the offset provided by the user. +If the mouse has not previously been moved, the position will be in the upper left +corner of the viewport. +Note that the pointer position does not change when the page is scrolled. + +{{< tabpane disableCodeBlock=true height="3" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L153-L155" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L126-L128" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L170-L172" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L119-L121" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform() - // Performs release event - actionProvider.release().build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Drag and Drop on Element + +This method firstly performs a click-and-hold on the source element, +moves to the location of the target element and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="5" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L166-L170" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L139-L143" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L184-L188" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L131-L135" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} +## Drag and Drop by Offset + +This method firstly performs a click-and-hold on the source element, moves to the given offset and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L179-L184" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L151-L156" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L198-L203" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L143-L148" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/mouse.zh-cn.md b/website_and_docs/content/documentation/webdriver/actions_api/mouse.zh-cn.md index 937d3b081fe7..94bf789cf4a9 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/mouse.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/mouse.zh-cn.md @@ -1,1062 +1,383 @@ --- -title: "鼠标Actions" -linkTitle: "鼠标" +title: "Mouse actions" +linkTitle: "Mouse" weight: 4 needsTranslation: true description: > - Mouse表示鼠标事件. 鼠标操作是通过使用底层接口执行的, 其允许我们向Web浏览器提供虚拟化的设备输入操作. + A representation of any pointer device for interacting with a web page. aliases: [ -"/documentation/zh-cn/support_packages/mouse_and_keyboard_actions_in_detail/", -"/zh-cn/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" +"/documentation/en/support_packages/mouse_and_keyboard_actions_in_detail/", +"/documentation/support_packages/mouse_and_keyboard_actions_in_detail/" ] --- -## clickAndHold - -它将移动到该元素,然后在给定元素的中间单击(不释放). - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class clickAndHold { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Sign In' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'Sign In' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform click-and-hold action on the element -webdriver.ActionChains(driver).click_and_hold(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ClickAndHold - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'Sign In' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform click-and-hold action on the element - actionProvider.ClickAndHold(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform click-and-hold action on the element - driver.action.click_and_hold(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/clickAndHold.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Sign In' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform click-and-hold action on the element - actionProvider.clickAndHold(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +There are only 3 actions that can be accomplished with a mouse: +pressing down on a button, releasing a pressed button, and moving the mouse. +Selenium provides convenience methods that combine these actions in the most common ways. + +## Click and hold + +This method combines moving the mouse to the center of an element with pressing the left mouse button. +This is useful for focusing a specific element: + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L22-L25" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L12-L15" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## contextClick - -此方法首先将鼠标移动到元素的位置, 然后在给定元素执行上下文点击(右键单击). - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class contextClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform context-click action on the element -webdriver.ActionChains(driver).context_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class ContextClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform context-click action on the element - actionProvider.ContextClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform context-click action on the element - driver.action.context_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function contextClick() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'signIn' button web element - let signIn = driver.findElement(By.linkText("Sign in")); - const actions = driver.actions({async: true}); - // Perform context-click action on the element - await actions.contextClick(signIn).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform context-click action on the element - actionProvider.contextClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Click and release + +This method combines moving to the center of an element with pressing and releasing the left mouse button. +This is otherwise known as "clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L34-L37" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L24-L27" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L30-L33" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L20-L23" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## doubleClick -它将移动到该元素, 并在给定元素的中间双击. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class doubleClick { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'signIn' button web element - WebElement signIn = driver.findElement(By.linkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'signIn' button web element -signIn = driver.find_element(By.LINK_TEXT, "Sign in") - -# Perform double-click action on the element -webdriver.ActionChains(driver).double_click(signIn).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DoubleClick - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'signIn' button web element - IWebElement signIn = driver.FindElement(By.LinkText("Sign in")); - Actions actionProvider = new Actions(driver); - // Perform double-click action on the element - actionProvider.DoubleClick(signIn).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Sign In' button web element - sign_in = driver.find_element(link_text: 'Sign in') - # Perform double-click action on the element - driver.action.double_click(sign_in).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/doubleClick.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'signIn' button web element - val signIn = driver.findElement(By.linkText("Sign in")) - val actionProvider = Actions(driver) - // Perform double-click action on the element - actionProvider.doubleClick(signIn).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Alternate Button Clicks + +There are a total of 5 defined buttons for a Mouse: +* 0 — Left Button (the default) +* 1 — Middle Button (currently unsupported) +* 2 — Right Button +* 3 — X1 (Back) Button +* 4 — X2 (Forward) Button + +### Context Click + +This method combines moving to the center of an element with pressing and releasing the right mouse button (button 2). +This is otherwise known as "right-clicking": + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L46-L49" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L35-L38" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L43-L46" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L31-L34" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## moveToElement -此方法将鼠标移到元素的中间. 执行此操作时, 该元素也会滚动到视图中. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveToElement { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") - -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_to_element(gmailLink).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveToElement - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the element - actionProvider.MoveToElement(gmailLink).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Performs mouse move action onto the element - driver.action.move_to(gmail_link).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/mouse/moveToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveToElement(gmailLink).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Back Click + +There is no convenience method for this, it is just pressing and releasing mouse button 3 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L60-L66" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L49-L52" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L59-L63" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L44-L47" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## moveByOffset: - -此方法将鼠标从其当前位置(或0,0)移动给定的偏移量. 如果坐标在视图窗口之外, 则鼠标最终将在浏览器窗口之外. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class moveByOffset { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://google.com"); - - // Store 'Gmail' anchor web element - WebElement gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture x and y offset positions of element - int xOffset = gmailLink.getRect().getX(); - int yOffset = gmailLink.getRect().getY(); - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.moveByOffset(xOffset, yOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("http://www.google.com") - -# Store 'google search' button web element -gmailLink = driver.find_element(By.LINK_TEXT, "Gmail") -#Set x and y offset positions of element -xOffset = 100 -yOffset = 100 -# Performs mouse move action onto the element -webdriver.ActionChains(driver).move_by_offset(xOffset,yOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class MoveByOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://google.com"); - // Store 'google search' button web element - IWebElement gmailLink = driver.FindElement(By.LinkText("Gmail")); - // Set x and y offset positions of element - int xOffset = 100; - int yOffset = 100; - Actions actionProvider = new Actions(driver); - // Performs mouse move action onto the offset position - actionProvider.MoveByOffset(xOffset, yOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://www.google.com' - # Store 'Gmail' anchor web element - gmail_link = driver.find_element(link_text: 'Gmail') - # Capture x and y offset positions of element - x_offset = gmail_link.rect.x - y_offset = gmail_link.rect.y - # Performs mouse move action onto the offset position - driver.action.move_to_location(x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function moveByOffset() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://www.google.com'); - // Store 'Gmail' anchor web element - let gmailLink = driver.findElement(By.linkText("Gmail")); - // Capture offset positions of element - let offset = await gmailLink.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs mouse move action onto the element - await actions.move({x:parseInt(x),y:parseInt(y)}).pause(3000).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://google.com") - // Store 'Gmail' anchor web element - val gmailLink = driver.findElement(By.linkText("Gmail")) - // Capture x and y offset positions of element - val xOffset = gmailLink.rect.getX() - val yOffset = gmailLink.rect.getY() - val actionProvider = Actions(driver) - // Performs mouse move action onto the element - actionProvider.moveByOffset(xOffset, yOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +### Forward Click + +There is no convenience method for this, it is just pressing and releasing mouse button 4 + +{{< tabpane disableCodeBlock=true height="7" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L78-L84" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L63-L66" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L77-L81" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L58-L61" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDrop - -此方法首先在源元素上单击并按住,然后移动到目标元素的位置后释放鼠标. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDrop { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -# Performs drag and drop action of sourceEle onto the targetEle -webdriver.ActionChains(driver).drag_and_drop(sourceEle,targetEle).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDrop - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDrop(sourceEle, targetEle).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - # Store 'box B' as source element - target_ele = driver.find_element(id: 'droppable') - # Performs drag and drop action of sourceEle onto the targetEle - driver.action.drag_and_drop(source_ele, target_ele).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDrop() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - // Performs drag and drop action of sourceEle onto the targetEle - await actions.dragAndDrop(sourceEle, targetEle).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.dragAndDrop(sourceEle, targetEle).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Double click + +This method combines moving to the center of an element with pressing and releasing the left mouse button twice. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L93-L96" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L74-L77" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L91-L94" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L69-L72" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## dragAndDropBy - -此方法首先在源元素上单击并按住, 移至给定的偏移量后释放鼠标. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class dragAndDropBy { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - int targetEleXOffset = targetEle.getLocation().getX(); - int targetEleYOffset = targetEle.getLocation().getY(); - Actions actionProvider = new Actions(driver); - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") -targetEleXOffset = targetEle.location.get("x") -targetEleYOffset = targetEle.location.get("y") - -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).drag_and_drop_by_offset(sourceEle, targetEleXOffset, targetEleYOffset).perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; - -namespace SeleniumApp -{ - public class DragAndDropToOffset - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - int targetEleXOffset = targetEle.Location.X; - int targetEleYOffset = targetEle.Location.Y; - Actions actionProvider = new Actions(driver); - // Performs drag and drop action of sourceEle onto the targetEle - actionProvider.DragAndDropToOffset(sourceEle, targetEleXOffset, targetEleYOffset).Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - # Store 'box A' as source element - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - # Capture x and y offset positions of element - x_offset = target_ele.rect.x - y_offset = target_ele.rect.y - # Performs dragAndDropBy onto the target element offset position - driver.action.drag_and_drop_by(source_ele, x_offset, y_offset).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); - -(async function dragAndDropBy() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - let offset = await targetEle.getRect(); - let x = await offset.x; - let y = await offset.y; - const actions = driver.actions({async: true}); - // Performs dragAndDropBy onto the target element offset position - await actions.dragAndDrop(sourceEle, {x:parseInt(x), y:parseInt(y)}).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions - -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val targetEleXOffset = targetEle.location.getX() - val targetEleYOffset = targetEle.location.getY() - val actionProvider = Actions(driver) - // Performs dragAndDropBy onto the target element offset position - actionProvider.dragAndDropBy(sourceEle, targetEleXOffset, targetEleYOffset).build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Move to element + +This method moves the mouse to the in-view center point of the element. +This is otherwise known as "hovering." +Note that the element must be in the viewport or else the command will error. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L105-L108" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L85-L88" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L104-L107" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L80-L83" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} -## release - -此操作将释放按下的鼠标左键. 如果WebElement转移了, 它将释放给定WebElement上按下的鼠标左键. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; - -public class release { - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - WebElement sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - WebElement targetEle = driver.findElement(By.id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform(); - // Performs release event - actionProvider.release().build().perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -driver = webdriver.Chrome() - -# Navigate to url -driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - -# Store 'box A' as source element -sourceEle = driver.find_element(By.ID, "draggable") -# Store 'box B' as source element -targetEle = driver.find_element(By.ID, "droppable") +## Move by offset + +These methods first move the mouse to the designated origin and then +by the number of pixels in the provided offset. +Note that the position of the mouse must be in the viewport or else the command will error. + +### Offset from Element (Top Left Origin) + +This method moves the mouse to the in-view center point of the element +then attempts to move to the upper left corner of the element and then moves by the +provided offset. + +This will be removed as an option in Selenium 4.3, and only an offset from center of the element +will be supported. As of Selenium 4.2, this is the default behavior for Ruby, .NET and Python in order +to be backwards compatible with previous versions of Selenium. +This approach does not work correctly when the element is not entirely inside the viewport. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} +**Not Implemented in Selenium 4** + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L96-L99" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L118-L121" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L91-L94" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -# Performs dragAndDropBy onto the target element offset position -webdriver.ActionChains(driver).click_and_hold(sourceEle).move_to_element(targetEle).perform() -#Performs release event -webdriver.ActionChains(driver).release().perform() - {{< /tab >}} - {{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.Interactions; +### Offset from Element (Center Origin) + +This method moves to the in-view center point of the element, +then moves the mouse by the provided offset + +This is the default behavior in Java as of Selenium 4.0, and will be the default +for the remaining languages as of Selenium 4.3. + +{{< tabpane disableCodeBlock=true height="4" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L117-L120" >}} + {{< /tab >}} + {{< tab header="Python" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L133-L136" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} +**Coming in Selenium 4.3** + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -namespace SeleniumApp -{ - public class Release - { - public static void Main(string[] args) - { - IWebDriver driver = new ChromeDriver(); - try - { - // Navigate to Url - driver.Navigate().GoToUrl("https://crossbrowsertesting.github.io/drag-and-drop"); - // Store 'box A' as source element - IWebElement sourceEle = driver.FindElement(By.Id("draggable")); - // Store 'box B' as source element - IWebElement targetEle = driver.FindElement(By.Id("droppable")); - Actions actionProvider = new Actions(driver); - actionProvider.ClickAndHold(sourceEle).MoveToElement(targetEle).Build().Perform(); - // Performs release event - actionProvider.Release().Build().Perform(); - } - finally - { - driver.Quit(); - } - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome +### Offset from Viewport + +This method moves the mouse from the upper left corner of the current viewport by the provided +offset. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L131-L136" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L109-L111" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L148-L152" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L105-L107" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -begin - # Navigate to Url - driver.get 'https://crossbrowsertesting.github.io/drag-and-drop' - source_ele = driver.find_element(id: 'draggable') - target_ele = driver.find_element(id: 'droppable') - driver.action.click_and_hold(source_ele).move_to(target_ele).perform - # Performs release event - driver.action.release.perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); +### Offset from Current Pointer Location + +This method moves the mouse from its current position by the offset provided by the user. +If the mouse has not previously been moved, the position will be in the upper left +corner of the viewport. +Note that the pointer position does not change when the page is scrolled. + +{{< tabpane disableCodeBlock=true height="3" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L153-L155" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L126-L128" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L170-L172" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L119-L121" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -(async function release() { - let driver = await new Builder().forBrowser('chrome').build(); - try { - // Navigate to Url - await driver.get('https://crossbrowsertesting.github.io/drag-and-drop'); - // Store 'box A' as source element - let sourceEle = driver.findElement(By.id("draggable")); - // Store 'box B' as source element - let targetEle = driver.findElement(By.id("droppable")); - const actions = driver.actions({async: true}); - await actions.move({origin:sourceEle}).press().perform(); - // Performs release event on target element - await actions.move({origin:targetEle}).release().perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions +## Drag and Drop on Element + +This method firstly performs a click-and-hold on the source element, +moves to the location of the target element and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="5" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L166-L170" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L139-L143" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L184-L188" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L131-L135" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} -fun main() { - val driver = ChromeDriver() - try { - // Navigate to Url - driver.get("https://crossbrowsertesting.github.io/drag-and-drop") - // Store 'box A' as source element - val sourceEle = driver.findElement(By.id("draggable")) - // Store 'box B' as source element - val targetEle = driver.findElement(By.id("droppable")) - val actionProvider = Actions(driver) - actionProvider.clickAndHold(sourceEle).moveToElement(targetEle).build().perform() - // Performs release event - actionProvider.release().build().perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Drag and Drop by Offset + +This method firstly performs a click-and-hold on the source element, moves to the given offset and then releases the mouse. + +{{< tabpane disableCodeBlock=true height="6" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/MouseTest.java#L179-L184" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_mouse.py#L151-L156" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/MouseTest.cs#L198-L203" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/mouse_spec.rb#L143-L148" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} {{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/pen.en.md b/website_and_docs/content/documentation/webdriver/actions_api/pen.en.md new file mode 100644 index 000000000000..04fdf4208d74 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/actions_api/pen.en.md @@ -0,0 +1,69 @@ +--- +title: "Pen actions" +linkTitle: "Pen" +weight: 5 +description: > + A representation of a pen stylus kind of pointer input for interacting with a web page. +--- + +{{< badge browser=Chromium wpt="perform_actions/pointer.py" >}} + +A Pen is a type of pointer input that has most of the same behavior as a mouse, but can +also have event properties unique to a stylus. Additionally, while a mouse +has 5 buttons, a pen has 3 equivalent button states: + +* 0 — Touch Contact (the default; equivalent to a left click) +* 2 — Barrel Button (equivalent to a right click) +* 5 — Eraser Button (currently unsupported by drivers) + +## Using a Pen + +{{< tabpane disableCodeBlock=true height="11">}} + {{< tab header="Java" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L26-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L12-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L19-L28" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L9-L15" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Adding Pointer Event Attributes + +{{< badge version="4.2" >}} + +{{< tabpane disableCodeBlock=true height="15">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L67-L81" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L53-L61" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L64-L77" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L48-L54" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + diff --git a/website_and_docs/content/documentation/webdriver/actions_api/pen.ja.md b/website_and_docs/content/documentation/webdriver/actions_api/pen.ja.md new file mode 100644 index 000000000000..04fdf4208d74 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/actions_api/pen.ja.md @@ -0,0 +1,69 @@ +--- +title: "Pen actions" +linkTitle: "Pen" +weight: 5 +description: > + A representation of a pen stylus kind of pointer input for interacting with a web page. +--- + +{{< badge browser=Chromium wpt="perform_actions/pointer.py" >}} + +A Pen is a type of pointer input that has most of the same behavior as a mouse, but can +also have event properties unique to a stylus. Additionally, while a mouse +has 5 buttons, a pen has 3 equivalent button states: + +* 0 — Touch Contact (the default; equivalent to a left click) +* 2 — Barrel Button (equivalent to a right click) +* 5 — Eraser Button (currently unsupported by drivers) + +## Using a Pen + +{{< tabpane disableCodeBlock=true height="11">}} + {{< tab header="Java" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L26-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L12-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L19-L28" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L9-L15" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Adding Pointer Event Attributes + +{{< badge version="4.2" >}} + +{{< tabpane disableCodeBlock=true height="15">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L67-L81" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L53-L61" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L64-L77" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L48-L54" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + diff --git a/website_and_docs/content/documentation/webdriver/actions_api/pen.pt-br.md b/website_and_docs/content/documentation/webdriver/actions_api/pen.pt-br.md new file mode 100644 index 000000000000..04fdf4208d74 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/actions_api/pen.pt-br.md @@ -0,0 +1,69 @@ +--- +title: "Pen actions" +linkTitle: "Pen" +weight: 5 +description: > + A representation of a pen stylus kind of pointer input for interacting with a web page. +--- + +{{< badge browser=Chromium wpt="perform_actions/pointer.py" >}} + +A Pen is a type of pointer input that has most of the same behavior as a mouse, but can +also have event properties unique to a stylus. Additionally, while a mouse +has 5 buttons, a pen has 3 equivalent button states: + +* 0 — Touch Contact (the default; equivalent to a left click) +* 2 — Barrel Button (equivalent to a right click) +* 5 — Eraser Button (currently unsupported by drivers) + +## Using a Pen + +{{< tabpane disableCodeBlock=true height="11">}} + {{< tab header="Java" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L26-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L12-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L19-L28" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L9-L15" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Adding Pointer Event Attributes + +{{< badge version="4.2" >}} + +{{< tabpane disableCodeBlock=true height="15">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L67-L81" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L53-L61" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L64-L77" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L48-L54" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + diff --git a/website_and_docs/content/documentation/webdriver/actions_api/pen.zh-cn.md b/website_and_docs/content/documentation/webdriver/actions_api/pen.zh-cn.md new file mode 100644 index 000000000000..04fdf4208d74 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/actions_api/pen.zh-cn.md @@ -0,0 +1,69 @@ +--- +title: "Pen actions" +linkTitle: "Pen" +weight: 5 +description: > + A representation of a pen stylus kind of pointer input for interacting with a web page. +--- + +{{< badge browser=Chromium wpt="perform_actions/pointer.py" >}} + +A Pen is a type of pointer input that has most of the same behavior as a mouse, but can +also have event properties unique to a stylus. Additionally, while a mouse +has 5 buttons, a pen has 3 equivalent button states: + +* 0 — Touch Contact (the default; equivalent to a left click) +* 2 — Barrel Button (equivalent to a right click) +* 5 — Eraser Button (currently unsupported by drivers) + +## Using a Pen + +{{< tabpane disableCodeBlock=true height="11">}} + {{< tab header="Java" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L26-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L12-L20" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L19-L28" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< badge version="4.2" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L9-L15" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + +## Adding Pointer Event Attributes + +{{< badge version="4.2" >}} + +{{< tabpane disableCodeBlock=true height="15">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/PenTest.java#L67-L81" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_pen.py#L53-L61" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/PenTest.cs#L64-L77" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/pen_spec.rb#L48-L54" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + // Add Code + {{< /tab >}} + {{< tab header="Kotlin" >}} + // Add Code + {{< /tab >}} +{{< /tabpane >}} + diff --git a/website_and_docs/content/documentation/webdriver/actions_api/wheel.en.md b/website_and_docs/content/documentation/webdriver/actions_api/wheel.en.md index 068f90aa3397..c13d3e0ec437 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/wheel.en.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/wheel.en.md @@ -6,608 +6,171 @@ description: > A representation of a scroll wheel input device for interacting with a web page. --- -## Scroll to element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollToElement { - - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.id("closepopup")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") -element = driver.find_element(By.ID, "closepopup") - -ActionChains(driver).scroll(0, 0, 0, 0, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -// This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:id, 'closepopup') - driver.action.scroll_to(element).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/wheelScrollToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.id("closepopup")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< badge version="4.2" >}} +{{< badge browser=Chromium wpt="perform_actions/wheel.py" >}} + +There are 5 scenarios for scrolling on a page. + +## Scroll to element + +This is the most common scenario. Unlike traditional click and send keys methods, +the actions class does not automatically scroll the target element into view, +so this method will need to be used if elements are not already inside the viewport. + +This method takes a web element as the sole argument. + +Regardless of whether the element is above or below the current viewscreen, +the viewport will be scrolled so the bottom of the element is at the bottom of the screen. + +{{< tabpane disableCodeBlock=true height="5">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L17-L20" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L11-L14" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount from element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. -Scrolls the viewport further by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromElement { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.linkText("Go To Page 2")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -element = driver.find_element(By.LINK_TEXT, "Go To Page 2") - -ActionChains(driver).scroll(0, 0, 0, 300, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:link_text, 'Go To Page 2') - driver.action.scroll_to(element, 0, 300).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/scrollByAmount.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.linkText("Go To Page 2")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll by given amount + +This is the second most common scenario for scrolling. Pass in an delta x and a delta y value for how much to scroll +in the right and down directions. Negative values represent left and up, respectively. + +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L29-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L22-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L31-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L20-L24" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount - -Scrolls the viewport by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromViewPort { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 200, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -ActionChains(driver).scroll(0, 0, 0, 200).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - - driver.action.scroll_by(0, 200).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromViewport() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 500, height: 400 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - - await driver.actions().scroll(0, 0, 0, 200, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 200, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element by a given amount + +This scenario is effectively a combination of the above two methods. + +To execute this use the "Scroll From" method, which takes 3 arguments. +The first represents the origination point, which we designate as the element, +and the second two are the delta x and delta y values. + +If the element is out of the viewport, +it will be scrolled to the bottom of the screen, then the page will be scrolled by the provided +delta x and delta y values. + +{{< tabpane disableCodeBlock=true height="8" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L42-L46" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L35-L39" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L46-L53" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L32-L36" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll from a offset of origin (viewport) by given amount - -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as viewport, the origin offset is calculated from the upper left corner of the viewport. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginViewportByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(600, 600)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(20, - 200, - 0, - -50, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(600, 600) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(20, 200, 0, -50).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(600, 600) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(20, 200) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 600, height: 600 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(20, 200, 0, -50, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(600, 600) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 20, - 200, - 0, - -50, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element with an offset + +This scenario is used when you need to scroll only a portion of the screen, and it is outside the viewport. +Or is inside the viewport and the portion of the screen that must be scrolled +is a known offset away from a specific element. + +This uses the "Scroll From" method again, and in addition to specifying the element, +an offset is specified to indicate the origin point of the scroll. The offset is +calculated from the center of the provided element. + +If the element is out of the viewport, +it first will be scrolled to the bottom of the screen, then the origin of the scroll will be determined +by adding the offset to the coordinates of the center of the element, and finally +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the center of the element falls outside of the viewport, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="10">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L57-L61" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L50-L54" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L66-L75" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L46-L50" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} ## Scroll from a offset of origin (element) by given amount -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as element, the origin offset is calculated from the center of the element. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginElementByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - WebElement submit = driver.findElement(By.id("submitbtn")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") -submit = driver.find_element(By.ID, "submitbtn") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(0, -50, 0, -50, origin=submit).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - submit = driver.find_element(:id, 'submitbtn') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(submit, 0, -50) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - submit = await driver.findElement(By.id('submitbtn')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(0, -50, 0, -50, submit).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val submit = driver.findElement(By.id("submitbtn")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +The final scenario is used when you need to scroll only a portion of the screen, +and it is already inside the viewport. + +This uses the "Scroll From" method again, but the viewport is designated instead +of an element. An offset is specified from the upper left corner of the +current viewport. After the origin point is determined, +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the upper left corner of the viewport falls outside of the screen, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="9" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L73-L76" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L68-L70" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L89-L97" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L62-L64" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/wheel.ja.md b/website_and_docs/content/documentation/webdriver/actions_api/wheel.ja.md index c591b39abc32..c13d3e0ec437 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/wheel.ja.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/wheel.ja.md @@ -2,613 +2,175 @@ title: "Scroll wheel actions" linkTitle: "Wheel" weight: 6 -needsTranslation: true description: > A representation of a scroll wheel input device for interacting with a web page. --- -## Scroll to element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollToElement { - - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.id("closepopup")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") -element = driver.find_element(By.ID, "closepopup") - -ActionChains(driver).scroll(0, 0, 0, 0, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:id, 'closepopup') - driver.action.scroll_to(element).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/wheelScrollToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.id("closepopup")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< badge version="4.2" >}} +{{< badge browser=Chromium wpt="perform_actions/wheel.py" >}} + +There are 5 scenarios for scrolling on a page. + +## Scroll to element + +This is the most common scenario. Unlike traditional click and send keys methods, +the actions class does not automatically scroll the target element into view, +so this method will need to be used if elements are not already inside the viewport. + +This method takes a web element as the sole argument. + +Regardless of whether the element is above or below the current viewscreen, +the viewport will be scrolled so the bottom of the element is at the bottom of the screen. + +{{< tabpane disableCodeBlock=true height="5">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L17-L20" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L11-L14" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount from element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. -Scrolls the viewport further by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromElement { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.linkText("Go To Page 2")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -element = driver.find_element(By.LINK_TEXT, "Go To Page 2") - -ActionChains(driver).scroll(0, 0, 0, 300, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:link_text, 'Go To Page 2') - driver.action.scroll_to(element, 0, 300).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/scrollByAmount.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.linkText("Go To Page 2")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll by given amount + +This is the second most common scenario for scrolling. Pass in an delta x and a delta y value for how much to scroll +in the right and down directions. Negative values represent left and up, respectively. + +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L29-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L22-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L31-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L20-L24" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount - -Scrolls the viewport by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromViewPort { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 200, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -ActionChains(driver).scroll(0, 0, 0, 200).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - - driver.action.scroll_by(0, 200).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromViewport() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 500, height: 400 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - - await driver.actions().scroll(0, 0, 0, 200, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 200, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element by a given amount + +This scenario is effectively a combination of the above two methods. + +To execute this use the "Scroll From" method, which takes 3 arguments. +The first represents the origination point, which we designate as the element, +and the second two are the delta x and delta y values. + +If the element is out of the viewport, +it will be scrolled to the bottom of the screen, then the page will be scrolled by the provided +delta x and delta y values. + +{{< tabpane disableCodeBlock=true height="8" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L42-L46" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L35-L39" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L46-L53" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L32-L36" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll from a offset of origin (viewport) by given amount - -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as viewport, the origin offset is calculated from the upper left corner of the viewport. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginViewportByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(600, 600)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(20, - 200, - 0, - -50, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(600, 600) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(20, 200, 0, -50).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(600, 600) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(20, 200) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 600, height: 600 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(20, 200, 0, -50, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(600, 600) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 20, - 200, - 0, - -50, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element with an offset + +This scenario is used when you need to scroll only a portion of the screen, and it is outside the viewport. +Or is inside the viewport and the portion of the screen that must be scrolled +is a known offset away from a specific element. + +This uses the "Scroll From" method again, and in addition to specifying the element, +an offset is specified to indicate the origin point of the scroll. The offset is +calculated from the center of the provided element. + +If the element is out of the viewport, +it first will be scrolled to the bottom of the screen, then the origin of the scroll will be determined +by adding the offset to the coordinates of the center of the element, and finally +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the center of the element falls outside of the viewport, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="10">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L57-L61" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L50-L54" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L66-L75" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L46-L50" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} ## Scroll from a offset of origin (element) by given amount -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as element, the origin offset is calculated from the center of the element. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginElementByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - WebElement submit = driver.findElement(By.id("submitbtn")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") -submit = driver.find_element(By.ID, "submitbtn") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(0, -50, 0, -50, origin=submit).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - submit = driver.find_element(:id, 'submitbtn') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(submit, 0, -50) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - submit = await driver.findElement(By.id('submitbtn')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(0, -50, 0, -50, submit).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val submit = driver.findElement(By.id("submitbtn")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +The final scenario is used when you need to scroll only a portion of the screen, +and it is already inside the viewport. + +This uses the "Scroll From" method again, but the viewport is designated instead +of an element. An offset is specified from the upper left corner of the +current viewport. After the origin point is determined, +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the upper left corner of the viewport falls outside of the screen, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="9" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L73-L76" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L68-L70" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L89-L97" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L62-L64" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/wheel.pt-br.md b/website_and_docs/content/documentation/webdriver/actions_api/wheel.pt-br.md index c591b39abc32..c13d3e0ec437 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/wheel.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/wheel.pt-br.md @@ -2,613 +2,175 @@ title: "Scroll wheel actions" linkTitle: "Wheel" weight: 6 -needsTranslation: true description: > A representation of a scroll wheel input device for interacting with a web page. --- -## Scroll to element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollToElement { - - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.id("closepopup")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") -element = driver.find_element(By.ID, "closepopup") - -ActionChains(driver).scroll(0, 0, 0, 0, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:id, 'closepopup') - driver.action.scroll_to(element).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/wheelScrollToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.id("closepopup")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< badge version="4.2" >}} +{{< badge browser=Chromium wpt="perform_actions/wheel.py" >}} + +There are 5 scenarios for scrolling on a page. + +## Scroll to element + +This is the most common scenario. Unlike traditional click and send keys methods, +the actions class does not automatically scroll the target element into view, +so this method will need to be used if elements are not already inside the viewport. + +This method takes a web element as the sole argument. + +Regardless of whether the element is above or below the current viewscreen, +the viewport will be scrolled so the bottom of the element is at the bottom of the screen. + +{{< tabpane disableCodeBlock=true height="5">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L17-L20" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L11-L14" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount from element - -Scrolls to the element by scrolling the viewport. This way the element is at the bottom. -Scrolls the viewport further by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromElement { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.linkText("Go To Page 2")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -element = driver.find_element(By.LINK_TEXT, "Go To Page 2") - -ActionChains(driver).scroll(0, 0, 0, 300, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:link_text, 'Go To Page 2') - driver.action.scroll_to(element, 0, 300).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/scrollByAmount.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.linkText("Go To Page 2")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll by given amount + +This is the second most common scenario for scrolling. Pass in an delta x and a delta y value for how much to scroll +in the right and down directions. Negative values represent left and up, respectively. + +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L29-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L22-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L31-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L20-L24" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll by given amount - -Scrolls the viewport by the given amount i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromViewPort { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 200, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -ActionChains(driver).scroll(0, 0, 0, 200).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - - driver.action.scroll_by(0, 200).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromViewport() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 500, height: 400 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - - await driver.actions().scroll(0, 0, 0, 200, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 200, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element by a given amount + +This scenario is effectively a combination of the above two methods. + +To execute this use the "Scroll From" method, which takes 3 arguments. +The first represents the origination point, which we designate as the element, +and the second two are the delta x and delta y values. + +If the element is out of the viewport, +it will be scrolled to the bottom of the screen, then the page will be scrolled by the provided +delta x and delta y values. + +{{< tabpane disableCodeBlock=true height="8" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L42-L46" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L35-L39" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L46-L53" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L32-L36" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## Scroll from a offset of origin (viewport) by given amount - -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as viewport, the origin offset is calculated from the upper left corner of the viewport. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginViewportByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(600, 600)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(20, - 200, - 0, - -50, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(600, 600) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(20, 200, 0, -50).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(600, 600) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(20, 200) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 600, height: 600 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(20, 200, 0, -50, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(600, 600) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 20, - 200, - 0, - -50, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element with an offset + +This scenario is used when you need to scroll only a portion of the screen, and it is outside the viewport. +Or is inside the viewport and the portion of the screen that must be scrolled +is a known offset away from a specific element. + +This uses the "Scroll From" method again, and in addition to specifying the element, +an offset is specified to indicate the origin point of the scroll. The offset is +calculated from the center of the provided element. + +If the element is out of the viewport, +it first will be scrolled to the bottom of the screen, then the origin of the scroll will be determined +by adding the offset to the coordinates of the center of the element, and finally +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the center of the element falls outside of the viewport, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="10">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L57-L61" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L50-L54" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L66-L75" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L46-L50" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} ## Scroll from a offset of origin (element) by given amount -The origin is the where the cursor is placed before the scroll is executed. -For example, the position on the screen where the cursor is before scrolling a mouse wheel. -For origin as element, the origin offset is calculated from the center of the element. -Starting from this origin, the viewport is scrolled by the given amount -i.e. horizontal and vertical offsets. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginElementByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - WebElement submit = driver.findElement(By.id("submitbtn")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") -submit = driver.find_element(By.ID, "submitbtn") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(0, -50, 0, -50, origin=submit).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - submit = driver.find_element(:id, 'submitbtn') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(submit, 0, -50) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - submit = await driver.findElement(By.id('submitbtn')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(0, -50, 0, -50, submit).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val submit = driver.findElement(By.id("submitbtn")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +The final scenario is used when you need to scroll only a portion of the screen, +and it is already inside the viewport. + +This uses the "Scroll From" method again, but the viewport is designated instead +of an element. An offset is specified from the upper left corner of the +current viewport. After the origin point is determined, +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the upper left corner of the viewport falls outside of the screen, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="9" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L73-L76" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L68-L70" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L89-L97" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L62-L64" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/actions_api/wheel.zh-cn.md b/website_and_docs/content/documentation/webdriver/actions_api/wheel.zh-cn.md index 45aa37e1fee0..c13d3e0ec437 100644 --- a/website_and_docs/content/documentation/webdriver/actions_api/wheel.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/actions_api/wheel.zh-cn.md @@ -1,621 +1,176 @@ --- -title: "滚轮操作" -linkTitle: "滚轮" +title: "Scroll wheel actions" +linkTitle: "Wheel" weight: 6 description: > - 用于与网页交互的滚轮输入设备的呈现. + A representation of a scroll wheel input device for interacting with a web page. --- -## 滚动到元素 - -通过滚动可视区域移动到元素. -使得元素位于底部. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollToElement { - - public static void main(String[] args) { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.id("closepopup")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") -element = driver.find_element(By.ID, "closepopup") - -ActionChains(driver).scroll(0, 0, 0, 0, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -// This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:id, 'closepopup') - driver.action.scroll_to(element).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/wheelScrollToElement.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.id("closepopup")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 0, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +{{< badge version="4.2" >}} +{{< badge browser=Chromium wpt="perform_actions/wheel.py" >}} + +There are 5 scenarios for scrolling on a page. + +## Scroll to element + +This is the most common scenario. Unlike traditional click and send keys methods, +the actions class does not automatically scroll the target element into view, +so this method will need to be used if elements are not already inside the viewport. + +This method takes a web element as the sole argument. + +Regardless of whether the element is above or below the current viewscreen, +the viewport will be scrolled so the bottom of the element is at the bottom of the screen. + +{{< tabpane disableCodeBlock=true height="5">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L17-L20" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L11-L14" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L17-L20" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L9-L12" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## 基于元素定量滚动 - -通过滚动可视区域移动到元素. -使得元素位于底部. -将可视区域按照进给定的量一步滚动, -例如水平和垂直偏移. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromElement { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement element = driver.findElement(By.linkText("Go To Page 2")); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -element = driver.find_element(By.LINK_TEXT, "Go To Page 2") - -ActionChains(driver).scroll(0, 0, 0, 300, origin=element).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - element = driver.find_element(:link_text, 'Go To Page 2') - driver.action.scroll_to(element, 0, 300).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" disableCodeBlock=true >}} - {{< gh-codeblock path="/examples/javascript/actionsApi/wheel/scrollByAmount.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val element = driver.findElement(By.linkText("Go To Page 2")) - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 300, - PointerInput.Origin.fromElement(element) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll by given amount + +This is the second most common scenario for scrolling. Pass in an delta x and a delta y value for how much to scroll +in the right and down directions. Negative values represent left and up, respectively. + +{{< tabpane disableCodeBlock=true height="6">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L29-L33" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L22-L26" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L31-L35" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L20-L24" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## 定量滚动 - -将可视区域按照进给定的量一步滚动, -例如水平和垂直偏移. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollByGivenAmountFromViewPort { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(500, 400)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - - Actions actions = new Actions(driver); - actions.scroll(0, - 0, - 0, - 200, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains - -driver = webdriver.Chrome() -driver.set_window_size(500, 400) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -ActionChains(driver).scroll(0, 0, 0, 200).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(500, 400) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - - driver.action.scroll_by(0, 200).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromViewport() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 500, height: 400 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - - await driver.actions().scroll(0, 0, 0, 200, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(500, 400) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val actions = Actions(driver) - actions.scroll( - 0, - 0, - 0, - 200, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element by a given amount + +This scenario is effectively a combination of the above two methods. + +To execute this use the "Scroll From" method, which takes 3 arguments. +The first represents the origination point, which we designate as the element, +and the second two are the delta x and delta y values. + +If the element is out of the viewport, +it will be scrolled to the bottom of the screen, then the page will be scrolled by the provided +delta x and delta y values. + +{{< tabpane disableCodeBlock=true height="8" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L42-L46" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L35-L39" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L46-L53" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L32-L36" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## 基于原点(可视区域)定量偏移滚动 - -原点是执行滚动之前光标所在的位置. -例如,滚动鼠标滚轮之前光标在屏幕上的位置. -对于"可视区域作为原点", -从可视区域的左上角计算原点偏移. -从该原点开始, -可视区域将按定量滚动, -例如水平和垂直偏移. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.Dimension; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginViewportByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.manage().window().setSize(new Dimension(600, 600)); - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(20, - 200, - 0, - -50, - PointerInput.Origin.viewport()) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.set_window_size(600, 600) -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(20, 200, 0, -50).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - target_size = Selenium::WebDriver::Dimension.new(600, 600) - driver.manage.window.size = target_size - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.viewport(20, 200) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Origin } = require('selenium-webdriver'); -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.manage().window().setRect({ width: 600, height: 600 }); - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(20, 200, 0, -50, Origin.VIEWPORT).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.Dimension -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver.manage().window().size = Dimension(600, 600) - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 20, - 200, - 0, - -50, - PointerInput.Origin.viewport() - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} +## Scroll from an element with an offset + +This scenario is used when you need to scroll only a portion of the screen, and it is outside the viewport. +Or is inside the viewport and the portion of the screen that must be scrolled +is a known offset away from a specific element. + +This uses the "Scroll From" method again, and in addition to specifying the element, +an offset is specified to indicate the origin point of the scroll. The offset is +calculated from the center of the provided element. + +If the element is out of the viewport, +it first will be scrolled to the bottom of the screen, then the origin of the scroll will be determined +by adding the offset to the coordinates of the center of the element, and finally +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the center of the element falls outside of the viewport, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="10">}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L57-L61" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L50-L54" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L66-L75" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L46-L50" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} {{< /tabpane >}} -## 基于原点(元素)定量偏移滚动 - -原点是执行滚动之前光标所在的位置. -例如,滚动鼠标滚轮之前光标在屏幕上的位置. -对于"元素作为原点", -原点偏移是从元素的中心计算的. -从该原点开始, -可视区域将按定量滚动, -例如水平和垂直偏移. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.interactions.PointerInput; - -public class scrollFromOffsetOfOriginElementByGivenAmount { - - public static void main(String[] args) throws Exception { - WebDriver driver = new ChromeDriver(); - try { - driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html"); - WebElement textarea = driver.findElement(By.name("textarea")); - WebElement submit = driver.findElement(By.id("submitbtn")); - - Actions actions = new Actions(driver); - - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); - - actions.scroll(0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit)) - .perform(); - } finally { - driver.quit(); - } - } -} - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By - -driver = webdriver.Chrome() -driver.get("https://crossbrowsertesting.github.io/selenium_example_page.html") - -textarea = driver.find_element(By.NAME, "textarea") -submit = driver.find_element(By.ID, "submitbtn") - -textarea.send_keys("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") - -ActionChains(driver).scroll(0, -50, 0, -50, origin=submit).perform() - -driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} - // This feature is not implemented - Help us by sending a pr to implement this feature - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -begin - driver = Selenium::WebDriver.for :chrome - driver.get 'https://crossbrowsertesting.github.io/selenium_example_page.html' - textarea = driver.find_element(:name, 'textarea') - submit = driver.find_element(:id, 'submitbtn') - - textarea.send_keys 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' - - origin = Selenium::WebDriver::WheelActions::ScrollOrigin.element(submit, 0, -50) - driver.action.scroll(0, -50, origin: origin).perform -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const { Builder, By } = require('selenium-webdriver'); - -(async function scollByGivenAmountFromElement() { - let driver = await new Builder().forBrowser('chrome').build(); - - try { - await driver.get('https://crossbrowsertesting.github.io/selenium_example_page.html'); - textarea = await driver.findElement(By.name('textarea')); - submit = await driver.findElement(By.id('submitbtn')); - - await textarea.sendKeys('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + - 'cccccccccccccccccccccccccccccccc' + - 'dddddddddddddddddddddddddddddddd' + - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'); - - await driver.actions().scroll(0, -50, 0, -50, submit).perform(); - } - finally { - await driver.quit(); - } -})(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.By -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.interactions.Actions -import org.openqa.selenium.interactions.PointerInput - -fun main() { - val driver: WebDriver = ChromeDriver() - try { - driver["https://crossbrowsertesting.github.io/selenium_example_page.html"] - val textarea = driver.findElement(By.name("textarea")) - val submit = driver.findElement(By.id("submitbtn")) - val actions = Actions(driver) - textarea.sendKeys( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + - "cccccccccccccccccccccccccccccccc" + - "dddddddddddddddddddddddddddddddd" + - "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - ) - actions.scroll( - 0, - -50, - 0, - -50, - PointerInput.Origin.fromElement(submit) - ).perform() - } finally { - driver.quit() - } -} - {{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +## Scroll from a offset of origin (element) by given amount + +The final scenario is used when you need to scroll only a portion of the screen, +and it is already inside the viewport. + +This uses the "Scroll From" method again, but the viewport is designated instead +of an element. An offset is specified from the upper left corner of the +current viewport. After the origin point is determined, +the page will be scrolled by the provided delta x and delta y values. + +Note that if the offset from the upper left corner of the viewport falls outside of the screen, +it will result in an exception. + +{{< tabpane disableCodeBlock=true height="9" >}} + {{< tab header="Java" >}} + {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/actions_api/WheelTest.java#L73-L76" >}} + {{< /tab >}} + {{< tab header="Python" >}} + {{< gh-codeblock path="examples/python/tests/actions_api/test_wheel.py#L68-L70" >}} + {{< /tab >}} + {{< tab header="CSharp" >}} + {{< gh-codeblock path="examples/dotnet/SeleniumDocs/ActionsAPI/WheelTest.cs#L89-L97" >}} + {{< /tab >}} + {{< tab header="Ruby" >}} + {{< gh-codeblock path="examples/ruby/spec/actions_api/wheel_spec.rb#L62-L64" >}} + {{< /tab >}} + {{< tab header="JavaScript" >}} + Not implemented yet + {{< /tab >}} + {{< tab header="Kotlin" >}} + Not implemented yet + {{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/layouts/partials/badge.html b/website_and_docs/layouts/partials/badge.html new file mode 100644 index 000000000000..d2adc31513b9 --- /dev/null +++ b/website_and_docs/layouts/partials/badge.html @@ -0,0 +1,3 @@ +

+{{ .text }}

diff --git a/website_and_docs/layouts/shortcodes/badge.html b/website_and_docs/layouts/shortcodes/badge.html new file mode 100644 index 000000000000..46e9c148f19d --- /dev/null +++ b/website_and_docs/layouts/shortcodes/badge.html @@ -0,0 +1,15 @@ +{{ $version := .Get "version" }} +{{ $browser := .Get "browser" }} +{{ $wpt := .Get "wpt" }} + +{{ if $version }} +{{ $href := printf "https://github.com/SeleniumHQ/selenium/releases/tag/selenium-%s.0" $version }} +{{ $title := printf "This code requires Selenium v%s or greater" $version }} +{{ $text := printf "Selenium v%s" $version }} +{{ partial "badge.html" (dict "type" "version" "title" $title "text" $text "href" $href) }} +{{ else }} +{{ $href := printf "https://wpt.fyi/results/webdriver/tests/%s" $wpt }} +{{ $title := "This code does not work in all browsers" }} +{{ $text := printf "%s Only" $browser }} +{{ partial "badge.html" (dict "type" "browser" "title" $title "text" $text "href" $href) }} +{{ end }} diff --git a/website_and_docs/layouts/shortcodes/tabpane.html b/website_and_docs/layouts/shortcodes/tabpane.html index 3215be43f3f6..d6536a8e321d 100644 --- a/website_and_docs/layouts/shortcodes/tabpane.html +++ b/website_and_docs/layouts/shortcodes/tabpane.html @@ -19,7 +19,8 @@ -
+{{- $height := default "auto" ($.Get "height") -}} +
{{- range $index, $element := $.Scratch.Get "tabs" -}} {{- $tabid := printf "tabs-%v-%v-tab" $.Ordinal $index | anchorize -}} {{- $entryid := printf "tabs-%v-%v" $.Ordinal $index | anchorize -}} @@ -28,7 +29,7 @@ id="{{ $entryid }}" role="tabpanel" aria-labelled-by="{{ $tabid }}"> {{ if $.Get "disableCodeBlock" }} -
+
{{- index . "content" | markdownify -}}
{{ else }}