calabash-android 0.3.8 → 0.4.0.pre1

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.
@@ -66,6 +66,9 @@ Finds a input field by index and blanks its value.
66
66
  Then /^I clear "([^\"]*)"$/ do |name|
67
67
  Finds a input field with matching content description and blanks its value.
68
68
 
69
+ Then /^I clear input field with id "([^\"]*)"$/ do |view_id|
70
+ Finds the input field with id `view_id` and clears the text from it.
71
+
69
72
  Then /^I select "([^\"]*)" from "([^\"]*)"$/ do |item_text, spinner_content_description|
70
73
  Finds the Spinner by 'spinner_content_description' and selects the item with the matching 'item_text'
71
74
 
@@ -53,6 +53,10 @@ module Operations
53
53
  default_device.wake_up()
54
54
  end
55
55
 
56
+ def clear_app_data
57
+ default_device.clear_app_data
58
+ end
59
+
56
60
  def start_test_server_in_background
57
61
  default_device.start_test_server_in_background()
58
62
  end
@@ -92,14 +96,16 @@ module Operations
92
96
  end
93
97
 
94
98
  def query(uiquery, *args)
95
- raise "Currently queries are only supported for webviews" unless uiquery.start_with? "webView"
96
-
97
- uiquery.slice!(0, "webView".length)
98
- if uiquery =~ /(css|xpath):\s*(.*)/
99
- r = performAction("query", $1, $2)
100
- JSON.parse(r["message"])
99
+ if uiquery.start_with? "webView"
100
+ uiquery.slice!(0, "webView".length)
101
+ if uiquery =~ /(css|xpath):\s*(.*)/
102
+ r = performAction("query", $1, $2)
103
+ JSON.parse(r["message"])
104
+ else
105
+ raise "Invalid query #{uiquery}"
106
+ end
101
107
  else
102
- raise "Invalid query #{uiquery}"
108
+ JSON.parse(http("/query", {"query" => uiquery}))
103
109
  end
104
110
  end
105
111
 
@@ -298,6 +304,11 @@ module Operations
298
304
  end
299
305
  end
300
306
 
307
+ def clear_app_data
308
+ cmd = "#{adb_command} shell am instrument sh.calaba.android.test/sh.calaba.instrumentationbackend.ClearAppData"
309
+ raise "Could not clear data" unless system(cmd)
310
+ end
311
+
301
312
  def start_test_server_in_background
302
313
  raise "Will not start test server because of previous failures." if Cucumber.wants_to_quit
303
314
 
@@ -371,7 +382,19 @@ module Operations
371
382
  end
372
383
 
373
384
  def touch(uiquery,options={})
374
- ni
385
+ if uiquery.instance_of? String
386
+ elements = query(uiquery, options)
387
+ raise "No elements found" if elements.empty?
388
+ element = elements.first
389
+ else
390
+ element = uiquery
391
+ end
392
+
393
+ performAction("touch_coordinate", element["frame"]["x"], element["frame"]["y"])
394
+ end
395
+
396
+ def http(options, data=nil)
397
+ default_device.http(options, data)
375
398
  end
376
399
 
377
400
  def html(q)
@@ -481,11 +504,6 @@ module Operations
481
504
  ni
482
505
  end
483
506
 
484
- def http(options, data=nil)
485
- ni
486
- end
487
-
488
-
489
507
  def url_for( verb )
490
508
  ni
491
509
  end
@@ -18,6 +18,10 @@ Then /^I clear input field number (\d+)$/ do |number|
18
18
  performAction('clear_numbered_field',number)
19
19
  end
20
20
 
21
+ Then /^I clear input field with id "([^\"]*)"$/ do |view_id|
22
+ performAction('clear_id_field', view_id)
23
+ end
24
+
21
25
  Then /^I enter text "([^\"]*)" into field with id "([^\"]*)"$/ do |text, view_id|
22
26
  performAction('enter_text_into_id_field', text, view_id)
23
27
  end
@@ -5,4 +5,3 @@ end
5
5
  Then /^I rotate the device to portrait$/ do
