blob: 0345118187f346f31b1682eeb5845d385e7dc76e [file] [log] [blame] [edit]
// <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'");
}
}