calabash 1.2.1 → 1.9.9.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +39 -0
- data/LICENSE +204 -21
- data/README.md +36 -6
- data/VERSIONING.md +16 -0
- data/bin/calabash +95 -0
- data/lib/calabash.rb +185 -1
- data/lib/calabash/android.rb +64 -0
- data/lib/calabash/android/adb.rb +277 -0
- data/lib/calabash/android/application.rb +110 -0
- data/lib/calabash/android/build.rb +12 -0
- data/lib/calabash/android/build/application.rb +13 -0
- data/lib/calabash/android/build/build_error.rb +11 -0
- data/lib/calabash/android/build/builder.rb +119 -0
- data/lib/calabash/android/build/java_keystore.rb +177 -0
- data/lib/calabash/android/build/resigner.rb +56 -0
- data/lib/calabash/android/build/test_server.rb +27 -0
- data/lib/calabash/android/console_helpers.rb +44 -0
- data/lib/calabash/android/cucumber.rb +3 -0
- data/lib/calabash/android/device.rb +965 -0
- data/lib/calabash/android/environment.rb +470 -0
- data/lib/calabash/android/gestures.rb +369 -0
- data/lib/calabash/android/interactions.rb +45 -0
- data/lib/calabash/android/lib/.irbrc +55 -0
- data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
- data/lib/calabash/android/lib/TestServer.apk +0 -0
- data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
- data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
- data/lib/calabash/android/life_cycle.rb +37 -0
- data/lib/calabash/android/orientation.rb +30 -0
- data/lib/calabash/android/physical_buttons.rb +39 -0
- data/lib/calabash/android/screenshot.rb +9 -0
- data/lib/calabash/android/scroll.rb +5 -0
- data/lib/calabash/android/server.rb +10 -0
- data/lib/calabash/android/text.rb +54 -0
- data/lib/calabash/application.rb +74 -0
- data/lib/calabash/cli.rb +12 -0
- data/lib/calabash/cli/build.rb +33 -0
- data/lib/calabash/cli/console.rb +90 -0
- data/lib/calabash/cli/generate.rb +110 -0
- data/lib/calabash/cli/helpers.rb +130 -0
- data/lib/calabash/cli/resign.rb +33 -0
- data/lib/calabash/cli/run.rb +99 -0
- data/lib/calabash/cli/setup_keystore.rb +39 -0
- data/lib/calabash/color.rb +32 -0
- data/lib/calabash/console_helpers.rb +90 -0
- data/lib/calabash/defaults.rb +56 -0
- data/lib/calabash/device.rb +401 -0
- data/lib/calabash/environment.rb +75 -0
- data/lib/calabash/gestures.rb +384 -0
- data/lib/calabash/http.rb +8 -0
- data/lib/calabash/http/error.rb +15 -0
- data/lib/calabash/http/request.rb +42 -0
- data/lib/calabash/http/retriable_client.rb +156 -0
- data/lib/calabash/interactions.rb +105 -0
- data/lib/calabash/ios.rb +37 -0
- data/lib/calabash/ios/application.rb +119 -0
- data/lib/calabash/ios/conditions.rb +79 -0
- data/lib/calabash/ios/console_helpers.rb +72 -0
- data/lib/calabash/ios/device.rb +24 -0
- data/lib/calabash/ios/device/device_implementation.rb +779 -0
- data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
- data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
- data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
- data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
- data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
- data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
- data/lib/calabash/ios/device/routes/error.rb +8 -0
- data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
- data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
- data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
- data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
- data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
- data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
- data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
- data/lib/calabash/ios/device/text_mixin.rb +19 -0
- data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
- data/lib/calabash/ios/device/uia_mixin.rb +12 -0
- data/lib/calabash/ios/environment.rb +41 -0
- data/lib/calabash/ios/interactions.rb +10 -0
- data/lib/calabash/ios/lib/.irbrc +55 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
- data/lib/calabash/ios/orientation.rb +117 -0
- data/lib/calabash/ios/scroll.rb +504 -0
- data/lib/calabash/ios/server.rb +73 -0
- data/lib/calabash/ios/text.rb +248 -0
- data/lib/calabash/ios/uia.rb +24 -0
- data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
- data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
- data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
- data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
- data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
- data/lib/calabash/life_cycle.rb +111 -0
- data/lib/calabash/location.rb +51 -0
- data/lib/calabash/logger.rb +87 -0
- data/lib/calabash/orientation.rb +84 -0
- data/lib/calabash/page.rb +35 -0
- data/lib/calabash/patch.rb +14 -0
- data/lib/calabash/patch/array.rb +16 -0
- data/lib/calabash/patch/run_loop.rb +90 -0
- data/lib/calabash/query.rb +160 -0
- data/lib/calabash/query_result.rb +85 -0
- data/lib/calabash/screenshot.rb +89 -0
- data/lib/calabash/server.rb +16 -0
- data/lib/calabash/text.rb +76 -0
- data/lib/calabash/utility.rb +58 -0
- data/lib/calabash/version.rb +3 -1
- data/lib/calabash/wait.rb +474 -0
- 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,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
|