calabash-android 0.4.7.pre9 → 0.4.7.pre10

Sign up to get free protection for your applications and to get access to all the features.
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: