calabash 1.2.1 → 1.9.9.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.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +39 -0
  3. data/LICENSE +204 -21
  4. data/README.md +36 -6
  5. data/VERSIONING.md +16 -0
  6. data/bin/calabash +95 -0
  7. data/lib/calabash.rb +185 -1
  8. data/lib/calabash/android.rb +64 -0
  9. data/lib/calabash/android/adb.rb +277 -0
  10. data/lib/calabash/android/application.rb +110 -0
  11. data/lib/calabash/android/build.rb +12 -0
  12. data/lib/calabash/android/build/application.rb +13 -0
  13. data/lib/calabash/android/build/build_error.rb +11 -0
  14. data/lib/calabash/android/build/builder.rb +119 -0
  15. data/lib/calabash/android/build/java_keystore.rb +177 -0
  16. data/lib/calabash/android/build/resigner.rb +56 -0
  17. data/lib/calabash/android/build/test_server.rb +27 -0
  18. data/lib/calabash/android/console_helpers.rb +44 -0
  19. data/lib/calabash/android/cucumber.rb +3 -0
  20. data/lib/calabash/android/device.rb +965 -0
  21. data/lib/calabash/android/environment.rb +470 -0
  22. data/lib/calabash/android/gestures.rb +369 -0
  23. data/lib/calabash/android/interactions.rb +45 -0
  24. data/lib/calabash/android/lib/.irbrc +55 -0
  25. data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
  26. data/lib/calabash/android/lib/TestServer.apk +0 -0
  27. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
  28. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
  29. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
  30. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
  31. data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
  32. data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
  33. data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
  34. data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
  35. data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
  36. data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
  37. data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
  38. data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
  39. data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
  40. data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
  41. data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
  42. data/lib/calabash/android/life_cycle.rb +37 -0
  43. data/lib/calabash/android/orientation.rb +30 -0
  44. data/lib/calabash/android/physical_buttons.rb +39 -0
  45. data/lib/calabash/android/screenshot.rb +9 -0
  46. data/lib/calabash/android/scroll.rb +5 -0
  47. data/lib/calabash/android/server.rb +10 -0
  48. data/lib/calabash/android/text.rb +54 -0
  49. data/lib/calabash/application.rb +74 -0
  50. data/lib/calabash/cli.rb +12 -0
  51. data/lib/calabash/cli/build.rb +33 -0
  52. data/lib/calabash/cli/console.rb +90 -0
  53. data/lib/calabash/cli/generate.rb +110 -0
  54. data/lib/calabash/cli/helpers.rb +130 -0
  55. data/lib/calabash/cli/resign.rb +33 -0
  56. data/lib/calabash/cli/run.rb +99 -0
  57. data/lib/calabash/cli/setup_keystore.rb +39 -0
  58. data/lib/calabash/color.rb +32 -0
  59. data/lib/calabash/console_helpers.rb +90 -0
  60. data/lib/calabash/defaults.rb +56 -0
  61. data/lib/calabash/device.rb +401 -0
  62. data/lib/calabash/environment.rb +75 -0
  63. data/lib/calabash/gestures.rb +384 -0
  64. data/lib/calabash/http.rb +8 -0
  65. data/lib/calabash/http/error.rb +15 -0
  66. data/lib/calabash/http/request.rb +42 -0
  67. data/lib/calabash/http/retriable_client.rb +156 -0
  68. data/lib/calabash/interactions.rb +105 -0
  69. data/lib/calabash/ios.rb +37 -0
  70. data/lib/calabash/ios/application.rb +119 -0
  71. data/lib/calabash/ios/conditions.rb +79 -0
  72. data/lib/calabash/ios/console_helpers.rb +72 -0
  73. data/lib/calabash/ios/device.rb +24 -0
  74. data/lib/calabash/ios/device/device_implementation.rb +779 -0
  75. data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
  76. data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
  77. data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
  78. data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
  79. data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
  80. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
  81. data/lib/calabash/ios/device/routes/error.rb +8 -0
  82. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
  83. data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
  84. data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
  85. data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
  86. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
  87. data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
  88. data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
  89. data/lib/calabash/ios/device/text_mixin.rb +19 -0
  90. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
  91. data/lib/calabash/ios/device/uia_mixin.rb +12 -0
  92. data/lib/calabash/ios/environment.rb +41 -0
  93. data/lib/calabash/ios/interactions.rb +10 -0
  94. data/lib/calabash/ios/lib/.irbrc +55 -0
  95. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
  96. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
  97. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
  98. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
  99. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
  100. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
  101. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
  102. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
  103. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
  104. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
  105. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
  106. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
  107. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
  108. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
  109. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
  110. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
  111. data/lib/calabash/ios/orientation.rb +117 -0
  112. data/lib/calabash/ios/scroll.rb +504 -0
  113. data/lib/calabash/ios/server.rb +73 -0
  114. data/lib/calabash/ios/text.rb +248 -0
  115. data/lib/calabash/ios/uia.rb +24 -0
  116. data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
  117. data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
  118. data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
  119. data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
  120. data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
  121. data/lib/calabash/life_cycle.rb +111 -0
  122. data/lib/calabash/location.rb +51 -0
  123. data/lib/calabash/logger.rb +87 -0
  124. data/lib/calabash/orientation.rb +84 -0
  125. data/lib/calabash/page.rb +35 -0
  126. data/lib/calabash/patch.rb +14 -0
  127. data/lib/calabash/patch/array.rb +16 -0
  128. data/lib/calabash/patch/run_loop.rb +90 -0
  129. data/lib/calabash/query.rb +160 -0
  130. data/lib/calabash/query_result.rb +85 -0
  131. data/lib/calabash/screenshot.rb +89 -0
  132. data/lib/calabash/server.rb +16 -0
  133. data/lib/calabash/text.rb +76 -0
  134. data/lib/calabash/utility.rb +58 -0
  135. data/lib/calabash/version.rb +3 -1
  136. data/lib/calabash/wait.rb +474 -0
  137. metadata +462 -24
@@ -0,0 +1,12 @@
1
+ module Calabash
2
+ module Android
3
+ module Build
4
+ require 'calabash/android/build/application'
5
+ require 'calabash/android/build/build_error'
6
+ require 'calabash/android/build/builder'
7
+ require 'calabash/android/build/java_keystore'
8
+ require 'calabash/android/build/resigner'
9
+ require 'calabash/android/build/test_server'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Calabash
2
+ module Android
3
+ # @!visibility private
4
+ module Build
5
+ # @!visibility private
6
+ class Application < Android::Application
7
+ def initialize(application_path, options = {})
8
+ super(application_path, nil, options)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Calabash
2
+ module Android
3
+ # @!visibility private
4
+ module Build
5
+ # @!visibility private
6
+ class BuildError < RuntimeError
7
+
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,119 @@
1
+ require 'zip'
2
+
3
+ module Calabash
4
+ module Android
5
+ module Build
6
+ # @!visibility private
7
+ class Builder
8
+ def initialize(application_path, options={})
9
+ @application_path = application_path
10
+
11
+ if options[:logger]
12
+ @logger = options[:logger] || Logger.new
13
+ else
14
+ @logger = Logger.new
15
+ @logger.default_log_level = :info
16
+ end
17
+ end
18
+
19
+ def build
20
+ apk_fingerprint = fingerprint_from_apk
21
+ @logger.log "#{@application_path} was signed with a certificate with fingerprint #{apk_fingerprint}", :debug
22
+
23
+ keystores = JavaKeystore.get_keystores
24
+ if keystores.empty?
25
+ @logger.log "No default keystores found."
26
+ @logger.log "Please create one or run calabash setup-keystore to configure calabash to use an existing keystore."
27
+
28
+ raise BuildError.new('No keystores found')
29
+ end
30
+ keystore = keystores.find { |k| k.fingerprint == apk_fingerprint}
31
+
32
+ unless keystore
33
+ @logger.log "#{@application_path} is not signed with any of the available keystores."
34
+ @logger.log "Tried the following keystores:"
35
+ keystores.each do |k|
36
+ @logger.log k.location
37
+ end
38
+ @logger.log ""
39
+ @logger.log "You can resign the app with #{keystores.first.location} by running:
40
+ calabash resign #{@application_path}"
41
+
42
+ @logger.log ""
43
+ @logger.log "Notice that resigning an app might break some functionality."
44
+ @logger.log "Getting a copy of the certificate used when the app was build will in general be more reliable."
45
+
46
+ raise BuildError.new("#{@application_path} is not signed with any of the available keystores")
47
+ end
48
+
49
+ application = Calabash::Application.from_path(@application_path)
50
+
51
+ test_server_file_name = TestServer.new(@application_path).path
52
+ FileUtils.mkdir_p File.dirname(test_server_file_name) unless File.exist? File.dirname(test_server_file_name)
53
+
54
+ Dir.mktmpdir do |workspace_dir|
55
+ Dir.chdir(workspace_dir) do
56
+ FileUtils.cp(UNSIGNED_TEST_SERVER_APK, "TestServer.apk")
57
+ FileUtils.cp(ANDROID_MANIFEST_PATH, "AndroidManifest.xml")
58
+
59
+ contents = File.read('AndroidManifest.xml')
60
+ contents.gsub!(/#targetPackage#/, application.identifier)
61
+ contents.gsub!(/#testPackage#/, "#{application.identifier}.test")
62
+
63
+ File.open('AndroidManifest.xml_tmp', 'w') {|file| file.write(contents)}
64
+ FileUtils.mv('AndroidManifest.xml_tmp', 'AndroidManifest.xml')
65
+
66
+ unless system %Q{"#{Environment.aapt_path}" package -M AndroidManifest.xml -I "#{Environment.android_jar_path}" -F dummy.apk}
67
+ raise "Could not create dummy.apk"
68
+ end
69
+
70
+ Zip::File.new("dummy.apk").extract("AndroidManifest.xml","customAndroidManifest.xml")
71
+ Zip::File.open("TestServer.apk") do |zip_file|
72
+ zip_file.add("AndroidManifest.xml", "customAndroidManifest.xml")
73
+ end
74
+ end
75
+ keystore.sign_apk("#{workspace_dir}/TestServer.apk", test_server_file_name)
76
+ begin
77
+
78
+ rescue => e
79
+ @logger.log e, :debug
80
+ raise BuildError.new("Could not sign test server")
81
+ end
82
+ end
83
+ @logger.log "Done signing the test server. Moved it to #{test_server_file_name}"
84
+ end
85
+
86
+ def fingerprint_from_apk
87
+ application_path = File.expand_path(@application_path)
88
+
89
+ Dir.mktmpdir do |tmp_dir|
90
+ Dir.chdir(tmp_dir) do
91
+ FileUtils.cp(application_path, "app.apk")
92
+ FileUtils.mkdir("META-INF")
93
+ Zip::File.foreach("app.apk") do |z|
94
+ z.extract if /^META-INF\/\w+.(rsa|dsa)/i =~ z.name
95
+ end
96
+ signature_files = Dir["#{tmp_dir}/META-INF/*"]
97
+
98
+ Logger.debug 'Signature files:'
99
+
100
+ signature_files.each do |signature_file|
101
+ Logger.debug signature_file
102
+ end
103
+
104
+ raise "No signature files found in META-INF. Cannot proceed." if signature_files.empty?
105
+ raise "More than one signature file (DSA or RSA) found in META-INF. Cannot proceed." if signature_files.length > 1
106
+
107
+ cmd = "#{Calabash::Android::Environment.keytool_path} -v -printcert -J\"-Dfile.encoding=utf-8\" -file \"#{signature_files.first}\""
108
+ Logger.debug cmd
109
+ fingerprints = `#{cmd}`
110
+ md5_fingerprint = JavaKeystore.extract_md5_fingerprint(fingerprints)
111
+ Logger.debug "MD5 fingerprint for signing cert (#{application_path}): #{md5_fingerprint}"
112
+ md5_fingerprint
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,177 @@
1
+ require 'escape'
2
+
3
+ module Calabash
4
+ module Android
5
+ module Build
6
+ class JavaKeystore
7
+ CALABASH_KEYSTORE_SETTINGS_FILENAME = 'calabash_keystore_settings.json'
8
+
9
+ attr_reader :errors, :location, :keystore_alias, :store_password
10
+ attr_reader :key_password, :fingerprint, :signature_algorithm_name
11
+
12
+ def initialize(location, keystore_alias, store_password, key_password, options={})
13
+ @logger = options[:logger] || Calabash::Logger.new
14
+
15
+ raise "No such keystore file '#{location}'" unless File.exists?(File.expand_path(location))
16
+
17
+ if key_password.nil? || key_password.empty?
18
+ key_password = store_password.dup
19
+ end
20
+
21
+ @logger.log "Reading keystore data from keystore file '#{File.expand_path(location)}'", :debug
22
+
23
+ keystore_data = system_with_stdout_on_success(Environment.keytool_path, '-list', '-v', '-alias', keystore_alias, '-keystore', location, '-storepass', store_password, '-keypass', key_password, '-J"-Dfile.encoding=utf-8"')
24
+
25
+ if keystore_data.nil?
26
+ if keystore_alias.empty?
27
+ @logger.log "Could not obtain keystore data. Will try to extract alias automatically", :debug
28
+
29
+ keystore_data = system_with_stdout_on_success(Environment.keytool_path, '-list', '-v', '-keystore', location, '-storepass', store_password, '-keypass', key_password, '-J"-Dfile.encoding=utf-8"')
30
+
31
+ if keystore_data.nil?
32
+ error = 'Could not read keystore alias. Probably because the credentials were incorrect.'
33
+ @errors = [{message: error}]
34
+ @logger.log error, :error
35
+ raise error
36
+ end
37
+
38
+ aliases = keystore_data.scan(/Alias name\:\s*(.*)/).flatten
39
+
40
+ if aliases.length == 0
41
+ raise 'Could not extract alias automatically. Please specify alias using calabash setup-keystore'
42
+ elsif aliases.length > 1
43
+ raise 'Multiple aliases found in keystore. Please specify alias using calabash setup-keystore'
44
+ else
45
+ keystore_alias = aliases.first
46
+ @logger.log "Extracted keystore alias '#{keystore_alias}'. Continuing", :debug
47
+
48
+ return initialize(location, keystore_alias, store_password, key_password)
49
+ end
50
+ else
51
+ error = "Could not list certificates in keystore. Probably because the credentials were incorrect."
52
+ @errors = [{:message => error}]
53
+ @logger.log error, :error
54
+ raise error
55
+ end
56
+ end
57
+
58
+ @location = location
59
+ @keystore_alias = keystore_alias
60
+ @store_password = store_password
61
+ @key_password = key_password
62
+ @logger.log "Key store data:", :debug
63
+ @logger.log keystore_data, :debug
64
+ @fingerprint = JavaKeystore.extract_md5_fingerprint(keystore_data)
65
+ @signature_algorithm_name = JavaKeystore.extract_signature_algorithm_name(keystore_data)
66
+ @logger.log "Fingerprint: #{fingerprint}", :debug
67
+ @logger.log "Signature algorithm name: #{signature_algorithm_name}", :debug
68
+ end
69
+
70
+ def sign_apk(apk_path, dest_path)
71
+ raise "Cannot sign with a miss configured keystore" if errors
72
+ raise "No such file: #{apk_path}" unless File.exists?(apk_path)
73
+
74
+ # E.g. MD5withRSA or MD5withRSAandMGF1
75
+ encryption = signature_algorithm_name.split('with')[1].split('and')[0]
76
+ signing_algorithm = "SHA1with#{encryption}"
77
+ digest_algorithm = 'SHA1'
78
+
79
+ Logger.info "Signing using the signature algorithm: '#{signing_algorithm}'"
80
+ Logger.info "Signing using the digest algorithm: '#{digest_algorithm}'"
81
+
82
+ unless system_with_stdout_on_success(Environment.jarsigner_path, '-sigfile', 'CERT', '-sigalg', signing_algorithm, '-digestalg', digest_algorithm, '-signedjar', dest_path, '-storepass', store_password, '-keypass', key_password, '-keystore', location, apk_path, keystore_alias)
83
+ Logger.error 'Could not sign the application. The keystore credentials are most like incorrect'
84
+ raise "Could not sign app '#{apk_path}'"
85
+ end
86
+ end
87
+
88
+ def system_with_stdout_on_success(cmd, *args)
89
+ a = Escape.shell_command(args)
90
+ cmd = "#{cmd} #{a.gsub("'", '"')}"
91
+ @logger.log cmd, :debug
92
+ out = `#{cmd}`
93
+ if $?.exitstatus == 0
94
+ out
95
+ else
96
+ nil
97
+ end
98
+ end
99
+
100
+ def fail_wrong_info
101
+ raise "Could not read keystore with the given credentials. Please ensure "
102
+ end
103
+
104
+ def self.read_keystore_with_default_password_and_alias(path)
105
+ path = File.expand_path path
106
+
107
+ if File.exists? path
108
+ keystore = nil
109
+
110
+ begin
111
+ keystore = JavaKeystore.new(path, 'androiddebugkey', 'android', 'android')
112
+ rescue => _
113
+ Logger.debug "Trying to read keystore from: #{path} - got error"
114
+ return nil
115
+ end
116
+
117
+ if keystore.errors
118
+ Logger.debug "Got errors #{keystore.errors}"
119
+ nil
120
+ else
121
+ Logger.debug "Unlocked keystore at #{path} - fingerprint: #{keystore.fingerprint}"
122
+ keystore
123
+ end
124
+ else
125
+ Logger.debug "Trying to read keystore from: #{path} - no such file"
126
+ nil
127
+ end
128
+ end
129
+
130
+ def self.get_keystores
131
+ if keystore = keystore_from_settings
132
+ [ keystore ]
133
+ else
134
+ [
135
+ read_keystore_with_default_password_and_alias(File.join(ENV["HOME"], "/.android/debug.keystore")),
136
+ read_keystore_with_default_password_and_alias("debug.keystore"),
137
+ read_keystore_with_default_password_and_alias(File.join(ENV["HOME"], ".local/share/Xamarin/Mono\\ for\\ Android/debug.keystore")),
138
+ read_keystore_with_default_password_and_alias(File.join(ENV["HOME"], "AppData/Local/Xamarin/Mono for Android/debug.keystore")),
139
+ ].compact
140
+ end
141
+ end
142
+
143
+ def self.keystore_from_settings
144
+ if File.exist?(CALABASH_KEYSTORE_SETTINGS_FILENAME)
145
+ Logger.info "Reading keystore information specified in #{CALABASH_KEYSTORE_SETTINGS_FILENAME}"
146
+
147
+ begin
148
+ keystore = JSON.parse(IO.read(CALABASH_KEYSTORE_SETTINGS_FILENAME))
149
+ rescue JSON::ParserError => e
150
+ Logger.error('Could not parse keystore settings. Please run calabash setup-keystore again')
151
+
152
+ raise e
153
+ end
154
+
155
+ JavaKeystore.new(keystore["keystore_location"], keystore["keystore_alias"], keystore["keystore_store_password"], keystore["keystore_key_password"])
156
+ end
157
+ end
158
+
159
+ def self.fail_if_key_missing(map, key)
160
+ raise "Found #{CALABASH_KEYSTORE_SETTINGS_FILENAME} but no #{key} defined." unless map[key]
161
+ end
162
+
163
+ def self.extract_md5_fingerprint(fingerprints)
164
+ m = fingerprints.scan(/MD5.*((?:[a-fA-F\d]{2}:){15}[a-fA-F\d]{2})/).flatten
165
+ raise "No MD5 fingerprint found:\n #{fingerprints}" if m.empty?
166
+ m.first
167
+ end
168
+
169
+ def self.extract_signature_algorithm_name(fingerprints)
170
+ m = fingerprints.scan(/Signature algorithm name: (.*)/).flatten
171
+ raise "No signature algorithm names found:\n #{fingerprints}" if m.empty?
172
+ m.first
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,56 @@
1
+ module Calabash
2
+ module Android
3
+ module Build
4
+ # @!visibility private
5
+ class Resigner
6
+ def initialize(application_path, options={})
7
+ @application_path = application_path
8
+
9
+ if options[:logger]
10
+ @logger = options[:logger] || Logger.new
11
+ else
12
+ @logger = Logger.new
13
+ @logger.default_log_level = :info
14
+ end
15
+ end
16
+
17
+ def resign!
18
+ Dir.mktmpdir do |tmp_dir|
19
+ @logger.log 'Resigning apk', :debug
20
+ unsigned_path = File.join(tmp_dir, 'unsigned.apk')
21
+ unaligned_path = File.join(tmp_dir, 'unaligned.apk')
22
+ FileUtils.cp(@application_path, unsigned_path)
23
+ unsign(unsigned_path)
24
+ sign(unsigned_path, unaligned_path)
25
+ zipalign(unaligned_path, @application_path)
26
+ end
27
+ end
28
+
29
+ def unsign(unsigned_path)
30
+ files_to_remove = `"#{Environment.aapt_path}" list "#{unsigned_path}"`.lines.collect(&:strip).grep(/^META-INF\//)
31
+ if files_to_remove.empty?
32
+ @logger.log "App wasn't signed. Will not try to unsign it.", :debug
33
+ else
34
+ system("\"#{Environment.aapt_path}\" remove \"#{unsigned_path}\" #{files_to_remove.join(" ")}")
35
+ end
36
+ end
37
+
38
+ def zipalign(unaligned_path, app_path)
39
+ cmd = %Q("#{Environment.zipalign_path}" -f 4 "#{unaligned_path}" "#{app_path}")
40
+ @logger.log "Zipaligning using: #{cmd}", :debug
41
+ system(cmd)
42
+ end
43
+
44
+ def sign(app_path, dest_path)
45
+ java_keystore = JavaKeystore.get_keystores.first
46
+
47
+ if java_keystore.nil?
48
+ raise 'No keystores found. You can specify the keystore location and credentials using calabash setup-keystore'
49
+ end
50
+
51
+ java_keystore.sign_apk(app_path, dest_path)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ module Calabash
2
+ module Android
3
+ module Build
4
+ # @!visibility private
5
+ class TestServer
6
+ def initialize(application_path)
7
+ @application_path = application_path
8
+ end
9
+
10
+ def path
11
+ File.expand_path("test_servers/#{checksum(@application_path)}_#{VERSION}.apk")
12
+ end
13
+
14
+ def exists?
15
+ File.exists?(path)
16
+ end
17
+
18
+ private
19
+
20
+ def checksum(file_path)
21
+ require 'digest/md5'
22
+ Digest::MD5.file(file_path).hexdigest
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ module Calabash
2
+ module ConsoleHelpers
3
+ def self.render(data, indentation)
4
+ if visible?(data)
5
+ type = data['type']
6
+ simple_name = type.split('.').last.split('$').last
7
+
8
+ str_type = if data['type'] == 'dom'
9
+ "#{Color.yellow("[")}#{simple_name}:#{Color.yellow("#{data['nodeName']}]")} "
10
+ else
11
+ Color.yellow("[#{simple_name}] ")
12
+ end
13
+
14
+ text = nil
15
+
16
+ if data['value']
17
+ unless data['value'].empty?
18
+ if data['value'].length > 45
19
+ text = "#{data['value'][0,45]}[...]"
20
+ else
21
+ text = data['value']
22
+ end
23
+
24
+ newline_index = text.index("\n")
25
+
26
+ unless newline_index.nil?
27
+ text = "#{text[0,newline_index]}[...]"
28
+ end
29
+ end
30
+ end
31
+
32
+ str_id = data['id'] ? "[id:#{Color.blue(data['id'])}] " : ''
33
+ str_label = data['label'] ? "[contentDescription:#{Color.green(data['label'])}] " : ''
34
+ str_text = text ? "[text:#{Color.magenta(text)}] " : ''
35
+ output("#{str_type}#{str_id}#{str_label}#{str_text}", indentation)
36
+ output("\n", indentation)
37
+ end
38
+ end
39
+
40
+ def self.visible?(data)
41
+ data['visible'] || data['children'].map{|child| visible?(child)}.any?
42
+ end
43
+ end
44
+ end