calabash-android 0.4.7.pre9 → 0.4.7.pre10

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.
Files changed (21) hide show
  1. checksums.yaml +4 -4
  2. data/bin/calabash-android-console.rb +0 -4
  3. data/bin/calabash-android-run.rb +1 -7
  4. data/lib/calabash-android/helpers.rb +6 -2
  5. data/lib/calabash-android/lib/TestServer.apk +0 -0
  6. data/lib/calabash-android/lib/screenshotTaker.jar +0 -0
  7. data/lib/calabash-android/operations.rb +149 -9
  8. data/lib/calabash-android/version.rb +1 -1
  9. data/test-server/AndroidManifest.xml +3 -0
  10. data/test-server/instrumentation-backend/.classpath +1 -1
  11. data/test-server/instrumentation-backend/libs/robotium-solo-4.2.jar +0 -0
  12. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearPreferences.java +36 -0
  13. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/GetPreferences.java +37 -0
  14. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/SetPreferences.java +56 -0
  15. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/TestHelpers.java +28 -4
  16. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/ClearPreferences.java +37 -0
  17. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/GetPreferences.java +39 -0
  18. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/PreferencesUtils.java +229 -0
  19. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/SetPreferences.java +56 -0
  20. metadata +11 -3
  21. data/test-server/instrumentation-backend/libs/robotium-solo-4.1.jar +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f56fb3f7f459dfeb08a1e0c6dce1c30b34036348
4
- data.tar.gz: 98f38bd3c9b31367831e9eb164554313507e1059
3
+ metadata.gz: f9bf0084a84ca0e23fb28a5dbc4309a4395cee8a
4
+ data.tar.gz: 62401164c05b9f8680516df03dccf9496266347c
5
5
  SHA512:
6
- metadata.gz: 7175bb6bb904ad0448d3eeb2035af00a27b4b4d79b782d8f293260d0c888e4e0e98a58ad4a633e62882123d5e7339fa6a82da4ccdfc802f2dab3613dce813d5a
7
- data.tar.gz: 801089f346a1a29a90a5606e948980c8d573c8e0bc4379cbf005c39855ccf9dc999972bcc076e1c1201c7124fa8b4312bf14d88cb27a2401ec3376a799e28cfb
6
+ metadata.gz: f98938832bd593c95650fd10bb04961be5cd1f0e2183a1a351a6d97e86e297f408fbdc7f285b453e6f307e2d6de3e319339f4f92897459221a272e13adaaceb0
7
+ data.tar.gz: ef73bc3c23d04b37452a010390c8c3274d6ba55c9ea2c5de7a51f021f930ef532c9e7d481a5d73b1111447b3ecf61cc40a4201c43d7ef4ecedac0b533e6ae0c4
@@ -1,10 +1,6 @@
1
1
  def calabash_console(app_path = nil)
2
2
  test_server_path = test_server_path(app_path)
3
3
 
4
- unless ENV["TEST_SERVER_PORT"]
5
- ENV["TEST_SERVER_PORT"] = "34777"
6
- end
7
-
8
4
  ENV["IRBRC"] = File.join(File.dirname(__FILE__), '..', 'irbrc')
9
5
 
10
6
  unless ENV["MAIN_ACTIVITY"]
@@ -16,15 +16,9 @@ def calabash_run(app_path = nil)
16
16
  build_test_server_if_needed(app_path)
17
17
 
18
18
  test_server_path = test_server_path(app_path)
19
- if ENV["TEST_SERVER_PORT"]
20
- test_server_port = ENV["TEST_SERVER_PORT"]
21
- else
22
- test_server_port = "34777"
23
- end
24
19
  env = "MAIN_ACTIVITY=#{main_activity(app_path)} "\
25
20
  "APP_PATH=\"#{app_path}\" "\
26
- "TEST_APP_PATH=\"#{test_server_path}\" "\
27
- "TEST_SERVER_PORT=#{test_server_port}"
21
+ "TEST_APP_PATH=\"#{test_server_path}\""
28
22
  else
29
23
  env = ""
30
24
  end
@@ -28,9 +28,9 @@ end
28
28
  def manifest(app)
29
29
  out_path = manifest_path(app)
30
30
  manifest_file = File.join(out_path, 'AndroidManifest.xml')
31
- unless File.exist?(manifest_file)
31
+ unless File.size?(manifest_file)
32
32
  manifest_extractor = File.join(File.expand_path(File.dirname(__FILE__)),'lib', 'apktool-cli-1.5.3-SNAPSHOT.jar')
