Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Testing] Add scroll methods to UITest #19181

Merged
merged 4 commits into from Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/Controls/tests/UITests/Tests/ScrollViewUITests.cs
Expand Up @@ -74,5 +74,18 @@ public void ScrollToElement3End()
Assert.Ignore("This test is failing, likely due to product issue");
}
}

[Test]
[Description("Scroll down the ScrollView using a gesture")]
public void ScrollUpAndDownWithGestures()
{
this.IgnoreIfPlatforms(new TestDevice[] { TestDevice.Mac, TestDevice.Windows });

App.ScrollDown("thescroller", ScrollStrategy.Gesture, 0.75);
App.Screenshot("Element scrolled down");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test to validate the added methods (scroll with gestures)
scroll-gesture-uitest


App.ScrollUp("thescroller", ScrollStrategy.Gesture, 0.75);
App.Screenshot("Element scrolled up");
}
}
}
215 changes: 215 additions & 0 deletions src/TestUtils/src/UITest.Appium/Actions/AppiumScrollActions.cs
@@ -0,0 +1,215 @@
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.MultiTouch;
using UITest.Core;

namespace UITest.Appium
{
public enum ScrollStrategy
{
Auto,
Gesture,
Programmatically
}

public class AppiumScrollActions : ICommandExecutionGroup
{
const string ScrollLeftCommand = "scrollLeft";
const string ScrollDownCommand = "scrollDown";
const string ScrollRightCommand = "scrollRight";
const string ScrollUpCommand = "scrollUp";

readonly AppiumApp _appiumApp;

readonly List<string> _commands = new()
{
ScrollLeftCommand,
ScrollDownCommand,
ScrollRightCommand,
ScrollUpCommand,
};

public AppiumScrollActions(AppiumApp appiumApp)
{
_appiumApp = appiumApp;
}

public bool IsCommandSupported(string commandName)
{
return _commands.Contains(commandName, StringComparer.OrdinalIgnoreCase);
}

public CommandResponse Execute(string commandName, IDictionary<string, object> parameters)
{
return commandName switch
{
ScrollLeftCommand => ScrollLeft(parameters),
ScrollDownCommand => ScrollDown(parameters),
ScrollRightCommand => ScrollRight(parameters),
ScrollUpCommand => ScrollUp(parameters),
_ => CommandResponse.FailedEmptyResponse,
};
}

CommandResponse ScrollLeft(IDictionary<string, object> parameters)
{
parameters.TryGetValue("element", out var value);
var element = GetAppiumElement(value);

if (element is null)
return CommandResponse.FailedEmptyResponse;

ScrollStrategy strategy = (ScrollStrategy)parameters["strategy"];
double swipePercentage = (double)parameters["swipePercentage"];
int swipeSpeed = (int)parameters["swipeSpeed"];
bool withInertia = (bool)parameters["withInertia"];

ScrollToLeft(_appiumApp.Driver, element, strategy, swipePercentage, swipeSpeed, withInertia);

return CommandResponse.SuccessEmptyResponse;
}

CommandResponse ScrollDown(IDictionary<string, object> parameters)
{
parameters.TryGetValue("element", out var value);
var element = GetAppiumElement(value);

if (element is null)
return CommandResponse.FailedEmptyResponse;

ScrollStrategy strategy = (ScrollStrategy)parameters["strategy"];
double swipePercentage = (double)parameters["swipePercentage"];
int swipeSpeed = (int)parameters["swipeSpeed"];
bool withInertia = (bool)parameters["withInertia"];

ScrollToDown(_appiumApp.Driver, element, strategy, swipePercentage, swipeSpeed, withInertia);

return CommandResponse.SuccessEmptyResponse;
}

CommandResponse ScrollRight(IDictionary<string, object> parameters)
{
parameters.TryGetValue("element", out var value);
var element = GetAppiumElement(value);

if (element is null)
return CommandResponse.FailedEmptyResponse;

ScrollStrategy strategy = (ScrollStrategy)parameters["strategy"];
double swipePercentage = (double)parameters["swipePercentage"];
int swipeSpeed = (int)parameters["swipeSpeed"];
bool withInertia = (bool)parameters["withInertia"];

ScrollToRight(_appiumApp.Driver, element, strategy, swipePercentage, swipeSpeed, withInertia);

return CommandResponse.SuccessEmptyResponse;
}

CommandResponse ScrollUp(IDictionary<string, object> parameters)
{
parameters.TryGetValue("element", out var value);
var element = GetAppiumElement(value);

if (element is null)
return CommandResponse.FailedEmptyResponse;

ScrollStrategy strategy = (ScrollStrategy)parameters["strategy"];
double swipePercentage = (double)parameters["swipePercentage"];
int swipeSpeed = (int)parameters["swipeSpeed"];
bool withInertia = (bool)parameters["withInertia"];

ScrollToUp(_appiumApp.Driver, element, strategy, swipePercentage, swipeSpeed, withInertia);

return CommandResponse.SuccessEmptyResponse;
}

static AppiumElement? GetAppiumElement(object? element)
{
if (element is AppiumElement appiumElement)
{
return appiumElement;
}
else if (element is AppiumDriverElement driverElement)
{
return driverElement.AppiumElement;
}

return null;
}

static void ScrollToLeft(AppiumDriver driver, AppiumElement element, ScrollStrategy strategy, double swipePercentage, int swipeSpeed, bool withInertia = true)
{
var position = element.Location;
var size = element.Size;

int startX = (int)(position.X + (size.Width * 0.05));
int startY = position.Y + size.Height / 2;

int endX = (int)(position.X + (size.Width * swipePercentage));
int endY = startY;

new TouchAction(driver)
.Press(startX, startY)
.Wait(strategy != ScrollStrategy.Programmatically ? swipeSpeed : 0)
.MoveTo(endX, endY)
.Release()
.Perform();
}

static void ScrollToDown(AppiumDriver driver, AppiumElement element, ScrollStrategy strategy, double swipePercentage, int swipeSpeed, bool withInertia = true)
{
var position = element.Location;
var size = element.Size;

int startX = position.X + size.Width / 2;
int startY = (int)(position.Y + (size.Height * swipePercentage));

int endX = startX;
int endY = (int)(position.Y + (size.Height * 0.05));

new TouchAction(driver)
.Press(startX, startY)
.Wait(strategy != ScrollStrategy.Programmatically ? swipeSpeed : 0)
.MoveTo(endX, endY)
.Release()
.Perform();
}

static void ScrollToRight(AppiumDriver driver, AppiumElement element, ScrollStrategy strategy, double swipePercentage, int swipeSpeed, bool withInertia = true)
{
var position = element.Location;
var size = element.Size;

int startX = (int)(position.X + (size.Width * swipePercentage));
int startY = position.Y + size.Height / 2;

int endX = (int)(position.X + (size.Width * 0.05));
int endY = startY;

new TouchAction(driver)
.Press(startX, startY)
.Wait(strategy != ScrollStrategy.Programmatically ? swipeSpeed : 0)
.MoveTo(endX, endY)
.Release()
.Perform();
}

static void ScrollToUp(AppiumDriver driver, AppiumElement element, ScrollStrategy strategy, double swipePercentage, int swipeSpeed, bool withInertia = true)
{
var position = element.Location;
var size = element.Size;

int startX = position.X + size.Width / 2;
int startY = (int)(position.Y + (size.Height * 0.05));

int endX = startX;
int endY = (int)(position.Y + (size.Height * swipePercentage));

new TouchAction(driver)
.Press(startX, startY)
.Wait(strategy != ScrollStrategy.Programmatically ? swipeSpeed : 0)
.MoveTo(endX, endY)
.Release()
.Perform();
}
}
}
3 changes: 2 additions & 1 deletion src/TestUtils/src/UITest.Appium/AppiumApp.cs
@@ -1,4 +1,4 @@
using OpenQA.Selenium;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using UITest.Core;
Expand All @@ -23,6 +23,7 @@ public AppiumApp(AppiumDriver driver, IConfig config)
_commandExecutor.AddCommandGroup(new AppiumVirtualKeyboardActions(this));
_commandExecutor.AddCommandGroup(new AppiumSliderActions(this));
_commandExecutor.AddCommandGroup(new AppiumSwipeActions(this));
_commandExecutor.AddCommandGroup(new AppiumScrollActions(this));
_commandExecutor.AddCommandGroup(new AppiumOrientationActions(this));
}

