honeydew 0.20.0 → 0.21.0

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.
@@ -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: