calabash-cucumber 0.18.2 → 0.19.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/bin/calabash-ios +0 -16
  3. data/bin/calabash-ios-build.rb +0 -86
  4. data/bin/calabash-ios-helpers.rb +0 -65
  5. data/bin/calabash-ios-setup.rb +5 -119
  6. data/bin/calabash-ios-sim.rb +0 -37
  7. data/bin/frank-calabash +0 -1
  8. data/doc/calabash-ios-help.txt +0 -8
  9. data/dylibs/libCalabashDyn.dylib +0 -0
  10. data/dylibs/libCalabashDynSim.dylib +0 -0
  11. data/features-skeleton/support/01_launch.rb +3 -4
  12. data/features/step_definitions/calabash_steps.rb +1 -7
  13. data/lib/calabash-cucumber.rb +1 -2
  14. data/lib/calabash-cucumber/actions/instruments_actions.rb +2 -3
  15. data/lib/calabash-cucumber/core.rb +97 -101
  16. data/lib/calabash-cucumber/device.rb +5 -118
  17. data/lib/calabash-cucumber/environment.rb +109 -5
  18. data/lib/calabash-cucumber/environment_helpers.rb +4 -66
  19. data/lib/calabash-cucumber/http/http.rb +114 -0
  20. data/lib/calabash-cucumber/http_helpers.rb +3 -1
  21. data/lib/calabash-cucumber/ipad_1x_2x.rb +5 -7
  22. data/lib/calabash-cucumber/keyboard_helpers.rb +0 -44
  23. data/lib/calabash-cucumber/launcher.rb +425 -808
  24. data/lib/calabash-cucumber/logging.rb +2 -74
  25. data/lib/calabash-cucumber/operations.rb +0 -2
  26. data/lib/calabash-cucumber/rotation_helpers.rb +2 -82
  27. data/lib/calabash-cucumber/status_bar_helpers.rb +2 -8
  28. data/lib/calabash-cucumber/store/preferences.rb +2 -1
  29. data/lib/calabash-cucumber/uia.rb +4 -9
  30. data/lib/calabash-cucumber/version.rb +2 -2
  31. data/lib/calabash-cucumber/wait_helpers.rb +0 -2
  32. data/staticlib/calabash.framework.zip +0 -0
  33. data/staticlib/libFrankCalabash.a +0 -0
  34. metadata +13 -143
  35. data/lib/calabash-cucumber/actions/playback_actions.rb +0 -109
  36. data/lib/calabash-cucumber/deprecated.rb +0 -34
  37. data/lib/calabash-cucumber/launch/simulator_helper.rb +0 -62
  38. data/lib/calabash-cucumber/launch/simulator_launcher.rb +0 -617
  39. data/lib/calabash-cucumber/playback_helpers.rb +0 -225
  40. data/lib/calabash-cucumber/resources/cell_swipe_ios4_ipad.base64 +0 -51
  41. data/lib/calabash-cucumber/resources/cell_swipe_ios4_iphone.base64 +0 -51
  42. data/lib/calabash-cucumber/resources/cell_swipe_ios5_ipad.base64 +0 -74
  43. data/lib/calabash-cucumber/resources/cell_swipe_ios5_iphone.base64 +0 -74
  44. data/lib/calabash-cucumber/resources/double_tap_ios5_ipad.base64 +0 -15
  45. data/lib/calabash-cucumber/resources/double_tap_ios5_iphone.base64 +0 -15
  46. data/lib/calabash-cucumber/resources/double_tap_ios6_ipad.base64 +0 -22
  47. data/lib/calabash-cucumber/resources/double_tap_ios6_iphone.base64 +0 -22
  48. data/lib/calabash-cucumber/resources/pan_ios5_ipad.base64 +0 -199
  49. data/lib/calabash-cucumber/resources/pan_ios5_iphone.base64 +0 -199
  50. data/lib/calabash-cucumber/resources/pan_ios6_ipad.base64 +0 -206
  51. data/lib/calabash-cucumber/resources/pan_ios6_iphone.base64 +0 -206
  52. data/lib/calabash-cucumber/resources/pinch_in_ios4_ipad.base64 +0 -104
  53. data/lib/calabash-cucumber/resources/pinch_in_ios4_iphone.base64 +0 -104
  54. data/lib/calabash-cucumber/resources/pinch_in_ios5_ipad.base64 +0 -144
  55. data/lib/calabash-cucumber/resources/pinch_in_ios5_iphone.base64 +0 -144
  56. data/lib/calabash-cucumber/resources/pinch_in_ios6_ipad.base64 +0 -70
  57. data/lib/calabash-cucumber/resources/pinch_in_ios6_iphone.base64 +0 -70
  58. data/lib/calabash-cucumber/resources/pinch_out_ios5_ipad.base64 +0 -207
  59. data/lib/calabash-cucumber/resources/pinch_out_ios5_iphone.base64 +0 -207
  60. data/lib/calabash-cucumber/resources/pinch_out_ios6_ipad.base64 +0 -96
  61. data/lib/calabash-cucumber/resources/pinch_out_ios6_iphone.base64 +0 -96
  62. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_ipad.base64 +0 -2
  63. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_iphone.base64 +0 -2
  64. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_ipad.base64 +0 -2
  65. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_iphone.base64 +0 -2
  66. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_ipad.base64 +0 -2
  67. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_iphone.base64 +0 -2
  68. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_ipad.base64 +0 -2
  69. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_iphone.base64 +0 -2
  70. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_ipad.base64 +0 -2
  71. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_iphone.base64 +0 -2
  72. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_ipad.base64 +0 -2
  73. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_iphone.base64 +0 -2
  74. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_ipad.base64 +0 -2
  75. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_iphone.base64 +0 -2
  76. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_ipad.base64 +0 -2
  77. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_iphone.base64 +0 -2
  78. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_ipad.base64 +0 -2
  79. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_iphone.base64 +0 -2
  80. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_ipad.base64 +0 -2
  81. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_iphone.base64 +0 -2
  82. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_ipad.base64 +0 -2
  83. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_iphone.base64 +0 -2
  84. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_ipad.base64 +0 -2
  85. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_iphone.base64 +0 -2
  86. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_ipad.base64 +0 -2
  87. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_iphone.base64 +0 -2
  88. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_ipad.base64 +0 -2
  89. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_iphone.base64 +0 -2
  90. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_ipad.base64 +0 -2
  91. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_iphone.base64 +0 -2
  92. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_ipad.base64 +0 -2
  93. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_iphone.base64 +0 -2
  94. data/lib/calabash-cucumber/resources/swipe_down_ios5_ipad.base64 +0 -18
  95. data/lib/calabash-cucumber/resources/swipe_down_ios5_iphone.base64 +0 -31
  96. data/lib/calabash-cucumber/resources/swipe_down_ios6_ipad.base64 +0 -25
  97. data/lib/calabash-cucumber/resources/swipe_down_ios6_iphone.base64 +0 -25
  98. data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_ipad.base64 +0 -15
  99. data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_iphone.base64 +0 -15
  100. data/lib/calabash-cucumber/resources/swipe_left_ios4_ipad.base64 +0 -18
  101. data/lib/calabash-cucumber/resources/swipe_left_ios4_iphone.base64 +0 -18
  102. data/lib/calabash-cucumber/resources/swipe_left_ios5_ipad.base64 +0 -17
  103. data/lib/calabash-cucumber/resources/swipe_left_ios5_iphone.base64 +0 -34
  104. data/lib/calabash-cucumber/resources/swipe_left_ios6_ipad.base64 +0 -28
  105. data/lib/calabash-cucumber/resources/swipe_left_ios6_iphone.base64 +0 -28
  106. data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_ipad.base64 +0 -17
  107. data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_iphone.base64 +0 -17
  108. data/lib/calabash-cucumber/resources/swipe_right_ios4_ipad.base64 +0 -13
  109. data/lib/calabash-cucumber/resources/swipe_right_ios4_iphone.base64 +0 -13
  110. data/lib/calabash-cucumber/resources/swipe_right_ios5_ipad.base64 +0 -17
  111. data/lib/calabash-cucumber/resources/swipe_right_ios5_iphone.base64 +0 -17
  112. data/lib/calabash-cucumber/resources/swipe_right_ios6_ipad.base64 +0 -25
  113. data/lib/calabash-cucumber/resources/swipe_right_ios6_iphone.base64 +0 -25
  114. data/lib/calabash-cucumber/resources/swipe_up_ios5_ipad.base64 +0 -34
  115. data/lib/calabash-cucumber/resources/swipe_up_ios5_iphone.base64 +0 -28
  116. data/lib/calabash-cucumber/resources/swipe_up_ios6_ipad.base64 +0 -25
  117. data/lib/calabash-cucumber/resources/swipe_up_ios6_iphone.base64 +0 -25
  118. data/lib/calabash-cucumber/resources/touch_done_ios4_ipad.base64 +0 -7
  119. data/lib/calabash-cucumber/resources/touch_done_ios4_iphone.base64 +0 -9
  120. data/lib/calabash-cucumber/resources/touch_done_ios5_ipad.base64 +0 -7
  121. data/lib/calabash-cucumber/resources/touch_done_ios5_iphone.base64 +0 -9
  122. data/lib/calabash-cucumber/resources/touch_hold_ios5_ipad.base64 +0 -9
  123. data/lib/calabash-cucumber/resources/touch_hold_ios5_iphone.base64 +0 -9
  124. data/lib/calabash-cucumber/resources/touch_hold_ios6_ipad.base64 +0 -9
  125. data/lib/calabash-cucumber/resources/touch_hold_ios6_iphone.base64 +0 -9
  126. data/lib/calabash-cucumber/resources/touch_ios4_ipad.base64 +0 -9
  127. data/lib/calabash-cucumber/resources/touch_ios4_iphone.base64 +0 -9
  128. data/lib/calabash-cucumber/resources/touch_ios5_ipad.base64 +0 -9
  129. data/lib/calabash-cucumber/resources/touch_ios5_iphone.base64 +0 -9
  130. data/lib/calabash-cucumber/resources/touch_ios7_ipad.base64 +0 -9
  131. data/lib/calabash-cucumber/resources/touch_ios7_iphone.base64 +0 -9
  132. data/lib/calabash-cucumber/resources/wheel_down_ios4_ipad.base64 +0 -159
  133. data/lib/calabash-cucumber/resources/wheel_down_ios4_iphone.base64 +0 -159
  134. data/lib/calabash-cucumber/resources/wheel_down_ios5_ipad.base64 +0 -156
  135. data/lib/calabash-cucumber/resources/wheel_down_ios5_iphone.base64 +0 -156
  136. data/lib/calabash-cucumber/resources/wheel_up_ios4_ipad.base64 +0 -166
  137. data/lib/calabash-cucumber/resources/wheel_up_ios4_iphone.base64 +0 -166
  138. data/lib/calabash-cucumber/resources/wheel_up_ios5_ipad.base64 +0 -156
  139. data/lib/calabash-cucumber/resources/wheel_up_ios5_iphone.base64 +0 -156
  140. data/lib/calabash-cucumber/utils/logging.rb +0 -111
  141. data/lib/calabash-cucumber/utils/plist_buddy.rb +0 -45
  142. data/lib/calabash-cucumber/utils/simulator_accessibility.rb +0 -334
  143. data/lib/calabash-cucumber/utils/xctools.rb +0 -101
  144. data/scripts/.irbrc +0 -64
  145. data/scripts/launch.rb +0 -48
@@ -1,896 +1,513 @@
1
- require 'calabash-cucumber/launch/simulator_launcher'
2
- require 'calabash-cucumber/utils/simulator_accessibility'
3
- require 'sim_launcher'
4
- require 'calabash-cucumber/device'
5
- require 'calabash-cucumber/actions/instruments_actions'
6
- require 'calabash-cucumber/actions/playback_actions'
7
- require 'run_loop'
8
- require 'cfpropertylist'
9
- require 'calabash-cucumber/utils/logging'
10
- require "calabash-cucumber/usage_tracker"
11
-
12
- # Used to launch apps for testing in iOS Simulator or on iOS Devices. By default
13
- # it uses Apple's `instruments` process to launch your app, but has legacy support
14
- # for using `sim_launcher`.
15
- #
16
- # ### Accessing the current launcher from ruby.
17
- #
18
- # If you need a reference to the current launcher in your ruby code.
19
- # This is usually not required, but might be useful in `support/01_launch.rb`.
20
- #
21
- # `Calabash::Cucumber::Launcher.launcher`
22
- #
23
- # ### Attaching to the current launcher in a console
24
- #
25
- # If Calabash already running and you want to attach to the current launcher,
26
- # use `console_attach`. This is useful when a cucumber Scenario has failed and
27
- # you want to query the current state of the app.
28
- #
29
- # * **Pro Tip:** set the `NO_STOP` environmental variable to 1 so calabash does
30
- # not exit the simulator when a Scenario fails.
31
- class Calabash::Cucumber::Launcher
32
-
33
- require "calabash-cucumber/dylibs"
34
- require "calabash-cucumber/environment"
35
-
36
- include Calabash::Cucumber::Logging
37
- include Calabash::Cucumber::SimulatorAccessibility
38
-
39
- # noinspection RubyClassVariableUsageInspection
40
-
41
- # @!visibility private
42
- @@launcher = nil
43
-
44
- # @!visibility private
45
- SERVER_VERSION_NOT_AVAILABLE = '0.0.0'
46
- # noinspection RubyClassVariableUsageInspection
47
-
48
- # @!visibility private
49
- # Class variable for caching the embedded server version so we only need to
50
- # check the server version one time.
51
- @@server_version = nil
52
-
53
- attr_accessor :run_loop
54
- attr_accessor :device
55
- attr_accessor :actions
56
- attr_accessor :launch_args
57
- attr_accessor :simulator_launcher
58
- attr_reader :xcode
59
- attr_reader :usage_tracker
60
-
61
- # @!visibility private
62
- # Generated when calabash cannot launch the app.
63
- class StartError < RuntimeError
64
- attr_accessor :error
65
-
66
- def initialize(err)
67
- self.error= err
68
- end
1
+ module Calabash
2
+ module Cucumber
69
3
 
70
- # @!visibility private
71
- def to_s
72
- "#{super.to_s}: #{error}"
73
- end
74
- end
4
+ # Raised when calabash cannot launch the app.
5
+ class LaunchError < RuntimeError
6
+ attr_accessor :error
75
7
 
76
- # @!visibility private
77
- # Generated when calabash cannot communicate with the app.
78
- class CalabashLauncherTimeoutErr < Timeout::Error
79
- end
8
+ def initialize(err)
9
+ self.error= err
10
+ end
80
11
 
81
- def xcode
82
- @xcode ||= RunLoop::Xcode.new
83
- end
12
+ # @!visibility private
13
+ def to_s
14
+ "#{super.to_s}: #{error}"
15
+ end
16
+ end
84
17
 
85
- def usage_tracker
86
- @usage_tracker ||= Calabash::Cucumber::UsageTracker.new
87
- end
18
+ # Raised when Calabash cannot find a device based on DEVICE_TARGET
19
+ class DeviceNotFoundError < RuntimeError ; end
20
+
21
+ # Launch apps on iOS Simulators and physical devices.
22
+ #
23
+ # ### Accessing the current launcher from ruby.
24
+ #
25
+ # If you need a reference to the current launcher in your ruby code.
26
+ #
27
+ # `Calabash::Cucumber::Launcher.launcher`
28
+ #
29
+ # This is usually not required, but might be useful in `support/01_launch.rb`.
30
+ #
31
+ # ### Attaching to the current launcher in a console
32
+ #
33
+ # If Calabash already running and you want to attach to the current launcher,
34
+ # use `console_attach`. This is useful when a cucumber Scenario has failed and
35
+ # you want to query the current state of the app.
36
+ #
37
+ # * **Pro Tip:** Set the `QUIT_APP_AFTER_SCENARIO=0` env variable so calabash
38
+ # does not quit your application after a failed Scenario.
39
+ class Launcher
40
+
41
+ require "calabash-cucumber/device"
42
+ require "calabash-cucumber/actions/instruments_actions"
43
+ require "calabash-cucumber/usage_tracker"
44
+ require "calabash-cucumber/dylibs"
45
+ require "calabash-cucumber/environment"
46
+ require "calabash-cucumber/http/http"
47
+ require "run_loop"
48
+
49
+ # @!visibility private
50
+ DEFAULTS = {
51
+ :launch_retries => 5
52
+ }
88
53
 
89
- # @!visibility private
90
- def initialize
91
- @simulator_launcher = Calabash::Cucumber::SimulatorLauncher.new
92
- @@launcher = self
93
- end
54
+ # @!visibility private
55
+ @@launcher = nil
94
56
 
95
- # @!visibility private
96
- def actions
97
- attach if @actions.nil?
98
- @actions
99
- end
57
+ # @!visibility private
58
+ @@launcher = nil
100
59
 
101
- # @see Calabash::Cucumber::Core#console_attach
102
- def self.attach
103
- l = launcher
104
- return l if l && l.active?
105
- l.attach
106
- end
60
+ # @!visibility private
61
+ attr_accessor :run_loop
107
62
 
108
- # @see Calabash::Cucumber::Core#console_attach
109
- def attach(options={})
110
- default_options = {:max_retry => 1,
111
- :timeout => 10}
112
- merged_options = default_options.merge(options)
63
+ # @!visibility private
64
+ attr_accessor :actions
113
65
 
114
- if calabash_no_launch?
115
- self.actions = Calabash::Cucumber::PlaybackActions.new
116
- return
117
- end
66
+ # @!visibility private
67
+ attr_accessor :launch_args
118
68
 
119
- self.run_loop = RunLoop::HostCache.default.read
69
+ # @!visibility private
70
+ attr_reader :usage_tracker
120
71
 
121
- # Sets the device attribute.
122
- ensure_connectivity(merged_options[:max_retry], merged_options[:timeout])
72
+ # @!visibility private
73
+ def initialize
74
+ @@launcher = self
75
+ end
123
76
 
124
- if self.run_loop[:pid]
125
- self.actions = Calabash::Cucumber::InstrumentsActions.new
126
- else
127
- self.actions = Calabash::Cucumber::PlaybackActions.new
128
- end
77
+ # @!visibility private
78
+ def to_s
79
+ msg = ["#{self.class}"]
80
+ if self.run_loop
81
+ msg << "Log file: #{self.run_loop[:log_file]}"
82
+ else
83
+ msg << "Not attached to instruments."
84
+ msg << "Start your app with `start_test_server_in_background`"
85
+ msg << "If you app is already running, try `console_attach`"
86
+ end
87
+ msg.join("\n")
88
+ end
129
89
 
130
- major = self.device.ios_major_version
131
- if major.to_i >= 7 && self.actions.is_a?(Calabash::Cucumber::PlaybackActions)
132
- puts %Q{
90
+ # @!visibility private
91
+ def inspect
92
+ to_s
93
+ end
133
94
 
134
- WARNING
95
+ # @!visibility private
96
+ #
97
+ # Use this method to see if your app is already running. This is helpful
98
+ # if you have Scenarios that don't require an app relaunch.
99
+ #
100
+ # @raise Raises an error if the server does not respond.
101
+ def ping_app
102
+ Calabash::Cucumber::HTTP.ping_app
103
+ end
135
104
 
136
- Connected to simulator that was not launched by Calabash.
105
+ # @!visibility private
106
+ #
107
+ # This Calabash::Cucumber::Device instance is required because we cannot
108
+ # determine the iOS version of physical devices.
109
+ #
110
+ # This device instance can only be created _if the server is running_.
111
+ #
112
+ # We need this instance because we need to know at runtime whether or
113
+ # not to translate touch coordinates in the client or on the server. For
114
+ # iOS >= 8.0 translation is done on the server. Further, we need a
115
+ # Device instance for iOS < 8 so we can perform the necessary
116
+ # coordinate normalization - based on the device attributes.
117
+ #
118
+ # We also need this instance to determine the default uia strategy.
119
+ #
120
+ # +1 for tools to ask physical devices about attributes.
121
+ def device
122
+ @device ||= lambda do
123
+ _, body = Calabash::Cucumber::HTTP.ensure_connectivity
124
+ endpoint = Calabash::Cucumber::Environment.device_endpoint
125
+ Calabash::Cucumber::Device.new(endpoint, body)
126
+ end.call
127
+ end
137
128
 
138
- Queries will work, but gestures will not.
129
+ # @!visibility private
130
+ #
131
+ # Legacy API. This is a required method. Do not remove
132
+ def device=(new_device)
133
+ @device = new_device
134
+ end
139
135
 
140
- }
141
- end
142
- self
143
- end
136
+ # @!visibility private
137
+ def usage_tracker
138
+ @usage_tracker ||= Calabash::Cucumber::UsageTracker.new
139
+ end
144
140
 
145
- # Are we running using instruments?
146
- #
147
- # @return {Boolean} true if we're using instruments to launch
148
- def self.instruments?
149
- l = launcher_if_used
150
- return false unless l
151
- l.instruments?
152
- end
141
+ # @!visibility private
142
+ def actions
143
+ attach if @actions.nil?
144
+ @actions
145
+ end
153
146
 
154
- # Get a reference to the current launcher (instantiates a new one if needed). Usually we use a singleton launcher throughout a test run.
155
- # @return {Calabash::Cucumber::Launcher} the current launcher
156
- def self.launcher
157
- @@launcher ||= Calabash::Cucumber::Launcher.new
158
- end
147
+ # @!visibility private
148
+ # @see Calabash::Cucumber::Core#console_attach
149
+ def self.attach
150
+ l = launcher
151
+ return l if l && l.active?
152
+ l.attach
153
+ end
159
154
 
160
- # Get a reference to the current launcher (does not instantiate a new one if unset).
161
- # Usually we use a singleton launcher throughout a test run.
162
- # @return {Calabash::Cucumber::Launcher} the current launcher or nil
163
- def self.launcher_if_used
164
- @@launcher
165
- end
155
+ # @!visibility private
156
+ # @see Calabash::Cucumber::Core#console_attach
157
+ def attach(options={})
158
+ if Calabash::Cucumber::Environment.xtc?
159
+ raise "This method is not available on the Xamarin Test Cloud"
160
+ end
166
161
 
167
- # "Major" component of the current iOS version of the device
168
- # @return {String} the "major" component, e.g., "7" for "7.1.1"
169
- def ios_major_version
170
- # pinging the app will set self.device
171
- ping_app if self.device.nil?
172
- # guard against Runtime errors
173
- return nil if device.nil? or device.ios_version.nil?
174
- device.ios_major_version
175
- end
162
+ default_options = {:http_connection_retry => 1,
163
+ :http_connection_timeout => 10}
164
+ merged_options = default_options.merge(options)
176
165
 
177
- # the current iOS version of the device
178
- # @return {String} the current iOS version of the device
179
- def ios_version
180
- return nil if device.nil?
181
- device.ios_version
182
- end
166
+ self.run_loop = RunLoop::HostCache.default.read
183
167
 
184
- # @deprecated 0.10.0 Replaced with {#reset_app_sandbox}.
185
- # Reset the app sandbox for a device.
186
- def reset_app_jail(sdk=nil, path=nil)
187
- # will be deprecated in a future version
188
- #_deprecated('0.10.0', 'use reset_app_sandbox instead', :warn)
189
- reset_app_sandbox({:sdk => sdk, :path => path})
190
- end
168
+ begin
169
+ Calabash::Cucumber::HTTP.ensure_connectivity(merged_options)
170
+ rescue Calabash::Cucumber::ServerNotRespondingError => _
171
+ device_endpoint = Calabash::Cucumber::Environment.device_endpoint
172
+ RunLoop.log_warn(
173
+ %Q[
191
174
 
192
- # Resets the app's content and settings by deleting the following directories
193
- # from application sandbox:
194
- #
195
- # * Library
196
- # * Documents
197
- # * tmp
198
- #
199
- # @note It is not recommended that you call this method directly. See the
200
- # examples below for how use the `RESET_BETWEEN_SCENARIOS` environmental
201
- # variable to reset the app sandbox.
202
- #
203
- # @note This method is only available for the iOS Simulator.
204
- #
205
- # @note Generates a warning if called when targeting a physical device and
206
- # otherwise has no effect.
207
- #
208
- # @note When testing against the Xamarin Test Cloud, this method is never
209
- # called. Use the `RESET_BETWEEN_SCENARIOS` environmental variable.
210
- # See the examples.
211
- #
212
- # @example Use `RESET_BETWEEN_SCENARIOS` to reset the app sandbox before every Scenario.
213
- # When testing devices outside the Xamarin Test Cloud this has no effect.
214
- #
215
- # On the Xamarin Test Cloud, the app sandbox will be reset, but this method
216
- # will not be called; the resetting is done via an alternative mechanism.
217
- #
218
- # When testing simulators, this method will be called.
219
- #
220
- # Launch cucumber with RESET_BETWEEN_SCENARIOS=1
221
- #
222
- # $ RESET_BETWEEN_SCENARIOS=1 bundle exec cucumber
223
- #
224
- # @example Use tags and a Before hook to reset the app sandbox before specific Scenarios.
225
- # # in your .feature file
226
- #
227
- # @reset_app_before_hook
228
- # Scenario: some scenario that requires the app be reset
229
- #
230
- # # in your support/01_launch.rb file
231
- # #
232
- # # 1. add a Before hook
233
- # Before('@reset_app_before_hook') do
234
- # ENV['RESET_BETWEEN_SCENARIOS'] = '1'
235
- # end
236
- #
237
- # # 2. after launching, revert the env var value
238
- # Before do |scenario|
239
- # # launch the app
240
- # launcher = Calabash::Cucumber::Launcher.new
241
- # unless launcher.calabash_no_launch?
242
- # launcher.relaunch
243
- # launcher.calabash_notify(self)
244
- # end
245
- # # disable resetting between Scenarios
246
- # ENV['RESET_BETWEEN_SCENARIOS'] = ''
247
- # end
248
- #
249
- # @param [Hash] opts can pass the target sdk or the path to the application bundle
250
- # @option opts [String, Symbol] :sdk (nil) The target sdk. If nil is
251
- # passed, then only app sandbox for the latest sdk will be deleted. If
252
- # `:all` is passed, then the sandboxes for all sdks will be deleted.
253
- # @option opts [String] :path (nil) path to the application bundle
254
- def reset_app_sandbox(opts={})
255
- calabash_warn(%Q{
256
- Starting in Calabash 0.17.0, this method does nothing.
257
-
258
- You can still control whether or not your app's sandbox is
259
- reset between Scenarios using RESET_BETWEEN_SCENARIOS=1 or
260
- by passing :reset => true as a launch option.
261
-
262
- options = {
263
- :reset => true
264
- }
175
+ Could not connect to Calabash Server @ #{device_endpoint}.
265
176
 
266
- launcher.relaunch(options)
177
+ If your app is running, check that you have set the DEVICE_ENDPOINT correctly.
267
178
 
268
- Please do not ignore this message.
179
+ If your app is not running, it was a mistake to call this method.
269
180
 
270
- Remove direct calls to reset_app_sandbox.
181
+ http://calabashapi.xamarin.com/ios/Calabash/Cucumber/Core.html#console_attach-instance_method
271
182
 
272
- })
273
- end
183
+ Try `start_test_server_in_background`
274
184
 
275
- # Erases a simulator. This is the same as touching the Simulator
276
- # "Reset Content & Settings" menu item.
277
- #
278
- # @param [RunLoop::Device, String] The simulator to erase. Can be a device
279
- # instance, a simulator UUID, or a human readable simulator name.
280
- #
281
- # @raise ArgumentError If the simulator is a physical device
282
- # @raise RuntimeError If the simulator cannot be shutdown
283
- # @raise RuntimeError If the simulator cannot be erased
284
- def reset_simulator(device=nil)
285
- if device_target?
286
- raise ArgumentError, "Resetting physical devices is not supported."
287
- end
185
+ ])
288
186
 
289
- simulator = nil
187
+ # Nothing to do except log the problem and exit early.
188
+ return false
189
+ end
290
190
 
291
- if device.nil? || device == ""
292
- device_target = Calabash::Cucumber::Environment.device_target
293
- if device_target.nil?
294
- default_simulator = RunLoop::Core.default_simulator
295
- simulator = RunLoop::Device.device_with_identifier(default_simulator)
296
- else
297
- simulator = RunLoop::Device.device_with_identifier(device_target)
298
- end
299
- elsif device.is_a?(RunLoop::Device)
300
- if device.physical_device?
301
- raise ArgumentError,
302
- %Q{
303
- Cannot reset: #{device}.
191
+ if self.run_loop[:pid]
192
+ self.actions = Calabash::Cucumber::InstrumentsActions.new
193
+ else
194
+ RunLoop.log_warn(
195
+ %Q[
304
196
 
305
- Resetting physical devices is not supported.
306
- }
307
- end
308
- simulator = device
309
- else
310
- simulator = RunLoop::Device.device_with_identifier(device)
311
- end
197
+ Connected to an app that was not launched by Calabash using instruments.
312
198
 
313
- RunLoop::CoreSimulator.erase(simulator)
314
- simulator
315
- end
199
+ Queries will work, but gestures will not.
316
200
 
317
- # @!visibility private
318
- def default_launch_args
319
- # APP_BUNDLE_PATH
320
- # BUNDLE_ID
321
- # APP (unifies APP_BUNDLE_PATH, BUNDLE_ID)
322
- # DEVICE_TARGET
323
- # SDK_VERSION
324
- # RESET_BETWEEN_SCENARIOS
325
- # DEVICE
326
- # NO_LAUNCH
327
- # NO_STOP
328
-
329
- args = {
330
- :launch_method => default_launch_method,
331
- :reset => reset_between_scenarios?,
332
- :bundle_id => ENV['BUNDLE_ID'],
333
- :no_stop => calabash_no_stop?,
334
- :no_launch => calabash_no_launch?,
335
- :sdk_version => sdk_version,
336
- :relaunch_simulator => true,
337
- # Do not advertise this to users!
338
- # For example, don't include documentation about this option.
339
- # This is used to instrument internal testing (failing fast).
340
- :launch_retries => 5
341
- }
342
-
343
- device_tgt = ENV['DEVICE_TARGET']
344
- if run_with_instruments?(args)
345
- if simulator_target?
346
- args[:device_target] = device_tgt
347
- args[:udid] = nil
348
- else
349
- if detect_connected_device? && (device_tgt.nil? || device_tgt.downcase == 'device')
350
- device_tgt = RunLoop::Core.detect_connected_device
201
+ ])
351
202
  end