6
6
  rotate_phone(0)
7
7
  end
8
-
@@ -1,5 +1,5 @@
1
1
  module Calabash
2
2
  module Android
3
- VERSION = "0.3.8"
3
+ VERSION = "0.4.0.pre1"
4
4
  end
5
5
  end
@@ -18,6 +18,7 @@
18
18
  </application>
19
19
  <uses-sdk android:minSdkVersion="4" />
20
20
  <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.CalabashInstrumentationTestRunner" />
21
+ <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.ClearAppData" />
21
22
 
22
23
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
23
24
  <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
@@ -0,0 +1,11 @@
1
+ package com.jayway.android.robotium.solo;
2
+
3
+ import android.app.Activity;
4
+ import android.app.Instrumentation;
5
+
6
+ public class PublicViewFetcher extends ViewFetcher {
7
+
8
+ public PublicViewFetcher(Instrumentation instrumentation, Activity activity) {
9
+ super(new ActivityUtils(instrumentation, activity, new Sleeper()));
10
+ }
11
+ }
@@ -0,0 +1,48 @@
1
+ package sh.calaba.instrumentationbackend;
2
+
3
+ import android.content.Context;
4
+ import android.os.Bundle;
5
+ import android.test.InstrumentationTestRunner;
6
+ import sh.calaba.instrumentationbackend.actions.HttpServer;
7
+
8
+ import java.io.File;
9
+ import java.lang.reflect.Method;
10
+
11
+ public class ClearAppData extends InstrumentationTestRunner {
12
+ @Override
13
+ public void onCreate(Bundle arguments) {
14
+ if (externalCacheDir() != null) {
15
+ delete(externalCacheDir().getParentFile());
16
+ }
17
+ if (cacheDir() != null) {
18
+ delete(cacheDir().getParentFile());
19
+ }
20
+ }
21
+
22
+ //If provided a file will delete it.
23
+ //If provided a directory will recursively delete files but preserve directories
24
+ private void delete(File file_or_directory) {
25
+ if (file_or_directory == null) {
26
+ return;
27
+ }
28
+
29
+ if (file_or_directory.isDirectory()) {
30
+ if (file_or_directory.listFiles() != null) {
31
+ for(File f : file_or_directory.listFiles()) {
32
+ delete(f);
33
+ }
34
+ }
35
+ } else {
36
+ file_or_directory.delete();
37
+ }
38
+ }
39
+
40
+ private File externalCacheDir() {
41
+ return getTargetContext().getExternalCacheDir();
42
+ }
43
+
44
+ private File cacheDir() {
45
+ return getTargetContext().getCacheDir();
46
+ }
47
+
48
+ }
@@ -2,6 +2,7 @@ package sh.calaba.instrumentationbackend;
2
2
 
3
3
  import android.Manifest;
4
4
  import android.content.pm.PackageManager;
5
+ import com.jayway.android.robotium.solo.PublicViewFetcher;
5
6
  import sh.calaba.instrumentationbackend.actions.Actions;
6
7
  import sh.calaba.instrumentationbackend.actions.HttpServer;
7
8
  import android.app.Activity;
@@ -21,6 +22,7 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
21
22
 
22
23
  public static Instrumentation instrumentation;
23
24
  public static SoloEnhanced solo;
25
+ public static PublicViewFetcher viewFetcher;
24
26
  public static Actions actions;
25
27
 
26
28
  public InstrumentationBackend() {
@@ -32,6 +34,7 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2 {
32
34
  super.setUp();
33
35
 
34
36
  solo = new SoloEnhanced(getInstrumentation(), this.getActivity());
37
+ viewFetcher = new PublicViewFetcher(getInstrumentation(), this.getActivity());
35
38
  actions = new Actions(getInstrumentation(), this);
36
39
  instrumentation = getInstrumentation();
37
40
  }
@@ -1,6 +1,7 @@
1
1
  package sh.calaba.instrumentationbackend.actions;
2
2
 
3
3
  import java.io.*;
4
+ import java.util.Map;
4
5
  import java.util.Properties;
5
6
  import java.util.List;
6
7
  import java.util.concurrent.locks.Condition;
@@ -16,9 +17,12 @@ import android.view.View;
16
17
  import sh.calaba.instrumentationbackend.Command;
17
18
  import sh.calaba.instrumentationbackend.InstrumentationBackend;
18
19
  import sh.calaba.instrumentationbackend.Result;
20
+ import sh.calaba.instrumentationbackend.query.QueryResult;
21
+ import sh.calaba.instrumentationbackend.query.Query;
19
22
  import sh.calaba.org.codehaus.jackson.map.DeserializationConfig.Feature;
20
23
  import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
21
24
  import android.util.Log;
25
+ import sh.calaba.org.codehaus.jackson.type.TypeReference;
22
26
 
23
27
  public class HttpServer extends NanoHTTPD {
24
28
  private static final String TAG = "InstrumentationBackend";
@@ -67,6 +71,17 @@ public class HttpServer extends NanoHTTPD {
67
71
  if (uri.endsWith("/ping")) {
68
72
  return new NanoHTTPD.Response( HTTP_OK, MIME_HTML, "pong");
69
73
 
74
+ } else if (uri.endsWith("/query")) {
75
+ try {
76
+ String commandString = params.getProperty("json");
77
+ ObjectMapper mapper = new ObjectMapper();
78
+ Map<String, String> command = mapper.readValue(commandString, new TypeReference<Map<String, String>>() {});
79
+ QueryResult result = new Query(command.get("query")).execute();
80
+ return new NanoHTTPD.Response( HTTP_OK, MIME_HTML, result.asJson());
81
+ } catch (IOException e) {
82
+ e.printStackTrace();
83
+ return new Response(HTTP_INTERNALERROR, MIME_PLAINTEXT, "Could not parse arguments as JSON");
84
+ }
70
85
  } else if (uri.endsWith("/kill")) {
71
86
  lock.lock();
72
87
  try {
@@ -0,0 +1,43 @@
1
+ package sh.calaba.instrumentationbackend.actions.activity;
2
+
3
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
4
+ import sh.calaba.instrumentationbackend.Result;
5
+ import sh.calaba.instrumentationbackend.actions.Action;
6
+
7
+ public class SetActivityOrientation implements Action {
8
+
9
+ @Override
10
+ public Result execute(String... args) {
11
+ if (args.length == 0) {
12
+ throw new IllegalArgumentException("No orientation provided. Use 'landscape' or 'portrait'");
13
+ }
14
+ String orientation = args[0].toLowerCase();
15
+
16
+ if (orientation != "landscape" && orientation != "portrait") {
17
+ throw new IllegalArgumentException("Invalid orientation '" + orientation + "'. Use 'landscape' or 'portrait'");
18
+ }
19
+
20
+ if (orientation == "landscape") {
21
+ InstrumentationBackend.solo.setActivityOrientation(0);
22
+ } else {
23
+ InstrumentationBackend.solo.setActivityOrientation(1);
24
+ }
25
+ // Wait 100ms for orientation change to happen.
26
+ sleep(100);
27
+
28
+ return Result.successResult();
29
+ }
30
+
31
+ private void sleep(long time) {
32
+ try {
33
+ Thread.sleep(time);
34
+ } catch (Exception e) {
35
+ throw new RuntimeException(e);
36
+ }
37
+ }
38
+
39
+ @Override
40
+ public String key() {
41
+ return "set_activity_orientation";
42
+ }
43
+ }
@@ -0,0 +1,39 @@
1
+ package sh.calaba.instrumentationbackend.actions.map;
2
+
3
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
4
+ import sh.calaba.instrumentationbackend.Result;
5
+ import sh.calaba.instrumentationbackend.actions.Action;
6
+
7
+ public class SetOrientation implements Action {
8
+
9
+ @Override
10
+ public Result execute(String... args) {
11
+ String orientation = "";
12
+ if (args != null && args.length >= 1) {
13
+ orientation = args[0].toLowerCase();
14
+ }
15
+
16
+ int changed = -1;
17
+
18
+ if( "landscape".contentEquals(orientation) ) {
19
+ changed = 0;
20
+ } else if( "portrait".contentEquals(orientation) ) {
21
+ changed = 1;
22
+ }
23
+
24
+ if (changed != -1) {
25
+ InstrumentationBackend.solo.setActivityOrientation(changed);
26
+ // Wait 100ms for orientation to happen.
27
+ try { Thread.sleep(100); } catch (Exception e) {}
28
+ // setActivityOrientation returns void so assume success.
29
+ return Result.successResult();
30
+ }
31
+
32
+ return new Result(false, "Requested invalid orientation: '" + orientation + "' Expected 'landscape' or 'portrait'.");
33
+ }
34
+
35
+ @Override
36
+ public String key() {
37
+ return "set_orientation";
38
+ }
39
+ }
@@ -0,0 +1,28 @@
1
+ package sh.calaba.instrumentationbackend.actions.gestures;
2
+
3
+
4
+ import android.view.Display;
5
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
6
+ import sh.calaba.instrumentationbackend.Result;
7
+ import sh.calaba.instrumentationbackend.actions.Action;
8
+
9
+
10
+ public class TouchCoordinates implements Action {
11
+
12
+ @Override
13
+ public Result execute(String... args) {
14
+ Display display = InstrumentationBackend.solo.getCurrentActivity().getWindowManager().getDefaultDisplay();
15
+
16
+ float x = Float.parseFloat(args[0]);
17
+ float y = Float.parseFloat(args[1]);
18
+
19
+ InstrumentationBackend.solo.clickOnScreen(x, y);
20
+ return Result.successResult();
21
+ }
22
+
23
+ @Override
24
+ public String key() {
25
+ return "touch_coordinate";
26
+ }
27
+
28
+ }
@@ -0,0 +1,90 @@
1
+ package sh.calaba.instrumentationbackend.query;
2
+
3
+ import android.content.res.Resources;
4
+ import android.view.View;
5
+ import android.widget.Button;
6
+ import android.widget.CheckBox;
7
+ import android.widget.TextView;
8
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
9
+
10
+ import java.util.ArrayList;
11
+ import java.util.HashMap;
12
+ import java.util.List;
13
+ import java.util.Map;
14
+
15
+ import static sh.calaba.instrumentationbackend.InstrumentationBackend.*;
16
+
17
+ public class Query {
18
+
19
+ private String queryString;
20
+
21
+ public Query(String queryString) {
22
+ System.out.println("CREATED QUERY: " + queryString);
23
+ this.queryString = queryString;
24
+ }
25
+
26
+
27
+ public QueryResult execute() {
28
+ List<Map<?,?>> result = new ArrayList<Map<?, ?>>();
29
+ for (View v : allVisibleViews()) {
30
+
31
+ if (!v.isShown() ) {
32
+ continue;
33
+ }
34
+
35
+ if (queryString != null) {
36
+ if (!queryString.isEmpty()) {
37
+ if (!queryString.equalsIgnoreCase(v.getClass().getSimpleName())) {
38
+ continue;
39
+ }
40
+ }
41
+ }
42
+
43
+ System.out.println(v.getClass().getSimpleName().toString());
44
+ Map view = new HashMap();
45
+ view.put("class", v.getClass().getSimpleName());
46
+ view.put("description", v.toString());
47
+ view.put("contentDescription", v.getContentDescription());
48
+ view.put("enabled", v.isEnabled());
49
+ String id = null;
50
+ try {
51
+ id = InstrumentationBackend.solo.getCurrentActivity().getResources().getResourceEntryName(v.getId());
52
+ } catch (Resources.NotFoundException e) {
53
+ System.out.println("Resource not found for " + v.getId() + ". Moving on.");
54
+ }
55
+ view.put("id", id);
56
+
57
+ Map frame = new HashMap();
58
+ int[] location = new int[2];
59
+ v.getLocationOnScreen(location);
60
+
61
+ frame.put("x", location[0]);
62
+ frame.put("y", location[1]);
63
+ frame.put("width", v.getWidth());
64
+ frame.put("height", v.getHeight());
65
+
66
+ view.put("frame", frame);
67
+
68
+ if (v instanceof Button) {
69
+ Button b = (Button)v;
70
+ view.put("text", b.getText().toString());
71
+ }
72
+ if (v instanceof CheckBox) {
73
+ CheckBox c = (CheckBox)v;
74
+ view.put("checked", c.isChecked());
75
+ }
76
+ if (v instanceof TextView) {
77
+ TextView t = (TextView)v;
78
+ view.put("text", t.getText().toString());
79
+ }
80
+
81
+ result.add(view);
82
+ }
83
+ return new QueryResult(result);
84
+ }
85
+
86
+
87
+ public List<View> allVisibleViews() {
88
+ return viewFetcher.getAllViews(false);
89
+ }
90
+ }
@@ -0,0 +1,27 @@
1
+ package sh.calaba.instrumentationbackend.query;
2
+
3
+ import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
4
+
5
+ import java.io.IOException;
6
+ import java.util.List;
7
+
8
+ public class QueryResult {
9
+
10
+ private List result;
11
+
12
+ public QueryResult(List result) {
13
+
14
+ this.result = result;
15
+ }
16
+
17
+
18
+ public String asJson() {
19
+ ObjectMapper mapper = new ObjectMapper();
20
+
21
+ try {
22
+ return mapper.writeValueAsString(result);
23
+ } catch (IOException e) {
24
+ throw new RuntimeException("Could not convert result to json", e);
25
+ }
26
+ }
27
+ }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calabash-android
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
5
- prerelease:
4
+ version: 0.4.0.pre1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jonas Maturana Larsen
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-07 00:00:00.000000000 Z
12
+ date: 2012-12-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber
@@ -169,8 +169,10 @@ files:
169
169
  - test-server/instrumentation-backend/res/layout/main.xml
170
170
  - test-server/instrumentation-backend/res/values/strings.xml
171
171
  - test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/MapViewUtils.java
172
+ - test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/PublicViewFetcher.java
172
173
  - test-server/instrumentation-backend/src/com/jayway/android/robotium/solo/SoloEnhanced.java
173
174
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/CalabashInstrumentationTestRunner.java
175
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearAppData.java
174
176
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Command.java
175
177
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java
176
178
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java
@@ -181,6 +183,8 @@ files:
181
183
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java
182
184
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/NanoHTTPD.java
183
185
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/NullAction.java
186
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetActivityOrientation.java
187
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetOrientation.java
184
188
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressButtonNumber.java
185
189
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressButtonText.java
186
190
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/button/PressImageButtonDescription.java
@@ -194,6 +198,7 @@ files:
194
198
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/gestures/ClickOnScreen.java
195
199
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/gestures/Drag.java
196
200
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/gestures/Swipe.java
201
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/gestures/TouchCoordinates.java
197
202
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/helpers/InspectCurrentDialog.java
198
203
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/helpers/ListActions.java
199
204
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/l10n/L10nHelper.java
@@ -274,6 +279,8 @@ files:
274
279
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/SetPropertyByCssSelector.java
275
280
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/SetText.java
276
281
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/Touch.java
282
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Query.java
283
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/QueryResult.java
277
284
  - test-server/instrumentation-backend/src/sh/calaba/org/codehaus/jackson/Base64Variant.java
278
285
  - test-server/instrumentation-backend/src/sh/calaba/org/codehaus/jackson/Base64Variants.java
279
286
  - test-server/instrumentation-backend/src/sh/calaba/org/codehaus/jackson/FormatSchema.java
@@ -698,9 +705,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
698
705
  required_rubygems_version: !ruby/object:Gem::Requirement
699
706
  none: false
700
707
  requirements:
701
- - - ! '>='
708
+ - - ! '>'
702
709
  - !ruby/object:Gem::Version
703
- version: '0'
710
+ version: 1.3.1
704
711
  requirements: []
705
712
  rubyforge_project:
706
713
  rubygems_version: 1.8.24