diff --git a/src/Winium.Desktop.Driver/CommandExecutors/GetElementLocationExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/GetElementLocationExecutor.cs new file mode 100644 index 0000000..0f8ed26 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/GetElementLocationExecutor.cs @@ -0,0 +1,33 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System.Collections.Generic; + + using Winium.StoreApps.Common; + + #endregion + + internal class GetElementLocationExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString(); + + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + var boundingRect = element.Properties.BoundingRectangle; + + var response = new Dictionary + { + { "x", boundingRect.X }, + { "y", boundingRect.Y } + }; + return this.JsonResponse(ResponseStatus.Success, response); + } + + #endregion + } +} diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchDoubleTapExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchDoubleTapExecutor.cs new file mode 100644 index 0000000..475b807 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchDoubleTapExecutor.cs @@ -0,0 +1,32 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using Winium.Cruciatus.Core; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchDoubleTapExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!this.ExecutedCommand.Parameters.ContainsKey("element")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + return TouchSimulator.DoubleTap(element) + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchFlickExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchFlickExecutor.cs new file mode 100644 index 0000000..070b609 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchFlickExecutor.cs @@ -0,0 +1,74 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + using System.Threading; + using System.Windows; + + using Winium.Cruciatus; + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchFlickExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (this.ExecutedCommand.Parameters.ContainsKey("element")) + { + return FlickElement(); + } + + return Flick(); + } + + string Flick() + { + if (!(this.ExecutedCommand.Parameters.ContainsKey("xspeed") + && this.ExecutedCommand.Parameters.ContainsKey("yspeed"))) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var xSpeed = this.ExecutedCommand.GetParameterAsInt("xspeed"); + var ySpeed = this.ExecutedCommand.GetParameterAsInt("yspeed"); + + return TouchSimulator.Flick(xSpeed, ySpeed) + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + string FlickElement() + { + if ( + !(this.ExecutedCommand.Parameters.ContainsKey("element") + && this.ExecutedCommand.Parameters.ContainsKey("xoffset") + && this.ExecutedCommand.Parameters.ContainsKey("yoffset") + && this.ExecutedCommand.Parameters.ContainsKey("speed"))) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + var xOffset = this.ExecutedCommand.GetParameterAsInt("xoffset"); + var yOffset = this.ExecutedCommand.GetParameterAsInt("yoffset"); + + var pixelsPerSecond = this.ExecutedCommand.GetParameterAsInt("speed"); + + return TouchSimulator.FlickElement(element, xOffset, yOffset, pixelsPerSecond) + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchLongPressExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchLongPressExecutor.cs new file mode 100644 index 0000000..c7cc60b --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchLongPressExecutor.cs @@ -0,0 +1,71 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + + using Winium.Cruciatus.Core; + using Winium.Cruciatus.Elements; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchLongPressExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + var haveElement = this.ExecutedCommand.Parameters.ContainsKey("element"); + var havePoint = this.ExecutedCommand.Parameters.ContainsKey("x") + && this.ExecutedCommand.Parameters.ContainsKey("y"); + + if (!(haveElement || havePoint)) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + bool success; + CruciatusElement element = null; + var x = 0; + var y = 0; + + if (haveElement) + { + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + } + + if (havePoint) + { + x = this.ExecutedCommand.GetParameterAsInt("x"); + y = this.ExecutedCommand.GetParameterAsInt("y"); + } + + var duration = this.ExecutedCommand.Parameters.ContainsKey("duration") + ? this.ExecutedCommand.GetParameterAsInt("duration") + : 1000; + + if (haveElement && havePoint) + { + success = TouchSimulator.LongTap(element, x, y, duration); + } + else if (haveElement) + { + success = TouchSimulator.LongTap(element, duration); + } + else + { + success = TouchSimulator.LongTap(x, y, duration); + } + + return success + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchMoveExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchMoveExecutor.cs new file mode 100644 index 0000000..a09c6a4 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchMoveExecutor.cs @@ -0,0 +1,50 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchMoveExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!this.ExecutedCommand.Parameters.ContainsKey("x") + && this.ExecutedCommand.Parameters.ContainsKey("y")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var x = this.ExecutedCommand.GetParameterAsInt("x"); + var y = this.ExecutedCommand.GetParameterAsInt("y"); + + bool success; + + if (this.ExecutedCommand.Parameters.ContainsKey("element")) + { + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + success = TouchSimulator.TouchUpdate(element, x, y); + } + else + { + success = TouchSimulator.TouchUpdate(x, y); + } + + return success + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchPerformExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchPerformExecutor.cs new file mode 100644 index 0000000..0d7ca03 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchPerformExecutor.cs @@ -0,0 +1,199 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Windows; + + using Winium.StoreApps.Common; + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.CommandHelpers; + using Winium.StoreApps.Common.Exceptions; + + #endregion + + internal class TouchPerformExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!this.ExecutedCommand.Parameters.ContainsKey("actions")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var actions = this.ExecutedCommand.Parameters["actions"] + .ToObject>() + .Select(a => new TouchAction(a, this.Automator)) + .ToList(); + + var success = false; + + if (actions.Count == 4 + && actions[0].Action == TouchAction.Press + && actions[1].Action == TouchAction.Wait + && actions[2].Action == TouchAction.MoveTo + && actions[3].Action == TouchAction.Release) + { + success = Flick(actions); + } + else if (actions.Count == 5 + && actions[0].Action == TouchAction.Press + && actions[1].Action == TouchAction.Wait + && actions[2].Action == TouchAction.MoveTo + && actions[3].Action == TouchAction.Wait + && actions[4].Action == TouchAction.Release) + { + success = DragWithTimes(actions); + } + else if (actions.Count == 3 + && actions[0].Action == TouchAction.LongPress + && actions[1].Action == TouchAction.MoveTo + && actions[2].Action == TouchAction.Release) + { + success = Drag(actions); + } + else + { + success = Perform(actions); + } + + return success + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + private static bool Flick(List actions) + { + var startPoint = actions[0].GetLocation(); + var endPoint = actions[2].GetLocation(); + + return TouchSimulator.Flick( + (int)startPoint.X, + (int)startPoint.Y, + (int)endPoint.X, + (int)endPoint.Y, + actions[1].MiliSeconds); + } + + private static bool DragWithTimes(List actions) + { + var startPoint = actions[0].GetLocation(); + var endPoint = actions[2].GetLocation(); + + return TouchSimulator.Scroll( + (int)startPoint.X, + (int)startPoint.Y, + (int)endPoint.X, + (int)endPoint.Y, + actions[1].MiliSeconds, + actions[3].MiliSeconds); + } + + private static bool Drag(List actions) + { + var startPoint = actions[0].GetLocation(); + var endPoint = actions[1].GetLocation(); + + return TouchSimulator.Scroll( + (int)startPoint.X, + (int)startPoint.Y, + (int)endPoint.X, + (int)endPoint.Y); + } + + private static bool Perform(List actions) + { + var previousX = 0; + var previousY = 0; + var havePrevious = false; + string previousAction = null; + + for (var i = 0; i < actions.Count; i ++) + { + var action = actions[i]; + + Point point; + + switch (action.Action) + { + case TouchAction.LongPress: + point = action.GetLocation(); + TouchSimulator.LongTap((int)point.X, (int)point.Y, action.MiliSeconds); + havePrevious = false; + break; + case TouchAction.MoveTo: + int? duration = null; + if (i > 0 && actions[i - 1].Action == TouchAction.Wait) + { + duration = actions[i - 1].MiliSeconds; + } + point = action.GetLocation(); + var x = (int)point.X; + var y = (int)point.Y; + TouchSimulator.MoveTo(previousX, previousY, previousX + x, previousY + y, duration); + previousX += x; + previousY += y; + havePrevious = true; + break; + case TouchAction.Press: + point = action.GetLocation(); + TouchSimulator.TouchDown((int)point.X, (int)point.Y); + previousX = (int)point.X; + previousY = (int)point.Y; + havePrevious = true; + break; + case TouchAction.Release: + if (previousAction == TouchAction.Tap || previousAction == TouchAction.LongPress) + { + break; + } + TouchSimulator.TouchUp(previousX, previousY); + havePrevious = false; + break; + case TouchAction.Tap: + point = action.GetLocation(); + for (var n = 1; n <= action.Count; n++) + { + TouchSimulator.Tap((int)point.X, (int)point.Y); + Thread.Sleep(250); + } + havePrevious = false; + break; + case TouchAction.Wait: + if (actions.Count > i + 1 && actions[i + 1].Action == TouchAction.MoveTo) + { + break; + } + if (havePrevious) + { + var startTime = DateTime.Now; + while (DateTime.Now < startTime + TimeSpan.FromMilliseconds(action.MiliSeconds)) + { + TouchSimulator.TouchUpdate(previousX, previousY); + Thread.Sleep(16); + } + } + else + { + Thread.Sleep(action.MiliSeconds); + } + break; + default: + throw new AutomationException($"unrecognised action {action.Action}"); + } + + previousAction = action.Action; + } + + return true; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchPressExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchPressExecutor.cs new file mode 100644 index 0000000..e6c7014 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchPressExecutor.cs @@ -0,0 +1,50 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchPressExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!this.ExecutedCommand.Parameters.ContainsKey("x") + && this.ExecutedCommand.Parameters.ContainsKey("y")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var x = this.ExecutedCommand.GetParameterAsInt("x"); + var y = this.ExecutedCommand.GetParameterAsInt("y"); + + bool success; + + if (this.ExecutedCommand.Parameters.ContainsKey("element")) + { + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + success = TouchSimulator.TouchDown(element, x, y); + } + else + { + success = TouchSimulator.TouchDown(x, y); + } + + return success + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchReleaseExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchReleaseExecutor.cs new file mode 100644 index 0000000..c9b336b --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchReleaseExecutor.cs @@ -0,0 +1,50 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchReleaseExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!this.ExecutedCommand.Parameters.ContainsKey("x") + && this.ExecutedCommand.Parameters.ContainsKey("y")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var x = this.ExecutedCommand.GetParameterAsInt("x"); + var y = this.ExecutedCommand.GetParameterAsInt("y"); + + bool success; + + if (this.ExecutedCommand.Parameters.ContainsKey("element")) + { + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + success = TouchSimulator.TouchUp(element, x, y); + } + else + { + success = TouchSimulator.TouchUp(x, y); + } + + return success + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed ('x' and 'y' must match preceeding 'down' or 'move' request)"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchScrollExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchScrollExecutor.cs new file mode 100644 index 0000000..76adeb3 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchScrollExecutor.cs @@ -0,0 +1,91 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using System; + using System.Threading; + using System.Windows; + + using Winium.Cruciatus; + using Winium.Cruciatus.Core; + using Winium.Desktop.Driver.Extensions; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchScrollExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + var haveElement = this.ExecutedCommand.Parameters.ContainsKey("element"); + var haveOffset = this.ExecutedCommand.Parameters.ContainsKey("xoffset") + && this.ExecutedCommand.Parameters.ContainsKey("yoffset"); + + if (!haveOffset) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var element = CruciatusFactory.Root; + + if (haveElement) + { + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + } + + var rect = element.Properties.BoundingRectangle; + + var startPoint = new Point( + rect.Left + (rect.Width / 2), + rect.Top + (rect.Height / 2)); + + var xOffset = this.ExecutedCommand.GetParameterAsInt("xoffset"); + var yOffset = this.ExecutedCommand.GetParameterAsInt("yoffset"); + + var endPoint = new Point( + startPoint.X + xOffset, + startPoint.Y + yOffset); + + if (!TouchSimulator.TouchDown((int)startPoint.X, (int)startPoint.Y)) + { + return this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + var distance = Math.Sqrt(Math.Pow(startPoint.X - endPoint.X, 2) + Math.Pow(startPoint.Y - endPoint.Y, 2)); + + for (var soFar = 6; soFar < distance; soFar += 6) + { + var soFarFraction = soFar / distance; + + var x = (int)(startPoint.X + (xOffset * soFarFraction)); + var y = (int)(startPoint.Y + (yOffset * soFarFraction)); + if (!TouchSimulator.TouchUpdate(x, y)) + { + return this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + Thread.Sleep(8); + } + + var startTime = DateTime.Now; + while (DateTime.Now < (startTime + TimeSpan.FromMilliseconds(500))) + { + if (!TouchSimulator.TouchUpdate((int)endPoint.X, (int)endPoint.Y)) + { + return this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + Thread.Sleep(16); + } + + return TouchSimulator.TouchUp((int)endPoint.X, (int)endPoint.Y) + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Winium.Desktop.Driver/CommandExecutors/TouchSingleTapExecutor.cs b/src/Winium.Desktop.Driver/CommandExecutors/TouchSingleTapExecutor.cs new file mode 100644 index 0000000..6dbaeba --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandExecutors/TouchSingleTapExecutor.cs @@ -0,0 +1,32 @@ +namespace Winium.Desktop.Driver.CommandExecutors +{ + #region using + + using Winium.Cruciatus.Core; + using Winium.StoreApps.Common; + + #endregion + + internal class TouchSingleTapExecutor : CommandExecutorBase + { + #region Methods + + protected override string DoImpl() + { + if (!ExecutedCommand.Parameters.ContainsKey("element")) + { + // TODO: in the future '400 : invalid argument' will be used + return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS"); + } + + var registeredKey = this.ExecutedCommand.Parameters["element"].ToString(); + var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey); + + return TouchSimulator.Tap(element) + ? this.JsonResponse() + : this.JsonResponse(ResponseStatus.UnknownError, "Touch input failed"); + } + + #endregion + } +} diff --git a/src/Winium.Desktop.Driver/CommandHelpers/JsonTouchAction.cs b/src/Winium.Desktop.Driver/CommandHelpers/JsonTouchAction.cs new file mode 100644 index 0000000..504e140 --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandHelpers/JsonTouchAction.cs @@ -0,0 +1,28 @@ +namespace Winium.Desktop.Driver.CommandHelpers +{ + #region usings + + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + #endregion + + class JsonTouchAction + { + #region Public Properties + + [JsonProperty("action")] + public string Action { get; set; } + + [JsonProperty("options")] + public Dictionary Options { get; set; } + + public int GetOptionAsInt(string optionName) + { + return (int)Math.Round(Convert.ToDouble(Options[optionName])); + } + + #endregion + } +} diff --git a/src/Winium.Desktop.Driver/CommandHelpers/TouchAction.cs b/src/Winium.Desktop.Driver/CommandHelpers/TouchAction.cs new file mode 100644 index 0000000..6687bcb --- /dev/null +++ b/src/Winium.Desktop.Driver/CommandHelpers/TouchAction.cs @@ -0,0 +1,111 @@ +namespace Winium.Desktop.Driver.CommandHelpers +{ + #region using + + using System; + using System.Windows; + + using Winium.Desktop.Driver.Automator; + + #endregion + + class TouchAction + { + #region Fields + + JsonTouchAction _jsonTouchAction; + + Automator _automator; + + #endregion + + #region Public Constants + + public const string LongPress = "longpress"; + public const string MoveTo = "moveto"; + public const string Press = "press"; + public const string Release = "release"; + public const string Tap = "tap"; + public const string Wait = "wait"; + + #endregion + + #region Public Properties + + public string Action => _jsonTouchAction.Action.ToLower(); + + public int MiliSeconds { get; } + + public int Count { get; } + + #endregion + + #region Public Methods + + public TouchAction(JsonTouchAction jsonTouchAction, Automator automator) + { + _jsonTouchAction = jsonTouchAction; + _automator = automator; + + if (this.Action == Wait) + { + this.MiliSeconds = jsonTouchAction.GetOptionAsInt("ms"); + return; + } + + if (this.Action == Release) + { + return; + } + + if (this.Action == Tap) + { + this.Count = jsonTouchAction.Options.ContainsKey("count") + ? Convert.ToInt32(jsonTouchAction.Options["count"]) + : 1; + } + + if (this.Action == LongPress) + { + this.MiliSeconds = jsonTouchAction.Options.ContainsKey("duration") + ? jsonTouchAction.GetOptionAsInt("duration") + : 1000; + } + } + + public Point GetLocation() + { + var point = new Point(); + + if (_jsonTouchAction.Options.ContainsKey("element")) + { + var element = _automator.ElementsRegistry.GetRegisteredElement( + _jsonTouchAction.Options["element"]); + + var rect = element.Properties.BoundingRectangle; + + point.X = _jsonTouchAction.Options.ContainsKey("x") + ? rect.Left + : (rect.Left + (rect.Width / 2)); + + point.Y = _jsonTouchAction.Options.ContainsKey("y") + ? rect.Top + : (rect.Top + (rect.Height / 2)); + } + + if (_jsonTouchAction.Options.ContainsKey("x")) + { + point.X += _jsonTouchAction.GetOptionAsInt("x"); + } + + if (_jsonTouchAction.Options.ContainsKey("y")) + { + point.Y += _jsonTouchAction.GetOptionAsInt("y"); + } + + return point; + } + + #endregion + } +} diff --git a/src/Winium.Desktop.Driver/Extensions/CommandHelper.cs b/src/Winium.Desktop.Driver/Extensions/CommandHelper.cs new file mode 100644 index 0000000..ce9cde8 --- /dev/null +++ b/src/Winium.Desktop.Driver/Extensions/CommandHelper.cs @@ -0,0 +1,18 @@ +namespace Winium.Desktop.Driver.Extensions +{ + #region using + + using System; + + using Winium.StoreApps.Common; + + #endregion + + public static class CommandHelper + { + public static int GetParameterAsInt(this Command command, string propertyName) + { + return (int)Math.Round(Convert.ToDouble(command.Parameters[propertyName])); + } + } +} diff --git a/src/Winium.Desktop.Driver/HttpRequest.cs b/src/Winium.Desktop.Driver/HttpRequest.cs index 5c9aa2f..81ea1c4 100644 --- a/src/Winium.Desktop.Driver/HttpRequest.cs +++ b/src/Winium.Desktop.Driver/HttpRequest.cs @@ -59,7 +59,11 @@ private static int GetContentLength(IReadOnlyDictionary headers) private static string ReadContent(TextReader textReader, int contentLength) { var readBuffer = new char[contentLength]; - textReader.Read(readBuffer, 0, readBuffer.Length); + var bytesRead = 0; + while (bytesRead < contentLength) + { + bytesRead += textReader.Read(readBuffer, bytesRead, contentLength - bytesRead); + } return readBuffer.Aggregate(string.Empty, (current, ch) => current + ch); } diff --git a/src/Winium.Desktop.Driver/Listener.cs b/src/Winium.Desktop.Driver/Listener.cs index d9884ac..cc6f07b 100644 --- a/src/Winium.Desktop.Driver/Listener.cs +++ b/src/Winium.Desktop.Driver/Listener.cs @@ -90,7 +90,24 @@ public void StartListening() // Get a stream object for reading and writing using (var stream = client.GetStream()) { - var acceptedRequest = HttpRequest.ReadFromStreamWithoutClosing(stream); + stream.ReadTimeout = 60 * 1000; + + HttpRequest acceptedRequest; + + try + { + acceptedRequest = HttpRequest.ReadFromStreamWithoutClosing(stream); + } + catch (IOException ex) + { + Logger.Error("Error occured while reading request: {0}", ex); + + client.Close(); + Logger.Debug("Client closed\n"); + + continue; + } + Logger.Debug("ACCEPTED REQUEST {0}", acceptedRequest.StartingLine); var response = this.HandleRequest(acceptedRequest); diff --git a/src/Winium.Desktop.Driver/UriDispatchTables.cs b/src/Winium.Desktop.Driver/UriDispatchTables.cs index aa3e610..e504ebc 100644 --- a/src/Winium.Desktop.Driver/UriDispatchTables.cs +++ b/src/Winium.Desktop.Driver/UriDispatchTables.cs @@ -286,7 +286,14 @@ private void InitializeSeleniumCommandDictionary() this.commandDictionary.Add( DriverCommand.TouchFlick, new CommandInfo("POST", "/session/{sessionId}/touch/flick")); + this.commandDictionary.Add( + DriverCommand.TouchPerform, + new CommandInfo("POST", "/session/{sessionId}/touch/perform")); + this.commandDictionary.Add( + DriverCommand.TouchMultiPerform, + new CommandInfo("POST", "/session/{sessionId}/touch/multi/perform")); this.commandDictionary.Add(DriverCommand.UploadFile, new CommandInfo("POST", "/session/{sessionId}/file")); + } private void InitializeWiniumCommandDictionary() diff --git a/src/Winium.Desktop.Driver/Winium.Desktop.Driver.csproj b/src/Winium.Desktop.Driver/Winium.Desktop.Driver.csproj index bf71cd7..3d044b1 100644 --- a/src/Winium.Desktop.Driver/Winium.Desktop.Driver.csproj +++ b/src/Winium.Desktop.Driver/Winium.Desktop.Driver.csproj @@ -50,6 +50,10 @@ + + ..\packages\TCD.System.TouchInjection.1.0.0\lib\net45\TCD.System.TouchInjection.dll + True + @@ -71,6 +75,7 @@ + @@ -113,10 +118,22 @@ + + + + + + + + + + + + diff --git a/src/Winium.Desktop.Driver/packages.config b/src/Winium.Desktop.Driver/packages.config index 8a2562a..4e1f55c 100644 --- a/src/Winium.Desktop.Driver/packages.config +++ b/src/Winium.Desktop.Driver/packages.config @@ -6,5 +6,6 @@ + \ No newline at end of file diff --git a/src/Winium.StoreApps.Common/DriverCommand.cs b/src/Winium.StoreApps.Common/DriverCommand.cs index 2773f3f..d8ea9fb 100644 --- a/src/Winium.StoreApps.Common/DriverCommand.cs +++ b/src/Winium.StoreApps.Common/DriverCommand.cs @@ -461,6 +461,18 @@ public static class DriverCommand /// public static readonly string TouchSingleTap = "touchSingleTap"; + /// + /// Represents the TouchPerform command. + /// + /// + public static readonly string TouchPerform = "touchPerform"; + + /// + /// Represents the TouchMultiPerform command. + /// + /// + public static readonly string TouchMultiPerform = "touchMultiPerform"; + /// /// Represents the UploadFile command. ///