calabash-android 0.4.22.pre4 → 0.5.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/calabash-android +66 -45
- data/lib/calabash-android/calabash_steps.rb +0 -8
- data/lib/calabash-android/canned_steps.md +2 -30
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/operations.rb +199 -23
- data/lib/calabash-android/removed_actions.txt +52 -0
- data/lib/calabash-android/steps/assert_steps.rb +9 -24
- data/lib/calabash-android/steps/check_box_steps.rb +2 -2
- data/lib/calabash-android/steps/context_menu_steps.rb +11 -4
- data/lib/calabash-android/steps/date_picker_steps.rb +2 -2
- data/lib/calabash-android/steps/enter_text_steps.rb +13 -13
- data/lib/calabash-android/steps/l10n_steps.rb +5 -5
- data/lib/calabash-android/steps/map_steps.rb +12 -12
- data/lib/calabash-android/steps/navigation_steps.rb +12 -12
- data/lib/calabash-android/steps/press_button_steps.rb +16 -12
- data/lib/calabash-android/steps/progress_steps.rb +19 -22
- data/lib/calabash-android/steps/search_steps.rb +2 -2
- data/lib/calabash-android/steps/spinner_steps.rb +10 -2
- data/lib/calabash-android/steps/time_picker_steps.rb +2 -2
- data/lib/calabash-android/version.rb +1 -1
- data/lib/calabash-android/wait_helpers.rb +29 -1
- data/test-server/instrumentation-backend/antlr/UIQuery.g +11 -11
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/CalabashInstrumentationTestRunner.java +3 -2
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +9 -4
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java +16 -12
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/application/Backdoor.java +55 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/gestures/LongPressCoordinate.java +19 -2
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/JavaScriptExecuter.java +105 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/QueryHelper.java +27 -30
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java +27 -18
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/ComparisonOperator.java +7 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTPredicate.java +16 -4
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTWith.java +13 -6
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryUtils.java +94 -48
- metadata +5 -59
- data/lib/calabash-android/steps/additions_manual_steps.rb +0 -11
- data/lib/calabash-android/steps/app_steps.rb +0 -10
- data/lib/calabash-android/steps/list_steps.rb +0 -41
- data/lib/calabash-android/steps/rotation_steps.rb +0 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressButtonNumber.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressButtonText.java +0 -27
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressImageButtonDescription.java +0 -39
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressImageButtonNumber.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/WaitForButton.java +0 -47
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/checkbox/ToggleCheckboxNumber.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/contextmenu/LongPressText.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/contextmenu/LongPressTextAndSelectFromMenuById.java +0 -26
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/contextmenu/LongPressTextAndSelectFromMenuByIndex.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/contextmenu/LongPressTextAndSelectFromMenuByText.java +0 -26
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/helpers/InspectCurrentDialog.java +0 -76
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/GetListData.java +0 -85
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/GetListItemProperties.java +0 -194
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/GetListItemText.java +0 -136
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/LongPressListItems.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/PressListItems.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/scrolling/ScrollDown.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/scrolling/ScrollUp.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/search/EnterQueryByIndex.java +0 -29
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/softkey/SelectFromMenuByText.java +0 -24
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/spinner/GetSelectedSpinnerItemText.java +0 -36
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/spinner/SelectSpinnerItemByContentDescription.java +0 -43
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/AssertGridViewContainsNoDuplicates.java +0 -72
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/AssertText.java +0 -31
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/AssertTextOfSpecificTextViewByContentDescription.java +0 -32
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/ClearTextById.java +0 -30
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/ClearTextByIndex.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/ClearTextFieldByContentDescription.java +0 -33
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/ClickOnText.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/EnterTextByContentDescription.java +0 -32
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/EnterTextById.java +0 -33
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/EnterTextByIndex.java +0 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/GetTextById.java +0 -42
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/AssertViewProperty.java +0 -141
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/ClickOnViewByDescription.java +0 -46
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/ClickOnViewById.java +0 -56
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetViewProperty.java +0 -101
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/HasView.java +0 -31
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/IsEnabled.java +0 -30
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/LongPressOnViewById.java +0 -34
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/Press.java +0 -89
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/SelectTab.java +0 -110
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/Wait.java +0 -24
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForDialogClose.java +0 -21
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForProgress.java +0 -47
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForScreen.java +0 -54
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForTab.java +0 -108
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForText.java +0 -37
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForView.java +0 -43
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForViewById.java +0 -58
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/JavaScriptOperation.java +0 -44
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/PressByCssSelector.java +0 -70
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/SetText.java +0 -64
@@ -11,58 +11,55 @@ import java.util.Map;
|
|
11
11
|
import sh.calaba.instrumentationbackend.InstrumentationBackend;
|
12
12
|
import sh.calaba.instrumentationbackend.actions.webview.CalabashChromeClient.WebFuture;
|
13
13
|
import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
|
14
|
+
|
15
|
+
import android.os.Build;
|
14
16
|
import android.util.Log;
|
15
17
|
import android.webkit.ValueCallback;
|
16
18
|
import android.webkit.WebView;
|
17
19
|
|
18
20
|
public class QueryHelper {
|
19
21
|
|
20
|
-
|
22
|
+
|
21
23
|
@SuppressWarnings("unchecked")
|
22
24
|
public static Map<String, Object> findFirstVisibleRectangle(List<HashMap<String,Object>> elements) {
|
23
|
-
return (Map<String, Object>)findFirstVisibleElement(elements).get("rect");
|
25
|
+
return (Map<String, Object>)findFirstVisibleElement(elements).get("rect");
|
24
26
|
}
|
25
|
-
|
27
|
+
|
26
28
|
public static Map<String, Object> findFirstVisibleElement(List<HashMap<String,Object>> elements) {
|
27
29
|
//TODO: Should do something more intelligent
|
28
|
-
return (Map<String, Object>)elements.get(0);
|
30
|
+
return (Map<String, Object>)elements.get(0);
|
29
31
|
}
|
30
|
-
|
32
|
+
|
31
33
|
public static float translateCoordToScreen(int offset, float scale, Object point) {
|
32
34
|
return offset + ((Number)point).floatValue() *scale;
|
33
35
|
}
|
34
|
-
|
35
|
-
public static Map<String,
|
36
|
+
|
37
|
+
public static Map<String, Integer> translateRectToScreenCoordinates(WebView webView, Map<String, Integer> rectangle) {
|
36
38
|
try {
|
37
|
-
|
38
39
|
float scale = webView.getScale();
|
39
40
|
|
40
41
|
int[] webviewLocation = new int[2];
|
41
42
|
webView.getLocationOnScreen(webviewLocation);
|
42
43
|
//center_x, center_y
|
43
44
|
//left, top, width, height
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
result.put("
|
54
|
-
result.put("
|
55
|
-
|
56
|
-
result.put("center_y",center_y);
|
57
|
-
|
45
|
+
int center_x = (int)translateCoordToScreen(webviewLocation[0], scale, rectangle.get("center_x"));
|
46
|
+
int center_y = (int)translateCoordToScreen(webviewLocation[1], scale, rectangle.get("center_y"));
|
47
|
+
|
48
|
+
int x = (int)translateCoordToScreen(webviewLocation[0], scale, rectangle.get("left"));
|
49
|
+
int y = (int)translateCoordToScreen(webviewLocation[0], scale, rectangle.get("top"));
|
50
|
+
Map<String,Integer> result = new HashMap<String, Integer>(rectangle);
|
51
|
+
|
52
|
+
result.put("x", x);
|
53
|
+
result.put("y", y);
|
54
|
+
result.put("center_x", center_x);
|
55
|
+
result.put("center_y", center_y);
|
56
|
+
|
58
57
|
return result;
|
59
|
-
|
60
|
-
|
61
58
|
} catch (Exception e) {
|
62
59
|
throw new RuntimeException(e);
|
63
60
|
}
|
64
61
|
}
|
65
|
-
|
62
|
+
|
66
63
|
public static String toJsonString(Object o) {
|
67
64
|
//http://www.mkyong.com/java/how-to-convert-java-map-to-from-json-jackson/
|
68
65
|
try {
|
@@ -71,7 +68,7 @@ public class QueryHelper {
|
|
71
68
|
throw new RuntimeException(e);
|
72
69
|
}
|
73
70
|
}
|
74
|
-
|
71
|
+
|
75
72
|
|
76
73
|
private static String readJavascriptFromAsset(String scriptPath) {
|
77
74
|
StringBuffer script = new StringBuffer();
|
@@ -88,7 +85,7 @@ public class QueryHelper {
|
|
88
85
|
}
|
89
86
|
return script.toString();
|
90
87
|
}
|
91
|
-
|
88
|
+
|
92
89
|
public static WebFuture executeAsyncJavascriptInWebviews(WebView webView,
|
93
90
|
String scriptPath, String selector, String type) {
|
94
91
|
|
@@ -99,12 +96,12 @@ public class QueryHelper {
|
|
99
96
|
|
100
97
|
CalabashChromeClient chromeClient = CalabashChromeClient.prepareWebView(webView);
|
101
98
|
|
102
|
-
if (
|
103
|
-
|
99
|
+
if (Build.VERSION.SDK_INT < 19) { // Android 4.4
|
100
|
+
JavaScriptExecuter javaScriptExecuter = new JavaScriptExecuter(webView);
|
101
|
+
javaScriptExecuter.executeJavaScript("calabash_result = " + script + ";prompt('calabash:' + calabash_result);");
|
104
102
|
} else {
|
105
103
|
chromeClient.evaluateCalabashScript(script);
|
106
104
|
}
|
107
|
-
|
108
105
|
return chromeClient.getResult();
|
109
106
|
}
|
110
107
|
}
|
data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java
CHANGED
@@ -15,17 +15,18 @@ import android.widget.TextView;
|
|
15
15
|
public class ViewMapper {
|
16
16
|
|
17
17
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
18
|
-
public static Object extractDataFromView(View v) {
|
19
|
-
|
18
|
+
public static Object extractDataFromView(View v) {
|
19
|
+
|
20
20
|
Map data = new HashMap();
|
21
|
-
data.put("class", getClassNameForView(v));
|
21
|
+
data.put("class", getClassNameForView(v));
|
22
22
|
data.put("description", v.toString());
|
23
23
|
data.put("contentDescription", getContentDescriptionForView(v));
|
24
24
|
data.put("enabled", v.isEnabled());
|
25
|
-
|
25
|
+
|
26
26
|
data.put("id", getIdForView(v));
|
27
|
+
data.put("tag", getTagForView(v));
|
27
28
|
|
28
|
-
Map rect = getRectForView(v);
|
29
|
+
Map<String,Integer> rect = getRectForView(v);
|
29
30
|
|
30
31
|
data.put("rect", rect);
|
31
32
|
|
@@ -45,19 +46,20 @@ public class ViewMapper {
|
|
45
46
|
|
46
47
|
}
|
47
48
|
|
48
|
-
|
49
|
-
|
49
|
+
public static Map<String, Integer> getRectForView(View v) {
|
50
|
+
Map<String,Integer> rect = new HashMap<String,Integer>();
|
50
51
|
int[] location = new int[2];
|
51
52
|
v.getLocationOnScreen(location);
|
52
53
|
|
53
54
|
rect.put("x", location[0]);
|
54
55
|
rect.put("y", location[1]);
|
55
|
-
|
56
|
-
rect.put("center_x", location[0] + v.getWidth()/2.0);
|
57
|
-
rect.put("center_y", location[1] + v.getHeight()/2.0);
|
58
|
-
|
56
|
+
|
57
|
+
rect.put("center_x", (int)(location[0] + v.getWidth()/2.0));
|
58
|
+
rect.put("center_y", (int)(location[1] + v.getHeight()/2.0));
|
59
|
+
|
59
60
|
rect.put("width", v.getWidth());
|
60
61
|
rect.put("height", v.getHeight());
|
62
|
+
|
61
63
|
return rect;
|
62
64
|
}
|
63
65
|
|
@@ -82,26 +84,33 @@ public class ViewMapper {
|
|
82
84
|
return id;
|
83
85
|
}
|
84
86
|
|
87
|
+
public static String getTagForView(View v) {
|
88
|
+
if (v.getTag() instanceof String || v.getTag() instanceof Integer) {
|
89
|
+
return v.getTag().toString();
|
90
|
+
}
|
91
|
+
return null;
|
92
|
+
}
|
93
|
+
|
85
94
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
86
95
|
public static Object mapView(Object o) {
|
87
96
|
if (o instanceof View) {
|
88
97
|
return extractDataFromView((View) o);
|
89
|
-
}
|
90
|
-
else if (o instanceof Map) {
|
91
|
-
Map copy = new HashMap();
|
98
|
+
}
|
99
|
+
else if (o instanceof Map) {
|
100
|
+
Map copy = new HashMap();
|
92
101
|
for (Object e : ((Map) o).entrySet()) {
|
93
102
|
Map.Entry entry = (Entry) e;
|
94
103
|
Object value = entry.getValue();
|
95
104
|
if (value instanceof View) {
|
96
105
|
copy.put(entry.getKey(), UIQueryUtils.getId((View) value));
|
97
|
-
}
|
106
|
+
}
|
98
107
|
else {
|
99
108
|
copy.put(entry.getKey(),entry.getValue());
|
100
|
-
}
|
109
|
+
}
|
101
110
|
}
|
102
|
-
|
111
|
+
|
103
112
|
return copy;
|
104
|
-
}
|
113
|
+
}
|
105
114
|
else if (o instanceof CharSequence) {
|
106
115
|
return o.toString();
|
107
116
|
}
|
@@ -25,7 +25,13 @@ public enum ComparisonOperator implements UIQueryASTPredicateRelation {
|
|
25
25
|
if (firstValue == secondValue) {
|
26
26
|
return true;
|
27
27
|
}
|
28
|
-
return (firstValue != null) && firstValue.equals(secondValue);
|
28
|
+
return (firstValue != null) && firstValue.equals(secondValue);
|
29
|
+
}
|
30
|
+
},
|
31
|
+
|
32
|
+
NOTEQUAL {
|
33
|
+
public boolean areRelated(Object firstValue, Object secondValue) {
|
34
|
+
return !EQUAL.areRelated(firstValue, secondValue);
|
29
35
|
}
|
30
36
|
},
|
31
37
|
|
@@ -80,6 +80,16 @@ public class UIQueryASTPredicate implements UIQueryAST {
|
|
80
80
|
}
|
81
81
|
}
|
82
82
|
|
83
|
+
// there's no tag property for non Views, handle them all here
|
84
|
+
if (this.propertyName.equals("tag")) {
|
85
|
+
String tag = (o instanceof View ? UIQueryUtils.getTag((View) o) : null);
|
86
|
+
if (this.relation.areRelated(tag, this.valueToMatch)) {
|
87
|
+
return o;
|
88
|
+
} else {
|
89
|
+
return null;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
83
93
|
Method propertyAccessor = UIQueryUtils
|
84
94
|
.hasProperty(o, this.propertyName);
|
85
95
|
if (propertyAccessor == null) {
|
@@ -90,8 +100,8 @@ public class UIQueryASTPredicate implements UIQueryAST {
|
|
90
100
|
if (this.relation.areRelated(value, this.valueToMatch)) {
|
91
101
|
return o;
|
92
102
|
} else if (this.valueToMatch instanceof String
|
93
|
-
|
94
|
-
|
103
|
+
&& value != null
|
104
|
+
&& this.relation.areRelated(value.toString(), this.valueToMatch)) {
|
95
105
|
return o;
|
96
106
|
} else {
|
97
107
|
return null;
|
@@ -109,7 +119,7 @@ public class UIQueryASTPredicate implements UIQueryAST {
|
|
109
119
|
return new UIQueryASTPredicate(prop.getText(),
|
110
120
|
UIQueryASTPredicate.parseRelation(rel),
|
111
121
|
UIQueryUtils.parseValue(val));
|
112
|
-
|
122
|
+
|
113
123
|
}
|
114
124
|
|
115
125
|
private static UIQueryASTPredicateRelation parseRelation(CommonTree rel) {
|
@@ -120,7 +130,7 @@ public class UIQueryASTPredicate implements UIQueryAST {
|
|
120
130
|
caseSensitive = false;
|
121
131
|
relText = relText.substring(0,relText.length() - CASE_INSENSITIVE_SPEC.length());
|
122
132
|
}
|
123
|
-
|
133
|
+
|
124
134
|
if ("BEGINSWITH".equals(relText)) {
|
125
135
|
return new BeginsWithRelation(caseSensitive);
|
126
136
|
} else if ("ENDSWITH".equals(relText)) {
|
@@ -139,6 +149,8 @@ public class UIQueryASTPredicate implements UIQueryAST {
|
|
139
149
|
return ComparisonOperator.GREATERTHAN;
|
140
150
|
} else if (">=".equals(relText)) {
|
141
151
|
return ComparisonOperator.GREATERTHANOREQUAL;
|
152
|
+
} else if ("!=".equals(relText) || "<>".equals(relText)) {
|
153
|
+
return ComparisonOperator.NOTEQUAL;
|
142
154
|
} else {
|
143
155
|
throw new IllegalStateException("Unsupported Relation: " + relText);
|
144
156
|
}
|
@@ -63,13 +63,13 @@ public class UIQueryASTWith implements UIQueryAST {
|
|
63
63
|
}
|
64
64
|
|
65
65
|
}
|
66
|
-
|
67
|
-
|
68
|
-
return new PartialFutureList(visibilityFilteredResults);
|
66
|
+
|
67
|
+
return new PartialFutureList(futureResult);
|
69
68
|
}
|
70
69
|
});
|
71
70
|
|
72
|
-
List processedResult = new ArrayList(queryResult.size());
|
71
|
+
final List processedResult = new ArrayList(queryResult.size());
|
72
|
+
|
73
73
|
for (Object o : queryResult) {
|
74
74
|
if (o instanceof Map) {
|
75
75
|
Map m = (Map) o;
|
@@ -85,9 +85,16 @@ public class UIQueryASTWith implements UIQueryAST {
|
|
85
85
|
processedResult.add(o);
|
86
86
|
}
|
87
87
|
}
|
88
|
-
return processedResult;
|
89
|
-
|
90
88
|
|
89
|
+
List visibilityFilteredResults = (List) UIQueryUtils.evaluateSyncInMainThread(new Callable() {
|
90
|
+
|
91
|
+
@Override
|
92
|
+
public Object call() throws Exception {
|
93
|
+
return visibility.evaluateWithViews(processedResult, direction, visibility);
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
return visibilityFilteredResults;
|
91
98
|
}
|
92
99
|
|
93
100
|
private boolean isDomQuery() {
|
@@ -30,6 +30,7 @@ import sh.calaba.org.codehaus.jackson.type.TypeReference;
|
|
30
30
|
import android.text.InputType;
|
31
31
|
import android.util.Log;
|
32
32
|
import android.view.View;
|
33
|
+
import android.view.ViewParent;
|
33
34
|
import android.webkit.WebView;
|
34
35
|
import android.widget.Button;
|
35
36
|
import android.widget.CheckBox;
|
@@ -47,7 +48,7 @@ public class UIQueryUtils {
|
|
47
48
|
|
48
49
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
49
50
|
public static List subviews(Object o) {
|
50
|
-
|
51
|
+
|
51
52
|
try {
|
52
53
|
Method getChild = o.getClass().getMethod("getChildAt", int.class);
|
53
54
|
getChild.setAccessible(true);
|
@@ -74,15 +75,15 @@ public class UIQueryUtils {
|
|
74
75
|
|
75
76
|
@SuppressWarnings({ "rawtypes" })
|
76
77
|
public static Future webViewSubViews(WebView o) {
|
77
|
-
|
78
|
+
|
78
79
|
Log.i("Calabash", "About to webViewSubViews");
|
79
|
-
|
80
|
+
|
80
81
|
|
81
82
|
WebFuture controls = QueryHelper.executeAsyncJavascriptInWebviews(o,
|
82
83
|
"calabash.js", "input,button","css");
|
83
|
-
|
84
|
+
|
84
85
|
return controls;
|
85
|
-
|
86
|
+
|
86
87
|
}
|
87
88
|
|
88
89
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@@ -168,18 +169,44 @@ public class UIQueryUtils {
|
|
168
169
|
}
|
169
170
|
|
170
171
|
public static boolean isVisible(Object v) {
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
172
|
+
if (v instanceof Map) {
|
173
|
+
Map map = (Map)v;
|
174
|
+
Map<String,Integer> viewRect = (Map<String,Integer>)map.get("rect");
|
175
|
+
Map<String,Integer> parentViewRec = ViewMapper.getRectForView((WebView)map.get("webView"));
|
175
176
|
|
176
|
-
|
177
|
-
|
178
|
-
|
177
|
+
return isViewSufficientlyShown(viewRect, parentViewRec);
|
178
|
+
} else if (v instanceof View) {
|
179
|
+
View view = (View) v;
|
179
180
|
|
180
|
-
|
181
|
+
if (view.getHeight() == 0 || view.getWidth() == 0) {
|
182
|
+
return false;
|
183
|
+
}
|
184
|
+
|
185
|
+
return view.isShown() && isViewSufficientlyShown(view);
|
186
|
+
} else {
|
187
|
+
return true;
|
188
|
+
}
|
181
189
|
}
|
182
190
|
|
191
|
+
public static boolean isViewSufficientlyShown(Map<String,Integer> viewRect, Map<String,Integer> parentViewRect) {
|
192
|
+
int centerX = viewRect.get("center_x");
|
193
|
+
int centerY = viewRect.get("center_y");
|
194
|
+
|
195
|
+
int parentX = parentViewRect.get("x");
|
196
|
+
int parentY = parentViewRect.get("y");
|
197
|
+
int parentWidth = parentViewRect.get("width");
|
198
|
+
int parentHeight = parentViewRect.get("height");
|
199
|
+
int windowWidth = parentX + parentWidth;
|
200
|
+
int windowHeight = parentY + parentHeight;
|
201
|
+
|
202
|
+
return (windowWidth > centerX && parentX < centerX &&
|
203
|
+
windowHeight > centerY && parentY < centerY);
|
204
|
+
}
|
205
|
+
|
206
|
+
public static boolean isViewSufficientlyShown(View view) {
|
207
|
+
return isViewSufficientlyShown(view, view.getParent());
|
208
|
+
}
|
209
|
+
|
183
210
|
public static boolean isClickable(Object v) {
|
184
211
|
if (!(v instanceof View)) {
|
185
212
|
return true;
|
@@ -193,6 +220,10 @@ public class UIQueryUtils {
|
|
193
220
|
return ViewMapper.getIdForView(view);
|
194
221
|
}
|
195
222
|
|
223
|
+
public static String getTag(View view) {
|
224
|
+
return ViewMapper.getTagForView(view);
|
225
|
+
}
|
226
|
+
|
196
227
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
197
228
|
public static Future evaluateAsyncInMainThread(final Callable callable) throws Exception {
|
198
229
|
|
@@ -246,8 +277,8 @@ public class UIQueryUtils {
|
|
246
277
|
new TypeReference<List<HashMap<String, Object>>>() {
|
247
278
|
});
|
248
279
|
for (Map<String, Object> data : parsedResult) {
|
249
|
-
Map<String,
|
250
|
-
Map<String,
|
280
|
+
Map<String, Integer> rect = (Map<String, Integer>) data.get("rect");
|
281
|
+
Map<String, Integer> updatedRect = QueryHelper.translateRectToScreenCoordinates(webView, rect);
|
251
282
|
data.put("rect", updatedRect);
|
252
283
|
data.put("webView", webView);
|
253
284
|
}
|
@@ -301,7 +332,7 @@ public class UIQueryUtils {
|
|
301
332
|
}
|
302
333
|
|
303
334
|
/*
|
304
|
-
*
|
335
|
+
*
|
305
336
|
* {"rect"=>{"x"=>0, "y"=>0, "width"=>768, "height"=>1024},
|
306
337
|
* "hit-point"=>{"x"=>384, "y"=>512}, "id"=>"", "action"=>false,
|
307
338
|
* "enabled"=>1, "visible"=>1, "value"=>nil, "type"=>"[object UIAWindow]",
|
@@ -343,7 +374,7 @@ public class UIQueryUtils {
|
|
343
374
|
childrenArray.add(dumpRecursively(serializedChild,
|
344
375
|
childrenList));
|
345
376
|
}
|
346
|
-
|
377
|
+
|
347
378
|
}
|
348
379
|
|
349
380
|
parentView.put("children", childrenArray);
|
@@ -373,7 +404,7 @@ public class UIQueryUtils {
|
|
373
404
|
}
|
374
405
|
|
375
406
|
/*
|
376
|
-
*
|
407
|
+
*
|
377
408
|
"enabled" => true,
|
378
409
|
"visible" => true,
|
379
410
|
"children" => [],
|
@@ -412,16 +443,16 @@ public class UIQueryUtils {
|
|
412
443
|
if (viewOrMap == null) {
|
413
444
|
return null;
|
414
445
|
}
|
415
|
-
|
416
|
-
if (viewOrMap instanceof Map)
|
446
|
+
|
447
|
+
if (viewOrMap instanceof Map)
|
417
448
|
{
|
418
|
-
Map map = (Map) viewOrMap;
|
449
|
+
Map map = (Map) viewOrMap;
|
419
450
|
map.put("el", map);
|
420
451
|
|
421
452
|
Map rect = (Map) map.get("rect");
|
422
453
|
Map hitPoint = extractHitPointFromRect(rect);
|
423
|
-
|
424
|
-
map.put("hit-point", hitPoint);
|
454
|
+
|
455
|
+
map.put("hit-point", hitPoint);
|
425
456
|
map.put("enabled", true);
|
426
457
|
map.put("visible", true);
|
427
458
|
map.put("value", null);
|
@@ -430,36 +461,36 @@ public class UIQueryUtils {
|
|
430
461
|
map.put("label", null);
|
431
462
|
map.put("children", Collections.EMPTY_LIST);
|
432
463
|
String html = (String)map.get("html");
|
433
|
-
String nodeName = (String) map.get("nodeName");
|
434
|
-
if (nodeName != null && nodeName.toLowerCase().equals("input")) {
|
464
|
+
String nodeName = (String) map.get("nodeName");
|
465
|
+
if (nodeName != null && nodeName.toLowerCase().equals("input")) {
|
435
466
|
String domType = extractDomType(html);
|
436
467
|
if (isDomPasswordType(domType)) {
|
437
468
|
map.put("entry_types", Collections.singletonList("password"));
|
438
469
|
}
|
439
470
|
else if (isDomTextType(domType)) {
|
440
471
|
map.put("entry_types", Collections.singletonList("text"));
|
441
|
-
}
|
472
|
+
}
|
442
473
|
else {
|
443
|
-
map.put("entry_types", Collections.emptyList());
|
444
|
-
}
|
474
|
+
map.put("entry_types", Collections.emptyList());
|
475
|
+
}
|
445
476
|
map.put("value", extractAttribute(html, "value"));
|
446
477
|
map.put("type", "dom");
|
447
478
|
map.put("name", extractAttribute(html, "name"));
|
448
479
|
map.put("label", extractAttribute(html, "title"));
|
449
|
-
}
|
450
|
-
|
451
|
-
return map;
|
452
|
-
|
480
|
+
}
|
481
|
+
|
482
|
+
return map;
|
483
|
+
|
453
484
|
}
|
454
|
-
else
|
485
|
+
else
|
455
486
|
{
|
456
487
|
Map m = new HashMap();
|
457
|
-
|
488
|
+
|
458
489
|
View view = (View) viewOrMap;
|
459
490
|
m.put("id", getId(view));
|
460
491
|
m.put("el", view);
|
461
492
|
|
462
|
-
Map rect = ViewMapper.getRectForView(view);
|
493
|
+
Map<String,Integer> rect = ViewMapper.getRectForView(view);
|
463
494
|
Map hitPoint = extractHitPointFromRect(rect);
|
464
495
|
|
465
496
|
m.put("rect", rect);
|
@@ -472,14 +503,29 @@ public class UIQueryUtils {
|
|
472
503
|
m.put("type", ViewMapper.getClassNameForView(view));
|
473
504
|
m.put("name", getNameForView(view));
|
474
505
|
m.put("label", ViewMapper.getContentDescriptionForView(view));
|
475
|
-
return m;
|
506
|
+
return m;
|
476
507
|
}
|
477
508
|
|
478
|
-
|
479
509
|
|
480
|
-
|
510
|
+
|
511
|
+
|
481
512
|
}
|
482
513
|
|
514
|
+
private static boolean isViewSufficientlyShown(View view, ViewParent viewParent) {
|
515
|
+
if (!(viewParent instanceof View)) return true;
|
516
|
+
|
517
|
+
View parent = (View)viewParent;
|
518
|
+
|
519
|
+
if (view.equals(parent) || parent == null) {
|
520
|
+
return true;
|
521
|
+
}
|
522
|
+
|
523
|
+
Map<String,Integer> viewRect = ViewMapper.getRectForView(view);
|
524
|
+
Map<String,Integer> parentRect = ViewMapper.getRectForView(parent);
|
525
|
+
|
526
|
+
return isViewSufficientlyShown(viewRect, parentRect) && isViewSufficientlyShown(view, parent.getParent());
|
527
|
+
}
|
528
|
+
|
483
529
|
private static boolean isDomTextType(String domType) {
|
484
530
|
if (domType == null) {
|
485
531
|
return true;
|
@@ -487,25 +533,25 @@ public class UIQueryUtils {
|
|
487
533
|
return DOM_TEXT_TYPES.contains(domType);
|
488
534
|
}
|
489
535
|
|
490
|
-
private static boolean isDomPasswordType(String domType) {
|
536
|
+
private static boolean isDomPasswordType(String domType) {
|
491
537
|
return "password".equalsIgnoreCase(domType);
|
492
538
|
}
|
493
539
|
|
494
540
|
// naive implementation only works for (valid) input tags
|
495
541
|
public static String extractDomType(String input) {
|
496
|
-
return extractAttribute(input, "type");
|
542
|
+
return extractAttribute(input, "type");
|
497
543
|
}
|
498
|
-
|
544
|
+
|
499
545
|
public static String extractAttribute(String input, String attribute) {
|
500
546
|
String[] split = input.split(attribute+"=");
|
501
547
|
if (split.length == 1) {
|
502
|
-
split = input.split(attribute+" =");
|
548
|
+
split = input.split(attribute+" =");
|
503
549
|
}
|
504
550
|
if (split.length > 1) {
|
505
551
|
String lastPart = split[1];
|
506
552
|
if (lastPart == null) {
|
507
|
-
return null;
|
508
|
-
}
|
553
|
+
return null;
|
554
|
+
}
|
509
555
|
if (lastPart.charAt(0) == '"' || lastPart.charAt(0) == '\'') {
|
510
556
|
int endIndex = -1;
|
511
557
|
for (int i=1;i<lastPart.length();i++) {
|
@@ -514,15 +560,15 @@ public class UIQueryUtils {
|
|
514
560
|
break;
|
515
561
|
}
|
516
562
|
}
|
517
|
-
|
563
|
+
|
518
564
|
if (endIndex > 0) {
|
519
565
|
return lastPart.substring(1,endIndex);
|
520
566
|
}
|
521
|
-
|
522
|
-
}
|
567
|
+
|
568
|
+
}
|
523
569
|
}
|
524
570
|
return null;
|
525
|
-
|
571
|
+
|
526
572
|
}
|
527
573
|
|
528
574
|
|