33
- output = `java -jar "#{manifest_extractor}" d -s "#{app}" #{out_path} 2>&1`
33
+ output = `java -jar "#{manifest_extractor}" d -s --frame-path "#{framework_path(app)}" -f "#{app}" #{out_path} 2>&1`
34
34
  raise "Unable to extract manifest: #{output}" unless File.size?(manifest_file)
35
35
  # Tidy up a bit. It would be nice if apktool could just dump the manifest alone.
36
36
  FileUtils.rm_rf(%w{res assets classes.dex}.map {|f| File.join(out_path, f) })
@@ -51,6 +51,10 @@ def manifest_path(apk_file_path)
51
51
  "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.res"
52
52
  end
53
53
 
54
+ def framework_path(apk_file_path)
55
+ "test_servers/apktool-#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}"
56
+ end
57
+
54
58
 
55
59
  def build_test_server_if_needed(app_path)
56
60
  unless File.exist?(test_server_path(app_path))
@@ -117,6 +117,18 @@ module Operations
117
117
  default_device.set_gps_coordinates(latitude, longitude)
118
118
  end
119
119
 
120
+ def get_preferences(name)
121
+ default_device.get_preferences(name)
122
+ end
123
+
124
+ def set_preferences(name, hash)
125
+ default_device.set_preferences(name, hash)
126
+ end
127
+
128
+ def clear_preferences(name)
129
+ default_device.clear_preferences(name)
130
+ end
131
+
120
132
  def query(uiquery, *args)
121
133
  converted_args = []
122
134
  args.each do |arg|
@@ -178,8 +190,8 @@ module Operations
178
190
  def initialize(cucumber_world, serial, server_port, app_path, test_server_path, test_server_port = 7102)
179
191
 
180
192
  @cucumber_world = cucumber_world
181
- @serial = serial
182
- @server_port = server_port
193
+ @serial = serial || default_serial
194
+ @server_port = server_port || default_server_port
183
195
  @app_path = app_path
184
196
  @test_server_path = test_server_path
185
197
  @test_server_port = test_server_port
@@ -224,7 +236,7 @@ module Operations
224
236
  unless succeeded
225
237
  ::Cucumber.wants_to_quit = true
226
238
  raise "#{pn} did not get updated. Aborting!"
227
- end
239
+ end
228
240
  end
229
241
 
230
242
  def uninstall_app(package_name)
@@ -400,10 +412,6 @@ module Operations
400
412
  end
401
413
  end
402
414
 
403
- def serial
404
- @serial || default_serial
405
- end
406
-
407
415
  def default_serial
408
416
  devices = connected_devices
409
417
  log "connected_devices: #{devices}"
@@ -412,11 +420,36 @@ module Operations
412
420
  devices.first
413
421
  end
414
422
 
423
+ def default_server_port
424
+ require 'yaml'
425
+ File.open(File.expand_path(server_port_configuration), File::RDWR|File::CREAT) do |f|
426
+ f.flock(File::LOCK_EX)
427
+ state = YAML::load(f) || {}
428
+ ports = state['server_ports'] ||= {}
429
+ return ports[serial] if ports.has_key?(serial)
430
+
431
+ port = 34777
432
+ port += 1 while ports.has_value?(port)
433
+ ports[serial] = port
434
+
435
+ f.rewind
436
+ f.write(YAML::dump(state))
437
+ f.truncate(f.pos)
438
+
439
+ log "Persistently allocated port #{port} to #{serial}"
440
+ return port
441
+ end
442
+ end
443
+
444
+ def server_port_configuration
445
+ File.expand_path(ENV['CALABASH_SERVER_PORTS'] || "~/.calabash.yaml")
446
+ end
447
+
415
448
  def connected_devices
416
449
  lines = `#{adb} devices`.split("\n")
417
450
  lines.shift
418
451
  lines.collect { |l| l.split("\t").first}
419
- end
452
+ end
420
453
 
421
454
  def wake_up
422
455
  wake_up_cmd = "#{adb_command} shell am start -a android.intent.action.MAIN -n #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.WakeUp"
@@ -551,9 +584,116 @@ module Operations
551
584
  def set_gps_coordinates(latitude, longitude)
552
585
  perform_action('set_gps_coordinates', latitude, longitude)
553
586
  end
554
- end
555
587
 
588
+ def get_preferences(name)
589
+
590
+ log "Get preferences: #{name}, app running? #{app_running?}"
591
+ preferences = {}
592
+
593
+ if app_running?
594
+ json = perform_action('get_preferences', name);
595
+ else
596
+
597
+ logcat_id = get_logcat_id()
598
+ cmd = "#{adb_command} shell am instrument -e logcat #{logcat_id} -e name \"#{name}\" #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.GetPreferences"
599
+
600
+ raise "Could not get preferences" unless system(cmd)
601
+
602
+ logcat_cmd = get_logcat_cmd(logcat_id)
603
+ logcat_output = `#{logcat_cmd}`
604
+
605
+ json = get_json_from_logcat(logcat_output)
606
+
607
+ raise "Could not get preferences" unless json != nil and json["success"]
608
+ end
609
+
610
+ # at this point we have valid json, coming from an action
611
+ # or instrumentation, but we don't care, just parse
612
+ if json["bonusInformation"].length > 0
613
+ json["bonusInformation"].each do |item|
614
+ json_item = JSON.parse(item)
615
+ preferences[json_item["key"]] = json_item["value"]
616
+ end
617
+ end
618
+
619
+ preferences
620
+ end
621
+
622
+ def set_preferences(name, hash)
556
623
 
624
+ log "Set preferences: #{name}, #{hash}, app running? #{app_running?}"
625
+
626
+ if app_running?
627
+ perform_action('set_preferences', name, hash);
628
+ else
629
+
630
+ params = hash.map {|k,v| "-e \"#{k}\" \"#{v}\""}.join(" ")
631
+
632
+ logcat_id = get_logcat_id()
633
+ cmd = "#{adb_command} shell am instrument -e logcat #{logcat_id} -e name \"#{name}\" #{params} #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.SetPreferences"
634
+
635
+ raise "Could not set preferences" unless system(cmd)
636
+
637
+ logcat_cmd = get_logcat_cmd(logcat_id)
638
+ logcat_output = `#{logcat_cmd}`
639
+
640
+ json = get_json_from_logcat(logcat_output)
641
+
642
+ raise "Could not set preferences" unless json != nil and json["success"]
643
+ end
644
+ end
645
+
646
+ def clear_preferences(name)
647
+
648
+ log "Clear preferences: #{name}, app running? #{app_running?}"
649
+
650
+ if app_running?
651
+ perform_action('clear_preferences', name);
652
+ else
653
+
654
+ logcat_id = get_logcat_id()
655
+ cmd = "#{adb_command} shell am instrument -e logcat #{logcat_id} -e name \"#{name}\" #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.ClearPreferences"
656
+ raise "Could not clear preferences" unless system(cmd)
657
+
658
+ logcat_cmd = get_logcat_cmd(logcat_id)
659
+ logcat_output = `#{logcat_cmd}`
660
+
661
+ json = get_json_from_logcat(logcat_output)
662
+
663
+ raise "Could not clear preferences" unless json != nil and json["success"]
664
+ end
665
+ end
666
+
667
+ def get_json_from_logcat(logcat_output)
668
+
669
+ logcat_output.split(/\r?\n/).each do |line|
670
+ begin
671
+ json = JSON.parse(line)
672
+ return json
673
+ rescue
674
+ # nothing to do here, just discarding logcat rubbish
675
+ end
676
+ end
677
+
678
+ return nil
679
+ end
680
+
681
+ def get_logcat_id()
682
+ # we need a unique logcat tag so we can later
683
+ # query the logcat output and filter out everything
684
+ # but what we are interested in
685
+
686
+ random = (0..10000).to_a.sample
687
+ "#{Time.now.strftime("%s")}_#{random}"
688
+ end
689
+
690
+ def get_logcat_cmd(tag)
691
+ # returns raw logcat output for our tag
692
+ # filtering out everthing else
693
+
694
+ "#{adb_command} logcat -d -v raw #{tag}:* *:S"
695
+ end
696
+ end
557
697
 
558
698
  def label(uiquery)
559
699
  ni
@@ -1,5 +1,5 @@
1
1
  module Calabash
2
2
  module Android
3
- VERSION = "0.4.7.pre9"
3
+ VERSION = "0.4.7.pre10"
4
4
  end
5
5
  end
@@ -19,6 +19,9 @@
19
19
  <uses-sdk android:minSdkVersion="4" />
20
20
  <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.CalabashInstrumentationTestRunner" />
21
21
  <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.ClearAppData" />
22
+ <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.ClearPreferences" />
23
+ <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.SetPreferences" />
24
+ <instrumentation android:targetPackage="#targetPackage#" android:name="sh.calaba.instrumentationbackend.GetPreferences" />
22
25
 
23
26
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
24
27
  <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
@@ -4,8 +4,8 @@
4
4
  <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
5
5
  <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
6
6
  <classpathentry kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
7
- <classpathentry kind="lib" path="libs/robotium-solo-4.1.jar"/>
8
7
  <classpathentry kind="src" path="src"/>
9
8
  <classpathentry kind="src" path="gen"/>
9
+ <classpathentry kind="lib" path="libs/robotium-solo-4.2.jar"/>
10
10
  <classpathentry kind="output" path="bin/classes"/>
11
11
  </classpath>
@@ -0,0 +1,36 @@
1
+ package sh.calaba.instrumentationbackend;
2
+
3
+ import sh.calaba.instrumentationbackend.actions.preferences.PreferencesUtils;
4
+ import android.content.SharedPreferences;
5
+ import android.os.Bundle;
6
+ import android.test.InstrumentationTestRunner;
7
+ import android.util.Log;
8
+
9
+ /**
10
+ * Allows clearing SharedPreferences.
11
+ *
12
+ * See Ruby API docs for more info:
13
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
14
+ *
15
+ * @author Juan Delgado (juan@ustwo.co.uk)
16
+ */
17
+ public class ClearPreferences extends InstrumentationTestRunner {
18
+
19
+ @Override
20
+ public void onCreate(Bundle arguments) {
21
+
22
+ SharedPreferences preferences = null;
23
+
24
+ try{
25
+ preferences = PreferencesUtils.getPreferencesFromBundle(arguments, getTargetContext());
26
+ } catch(Exception e){
27
+ e.printStackTrace();
28
+ return;
29
+ }
30
+
31
+ preferences.edit().clear().commit();
32
+
33
+ String logcat = arguments.getString(PreferencesUtils.BUNDLE_LOGCAT_ID);
34
+ Log.d(logcat, PreferencesUtils.resultToJson(Result.successResult()));
35
+ }
36
+ }
@@ -0,0 +1,37 @@
1
+ package sh.calaba.instrumentationbackend;
2
+
3
+ import sh.calaba.instrumentationbackend.actions.preferences.PreferencesUtils;
4
+ import android.content.SharedPreferences;
5
+ import android.os.Bundle;
6
+ import android.test.InstrumentationTestRunner;
7
+ import android.util.Log;
8
+
9
+ /**
10
+ * Allows reading of SharedPreferences.
11
+ *
12
+ * See Ruby API docs for more info:
13
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
14
+ *
15
+ * @author Juan Delgado (juan@ustwo.co.uk)
16
+ */
17
+ public class GetPreferences extends InstrumentationTestRunner {
18
+
19
+ @Override
20
+ public void onCreate(Bundle arguments) {
21
+
22
+ SharedPreferences preferences = null;
23
+
24
+ try{
25
+ preferences = PreferencesUtils.getPreferencesFromBundle(arguments, getTargetContext());
26
+ } catch(Exception e){
27
+ e.printStackTrace();
28
+ return;
29
+ }
30
+
31
+ Result result = Result.successResult();
32
+ PreferencesUtils.addPreferencesToResult(preferences, result);
33
+
34
+ String logcat = arguments.getString(PreferencesUtils.BUNDLE_LOGCAT_ID);
35
+ Log.d(logcat, PreferencesUtils.resultToJson(result));
36
+ }
37
+ }
@@ -0,0 +1,56 @@
1
+ package sh.calaba.instrumentationbackend;
2
+
3
+ import java.util.Set;
4
+
5
+ import sh.calaba.instrumentationbackend.actions.preferences.PreferencesUtils;
6
+ import android.content.SharedPreferences;
7
+ import android.os.Bundle;
8
+ import android.test.InstrumentationTestRunner;
9
+ import android.util.Log;
10
+
11
+ /**
12
+ * Allows writing of SharedPreferences.
13
+ *
14
+ * See Ruby API docs for more info:
15
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
16
+ *
17
+ * @author Juan Delgado (juan@ustwo.co.uk)
18
+ */
19
+ public class SetPreferences extends InstrumentationTestRunner {
20
+
21
+ @Override
22
+ public void onCreate(Bundle arguments) {
23
+
24
+ SharedPreferences preferences = null;
25
+
26
+ try{
27
+ preferences = PreferencesUtils.getPreferencesFromBundle(arguments, getTargetContext());
28
+ } catch(Exception e){
29
+ e.printStackTrace();
30
+ return;
31
+ }
32
+
33
+ Set<String> keys = arguments.keySet();
34
+
35
+ String[] parserdArgs = new String[keys.size() * 2];
36
+
37
+ int added = 0;
38
+ for (String key : keys) {
39
+
40
+ if(key.equals(PreferencesUtils.BUNDLE_LOGCAT_ID) || key.equals(PreferencesUtils.BUNDLE_NAME)){
41
+ continue;
42
+ }
43
+
44
+ parserdArgs[added++] = key;
45
+ parserdArgs[added++] = arguments.get(key).toString();
46
+ }
47
+
48
+ SharedPreferences.Editor editor = preferences.edit();
49
+
50
+ PreferencesUtils.setPreferences(editor, parserdArgs);
51
+ editor.commit();
52
+
53
+ String logcat = arguments.getString(PreferencesUtils.BUNDLE_LOGCAT_ID);
54
+ Log.d(logcat, PreferencesUtils.resultToJson(Result.successResult()));
55
+ }
56
+ }
@@ -11,6 +11,7 @@ import java.util.Date;
11
11
  import java.util.HashMap;
12
12
  import java.util.Map;
13
13
 
14
+ import android.app.Activity;
14
15
  import android.content.Context;
15
16
  import android.content.res.Resources.NotFoundException;
16
17
  import android.graphics.drawable.Drawable;
@@ -53,19 +54,42 @@ public class TestHelpers {
53
54
  if (!expectedViewType.isInstance(theView)) {
54
55
  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()));
55
56
  }
56
-
57
+
57
58
  return (ViewType) theView;
58
59
  }
59
60
 
60
61
  public static View getViewById(String resName) {
61
- int id = InstrumentationBackend.solo.getCurrentActivity().getResources().getIdentifier(resName, "id", InstrumentationBackend.solo.getCurrentActivity().getPackageName());
62
+ int id = getIdFromString(resName);
62
63
  if (id == 0) {
63
64
  return null;
64
65
  }
65
66
 
66
67
  return InstrumentationBackend.solo.getView(id);
67
68
  }
68
-
69
+
70
+ /**
71
+ * Converts a string identifier name to the corresponding {@code R.id.*}
72
+ * (Integer) resource identifier.
73
+ *
74
+ * If the string appears to be a number, it will be converted to an
75
+ * integer and assumed to be an existing identifier.
76
+ *
77
+ * @param resName the resource identifier name
78
+ * @return the corresponding {@code R.id.[resName]} identifier
79
+ */
80
+ public static int getIdFromString(String resName) {
81
+ try
82
+ {
83
+ // Check if th string is just a direct number (unlikely)
84
+ return Integer.parseInt(resName);
85
+ } catch (NumberFormatException nfe) {
86
+ // Assume this is an "R.id.<name>" string.
87
+ }
88
+
89
+ final Activity activity = InstrumentationBackend.solo.getCurrentActivity();
90
+ return activity.getResources().getIdentifier(resName, "id", activity.getPackageName());
91
+ }
92
+
69
93
  public static Drawable getDrawableById(String resName) {
70
94
  int id;
71
95
  try {
@@ -117,7 +141,7 @@ public class TestHelpers {
117
141
  public static void wait(int durationInSeconds) {
118
142
  wait(new Double(durationInSeconds));
119
143
  }
120
-
144
+
121
145
 
122
146
  public static void wait(double durationInSeconds) {
123
147
  try {
@@ -0,0 +1,37 @@
1
+ package sh.calaba.instrumentationbackend.actions.preferences;
2
+
3
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
4
+ import sh.calaba.instrumentationbackend.Result;
5
+ import sh.calaba.instrumentationbackend.actions.Action;
6
+ import android.content.SharedPreferences;
7
+
8
+ /**
9
+ * Allows clearing SharedPreferences.
10
+ *
11
+ * See Ruby API docs for more info:
12
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
13
+ *
14
+ * @author Juan Delgado (juan@ustwo.co.uk)
15
+ */
16
+ public class ClearPreferences implements Action {
17
+
18
+ @Override
19
+ public Result execute(String... args) {
20
+
21
+ try{
22
+
23
+ SharedPreferences preferences = PreferencesUtils.getPreferencesFromArgs(args, InstrumentationBackend.instrumentation.getTargetContext());
24
+ preferences.edit().clear().commit();
25
+
26
+ return Result.successResult();
27
+
28
+ } catch(Exception e) {
29
+ return Result.fromThrowable(e);
30
+ }
31
+ }
32
+
33
+ @Override
34
+ public String key() {
35
+ return "clear_preferences";
36
+ }
37
+ }
@@ -0,0 +1,39 @@
1
+ package sh.calaba.instrumentationbackend.actions.preferences;
2
+
3
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
4
+ import sh.calaba.instrumentationbackend.Result;
5
+ import sh.calaba.instrumentationbackend.actions.Action;
6
+ import android.content.SharedPreferences;
7
+
8
+ /**
9
+ * Allows reading of SharedPreferences.
10
+ *
11
+ * See Ruby API docs for more info:
12
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
13
+ *
14
+ * @author Juan Delgado (juan@ustwo.co.uk)
15
+ */
16
+ public class GetPreferences implements Action {
17
+
18
+ @Override
19
+ public Result execute(String... args) {
20
+
21
+ SharedPreferences preferences = null;
22
+
23
+ try{
24
+ preferences = PreferencesUtils.getPreferencesFromArgs(args, InstrumentationBackend.instrumentation.getTargetContext());
25
+ } catch(Exception e){
26
+ return Result.fromThrowable(e);
27
+ }
28
+
29
+ Result result = Result.successResult();
30
+ PreferencesUtils.addPreferencesToResult(preferences, result);
31
+
32
+ return result;
33
+ }
34
+
35
+ @Override
36
+ public String key() {
37
+ return "get_preferences";
38
+ }
39
+ }
@@ -0,0 +1,229 @@
1
+ package sh.calaba.instrumentationbackend.actions.preferences;
2
+
3
+ import java.util.Map;
4
+ import java.util.Map.Entry;
5
+
6
+ import sh.calaba.instrumentationbackend.Result;
7
+ import sh.calaba.org.codehaus.jackson.map.DeserializationConfig.Feature;
8
+ import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
9
+ import android.content.Context;
10
+ import android.content.SharedPreferences;
11
+ import android.content.SharedPreferences.Editor;
12
+ import android.os.Bundle;
13
+
14
+ /**
15
+ * Utility methods for SharedPreferences actions and instrumentation.
16
+ *
17
+ * See Ruby API docs for more info:
18
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
19
+ *
20
+ * @author Juan Delgado (juan@ustwo.co.uk)
21
+ */
22
+ public class PreferencesUtils {
23
+
24
+ private static final String MISSING_CONTEXT = "Missing context";
25
+ private static final String MISSING_BUNDLE = "Missing bundle";
26
+ private static final String MISSING_NAME = "Missing SharedPreferences name";
27
+ private static final String MISSING_LOGCAT_ID = "Missing LogCat ID";
28
+ private static final String MISSING_PREFERENCES = "Missing preferences";
29
+ private static final String MISSING_RESULT = "Missing result";
30
+ private static final String MISSING_EDITOR = "Missing editor";
31
+ private static final String MISSING_VALUES = "Missing values";
32
+
33
+ public static final String BUNDLE_NAME = "name";
34
+ public static final String BUNDLE_LOGCAT_ID = "logcat";
35
+
36
+ private final static ObjectMapper mapper = createJsonMapper();
37
+
38
+ /**
39
+ * Returns a SharedPreferences object based on arguments and context.
40
+ *
41
+ * @param args First item on the array is the name expected to retrieve the SharedPreferences.
42
+ * @param context Typically the context of the tested application.
43
+ * @return A SharedPreferences instance.
44
+ *
45
+ * @throws IllegalArgumentException if missing args, name or context.
46
+ */
47
+ public static SharedPreferences getPreferencesFromArgs(String[] args, Context context){
48
+
49
+ if(args == null){
50
+ throw new IllegalArgumentException(MISSING_NAME);
51
+ }
52
+
53
+ if(context == null){
54
+ throw new IllegalArgumentException(MISSING_CONTEXT);
55
+ }
56
+
57
+ String name = args[0];
58
+
59
+ if(name == null){
60
+ throw new IllegalArgumentException(MISSING_NAME);
61
+ }
62
+
63
+ return context.getSharedPreferences(name, Context.MODE_PRIVATE);
64
+ }
65
+
66
+ /**
67
+ * Returns a SharedPreferences object based on arguments and context.
68
+ *
69
+ * @param bundle Expected to contain "name" and "logcat" properties.
70
+ * @param context Typically the context of the tested application.
71
+ * @return A SharedPreferences instance.
72
+ *
73
+ * @throws IllegalArgumentException if missing bundle, name, logcat or context.
74
+ */
75
+ public static SharedPreferences getPreferencesFromBundle(Bundle bundle, Context context){
76
+
77
+ if(bundle == null){
78
+ throw new IllegalArgumentException(MISSING_BUNDLE);
79
+ }
80
+
81
+ if(context == null){
82
+ throw new IllegalArgumentException(MISSING_CONTEXT);
83
+ }
84
+
85
+ String logcat = bundle.getString(PreferencesUtils.BUNDLE_LOGCAT_ID);
86
+ String name = bundle.getString(PreferencesUtils.BUNDLE_NAME);
87
+
88
+ if(logcat == null){
89
+ throw new IllegalArgumentException(MISSING_LOGCAT_ID);
90
+ }
91
+
92
+ if(name == null){
93
+ throw new IllegalArgumentException(MISSING_NAME);
94
+ }
95
+
96
+ return context.getSharedPreferences(name, Context.MODE_PRIVATE);
97
+ }
98
+
99
+ /**
100
+ * Iterates over the values stored in SharedPrefereces and adds them as JSON
101
+ * key:value pairs to the bonusInformation of a result.
102
+ *
103
+ * @param preferences SharedPreferences object we want to add.
104
+ * @param result The Result object we want to add to.
105
+ *
106
+ * @throws IllegalArgumentException if missing preferences or result.
107
+ */
108
+ public static void addPreferencesToResult(SharedPreferences preferences, Result result){
109
+
110
+ if(preferences == null){
111
+ throw new IllegalArgumentException(MISSING_PREFERENCES);
112
+ }
113
+
114
+ if(result == null){
115
+ throw new IllegalArgumentException(MISSING_RESULT);
116
+ }
117
+
118
+ Map<String, ?> map = preferences.getAll();
119
+
120
+ for(Entry<String, ?> entry : map.entrySet()){
121
+
122
+ StringBuilder json = new StringBuilder();
123
+ String value = null;
124
+
125
+ json.append("{");
126
+
127
+ if(entry.getValue() instanceof Integer ||
128
+ entry.getValue() instanceof Float ||
129
+ entry.getValue() instanceof Boolean){
130
+
131
+ value = String.valueOf(entry.getValue());
132
+
133
+ } else {
134
+ value = "\"" + entry.getValue() + "\"";
135
+ }
136
+
137
+ json.append("\"key\": \"" + entry.getKey() + "\", ");
138
+ json.append("\"value\": " + value);
139
+ json.append("}");
140
+
141
+ result.addBonusInformation(json.toString());
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Adds values to a SharedPreferences Editor object. Key,value
147
+ * pairs are expected to come in the values array one after another
148
+ * such as [key1, value1, key2, value2], etc. This is a side effect
149
+ * of the Ruby to Java communication through ADB.
150
+ *
151
+ * @param editor Editor to which add the values to.
152
+ * @param values Array of key/value pairs.
153
+ *
154
+ * @throws IllegalArgumentException if missing editor or values.
155
+ */
156
+ public static void setPreferences(Editor editor, String[] values){
157
+
158
+ if(editor == null){
159
+ throw new IllegalArgumentException(MISSING_EDITOR);
160
+ }
161
+
162
+ if(values == null){
163
+ throw new IllegalArgumentException(MISSING_VALUES);
164
+ }
165
+
166
+ // we expect key/value pairs passed one after another such as:
167
+ // [key1 value1 key2 value2], etc
168
+ // So we go through them with a 2 step loop
169
+ int totalParsedArgs = values.length;
170
+ for(int i = 0; i <totalParsedArgs; i += 2){
171
+
172
+ if(values[i] == null){
173
+ break;
174
+ }
175
+
176
+ String key = values[i];
177
+ String value = values[i+1];
178
+
179
+ try {
180
+
181
+ int x = Integer.parseInt(value);
182
+ editor.putInt(key, x);
183
+
184
+ } catch (NumberFormatException e){
185
+
186
+ try {
187
+
188
+ float y = Float.parseFloat(value);
189
+ editor.putFloat(key, y);
190
+
191
+ } catch (NumberFormatException e1) {
192
+
193
+ if(value.equals("true") || value.equals("false")){
194
+ editor.putBoolean(key, Boolean.parseBoolean(value));
195
+ } else {
196
+ editor.putString(key, value);
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Formats a Result object as a JSON string.
205
+ *
206
+ * @param result The result that has to be formatted.
207
+ * @return The result formatted as a JSON string
208
+ *
209
+ * @throws IllegalArgumentException if missing result.
210
+ */
211
+ public static String resultToJson(Result result) {
212
+
213
+ if(result == null){
214
+ throw new IllegalArgumentException(MISSING_RESULT);
215
+ }
216
+
217
+ try {
218
+ return mapper.writeValueAsString(result);
219
+ } catch (Exception e) {
220
+ throw new RuntimeException(e);
221
+ }
222
+ }
223
+
224
+ private static ObjectMapper createJsonMapper() {
225
+ ObjectMapper mapper = new ObjectMapper();
226
+ mapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
227
+ return mapper;
228
+ }
229
+ }
@@ -0,0 +1,56 @@
1
+ package sh.calaba.instrumentationbackend.actions.preferences;
2
+
3
+ import sh.calaba.instrumentationbackend.InstrumentationBackend;
4
+ import sh.calaba.instrumentationbackend.Result;
5
+ import sh.calaba.instrumentationbackend.actions.Action;
6
+ import android.content.SharedPreferences;
7
+
8
+ /**
9
+ * Allows writing of SharedPreferences.
10
+ *
11
+ * See Ruby API docs for more info:
12
+ * https://github.com/calabash/calabash-android/blob/master/documentation/ruby_api.md
13
+ *
14
+ * @author Juan Delgado (juan@ustwo.co.uk)
15
+ */
16
+ public class SetPreferences implements Action {
17
+
18
+ @Override
19
+ public Result execute(String... args) {
20
+
21
+ SharedPreferences preferences = null;
22
+
23
+ try{
24
+ preferences = PreferencesUtils.getPreferencesFromArgs(args, InstrumentationBackend.instrumentation.getTargetContext());
25
+ } catch(Exception e){
26
+ return Result.fromThrowable(e);
27
+ }
28
+
29
+ String[] parserdArgs = new String[args.length];
30
+
31
+ int totalArgs = args.length;
32
+ int added = 0;
33
+ for(int i = 0; i <totalArgs; i++){
34
+
35
+ String arg = args[i];
36
+
37
+ // ignoring SharedPreferences name and weird chars
38
+ if(arg.equals(args[0]) || arg.equals("{") || arg.equals("}")){
39
+ continue;
40
+ }
41
+
42
+ parserdArgs[added++] = arg;
43
+ }
44
+
45
+ SharedPreferences.Editor editor = preferences.edit();
46
+ PreferencesUtils.setPreferences(editor, parserdArgs);
47
+ editor.commit();
48
+
49
+ return Result.successResult();
50
+ }
51
+
52
+ @Override
53
+ public String key() {
54
+ return "set_preferences";
55
+ }
56
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calabash-android
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7.pre9
4
+ version: 0.4.7.pre10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Maturana Larsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-27 00:00:00.000000000 Z
11
+ date: 2013-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -190,7 +190,7 @@ files:
190
190
  - test-server/instrumentation-backend/build-libs/antlr-3.4-complete.jar
191
191
  - test-server/instrumentation-backend/build-libs/junit.jar
192
192
  - test-server/instrumentation-backend/build.xml
193
- - test-server/instrumentation-backend/libs/robotium-solo-4.1.jar
193
+ - test-server/instrumentation-backend/libs/robotium-solo-4.2.jar
194
194
  - test-server/instrumentation-backend/project.properties
195
195
  - test-server/instrumentation-backend/res/drawable-hdpi/ic_launcher.png
196
196
  - test-server/instrumentation-backend/res/drawable-ldpi/ic_launcher.png
@@ -287,10 +287,13 @@ files:
287
287
  - test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeWizard.java
288
288
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/CalabashInstrumentationTestRunner.java
289
289
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearAppData.java
290
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearPreferences.java
290
291
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Command.java
291
292
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/FranklyResult.java
293
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/GetPreferences.java
292
294
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java
293
295
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java
296
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/SetPreferences.java
294
297
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/TestHelpers.java
295
298
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/WakeUp.java
296
299
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/Action.java
@@ -337,6 +340,10 @@ files:
337
340
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/SetMapZoom.java
338
341
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/TapAwayFromMarkers.java
339
342
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/map/TapMapMarker.java
343
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/ClearPreferences.java
344
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/GetPreferences.java
345
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/PreferencesUtils.java
346
+ - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/preferences/SetPreferences.java
340
347
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/scrolling/ScrollDown.java
341
348
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/scrolling/ScrollUp.java
342
349
  - test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/search/EnterQueryByIndex.java
@@ -861,3 +868,4 @@ signing_key:
861
868
  specification_version: 4
862
869
  summary: Client for calabash-android for automated functional testing on Android
863
870
  test_files: []
871
+ has_rdoc: