Skip to content

Commit

Permalink
Make the taps work on all platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
hartez committed Sep 14, 2023
1 parent 376832c commit 399b4f9
Showing 1 changed file with 62 additions and 18 deletions.
80 changes: 62 additions & 18 deletions src/Controls/tests/UITests/Tests/Issues/Issue16561.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System.Drawing;
using Microsoft.Maui.Appium;
using NUnit.Framework;
using OpenQA.Selenium.Appium.Mac;
using OpenQA.Selenium.Appium.MultiTouch;
using OpenQA.Selenium.Appium.Interactions;
using OpenQA.Selenium.Appium.iOS;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Interactions;
//using OpenQA.Selenium.Appium.Windows;
using TestUtils.Appium.UITests;
using PointerInputDevice = OpenQA.Selenium.Appium.Interactions.PointerInputDevice;

namespace Microsoft.Maui.AppiumTests.Issues
{
Expand Down Expand Up @@ -45,21 +45,7 @@ public void TapTwoPlacesQuickly()
var expectedX1 = point1.X - tapArea.X;
var expectedX2 = point2.X - tapArea.X;

if (app2.Driver is WindowsDriver)
{
// Windows will throw an error if we try to execute Taps with a TouchAction, so we'll just use TapCoordinates instead
app2.TapCoordinates(point1.X, point1.Y);
app2.TapCoordinates(point2.X, point2.Y);
}
else
{
// Just calling Tap twice will be too slow; we need to queue up the actions so they happen quickly
var actionsList = new TouchAction(app2.Driver);

// Tap the first point, then the second point
actionsList.Tap(point1.X, point1.Y).Tap(point2.X, point2.Y);
app2.Driver.PerformTouchAction(actionsList);
}
TapTwice(app2, point1, point2);

// The results for each tap should show up in the labels on the screen; find the text
// of each tap result and check to see that it meets the expected values
Expand All @@ -70,6 +56,64 @@ public void TapTwoPlacesQuickly()
AssertCorrectTapLocation(result[0].Text, expectedX2, expectedY, "Second");
}

static void TapTwice(IApp2 app, PointF point1, PointF point2)
{
var driver = app.Driver ?? throw new InvalidOperationException("The Appium driver is null; cannot perform taps.");

if (driver is WindowsDriver)
{
// Windows will throw an error if we try to execute Taps with a TouchAction
// or if we try to use ExecuteScript, so we'll just use TapCoordinates instead
app.TapCoordinates(point1.X, point1.Y);
app.TapCoordinates(point2.X, point2.Y);
}
else if (driver is IOSDriver)
{
// iOS, on the other hand, will allow us to use ExecuteScript to run two taps quickly
// It will not work with an ActionSequence, though; one of the taps will simply never
// happen. No errors, but no second tap.

driver.ExecuteScript("mobile: tap", new Dictionary<string, object> {
{ "x", point1.X },
{ "y", point1.Y }
});

driver.ExecuteScript("mobile: tap", new Dictionary<string, object> {
{ "x", point2.X },
{ "y", point2.Y }
});
}
else
{
// For Android, TapCoordinates won't work (it's far too slow), and ExecuteScript
// throws an error. So we'll use an ActionSequence, which is what we wanted in
// the first place.

PointerInputDevice touchDevice = new PointerInputDevice(PointerKind.Touch);
var sequence = new ActionSequence(touchDevice, 0);

// Move to the first location and tap
sequence.AddAction(touchDevice.CreatePointerMove(CoordinateOrigin.Viewport,
(int)point1.X, (int)point1.Y, TimeSpan.FromMilliseconds(250)));
sequence.AddAction(touchDevice.CreatePointerDown(PointerButton.TouchContact));
sequence.AddAction(touchDevice.CreatePointerUp(PointerButton.TouchContact));

// If we don't put some kind of pause between the taps, Appium will throw an exception
// We'll use a pause that's shorter than the default time for a double-tap on Android,
// so we're very clearly simulating two different taps on two different locations
sequence.AddAction(touchDevice.CreatePause(TimeSpan.FromMilliseconds(250)));

// Move to the second location and tap
sequence.AddAction(touchDevice.CreatePointerMove(CoordinateOrigin.Viewport,
(int)point2.X, (int)point2.Y, TimeSpan.FromMilliseconds(0)));
sequence.AddAction(touchDevice.CreatePointerDown(PointerButton.TouchContact));
sequence.AddAction(touchDevice.CreatePointerUp(PointerButton.TouchContact));

// Run the sequence we just built
driver.PerformActions(new List<ActionSequence> { sequence });
}
}

static void AssertCorrectTapLocation(string tapData, float expectedX, float expectedY, string which)
{
// Turn the text values into numbers so we can compare with a tolerance
Expand Down

0 comments on commit 399b4f9

Please sign in to comment.