Skip to content

Commit

Permalink
Merged PR 824580: Add unit test for mouse interaction and dynamic tou…
Browse files Browse the repository at this point in the history
…ch API endpoints in WebDriverAPI test project

Add unit test for mouse interaction API endpoints in WebDriverAPI test project
Add unit test for dynamic touch API endpoints such as touch/down, move, and up
Replace PressKey C# commands in WebDriverAPI SendKeys test to avoid confusion
Enhance unit test for active element to cover application not in focus scenario
Adjust various test delay and implicit timeout in WebDriverAPI test
Fix inaccurate comments and variable names
Fix minor formatting and update README.md
  • Loading branch information
timotiusmargo committed Sep 8, 2017
2 parents 945e7ac + 26133e4 commit ec19c10
Show file tree
Hide file tree
Showing 17 changed files with 317 additions and 77 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ This Github project provides:

**Videos about WinAppDriver**

<https://channel9.msdn.com/events/Connect/2016/202> - 8 minutes overview with demos
<https://channel9.msdn.com/events/Build/2016/Panel-Engineering-Quality> - Session with Jonathan Lipps
<https://channel9.msdn.com/events/Build/2016/P499> - Longer discussion
<https://www.youtube.com/watch?v=XAJVpvaEchY> - C# demo with calculator sample walkthrough
- <https://channel9.msdn.com/events/Connect/2016/202> - 8 minutes overview with demos
- <https://channel9.msdn.com/events/Build/2016/Panel-Engineering-Quality> - Session with Jonathan Lipps
- <https://channel9.msdn.com/events/Build/2016/P499> - Longer discussion
- <https://www.youtube.com/watch?v=XAJVpvaEchY> - C# demo with calculator sample walkthrough


## Getting Started
Expand Down Expand Up @@ -42,7 +42,7 @@ WinAppDriver.exe 10.0.0.10 4723/wd/hub
### Running on a Remote Machine

Windows Application Driver can run remotely on any Windows 10 machine with `WinAppDriver.exe` installed and running. This *test machine* can then serve any JSON wire protocol commands coming from the *test runner* remotely through the network. Below are the steps to the one time setup for the *test machine* to receive inbound requests:
Windows Application Driver can run remotely on any Windows 10 machine with `WinAppDriver.exe` installed and running. This *test machine* can then serve any JSON wire protocol commands coming from the *test runner* remotely through the network. Below are the steps to the one-time setup for the *test machine* to receive inbound requests:

1. On the *test machine* you want to run the test application on, open up **Windows Firewall with Advanced Security**
- Select **Inbound Rules** -> **New Rule...**
Expand All @@ -55,7 +55,7 @@ Windows Application Driver can run remotely on any Windows 10 machine with `WinA
2. Run `ipconfig.exe` to determine your machine's local IP address
> **Note**: Setting `*` as the IP address command line option will cause it to bind to all bound IP addresses on the machine
3. Run `WinAppDriver.exe` as **administrator** with command line arguments as seen above specifying local IP and port
4. On the *test runner* machine where the runner and scripts are, update the the test script to point to the IP of the remote *test machine*
4. On the *test runner* machine where the runner and scripts are, update the test script to point to the IP of the remote *test machine*
5. Execute the test script on the *test runner* to perform the test actions against the test application on the remote *test machine*.


Expand Down Expand Up @@ -243,13 +243,14 @@ Windows Application Driver supports various locators to find UI element in the a
| FindElementById | id | RuntimeId (decimal) | 42.333896.3.1 |
| FindElementByName | name | Name | Calculator |
| FindElementByTagName | tag name | LocalizedControlType (upper camel case) | Text |
| FindElementByXPath | xpath | Any | //Button[0] |


## Inspecting UI Elements

The latest Microsoft Visual Studio version by default includes the Windows SDK with a great tool to inspect the application you are testing. This tool allows you to see every UI element/node that you can query using Windows Application Driver. This **inspect.exe** tool can be found under the Windows SDK folder which is typically `C:\Program Files (x86)\Windows Kits\10\bin\x86`

More detailed documentation on Inspect is available on MSDN <"https://msdn.microsoft.com/library/windows/desktop/dd318521(v=vs.85).aspx">.
More detailed documentation on Inspect is available on MSDN <https://msdn.microsoft.com/library/windows/desktop/dd318521(v=vs.85).aspx>.


## Using Appium
Expand Down
1 change: 1 addition & 0 deletions Samples/C#/AlarmClockTest/ScenarioStopwatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public void StopwatchStart()
stopwatchPlayPauseButton.Click();
Assert.AreEqual("Pause", stopwatchPlayPauseButton.Text);
Assert.IsFalse(stopwatchResetButton.Displayed);
Thread.Sleep(TimeSpan.FromSeconds(1));

// Pause the stopwatch and verify that stopwatchPlayPauseButton switched back from Pause to Start while stopwatchResetButton is enabled
stopwatchPlayPauseButton.Click();
Expand Down
4 changes: 2 additions & 2 deletions Tests/WebDriverAPI/AppSessionBase/AlarmClockBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ public static void Setup(TestContext context)
Assert.IsNotNull(session);
Assert.IsNotNull(session.SessionId);

// Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1.5));
// Set implicit timeout to 2.5 seconds to make element search to retry every 500 ms for at most five times
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(2.5));

// Initialize touch screen object
touchScreen = new RemoteTouchScreen(session);
Expand Down
1 change: 0 additions & 1 deletion Tests/WebDriverAPI/AppiumAppClose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ private void CloseApplication(string applicationId)

session.CloseApp();

Thread.Sleep(TimeSpan.FromSeconds(2));
Assert.IsNotNull(session.SessionId);
Assert.AreEqual(0, session.WindowHandles.Count);

Expand Down
19 changes: 18 additions & 1 deletion Tests/WebDriverAPI/ElementActive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,27 @@ public static void ClassCleanup()
}

[TestMethod]
public void GetActiveElement()
public void GetActiveElement_Empty()
{
// Set focus on the application by switching window to itself
session.SwitchTo().Window(session.CurrentWindowHandle);

// Verify that active element id is not empty when the current session/application owns the focus
WindowsElement activeElement = session.SwitchTo().ActiveElement() as WindowsElement;
Assert.IsNotNull(activeElement);
Assert.AreNotEqual(string.Empty, activeElement.Id);

// Open Windows start menu to deliberately take focus away from the calculator
session.Keyboard.PressKey(OpenQA.Selenium.Keys.Meta + OpenQA.Selenium.Keys.Meta);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));

// Verify that active element id is now empty as the current session/application no longer owns the focus
activeElement = session.SwitchTo().ActiveElement() as WindowsElement;
Assert.IsNotNull(activeElement);
Assert.AreEqual(string.Empty, activeElement.Id);

// Dismiss start menu
session.Keyboard.PressKey(OpenQA.Selenium.Keys.Escape);
}

[TestMethod]
Expand Down
1 change: 1 addition & 0 deletions Tests/WebDriverAPI/ElementDisplayed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public void GetElementDisplayedState()
// Navigate to Stopwatch tab
WindowsElement stopwatchPivotItem = session.FindElementByAccessibilityId("StopwatchPivotItem");
stopwatchPivotItem.Click();
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
WindowsElement stopwatchStartButton = session.FindElementByName("Start");
Assert.IsTrue(stopwatchStartButton.Displayed);
Assert.IsFalse(addAlarmButton.Displayed);
Expand Down
4 changes: 2 additions & 2 deletions Tests/WebDriverAPI/ElementName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public void GetElementTagName()
WindowsElement header = session.FindElementByAccessibilityId("AppNameTitle");
Assert.AreEqual("ControlType.Text", header.TagName);

WindowsElement plusButton = session.FindElementByAccessibilityId("NavButton");
Assert.AreEqual("ControlType.Button", plusButton.TagName);
WindowsElement navButton = session.FindElementByAccessibilityId("NavButton");
Assert.AreEqual("ControlType.Button", navButton.TagName);
}

[TestMethod]
Expand Down
2 changes: 1 addition & 1 deletion Tests/WebDriverAPI/ElementSendKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public override void TestInit()
{
base.TestInit();
alarmTabElement.FindElementByAccessibilityId("AddAlarmButton").Click();
Thread.Sleep(TimeSpan.FromSeconds(1));
Thread.Sleep(TimeSpan.FromSeconds(1.5));
alarmNameTextBox = session.FindElementByAccessibilityId("AlarmNameTextBox");
}

Expand Down
6 changes: 3 additions & 3 deletions Tests/WebDriverAPI/Forward.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ public void TestCleanup()
public void NavigateForward_Browser()
{
session = Utility.CreateNewSession(CommonTestSettings.EdgeAppId, "-private " + CommonTestSettings.EdgeAboutFlagsURL);
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1));
Thread.Sleep(TimeSpan.FromSeconds(2.5));
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(2));
Thread.Sleep(TimeSpan.FromSeconds(2));
var originalTitle = session.Title;
Assert.AreNotEqual(string.Empty, originalTitle);

// Navigate to different URLs
session.FindElementByAccessibilityId("addressEditBox").SendKeys(Keys.Alt + 'd' + Keys.Alt + CommonTestSettings.EdgeAboutTabsURL + Keys.Enter);
Thread.Sleep(TimeSpan.FromSeconds(1));
Thread.Sleep(TimeSpan.FromSeconds(2));
var newTitle = session.Title;
Assert.AreNotEqual(originalTitle, newTitle);

Expand Down
134 changes: 134 additions & 0 deletions Tests/WebDriverAPI/Mouse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//******************************************************************************
//
// Copyright (c) 2017 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using System.Threading;
using System.Drawing;
using System;

namespace WebDriverAPI
{
[TestClass]
public class Mouse : CalculatorBase
{
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
Setup(context);
}

[ClassCleanup]
public static void ClassCleanup()
{
TearDown();
}

[TestInitialize]
public virtual void TestInit()
{
// Set focus on the application by switching window to itself
session.SwitchTo().Window(session.CurrentWindowHandle);

// Restore the Calculator window if it is currently maximized
WindowsElement maximizeButton = session.FindElementByAccessibilityId("Maximize");
if (!maximizeButton.Text.Contains("Maximize"))
{
maximizeButton.Click();
}
}

[TestMethod]
public void MouseClick()
{
// Locate the calculatorResult element
WindowsElement calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
Assert.IsNotNull(calculatorResult);

// Implicitly invoke /session/:sessionId/moveto and /session/:sessionId/click
WindowsElement num8Button = session.FindElementByAccessibilityId("num8Button");
session.Mouse.Click(num8Button.Coordinates);
Assert.AreEqual("8", calculatorResult.Text.Replace("Display is", string.Empty).Trim());

// Explicitly invoke /session/:sessionId/moveto and then /session/:sessionId/click on the current position
WindowsElement clearButton = session.FindElementByAccessibilityId("clearButton");
session.Mouse.MouseMove(clearButton.Coordinates);
session.Mouse.Click(null);
Assert.AreEqual("0", calculatorResult.Text.Replace("Display is", string.Empty).Trim());

// Open a context menu on the application title bar to expose the context menu and verify that it contains minimize.
// The context menu is parented on the desktop instead of the application. Thus, a desktop session is used to find it.
// This command implicitly invoke /session/:sessionId/moveto and /session/:sessionId/click with button 2 parameter
WindowsElement appNameTitle = session.FindElementByAccessibilityId("AppNameTitle");
session.Mouse.ContextClick(appNameTitle.Coordinates);
Thread.Sleep(TimeSpan.FromSeconds(1.5));
WindowsDriver<WindowsElement> desktopSession = Utility.CreateNewSession(CommonTestSettings.DesktopAppId);
Assert.IsNotNull(desktopSession.FindElementByName("System").FindElementByName("Minimize"));
clearButton.Click(); // Dismiss the context menu
}

[TestMethod]
public void MouseDoubleClick()
{
WindowsElement maximizeButton = session.FindElementByAccessibilityId("Maximize");
Assert.IsNotNull(maximizeButton);

// Verify that the window is currently not maximized
Assert.IsTrue(maximizeButton.Text.Contains("Maximize"));

// Perform mouse double click on the title bar to maximize the Calculator window
WindowsElement appNameTitle = session.FindElementByAccessibilityId("AppNameTitle");
session.Mouse.MouseMove(appNameTitle.Coordinates);
session.Mouse.DoubleClick(null); // Pass null as this command omit the given parameter
Thread.Sleep(TimeSpan.FromSeconds(1));
Assert.IsFalse(maximizeButton.Text.Contains("Maximize"));

// Perform mouse double click on the title bar to restore the Calculator window
session.Mouse.MouseMove(appNameTitle.Coordinates);
session.Mouse.DoubleClick(null); // Pass null as this command omit the given parameter
Thread.Sleep(TimeSpan.FromSeconds(1));
Assert.IsTrue(maximizeButton.Text.Contains("Maximize"));
}

[TestMethod]
public void MouseDownMoveUp()
{
const int offset = 100;
WindowsElement appNameTitle = session.FindElementByAccessibilityId("AppNameTitle");
Assert.IsNotNull(appNameTitle);

// Save application window original position
Point originalPosition = session.Manage().Window.Position;
Assert.IsNotNull(originalPosition);

// Send mouse down, move, and up actions combination to perform a drag and drop
// action on the app title bar. These actions reposition Calculator window.
session.Mouse.MouseMove(appNameTitle.Coordinates);
session.Mouse.MouseDown(null); // Pass null as this command omit the given parameter
session.Mouse.MouseMove(appNameTitle.Coordinates, offset, offset);
session.Mouse.MouseUp(null); // Pass null as this command omit the given parameter
Thread.Sleep(TimeSpan.FromSeconds(1));

// Verify that application window is now re-positioned from the original location
Assert.AreNotEqual(originalPosition, session.Manage().Window.Position);
Assert.IsTrue(originalPosition.Y < session.Manage().Window.Position.Y);

// Restore application window original position
session.Manage().Window.Position = originalPosition;
Assert.AreEqual(originalPosition, session.Manage().Window.Position);
}
}
}
16 changes: 8 additions & 8 deletions Tests/WebDriverAPI/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ The test scenarios are written against Windows 10 built-in apps such as **Calcul
| POST | [/session/:sessionId/appium/app/launch ](./AppiumAppClose.cs) |
| POST | [/session/:sessionId/appium/app/close ](./AppiumAppLaunch.cs) |
| POST | [/session/:sessionId/back ](./Back.cs) |
| POST | /session/:sessionId/buttondown |
| POST | /session/:sessionId/buttonup |
| POST | /session/:sessionId/click |
| POST | /session/:sessionId/doubleclick |
| POST | [/session/:sessionId/buttondown ](./Mouse.cs) |
| POST | [/session/:sessionId/buttonup ](./Mouse.cs) |
| POST | [/session/:sessionId/click ](./Mouse.cs) |
| POST | [/session/:sessionId/doubleclick ](./Mouse.cs) |
| POST | [/session/:sessionId/element ](./Element.cs) |
| POST | [/session/:sessionId/elements ](./Elements.cs) |
| POST | [/session/:sessionId/element/active ](./ElementActive.cs) |
Expand All @@ -57,21 +57,21 @@ The test scenarios are written against Windows 10 built-in apps such as **Calcul
| POST | [/session/:sessionId/forward ](./Forward.cs) |
| POST | [/session/:sessionId/keys ](./SendKeys.cs) |
| GET | [/session/:sessionId/location ](./Location.cs) |
| POST | /session/:sessionId/moveto |
| POST | [/session/:sessionId/moveto ](./Mouse.cs) |
| GET | [/session/:sessionId/orientation ](./Orientation.cs) |
| GET | [/session/:sessionId/screenshot ](./Screenshot.cs) |
| GET | [/session/:sessionId/source ](./Source.cs) |
| POST | [/session/:sessionId/timeouts ](./Timeouts.cs) |
| GET | [/session/:sessionId/title ](./Title.cs) |
| POST | [/session/:sessionId/touch/click ](./TouchClick.cs) |
| POST | [/session/:sessionId/touch/doubleclick ](./TouchDoubleClick.cs) |
| POST | /session/:sessionId/touch/down |
| POST | [/session/:sessionId/touch/down ](./TouchDownMoveUp.cs) |
| POST | [/session/:sessionId/touch/flick ](./TouchFlick.cs) |
| POST | [/session/:sessionId/touch/longclick ](./TouchLongClick.cs) |
| POST | /session/:sessionId/touch/move |
| POST | [/session/:sessionId/touch/move ](./TouchDownMoveUp.cs) |
| POST | /session/:sessionId/touch/multi/perform |
| POST | [/session/:sessionId/touch/scroll ](./TouchScroll.cs) |
| POST | /session/:sessionId/touch/up |
| POST | [/session/:sessionId/touch/up ](./TouchDownMoveUp.cs) |
| DELETE | [/session/:sessionId/window ](./Window.cs) |
| POST | [/session/:sessionId/window ](./Window.cs) |
| POST | [/session/:sessionId/window/maximize ](./Window.cs) |
Expand Down
Loading

0 comments on commit ec19c10

Please sign in to comment.