352
203
 
353
- if device_tgt
354
- args[:device_target] = args[:udid] = device_tgt
355
- end
204
+ self
356
205
  end
357
- end
358
-
359
- if args[:device_target].nil?
360
- args[:device_target] = device_tgt || 'simulator'
361
- end
362
- args
363
- end
364
206
 
365
- # @!visibility private
366
- def detect_connected_device?
367
- if ENV['DETECT_CONNECTED_DEVICE'] == '1'
368
- return true
369
- end
370
-
371
- if ENV['BUNDLE_ID'].nil? && ENV['DETECT_CONNECTED_DEVICE'].nil?
372
- return false
373
- end
374
- if ENV['BUNDLE_ID'] && ENV['DETECT_CONNECTED_DEVICE'].nil?
375
- return true
376
- end
377
- if ENV['DETECT_CONNECTED_DEVICE']
378
- return ENV['DETECT_CONNECTED_DEVICE'] != '0'
379
- end
380
-
381
- return false
382
- end
383
-
384
- # @!visibility private
385
- def default_launch_method
386
- sdk = sdk_version
387
- major = nil
388
- if sdk && !sdk.strip.empty?
389
- major = sdk.split('.')[0]
390
- begin
391
- major = major.to_i
392
- rescue
393
- calabash_warn("SDK_VERSION invalid #{sdk_version} - ignoring...")
207
+ # Are we running using instruments?
208
+ #
209
+ # @return {Boolean} true if we're using instruments to launch
210
+ def self.instruments?
211
+ l = launcher_if_used
212
+ return false unless l
213
+ l.instruments?
394
214
  end
395
- end
396
- return :instruments if major && major >= 7 # Only instruments supported for iOS7+
397
- return :sim_launcher if major # and then we have <= 6
398
-
399
- if RunLoop::Xcode.new.version_gte_51?
400
- return use_sim_launcher_env? ? :sim_launcher : :instruments
401
- end
402
215
 
403
- available = self.simulator_launcher.sdk_detector.available_sdk_versions.reject { |v| v.start_with?('7') }
404
- if available.include?(sdk_version)
405
- :sim_launcher
406
- else
407
- :instruments
408
- end
409
- end
410
-
411
- # Launches your app on the connected device or simulator.
412
- #
413
- # `relaunch` does a lot of error detection and handling to reliably start the
414
- # app and test. Instruments (particularly the cli) has stability issues which
415
- # we workaround by restarting the simulator process and checking that
416
- # UIAutomation is correctly attaching to your application.
417
- #
418
- # Use the `args` parameter to to control:
419
- #
420
- # * `:app` - which app to launch.
421
- # * `:device_target` - simulator or device to target.
422
- # * `:reset_app_sandbox - reset he app's data (sandbox) before testing
423
- #
424
- # and many other behaviors.
425
- #
426
- # Many of these behaviors can be be controlled by environment variables. The
427
- # most important environment variables are `APP`, `DEVICE_TARGET`, and
428
- # `DEVICE_ENDPOINT`.
429
- #
430
- # @param {Hash} args optional arguments to control the how the app is launched
431
- def relaunch(args={})
432
-
433
- # @todo Don't overwrite the _args_ parameter!
434
- args = default_launch_args.merge(args)
435
-
436
- # RunLoop::Core.run_with_options can reuse the SimControl instance. Many
437
- # of the Xcode tool calls, like instruments -s templates, take a long time
438
- # to execute.
439
- # @todo Use SimControl in Launcher in place of methods like simulator_target?
440
- args[:sim_control] = RunLoop::SimControl.new
441
- args[:instruments] = RunLoop::Instruments.new
442
- args[:xcode] = xcode
443
-
444
- if args[:app]
445
- if !File.exist?(args[:app])
446
- raise "Unable to find app bundle at #{args[:app]}. It should be an iOS Simulator build (typically a *.app directory)."
216
+ # @!visibility private
217
+ def instruments?
218
+ !!(active? && run_loop[:pid])
447
219
  end
448
- end
449
220
 
450
- # User passed {:app => "path/to/my.app"} _and_ it exists.
451
- # User defined BUNDLE_ID or passed {:bundle_id => com.example.myapp}
452
- # User defined APP or APP_BUNDLE_PATH env vars _or_ APP_BUNDLE_PATH constant.
453
- args[:app] = args[:app] || args[:bundle_id] || app_path
454
-
455
- if args[:app]
456
- if File.directory?(args[:app])
457
- args[:app] = File.expand_path(args[:app])
458
- else
459
- # args[:app] is not a directory so must be a bundle id.
460
- if simulator_target?(args)
461
- args[:app] = app_path
462
- end
221
+ # @!visibility private
222
+ def active?
223
+ not run_loop.nil?
463
224
  end
464
- end
465
225
 
466
- # At this point :app is either nil because we are targeting a simulator
467
- # or it is a CFBundleIdentifier.
468
- if args[:app]
469
- # nothing to do because :bundle_id and :app are the same.
470
- else
471
- # User gave us no information about where the simulator app is located
472
- # so we have to auto detect it. This RunLoop method raises an error
473
- # with a meaningful message based on the environment. The message
474
- # includes suggestions about what to do next.
475
- run_loop_app = RunLoop::DetectAUT::Detect.new.app_for_simulator
476
-
477
- # This is not great - RunLoop is going to take this path and create a new
478
- # RunLoop::App. This is the best we can do for now.
479
- args[:app] = run_loop_app.path
480
- args[:bundle_id] = run_loop_app.bundle_identifier
481
- end
482
-
483
- use_dylib = args[:inject_dylib]
484
- if use_dylib
485
- # User passed a Boolean, not a file.
486
- if use_dylib.is_a?(TrueClass)
487
- if simulator_target?(args)
488
- args[:inject_dylib] = Calabash::Cucumber::Dylibs.path_to_sim_dylib
489
- else
490
- raise RuntimeError, "Injecting a dylib is not supported when targetting a device"
491
- end
492
- else
493
- unless File.exist? use_dylib
494
- raise "Dylib does not exist at path: '#{use_dylib}'"
495
- end
226
+ # A reference to the current launcher (instantiates a new one if needed).
227
+ # @return {Calabash::Cucumber::Launcher} the current launcher
228
+ def self.launcher
229
+ @@launcher ||= Calabash::Cucumber::Launcher.new
496
230
  end
497
- end
498
-
499
- if run_with_instruments?(args)
500
- # Patch for bug in Xcode 6 GM + iOS 8 device testing.
501
- # http://openradar.appspot.com/radar?id=5891145586442240
502
- uia_strategy = default_uia_strategy(args, args[:sim_control], args[:instruments])
503
- args[:uia_strategy] ||= uia_strategy
504
- calabash_info "Using uia strategy: '#{args[:uia_strategy]}'" if debug_logging?
505
-
506
- self.run_loop = new_run_loop(args)
507
- self.actions= Calabash::Cucumber::InstrumentsActions.new
508
- else
509
- # run with sim launcher
510
- self.actions= Calabash::Cucumber::PlaybackActions.new
511
- # why not just pass args - AFAICT args[:app] == app_path?
512
- self.simulator_launcher.relaunch(app_path, sdk_version(), args)
513
- end
514
- self.launch_args = args
515
231
 
516
- unless args[:calabash_lite]
517
- ensure_connectivity
518
- # skip compatibility check if injecting dylib
519
- unless args.fetch(:inject_dylib, false)
520
- check_server_gem_compatibility
232
+ # Get a reference to the current launcher (does not instantiate a new one if unset).
233
+ # @return {Calabash::Cucumber::Launcher} the current launcher or nil
234
+ def self.launcher_if_used
235
+ @@launcher
521
236
  end
522
- end
523
-
524
- usage_tracker.post_usage_async
525
- end
526
237
 
527
- # @!visibility private
528
- #
529
- # Choose the appropriate default UIA strategy based on the test target.
530
- #
531
- # This is a temporary (I hope) fix for a UIAApplication bug in
532
- # setPreferencesValueForKey on iOS 8 devices in Xcode 6 GM.
533
- #
534
- # rdar://18296714
535
- # http://openradar.appspot.com/radar?id=5891145586442240
536
- #
537
- # @param [Hash] launch_args The launch arguments.
538
- # @param [RunLoop::SimControl] sim_control Used to find simulators.
539
- # @param [RunLoop::Instruments] instruments Used to find physical devices.
540
- def default_uia_strategy(launch_args, sim_control, instruments)
541
-
542
- xcode = sim_control.xcode
543
- if xcode.version_gte_7?
544
- :host
545
- else
546
- udid_or_name = launch_args[:device_target]
547
-
548
- # Can't make a determination, so return :host because it works everywhere.
549
- return :host if udid_or_name == nil || udid_or_name == ''
550
-
551
- # The default.
552
- # No DEVICE_TARGET is set and no option was passed to relaunch.
553
- return :preferences if udid_or_name.downcase.include?('simulator')
554
-
555
- simulator = sim_control.simulators.find do |sim|
556
- sim.instruments_identifier(xcode) == udid_or_name ||
557
- sim.udid == udid_or_name
558
- end
559
-
560
- return :preferences if simulator
561
-
562
- physical_device = instruments.physical_devices.find do |device|
563
- device.name == udid_or_name ||
564
- device.udid == udid_or_name
565
- end
566
-
567
- if physical_device
568
- if physical_device.version < RunLoop::Version.new('8.0')
569
- :preferences
238
+ # Erases a simulator. This is the same as touching the Simulator
239
+ # "Reset Content & Settings" menu item.
240
+ #
241
+ # @param [RunLoop::Device, String] device The simulator to erase. Can be a
242
+ # RunLoop::Device instance, a simulator UUID, or a human readable simulator
243
+ # name.
244
+ #
245
+ # @raise ArgumentError If the simulator is a physical device
246
+ # @raise RuntimeError If the simulator cannot be shutdown
247
+ # @raise RuntimeError If the simulator cannot be erased
248
+ def reset_simulator(device=nil)
249
+ if device.is_a?(RunLoop::Device)
250
+ device_target = device
570
251
  else
571
- :host
252
+ device_target = detect_device(:device => device)
572
253
  end
573
- else
574
- # Return host because it works everywhere.
575
- :host
576
- end
577
- end
578
- end
579
-
580
- # @!visibility private
581
- def new_run_loop(args)
582
254
 
583
- last_err = nil
255
+ if device_target.physical_device?
256
+ raise ArgumentError,
257
+ %Q{
258
+ Cannot reset: #{device_target}.
584
259
 
585
- num_retries = args[:launch_retries] || 5
260
+ Resetting physical devices is not supported.
261
+ }
262
+ end
586
263
 
587
- num_retries.times do
588
- begin
589
- return RunLoop.run(args)
590
- rescue RunLoop::TimeoutError => e
591
- last_err = e
264
+ RunLoop::CoreSimulator.erase(device_target)
265
+ device_target
592
266
  end
593
- end
594
-
595
- if simulator_target?(args)
596
- puts "Unable to launch app on Simulator."
597
- else
598
- puts "Unable to launch app on physical device"
599
- end
600
- raise StartError.new(last_err)
601
- end
602
267
 
603
- # @!visibility private
604
- def ensure_connectivity(max_retry=10, timeout=30)
605
- begin
606
- max_retry_count = (ENV['MAX_CONNECT_RETRY'] || max_retry).to_i
607
- timeout = (ENV['CONNECT_TIMEOUT'] || timeout).to_i
608
- retry_count = 0
609
- connected = false
610
- if full_console_logging?
611
- puts 'Waiting for App to be ready'
612
- end
613
- until connected do
614
- if retry_count == max_retry_count
615
- raise "Timed out connecting to Calabash server after #{max_retry_count} retries. Make sure it is linked and App isn't crashing"
616
- end
617
- retry_count += 1
618
- begin
619
- Timeout::timeout(timeout, CalabashLauncherTimeoutErr) do
620
- until connected
621
- begin
622
- connected = (ping_app == '200')
623
- break if connected
624
- rescue StandardError => e
625
- if full_console_logging?
626
- puts "Could not connect. #{e.message}"
627
- puts "Will retry ..."
628
- end
629
- ensure
630
- sleep 1 unless connected
631
- end
632
- end
633
- end
634
- rescue CalabashLauncherTimeoutErr => e
635
- if full_console_logging?
636
- puts "Timed out after #{timeout} secs, trying to connect to Calabash server..."
637
- puts "Will retry #{max_retry_count - retry_count}"
638
- end
268
+ # Launches your app on the connected device or simulator.
269
+ #
270
+ # `relaunch` does a lot of error detection and handling to reliably start the
271
+ # app and test. Instruments (particularly the cli) has stability issues which
272
+ # we workaround by restarting the simulator process and checking that
273
+ # UIAutomation is correctly attaching to your application.
274
+ #
275
+ # Use the `args` parameter to to control:
276
+ #
277
+ # * `:app` - which app to launch.
278
+ # * `:device` - simulator or device to target.
279
+ # * `:reset_app_sandbox - reset the app's data (sandbox) before testing
280
+ #
281
+ # and many other behaviors.
282
+ #
283
+ # Many of these behaviors can be be controlled by environment variables. The
284
+ # most important environment variables are `APP`, `DEVICE_TARGET`, and
285
+ # `DEVICE_ENDPOINT`.
286
+ #
287
+ # @param {Hash} launch_options optional arguments to control the how the app is launched
288
+ def relaunch(launch_options={})
289
+ simctl = launch_options[:simctl] || launch_options[:sim_control]
290
+ instruments = launch_options[:instruments]
291
+ xcode = launch_options[:xcode]
292
+
293
+ options = launch_options.clone
294
+
295
+ # Reusing SimControl, Instruments, and Xcode can speed up launches.
296
+ options[:simctl] = simctl || Calabash::Cucumber::Environment.simctl
297
+ options[:instruments] = instruments || Calabash::Cucumber::Environment.instruments
298
+ options[:xcode] = xcode || Calabash::Cucumber::Environment.xcode
299
+
300
+ self.launch_args = options
301
+
302
+ self.run_loop = new_run_loop(options)
303
+ self.actions= Calabash::Cucumber::InstrumentsActions.new
304
+
305
+ if !options[:calabash_lite]
306
+ Calabash::Cucumber::HTTP.ensure_connectivity
307
+ check_server_gem_compatibility
639
308
  end
640
- end
641
- rescue RuntimeError => e
642
- p e
643
- msg = "Unable to make connection to Calabash Server at #{ENV['DEVICE_ENDPOINT']|| "http://localhost:37265/"}\n"
644
- msg << "Make sure you don't have a firewall blocking traffic to #{ENV['DEVICE_ENDPOINT']|| "http://localhost:37265/"}.\n"
645
- raise msg
646
- end
647
- end
648
-
649
- # @!visibility private
650
- def ping_app
651
- url = URI.parse(ENV['DEVICE_ENDPOINT']|| "http://localhost:37265/")
652
-
653
- http = Net::HTTP.new(url.host, url.port)
654
- res = http.start do |sess|
655
- sess.request Net::HTTP::Get.new(ENV['CALABASH_VERSION_PATH'] || "version")
656
- end
657
- status = res.code
658
309
 
659
- http.finish if http and http.started?
310
+ usage_tracker.post_usage_async
660
311
 
661
- if status == '200'
662
- version_body = JSON.parse(res.body)
663
- self.device = Calabash::Cucumber::Device.new(url, version_body)
664
- end
665
-
666
- status
667
- end
668
-
669
- # @!visibility private
670
- def stop
671
- RunLoop.stop(run_loop) if run_loop && run_loop[:pid]
672
- end
312
+ # :on_launch to the Cucumber World if:
313
+ # * the Launcher is part of the World (it is not by default).
314
+ # * Cucumber responds to :on_launch.
315
+ self.send(:on_launch) if self.respond_to?(:on_launch)
673
316
 
674
- # @!visibility private
675
- def calabash_notify(world)
676
- if world.respond_to?(:on_launch)
677
- world.on_launch
678
- end
679
- end
680
-
681
- # @!visibility private
682
- def calabash_no_stop?
683
- calabash_no_launch? or ENV['NO_STOP']=="1"
684
- end
685
-
686
- # @!visibility private
687
- def calabash_no_launch?
688
- ENV['NO_LAUNCH']=='1'
689
- end
690
-
691
- # @!visibility private
692
- def device_target?
693
- (ENV['DEVICE_TARGET'] != nil) && (not simulator_target?)
694
- end
695
-
696
- # @!visibility private
697
- def discover_device_target(launch_args)
698
- ENV['DEVICE_TARGET'] || launch_args[:device_target]
699
- end
700
-
701
- # @!visibility private
702
- def simulator_target?(launch_args={})
703
- udid_or_name = discover_device_target(launch_args)
704
-
705
- return false if udid_or_name.nil? || udid_or_name == ''
706
-
707
- return true if udid_or_name.downcase.include?('simulator')
708
-
709
- return false if udid_or_name[RunLoop::Regex::DEVICE_UDID_REGEX, 0] != nil
710
-
711
- if xcode.version_gte_6?
712
- sim_control = launch_args[:sim_control] || RunLoop::SimControl.new
713
- simulator = sim_control.simulators.find do |sim|
714
- sim.instruments_identifier(xcode) == udid_or_name ||
715
- sim.udid == udid_or_name
317
+ self
716
318
  end
717
319
 
718
- !simulator.nil?
719
- else
720
- false
721
- end
722
- end
723
-
724
- # @!visibility private
725
- def sdk_version
726
- ENV['SDK_VERSION']
727
- end
320
+ # @!visibility private
321
+ def new_run_loop(args)
322
+ last_err = nil
323
+ num_retries = args[:launch_retries] || DEFAULTS[:launch_retries]
324
+ num_retries.times do
325
+ begin
326
+ return RunLoop.run(args)
327
+ rescue RunLoop::TimeoutError => e
328
+ last_err = e
329
+ end
330
+ end
728
331
 
729
- # @!visibility private
730
- def sdk_version_for_simulator_target(launch_args)
731
- return nil if device_target?
732
- value = launch_args[:device_target]
733
- return nil if value.nil?
734
- return nil unless value.downcase.include?('simulator')
735
- # we have a string like:
736
- # iPhone Retina (4-inch) - Simulator - iOS 7.1
737
- # iPad Retina - Simulator - iOS 6.1
738
- # iPhone Retina (4-inch 64-bit) - Simulator - iOS 7.0
739
- sdk = value.split(' ').last
740
-
741
- # legacy support for DEVICE_TARGET=simulator
742
- return nil if sdk == 'simulator'
743
- sdk
744
- end
332
+ raise Calabash::Cucumber::LaunchError.new(last_err)
333
+ end
745
334
 
746
- # @!visibility private
747
- def use_instruments_env?
748
- ENV['LAUNCH_VIA'] == 'instruments'
749
- end
335
+ # @!visibility private
336
+ # TODO Should call calabash exit route to shutdown the server.
337
+ def stop
338
+ RunLoop.stop(run_loop) if run_loop && run_loop[:pid]
339
+ end
750
340
 
751
- # @!visibility private
752
- def use_sim_launcher_env?
753
- ENV['LAUNCH_VIA'] == 'sim_launcher'
754
- end
341
+ # Should Calabash quit the app under test after a Scenario?
342
+ #
343
+ # Control this behavior using the QUIT_APP_AFTER_SCENARIO variable.
344
+ #
345
+ # The default behavior is to quit after every Scenario.
346
+ def quit_app_after_scenario?
347
+ Calabash::Cucumber::Environment.quit_app_after_scenario?
348
+ end
755
349
 
756
- # @!visibility private
757
- def reset_between_scenarios?
758
- ENV['RESET_BETWEEN_SCENARIOS']=="1"
759
- end
350
+ # @!visibility private
351
+ # Checks the server and gem version compatibility and generates a warning if
352
+ # the server and gem are not compatible.
353
+ #
354
+ # @note This is a proof-of-concept implementation and requires _strict_
355
+ # equality. in the future we should allow minimum framework compatibility.
356
+ #
357
+ # @return [nil] nothing to return
358
+ def check_server_gem_compatibility
359
+ # Only check once.
360
+ return server_version if server_version
361
+
362
+ version_string = self.device.server_version
363
+
364
+ @server_version = RunLoop::Version.new(version_string)
365
+ gem_version = RunLoop::Version.new(Calabash::Cucumber::VERSION)
366
+ min_server_version = RunLoop::Version.new(Calabash::Cucumber::MIN_SERVER_VERSION)
367
+
368
+ if @server_version < min_server_version
369
+ msgs = [
370
+ "The server version is not compatible with gem version.",
371
+ "Please update your server.",
372
+ "https://github.com/calabash/calabash-ios/wiki/Updating-your-Calabash-iOS-version",
373
+ " gem version: '#{gem_version}'",
374
+ "min server version: '#{min_server_version}'",
375
+ " server version: '#{@server_version}'"]
376
+ RunLoop.log_warn("#{msgs.join("\n")}")
377
+ end
378
+ @server_version
379
+ end
760
380
 
761
- # @!visibility private
762
- def app_path
763
- RunLoop::Environment.path_to_app_bundle || (defined?(APP_BUNDLE_PATH) && APP_BUNDLE_PATH)
764
- end
381
+ # @deprecated 0.19.0 - replaced with #quit_app_after_scenario?
382
+ # @!visibility private
383
+ def calabash_no_stop?
384
+ # Not yet. Save for 0.20.0.
385
+ # RunLoop.deprecated("0.19.0", "replaced with quit_app_after_scenario")
386
+ !quit_app_after_scenario?
387
+ end
765
388
 
766
- # @!visibility private
767
- def run_with_instruments?(args)
768
- args && args[:launch_method] == :instruments
769
- end
389
+ # @!visibility private
390
+ # @deprecated 0.19.0 - no replacement
391
+ def calabash_no_launch?
392
+ RunLoop.log_warn(%Q[
393
+ Calabash::Cucumber::Launcher #calabash_no_launch? and support for the NO_LAUNCH
394
+ environment variable has been removed from Calabash. This always returns
395
+ true. Please remove this method call from your hooks.
396
+ ])
397
+ false
398
+ end
770
399
 
771
- # @!visibility private
772
- def active?
773
- not run_loop.nil?
774
- end
400
+ # @!visibility private
401
+ # @deprecated 0.19.0 - no replacement.
402
+ def default_uia_strategy(launch_args, sim_control, instruments)
403
+ RunLoop::deprecated("0.19.0", "This method has been removed.")
404
+ :host
405
+ end
775
406
 
776
- # @!visibility private
777
- def instruments?
778
- !!(active? && run_loop[:pid])
779
- end
407
+ # @!visibility private
408
+ # @deprecated 0.19.0 - no replacement
409
+ def detect_connected_device?
410
+ RunLoop.deprecated("0.19.0", "No replacement")
411
+ false
412
+ end
780
413
 
