-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Testing] Implement Pinch gestures in UITest extensions methods (#25316)
* Implement Pinch gestures in UITest extensions methods * Updated test * Updated test * More changes * Apply suggestions from code review --------- Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
- Loading branch information
1 parent
2077463
commit d91ba8e
Showing
4 changed files
with
356 additions
and
12 deletions.
There are no files selected for viewing
36 changes: 24 additions & 12 deletions
36
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Bugzilla/Bugzilla57515.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,37 @@ | ||
using NUnit.Framework; | ||
#if ANDROID || IOS // TODO: Cannot find the element ZoomContainer on Desktop. Investigate the reason. | ||
using NUnit.Framework; | ||
using NUnit.Framework.Legacy; | ||
using UITest.Appium; | ||
using UITest.Core; | ||
|
||
namespace Microsoft.Maui.TestCases.Tests.Issues; | ||
|
||
public class Bugzilla57515 : _IssuesUITest | ||
{ | ||
const string ZoomContainer = "zoomContainer"; | ||
|
||
public Bugzilla57515(TestDevice testDevice) : base(testDevice) | ||
{ | ||
} | ||
|
||
public override string Issue => "PinchGestureRecognizer not getting called on Android "; | ||
|
||
// [Test] | ||
// [Category(UITestCategories.Gestures)] | ||
// [FailsOnIOSWhenRunningOnXamarinUITest] | ||
// public void Bugzilla57515Test() | ||
// { | ||
// App.WaitForElement(ZoomContainer); | ||
// App.WaitForElement("1"); | ||
// App.PinchToZoomIn(ZoomContainer); | ||
// App.WaitForNoElement("1"); // The scale should have changed during the zoom | ||
// } | ||
} | ||
[Test] | ||
[Category(UITestCategories.Gestures)] | ||
[FailsOnIOSWhenRunningOnXamarinUITest] | ||
public void Bugzilla57515Test() | ||
{ | ||
if (App is not AppiumApp app2 || app2 is null || app2.Driver is null) | ||
{ | ||
throw new InvalidOperationException("Cannot run test. Missing driver to run quick tap actions."); | ||
} | ||
|
||
App.WaitForElement(ZoomContainer); | ||
var zoomScale1 = app2.Driver.FindElement(OpenQA.Selenium.By.XPath("//*[@text='" + "1" + "']")); | ||
ClassicAssert.AreEqual("1", zoomScale1.Text); | ||
App.PinchToZoomIn(ZoomContainer); | ||
var elements = app2.Driver.FindElements(OpenQA.Selenium.By.XPath("//*[@text='" + "1" + "']")); | ||
ClassicAssert.AreEqual(0, elements.Count); // The scale should have changed during the zoom | ||
} | ||
} | ||
#endif |
261 changes: 261 additions & 0 deletions
261
src/TestUtils/src/UITest.Appium/Actions/AppiumPinchToZoomActions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
using OpenQA.Selenium.Appium; | ||
using OpenQA.Selenium.Appium.Interactions; | ||
using OpenQA.Selenium.Interactions; | ||
using UITest.Core; | ||
|
||
namespace UITest.Appium | ||
{ | ||
class AppiumPinchToZoomActions : ICommandExecutionGroup | ||
{ | ||
const string PinchToZoomInCommand = "pinchToZoomIn"; | ||
const string PinchToZoomInCoordinatesCommand = "pinchToZoomInCoordinates"; | ||
const string PinchToZoomOutCommand = "pinchToZoomOut"; | ||
const string PinchToZoomOutCoordinatesCommand = "pinchToZoomOutCoordinates"; | ||
|
||
protected readonly AppiumApp _app; | ||
|
||
readonly List<string> _commands = new() | ||
{ | ||
PinchToZoomInCommand, | ||
PinchToZoomInCoordinatesCommand, | ||
PinchToZoomOutCommand, | ||
PinchToZoomOutCoordinatesCommand, | ||
}; | ||
|
||
public AppiumPinchToZoomActions(AppiumApp app) | ||
{ | ||
_app = app; | ||
} | ||
|
||
public bool IsCommandSupported(string commandName) | ||
{ | ||
return _commands.Contains(commandName, StringComparer.OrdinalIgnoreCase); | ||
} | ||
|
||
public CommandResponse Execute(string commandName, IDictionary<string, object> parameters) | ||
{ | ||
return commandName switch | ||
{ | ||
PinchToZoomInCommand => PinchToZoomIn(parameters), | ||
PinchToZoomInCoordinatesCommand => PinchToZoomInCoordinates(parameters), | ||
PinchToZoomOutCommand => PinchToZoomOut(parameters), | ||
PinchToZoomOutCoordinatesCommand => PinchToZoomOutCoordinates(parameters), | ||
_ => CommandResponse.FailedEmptyResponse, | ||
}; | ||
} | ||
|
||
CommandResponse PinchToZoomIn(IDictionary<string, object> parameters) | ||
{ | ||
try | ||
{ | ||
parameters.TryGetValue("element", out var value); | ||
var element = GetAppiumElement(value); | ||
|
||
TimeSpan duration = (TimeSpan)parameters["duration"]; | ||
|
||
PinchToZoomIn(_app.Driver, element, duration); | ||
|
||
return CommandResponse.SuccessEmptyResponse; | ||
} | ||
catch | ||
{ | ||
return CommandResponse.FailedEmptyResponse; | ||
} | ||
} | ||
|
||
CommandResponse PinchToZoomInCoordinates(IDictionary<string, object> parameters) | ||
{ | ||
try | ||
{ | ||
int x = (int)parameters["x"]; | ||
int y = (int)parameters["y"]; | ||
TimeSpan duration = (TimeSpan)parameters["duration"]; | ||
|
||
PinchToZoomInCoordinates(_app.Driver, x, y, duration); | ||
|
||
return CommandResponse.SuccessEmptyResponse; | ||
} | ||
catch | ||
{ | ||
return CommandResponse.FailedEmptyResponse; | ||
} | ||
} | ||
|
||
CommandResponse PinchToZoomOut(IDictionary<string, object> parameters) | ||
{ | ||
try | ||
{ | ||
parameters.TryGetValue("element", out var value); | ||
var element = GetAppiumElement(value); | ||
|
||
TimeSpan duration = (TimeSpan)parameters["duration"]; | ||
|
||
PinchToZoomOut(_app.Driver, element, duration); | ||
|
||
return CommandResponse.SuccessEmptyResponse; | ||
} | ||
catch | ||
{ | ||
return CommandResponse.FailedEmptyResponse; | ||
} | ||
} | ||
|
||
CommandResponse PinchToZoomOutCoordinates(IDictionary<string, object> parameters) | ||
{ | ||
try | ||
{ | ||
int x = (int)parameters["x"]; | ||
int y = (int)parameters["y"]; | ||
TimeSpan duration = (TimeSpan)parameters["duration"]; | ||
|
||
PinchToZoomOutCoordinates(_app.Driver, x, y, duration); | ||
|
||
return CommandResponse.SuccessEmptyResponse; | ||
} | ||
catch | ||
{ | ||
return CommandResponse.FailedEmptyResponse; | ||
} | ||
} | ||
|
||
static void PinchToZoomIn(AppiumDriver driver, AppiumElement? element, TimeSpan duration) | ||
{ | ||
var position = element is not null ? element.Location : System.Drawing.Point.Empty; | ||
var size = element is not null ? element.Size : driver.Manage().Window.Size; | ||
|
||
int touch1StartX = position.X + size.Width / 2; | ||
int touch1StartY = position.Y + size.Height / 2; | ||
int touch1EndX = position.X; | ||
int touch1EndY = position.Y; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch1 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch1Sequence = new ActionSequence(touch1, 0); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1StartX, touch1StartY, TimeSpan.Zero)); | ||
touch1Sequence.AddAction(touch1.CreatePointerDown(PointerButton.TouchContact)); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1EndX, touch1EndY, duration)); | ||
touch1Sequence.AddAction(touch1.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
int touch2StartX = position.X + size.Width / 2; | ||
int touch2StartY = position.Y + size.Height / 2; | ||
int touch2EndX = position.X + size.Width; | ||
int touch2EndY = position.Y + size.Height; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch2 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch2Sequence = new ActionSequence(touch2, 0); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2StartX, touch2StartY, TimeSpan.Zero)); | ||
touch2Sequence.AddAction(touch2.CreatePointerDown(PointerButton.TouchContact)); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2EndX, touch2EndY, duration)); | ||
touch2Sequence.AddAction(touch2.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
driver.PerformActions([touch1Sequence, touch2Sequence]); | ||
} | ||
|
||
static void PinchToZoomInCoordinates(AppiumDriver driver, int x, int y, TimeSpan duration) | ||
{ | ||
const int distance = 50; | ||
|
||
int touch1StartX = x; | ||
int touch1StartY = y; | ||
int touch1EndX = x - distance; | ||
int touch1EndY = y - distance; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch1 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch1Sequence = new ActionSequence(touch1, 0); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1StartX, touch1StartY, TimeSpan.Zero)); | ||
touch1Sequence.AddAction(touch1.CreatePointerDown(PointerButton.TouchContact)); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1EndX, touch1EndY, duration)); | ||
touch1Sequence.AddAction(touch1.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
int touch2StartX = x; | ||
int touch2StartY = y; | ||
int touch2EndX = x + distance; | ||
int touch2EndY = y + distance; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch2 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch2Sequence = new ActionSequence(touch2, 0); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2StartX, touch2StartY, TimeSpan.Zero)); | ||
touch2Sequence.AddAction(touch2.CreatePointerDown(PointerButton.TouchContact)); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2EndX, touch2EndY, duration)); | ||
touch2Sequence.AddAction(touch2.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
driver.PerformActions([touch1Sequence, touch2Sequence]); | ||
} | ||
|
||
static void PinchToZoomOut(AppiumDriver driver, AppiumElement? element, TimeSpan duration) | ||
{ | ||
var position = element is not null ? element.Location : System.Drawing.Point.Empty; | ||
var size = element is not null ? element.Size : driver.Manage().Window.Size; | ||
|
||
int touch1StartX = position.X; | ||
int touch1StartY = position.Y; | ||
int touch1EndX = position.X + size.Width / 2; | ||
int touch1EndY = position.Y + size.Height / 2; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch1 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch1Sequence = new ActionSequence(touch1, 0); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1StartX, touch1StartY, TimeSpan.Zero)); | ||
touch1Sequence.AddAction(touch1.CreatePointerDown(PointerButton.TouchContact)); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1EndX, touch1EndY, duration)); | ||
touch1Sequence.AddAction(touch1.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
int touch2StartX = position.X + size.Width; | ||
int touch2StartY = position.Y + size.Height; | ||
int touch2EndX = position.X + size.Width / 2; | ||
int touch2EndY = position.Y + size.Height / 2; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch2 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch2Sequence = new ActionSequence(touch2, 0); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2StartX, touch2StartY, TimeSpan.Zero)); | ||
touch2Sequence.AddAction(touch2.CreatePointerDown(PointerButton.TouchContact)); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2EndX, touch2EndY, duration)); | ||
touch2Sequence.AddAction(touch2.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
driver.PerformActions([touch1Sequence, touch2Sequence]); | ||
} | ||
|
||
static void PinchToZoomOutCoordinates(AppiumDriver driver, int x, int y, TimeSpan duration) | ||
{ | ||
const int distance = 50; | ||
|
||
int touch1StartX = x - distance; | ||
int touch1StartY = y - distance; | ||
int touch1EndX = x; | ||
int touch1EndY = y; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch1 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch1Sequence = new ActionSequence(touch1, 0); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1StartX, touch1StartY, TimeSpan.Zero)); | ||
touch1Sequence.AddAction(touch1.CreatePointerDown(PointerButton.TouchContact)); | ||
touch1Sequence.AddAction(touch1.CreatePointerMove(CoordinateOrigin.Viewport, touch1EndX, touch1EndY, duration)); | ||
touch1Sequence.AddAction(touch1.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
int touch2StartX = x + distance; | ||
int touch2StartY = y + distance; | ||
int touch2EndX = x; | ||
int touch2EndY = y; | ||
|
||
OpenQA.Selenium.Appium.Interactions.PointerInputDevice touch2 = new OpenQA.Selenium.Appium.Interactions.PointerInputDevice(PointerKind.Touch); | ||
ActionSequence touch2Sequence = new ActionSequence(touch2, 0); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2StartX, touch2StartY, TimeSpan.Zero)); | ||
touch2Sequence.AddAction(touch2.CreatePointerDown(PointerButton.TouchContact)); | ||
touch2Sequence.AddAction(touch2.CreatePointerMove(CoordinateOrigin.Viewport, touch2EndX, touch2EndY, duration)); | ||
touch2Sequence.AddAction(touch2.CreatePointerUp(PointerButton.TouchContact)); | ||
|
||
driver.PerformActions([touch1Sequence, touch2Sequence]); | ||
} | ||
|
||
static AppiumElement? GetAppiumElement(object? element) | ||
{ | ||
if (element is AppiumElement appiumElement) | ||
{ | ||
return appiumElement; | ||
} | ||
else if (element is AppiumDriverElement driverElement) | ||
{ | ||
return driverElement.AppiumElement; | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters