calabash-cucumber 0.18.2 → 0.19.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/calabash-ios +0 -16
- data/bin/calabash-ios-build.rb +0 -86
- data/bin/calabash-ios-helpers.rb +0 -65
- data/bin/calabash-ios-setup.rb +5 -119
- data/bin/calabash-ios-sim.rb +0 -37
- data/bin/frank-calabash +0 -1
- data/doc/calabash-ios-help.txt +0 -8
- data/dylibs/libCalabashDyn.dylib +0 -0
- data/dylibs/libCalabashDynSim.dylib +0 -0
- data/features-skeleton/support/01_launch.rb +3 -4
- data/features/step_definitions/calabash_steps.rb +1 -7
- data/lib/calabash-cucumber.rb +1 -2
- data/lib/calabash-cucumber/actions/instruments_actions.rb +2 -3
- data/lib/calabash-cucumber/core.rb +97 -101
- data/lib/calabash-cucumber/device.rb +5 -118
- data/lib/calabash-cucumber/environment.rb +109 -5
- data/lib/calabash-cucumber/environment_helpers.rb +4 -66
- data/lib/calabash-cucumber/http/http.rb +114 -0
- data/lib/calabash-cucumber/http_helpers.rb +3 -1
- data/lib/calabash-cucumber/ipad_1x_2x.rb +5 -7
- data/lib/calabash-cucumber/keyboard_helpers.rb +0 -44
- data/lib/calabash-cucumber/launcher.rb +425 -808
- data/lib/calabash-cucumber/logging.rb +2 -74
- data/lib/calabash-cucumber/operations.rb +0 -2
- data/lib/calabash-cucumber/rotation_helpers.rb +2 -82
- data/lib/calabash-cucumber/status_bar_helpers.rb +2 -8
- data/lib/calabash-cucumber/store/preferences.rb +2 -1
- data/lib/calabash-cucumber/uia.rb +4 -9
- data/lib/calabash-cucumber/version.rb +2 -2
- data/lib/calabash-cucumber/wait_helpers.rb +0 -2
- data/staticlib/calabash.framework.zip +0 -0
- data/staticlib/libFrankCalabash.a +0 -0
- metadata +13 -143
- data/lib/calabash-cucumber/actions/playback_actions.rb +0 -109
- data/lib/calabash-cucumber/deprecated.rb +0 -34
- data/lib/calabash-cucumber/launch/simulator_helper.rb +0 -62
- data/lib/calabash-cucumber/launch/simulator_launcher.rb +0 -617
- data/lib/calabash-cucumber/playback_helpers.rb +0 -225
- data/lib/calabash-cucumber/resources/cell_swipe_ios4_ipad.base64 +0 -51
- data/lib/calabash-cucumber/resources/cell_swipe_ios4_iphone.base64 +0 -51
- data/lib/calabash-cucumber/resources/cell_swipe_ios5_ipad.base64 +0 -74
- data/lib/calabash-cucumber/resources/cell_swipe_ios5_iphone.base64 +0 -74
- data/lib/calabash-cucumber/resources/double_tap_ios5_ipad.base64 +0 -15
- data/lib/calabash-cucumber/resources/double_tap_ios5_iphone.base64 +0 -15
- data/lib/calabash-cucumber/resources/double_tap_ios6_ipad.base64 +0 -22
- data/lib/calabash-cucumber/resources/double_tap_ios6_iphone.base64 +0 -22
- data/lib/calabash-cucumber/resources/pan_ios5_ipad.base64 +0 -199
- data/lib/calabash-cucumber/resources/pan_ios5_iphone.base64 +0 -199
- data/lib/calabash-cucumber/resources/pan_ios6_ipad.base64 +0 -206
- data/lib/calabash-cucumber/resources/pan_ios6_iphone.base64 +0 -206
- data/lib/calabash-cucumber/resources/pinch_in_ios4_ipad.base64 +0 -104
- data/lib/calabash-cucumber/resources/pinch_in_ios4_iphone.base64 +0 -104
- data/lib/calabash-cucumber/resources/pinch_in_ios5_ipad.base64 +0 -144
- data/lib/calabash-cucumber/resources/pinch_in_ios5_iphone.base64 +0 -144
- data/lib/calabash-cucumber/resources/pinch_in_ios6_ipad.base64 +0 -70
- data/lib/calabash-cucumber/resources/pinch_in_ios6_iphone.base64 +0 -70
- data/lib/calabash-cucumber/resources/pinch_out_ios5_ipad.base64 +0 -207
- data/lib/calabash-cucumber/resources/pinch_out_ios5_iphone.base64 +0 -207
- data/lib/calabash-cucumber/resources/pinch_out_ios6_ipad.base64 +0 -96
- data/lib/calabash-cucumber/resources/pinch_out_ios6_iphone.base64 +0 -96
- data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_ipad.base64 +0 -2
- data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_iphone.base64 +0 -2
- data/lib/calabash-cucumber/resources/swipe_down_ios5_ipad.base64 +0 -18
- data/lib/calabash-cucumber/resources/swipe_down_ios5_iphone.base64 +0 -31
- data/lib/calabash-cucumber/resources/swipe_down_ios6_ipad.base64 +0 -25
- data/lib/calabash-cucumber/resources/swipe_down_ios6_iphone.base64 +0 -25
- data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_ipad.base64 +0 -15
- data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_iphone.base64 +0 -15
- data/lib/calabash-cucumber/resources/swipe_left_ios4_ipad.base64 +0 -18
- data/lib/calabash-cucumber/resources/swipe_left_ios4_iphone.base64 +0 -18
- data/lib/calabash-cucumber/resources/swipe_left_ios5_ipad.base64 +0 -17
- data/lib/calabash-cucumber/resources/swipe_left_ios5_iphone.base64 +0 -34
- data/lib/calabash-cucumber/resources/swipe_left_ios6_ipad.base64 +0 -28
- data/lib/calabash-cucumber/resources/swipe_left_ios6_iphone.base64 +0 -28
- data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_ipad.base64 +0 -17
- data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_iphone.base64 +0 -17
- data/lib/calabash-cucumber/resources/swipe_right_ios4_ipad.base64 +0 -13
- data/lib/calabash-cucumber/resources/swipe_right_ios4_iphone.base64 +0 -13
- data/lib/calabash-cucumber/resources/swipe_right_ios5_ipad.base64 +0 -17
- data/lib/calabash-cucumber/resources/swipe_right_ios5_iphone.base64 +0 -17
- data/lib/calabash-cucumber/resources/swipe_right_ios6_ipad.base64 +0 -25
- data/lib/calabash-cucumber/resources/swipe_right_ios6_iphone.base64 +0 -25
- data/lib/calabash-cucumber/resources/swipe_up_ios5_ipad.base64 +0 -34
- data/lib/calabash-cucumber/resources/swipe_up_ios5_iphone.base64 +0 -28
- data/lib/calabash-cucumber/resources/swipe_up_ios6_ipad.base64 +0 -25
- data/lib/calabash-cucumber/resources/swipe_up_ios6_iphone.base64 +0 -25
- data/lib/calabash-cucumber/resources/touch_done_ios4_ipad.base64 +0 -7
- data/lib/calabash-cucumber/resources/touch_done_ios4_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_done_ios5_ipad.base64 +0 -7
- data/lib/calabash-cucumber/resources/touch_done_ios5_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_hold_ios5_ipad.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_hold_ios5_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_hold_ios6_ipad.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_hold_ios6_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios4_ipad.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios4_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios5_ipad.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios5_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios7_ipad.base64 +0 -9
- data/lib/calabash-cucumber/resources/touch_ios7_iphone.base64 +0 -9
- data/lib/calabash-cucumber/resources/wheel_down_ios4_ipad.base64 +0 -159
- data/lib/calabash-cucumber/resources/wheel_down_ios4_iphone.base64 +0 -159
- data/lib/calabash-cucumber/resources/wheel_down_ios5_ipad.base64 +0 -156
- data/lib/calabash-cucumber/resources/wheel_down_ios5_iphone.base64 +0 -156
- data/lib/calabash-cucumber/resources/wheel_up_ios4_ipad.base64 +0 -166
- data/lib/calabash-cucumber/resources/wheel_up_ios4_iphone.base64 +0 -166
- data/lib/calabash-cucumber/resources/wheel_up_ios5_ipad.base64 +0 -156
- data/lib/calabash-cucumber/resources/wheel_up_ios5_iphone.base64 +0 -156
- data/lib/calabash-cucumber/utils/logging.rb +0 -111
- data/lib/calabash-cucumber/utils/plist_buddy.rb +0 -45
- data/lib/calabash-cucumber/utils/simulator_accessibility.rb +0 -334
- data/lib/calabash-cucumber/utils/xctools.rb +0 -101
- data/scripts/.irbrc +0 -64
- data/scripts/launch.rb +0 -48
@@ -1,896 +1,513 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
4
|
+
# Raised when calabash cannot launch the app.
|
5
|
+
class LaunchError < RuntimeError
|
6
|
+
attr_accessor :error
|
75
7
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
8
|
+
def initialize(err)
|
9
|
+
self.error= err
|
10
|
+
end
|
80
11
|
|
81
|
-
|
82
|
-
|
83
|
-
|
12
|
+
# @!visibility private
|
13
|
+
def to_s
|
14
|
+
"#{super.to_s}: #{error}"
|
15
|
+
end
|
16
|
+
end
|
84
17
|
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
90
|
-
|
91
|
-
@simulator_launcher = Calabash::Cucumber::SimulatorLauncher.new
|
92
|
-
@@launcher = self
|
93
|
-
end
|
54
|
+
# @!visibility private
|
55
|
+
@@launcher = nil
|
94
56
|
|
95
|
-
|
96
|
-
|
97
|
-
attach if @actions.nil?
|
98
|
-
@actions
|
99
|
-
end
|
57
|
+
# @!visibility private
|
58
|
+
@@launcher = nil
|
100
59
|
|
101
|
-
|
102
|
-
|
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
|
-
|
109
|
-
|
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
|
-
|
115
|
-
|
116
|
-
return
|
117
|
-
end
|
66
|
+
# @!visibility private
|
67
|
+
attr_accessor :launch_args
|
118
68
|
|
119
|
-
|
69
|
+
# @!visibility private
|
70
|
+
attr_reader :usage_tracker
|
120
71
|
|
121
|
-
|
122
|
-
|
72
|
+
# @!visibility private
|
73
|
+
def initialize
|
74
|
+
@@launcher = self
|
75
|
+
end
|
123
76
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
90
|
+
# @!visibility private
|
91
|
+
def inspect
|
92
|
+
to_s
|
93
|
+
end
|
133
94
|
|
134
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
142
|
-
|
143
|
-
|
136
|
+
# @!visibility private
|
137
|
+
def usage_tracker
|
138
|
+
@usage_tracker ||= Calabash::Cucumber::UsageTracker.new
|
139
|
+
end
|
144
140
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
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
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
-
|
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
|
-
|
177
|
+
If your app is running, check that you have set the DEVICE_ENDPOINT correctly.
|
267
178
|
|
268
|
-
|
179
|
+
If your app is not running, it was a mistake to call this method.
|
269
180
|
|
270
|
-
|
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
|
-
|
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
|
-
|
187
|
+
# Nothing to do except log the problem and exit early.
|
188
|
+
return false
|
189
|
+
end
|
290
190
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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
|
-
|
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
|
-
|
314
|
-
simulator
|
315
|
-
end
|
199
|
+
Queries will work, but gestures will not.
|
316
200
|
|
317
|
-
|
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
|
-
|
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
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
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
|
-
|
404
|
-
|
405
|
-
|
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
|
-
|
451
|
-
|
452
|
-
|
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
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
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
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
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
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
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
|
-
:
|
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
|
-
|
255
|
+
if device_target.physical_device?
|
256
|
+
raise ArgumentError,
|
257
|
+
%Q{
|
258
|
+
Cannot reset: #{device_target}.
|
584
259
|
|
585
|
-
|
260
|
+
Resetting physical devices is not supported.
|
261
|
+
}
|
262
|
+
end
|
586
263
|
|
587
|
-
|
588
|
-
|
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
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
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
|
-
|
310
|
+
usage_tracker.post_usage_async
|
660
311
|
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
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
|
-
|
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
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
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
|
-
|
730
|
-
|
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
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
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
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
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
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
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
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
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
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
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
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
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
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
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
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
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
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
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
|
-
|
816
|
-
|
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
|
-
|
819
|
-
|
820
|
-
|
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
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
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
|
-
|
832
|
-
|
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
|
-
|
835
|
-
|
836
|
-
|
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
|
-
|
839
|
-
|
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
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
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
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
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
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
488
|
+
if app.respond_to?(:calabash_server_version)
|
489
|
+
app.calabash_server_version
|
490
|
+
else
|
491
|
+
nil
|
492
|
+
end
|
493
|
+
end
|
874
494
|
|
875
|
-
|
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
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
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
|
+
|