calabash-android 0.2.11 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +6 -0
- data/features-skeleton/support/app_installation_hooks.rb +11 -3
- data/features-skeleton/support/app_life_cycle_hooks.rb +9 -0
- data/features-skeleton/support/hooks.rb +18 -2
- data/lib/calabash-android/operations.rb +1 -1
- data/lib/calabash-android/steps/assert_steps.rb +12 -0
- data/lib/calabash-android/steps/list_steps.rb +40 -0
- data/lib/calabash-android/steps/map_steps.rb +61 -0
- data/lib/calabash-android/steps/navigation_steps.rb +10 -1
- data/lib/calabash-android/steps/progress_steps.rb +5 -0
- data/lib/calabash-android/version.rb +2 -2
- data/test-server/AndroidManifest.xml +5 -5
- data/test-server/build.xml +4 -0
- data/test-server/instrumentation-backend/.gitignore +1 -0
- data/test-server/instrumentation-backend/AndroidManifest.xml +4 -3
- data/test-server/instrumentation-backend/project.properties +1 -1
- data/test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/MapViewUtils.java +328 -0
- data/test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/SoloEnhanced.java +97 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +3 -3
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/TestHelpers.java +51 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/GetListItemProperties.java +195 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/list/GetListItemText.java +136 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/GetMapBounds.java +27 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/GetMapCenter.java +27 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/GetMapMarker.java +31 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/GetMapMarkers.java +48 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/GetMapZoom.java +19 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/PanMapTo.java +23 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/SetMapCenter.java +23 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/SetMapZoom.java +34 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/TapAwayFromMarkers.java +28 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/TapMapMarker.java +29 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/spinner/GetSelectedSpinnerItemText.java +36 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/AssertGridViewContainsNoDuplicates.java +72 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/text/GetTextById.java +42 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/AssertViewProperty.java +141 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/ClickOnViewById.java +1 -8
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetActivityName.java +32 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetViewProperty.java +107 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/HasView.java +31 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/Press.java +1 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/SelectTab.java +110 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForScreen.java +10 -6
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/wait/WaitForTab.java +108 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/{view → wait}/WaitForView.java +1 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/{view → wait}/WaitForViewById.java +21 -11
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/QueryHelper.java +3 -3
- metadata +102 -88
data/test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/SoloEnhanced.java
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
package com.jayway.android.robotium.solo;
|
2
|
+
|
3
|
+
import java.util.List;
|
4
|
+
|
5
|
+
import android.app.Activity;
|
6
|
+
import android.app.Instrumentation;
|
7
|
+
|
8
|
+
public class SoloEnhanced extends Solo {
|
9
|
+
// private Pincher pincher;
|
10
|
+
private MapViewUtils mapViewUtils;
|
11
|
+
|
12
|
+
public SoloEnhanced(Instrumentation instrumentation, Activity activity) {
|
13
|
+
super(instrumentation, activity);
|
14
|
+
this.mapViewUtils = new MapViewUtils(instrumentation, viewFetcher, sleeper, waiter);
|
15
|
+
// this.pincher = new Pincher(instrumentation, viewFetcher);
|
16
|
+
}
|
17
|
+
|
18
|
+
public void setMapCenter( double lat, double lon ) {
|
19
|
+
mapViewUtils.setCenter(lat, lon);
|
20
|
+
}
|
21
|
+
|
22
|
+
/** @return {lat,lon} */
|
23
|
+
public double[] getMapCenter() {
|
24
|
+
return mapViewUtils.getMapCenter();
|
25
|
+
}
|
26
|
+
|
27
|
+
public void panMapTo( double lat, double lon ) {
|
28
|
+
mapViewUtils.panTo(lat, lon);
|
29
|
+
}
|
30
|
+
|
31
|
+
public boolean zoomInOnMap() {
|
32
|
+
return mapViewUtils.zoomIn();
|
33
|
+
}
|
34
|
+
|
35
|
+
public boolean zoomOutOnMap() {
|
36
|
+
return mapViewUtils.zoomOut();
|
37
|
+
}
|
38
|
+
|
39
|
+
public int setMapZoom( int zoomLevel ) {
|
40
|
+
return mapViewUtils.setZoom(zoomLevel);
|
41
|
+
}
|
42
|
+
|
43
|
+
public int getMapZoom() {
|
44
|
+
return mapViewUtils.getZoom();
|
45
|
+
}
|
46
|
+
|
47
|
+
public List<String> getMapMarkerItems() {
|
48
|
+
return mapViewUtils.getMarkerItems();
|
49
|
+
}
|
50
|
+
|
51
|
+
public String getMapMarkerItem( String title ) {
|
52
|
+
return mapViewUtils.getMarkerItem( title );
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @param title
|
57
|
+
* @param timeout in ms
|
58
|
+
* @return
|
59
|
+
*/
|
60
|
+
public boolean tapMapMarkerItem( String title, long timeout ) {
|
61
|
+
return mapViewUtils.tapMarkerItem( title, timeout );
|
62
|
+
}
|
63
|
+
|
64
|
+
public boolean tapMapAwayFromMarkers( int step ) {
|
65
|
+
return mapViewUtils.tapAwayFromMarkerItems( step );
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @return [top, right, bottom, left] in decimal degrees
|
70
|
+
*/
|
71
|
+
public List<String> getMapBounds() {
|
72
|
+
return mapViewUtils.getBounds();
|
73
|
+
}
|
74
|
+
|
75
|
+
// /**
|
76
|
+
// * Sorry, doesn't work yet
|
77
|
+
// * @param togetherOrApart - {@link Pincher#TOGETHER} or {@link Pincher#APART}
|
78
|
+
// */
|
79
|
+
// public void pinch(int togetherOrApart) {
|
80
|
+
// switch( togetherOrApart ) {
|
81
|
+
// case Pincher.TOGETHER: pincher.pinch(Pincher.Direction.TOGETHER); break;
|
82
|
+
// case Pincher.APART: pincher.pinch(Pincher.Direction.APART); break;
|
83
|
+
// }
|
84
|
+
// }
|
85
|
+
//
|
86
|
+
// /**
|
87
|
+
// * Sorry, doesn't work yet
|
88
|
+
// * @param togetherOrApart - {@link Pincher#TOGETHER} or {@link Pincher#APART}
|
89
|
+
// * @param view
|
90
|
+
// */
|
91
|
+
// public void pinch(int togetherOrApart, View view) {
|
92
|
+
// switch( togetherOrApart ) {
|
93
|
+
// case Pincher.TOGETHER: pincher.pinch(Pincher.Direction.TOGETHER, view); break;
|
94
|
+
// case Pincher.APART: pincher.pinch(Pincher.Direction.APART, view); break;
|
95
|
+
// }
|
96
|
+
// }
|
97
|
+
}
|
@@ -6,7 +6,7 @@ import android.app.Instrumentation;
|
|
6
6
|
import android.test.ActivityInstrumentationTestCase2;
|
7
7
|
import android.util.Log;
|
8
8
|
|
9
|
-
import com.jayway.android.robotium.solo.
|
9
|
+
import com.jayway.android.robotium.solo.SoloEnhanced;
|
10
10
|
|
11
11
|
public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
|
12
12
|
public static final String TARGET_PACKAGE = "#ACTIVITY_PACKAGE#"; //Set from Ant at compile time
|
@@ -15,7 +15,7 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
|
|
15
15
|
private static final String TAG = "InstrumentationBackend";
|
16
16
|
|
17
17
|
public static Instrumentation instrumentation;
|
18
|
-
public static
|
18
|
+
public static SoloEnhanced solo;
|
19
19
|
public static Actions actions;
|
20
20
|
|
21
21
|
private static Class getActivityClass() {
|
@@ -34,7 +34,7 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
|
|
34
34
|
protected void setUp() throws Exception {
|
35
35
|
super.setUp();
|
36
36
|
|
37
|
-
solo = new
|
37
|
+
solo = new SoloEnhanced(getInstrumentation(), this.getActivity());
|
38
38
|
actions = new Actions(getInstrumentation(), this);
|
39
39
|
instrumentation = getInstrumentation();
|
40
40
|
TestHelpers.loadIds(instrumentation.getContext());
|
data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/TestHelpers.java
CHANGED
@@ -12,6 +12,8 @@ import java.util.HashMap;
|
|
12
12
|
import java.util.Map;
|
13
13
|
|
14
14
|
import android.content.Context;
|
15
|
+
import android.content.res.Resources.NotFoundException;
|
16
|
+
import android.graphics.drawable.Drawable;
|
15
17
|
import android.view.View;
|
16
18
|
import android.widget.TextView;
|
17
19
|
|
@@ -69,6 +71,21 @@ public class TestHelpers {
|
|
69
71
|
return null;
|
70
72
|
}
|
71
73
|
|
74
|
+
@SuppressWarnings("unchecked")
|
75
|
+
public static <ViewType extends View> ViewType getViewById(String resName, Class<? extends View> expectedViewType) {
|
76
|
+
final View theView = getViewById(resName);
|
77
|
+
|
78
|
+
if (null == theView) {
|
79
|
+
return null;
|
80
|
+
}
|
81
|
+
|
82
|
+
if (!expectedViewType.isInstance(theView)) {
|
83
|
+
throw new RuntimeException(String.format("getViewById: Expected to find a View of type %s but found one of type %s", expectedViewType.getClass().getName(), theView.getClass().getName()));
|
84
|
+
}
|
85
|
+
|
86
|
+
return (ViewType) theView;
|
87
|
+
}
|
88
|
+
|
72
89
|
public static View getViewById(String resName) {
|
73
90
|
Integer intID = resourceNamesToIds.get(resName);
|
74
91
|
System.out.println("getViewById: Looking for view " + resName + " as id " + intID);
|
@@ -76,7 +93,7 @@ public class TestHelpers {
|
|
76
93
|
throw new RuntimeException("getViewById: Looking for view " + resName + " which does not have an id");
|
77
94
|
}
|
78
95
|
int id = intID.intValue();
|
79
|
-
View view = InstrumentationBackend.solo.
|
96
|
+
View view = InstrumentationBackend.solo.getView(id);
|
80
97
|
if (view != null) {
|
81
98
|
if (id == view.getId()) {
|
82
99
|
System.out.println("Did find view " + resName + ".");
|
@@ -87,6 +104,39 @@ public class TestHelpers {
|
|
87
104
|
System.out.println("Did not find view " + resName);
|
88
105
|
return view;
|
89
106
|
}
|
107
|
+
|
108
|
+
public static Drawable getDrawableById(String resName) {
|
109
|
+
int id;
|
110
|
+
// This would probably work too...
|
111
|
+
if( true ) {
|
112
|
+
try {
|
113
|
+
// if( resName.startsWith("drawable/") == false ) {
|
114
|
+
// resName = "drawable/" + resName;
|
115
|
+
// }
|
116
|
+
// TypedValue outValue = new TypedValue();
|
117
|
+
// InstrumentationBackend.solo.getCurrentActivity().getResources().getValue( resName, outValue, false );
|
118
|
+
// id = outValue.resourceId;
|
119
|
+
id = InstrumentationBackend.solo.getCurrentActivity().getResources().getIdentifier( resName, "drawable", InstrumentationBackend.solo.getCurrentActivity().getPackageName() );
|
120
|
+
} catch( NotFoundException e ) {
|
121
|
+
throw new RuntimeException("getDrawableById: Looking for drawable " + resName + " but was not found");
|
122
|
+
}
|
123
|
+
} else {
|
124
|
+
Integer intID = resourceNamesToIds.get(resName);
|
125
|
+
System.out.println("getDrawableById: Looking for drawable " + resName + " as id " + intID);
|
126
|
+
if (intID == null) {
|
127
|
+
throw new RuntimeException("getDrawableById: Looking for drawable " + resName + " which does not have an id");
|
128
|
+
}
|
129
|
+
id = intID.intValue();
|
130
|
+
}
|
131
|
+
Drawable drawable = InstrumentationBackend.solo.getCurrentActivity().getResources().getDrawable(id);
|
132
|
+
if (drawable != null) {
|
133
|
+
System.out.println("Did find drawable " + resName + ": " + drawable);
|
134
|
+
return drawable;
|
135
|
+
} else {
|
136
|
+
System.out.println("Did not find drawable " + resName);
|
137
|
+
return drawable;
|
138
|
+
}
|
139
|
+
}
|
90
140
|
|
91
141
|
public static int[] parseTime(String timeString) {
|
92
142
|
String[] splitTimeString = timeString.split(":");
|
@@ -0,0 +1,195 @@
|
|
1
|
+
package sh.calaba.instrumentationbackend.actions.list;
|
2
|
+
|
3
|
+
import java.lang.reflect.Method;
|
4
|
+
import java.util.ArrayList;
|
5
|
+
|
6
|
+
import sh.calaba.instrumentationbackend.InstrumentationBackend;
|
7
|
+
import sh.calaba.instrumentationbackend.Result;
|
8
|
+
import sh.calaba.instrumentationbackend.actions.Action;
|
9
|
+
import android.graphics.drawable.ColorDrawable;
|
10
|
+
import android.graphics.drawable.Drawable;
|
11
|
+
import android.view.View;
|
12
|
+
import android.view.ViewGroup;
|
13
|
+
import android.widget.ListView;
|
14
|
+
import android.widget.TableRow;
|
15
|
+
import android.widget.TextView;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* args:
|
19
|
+
* <ul>
|
20
|
+
* <li>1-based list index (first list is used if not specified)</li>
|
21
|
+
* <li>1-based row index (returns all rows if <=0 or not specified)</li>
|
22
|
+
* </ul>
|
23
|
+
*
|
24
|
+
* eg: (all items of 1st list) <code>performAction( 'get_list_item_properties' )</code>
|
25
|
+
* eg: (all items of 2nd list) <code>performAction( 'get_list_item_properties', '2' )</code>
|
26
|
+
* eg: (1st item of 2nd list) <code>performAction( 'get_list_item_properties', '2' , '1' )</code>
|
27
|
+
*
|
28
|
+
* @return <code>bonusInformation</code> contain an array of Strings, one for each row in the list (or only for the specified row):
|
29
|
+
* eg: {[{"id":"title", "text":"My Title", "compoundDrawables":["left"]}, {"id":"subtitle", "text":"Another text field for the same list item"}]}
|
30
|
+
*
|
31
|
+
*
|
32
|
+
* In ruby, we can then parse the response:
|
33
|
+
* <pre>
|
34
|
+
* response_table = result['bonusInformation']
|
35
|
+
* response_table.each_with_index do | row_data, index |
|
36
|
+
* row_data = JSON.parse( row_data )
|
37
|
+
* response_table[index] = row_data
|
38
|
+
* end
|
39
|
+
* </pre>
|
40
|
+
*
|
41
|
+
* @author Nicholas Albion
|
42
|
+
*/
|
43
|
+
public class GetListItemProperties implements Action {
|
44
|
+
|
45
|
+
@Override
|
46
|
+
public Result execute(String... args) {
|
47
|
+
int listIndex;
|
48
|
+
int rowIndex = -1;
|
49
|
+
|
50
|
+
if( args.length == 0 ) {
|
51
|
+
listIndex = 0;
|
52
|
+
} else {
|
53
|
+
if( args.length > 1 ) {
|
54
|
+
rowIndex = (Integer.parseInt(args[1]) - 1);
|
55
|
+
}
|
56
|
+
listIndex = (Integer.parseInt(args[0]) - 1);
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
ArrayList<ListView> listViews = InstrumentationBackend.solo.getCurrentListViews();
|
61
|
+
if( listViews == null || listViews.size() <= listIndex ) {
|
62
|
+
return new Result(false, "Could not find list #" + (listIndex + 1));
|
63
|
+
}
|
64
|
+
|
65
|
+
ListView list = listViews.get(listIndex);
|
66
|
+
Result result = new Result(true);
|
67
|
+
|
68
|
+
if( rowIndex < 0 ) {
|
69
|
+
int count = list.getChildCount();
|
70
|
+
for( int i = 0; i < count; i++ ) {
|
71
|
+
result.addBonusInformation( getListItemString( list.getChildAt(i) ) );
|
72
|
+
}
|
73
|
+
} else {
|
74
|
+
result.addBonusInformation( getListItemString( list.getChildAt(rowIndex) ) );
|
75
|
+
}
|
76
|
+
|
77
|
+
return result;
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* @return <code>bonusInformation</code> contain an array of Strings, one for each row in the list (or only for the specified row):
|
82
|
+
* eg: {[{"id":"title", "text":"My Title", "compoundDrawables":{"left":"drawable_id"}}, {"id":"subtitle", "text":"Another text field for the same list item"}]}
|
83
|
+
*/
|
84
|
+
private String getListItemString( View row ) {
|
85
|
+
StringBuilder json = new StringBuilder("{");
|
86
|
+
|
87
|
+
if( row instanceof TextView ) {
|
88
|
+
addViewInfo( json, (TextView)row );
|
89
|
+
} else if( row instanceof ViewGroup ) {
|
90
|
+
addViewInfo( json, (ViewGroup)row );
|
91
|
+
}
|
92
|
+
|
93
|
+
json.deleteCharAt( json.length() - 1 ); // remove the last comma
|
94
|
+
json.append('}');
|
95
|
+
return json.toString();
|
96
|
+
}
|
97
|
+
|
98
|
+
private void addViewInfo( StringBuilder json, TextView view ) {
|
99
|
+
int resId = view.getId();
|
100
|
+
String resIdName = view.getResources().getResourceEntryName(resId);
|
101
|
+
|
102
|
+
json.append("\"id\":\"").append(resIdName).append("\", \"text:\"").append( ((TextView)view).getText() ).append("\"");
|
103
|
+
|
104
|
+
json.append(", \"color\":").append( view.getCurrentTextColor() );
|
105
|
+
Drawable background = view.getBackground();
|
106
|
+
if( background instanceof ColorDrawable ) {
|
107
|
+
try {
|
108
|
+
// As pointed out by kbielenberg, ColorDrawable.getColor() was only added in level 11/Android 3/Honeycomb
|
109
|
+
Method getColor = ColorDrawable.class.getMethod("getColor");
|
110
|
+
Integer color = (Integer)getColor.invoke(background);
|
111
|
+
json.append(", \"background\":").append( color );
|
112
|
+
} catch (Exception e) {}
|
113
|
+
}
|
114
|
+
|
115
|
+
StringBuilder compoundStr = new StringBuilder();
|
116
|
+
Drawable[] compoundDrawables = view.getCompoundDrawables(); // left, top, right, and bottom
|
117
|
+
if( compoundDrawables[0] != null ) {
|
118
|
+
compoundStr.append("\"left\"");
|
119
|
+
}
|
120
|
+
if( compoundDrawables[1] != null ) {
|
121
|
+
if( compoundStr.length() != 0 ) {
|
122
|
+
compoundStr.append(',');
|
123
|
+
}
|
124
|
+
compoundStr.append("\"top\"");
|
125
|
+
}
|
126
|
+
if( compoundDrawables[2] != null ) {
|
127
|
+
if( compoundStr.length() != 0 ) {
|
128
|
+
compoundStr.append(',');
|
129
|
+
}
|
130
|
+
compoundStr.append("\"right\"");
|
131
|
+
}
|
132
|
+
if( compoundDrawables[3] != null ) {
|
133
|
+
if( compoundStr.length() != 0 ) {
|
134
|
+
compoundStr.append(',');
|
135
|
+
}
|
136
|
+
compoundStr.append("\"bottom\"");
|
137
|
+
}
|
138
|
+
if( compoundStr.length() != 0 ) {
|
139
|
+
json.append(", \"compoundDrawables\":[").append(compoundStr).append(']');
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
private void addViewInfo( StringBuilder json, TableRow tableRow ) {
|
144
|
+
json.append("\"cells\":[");
|
145
|
+
|
146
|
+
int count = tableRow.getVirtualChildCount();
|
147
|
+
for( int i = 0; i < count; i++ ) {
|
148
|
+
if( i != 0 ) {
|
149
|
+
json.append(", ");
|
150
|
+
}
|
151
|
+
json.append("{\"column\":").append(i).append(", ");
|
152
|
+
|
153
|
+
View view = tableRow.getVirtualChildAt(i);
|
154
|
+
if( view instanceof TextView ) {
|
155
|
+
addViewInfo( json, (TextView)view );
|
156
|
+
} else if( view instanceof ViewGroup ) {
|
157
|
+
addViewInfo( json, (ViewGroup)view );
|
158
|
+
}
|
159
|
+
|
160
|
+
json.append('}');
|
161
|
+
}
|
162
|
+
|
163
|
+
json.append(']');
|
164
|
+
}
|
165
|
+
|
166
|
+
private void addViewInfo( StringBuilder json, ViewGroup viewGroup ) {
|
167
|
+
json.append("\"children\":[");
|
168
|
+
|
169
|
+
int count = viewGroup.getChildCount();
|
170
|
+
for( int i = 0; i < count; i++ ) {
|
171
|
+
if( i != 0 ) {
|
172
|
+
json.append(", ");
|
173
|
+
}
|
174
|
+
json.append('{');
|
175
|
+
|
176
|
+
View view = viewGroup.getChildAt(i);
|
177
|
+
if( view instanceof TextView ) {
|
178
|
+
addViewInfo( json, (TextView)view );
|
179
|
+
} else if( view instanceof TableRow ) {
|
180
|
+
addViewInfo( json, (TableRow)view );
|
181
|
+
} else if( view instanceof ViewGroup ) {
|
182
|
+
addViewInfo( json, (ViewGroup)view );
|
183
|
+
}
|
184
|
+
|
185
|
+
json.append('}');
|
186
|
+
}
|
187
|
+
|
188
|
+
json.append(']');
|
189
|
+
}
|
190
|
+
|
191
|
+
@Override
|
192
|
+
public String key() {
|
193
|
+
return "get_list_item_properties";
|
194
|
+
}
|
195
|
+
}
|
@@ -0,0 +1,136 @@
|
|
1
|
+
package sh.calaba.instrumentationbackend.actions.list;
|
2
|
+
|
3
|
+
import java.util.ArrayList;
|
4
|
+
|
5
|
+
import sh.calaba.instrumentationbackend.InstrumentationBackend;
|
6
|
+
import sh.calaba.instrumentationbackend.Result;
|
7
|
+
import sh.calaba.instrumentationbackend.actions.Action;
|
8
|
+
import android.util.Log;
|
9
|
+
import android.view.View;
|
10
|
+
import android.view.ViewGroup;
|
11
|
+
import android.widget.ListView;
|
12
|
+
import android.widget.TableRow;
|
13
|
+
import android.widget.TextView;
|
14
|
+
|
15
|
+
/**
|
16
|
+
* args:
|
17
|
+
* <ul>
|
18
|
+
* <li>1-based list index (first list is used if not specified)</li>
|
19
|
+
* <li>1-based row index (returns all rows if <=0 or not specified)</li>
|
20
|
+
* </ul>
|
21
|
+
*
|
22
|
+
* eg: (all items of 1st list) <code>performAction( 'get_list_item_text' )</code>
|
23
|
+
* eg: (all items of 2nd list) <code>performAction( 'get_list_item_text', '2' )</code>
|
24
|
+
* eg: (1st item of 2nd list) <code>performAction( 'get_list_item_text', '2' , '1' )</code>
|
25
|
+
*
|
26
|
+
* @return <code>bonusInformation</code> contain an array of Strings, one for each row in the list (or only for the specified row):
|
27
|
+
* eg: {"title":"My Title", "subtitle":"Another text field for the same list item"}
|
28
|
+
*
|
29
|
+
*
|
30
|
+
* In ruby, we can then parse the response:
|
31
|
+
* <pre>
|
32
|
+
* response_table = result['bonusInformation']
|
33
|
+
* response_table.each_with_index do | row_data, index |
|
34
|
+
* row_data = JSON.parse( row_data )
|
35
|
+
* response_table[index] = row_data
|
36
|
+
* end
|
37
|
+
* </pre>
|
38
|
+
*
|
39
|
+
* @author Nicholas Albion
|
40
|
+
*/
|
41
|
+
public class GetListItemText implements Action {
|
42
|
+
|
43
|
+
@Override
|
44
|
+
public Result execute(String... args) {
|
45
|
+
int listIndex;
|
46
|
+
int rowIndex = -1;
|
47
|
+
|
48
|
+
if( args.length == 0 ) {
|
49
|
+
listIndex = 0;
|
50
|
+
} else {
|
51
|
+
if( args.length > 1 ) {
|
52
|
+
rowIndex = (Integer.parseInt(args[1]) - 1);
|
53
|
+
}
|
54
|
+
listIndex = (Integer.parseInt(args[0]) - 1);
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
ArrayList<ListView> listViews = InstrumentationBackend.solo.getCurrentListViews();
|
59
|
+
Log.d("GetListItemText", "Found " + listViews.size() + " list views");
|
60
|
+
if( listViews == null || listViews.size() <= listIndex ) {
|
61
|
+
return new Result(false, "Could not find list #" + (listIndex + 1));
|
62
|
+
}
|
63
|
+
|
64
|
+
ListView list = listViews.get(listIndex);
|
65
|
+
Result result = new Result(true);
|
66
|
+
|
67
|
+
if( rowIndex < 0 ) {
|
68
|
+
int count = list.getChildCount();
|
69
|
+
Log.d("GetListItemText", "Found " + count + " list items");
|
70
|
+
for( int i = 0; i < count; i++ ) {
|
71
|
+
result.addBonusInformation( getListItemString( list.getChildAt(i) ) );
|
72
|
+
}
|
73
|
+
} else {
|
74
|
+
result.addBonusInformation( getListItemString( list.getChildAt(rowIndex) ) );
|
75
|
+
}
|
76
|
+
|
77
|
+
return result;
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* @return <code>bonusInformation</code> contain an array of Strings, one for each row in the list (or only for the specified row):
|
82
|
+
* eg: {"title":"My Title", "subtitle":"Another text field for the same list item"}
|
83
|
+
*/
|
84
|
+
private String getListItemString( View row ) {
|
85
|
+
StringBuilder json = new StringBuilder("{");
|
86
|
+
|
87
|
+
if( row instanceof TextView ) {
|
88
|
+
addViewInfo( json, (TextView)row );
|
89
|
+
} else if( row instanceof ViewGroup ) {
|
90
|
+
addViewInfo( json, (ViewGroup)row );
|
91
|
+
}
|
92
|
+
|
93
|
+
json.deleteCharAt( json.length() - 1 ); // remove the last comma
|
94
|
+
json.append('}');
|
95
|
+
return json.toString();
|
96
|
+
}
|
97
|
+
|
98
|
+
private void addViewInfo( StringBuilder json, TextView view ) {
|
99
|
+
int resId = view.getId();
|
100
|
+
String resIdName = view.getResources().getResourceEntryName(resId);
|
101
|
+
|
102
|
+
//json.append("\"id\":\"").append(resIdName).append("\", \"text:\"").append( ((TextView)row).getText() ).append("\"");
|
103
|
+
json.append('"').append(resIdName).append("\":\"").append( ((TextView)view).getText() ).append("\",");
|
104
|
+
}
|
105
|
+
|
106
|
+
private void addViewInfo( StringBuilder json, TableRow tableRow ) {
|
107
|
+
int count = tableRow.getVirtualChildCount();
|
108
|
+
for( int i = 0; i < count; i++ ) {
|
109
|
+
View view = tableRow.getVirtualChildAt(i);
|
110
|
+
if( view instanceof TextView ) {
|
111
|
+
addViewInfo( json, (TextView)view );
|
112
|
+
} else if( view instanceof ViewGroup ) {
|
113
|
+
addViewInfo( json, (ViewGroup)view );
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
private void addViewInfo( StringBuilder json, ViewGroup viewGroup ) {
|
119
|
+
int count = viewGroup.getChildCount();
|
120
|
+
for( int i = 0; i < count; i++ ) {
|
121
|
+
View view = viewGroup.getChildAt(i);
|
122
|
+
if( view instanceof TextView ) {
|
123
|
+
addViewInfo( json, (TextView)view );
|
124
|
+
} else if( view instanceof TableRow ) {
|
125
|
+
addViewInfo( json, (TableRow)view );
|
126
|
+
} else if( view instanceof ViewGroup ) {
|
127
|
+
addViewInfo( json, (ViewGroup)view );
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
@Override
|
133
|
+
public String key() {
|
134
|
+
return "get_list_item_text";
|
135
|
+
}
|
136
|
+
}
|