calabash-cucumber 0.9.169.pre2 → 0.9.169.pre5
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/Rakefile +14 -1
- data/bin/calabash-ios-setup.rb +2 -4
- data/bin/calabash-ios-sim.rb +10 -40
- data/calabash-cucumber.gemspec +25 -22
- data/features-skeleton/support/01_launch.rb +1 -1
- data/lib/calabash-cucumber.rb +13 -1
- data/lib/calabash-cucumber/actions/instruments_actions.rb +0 -4
- data/lib/calabash-cucumber/actions/playback_actions.rb +0 -4
- data/lib/calabash-cucumber/core.rb +9 -16
- data/lib/calabash-cucumber/device.rb +11 -2
- data/lib/calabash-cucumber/environment_helpers.rb +4 -56
- data/lib/calabash-cucumber/ios7_operations.rb +4 -2
- data/lib/calabash-cucumber/keyboard_helpers.rb +6 -3
- data/lib/calabash-cucumber/launch/simulator_helper.rb +40 -386
- data/lib/calabash-cucumber/launch/simulator_launcher.rb +534 -0
- data/lib/calabash-cucumber/launcher.rb +172 -36
- data/lib/calabash-cucumber/operations.rb +3 -4
- data/lib/calabash-cucumber/playback_helpers.rb +15 -29
- data/lib/calabash-cucumber/rotation_helpers.rb +14 -10
- data/lib/calabash-cucumber/status_bar_helpers.rb +5 -1
- data/lib/calabash-cucumber/uia.rb +6 -12
- data/lib/calabash-cucumber/utils/logging.rb +97 -0
- data/lib/calabash-cucumber/utils/plist_buddy.rb +178 -0
- data/lib/calabash-cucumber/utils/simulator_accessibility.rb +250 -0
- data/lib/calabash-cucumber/utils/xctools.rb +95 -0
- data/lib/calabash-cucumber/version.rb +197 -2
- data/lib/calabash-cucumber/wait_helpers.rb +16 -20
- data/scripts/.irbrc +11 -6
- data/scripts/com.example.plist +0 -0
- data/scripts/launch.rb +1 -1
- data/spec/bin/calabash_ios_sim_spec.rb +24 -0
- data/spec/launcher_spec.rb +76 -0
- data/spec/logging_spec.rb +38 -0
- data/spec/plist_buddy_spec.rb +99 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Default-568h@2x.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/PkgInfo +1 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/InfoPlist.strings +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first@2x.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second@2x.png +0 -0
- data/spec/resources/plist_buddy/com.example.plist +0 -0
- data/spec/resources/plist_buddy/com.testing.plist +18 -0
- data/spec/simulator_accessibility_spec.rb +144 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/xctools_spec.rb +58 -0
- metadata +120 -34
@@ -0,0 +1,534 @@
|
|
1
|
+
require 'sim_launcher'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'cfpropertylist'
|
5
|
+
require 'calabash-cucumber/utils/logging'
|
6
|
+
|
7
|
+
module Calabash
|
8
|
+
module Cucumber
|
9
|
+
|
10
|
+
# acts as a bridge to the sim_launcher SimLauncher and SdkDetector classes
|
11
|
+
class SimulatorLauncher
|
12
|
+
include Calabash::Cucumber::Logging
|
13
|
+
|
14
|
+
# custom error indicating a timeout in launching and connecting to the
|
15
|
+
# embedded calabash server
|
16
|
+
# todo is duplicated in Launcher class - consider exceptions.rb module
|
17
|
+
class TimeoutErr < RuntimeError
|
18
|
+
end
|
19
|
+
|
20
|
+
# the file path to the default Xcode DerivedData directory
|
21
|
+
DERIVED_DATA = File.expand_path('~/Library/Developer/Xcode/DerivedData')
|
22
|
+
|
23
|
+
# REGEX for finding application Info.plist
|
24
|
+
DEFAULT_DERIVED_DATA_INFO = File.expand_path("#{DERIVED_DATA}/*/info.plist")
|
25
|
+
|
26
|
+
# if CONNECT_TIMEOUT is not set, wait this long for the app to launch
|
27
|
+
# in the simulator before retrying
|
28
|
+
DEFAULT_SIM_WAIT = 30
|
29
|
+
|
30
|
+
# if MAX_CONNECT_RETRY is not set, try to launch the app this many times
|
31
|
+
# in the simulator before giving up
|
32
|
+
DEFAULT_SIM_RETRY = 2
|
33
|
+
|
34
|
+
# an instance of Calabash::Cucumber::Device
|
35
|
+
attr_accessor :device
|
36
|
+
|
37
|
+
# an instance of SimLauncher::Simulator
|
38
|
+
attr_accessor :simulator
|
39
|
+
|
40
|
+
# an instance of SimLauncher::SdkDetector
|
41
|
+
attr_accessor :sdk_detector
|
42
|
+
|
43
|
+
# the launch args passed from Calabash::Cucumber::Launcher to the
|
44
|
+
# launch and relaunch methods.
|
45
|
+
attr_accessor :launch_args
|
46
|
+
|
47
|
+
# creates a new instance an sets the :simulator and :sdk_detector attributes
|
48
|
+
def initialize
|
49
|
+
@simulator = SimLauncher::Simulator.new
|
50
|
+
@sdk_detector = SimLauncher::SdkDetector.new()
|
51
|
+
end
|
52
|
+
|
53
|
+
# uses heuristics to deduce the derived data directory for the project
|
54
|
+
# so the path to the app bundle (.app) can be detected.
|
55
|
+
# @return [String] absolute path to derived data directory
|
56
|
+
# @raise [RuntimeError] if the derived data directory cannot be found
|
57
|
+
def derived_data_dir_for_project
|
58
|
+
dir = project_dir
|
59
|
+
xcode_workspace_name = ''
|
60
|
+
info_plist = Dir.glob(DEFAULT_DERIVED_DATA_INFO).find { |plist_file|
|
61
|
+
begin
|
62
|
+
plist = CFPropertyList::List.new(:file => plist_file)
|
63
|
+
hash = CFPropertyList.native_types(plist.value)
|
64
|
+
ws_dir = File.dirname(hash['WorkspacePath']).downcase
|
65
|
+
p_dir = dir.downcase
|
66
|
+
if p_dir.include? ws_dir
|
67
|
+
xcode_workspace_name = ws_dir.split('/').last
|
68
|
+
end
|
69
|
+
ws_dir == p_dir
|
70
|
+
rescue
|
71
|
+
false
|
72
|
+
end
|
73
|
+
}
|
74
|
+
|
75
|
+
return File.dirname(info_plist) unless info_plist.nil?
|
76
|
+
|
77
|
+
res = Dir.glob("#{dir}/*.xcodeproj")
|
78
|
+
if res.empty?
|
79
|
+
raise "Unable to find *.xcodeproj in #{dir}"
|
80
|
+
elsif res.count > 1
|
81
|
+
raise "Unable to found several *.xcodeproj in #{dir}: #{res}"
|
82
|
+
end
|
83
|
+
|
84
|
+
xcode_proj_name = res.first.split('.xcodeproj')[0]
|
85
|
+
|
86
|
+
xcode_proj_name = File.basename(xcode_proj_name)
|
87
|
+
|
88
|
+
build_dirs = Dir.glob("#{DERIVED_DATA}/*").find_all do |xc_proj|
|
89
|
+
File.basename(xc_proj).start_with?(xcode_proj_name)
|
90
|
+
end
|
91
|
+
|
92
|
+
if build_dirs.count == 0 && !xcode_workspace_name.empty?
|
93
|
+
# check for directory named "workspace-{deriveddirectoryrandomcharacters}"
|
94
|
+
build_dirs = Dir.glob("#{DERIVED_DATA}/*").find_all do |xc_proj|
|
95
|
+
File.basename(xc_proj).downcase.start_with?(xcode_workspace_name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# todo analyze `derived_data_dir_for_project` to see if it contains dead code
|
100
|
+
# todo assuming this is not dead code, the documentation around derived data for project needs to be updated
|
101
|
+
|
102
|
+
if build_dirs.count == 0
|
103
|
+
msg = ['Unable to find your built app.']
|
104
|
+
msg << "This means that Calabash can't automatically launch iOS simulator."
|
105
|
+
msg << "Searched in Xcode 4.x default: #{DEFAULT_DERIVED_DATA_INFO}"
|
106
|
+
msg << ''
|
107
|
+
msg << "To fix there are a couple of options:\n"
|
108
|
+
msg << 'Option 1) Make sure you are running this command from your project directory, '
|
109
|
+
msg << 'i.e., the directory containing your .xcodeproj file.'
|
110
|
+
msg << 'In Xcode, build your calabash target for simulator.'
|
111
|
+
msg << "Check that your app can be found in\n #{DERIVED_DATA}"
|
112
|
+
msg << "\n\nOption 2). In features/support/01_launch.rb set APP_BUNDLE_PATH to"
|
113
|
+
msg << 'the path where Xcode has built your Calabash target.'
|
114
|
+
msg << "Alternatively you can use the environment variable APP_BUNDLE_PATH.\n"
|
115
|
+
raise msg.join("\n")
|
116
|
+
|
117
|
+
elsif build_dirs.count > 1
|
118
|
+
msg = ['Unable to auto detect APP_BUNDLE_PATH.']
|
119
|
+
msg << "You have several projects with the same name: #{xcode_proj_name} in #{DERIVED_DATA}:\n"
|
120
|
+
msg << build_dirs.join("\n")
|
121
|
+
|
122
|
+
msg << "\nThis means that Calabash can't automatically launch iOS simulator."
|
123
|
+
msg << "Searched in Xcode 4.x default: #{DEFAULT_DERIVED_DATA_INFO}"
|
124
|
+
msg << "\nIn features/support/01_launch.rb set APP_BUNDLE_PATH to"
|
125
|
+
msg << 'the path where Xcode has built your Calabash target.'
|
126
|
+
msg << "Alternatively you can use the environment variable APP_BUNDLE_PATH.\n"
|
127
|
+
raise msg.join("\n")
|
128
|
+
else
|
129
|
+
if full_console_logging?
|
130
|
+
puts "Found potential build dir: #{build_dirs.first}"
|
131
|
+
puts 'Checking...'
|
132
|
+
end
|
133
|
+
build_dirs.first
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# returns the absolute path to the project directory
|
138
|
+
# unless PROJECT_DIR is defined, returns the absolute path to the current
|
139
|
+
# directory
|
140
|
+
# @return [String] absolute path to the project directory
|
141
|
+
# todo migrate PROJECT_DIR to environment_helpers.rb
|
142
|
+
def project_dir
|
143
|
+
File.expand_path(ENV['PROJECT_DIR'] || Dir.pwd)
|
144
|
+
end
|
145
|
+
|
146
|
+
# attempts to deduce the app bundle path
|
147
|
+
# @param [String] path NEEDS DOCUMENTATION
|
148
|
+
# @param [String] device_build_dir NEEDS DOCUMENTATION
|
149
|
+
# @return [String] absolute path to app bundle (.app)
|
150
|
+
# @return [nil] iff app bundle cannot be found
|
151
|
+
# todo methods should not use 2 optional arguments
|
152
|
+
def detect_app_bundle(path=nil,device_build_dir='iPhoneSimulator')
|
153
|
+
begin
|
154
|
+
app_bundle_or_raise(path,device_build_dir)
|
155
|
+
rescue
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# attempts to deduce the path the to the app bundle (.app)
|
161
|
+
# @param [String] path NEEDS DOCUMENTATION
|
162
|
+
# @param [String] device_build_dir NEEDS DOCUMENTATION
|
163
|
+
# @return [String] absolute path to app bundle (.app)
|
164
|
+
# @raise [RuntimeError] if app bundle (.app) cannot be found
|
165
|
+
# todo methods should not use 2 optional arguments
|
166
|
+
def app_bundle_or_raise(path=nil, device_build_dir='iPhoneSimulator')
|
167
|
+
path = File.expand_path(path) if path
|
168
|
+
|
169
|
+
if path and not File.directory?(path)
|
170
|
+
raise "Unable to find .app bundle at #{path}. It should be an .app directory."
|
171
|
+
elsif path
|
172
|
+
bundle_path = path
|
173
|
+
elsif xamarin_project?
|
174
|
+
bundle_path = bundle_path_from_xamarin_project(device_build_dir)
|
175
|
+
unless bundle_path
|
176
|
+
msg = ['Detected Xamarin project, but did not detect built app linked with Calabash']
|
177
|
+
msg << 'You should build your project from Xamarin Studio'
|
178
|
+
msg << "Make sure you build for Simulator and that you're using the Calabash components"
|
179
|
+
raise msg.join("\n")
|
180
|
+
end
|
181
|
+
if full_console_logging?
|
182
|
+
puts('-'*37)
|
183
|
+
puts "Auto detected APP_BUNDLE_PATH:\n\n"
|
184
|
+
|
185
|
+
puts "APP_BUNDLE_PATH= '#{bundle_path}'\n\n"
|
186
|
+
puts 'Please verify!'
|
187
|
+
puts "If this is wrong please set it as APP_BUNDLE_PATH in features/support/01_launch.rb\n"
|
188
|
+
puts('-'*37)
|
189
|
+
end
|
190
|
+
else
|
191
|
+
dd_dir = derived_data_dir_for_project
|
192
|
+
sim_dirs = Dir.glob(File.join(dd_dir, 'Build', 'Products', '*-iphonesimulator', '*.app'))
|
193
|
+
if sim_dirs.empty?
|
194
|
+
msg = ['Unable to auto detect APP_BUNDLE_PATH.']
|
195
|
+
msg << 'Have you built your app for simulator?'
|
196
|
+
msg << "Searched dir: #{dd_dir}/Build/Products"
|
197
|
+
msg << 'Please build your app from Xcode'
|
198
|
+
msg << 'You should build the -cal target.'
|
199
|
+
msg << ''
|
200
|
+
msg << 'Alternatively, specify APP_BUNDLE_PATH in features/support/01_launch.rb'
|
201
|
+
msg << "This should point to the location of your built app linked with calabash.\n"
|
202
|
+
raise msg.join("\n")
|
203
|
+
end
|
204
|
+
preferred_dir = find_preferred_dir(sim_dirs)
|
205
|
+
if preferred_dir.nil?
|
206
|
+
msg = ['Error... Unable to find APP_BUNDLE_PATH.']
|
207
|
+
msg << 'Cannot find a built app that is linked with calabash.framework'
|
208
|
+
msg << 'Please build your app from Xcode'
|
209
|
+
msg << 'You should build your calabash target.'
|
210
|
+
msg << ''
|
211
|
+
msg << 'Alternatively, specify APP_BUNDLE_PATH in features/support/01_launch.rb'
|
212
|
+
msg << "This should point to the location of your built app linked with calabash.\n"
|
213
|
+
raise msg.join("\n")
|
214
|
+
end
|
215
|
+
if full_console_logging?
|
216
|
+
puts('-'*37)
|
217
|
+
puts "Auto detected APP_BUNDLE_PATH:\n\n"
|
218
|
+
|
219
|
+
puts "APP_BUNDLE_PATH=#{preferred_dir || sim_dirs[0]}\n\n"
|
220
|
+
puts 'Please verify!'
|
221
|
+
puts "If this is wrong please set it as APP_BUNDLE_PATH in features/support/01_launch.rb\n"
|
222
|
+
puts('-'*37)
|
223
|
+
end
|
224
|
+
bundle_path = sim_dirs[0]
|
225
|
+
end
|
226
|
+
bundle_path
|
227
|
+
end
|
228
|
+
|
229
|
+
# is this a Xamarin IDE project?
|
230
|
+
# @return [Boolean] true iff the project is a Xamarin IDE project
|
231
|
+
def xamarin_project?
|
232
|
+
xamarin_ios_csproj_path != nil
|
233
|
+
end
|
234
|
+
|
235
|
+
# path to the Xamarin IDE project
|
236
|
+
# @return [String] absolute path to the Xamarin IDE project
|
237
|
+
def xamarin_ios_csproj_path
|
238
|
+
solution_path = Dir['*.sln'].first
|
239
|
+
|
240
|
+
project_dir = nil
|
241
|
+
if solution_path
|
242
|
+
project_dir = Dir.pwd
|
243
|
+
else
|
244
|
+
solution_path = Dir[File.join('..','*.sln')].first
|
245
|
+
if solution_path
|
246
|
+
project_dir = File.expand_path('..')
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
return nil unless project_dir
|
251
|
+
|
252
|
+
ios_project_dir = Dir[File.join(project_dir,'*.iOS')].first
|
253
|
+
return ios_project_dir if ios_project_dir && File.directory?(ios_project_dir)
|
254
|
+
# ios_project_dir does not exist
|
255
|
+
# Detect case where there is no such sub directory
|
256
|
+
# (i.e. iOS only Xamarin project)
|
257
|
+
bin_dir = File.join(project_dir, 'bin')
|
258
|
+
if xamarin_ios_bin_dir?(bin_dir)
|
259
|
+
return project_dir ## Looks like iOS bin dir is here
|
260
|
+
end
|
261
|
+
|
262
|
+
sub_dirs = Dir[File.join(project_dir,'*')].select {|dir| File.directory?(dir)}
|
263
|
+
|
264
|
+
sub_dirs.find do |sub_dir|
|
265
|
+
contains_csproj = Dir[File.join(sub_dir,'*.csproj')].first
|
266
|
+
contains_csproj && xamarin_ios_bin_dir?(File.join(sub_dir,'bin'))
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
# is this the Xamarin iOS bin directory?
|
272
|
+
# @return [Boolean] true iff this is the Xamarin iOS bin directory
|
273
|
+
def xamarin_ios_bin_dir?(bin_dir)
|
274
|
+
File.directory?(bin_dir) &&
|
275
|
+
(File.directory?(File.join(bin_dir,'iPhoneSimulator')) ||
|
276
|
+
File.directory?(File.join(bin_dir,'iPhone')))
|
277
|
+
end
|
278
|
+
|
279
|
+
# attempts to deduce the path to the app bundle path (*.app) using
|
280
|
+
# heuristics and checking for executables linked with the Calabash server
|
281
|
+
#
|
282
|
+
# @param [String] device_build_dir NEEDS DOCUMENTATION
|
283
|
+
# @return [String] absolute path the app bundle .app
|
284
|
+
# @return [nil] iff the app bundle cannot be found
|
285
|
+
def bundle_path_from_xamarin_project(device_build_dir='iPhoneSimulator')
|
286
|
+
ios_project_path = xamarin_ios_csproj_path
|
287
|
+
conf_glob = File.join(ios_project_path,'bin',device_build_dir,'*')
|
288
|
+
built_confs = Dir[conf_glob]
|
289
|
+
|
290
|
+
calabash_build = built_confs.find {|path| File.basename(path) == 'Calabash'}
|
291
|
+
debug_build = built_confs.find {|path| File.basename(path) == 'Debug'}
|
292
|
+
|
293
|
+
bundle_path = [calabash_build, debug_build, *built_confs].find do |path|
|
294
|
+
next unless path && File.directory?(path)
|
295
|
+
app_dir = Dir[File.join(path,'*.app')].first
|
296
|
+
app_dir && linked_with_calabash?(app_dir)
|
297
|
+
end
|
298
|
+
|
299
|
+
Dir[File.join(bundle_path,'*.app')].first if bundle_path
|
300
|
+
end
|
301
|
+
|
302
|
+
# searches +d+ for a file linked with Calabash server
|
303
|
+
# @param [String] d path to a directory
|
304
|
+
# @return [Boolean] true iff there is a file that is linked with the
|
305
|
+
# Calabash server
|
306
|
+
# todo why are we not grep'ing for executable files? see server_version_from_bundle
|
307
|
+
def linked_with_calabash?(d)
|
308
|
+
skipped_formats = ['.png', '.jpg', '.jpeg', '.plist', '.nib', '.lproj']
|
309
|
+
dir = File.expand_path(d)
|
310
|
+
|
311
|
+
# For every file on that .app directory
|
312
|
+
Dir.entries(d).each do |file|
|
313
|
+
# If this is an asset or any of those skipped formats, skip it.
|
314
|
+
next if skipped_formats.include? File.extname(file)
|
315
|
+
|
316
|
+
# If its not, try to run otool against that file, check whether we are linked against calabash framework.
|
317
|
+
out = `otool "#{dir}/#{file}" -o 2> /dev/null | grep CalabashServer`
|
318
|
+
return true if /CalabashServer/.match(out)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Defaulted to false
|
322
|
+
false
|
323
|
+
end
|
324
|
+
|
325
|
+
# @return [String] the first path in +sim_dirs+ that contains a binary
|
326
|
+
# linked with Calabash server
|
327
|
+
# @return [nil] iff there is no path in +sim_dirs+ that contains a binary
|
328
|
+
# linked with Calabash server
|
329
|
+
# @param [Array<String>] sim_dirs eke! why sim_dirs? why not a list of any directories?
|
330
|
+
# todo find_preferred_dir is a bad name - preferred for what?
|
331
|
+
# todo sim_dirs arg is a bad name - we can be iterating over any directory
|
332
|
+
def find_preferred_dir(sim_dirs)
|
333
|
+
sim_dirs.find do |d|
|
334
|
+
linked_with_calabash?(d)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# ping the version route of the calabash server embedded in the app
|
340
|
+
#
|
341
|
+
# has the side effect of setting self.device attribute if successful
|
342
|
+
#
|
343
|
+
# @return [String] returns the server status - '200' is a success
|
344
|
+
# todo migrate DEVICE_ENDPOINT to environment_helpers
|
345
|
+
# todo migrate CALABASH_VERSION_PATH to environment_helpers
|
346
|
+
# todo this is an exact duplicate of Launcher ping method
|
347
|
+
def ping_app
|
348
|
+
url = URI.parse(ENV['DEVICE_ENDPOINT']|| 'http://localhost:37265/')
|
349
|
+
if full_console_logging?
|
350
|
+
puts "Ping #{url}..."
|
351
|
+
end
|
352
|
+
|
353
|
+
http = Net::HTTP.new(url.host, url.port)
|
354
|
+
res = http.start do |sess|
|
355
|
+
# noinspection RubyResolve
|
356
|
+
sess.request Net::HTTP::Get.new(ENV['CALABASH_VERSION_PATH'] || 'version')
|
357
|
+
end
|
358
|
+
|
359
|
+
status = res.code
|
360
|
+
begin
|
361
|
+
http.finish if http and http.started?
|
362
|
+
rescue
|
363
|
+
# nop
|
364
|
+
end
|
365
|
+
|
366
|
+
if status == '200'
|
367
|
+
version_body = JSON.parse(res.body)
|
368
|
+
self.device = Calabash::Cucumber::Device.new(url, version_body)
|
369
|
+
end
|
370
|
+
|
371
|
+
if full_console_logging?
|
372
|
+
puts "ping status = '#{status}'"
|
373
|
+
end
|
374
|
+
status
|
375
|
+
end
|
376
|
+
|
377
|
+
# attempts to connect to launch the app and connect to the embedded
|
378
|
+
# calabash server.
|
379
|
+
#
|
380
|
+
# to change the number of times launching is attempted set MAX_CONNECT_RETRY
|
381
|
+
#
|
382
|
+
# to change the relaunch timeout set CONNECT_TIMEOUT
|
383
|
+
#
|
384
|
+
# @param [String] app_bundle_path path to the .app that should be launched
|
385
|
+
# @param [String] sdk 6.0.3, 6.1. if nil latest SDK will be used
|
386
|
+
# @param [String] device_family {iphone | ipad}
|
387
|
+
# @param [Hash] args eke! not used (see todo)
|
388
|
+
#
|
389
|
+
# @raise [TimeoutErr] if app cannot be launched in the simulator
|
390
|
+
# todo nearly a duplicate of Launcher ensure_connectivity
|
391
|
+
# todo args was originally intended to be the args passed to the application @ launch
|
392
|
+
def ensure_connectivity(app_bundle_path, sdk, device_family, args = nil)
|
393
|
+
begin
|
394
|
+
# todo should get the retry could from the args
|
395
|
+
# todo should migrate MAX_CONNECT_RETRY to environment_helpers
|
396
|
+
max_retry_count = (ENV['MAX_CONNECT_RETRY'] || DEFAULT_SIM_RETRY).to_i
|
397
|
+
# todo should get the timeout from the args
|
398
|
+
# todo should migrate CONNECT_TIMEOUT to environment helpers
|
399
|
+
timeout = (ENV['CONNECT_TIMEOUT'] || DEFAULT_SIM_WAIT).to_i
|
400
|
+
retry_count = 0
|
401
|
+
connected = false
|
402
|
+
|
403
|
+
if full_console_logging?
|
404
|
+
puts "Waiting at most #{timeout} seconds for simulator (CONNECT_TIMEOUT)"
|
405
|
+
puts "Retrying at most #{max_retry_count} times (MAX_CONNECT_RETRY)"
|
406
|
+
end
|
407
|
+
|
408
|
+
until connected do
|
409
|
+
raise 'MAX_RETRIES' if retry_count == max_retry_count
|
410
|
+
retry_count += 1
|
411
|
+
if full_console_logging?
|
412
|
+
puts "(#{retry_count}.) Start Simulator #{sdk}, #{device_family}, for #{app_bundle_path}"
|
413
|
+
end
|
414
|
+
begin
|
415
|
+
Timeout::timeout(timeout, TimeoutErr) do
|
416
|
+
launch(app_bundle_path, sdk, device_family, args)
|
417
|
+
until connected
|
418
|
+
begin
|
419
|
+
connected = (ping_app == '200')
|
420
|
+
break if connected
|
421
|
+
rescue Exception => e
|
422
|
+
# nop
|
423
|
+
ensure
|
424
|
+
sleep 1 unless connected
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
rescue TimeoutErr => e
|
429
|
+
puts 'Timed out... Retrying'
|
430
|
+
stop
|
431
|
+
end
|
432
|
+
end
|
433
|
+
rescue RuntimeError => e
|
434
|
+
p e
|
435
|
+
msg = "Unable to make connection to Calabash Server at #{ENV['DEVICE_ENDPOINT']|| 'http://localhost:37265/'}\n"
|
436
|
+
msg << "Make sure you've' linked correctly with calabash.framework and set Other Linker Flags.\n"
|
437
|
+
msg << "Make sure you don't have a firewall blocking traffic to #{ENV['DEVICE_ENDPOINT']|| 'http://localhost:37265/'}.\n"
|
438
|
+
raise msg
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
# launches the app
|
443
|
+
# @param [String] app_bundle_path path to the .app that should be launched
|
444
|
+
# @param [String] sdk 6.0.3, 6.1. if nil latest SDK will be used
|
445
|
+
# @param [String] device_family {iphone | ipad}
|
446
|
+
# @param [Hash] args eke! not used (see todo)
|
447
|
+
# todo args was originally intended to be the args passed to the application @ launch
|
448
|
+
def launch(app_bundle_path, sdk, device_family, args = nil)
|
449
|
+
# cached but not used
|
450
|
+
self.launch_args = args
|
451
|
+
# launch arguments (eg. -NSShowNonLocalizedStrings) are not being passed
|
452
|
+
# to sim_launcher
|
453
|
+
# https://github.com/calabash/calabash-ios/issues/363
|
454
|
+
self.simulator.launch_ios_app(app_bundle_path, sdk, device_family)
|
455
|
+
simulator
|
456
|
+
end
|
457
|
+
|
458
|
+
# relaunches the app at +app_path+ in the simulator using +sdk+ and +args+
|
459
|
+
#
|
460
|
+
# @param [String] app_path the path to the .app
|
461
|
+
# @param [String] sdk eg. 6.0.3, 6.1
|
462
|
+
# @param [Hash] args the only option we are interested in is :device
|
463
|
+
#
|
464
|
+
# todo args was originally intended to be the args passed to the application @ launch
|
465
|
+
# todo it is _very_ likely that args[:app] == app_path so we might be able
|
466
|
+
# to eliminate an argument
|
467
|
+
def relaunch(app_path, sdk, args)
|
468
|
+
app_bundle_path = app_bundle_or_raise(app_path)
|
469
|
+
|
470
|
+
if sdk.nil?
|
471
|
+
# iOS 7 requires launching with instruments, so we _must_ launch with
|
472
|
+
# the first SDK that is _not_ iOS 7
|
473
|
+
_sdk = self.sdk_detector.available_sdk_versions.reverse.find { |x| !x.start_with?('7') }
|
474
|
+
else
|
475
|
+
# use SDK_VERSION to specify a different version
|
476
|
+
# as of Xcode 5.0.2, the min supported simulator version is iOS 6
|
477
|
+
_sdk = sdk
|
478
|
+
end
|
479
|
+
|
480
|
+
if args[:device]
|
481
|
+
device_family = args[:device].to_s
|
482
|
+
else
|
483
|
+
device_family = 'iphone'
|
484
|
+
end
|
485
|
+
|
486
|
+
self.launch_args = args
|
487
|
+
|
488
|
+
ensure_connectivity(app_bundle_path, _sdk, device_family, args)
|
489
|
+
end
|
490
|
+
|
491
|
+
# stops (quits) the simulator
|
492
|
+
def stop
|
493
|
+
self.simulator.quit_simulator
|
494
|
+
end
|
495
|
+
|
496
|
+
|
497
|
+
# @deprecated Calabash::Cucumber::Launcher.launcher.device instance methods
|
498
|
+
# @since 0.9.169
|
499
|
+
# @raise [NotImplementedError] no longer implemented
|
500
|
+
def get_version
|
501
|
+
_deprecated('0.9.169', 'use an instance Device class instead', :warn)
|
502
|
+
raise(NotImplementedError, 'this method has been deprecated')
|
503
|
+
end
|
504
|
+
|
505
|
+
# @deprecated Calabash::Cucumber::Launcher.launcher.device instance methods
|
506
|
+
# @since 0.9.169
|
507
|
+
# @raise [NotImplementedError] no longer implemented
|
508
|
+
def ios_version
|
509
|
+
_deprecated('0.9.169', 'use an instance Device class instead', :warn)
|
510
|
+
raise(NotImplementedError, 'this method has been deprecated')
|
511
|
+
end
|
512
|
+
|
513
|
+
# @deprecated use Calabash::Cucumber::Launcher.launcher.ios_major_version
|
514
|
+
# @since 0.9.169
|
515
|
+
# @raise [NotImplementedError] no longer implemented
|
516
|
+
def ios_major_version
|
517
|
+
_deprecated('0.9.169', 'use an instance Device class instead', :warn)
|
518
|
+
raise(NotImplementedError, 'this method has been deprecated')
|
519
|
+
end
|
520
|
+
|
521
|
+
|
522
|
+
# noinspection RubyUnusedLocalVariable
|
523
|
+
|
524
|
+
# @deprecated version checking is done in Launcher
|
525
|
+
# @since 0.9.169
|
526
|
+
# @raise [NotImplementedError] no longer implemented
|
527
|
+
def version_check(version)
|
528
|
+
_deprecated('0.9.169', 'check is now done in Launcher', :warn)
|
529
|
+
raise(NotImplementedError, 'this method has been deprecated and will be removed')
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
end
|
534
|
+
end
|