diff options
Diffstat (limited to 'Xamarin.Forms.Core.iOS.UITests/Utilities')
8 files changed, 1132 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs new file mode 100644 index 00000000..c6f2508c --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NUnit.Framework; + +using Xamarin.UITest; +using Xamarin.UITest.Android; +using Xamarin.UITest.iOS; +using Xamarin.UITest.Queries; +using System.Text.RegularExpressions; + +namespace Xamarin.Forms.Core.UITests +{ + internal static class AppExtensions + { + public static AppRect ScreenBounds (this IApp app) + { + return app.Query (Queries.Root ()).First().Rect; + } + + public static void NavigateBack (this IApp app) + { + app.Tap (Queries.NavigationBarBackButton ()); + } + + public static void NavigateToGallery (this IApp app, string page) + { + var text = Regex.Match (page, "'(?<text>[^']*)'").Groups["text"].Value; + app.EnterText (q => q.Raw ("* marked:'SearchBar'"), text); + //var searchBar = app.Query (q => q.Raw ("* marked:'SearchBar'")).Single (); + Thread.Sleep(10000); + + app.Tap (q => q.Raw ("* marked:'GoToTestButton'")); + app.WaitForNoElement (o => o.Raw ("* marked:'GoToTestButton'"), "Timed out", TimeSpan.FromMinutes(2)); + + //app.Screenshot ("Navigating to gallery ..."); + //var galleryListViewBounds = app.Query (Queries.GalleryListView)[0].Rect; + //app.ScrollForElement (page, new Drag (galleryListViewBounds, Drag.Direction.BottomToTop, Drag.DragLength.Long)); + //app.Tap (q => q.Raw (page)); + //app.Screenshot ("At gallery!"); + } + + public static void NavigateToTestCases (this IApp app, string testCase) + { + app.Tap (q => q.Button ("Go to Test Cases")); + app.WaitForElement (q => q.Raw ("* marked:'TestCasesIssueList'")); + + app.EnterText (q => q.Raw ("* marked:'SearchBarGo'"), testCase); + + app.WaitForElement (q => q.Raw ("* marked:'SearchButton'")); + app.Tap (q => q.Raw ("* marked:'SearchButton'")); + + //app.NavigateToTestCase(testCase); + } + + public static void NavigateToTestCase (this IApp app, string testCase) + { + string testCasesQuery = "* marked:'" + testCase + "'"; + var testCaseIssue = app.Query (q => q.Raw ("* marked:'TestCasesIssueList'")).FirstOrDefault (); + if (testCaseIssue != null) { + AppRect scrollRect = testCaseIssue.Rect; + app.ScrollForElement (testCasesQuery, new Drag (scrollRect, Drag.Direction.BottomToTop, Drag.DragLength.Long)); + app.Tap (q => q.Raw (testCasesQuery)); + } else { + Debug.WriteLine (string.Format ("Failed to find test case {0}", testCase)); + } + } + + public static bool RectsEqual (AppRect rectOne, AppRect rectTwo) + { + const float equalsTolerance = 0.1f; + + bool areEqual = + (Math.Abs (rectOne.X - rectTwo.X) < equalsTolerance) && + (Math.Abs (rectOne.Y - rectTwo.Y) < equalsTolerance) && + (Math.Abs (rectOne.Width - rectTwo.Width) < equalsTolerance) && + (Math.Abs (rectOne.Height - rectTwo.Height) < equalsTolerance) && + (Math.Abs (rectOne.CenterX - rectTwo.CenterX) < equalsTolerance) && + (Math.Abs (rectOne.CenterY - rectTwo.CenterY) < equalsTolerance); + + return areEqual; + } + + public static void WaitForAnimating (this IApp app, Func<AppQuery, AppQuery> query) + { + // Right now only checks if bounds are moving + const int pollingRate = 200; + const int timeout = 5000; + var sw = new Stopwatch (); + + var previousState = app.Query (query).First ().Rect; + + sw.Start (); + while (true) { + + var newState = app.Query (query).First ().Rect; + + if (RectsEqual (previousState, newState)) + break; + + previousState = newState; + + if (sw.ElapsedMilliseconds >= timeout) + throw new Exception("Timed out"); + + Thread.Sleep (pollingRate); + } + sw.Stop (); + } + } +} diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs new file mode 100644 index 00000000..71b1fa03 --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs @@ -0,0 +1,173 @@ +using System.Reflection.Emit; + +using Xamarin.UITest.Queries; + +namespace Xamarin.Forms.Core.UITests +{ + internal class Drag + { + internal enum DragLength + { + Long, + Medium, + Short + } + + internal enum Direction + { + TopToBottom, + BottomToTop, + RightToLeft, + LeftToRight + } + + AppRect dragBounds; + float xStart; + float yStart; + float xEnd; + float yEnd; + Direction dragDirection; + Direction oppositeDirection; + DragLength dragLength; + + public Drag (AppRect dragbounds, float xStart, float yStart, float xEnd, float yEnd, Direction direction) + { + dragBounds = dragbounds; + this.xStart = xStart; + this.yStart = yStart; + this.xEnd = xEnd; + this.yEnd = yEnd; + dragDirection = direction; + oppositeDirection = GetOppositeDirection (direction); + } + + public Drag (AppRect dragBounds, Direction direction, DragLength dragLength) + { + this.dragBounds = dragBounds; + dragDirection = direction; + this.dragLength = dragLength; + SetDragForBounds (dragDirection, dragLength); + } + + void SetDragForBounds (Direction direction, DragLength dragLength) + { + // percentage of bounds to scroll centered in element + float scrollPercentage; + + switch (dragLength) { + case DragLength.Long: + scrollPercentage = 0.8f; + break; + case DragLength.Medium: + scrollPercentage = 0.5f; + break; + default: + scrollPercentage = 0.2f; + break; + } + + if (direction == Direction.LeftToRight) { + yStart = dragBounds.CenterY; + yEnd = dragBounds.CenterY; + float xDisplacement = (dragBounds.CenterX + (dragBounds.Width / 2)) - dragBounds.X; + float insetForScroll = (xDisplacement - (xDisplacement * scrollPercentage)) / 2; + xStart = dragBounds.X + insetForScroll; + xEnd = (dragBounds.CenterX + (dragBounds.Width / 2)) - insetForScroll; + } else if (direction == Direction.RightToLeft) { + yStart = dragBounds.CenterY; + yEnd = dragBounds.CenterY; + float xDisplacement = (dragBounds.CenterX + (dragBounds.Width / 2)) - dragBounds.X; + float insetForScroll = (xDisplacement - (xDisplacement * scrollPercentage)) / 2; + xStart = (dragBounds.CenterX + (dragBounds.Width / 2)) - insetForScroll; + xEnd = dragBounds.X + insetForScroll; + } else if (direction == Direction.TopToBottom) { + xStart = dragBounds.CenterX; + xEnd = dragBounds.CenterX; + float yDisplacement = (dragBounds.CenterY + (dragBounds.Height / 2)) - dragBounds.Y; + float insetForScroll = (yDisplacement - (yDisplacement * scrollPercentage)) / 2; + yStart = dragBounds.Y + insetForScroll; + yEnd = (dragBounds.CenterY + (dragBounds.Height / 2)) - insetForScroll; + } else if (direction == Direction.BottomToTop) { + xStart = dragBounds.CenterX; + xEnd = dragBounds.CenterX; + float yDisplacement = (dragBounds.CenterY + (dragBounds.Height / 2)) - dragBounds.Y; + float insetForScroll = (yDisplacement - (yDisplacement * scrollPercentage)) / 2; + yStart = (dragBounds.CenterY + (dragBounds.Height / 2)) - insetForScroll; + yEnd = dragBounds.Y + insetForScroll; + + } + } + + Direction GetOppositeDirection (Direction direction) + { + switch (direction) { + case Direction.TopToBottom: + return Direction.BottomToTop; + case Direction.BottomToTop: + return Direction.TopToBottom; + case Direction.RightToLeft: + return Direction.LeftToRight; + case Direction.LeftToRight: + return Direction.RightToLeft; + default: + return Direction.TopToBottom; + } + } + + public AppRect DragBounds + { + get { return dragBounds; } + } + + public float XStart + { + get { return xStart; } + } + + public float YStart + { + get { return yStart; } + } + + public float XEnd + { + get { return xEnd; } + } + + public float YEnd + { + get { return yEnd; } + } + + public Direction DragDirection + { + get { return dragDirection; } + set + { + if (dragDirection == value) + return; + + dragDirection = value; + oppositeDirection = GetOppositeDirection (dragDirection); + OnDragDirectionChanged (); + } + } + + void OnDragDirectionChanged () + { + SetDragForBounds (dragDirection, dragLength); + } + + public Direction OppositeDirection + { + get { return oppositeDirection; } + private set + { + if (oppositeDirection == value) + return; + + oppositeDirection = value; + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs new file mode 100644 index 00000000..548ff06d --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs @@ -0,0 +1,114 @@ +using System; +using System.Dynamic; +using System.Linq; +using System.Security.Cryptography; + +using Xamarin.UITest; +using Xamarin.UITest.Android; +using Xamarin.UITest.iOS; +using Xamarin.UITest.Queries; + +namespace Xamarin.Forms.Core.UITests +{ + internal static class Gestures + { + public static bool ScrollForElement (this IApp app, string query, Drag drag, int maxSteps = 25) + { + int count = 0; + + int centerTolerance = 50; + + Func<AppQuery, AppQuery> elementQuery = q => q.Raw (query); + + // Visible elements + if (app.Query (elementQuery).Length > 1) { + throw new UITestQueryMultipleResultsException (query); + } + + // check to see if the element is visible already + if (app.Query (elementQuery).Length == 1) { + // centering an element whos CenterX is close to the bounding rectangle's center X can sometime register the swipe as a tap + float elementDistanceToDragCenter = Math.Abs (app.Query (elementQuery).First ().Rect.CenterY - drag.DragBounds.CenterY); + if (elementDistanceToDragCenter > centerTolerance) + app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection); + return true; + } + + // loop until element is seen + while (app.Query (elementQuery).Length == 0 && count < maxSteps) { + app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd); + count++; + } + + if (count != maxSteps) { + // centering an element whos CenterX is close to the bounding rectangle's center X can sometime register the swipe as a tap + float elementDistanceToDragCenter = Math.Abs (app.Query (elementQuery).First ().Rect.CenterY - drag.DragBounds.CenterY); + if (elementDistanceToDragCenter > centerTolerance) + app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection); + return true; + } + + count = 0; + drag.DragDirection = drag.OppositeDirection; + + while (app.Query (elementQuery).Length == 0 && count < maxSteps) { + app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd); + count++; + } + + if (count != maxSteps) { + app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection); + return true; + } + + return false; + } + + static void CenterElementInView (this IApp app, Func<AppQuery, AppQuery> element, AppRect containingView, Drag.Direction direction) + { + // TODO Implement horizontal centering + + if (direction == Drag.Direction.BottomToTop || direction == Drag.Direction.TopToBottom) { + + var elementBounds = app.Query (element).First ().Rect; + + bool elementCenterBelowContainerCenter = elementBounds.CenterY > containingView.CenterY; + bool elementCenterAboveContainerCenter = elementBounds.CenterY < containingView.CenterY; + + var displacementToCenter = Math.Abs (elementBounds.CenterY - containingView.CenterY) / 2; + + // avoid drag as touch + if (displacementToCenter < 50) + return; + + if (elementCenterBelowContainerCenter) { + + var drag = new Drag ( + containingView, + containingView.CenterX, containingView.CenterY + displacementToCenter, + containingView.CenterX, containingView.CenterY - displacementToCenter, + Drag.Direction.BottomToTop + ); + + app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd); + + } else if (elementCenterAboveContainerCenter) { + + var drag = new Drag ( + containingView, + containingView.CenterX, containingView.CenterY - displacementToCenter, + containingView.CenterX, containingView.CenterY + displacementToCenter, + Drag.Direction.TopToBottom + ); + + app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd); + } + } + } + + public static void Pan (this IApp app, Drag drag) + { + app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs new file mode 100644 index 00000000..ed0041ae --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Reflection; + +using Xamarin.UITest.Queries; + +namespace Xamarin.Forms.Core.UITests +{ + internal static class Logger + { + static StreamWriter queryWriter; + + public static void Init () + { + queryWriter = new StreamWriter ("../../Xamarin.Forms.Core-UITest-queries.log", false); + } + + public static void Log (string text) + { + queryWriter.Write (text); + } + + public static void LogLine (string text = "") + { + queryWriter.WriteLine (text); + } + + public static void Close () + { + queryWriter.Flush (); + queryWriter.Close (); + } + + public static void LogQueryResult (AppResult[] resultsForQuery) + { + foreach (AppResult result in resultsForQuery) + WriteAppResult (result); + } + + static void WriteAppResult (AppResult appResult) + { + var classText = string.Format (" {0, -10} : {1}", "Class", appResult.Class); + var descriptionText = string.Format (" {0, -10} : {1}", "Description", appResult.Description); + var enabledText = string.Format (" {0, -10} : {1}", "Enabled", appResult.Enabled); + var idText = string.Format (" {0, -10} : {1}", "Id", appResult.Id); + var labelText = string.Format (" {0, -10} : {1}", "Label", appResult.Id); + var textText = string.Format (" {0, -10} : {1}", "Text", appResult.Text); + + var rectText = string.Format (" {0, -10}", "Rect"); + var rectContentsText = string.Format (" [X:{0} Y:{1} W:{2} H:{3}] [CX:{4} CY:{5}]", + appResult.Rect.X, + appResult.Rect.Y, + appResult.Rect.Width, + appResult.Rect.Height, + appResult.Rect.CenterX, + appResult.Rect.CenterY + ); + + queryWriter.WriteLine (classText); + queryWriter.WriteLine (descriptionText); + queryWriter.WriteLine (enabledText); + queryWriter.WriteLine (idText); + queryWriter.WriteLine (labelText); + queryWriter.WriteLine (textText); + queryWriter.WriteLine (rectText); + queryWriter.WriteLine (rectContentsText); + queryWriter.WriteLine(); + } + + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs new file mode 100644 index 00000000..13a4b2bf --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.Remoting.Messaging; + +using NUnit.Framework; + +using Xamarin.UITest; +using Xamarin.UITest.Queries; +using Xamarin.UITest.Android; +using Xamarin.UITest.iOS; +using System.Globalization; + +namespace Xamarin.Forms.Core.UITests +{ + internal class Matrix : Object + { + public double M00, M01, M02, M03; + public double M10, M11, M12, M13; + public double M20, M21, M22, M23; + public double M30, M31, M32, M33; + + public void Log () { + + //Logger.LogLine (); + + //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M00, M01, M02, M03)); + //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M10, M11, M12, M13)); + //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M20, M21, M22, M23)); + //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M30, M31, M32, M33)); + + //Logger.LogLine (); + } + + public override bool Equals (object obj) + { + if (obj == null) + return false; + + var transform = obj as Matrix; + if ((Object)transform == null) + return false; + + const double tolerance = 0.01; + bool result = + Math.Abs (M00 - transform.M00) < tolerance && + Math.Abs (M01 - transform.M01) < tolerance && + Math.Abs (M02 - transform.M02) < tolerance && + Math.Abs (M03 - transform.M03) < tolerance && + Math.Abs (M10 - transform.M10) < tolerance && + Math.Abs (M11 - transform.M11) < tolerance && + Math.Abs (M12 - transform.M12) < tolerance && + Math.Abs (M13 - transform.M13) < tolerance && + Math.Abs (M20 - transform.M20) < tolerance && + Math.Abs (M21 - transform.M21) < tolerance && + Math.Abs (M22 - transform.M22) < tolerance && + Math.Abs (M23 - transform.M23) < tolerance && + Math.Abs (M30 - transform.M30) < tolerance && + Math.Abs (M31 - transform.M31) < tolerance && + Math.Abs (M32 - transform.M32) < tolerance && + Math.Abs (M33 - transform.M33) < tolerance; + + return result; + } + + public override int GetHashCode () + { + return 0; + } + } + + internal enum Axis + { + X, + Y, + Z + } + + internal static class NumericExtensions + { + public static double ToRadians(this float val) + { + return (Math.PI / 180.0) * val; + } + + public static Matrix CalculateRotationMatrixForDegrees (float degrees, Axis rotationAxis) + { + var angle = degrees.ToRadians (); + + var transform = new Matrix (); + if (rotationAxis == Axis.X) { + transform.M00 = 1; transform.M01 = 0; transform.M02 = 0; transform.M03 = 0; + transform.M10 = 0; transform.M11 = (float) Math.Cos (angle); transform.M12 = (float) Math.Sin (angle); transform.M13 = 0; + transform.M20 = 0; transform.M21 = -(float) Math.Sin (angle); transform.M22 = (float) Math.Cos (angle); transform.M23 = 0; + transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1; + } else if (rotationAxis == Axis.Y) { + transform.M00 = (float) Math.Cos (angle); transform.M01 = 0; transform.M02 = -(float) Math.Sin (angle); transform.M03 = 0; + transform.M10 = 0; transform.M11 = 1; transform.M12 = 0; transform.M13 = 0; + transform.M20 = (float) Math.Sin (angle); transform.M21 = 0; transform.M22 = (float) Math.Cos (angle); transform.M23 = 0; + transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1; + } else { + transform.M00 = (float) Math.Cos (angle); transform.M01 = (float) Math.Sin (angle); transform.M02 = 0; transform.M03 = 0; + transform.M10 = -(float) Math.Sin (angle); transform.M11 = (float) Math.Cos (angle); transform.M12 = 0; transform.M13 = 0; + transform.M20 = 0; transform.M21 = 0; transform.M22 = 1; transform.M23 = 0; + transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1; + } + + return transform; + } + + public static Matrix BuildScaleMatrix (float scale) + { + var transform = new Matrix (); + + transform.M00 = scale; transform.M01 = 0; transform.M02 = 0; transform.M03 = 0; + transform.M10 = 0; transform.M11 = scale; transform.M12 = 0; transform.M13 = 0; + transform.M20 = 0; transform.M21 = 0; transform.M22 = scale; transform.M23 = 0; + transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1; + + return transform; + } + + } + +}
\ No newline at end of file diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs new file mode 100644 index 00000000..6598e0f5 --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.Remoting.Messaging; + +using NUnit.Framework; + +using Xamarin.UITest; +using Xamarin.UITest.Queries; +using Xamarin.UITest.Android; +using Xamarin.UITest.iOS; +using System.Globalization; +using System.Text.RegularExpressions; +using System.IO; + +namespace Xamarin.Forms.Core.UITests +{ + + internal static class ParsingUtils + { + public static Font ParseUIFont (string font) + { + FontAttributes fontAttrs = FontAttributes.None; + + // Logger.LogLine ("TEST PARSING"); + + if (font.Contains ("font-weight: bold;")) { + // Logger.LogLine ("Found Bold"); + fontAttrs = FontAttributes.Bold; + } + + return new Font ().WithAttributes (fontAttrs); + } + + public static Color ParseUIColor (string backgroundColor) + { + var delimiters = new char[] { ' ' }; + string[] words = backgroundColor.Split (delimiters, StringSplitOptions.RemoveEmptyEntries); + return new Color (double.Parse (words[1]), double.Parse (words[2]), double.Parse (words[3]), double.Parse (words[4])); + } + + public static Point ParseCGPoint (object CGPoint) { + var point = new Point { X = 0, Y = 0 }; + return point; + } + + public static Matrix ParseCATransform3D (string CATransform3D) + { + // Logger.Log (CATransform3D); + char[] delimiters = { '<', ' ', '>' }; + string[] words = CATransform3D.Split (delimiters, StringSplitOptions.RemoveEmptyEntries); + + List<double> numbers = new List<double> (); + + // Each number is represented by 2 blocks returned by server + for (int i = 0; i < (words.Length - 1); i += 2) { + string word = words[i] + words[i + 1]; + var number = Int64.Parse (word, NumberStyles.HexNumber); + byte[] bytes = BitConverter.GetBytes (number); + byte[] reversedBytes = bytes.Reverse ().ToArray (); + double value = BitConverter.ToDouble (reversedBytes, 0); + numbers.Add (value); + } + + var transformationMatrix = new Matrix (); + transformationMatrix.M00 = numbers[0]; + transformationMatrix.M01 = numbers[1]; + transformationMatrix.M02 = numbers[2]; + transformationMatrix.M03 = numbers[3]; + transformationMatrix.M10 = numbers[4]; + transformationMatrix.M11 = numbers[5]; + transformationMatrix.M12 = numbers[6]; + transformationMatrix.M13 = numbers[7]; + transformationMatrix.M20 = numbers[8]; + transformationMatrix.M21 = numbers[9]; + transformationMatrix.M22 = numbers[10]; + transformationMatrix.M23 = numbers[11]; + transformationMatrix.M30 = numbers[12]; + transformationMatrix.M31 = numbers[13]; + transformationMatrix.M32 = numbers[14]; + transformationMatrix.M33 = numbers[15]; + + return transformationMatrix; + } + + } + +}
\ No newline at end of file diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs new file mode 100644 index 00000000..6969ac52 --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xamarin.UITest.Queries; +using System.Runtime.CompilerServices; + +namespace Xamarin.Forms.Core.UITests +{ + internal class UITestQueryNoResultException : Exception + { + readonly string message; + + public UITestQueryNoResultException (string query) + { + message = string.Format ("Found no elements for query with target: {0}", query); + } + + public override string Message + { + get { return message; } + } + } + + internal class UITestQuerySingleResultException : Exception + { + readonly string message; + + public UITestQuerySingleResultException (string query) + { + message = string.Format ("Found single element for query with target: {0}", query); + } + + public override string Message + { + get { return message; } + } + } + + internal class UITestQueryMultipleResultsException : Exception + { + readonly string message; + + public UITestQueryMultipleResultsException (string query) + { + message = string.Format ("Found muliple elements for query with target: {0}", query); + } + + public override string Message + { + get { return message; } + } + } + + internal class UITestRemoteException : Exception + { + readonly string message; + + public UITestRemoteException (string message) + { + this.message = message; + } + + public override string Message + { + get { return message; } + } + } + + internal class UITestRemoteQueryException : Exception + { + readonly string message; + + public UITestRemoteQueryException (string query) + { + message = string.Format ("Error for query with target: {0}", query); + } + + public override string Message + { + get { return message; } + } + } + + internal class UITestErrorException : Exception + { + readonly string message; + + public UITestErrorException (string message, [CallerMemberName] string caller = null) + { + message = string.Format ("Test error: {0}, {1}", caller, message); + } + + public override string Message + { + get { return message; } + } + } +} diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs new file mode 100644 index 00000000..288ee3d6 --- /dev/null +++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; + +using Xamarin.UITest; +using Xamarin.UITest.Android; +using Xamarin.UITest.iOS; +using System.Linq; + +namespace Xamarin.Forms.Core.UITests +{ + internal static class ViewInspector + { + public static void LogPropertiesForView (this IApp app, string query, bool isOnParent = false) + { + if (app is AndroidApp) { + LogPropertiesForAndroidView ((AndroidApp)app, query, isOnParent); + } else { + LogPropertiesForUIView ((iOSApp)app, query, isOnParent); + LogPropertiesForCALayer ((iOSApp)app, query, isOnParent); + } + } + + static void LogPropertiesForUIView (this iOSApp app, string query, bool isOnParent = false) { + + //Logger.LogLine ("--- UIView Properties ---"); + + var properties = new [] { + // just getters with no params, bools + "alpha", + "autoresizesSubviews", + "autoresizingMask", + "backgroundColor", + "bounds", + "center", + "clearsContextBeforeDrawing", + "clipsToBounds", + "contentMode", + "contentScaleFactor", + "exclusiveTouch", + "frame", + "gestureRecognizers", + "hidden", + "layer", + "motionEffects", + "multipleTouchEnabled", + "opaque", + "restorationIdentifier", + "subviews", + "superview", + "tag", + "tintAdjustmentMode", + "tintColor", + "transform", + "userInteractionEnabled", + "window" + }; + + if (isOnParent) + query = query + " parent * index:0"; + + foreach (var property in properties) { + object prop; + bool found = + MaybeGetProperty<string> (app, query, property, out prop) || + MaybeGetProperty<int> (app, query, property, out prop) || + MaybeGetProperty<float> (app, query, property, out prop) || + MaybeGetProperty<bool> (app, query, property, out prop); + + //if (found) + // Logger.LogLine (string.Format ("{0,-30}: {1}", property, prop)); + } + + //Logger.LogLine(); + + } + + static void LogPropertiesForCALayer(this iOSApp app, string query, bool isOnParent = false) + { + // Logger.LogLine ("--- UIView.Layer Properties ---"); + + var properties = new[] { + "actions", + "anchorPoint", + "anchorPointZ", + "backgroundColor", + "backgroundFilters", + "borderColor", + "borderWidth", + "bounds", + "compositingFilter", + "contents", + "contentsCenter", + "contentsGravity", + "contentsRect", + "contentsScale", + "cornerRadius", + "delegate", + "doubleSided", + "drawsAsynchronously", + "edgeAntialiasingMask", + "filters", + "frame", + "geometryFlipped", + "hidden", + "magnificationFilter", + "mask", + "masksToBounds", + "minificationFilter", + "minificationFilterBias", + "name", + "needsDisplayOnBoundsChange", + "opacity", + "opaque", + "position", + "rasterizationScale", + "shadowColor", + "shadowOffset", + "shadowOpacity", + "shadowPath", + "shadowRadius", + "shouldRasterize", + "style", + "sublayers", + "sublayerTransform", + "superlayer", + "transform", + "visibleRect", + "zPosition" + }; + + if (isOnParent) + query = query + " parent * index:0"; + + foreach (var property in properties) + { + object prop; + bool found = + MaybeGetLayerProperty<string>(app, query, property, out prop) || + MaybeGetLayerProperty<int>(app, query, property, out prop) || + MaybeGetLayerProperty<bool>(app, query, property, out prop); + + //if (found) + // Logger.LogLine(string.Format("{0,-30}: {1}", property, prop)); + } + + //Logger.LogLine(); + + } + + static void LogPropertiesForAndroidView (this AndroidApp app, string query, bool isOnParent = false) + { + // Logger.LogLine( "--- Android View Properties ---"); + + var properties = new [] { + // just getters with no params, bools + //"getAccessibilityLiveRegion", + //"getAccessibilbityNodeProvider", + //"getAlpha", + //"getAnimation", + //"getApplicationWindowToken", + //"getBackground", + //"getBaseline", + //"getBottom", + //"getCameraDistance", + //"getClipBounds", + //"getContentDescription", + //"getContext", + //"getDefaultSize", + //"getDisplay", + //"getDrawableState", + //"getDrawingCache", + //"getDrawingCacheBackgroundColor", + //"getDrawingRect", + //"getDrawingTime", + //"getFilterTouchesWhenObscurred", + //"getFitsSystemWindows", + //"getFocusables", + //"getHandler", + //"getHeight", + //"getHitRect", + //"getHorizontalFadingEdgeLength", + //"getId", + //"getImportantForAccessibility", + //"getKeepScreenOn", + //"getKeyDispatcherState", + //"getLabelFor", + //"getLayerType", + //"getLayoutDirection", + //"getLayourParams", + //"getLeft", + "getMatrix", + //"getMeasuredHeight", + //"getMeasuredHeightAndState", + //"getMeasuredState", + //"getMeasuredWidth", + //"getMeasuredWidthAndState", + //"getMinimumHeight", + //"getMinimumWidth", + //"getNextFocusDownId", + //"getNextFocusForwardId", + //"getNextFocusLeftId", + //"getNextFocusRightId", + //"getNextFocusUpId", + //"getOnFocusChangedListener", + //"getOverScrollMethod", + //"getOverlay", + //"getPaddingBottom", + //"getPaddingEnd", + //"getPaddingLeft", + //"getPaddingRight", + //"getPaddingStart", + //"getPaddingTop", + //"getParent", + //"getParentForAccessibility", + //"getPivotX", + //"getPivotY", + //"getResources", + //"getRight", + //"getRootView", + //"getRotation", + //"getRotationX", + //"getRotationY", + "getScaleX", + "getScaleY", + //"getScrollBarDefaultDelayBeforeFade", + //"getScrollBarFadeDuration", + //"getScrollBarSize", + //"getScrollBarStyle", + //"getScrollX", + //"getScrollY", + //"getSolidColor", + //"getSystemUiVisibility", + //"getTag", + //"getTextAlignment", + //"getTextDirection", + //"getTop", + //"getTouchDelegate", + //"getTouchables", + //"getTranslationX", + //"getTranslationY", + //"getVerticalFadingEdgeLength", + //"getVerticalScrollbarPosition", + //"getVerticalScrollbarWidth", + //"getViewTreeObserver", + //"getVisibility", + //"getWidth", + //"getWindowId", + //"getWindowSystemUiVisbility", + //"getWindowToken", + //"getWindowVisibility", + //"getX", + //"getY", + //"hasFocus", + //"hasFocusable", + //"hasOnClickListener", + //"hasOverlappingRendering", + //"hasTransientState", + //"hasWindowFocus", + //"isActivated", + //"isAttachedToWindow", + //"isClickable", + //"isDirty", + //"isDrawingCacheEnabled", + //"isDuplicateParentStateEnabled", + //"isEnabled", + //"isFocusable", + //"isFocusableInTouchWindow", + //"isFocused", + //"isHapticFeedbackEnabled", + //"isHardwareAccelerated", + //"isHorizontalFadingEdgeEnabled", + //"isHovered", + //"idInEditMode", + //"isInLayout", + //"isInTouchMode", + //"isLaidOut", + //"isLayoutDirectionResolved", + //"isLayoutRequested", + //"isLongClickable", + //"isOpaque", + //"isPaddingRelative", + //"isPressed", + //"isSaveEnabled", + //"isSaveFromParentEnabled", + //"isScrollContainer", + //"isScrollBarFadingEnabled", + //"isSelected", + //"isShown", + //"isSoundEffectsEnabled", + //"isTextAlignmentResolved", + //"isTextDirectionResolved", + //"isVerticalFadingEdgeEnabled", + //"isVerticalScrollBarEnabled" + }; + + if (isOnParent) + query = query + " parent * index:0"; + + foreach (var property in properties) { + object prop; + bool found = + MaybeGetProperty<string> (app, query, property, out prop) || + //MaybeGetProperty<int> (app, query, property, out prop) || + MaybeGetProperty<float> (app, query, property, out prop) || + MaybeGetProperty<bool> (app, query, property, out prop); + + //if (found) + // Logger.LogLine (string.Format ("{0,-30}: {1}", property, prop)); + } + + //Logger.LogLine(); + + } + + static bool MaybeGetLayerProperty<T> (iOSApp app, string query, string property, out object result) + { + + try { + result = app.Query (q => q.Raw (query).Invoke ("layer").Invoke (property).Value<T> ()).First (); + } catch { + result = null; + return false; + } + + return true; + } + + static bool MaybeGetProperty<T> (IApp app, string query, string property, out object result) + { + + try { + result = app.Query (q => q.Raw (query).Invoke (property).Value<T> ()).First (); + } catch { + result = null; + return false; + } + + return true; + } + } +} + |