honeydew 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,6 +24,7 @@ module Honeydew
24
24
  perform_assertion :is_button_present, :text => button_text
25
25
  end
26
26
 
27
+ # TODO: Look for a better way to express these similar looking matchers
27
28
  def has_child_count?(parent_element_description, child_element_description, child_count)
28
29
  perform_assertion :is_child_count_equal_to,
29
30
  :parent_description => parent_element_description,
@@ -31,6 +32,13 @@ module Honeydew
31
32
  :child_count => child_count
32
33
  end
33
34
 
35
+ def has_child_count_greater_than?(parent_element_description, child_element_description, child_count)
36
+ perform_assertion :is_child_count_greater_than,
37
+ :parent_description => parent_element_description,
38
+ :child_description => child_element_description,
39
+ :child_count => child_count
40
+ end
41
+
34
42
  def has_element_with_nested_text?(parent_description, child_text)
35
43
  perform_assertion :is_element_with_nested_text_present,
36
44
  :parent_description => parent_description,
@@ -1,3 +1,3 @@
1
1
  module Honeydew
2
- VERSION = '0.20.0'
2
+ VERSION = '0.21.0'
3
3
  end
data/server/pom.xml CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  <groupId>amplify</groupId>
7
7
  <artifactId>honeydew-server</artifactId>
8
- <version>0.20.0</version>
8
+ <version>0.21.0</version>
9
9
  <packaging>jar</packaging>
10
10
  <name>Honeydew Android Server</name>
11
11
 
@@ -72,11 +72,12 @@
72
72
  <groupId>fi.iki.elonen</groupId>
73
73
  <artifactId>nanohttpd</artifactId>
74
74
  <version>2.0.3</version>
75
- </dependency>
76
- <dependency>
77
- <groupId>fi.iki.elonen</groupId>
78
- <artifactId>nanohttpd-webserver</artifactId>
79
- <version>2.0.3</version>
75
+ <exclusions>
76
+ <exclusion>
77
+ <groupId>org.apache.httpcomponents</groupId>
78
+ <artifactId>httpclient</artifactId>
79
+ </exclusion>
80
+ </exclusions>
80
81
  </dependency>
81
82
  </dependencies>
82
83
 