781
- # @!visibility private
782
- def inspect
783
- msg = ["#{self.class}: Launch Method #{launch_args && launch_args[:launch_method]}"]
784
- if run_with_instruments?(self.launch_args) && self.run_loop
785
- msg << "Log file: #{self.run_loop[:log_file]}"
786
- end
787
- msg.join("\n")
788
- end
414
+ # @!visibility private
415
+ # @deprecated 0.19.0 - no replacement
416
+ def default_launch_args
417
+ RunLoop.deprecated("0.19.0", "No replacement")
418
+ {}
419
+ end
789
420
 
790
- # @!visibility private
791
- # Extracts server version from the app binary at `app_bundle_path` by
792
- # inspecting the binary's strings table.
793
- #
794
- # @note
795
- # SPECIAL: sets the `@@server_version` class variable to cache the server
796
- # version because the server version will never change during runtime.
797
- #
798
- # @return [String] the server version
799
- # @param [String] app_bundle_path file path (usually) to the application bundle
800
- # @raise [RuntimeError] if there is no executable at `app_bundle_path`
801
- # @raise [RuntimeError] if the server version cannot be extracted from any
802
- # binary at `app_bundle_path`
803
- def server_version_from_bundle(app_bundle_path)
804
- return @@server_version unless @@server_version.nil?
805
- exe_paths = []
806
- Dir.foreach(app_bundle_path) do |item|
807
- next if item == '.' or item == '..'
808
-
809
- full_path = File.join(app_bundle_path, item)
810
- if File.executable?(full_path) and not File.directory?(full_path)
811
- exe_paths << full_path
421
+ # @!visibility private
422
+ # @deprecated 0.19.0 - no replacement
423
+ def discover_device_target(launch_args)
424
+ RunLoop.deprecated("0.19.0", "No replacement")
425
+ nil
812
426
  end
813
- end
814
427
 
815
- if exe_paths.empty?
816
- calabash_warn "could not find executable in '#{app_bundle_path}'"
428
+ # @!visibility private
429
+ # @deprecated 0.19.0 - no replacement
430
+ def device_target?(options={})
431
+ RunLoop.deprecated("0.19.0", "No replacement")
432
+ detect_device(options).physical_device?
433
+ end
817
434
 
818
- @@server_version = SERVER_VERSION_NOT_AVAILABLE
819
- return @@server_version
820
- end
435
+ # @!visibility private
436
+ # @deprecated 0.19.0 - no replacement
437
+ def simulator_target?(options={})
438
+ RunLoop.deprecated("0.19.0", "No replacement")
439
+ detect_device(options).simulator?
440
+ end
821
441
 
822
- server_version = nil
823
- exe_paths.each do |path|
824
- server_version_string = `xcrun strings "#{path}" | grep -E 'CALABASH VERSION'`.chomp!
825
- if server_version_string
826
- server_version = server_version_string.split(' ').last
827
- break
442
+ # @!visibility private
443
+ # @deprecated 0.19.0 - no replacement
444
+ def app_path
445
+ RunLoop.deprecated("0.19.0", "No replacement")
446
+ nil
828
447
  end
829
- end
830
448
 
831
- unless server_version
832
- calabash_warn('could not find server version by inspecting the binary strings table')
449
+ # @!visibility private
450
+ # @deprecated 0.19.0 - no replacement
451
+ def xcode
452
+ RunLoop.deprecated("0.19.0", "Use Calabash::Cucumber::Environment.xcode")
453
+ Calabash::Cucumber::Environment.xcode
454
+ end
833
455
 
834
- @@server_version = SERVER_VERSION_NOT_AVAILABLE
835
- return @@server_version
836
- end
456
+ # @!visibility private
457
+ # @deprecated 0.19.0 - no replacement
458
+ def ensure_connectivity
459
+ RunLoop.deprecated("0.19.0", "No replacement")
460
+ Calabash::Cucumber::HTTP.ensure_connectivity
461
+ end
837
462
 
838
- @@server_version = server_version
839
- end
463
+ # @!visibility private
464
+ # @deprecated 0.19.0 - no replacement - this method is a no op
465
+ #
466
+ # #relaunch will now send ":on_launch" to the Cucumber World if:
467
+ # * the Launcher is part of the World (it is not by default).
468
+ # * Cucumber responds to :on_launch.
469
+ def calabash_notify(_)
470
+ false
471
+ end
840
472
 
841
- # queries the server for its version.
842
- #
843
- # SPECIAL: sets the +@@server_version+ class variable to cache the server
844
- # version because the server version will never change during runtime.
845
- #
846
- # @return [String] the server version
847
- # @raise [RuntimeError] if the server cannot be reached
848
- def server_version_from_server
849
- return @@server_version unless @@server_version.nil?
850
- ensure_connectivity if self.device == nil
851
- @@server_version = self.device.server_version
852
- end
473
+ # @!visibility private
474
+ # @deprecated 0.19.0 - no replacement.
475
+ def server_version_from_server
476
+ RunLoop.deprecated("0.19.0", "No replacement")
477
+ server_version
478
+ end
853
479
 
854
- # @!visibility private
855
- # Checks the server and gem version compatibility and generates a warning if
856
- # the server and gem are not compatible.
857
- #
858
- # @note This is a proof-of-concept implementation and requires _strict_
859
- # equality. in the future we should allow minimum framework compatibility.
860
- #
861
- # @return [nil] nothing to return
862
- def check_server_gem_compatibility
863
- app_bundle_path = self.launch_args[:app]
864
- if File.directory?(app_bundle_path)
865
- server_version = server_version_from_bundle(app_bundle_path)
866
- else
867
- server_version = server_version_from_server
868
- end
480
+ # @!visibility private
481
+ # @deprecated 0.19.0 - no replacement
482
+ def server_version_from_bundle(app_bundle_path)
483
+ RunLoop.deprecated("0.19.0", "No replacement")
484
+ options = {:app => app_bundle_path }
485
+ app_details = RunLoop::DetectAUT.detect_app_under_test(options)
486
+ app = app_details[:app]
869
487
 
870
- if server_version == SERVER_VERSION_NOT_AVAILABLE
871
- calabash_warn('server version could not be found - skipping compatibility check')
872
- return nil
873
- end
488
+ if app.respond_to?(:calabash_server_version)
489
+ app.calabash_server_version
490
+ else
491
+ nil
492
+ end
493
+ end
874
494
 
875
- server_version = RunLoop::Version.new(server_version)
876
- gem_version = RunLoop::Version.new(Calabash::Cucumber::VERSION)
877
- min_server_version = RunLoop::Version.new(Calabash::Cucumber::MIN_SERVER_VERSION)
495
+ private
878
496
 
879
- if server_version < min_server_version
880
- msgs = [
881
- 'The server version is not compatible with gem version.',
882
- 'Please update your server.',
883
- 'https://github.com/calabash/calabash-ios/wiki/Updating-your-Calabash-iOS-version',
884
- " gem version: '#{gem_version}'",
885
- "min server version: '#{min_server_version}'",
886
- " server version: '#{server_version}'"]
887
- calabash_warn("#{msgs.join("\n")}")
888
- else
889
- if full_console_logging?
890
- calabash_info("gem #{gem_version} is compat with '#{server_version}'")
497
+ # @!visibility private
498
+ #
499
+ # A convenience wrapper around RunLoop::Device.detect_device
500
+ def detect_device(options)
501
+ xcode = Calabash::Cucumber::Environment.xcode
502
+ simctl = Calabash::Cucumber::Environment.simctl
503
+ instruments = Calabash::Cucumber::Environment.instruments
504
+ RunLoop::Device.detect_device(options, xcode, simctl, instruments)
891
505
  end
506
+
507
+ # The version of the embedded LPServer
508
+ # @return RunLoop::Version
509
+ attr_reader :server_version
892
510
  end
893
- nil
894
511
  end
895
-
896
512
  end
513
+