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.
- 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
|