@@ -9,6 +9,8 @@ import java.util.Map;
9
9
  public abstract class Action {
10
10
  protected final UiDevice uiDevice;
11
11
 
12
+ protected final String TAG = getClass().getSimpleName();
13
+
12
14
  public Action(UiDevice uiDevice) {
13
15
  this.uiDevice = uiDevice;
14
16
  }
@@ -39,17 +41,17 @@ public abstract class Action {
39
41
  protected ViewSelector getViewSelector(Map<String, Object> arguments) {
40
42
  ViewSelector viewSelector = new ViewSelector();
41
43
 
42
- Log.d(getClass().getName(), arguments.toString());
44
+ Log.d(TAG, arguments.toString());
43
45
  if (arguments.containsKey("type")) {
44
- Log.d(getClass().getName(), String.format("Type %s", (String) arguments.get("type")));
46
+ Log.d(TAG, String.format("Type %s", (String) arguments.get("type")));
45
47
  viewSelector.withType((String) arguments.get("type"));
46
48
  }
47
49
  if (arguments.containsKey("text")) {
48
- Log.d(getClass().getName(), String.format("Text %s", (String) arguments.get("text")));
50
+ Log.d(TAG, String.format("Text %s", (String) arguments.get("text")));
49
51
  viewSelector.withText((String) arguments.get("text"));
50
52
  }
51
53
  if (arguments.containsKey("description")) {
52
- Log.d(getClass().getName(), String.format("Description %s", (String) arguments.get("description")));
54
+ Log.d(TAG, String.format("Description %s", (String) arguments.get("description")));
53
55
  viewSelector.withDescription((String) arguments.get("description"));
54
56
  }
55
57
  return viewSelector;
@@ -8,24 +8,26 @@ import com.google.common.base.Stopwatch;
8
8
 
9
9
  import java.lang.reflect.Constructor;
10
10
  import java.lang.reflect.InvocationTargetException;
11
- import java.util.HashMap;
11
+ import java.util.Map;
12
12
  import java.util.Set;
13
- import java.util.concurrent.TimeUnit;
14
13
 
14
+ import static com.google.common.collect.Maps.newHashMap;
15
15
  import static com.google.common.collect.Sets.newHashSet;
16
+ import static java.util.concurrent.TimeUnit.MILLISECONDS;
16
17
 
17
18
  public class ActionsExecutor {
18
19
 
19
- private final UiDevice uiDevice;
20
- private final HashMap<String, Action> actions;
20
+ protected final UiDevice uiDevice;
21
+ private final Map<String, Action> actions;
22
+ private static final String TAG = ActionsExecutor.class.getName();
21
23
 
22
24
  public ActionsExecutor(UiDevice uiDevice) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
23
25
  this.uiDevice = uiDevice;
24
- actions = new HashMap();
26
+ actions = newHashMap();
25
27
  for (Class<? extends Action> actionClass : allActionClasses()) {
26
28
  Constructor<? extends Action> constructor = actionClass.getConstructor(UiDevice.class);
27
- Action action = constructor.newInstance(getUiDevice());
28
- Log.d(getClass().getName(), String.format("Registering action: %s", action.name()));
29
+ Action action = constructor.newInstance(this.uiDevice);
30
+ Log.d(TAG, String.format("Registering action: %s", action.name()));
29
31
  actions.put(action.name(), action);
30
32
  }
31
33
  }
@@ -35,12 +37,9 @@ public class ActionsExecutor {
35
37
  try {
36
38
  Action action = actions.get(actionName);
37
39
  if (action == null) {
38
- return new Result("Action: " + actionName + " does not exists");
40
+ return new Result("Action: " + actionName + " does not exist");
39
41
  }
40
-
41
- Result result = executeWithStopwatch(command, action);
42
-
43
- return result;
42
+ return executeWithStopwatch(command, action);
44
43
  } catch (Exception e) {
45
44
  return new Result("Exception, on calling " + actionName, e);
46
45
  }
@@ -52,8 +51,8 @@ public class ActionsExecutor {
52
51
  Result result = action.execute(command.getArguments());
53
52
 
54
53
  timer.stop();
55
- Log.i(getClass().getName(), String.format("action '%s' took %d ms to execute on the tablet",
56
- command.getAction(), timer.elapsed(TimeUnit.MILLISECONDS)));
54
+ Log.i(TAG, String.format("action '%s' took %d ms to execute on the tablet",
55
+ command.getAction(), timer.elapsed(MILLISECONDS)));
57
56
  return result;
58
57
  }
59
58
 
@@ -68,6 +67,7 @@ public class ActionsExecutor {
68
67
  actionClasses.add(IsButtonPresent.class);
69
68
  actionClasses.add(IsElementWithNestedTextPresent.class);
70
69
  actionClasses.add(IsChildCountEqualTo.class);
70
+ actionClasses.add(IsChildCountGreaterThan.class);
71
71
  actionClasses.add(Click.class);
72
72
  actionClasses.add(ClickAndWaitForNewWindow.class);
73
73
  actionClasses.add(LongClick.class);
@@ -84,8 +84,4 @@ public class ActionsExecutor {
84
84
  actionClasses.add(ScrollToTextByIndex.class);
85
85
  return actionClasses;
86
86
  }
87
-
88
- private UiDevice getUiDevice() {
89
- return uiDevice;
90
- }
91
87
  }
@@ -5,21 +5,22 @@ import android.view.KeyEvent;
5
5
  import com.amplify.honeydew_server.httpd.RemoteCommandReceiver;
6
6
  import com.android.uiautomator.core.UiDevice;
7
7
  import com.android.uiautomator.testrunner.UiAutomatorTestCase;
8
- import fi.iki.elonen.ServerRunner;
9
8
 
10
9
  public class TestRunner extends UiAutomatorTestCase {
11
10
 
11
+ private static final String TAG = TestRunner.class.getSimpleName();
12
+
12
13
  public void testRemoteLoop() throws Exception {
13
- Log.d(getClass().getName(), "Starting honeydew-server...");
14
+ Log.d(TAG, "Starting honeydew-server...");
14
15
 
15
16
  UiDevice uiDevice = getUiDevice();
16
17
  uiDevice.wakeUp();
17
18
  unlockEmulator();
18
19
 
19
20
  RemoteCommandReceiver remoteCommandReceiver = new RemoteCommandReceiver(new ActionsExecutor(uiDevice));
20
- ServerRunner.executeInstance(remoteCommandReceiver);
21
+ remoteCommandReceiver.start();
21
22
 
22
- Log.d(getClass().getName(), "honeydew-server started, waiting for commands");
23
+ Log.d(TAG, "honeydew-server started, waiting for commands");
23
24
  while(true) {
24
25
  Thread.sleep(1000);
25
26
  }
@@ -0,0 +1,33 @@
1
+ package com.amplify.honeydew_server.actions;
2
+
3
+ import android.util.Log;
4
+ import com.amplify.honeydew_server.Action;
5
+ import com.amplify.honeydew_server.Result;
6
+ import com.android.uiautomator.core.UiCollection;
7
+ import com.android.uiautomator.core.UiDevice;
8
+ import com.android.uiautomator.core.UiObjectNotFoundException;
9
+ import com.android.uiautomator.core.UiSelector;
10
+
11
+ import java.util.Map;
12
+
13
+ public abstract class AbstractChildCountAction extends Action {
14
+ public AbstractChildCountAction(UiDevice uiDevice) {
15
+ super(uiDevice);
16
+ }
17
+
18
+ protected abstract boolean isTrue(int childCount, int count);
19
+
20
+ @Override
21
+ public final Result execute(Map<String, Object> arguments) throws UiObjectNotFoundException {
22
+ Log.d(TAG, "Entering " + TAG);
23
+ String parentDescription = (String) arguments.get("parent_description");
24
+ String childDescription = (String) arguments.get("child_description");
25
+ int expectedCount = ((Double) arguments.get("child_count")).intValue();
26
+
27
+ UiCollection parentElement = new UiCollection(new UiSelector().description(parentDescription));
28
+ int actualCount = parentElement.getChildCount(new UiSelector().description(childDescription));
29
+ Log.d(TAG, "Actual count was: " + actualCount + " when " + expectedCount + " was expected");
30
+ return new Result(isTrue(expectedCount, actualCount), "Actual count was: " + actualCount + " when " + expectedCount + " was expected");
31
+
32
+ }
33
+ }
@@ -1,25 +1,17 @@
1
1
  package com.amplify.honeydew_server.actions;
2
2
 
3
- import com.amplify.honeydew_server.*;
4
- import com.android.uiautomator.core.*;
3
+ import com.android.uiautomator.core.UiDevice;
5
4
 
6
- import java.util.Map;
7
-
8
- public class IsChildCountEqualTo extends Action {
5
+ public class IsChildCountEqualTo extends AbstractChildCountAction {
9
6
 
10
7
  public IsChildCountEqualTo(UiDevice uiDevice) {
11
8
  super(uiDevice);
12
9
  }
13
10
 
14
11
  @Override
15
- public Result execute(Map<String, Object> arguments) throws UiObjectNotFoundException {
16
- String parentDescription = (String) arguments.get("parent_description");
17
- String childDescription = (String) arguments.get("child_description");
18
- int childCount = (Integer) arguments.get("child_count");
19
-
20
- UiCollection parentElement = new UiCollection(new UiSelector().description(parentDescription));
21
- int count = parentElement.getChildCount(new UiSelector().description(childDescription));
22
- return new Result(childCount == count, "Actual count was: " + count + " when " + childCount + " was expected");
12
+ protected boolean isTrue(int childCount, int count) {
13
+ return childCount == count;
23
14
  }
24
15
 
16
+
25
17
  }
@@ -0,0 +1,16 @@
1
+ package com.amplify.honeydew_server.actions;
2
+
3
+ import com.android.uiautomator.core.UiDevice;
4
+
5
+ public class IsChildCountGreaterThan extends AbstractChildCountAction {
6
+
7
+ public IsChildCountGreaterThan(UiDevice uiDevice) {
8
+ super(uiDevice);
9
+ }
10
+
11
+ @Override
12
+ protected boolean isTrue(int expectedCount, int actualCount) {
13
+ return actualCount > expectedCount;
14
+ }
15
+
16
+ }
@@ -1,7 +1,9 @@
1
1
  package com.amplify.honeydew_server.httpd;
2
2
 
3
3
  import android.util.Log;
4
- import com.amplify.honeydew_server.*;
4
+ import com.amplify.honeydew_server.ActionsExecutor;
5
+ import com.amplify.honeydew_server.Command;
6
+ import com.amplify.honeydew_server.Result;
5
7
  import com.google.gson.Gson;
6
8
  import com.google.gson.reflect.TypeToken;
7
9
  import fi.iki.elonen.NanoHTTPD;
@@ -10,15 +12,20 @@ import java.io.IOException;
10
12
  import java.lang.reflect.Type;
11
13
  import java.util.Map;
12
14
 
15
+ import static java.lang.String.format;
16
+
13
17
  public class RemoteCommandReceiver extends NanoHTTPD {
14
18
 
15
19
  private static final String PLAIN_TEXT = "plain/text";
20
+ public static final Type ARGUMENTS_COLLECTION_TYPE = new TypeToken<Map<String, Object>>() {
21
+ }.getType();
16
22
  private final ActionsExecutor actionsExecutor;
17
23
 
18
- private final Response statusOkResponse = new Response("honeydew-server is awaiting commands");
19
- private final Response terminateOkResponse = new Response("honeydew-server is stopping");
20
- private final Response badRequestResponse = new Response(Response.Status.BAD_REQUEST, PLAIN_TEXT, "Unsupported command");
24
+ private static final Response OK = new Response("honeydew-server is awaiting commands");
25
+ private static final Response TERMINATED = new Response("honeydew-server is stopping");
26
+ private final Response BAD_REQUEST = new Response(Response.Status.BAD_REQUEST, PLAIN_TEXT, "Unsupported command");
21
27
 
28
+ private static final String TAG = RemoteCommandReceiver.class.getSimpleName();
22
29
  private final Gson jsonParser = new Gson();
23
30
 
24
31
  public RemoteCommandReceiver(ActionsExecutor actionsExecutor) throws IOException, InterruptedException {
@@ -29,35 +36,43 @@ public class RemoteCommandReceiver extends NanoHTTPD {
29
36
  @Override
30
37
  public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files) {
31
38
  if (method == Method.POST && uri.equalsIgnoreCase("/terminate")) {
32
- Log.d(getClass().getName(), "Got terminate request, finishing up...");
33
- stop();
34
- return terminateOkResponse;
35
- } else if (method == Method.POST && uri.equalsIgnoreCase("/command")) {
39
+ return terminate();
40
+ }
41
+ if (method == Method.POST && uri.equalsIgnoreCase("/command")) {
36
42
  return performCommand(params);
37
- } else if (method == Method.GET && uri.equalsIgnoreCase("/status")) {
38
- Log.d(getClass().getName(), "Got status request, responding OK");
39
- return statusOkResponse;
40
43
  }
44
+ if (method == Method.GET && uri.equalsIgnoreCase("/status")) {
45
+ return status();
46
+ }
47
+
48
+ return BAD_REQUEST;
49
+ }
50
+
51
+ private Response status() {
52
+ Log.d(TAG, "Got status request, responding OK");
53
+ return OK;
54
+ }
41
55
 
42
- return badRequestResponse;
56
+ private Response terminate() {
57
+ Log.d(TAG, "Got terminate request, finishing up...");
58
+ stop();
59
+ return TERMINATED;
43
60
  }
44
61
 
45
62
  private Response performCommand(Map<String, String> params) {
46
63
  String action = params.get("action");
47
64
  String argumentJson = params.get("arguments");
48
- Type argumentCollectionType = new TypeToken<Map<String, Object>>(){}.getType();
49
- Map<String, Object> arguments = jsonParser.fromJson(argumentJson, argumentCollectionType);
65
+ Map<String, Object> arguments = jsonParser.fromJson(argumentJson, ARGUMENTS_COLLECTION_TYPE);
50
66
 
51
- Log.i(getClass().getName(), String.format("Performing action %s: %s for %s", action, argumentJson, params.toString()));
67
+ Log.i(TAG, format("Performing action %s: %s for %s", action, argumentJson, params.toString()));
52
68
  try {
53
69
  Result result = actionsExecutor.execute(new Command(action, arguments));
54
70
  if (result.success) {
55
71
  return new Response(result.description);
56
- } else {
57
- return new Response(Response.Status.NO_CONTENT, null, (String) null);
58
72
  }
59
- } catch(Exception exception) {
60
- Log.e(getClass().getName(), String.format("Server error while processing command %s: %s", action, exception.toString()));
73
+ return new Response(Response.Status.NO_CONTENT, null, (String) null);
74
+ } catch (Exception exception) {
75
+ Log.e(TAG, format("Server error while processing command %s: %s", action, exception.toString()));
61
76
  return new Response(Response.Status.INTERNAL_ERROR, PLAIN_TEXT, exception.getMessage());
62
77
  }
63
78
  }
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: honeydew
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.20.0
5
+ version: 0.21.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Selvakumar Natesan
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-08-19 00:00:00.000000000 Z
15
+ date: 2013-08-22 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -182,6 +182,7 @@ files:
182
182
  - server/src/main/java/com/amplify/honeydew_server/Command.java
183
183
  - server/src/main/java/com/amplify/honeydew_server/Result.java
184
184
  - server/src/main/java/com/amplify/honeydew_server/TestRunner.java
185
+ - server/src/main/java/com/amplify/honeydew_server/actions/AbstractChildCountAction.java
185
186
  - server/src/main/java/com/amplify/honeydew_server/actions/Click.java
186
187
  - server/src/main/java/com/amplify/honeydew_server/actions/ClickAndWaitForNewWindow.java
187
188
  - server/src/main/java/com/amplify/honeydew_server/actions/DumpWindowHierarchy.java
@@ -189,6 +190,7 @@ files:
189
190
  - server/src/main/java/com/amplify/honeydew_server/actions/InspectOptionInSettingsMenu.java
190
191
  - server/src/main/java/com/amplify/honeydew_server/actions/IsButtonPresent.java
191
192
  - server/src/main/java/com/amplify/honeydew_server/actions/IsChildCountEqualTo.java
193
+ - server/src/main/java/com/amplify/honeydew_server/actions/IsChildCountGreaterThan.java
192
194
  - server/src/main/java/com/amplify/honeydew_server/actions/IsElementWithNestedTextPresent.java
193
195
  - server/src/main/java/com/amplify/honeydew_server/actions/IsOptionInSettingsMenuDisabled.java
194
196
  - server/src/main/java/com/amplify/honeydew_server/actions/IsOptionInSettingsMenuEnabled.java
@@ -210,7 +212,7 @@ files:
210
212
  - spec/honeydew/device_matchers_spec.rb
211
213
  - spec/honeydew/device_spec.rb
212
214
  - spec/spec_helper.rb
213
- - server/target/honeydew-server-0.20.0.jar
215
+ - server/target/honeydew-server-0.21.0.jar
214
216
  homepage:
215
217
  licenses: []
216
218
  post_install_message: