summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs
blob: 548ff06d3d4f4a63f189271f46bf70d396d56614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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);
		}
	}
}