Path: blob/trunk/dotnet/test/common/Interactions/CombinedInputActionsTest.cs
2868 views
// <copyright file="CombinedInputActionsTest.cs" company="Selenium Committers"> // Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // </copyright> using NUnit.Framework; using OpenQA.Selenium.Environment; using System; using System.Collections.ObjectModel; using System.Drawing; using System.Runtime.InteropServices; namespace OpenQA.Selenium.Interactions; [TestFixture] public class CombinedInputActionsTest : DriverTestFixture { [SetUp] public void Setup() { // new Actions(driver).SendKeys(Keys.Null).Perform(); IActionExecutor actionExecutor = driver as IActionExecutor; if (actionExecutor != null) { actionExecutor.ResetInputState(); } } [TearDown] public void ReleaseModifierKeys() { // new Actions(driver).SendKeys(Keys.Null).Perform(); IActionExecutor actionExecutor = driver as IActionExecutor; if (actionExecutor != null) { actionExecutor.ResetInputState(); } } [Test] [IgnoreBrowser(Browser.IE, "IE reports [0,0] as location for <option> elements")] public void PlainClickingOnMultiSelectionList() { driver.Url = formSelectionPage; ReadOnlyCollection<IWebElement> options = driver.FindElements(By.TagName("option")); Actions actionBuider = new Actions(driver); IAction selectThreeOptions = actionBuider.Click(options[1]) .Click(options[2]) .Click(options[3]).Build(); selectThreeOptions.Perform(); IWebElement showButton = driver.FindElement(By.Name("showselected")); showButton.Click(); IWebElement resultElement = driver.FindElement(By.Id("result")); Assert.That(resultElement.Text, Is.EqualTo("cheddar"), "Should have picked the third option only."); } [Test] public void ShouldAllowSettingActivePointerWithKeyBoardActions() { driver.Url = loginPage; IWebElement username = driver.FindElement(By.Id("username-field")); IWebElement password = driver.FindElement(By.Id("password-field")); IWebElement login = driver.FindElement(By.Id("login-form-submit")); Actions actionProvider = new Actions(driver); IAction loginAction = actionProvider .SendKeys(username, "username") .SendKeys(password, "password") .SetActivePointer(PointerKind.Mouse, "test") .MoveToElement(login) .Click() .Build(); loginAction.Perform(); IAlert alert = driver.SwitchTo().Alert(); Assert.That(alert.Text, Is.EqualTo("You have successfully logged in.")); alert.Accept(); } [Test] [IgnoreBrowser(Browser.IE, "IE reports [0,0] as location for <option> elements")] public void ShiftClickingOnMultiSelectionList() { driver.Url = formSelectionPage; ReadOnlyCollection<IWebElement> options = driver.FindElements(By.TagName("option")); Actions actionBuider = new Actions(driver); IAction selectThreeOptions = actionBuider.Click(options[1]) .KeyDown(Keys.Shift) .Click(options[2]) .Click(options[3]) .KeyUp(Keys.Shift).Build(); selectThreeOptions.Perform(); IWebElement showButton = driver.FindElement(By.Name("showselected")); showButton.Click(); IWebElement resultElement = driver.FindElement(By.Id("result")); Assert.That(resultElement.Text, Is.EqualTo("roquefort parmigiano cheddar"), "Should have picked the last three options."); } [Test] [IgnoreBrowser(Browser.IE, "IE reports [0,0] as location for <option> elements")] public void ControlClickingOnMultiSelectionList() { string controlModifier = Keys.Control; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { controlModifier = Keys.Command; } driver.Url = formSelectionPage; ReadOnlyCollection<IWebElement> options = driver.FindElements(By.TagName("option")); Actions actionBuider = new Actions(driver); IAction selectThreeOptions = actionBuider.Click(options[1]) .KeyDown(controlModifier) .Click(options[3]) .KeyUp(controlModifier).Build(); selectThreeOptions.Perform(); IWebElement showButton = driver.FindElement(By.Name("showselected")); showButton.Click(); IWebElement resultElement = driver.FindElement(By.Id("result")); Assert.That(resultElement.Text, Is.EqualTo("roquefort cheddar"), "Should have picked the first and third options."); } [Test] public void ControlClickingOnCustomMultiSelectionList() { string controlModifier = Keys.Control; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { controlModifier = Keys.Command; } driver.Url = selectableItemsPage; IWebElement reportingElement = driver.FindElement(By.Id("infodiv")); Assert.That(reportingElement.Text, Is.EqualTo("no info")); ReadOnlyCollection<IWebElement> listItems = driver.FindElements(By.TagName("li")); IAction selectThreeItems = new Actions(driver).KeyDown(controlModifier) .Click(listItems[1]) .Click(listItems[3]) .Click(listItems[5]) .KeyUp(controlModifier).Build(); selectThreeItems.Perform(); Assert.That(reportingElement.Text, Is.EqualTo("#item2 #item4 #item6")); // Now click on another element, make sure that's the only one selected. new Actions(driver).Click(listItems[6]).Build().Perform(); Assert.That(reportingElement.Text, Is.EqualTo("#item7")); } [Test] public void CanMoveMouseToAnElementInAnIframeAndClick() { driver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("click_tests/click_in_iframe.html"); WaitFor<IWebElement>(() => driver.FindElement(By.Id("ifr")), "Did not find element"); driver.SwitchTo().Frame("ifr"); try { IWebElement link = driver.FindElement(By.Id("link")); new Actions(driver) .MoveToElement(link) .Click() .Perform(); WaitFor(() => driver.Title == "Submitted Successfully!", "Browser title not correct"); } finally { driver.SwitchTo().DefaultContent(); } } [Test] public void CanClickOnLinks() { this.NavigateToClicksPageAndClickLink(); } [Test] public void CanClickOnLinksWithAnOffset() { driver.Url = clicksPage; WaitFor(() => { return driver.FindElement(By.Id("normal")); }, "Could not find element with id 'normal'"); IWebElement link = driver.FindElement(By.Id("normal")); new Actions(driver) .MoveToElement(link, 1, 1) .Click() .Perform(); WaitFor(() => { return driver.Title == "XHTML Test Page"; }, "Browser title is not 'XHTML Test Page'"); } [Test] public void ClickAfterMoveToAnElementWithAnOffsetShouldUseLastMousePosition() { driver.Url = clickEventPage; IWebElement element = driver.FindElement(By.Id("eventish")); Point location = element.Location; Size size = element.Size; new Actions(driver) .MoveToElement(element, 20 - size.Width / 2, 10 - size.Height / 2) .Click() .Perform(); WaitFor<IWebElement>(() => driver.FindElement(By.Id("pageX")), "Did not find element with ID pageX"); int x = Convert.ToInt16(Math.Round(Convert.ToDouble(driver.FindElement(By.Id("pageX")).Text))); int y = Convert.ToInt16(Math.Round(Convert.ToDouble(driver.FindElement(By.Id("pageY")).Text))); Assert.That(FuzzyPositionMatching(location.X + 20, location.Y + 10, string.Format("{0},{1}", x, y)), Is.True); } /** * This test demonstrates the following problem: When the representation of * the mouse in the driver keeps the wrong state, mouse movement will end * up at the wrong coordinates. */ [Test] public void MouseMovementWorksWhenNavigatingToAnotherPage() { NavigateToClicksPageAndClickLink(); IWebElement linkId = driver.FindElement(By.Id("linkId")); new Actions(driver) .MoveToElement(linkId, 1, 1) .Click() .Perform(); WaitFor(() => { return driver.Title == "We Arrive Here"; }, "Browser title is not 'We Arrive Here'"); } [Test] public void ChordControlCutAndPaste() { string controlModifier = Keys.Control; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { controlModifier = Keys.Command; } driver.Url = javascriptPage; IWebElement element = driver.FindElement(By.Id("keyReporter")); // Must scroll element into view for W3C-compliant drivers. ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView()", element); new Actions(driver) .SendKeys(element, "abc def") .Perform(); Assert.That(element.GetAttribute("value"), Is.EqualTo("abc def")); //TODO: Figure out why calling sendKey(Key.CONTROL + "a") and then //sendKeys("x") does not work on Linux. new Actions(driver).KeyDown(controlModifier) .SendKeys("a" + "x") .Perform(); // Release keys before next step. new Actions(driver).SendKeys(Keys.Null).Perform(); Assert.That(element.GetAttribute("value"), Is.Empty); new Actions(driver).KeyDown(controlModifier) .SendKeys("v") .SendKeys("v") .Perform(); new Actions(driver).SendKeys(Keys.Null).Perform(); Assert.That(element.GetAttribute("value"), Is.EqualTo("abc defabc def")); } [Test] [IgnoreBrowser(Browser.IE, "Edge in IE Mode does not properly handle multiple windows")] [NeedsFreshDriver(IsCreatedBeforeTest = true)] public void CombiningShiftAndClickResultsInANewWindow() { driver.Url = linkedImage; IWebElement link = driver.FindElement(By.Id("link")); string originalTitle = driver.Title; new Actions(driver) .MoveToElement(link) .KeyDown(Keys.Shift) .Click() .KeyUp(Keys.Shift) .Perform(); WaitFor(() => { return driver.WindowHandles.Count > 1; }, "Did not receive new window"); Assert.That(driver.WindowHandles, Has.Exactly(2).Items, "Should have opened a new window."); Assert.That(driver.Title, Is.EqualTo(originalTitle), "Should not have navigated away."); string originalHandle = driver.CurrentWindowHandle; foreach (string newHandle in driver.WindowHandles) { if (newHandle != originalHandle) { driver.SwitchTo().Window(newHandle); driver.Close(); } } driver.SwitchTo().Window(originalHandle); } [Test] [IgnoreBrowser(Browser.IE, "Edge in IE Mode does not properly handle multiple windows")] public void HoldingDownShiftKeyWhileClicking() { driver.Url = clickEventPage; IWebElement toClick = driver.FindElement(By.Id("eventish")); new Actions(driver).MoveToElement(toClick).KeyDown(Keys.Shift).Click().KeyUp(Keys.Shift).Perform(); IWebElement shiftInfo = WaitFor(() => { return driver.FindElement(By.Id("shiftKey")); }, "Could not find element with id 'shiftKey'"); Assert.That(shiftInfo.Text, Is.EqualTo("true")); } [Test] public void CanClickOnSuckerFishStyleMenu() { driver.Url = javascriptPage; // Move to a different element to make sure the mouse is not over the // element with id 'item1' (from a previous test). new Actions(driver).MoveToElement(driver.FindElement(By.Id("dynamo"))).Build().Perform(); IWebElement element = driver.FindElement(By.Id("menu1")); IWebElement target = driver.FindElement(By.Id("item1")); Assert.That(target.Text, Is.Empty); ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.background = 'green'", element); new Actions(driver).MoveToElement(element).Build().Perform(); // Intentionally wait to make sure hover persists. System.Threading.Thread.Sleep(2000); target.Click(); IWebElement result = driver.FindElement(By.Id("result")); WaitFor(() => { return result.Text.Contains("item 1"); }, "Result element does not contain text 'item 1'"); } [Test] public void CanClickOnSuckerFishMenuItem() { driver.Url = javascriptPage; // Move to a different element to make sure the mouse is not over the // element with id 'item1' (from a previous test). new Actions(driver).MoveToElement(driver.FindElement(By.Id("dynamo"))).Build().Perform(); IWebElement element = driver.FindElement(By.Id("menu1")); new Actions(driver).MoveToElement(element).Build().Perform(); IWebElement target = driver.FindElement(By.Id("item1")); Assert.That(target.Displayed, "Target element was not displayed"); target.Click(); IWebElement result = driver.FindElement(By.Id("result")); WaitFor(() => { return result.Text.Contains("item 1"); }, "Result element does not contain text 'item 1'"); } [Test] public void PerformsPause() { DateTime start = DateTime.Now; new Actions(driver).Pause(TimeSpan.FromMilliseconds(1200)).Build().Perform(); Assert.That(DateTime.Now - start > TimeSpan.FromMilliseconds(1200), Is.True); } [Test] public void ShouldHandleClashingDeviceNamesGracefully() { var actionsWithPointer = new Actions(driver) .SetActivePointer(PointerKind.Mouse, "test") .Click(); Assert.That(() => { actionsWithPointer.SetActiveWheel("test"); }, Throws.InvalidOperationException.With.Message.EqualTo("Device under the name \"test\" is not a wheel. Actual input type: Pointer")); var actionsWithKeyboard = new Actions(driver) .SetActiveKeyboard("test") .KeyDown(Keys.Shift).KeyUp(Keys.Shift); Assert.That(() => { actionsWithKeyboard.SetActivePointer(PointerKind.Pen, "test"); }, Throws.InvalidOperationException.With.Message.EqualTo("Device under the name \"test\" is not a pointer. Actual input type: Key")); var actionsWithWheel = new Actions(driver) .SetActiveWheel("test") .ScrollByAmount(0, 0); Assert.That(() => { actionsWithWheel.SetActiveKeyboard("test"); }, Throws.InvalidOperationException.With.Message.EqualTo("Device under the name \"test\" is not a keyboard. Actual input type: Wheel")); } private bool FuzzyPositionMatching(int expectedX, int expectedY, string locationTuple) { string[] splitString = locationTuple.Split(','); int gotX = int.Parse(splitString[0].Trim()); int gotY = int.Parse(splitString[1].Trim()); // Everything within 5 pixels range is OK const int ALLOWED_DEVIATION = 5; return Math.Abs(expectedX - gotX) < ALLOWED_DEVIATION && Math.Abs(expectedY - gotY) < ALLOWED_DEVIATION; } private void NavigateToClicksPageAndClickLink() { driver.Url = clicksPage; WaitFor(() => { return driver.FindElement(By.Id("normal")); }, "Could not find element with id 'normal'"); IWebElement link = driver.FindElement(By.Id("normal")); new Actions(driver) .Click(link) .Perform(); WaitFor(() => { return driver.Title == "XHTML Test Page"; }, "Browser title is not 'XHTML Test Page'"); } }