calabash 1.2.1 → 1.9.9.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +39 -0
- data/LICENSE +204 -21
- data/README.md +36 -6
- data/VERSIONING.md +16 -0
- data/bin/calabash +95 -0
- data/lib/calabash.rb +185 -1
- data/lib/calabash/android.rb +64 -0
- data/lib/calabash/android/adb.rb +277 -0
- data/lib/calabash/android/application.rb +110 -0
- data/lib/calabash/android/build.rb +12 -0
- data/lib/calabash/android/build/application.rb +13 -0
- data/lib/calabash/android/build/build_error.rb +11 -0
- data/lib/calabash/android/build/builder.rb +119 -0
- data/lib/calabash/android/build/java_keystore.rb +177 -0
- data/lib/calabash/android/build/resigner.rb +56 -0
- data/lib/calabash/android/build/test_server.rb +27 -0
- data/lib/calabash/android/console_helpers.rb +44 -0
- data/lib/calabash/android/cucumber.rb +3 -0
- data/lib/calabash/android/device.rb +965 -0
- data/lib/calabash/android/environment.rb +470 -0
- data/lib/calabash/android/gestures.rb +369 -0
- data/lib/calabash/android/interactions.rb +45 -0
- data/lib/calabash/android/lib/.irbrc +55 -0
- data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
- data/lib/calabash/android/lib/TestServer.apk +0 -0
- data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
- data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
- data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
- data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
- data/lib/calabash/android/life_cycle.rb +37 -0
- data/lib/calabash/android/orientation.rb +30 -0
- data/lib/calabash/android/physical_buttons.rb +39 -0
- data/lib/calabash/android/screenshot.rb +9 -0
- data/lib/calabash/android/scroll.rb +5 -0
- data/lib/calabash/android/server.rb +10 -0
- data/lib/calabash/android/text.rb +54 -0
- data/lib/calabash/application.rb +74 -0
- data/lib/calabash/cli.rb +12 -0
- data/lib/calabash/cli/build.rb +33 -0
- data/lib/calabash/cli/console.rb +90 -0
- data/lib/calabash/cli/generate.rb +110 -0
- data/lib/calabash/cli/helpers.rb +130 -0
- data/lib/calabash/cli/resign.rb +33 -0
- data/lib/calabash/cli/run.rb +99 -0
- data/lib/calabash/cli/setup_keystore.rb +39 -0
- data/lib/calabash/color.rb +32 -0
- data/lib/calabash/console_helpers.rb +90 -0
- data/lib/calabash/defaults.rb +56 -0
- data/lib/calabash/device.rb +401 -0
- data/lib/calabash/environment.rb +75 -0
- data/lib/calabash/gestures.rb +384 -0
- data/lib/calabash/http.rb +8 -0
- data/lib/calabash/http/error.rb +15 -0
- data/lib/calabash/http/request.rb +42 -0
- data/lib/calabash/http/retriable_client.rb +156 -0
- data/lib/calabash/interactions.rb +105 -0
- data/lib/calabash/ios.rb +37 -0
- data/lib/calabash/ios/application.rb +119 -0
- data/lib/calabash/ios/conditions.rb +79 -0
- data/lib/calabash/ios/console_helpers.rb +72 -0
- data/lib/calabash/ios/device.rb +24 -0
- data/lib/calabash/ios/device/device_implementation.rb +779 -0
- data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
- data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
- data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
- data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
- data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
- data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
- data/lib/calabash/ios/device/routes/error.rb +8 -0
- data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
- data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
- data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
- data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
- data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
- data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
- data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
- data/lib/calabash/ios/device/text_mixin.rb +19 -0
- data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
- data/lib/calabash/ios/device/uia_mixin.rb +12 -0
- data/lib/calabash/ios/environment.rb +41 -0
- data/lib/calabash/ios/interactions.rb +10 -0
- data/lib/calabash/ios/lib/.irbrc +55 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
- data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
- data/lib/calabash/ios/orientation.rb +117 -0
- data/lib/calabash/ios/scroll.rb +504 -0
- data/lib/calabash/ios/server.rb +73 -0
- data/lib/calabash/ios/text.rb +248 -0
- data/lib/calabash/ios/uia.rb +24 -0
- data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
- data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
- data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
- data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
- data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
- data/lib/calabash/life_cycle.rb +111 -0
- data/lib/calabash/location.rb +51 -0
- data/lib/calabash/logger.rb +87 -0
- data/lib/calabash/orientation.rb +84 -0
- data/lib/calabash/page.rb +35 -0
- data/lib/calabash/patch.rb +14 -0
- data/lib/calabash/patch/array.rb +16 -0
- data/lib/calabash/patch/run_loop.rb +90 -0
- data/lib/calabash/query.rb +160 -0
- data/lib/calabash/query_result.rb +85 -0
- data/lib/calabash/screenshot.rb +89 -0
- data/lib/calabash/server.rb +16 -0
- data/lib/calabash/text.rb +76 -0
- data/lib/calabash/utility.rb +58 -0
- data/lib/calabash/version.rb +3 -1
- data/lib/calabash/wait.rb +474 -0
- metadata +462 -24
@@ -0,0 +1,73 @@
|
|
1
|
+
module Calabash
|
2
|
+
module IOS
|
3
|
+
|
4
|
+
# A representation of the embedded Calabash iOS server.
|
5
|
+
class Server < ::Calabash::Server
|
6
|
+
|
7
|
+
# Returns the default server.
|
8
|
+
#
|
9
|
+
# You can set the default server by setting the `CAL_ENDPOINT` environment
|
10
|
+
# variable. If this value is not set, the default server will be
|
11
|
+
# `http://localhost:37265`.
|
12
|
+
#
|
13
|
+
# **IMPORTANT**
|
14
|
+
#
|
15
|
+
# You must include http:// and the port number when setting the
|
16
|
+
# `CAL_ENDPOINT` variable.
|
17
|
+
#
|
18
|
+
# ### Physical Devices
|
19
|
+
#
|
20
|
+
# When targeting a physical device, you _must_ set the `CAL_ENDPOINT`
|
21
|
+
# environment variable. Your device must be on the same network as the
|
22
|
+
# host machine. You can find your device's IP address the Settings.app.
|
23
|
+
#
|
24
|
+
# Settings.app > WiFi > touch the (i)nfo
|
25
|
+
# disclosure button of the network you are
|
26
|
+
# connected to.
|
27
|
+
#
|
28
|
+
# ### Pro Tip: Name your devices.
|
29
|
+
#
|
30
|
+
# The Calabash iOS Server is a Bonjour web service. You can avoid the
|
31
|
+
# hassle of determining a device's IP address by naming your devices. The
|
32
|
+
# names should not have spaces or characters that cannot be displayed
|
33
|
+
# plainly in a URL.
|
34
|
+
#
|
35
|
+
# Suppose you have 3 devices: an iPad Mini Retina, an iPhone 4S, and an
|
36
|
+
# iPhone 6.
|
37
|
+
#
|
38
|
+
# | Device | Name | IP |
|
39
|
+
# |--------|------|----|
|
40
|
+
# | iPad | ipad-mini | CAL_ENDPOINT=http://ipad-mini.local:37265 |
|
41
|
+
# | iPhone 4S | iphone4s | CAL_ENDPOINT=http://iphone4s.local:37265 |
|
42
|
+
# | iPhone 6 | iphone6 | CAL_ENDPOINT=http://iphone6.local:37265 |
|
43
|
+
#
|
44
|
+
# ### Pro Tip: Changing the Calabash server port.
|
45
|
+
#
|
46
|
+
# You can change the port number of the server by adding
|
47
|
+
# `CalabashServerPort` to your app's Info plist.
|
48
|
+
#
|
49
|
+
# CalabashServerPort NSNumber 9999
|
50
|
+
#
|
51
|
+
# ### Pro Tip: Share your wired connection
|
52
|
+
#
|
53
|
+
# https://github.com/calabash/calabash/wiki/iOS:-Improving-Network-Stability
|
54
|
+
#
|
55
|
+
# @return [Calabash::IOS::Server] The Calabash iOS server that is
|
56
|
+
# embedded in your app.
|
57
|
+
def self.default
|
58
|
+
endpoint = Environment::DEVICE_ENDPOINT
|
59
|
+
Server.new(endpoint)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Is this server running on the host machine?
|
63
|
+
#
|
64
|
+
# Apps running on the iOS Simulator are running on localhost.
|
65
|
+
#
|
66
|
+
# @return [Boolean] Returns true if the server hostname resolves to
|
67
|
+
# localhost.
|
68
|
+
def localhost?
|
69
|
+
endpoint.hostname == 'localhost' || endpoint.hostname == '127.0.0.1'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
module Calabash
|
2
|
+
module IOS
|
3
|
+
module Text
|
4
|
+
# @!visibility private
|
5
|
+
def enter_text(text)
|
6
|
+
wait_for_keyboard
|
7
|
+
existing_text = text_from_keyboard_first_responder
|
8
|
+
options = { existing_text: existing_text }
|
9
|
+
Device.default.uia_type_string(text, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @!visibility private
|
13
|
+
def _enter_text_in(view, text)
|
14
|
+
tap(view)
|
15
|
+
enter_text(text)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @!visibility private
|
19
|
+
def _clear_text
|
20
|
+
unless view_exists?("* isFirstResponder:1")
|
21
|
+
raise 'Cannot clear text. No view has focus'
|
22
|
+
end
|
23
|
+
|
24
|
+
clear_text_in("* isFirstResponder:1")
|
25
|
+
end
|
26
|
+
|
27
|
+
# @!visibility private
|
28
|
+
def _clear_text_in(view)
|
29
|
+
unless keyboard_visible?
|
30
|
+
tap(view)
|
31
|
+
wait_for_keyboard
|
32
|
+
end
|
33
|
+
|
34
|
+
unless wait_for_view(view)['text'].empty?
|
35
|
+
tap(view)
|
36
|
+
tap("UICalloutBarButton marked:'Select All'")
|
37
|
+
tap_keyboard_delete_key
|
38
|
+
end
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if a docked keyboard is visible.
|
44
|
+
#
|
45
|
+
# A docked keyboard is pinned to the bottom of the view.
|
46
|
+
#
|
47
|
+
# Keyboards on the iPhone and iPod are docked.
|
48
|
+
#
|
49
|
+
# @return [Boolean] Returns true if a keyboard is visible and docked.
|
50
|
+
def docked_keyboard_visible?
|
51
|
+
Device.default.docked_keyboard_visible?
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if an undocked keyboard is visible.
|
55
|
+
#
|
56
|
+
# A undocked keyboard is floats in the middle of the view.
|
57
|
+
#
|
58
|
+
# @return [Boolean] Returns false if the device is not an iPad; all
|
59
|
+
# keyboards on the iPhone and iPod are docked.
|
60
|
+
def undocked_keyboard_visible?
|
61
|
+
Device.default.undocked_keyboard_visible?
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns true if a split keyboard is visible.
|
65
|
+
#
|
66
|
+
# A split keyboard is floats in the middle of the view and is split to
|
67
|
+
# allow faster thumb typing
|
68
|
+
#
|
69
|
+
# @return [Boolean] Returns false if the device is not an iPad; all
|
70
|
+
# keyboards on the Phone and iPod are docked and not split.
|
71
|
+
def split_keyboard_visible?
|
72
|
+
Device.default.split_keyboard_visible?
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns true if there is a visible keyboard.
|
76
|
+
#
|
77
|
+
# @return [Boolean] Returns true if there is a visible keyboard.
|
78
|
+
def keyboard_visible?
|
79
|
+
docked_keyboard_visible? || undocked_keyboard_visible? || split_keyboard_visible?
|
80
|
+
end
|
81
|
+
|
82
|
+
# Waits for a keyboard to appear.
|
83
|
+
#
|
84
|
+
# @see Calabash::Wait.default_options
|
85
|
+
#
|
86
|
+
# @param [Number] timeout How long to wait for the keyboard.
|
87
|
+
# @raise [Calabash::Wait::TimeoutError] Raises error if no keyboard
|
88
|
+
# appears.
|
89
|
+
def wait_for_keyboard(timeout=nil)
|
90
|
+
keyboard_timeout = keyboard_wait_timeout(timeout)
|
91
|
+
message = "Timed out after #{keyboard_timeout} seconds waiting for the keyboard to appear"
|
92
|
+
wait_for(message, timeout: keyboard_timeout) do
|
93
|
+
keyboard_visible?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Waits for the keyboard to disappear.
|
98
|
+
#
|
99
|
+
# @see Calabash::Wait.default_options
|
100
|
+
#
|
101
|
+
# @param [Number] timeout How log to wait for the keyboard to disappear.
|
102
|
+
# @raise [Calabash::Wait::TimeoutError] Raises error if any keyboard is
|
103
|
+
# visible after the `timeout`.
|
104
|
+
def wait_for_no_keyboard(timeout=nil)
|
105
|
+
keyboard_timeout = keyboard_wait_timeout(timeout)
|
106
|
+
message = "Timed out after #{keyboard_timeout} seconds waiting for the keyboard to disappear"
|
107
|
+
wait_for(message, timeout: keyboard_timeout) do
|
108
|
+
!keyboard_visible?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Touches the keyboard action key.
|
113
|
+
#
|
114
|
+
# The action key depends on the keyboard. Some examples include:
|
115
|
+
#
|
116
|
+
# * Return
|
117
|
+
# * Next
|
118
|
+
# * Go
|
119
|
+
# * Join
|
120
|
+
# * Search
|
121
|
+
#
|
122
|
+
# Not all keyboards have an action key. For example, numeric keyboards
|
123
|
+
# do not have an action key.
|
124
|
+
#
|
125
|
+
# @raise [RuntimeError] If the text cannot be typed.
|
126
|
+
# @todo Refactor uia_route to a public API call
|
127
|
+
# @todo Move this documentation to the public method
|
128
|
+
def _tap_current_keyboard_action_key
|
129
|
+
char_sequence = ESCAPED_KEYBOARD_CHARACTERS[:action]
|
130
|
+
Device.default.uia_route("uia.keyboard().typeString('#{char_sequence}')")
|
131
|
+
end
|
132
|
+
|
133
|
+
# Touches the keyboard delete key.
|
134
|
+
#
|
135
|
+
# The 'delete' key difficult to find and touch because its behavior
|
136
|
+
# changes depending on the iOS version and keyboard type. Consider the
|
137
|
+
# following:
|
138
|
+
#
|
139
|
+
# On iOS 6, the 'delete' char code is _not_ \b.
|
140
|
+
# On iOS 7: The Delete char code is \b on non-numeric keyboards.
|
141
|
+
# On numeric keyboards, the delete key is a button on the
|
142
|
+
# the keyboard.
|
143
|
+
#
|
144
|
+
# By default, Calabash uses a raw UIAutomaton JavaScript call to tap the
|
145
|
+
# element named 'Delete'. This works well in English localizations for
|
146
|
+
# most keyboards. If you find that it does not work, use the options
|
147
|
+
# pass either an translation of 'Delete' for your localization or use the
|
148
|
+
# default the escaped keyboard character.
|
149
|
+
#
|
150
|
+
# @example
|
151
|
+
# # Uses UIAutomation to tap the 'Delete' key or button.
|
152
|
+
# tap_keyboard_delete_key
|
153
|
+
#
|
154
|
+
# # Types the \b key.
|
155
|
+
# tap_keyboard_delete_key({:use_escaped_char => true})
|
156
|
+
#
|
157
|
+
# # Types the \d key.
|
158
|
+
# tap_keyboard_delete_key({:use_escaped_char => '\d'})
|
159
|
+
#
|
160
|
+
# # Uses UIAutomation to tap the 'Slet' key or button.
|
161
|
+
# tap_keyboard_delete_key({:delete_key_label => 'Slet'})
|
162
|
+
#
|
163
|
+
# # Don't specify both options! If :use_escape_sequence is truthy,
|
164
|
+
# # Calabash will ignore the :delete_key_label and try to use an
|
165
|
+
# # escaped character sequence.
|
166
|
+
# tap_keyboard_delete_key({:use_escaped_char => true,
|
167
|
+
# :delete_key_label => 'Slet'})
|
168
|
+
#
|
169
|
+
# @param [Hash] options Alternative ways to tap the delete key.
|
170
|
+
# @option options [Boolean, String] :use_escaped_char (false) If true,
|
171
|
+
# delete by typing the \b character. If this value is truthy, but not
|
172
|
+
# 'true', they it is expected to be an alternative escaped character.
|
173
|
+
# @option options [String] :delete_key_label ('Delete') An alternative
|
174
|
+
# localization of 'Delete'.
|
175
|
+
# @todo Need translations of 'Delete' key.
|
176
|
+
def tap_keyboard_delete_key(options = {})
|
177
|
+
default_options =
|
178
|
+
{
|
179
|
+
use_escaped_char: false,
|
180
|
+
delete_key_label: 'Delete'
|
181
|
+
}
|
182
|
+
merged_options = default_options.merge(options)
|
183
|
+
|
184
|
+
use_escape_sequence = merged_options[:use_escaped_char]
|
185
|
+
if use_escape_sequence
|
186
|
+
if use_escape_sequence.to_s == 'true'
|
187
|
+
# Use the default \b
|
188
|
+
char_sequence = ESCAPED_KEYBOARD_CHARACTERS[:delete]
|
189
|
+
else
|
190
|
+
char_sequence = use_escape_sequence
|
191
|
+
end
|
192
|
+
return Device.default.uia_route("uia.keyboard().typeString('#{char_sequence}')")
|
193
|
+
end
|
194
|
+
|
195
|
+
delete_key_label = merged_options[:delete_key_label]
|
196
|
+
uia = "uia.keyboard().elements().firstWithName('#{delete_key_label}').tap()"
|
197
|
+
Device.default.uia_route(uia)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Returns the the text in the first responder.
|
201
|
+
#
|
202
|
+
# The first responder will be the UITextField or UITextView instance
|
203
|
+
# that is associated with the visible keyboard.
|
204
|
+
#
|
205
|
+
# Returns empty string if no textField or textView elements are found to be
|
206
|
+
# the first responder. Otherwise, it will return the text in the
|
207
|
+
# UITextField or UITextField that is associated with the keyboard.
|
208
|
+
#
|
209
|
+
# @raise [RuntimeError] If there is no visible keyboard.
|
210
|
+
def text_from_keyboard_first_responder
|
211
|
+
Device.default.text_from_keyboard_first_responder
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
# @!visibility private
|
217
|
+
# noinspection RubyStringKeysInHashInspection
|
218
|
+
ESCAPED_KEYBOARD_CHARACTERS =
|
219
|
+
{
|
220
|
+
:action => '\n',
|
221
|
+
|
222
|
+
# This works for some combinations of keyboard types and
|
223
|
+
# iOS version. The current solution is use a raw UIA call
|
224
|
+
# to find the 'Delete' key, which may not work in some
|
225
|
+
# situations, for example in non-English environments. The
|
226
|
+
# tap_keyboard_delete_key allows an option to us this escape
|
227
|
+
# sequence.
|
228
|
+
:delete => '\b',
|
229
|
+
|
230
|
+
# These are not supported yet and I am pretty sure that they
|
231
|
+
# cannot be touched by passing an escaped character and instead
|
232
|
+
# the must be found using UIAutomation calls. -jmoody
|
233
|
+
#'Dictation' => nil,
|
234
|
+
#'Shift' => nil,
|
235
|
+
#'International' => nil,
|
236
|
+
#'More' => nil,
|
237
|
+
}
|
238
|
+
|
239
|
+
def keyboard_wait_timeout(timeout)
|
240
|
+
if timeout.nil?
|
241
|
+
Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
|
242
|
+
else
|
243
|
+
timeout
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Calabash
|
2
|
+
module IOS
|
3
|
+
module UIA
|
4
|
+
|
5
|
+
# Evaluates `script` with Apple's UIAutomation API.
|
6
|
+
#
|
7
|
+
def uia(script)
|
8
|
+
Device.default.evaluate_uia(script)
|
9
|
+
end
|
10
|
+
|
11
|
+
def uia_with_target(script)
|
12
|
+
uia("UIATarget.localTarget().#{script}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def uia_with_app(script)
|
16
|
+
uia("UIATarget.localTarget().frontMostApp().#{script}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def uia_with_main_window(script)
|
20
|
+
uia("UIATarget.localTarget().frontMostApp().mainWindow().#{script}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Given(/^I have done a specific thing$/) do
|
2
|
+
# Sample step definition
|
3
|
+
# Example: (Given I am logged in)
|
4
|
+
# enter_text("* marked:'username'", USERNAME)
|
5
|
+
# enter_text("* marked:'password'", PASSWORD)
|
6
|
+
# touch("* marked:'login'")
|
7
|
+
# wait_for_view("* text:'Welcome #{USERNAME}'")
|
8
|
+
|
9
|
+
# Remember: any Ruby is allowed in your step definitions
|
10
|
+
did_something = true
|
11
|
+
|
12
|
+
unless did_something
|
13
|
+
fail 'Expected to have done something'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
When(/^I do something$/) do
|
18
|
+
# Sample step definition
|
19
|
+
# Example: When I create a new entry
|
20
|
+
# touch("* marked:'new_entry'")
|
21
|
+
# enter_text("* marked:'entry_title'", 'My Entry')
|
22
|
+
# touch("* marked:'submit'")
|
23
|
+
end
|
24
|
+
|
25
|
+
Then(/^something should happen$/) do
|
26
|
+
# Sample step definition
|
27
|
+
# Example: Then I should see the entry on my home page
|
28
|
+
# wait_for_view("* text:'My Entry'")
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'calabash'
|
2
|
+
|
3
|
+
platform = Calabash::Environment.variable('PLATFORM')
|
4
|
+
|
5
|
+
case platform
|
6
|
+
when 'android'
|
7
|
+
require 'calabash/android'
|
8
|
+
|
9
|
+
World(Calabash::Android)
|
10
|
+
|
11
|
+
# Setup the default application
|
12
|
+
Calabash::Application.default =
|
13
|
+
Calabash::Android::Application.default_from_environment
|
14
|
+
|
15
|
+
identifier = Calabash::Android::Device.default_serial
|
16
|
+
server = Calabash::Android::Server.default
|
17
|
+
|
18
|
+
# Setup the default device
|
19
|
+
Calabash::Device.default =
|
20
|
+
Calabash::Android::Device.new(identifier, server)
|
21
|
+
when 'ios'
|
22
|
+
require 'calabash/ios'
|
23
|
+
|
24
|
+
World(Calabash::IOS)
|
25
|
+
|
26
|
+
# Setup the default application
|
27
|
+
Calabash::Application.default =
|
28
|
+
Calabash::IOS::Application.default_from_environment
|
29
|
+
|
30
|
+
identifier =
|
31
|
+
Calabash::IOS::Device.default_identifier_for_application(Calabash::Application.default)
|
32
|
+
|
33
|
+
server = Calabash::IOS::Server.default
|
34
|
+
|
35
|
+
# Setup the default device
|
36
|
+
Calabash::Device.default =
|
37
|
+
Calabash::IOS::Device.new(identifier, server)
|
38
|
+
else
|
39
|
+
message = if platform.nil? || platform.empty?
|
40
|
+
'No platform given'
|
41
|
+
else
|
42
|
+
"Invalid platform '#{platform}'. Expected 'android' or 'ios'"
|
43
|
+
end
|
44
|
+
|
45
|
+
failure_messages =
|
46
|
+
[
|
47
|
+
'ERROR! Unable to start the cucumber test:',
|
48
|
+
message,
|
49
|
+
"Use the profile 'android' or 'ios', or run cucumber using $ calabash run"
|
50
|
+
]
|
51
|
+
|
52
|
+
Calabash::Logger.error(failure_messages.join("\n"))
|
53
|
+
exit(1)
|
54
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'calabash'
|
2
|
+
|
3
|
+
Before do |scenario|
|
4
|
+
if scenario.respond_to?(:scenario_outline)
|
5
|
+
scenario = scenario.scenario_outline
|
6
|
+
end
|
7
|
+
|
8
|
+
AppLifeCycle.on_new_scenario(scenario)
|
9
|
+
|
10
|
+
start_app
|
11
|
+
end
|
12
|
+
|
13
|
+
After do
|
14
|
+
stop_app
|
15
|
+
end
|
16
|
+
|
17
|
+
module AppLifeCycle
|
18
|
+
# Since this is a module, the methods in the Cucumber World are not
|
19
|
+
# available inside the scope of this module. We can safely include Calabash
|
20
|
+
# because we will not affect the scope outside this module. The methods are
|
21
|
+
# loaded as class (static) methods.
|
22
|
+
class << self
|
23
|
+
include Calabash
|
24
|
+
end
|
25
|
+
|
26
|
+
DEFAULT_RESET_BETWEEN = #!DEFAULT_RESET_BETWEEN#! # Filled in by calabash gen
|
27
|
+
DEFAULT_RESET_METHOD = #!DEFAULT_RESET_METHOD#! # Filled in by calabash gen
|
28
|
+
|
29
|
+
RESET_BETWEEN = if Calabash::Environment.variable('RESET_BETWEEN')
|
30
|
+
Calabash::Environment.variable('RESET_BETWEEN').downcase.to_sym
|
31
|
+
else
|
32
|
+
DEFAULT_RESET_BETWEEN
|
33
|
+
end
|
34
|
+
|
35
|
+
RESET_METHOD = if Calabash::Environment.variable('RESET_METHOD')
|
36
|
+
Calabash::Environment.variable('RESET_METHOD').downcase.to_sym
|
37
|
+
else
|
38
|
+
DEFAULT_RESET_METHOD
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.on_new_scenario(scenario)
|
42
|
+
# Ensure the app is installed at the beginning of the test,
|
43
|
+
# if we never reset
|
44
|
+
if @last_feature.nil? && RESET_BETWEEN == :never
|
45
|
+
ensure_app_installed
|
46
|
+
end
|
47
|
+
|
48
|
+
if should_reset?(scenario)
|
49
|
+
reset
|
50
|
+
end
|
51
|
+
|
52
|
+
@last_feature = scenario.feature
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def self.should_reset?(scenario)
|
58
|
+
case RESET_BETWEEN
|
59
|
+
when :scenarios
|
60
|
+
true
|
61
|
+
when :features
|
62
|
+
scenario.feature != @last_feature
|
63
|
+
when :never
|
64
|
+
false
|
65
|
+
else
|
66
|
+
raise "Invalid reset between option '#{RESET_BETWEEN}'"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reset
|
71
|
+
case RESET_METHOD
|
72
|
+
when :reinstall
|
73
|
+
install_app
|
74
|
+
when :clear
|
75
|
+
ensure_app_installed
|
76
|
+
clear_app_data
|
77
|
+
when '', nil
|
78
|
+
raise 'No reset method given'
|
79
|
+
else
|
80
|
+
raise "Invalid reset method '#{RESET_METHOD}'"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|