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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -1
  3. data/bin/calabash-ios-setup.rb +2 -4
  4. data/bin/calabash-ios-sim.rb +10 -40
  5. data/calabash-cucumber.gemspec +25 -22
  6. data/features-skeleton/support/01_launch.rb +1 -1
  7. data/lib/calabash-cucumber.rb +13 -1
  8. data/lib/calabash-cucumber/actions/instruments_actions.rb +0 -4
  9. data/lib/calabash-cucumber/actions/playback_actions.rb +0 -4
  10. data/lib/calabash-cucumber/core.rb +9 -16
  11. data/lib/calabash-cucumber/device.rb +11 -2
  12. data/lib/calabash-cucumber/environment_helpers.rb +4 -56
  13. data/lib/calabash-cucumber/ios7_operations.rb +4 -2
  14. data/lib/calabash-cucumber/keyboard_helpers.rb +6 -3
  15. data/lib/calabash-cucumber/launch/simulator_helper.rb +40 -386
  16. data/lib/calabash-cucumber/launch/simulator_launcher.rb +534 -0
  17. data/lib/calabash-cucumber/launcher.rb +172 -36
  18. data/lib/calabash-cucumber/operations.rb +3 -4
  19. data/lib/calabash-cucumber/playback_helpers.rb +15 -29
  20. data/lib/calabash-cucumber/rotation_helpers.rb +14 -10
  21. data/lib/calabash-cucumber/status_bar_helpers.rb +5 -1
  22. data/lib/calabash-cucumber/uia.rb +6 -12
  23. data/lib/calabash-cucumber/utils/logging.rb +97 -0
  24. data/lib/calabash-cucumber/utils/plist_buddy.rb +178 -0
  25. data/lib/calabash-cucumber/utils/simulator_accessibility.rb +250 -0
  26. data/lib/calabash-cucumber/utils/xctools.rb +95 -0
  27. data/lib/calabash-cucumber/version.rb +197 -2
  28. data/lib/calabash-cucumber/wait_helpers.rb +16 -20
  29. data/scripts/.irbrc +11 -6
  30. data/scripts/com.example.plist +0 -0
  31. data/scripts/launch.rb +1 -1
  32. data/spec/bin/calabash_ios_sim_spec.rb +24 -0
  33. data/spec/launcher_spec.rb +76 -0
  34. data/spec/logging_spec.rb +38 -0
  35. data/spec/plist_buddy_spec.rb +99 -0
  36. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Default-568h@2x.png +0 -0
  37. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist +0 -0
  38. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal +0 -0
  39. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/PkgInfo +1 -0
  40. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/InfoPlist.strings +0 -0
  41. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController.nib +0 -0
  42. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController~ipad.nib +0 -0
  43. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController.nib +0 -0
  44. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController~ipad.nib +0 -0
  45. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController.nib +0 -0
  46. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController~ipad.nib +0 -0
  47. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController.nib +0 -0
  48. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController~ipad.nib +0 -0
  49. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first.png +0 -0
  50. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first@2x.png +0 -0
  51. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second.png +0 -0
  52. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second@2x.png +0 -0
  53. data/spec/resources/plist_buddy/com.example.plist +0 -0
  54. data/spec/resources/plist_buddy/com.testing.plist +18 -0
  55. data/spec/simulator_accessibility_spec.rb +144 -0
  56. data/spec/spec_helper.rb +31 -0
  57. data/spec/xctools_spec.rb +58 -0
  58. 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