Expand Down
99 changes: 96 additions & 3 deletions src/TestUtils/src/UITest.Appium/HelperExtensions.cs
@@ -1,4 +1,4 @@
using System.Collections.Immutable;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
Expand Down Expand Up @@ -224,7 +224,7 @@ public static void SwipeLeftToRight(this IApp app, string marked, double swipePe

app.CommandExecutor.Execute("swipeLeftToRight", new Dictionary<string, object>
{
{ "element", elementToSwipe},
{ "element", elementToSwipe},
{ "swipePercentage", swipePercentage },
{ "swipeSpeed", swipeSpeed },
{ "withInertia", withInertia }
Expand Down Expand Up @@ -270,6 +270,99 @@ public static void SwipeRightToLeft(this IApp app, string marked, double swipePe
});
}

/// <summary>
/// Scrolls left on the first element matching query.
/// </summary>
jfversluis marked this conversation as resolved.
Show resolved Hide resolved
/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="marked">Marked selector to match.</param>
/// <param name="strategy">Strategy for scrolling element.</param>
/// <param name="swipePercentage">How far across the element to swipe (from 0.0 to 1.0).</param>
/// <param name="swipeSpeed">The speed of the gesture.</param>
/// <param name="withInertia">Whether swipes should cause inertia.</param>
public static void ScrollLeft(this IApp app, string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
{
var elementToSwipe = app.FindElement(marked);

app.CommandExecutor.Execute("scrollLeft", new Dictionary<string, object>
{
{ "element", elementToSwipe},
{ "strategy", strategy },
{ "swipePercentage", swipePercentage },
{ "swipeSpeed", swipeSpeed },
{ "withInertia", withInertia }
});
}

/// <summary>
/// Scrolls down on the first element matching query.
/// </summary>
/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="marked">Marked selector to match.</param>
/// <param name="strategy">Strategy for scrolling element.</param>
/// <param name="swipePercentage">How far across the element to swipe (from 0.0 to 1.0).</param>
/// <param name="swipeSpeed">The speed of the gesture.</param>
/// <param name="withInertia">Whether swipes should cause inertia.</param>
public static void ScrollDown(this IApp app, string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var elementToSwipe = app.FindElement(marked);

app.CommandExecutor.Execute("scrollDown", new Dictionary<string, object>
{
{ "element", elementToSwipe},
{ "strategy", strategy },
{ "swipePercentage", swipePercentage },
{ "swipeSpeed", swipeSpeed },
{ "withInertia", withInertia }
});
}

/// <summary>
/// Scrolls right on the first element matching query.
/// </summary>
/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="marked">Marked selector to match.</param>
/// <param name="strategy">Strategy for scrolling element.</param>
/// <param name="swipePercentage">How far across the element to swipe (from 0.0 to 1.0).</param>
/// <param name="swipeSpeed">The speed of the gesture.</param>
/// <param name="withInertia">Whether swipes should cause inertia.</param>
public static void ScrollRight(this IApp app, string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
{
var elementToSwipe = app.FindElement(marked);

app.CommandExecutor.Execute("scrollRight", new Dictionary<string, object>
{
{ "element", elementToSwipe},
{ "strategy", strategy },
{ "swipePercentage", swipePercentage },
{ "swipeSpeed", swipeSpeed },
{ "withInertia", withInertia }
});
}

/// <summary>
/// Scrolls up on the first element matching query.
/// </summary>
/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="marked">Marked selector to match.</param>
/// <param name="strategy">Strategy for scrolling element.</param>
/// <param name="swipePercentage">How far across the element to swipe (from 0.0 to 1.0).</param>
/// <param name="swipeSpeed">The speed of the gesture.</param>
/// <param name="withInertia">Whether swipes should cause inertia.</param>
public static void ScrollUp(this IApp app, string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true)
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var elementToSwipe = app.FindElement(marked);

app.CommandExecutor.Execute("scrollUp", new Dictionary<string, object>
{
{ "element", elementToSwipe},
{ "strategy", strategy },
{ "swipePercentage", swipePercentage },
{ "swipeSpeed", swipeSpeed },
{ "withInertia", withInertia }
});
}

/// <summary>
/// Changes the device orientation to landscape mode.
/// </summary>
/// <param name="app">Represents the main gateway to interact with an app.</param>
Expand Down Expand Up @@ -392,4 +485,4 @@ public static void SetSliderValue(this IApp app, string marked, double value, do
Wait(query, i => i == null, timeoutMessage, timeout, retryFrequency);
}
}
}
}