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