calabash 2.0.0.pre10 → 2.0.0.pre11
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/README.md +5 -17
- data/bin/calabash +3 -4
- data/lib/calabash.rb +53 -10
- data/lib/calabash/android.rb +89 -28
- data/lib/calabash/android/adb.rb +32 -20
- data/lib/calabash/android/application.rb +1 -1
- data/lib/calabash/android/build/builder.rb +1 -1
- data/lib/calabash/android/build/java_keystore.rb +1 -1
- data/lib/calabash/android/build/resigner.rb +1 -1
- data/lib/calabash/android/device.rb +22 -66
- data/lib/calabash/android/device/helper_application.rb +95 -0
- data/lib/calabash/android/environment.rb +14 -1
- data/lib/calabash/android/gestures.rb +6 -22
- data/lib/calabash/android/interactions.rb +14 -17
- data/lib/calabash/android/lib/.irbrc +9 -1
- data/lib/calabash/android/lib/AndroidManifest.xml +23 -2
- data/lib/calabash/android/lib/HelperApplication.apk +0 -0
- data/lib/calabash/android/lib/HelperApplicationTestServer.apk +0 -0
- data/lib/calabash/android/lib/TestServer.apk +0 -0
- data/lib/calabash/android/life_cycle.rb +3 -3
- data/lib/calabash/android/orientation.rb +8 -8
- data/lib/calabash/android/physical_buttons.rb +19 -16
- data/lib/calabash/android/server.rb +1 -1
- data/lib/calabash/android/text.rb +12 -12
- data/lib/calabash/android/web.rb +12 -0
- data/lib/calabash/application.rb +3 -0
- data/lib/calabash/cli/generate.rb +8 -18
- data/lib/calabash/cli/helpers.rb +4 -9
- data/lib/calabash/cli/run.rb +1 -1
- data/lib/calabash/console_helpers.rb +179 -11
- data/lib/calabash/device.rb +4 -19
- data/lib/calabash/gestures.rb +292 -198
- data/lib/calabash/interactions.rb +3 -40
- data/lib/calabash/internal.rb +48 -0
- data/lib/calabash/ios.rb +76 -16
- data/lib/calabash/ios/automator.rb +9 -0
- data/lib/calabash/ios/automator/automator.rb +217 -0
- data/lib/calabash/ios/automator/coordinates.rb +37 -0
- data/lib/calabash/ios/automator/device_agent.rb +379 -0
- data/lib/calabash/ios/conditions.rb +1 -1
- data/lib/calabash/ios/console_helpers.rb +2 -2
- data/lib/calabash/ios/date_picker.rb +10 -8
- data/lib/calabash/ios/device.rb +0 -1
- data/lib/calabash/ios/device/device_implementation.rb +9 -21
- data/lib/calabash/ios/device/gestures_mixin.rb +53 -55
- data/lib/calabash/ios/device/keyboard_mixin.rb +21 -0
- data/lib/calabash/ios/device/rotation_mixin.rb +3 -65
- data/lib/calabash/ios/gestures.rb +24 -90
- data/lib/calabash/ios/interactions.rb +1 -6
- data/lib/calabash/ios/lib/.irbrc +9 -2
- data/lib/calabash/ios/orientation.rb +8 -8
- data/lib/calabash/ios/runtime.rb +14 -14
- data/lib/calabash/ios/scroll.rb +25 -17
- data/lib/calabash/ios/slider.rb +11 -18
- data/lib/calabash/ios/text.rb +20 -74
- data/lib/calabash/ios/uia.rb +1 -1
- data/lib/calabash/ios/web.rb +10 -0
- data/lib/calabash/lib/skeleton/{Gemfile → Gemfile.skeleton} +0 -0
- data/lib/calabash/lib/skeleton/config/{cucumber.yml → cucumber.yml.skeleton} +0 -0
- data/lib/calabash/lib/skeleton/features/{sample.feature → sample.feature.skeleton} +0 -0
- data/lib/calabash/lib/skeleton/features/step_definitions/{calabash_steps.rb → sample_steps.rb.skeleton} +8 -8
- data/lib/calabash/lib/skeleton/features/support/{dry_run.rb → dry_run.rb.skeleton} +2 -5
- data/lib/calabash/lib/skeleton/features/support/{env.rb → env.rb.skeleton} +2 -8
- data/lib/calabash/lib/skeleton/features/support/hooks.rb.skeleton +34 -0
- data/lib/calabash/life_cycle.rb +16 -8
- data/lib/calabash/location.rb +14 -15
- data/lib/calabash/orientation.rb +8 -8
- data/lib/calabash/page.rb +1 -4
- data/lib/calabash/retry.rb +33 -0
- data/lib/calabash/screenshot.rb +3 -3
- data/lib/calabash/stubs.rb +21 -0
- data/lib/calabash/text.rb +31 -19
- data/lib/calabash/utility.rb +41 -8
- data/lib/calabash/version.rb +1 -1
- data/lib/calabash/wait.rb +177 -192
- data/lib/calabash/web.rb +44 -0
- metadata +39 -32
- data/lib/calabash/ios/device/text_mixin.rb +0 -21
- data/lib/calabash/lib/skeleton/features/support/hooks.rb +0 -83
@@ -62,7 +62,7 @@ module Calabash
|
|
62
62
|
#
|
63
63
|
# @return [Calabash::QueryResult] A result of the query
|
64
64
|
def query(query, *args)
|
65
|
-
Calabash::
|
65
|
+
Calabash::Internal.with_default_device {|device| device.map_route(Query.new(query), :query, *args)}
|
66
66
|
end
|
67
67
|
|
68
68
|
# Flashes any views matching `query`. Only one view is flashed at a time,
|
@@ -71,39 +71,7 @@ module Calabash
|
|
71
71
|
# @param [String, Hash, Calabash::Query] query The query to match the
|
72
72
|
# view(s)
|
73
73
|
def flash(query)
|
74
|
-
Calabash::
|
75
|
-
end
|
76
|
-
|
77
|
-
# Evaluate javascript in a Web View. On iOS, an implicit return is
|
78
|
-
# inserted, on Android an explicit return is needed.
|
79
|
-
#
|
80
|
-
# @example
|
81
|
-
# # iOS
|
82
|
-
# evaluate_javascript_in("UIWebView", "2+2")
|
83
|
-
# # Android
|
84
|
-
# evaluate_javascript_in("WebView", "return 2+2")
|
85
|
-
#
|
86
|
-
# @example
|
87
|
-
# # iOS
|
88
|
-
# evaluate_javascript_in("WKWebView",
|
89
|
-
# "document.body.style.backgroundColor = 'red';")
|
90
|
-
#
|
91
|
-
# # Android
|
92
|
-
# evaluate_javascript_in("XWalkContent",
|
93
|
-
# "document.body.style.backgroundColor = 'red';")
|
94
|
-
#
|
95
|
-
# @note No error will be raised if the javascript given is invalid, or
|
96
|
-
# throws an exception.
|
97
|
-
#
|
98
|
-
# @param [String, Hash, Calabash::Query] query Query that matches the view
|
99
|
-
# @param [String] javascript The javascript to evaluate
|
100
|
-
#
|
101
|
-
# @raise ViewNotFoundError If no views are found matching `query`
|
102
|
-
def evaluate_javascript_in(query, javascript)
|
103
|
-
wait_for_view(query,
|
104
|
-
timeout: Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT)
|
105
|
-
|
106
|
-
_evaluate_javascript_in(query, javascript)
|
74
|
+
Calabash::Internal.with_default_device {|device| device.map_route(Query.new(query), :flash)}
|
107
75
|
end
|
108
76
|
|
109
77
|
# Invoke a method in your application.
|
@@ -158,12 +126,7 @@ module Calabash
|
|
158
126
|
# @return [Object] the result of performing the selector/method with the
|
159
127
|
# arguments (serialized)
|
160
128
|
def backdoor(name, *arguments)
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
# @!visibility private
|
165
|
-
def _evaluate_javascript_in(query, javascript)
|
166
|
-
abstract_method!
|
129
|
+
Calabash::Internal.with_default_device {|device| device.backdoor(name, *arguments)}
|
167
130
|
end
|
168
131
|
end
|
169
132
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Calabash
|
2
|
+
# @!visibility private
|
3
|
+
# Internal usage, NOT a public API
|
4
|
+
module Internal
|
5
|
+
def self.with_default_device(required_os: nil, &block)
|
6
|
+
unless block
|
7
|
+
raise ArgumentError, "No block given"
|
8
|
+
end
|
9
|
+
|
10
|
+
device = Calabash.default_device
|
11
|
+
|
12
|
+
if device.nil?
|
13
|
+
raise "The default device is not set. Set it using Calabash.default_device = ..."
|
14
|
+
end
|
15
|
+
|
16
|
+
if required_os
|
17
|
+
required_class = nil
|
18
|
+
required_type = nil
|
19
|
+
current_type = nil
|
20
|
+
|
21
|
+
case required_os
|
22
|
+
when :ios
|
23
|
+
required_class = Calabash::IOS::Device
|
24
|
+
required_type = 'iOS'
|
25
|
+
when :android
|
26
|
+
required_class = Calabash::Android::Device
|
27
|
+
required_type = 'Android'
|
28
|
+
else
|
29
|
+
raise ArgumentError, "Unknown OS '#{required_os}'"
|
30
|
+
end
|
31
|
+
|
32
|
+
if Calabash::Android.const_defined?(:Device, false) && device.is_a?(Calabash::Android::Device)
|
33
|
+
current_type = 'Android'
|
34
|
+
elsif Calabash::IOS.const_defined?(:Device, false) && device.is_a?(Calabash::IOS::Device)
|
35
|
+
current_type = 'iOS'
|
36
|
+
else
|
37
|
+
current_type = 'unknown'
|
38
|
+
end
|
39
|
+
|
40
|
+
unless device.is_a?(required_class)
|
41
|
+
raise "The default device is not set to an #{required_type} device, it is an #{current_type} device."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
block.call(device)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/calabash/ios.rb
CHANGED
@@ -1,21 +1,7 @@
|
|
1
1
|
module Calabash
|
2
|
-
#
|
3
|
-
module
|
2
|
+
# @!visibility private
|
3
|
+
module IOSInternal
|
4
4
|
require 'calabash'
|
5
|
-
include Calabash
|
6
|
-
|
7
|
-
# @!visibility private
|
8
|
-
def self.extended(base)
|
9
|
-
Calabash.send(:extended, base)
|
10
|
-
end
|
11
|
-
|
12
|
-
# @!visibility private
|
13
|
-
def self.included(base)
|
14
|
-
Calabash.send(:included, base)
|
15
|
-
end
|
16
|
-
|
17
|
-
require 'calabash/ios/defaults'
|
18
|
-
extend Calabash::IOS::Defaults
|
19
5
|
|
20
6
|
require 'calabash/ios/environment'
|
21
7
|
require 'calabash/ios/application'
|
@@ -32,6 +18,8 @@ module Calabash
|
|
32
18
|
require 'calabash/ios/gestures'
|
33
19
|
require 'calabash/ios/slider'
|
34
20
|
require 'calabash/ios/date_picker'
|
21
|
+
require 'calabash/ios/automator'
|
22
|
+
require 'calabash/ios/web'
|
35
23
|
|
36
24
|
include Calabash::IOS::Conditions
|
37
25
|
include Calabash::IOS::Orientation
|
@@ -43,7 +31,79 @@ module Calabash
|
|
43
31
|
include Calabash::IOS::Gestures
|
44
32
|
include Calabash::IOS::Slider
|
45
33
|
include Calabash::IOS::DatePicker
|
34
|
+
include Calabash::IOS::Web
|
35
|
+
end
|
36
|
+
|
37
|
+
# Contains the iOS implementations of the Calabash APIs.
|
38
|
+
module IOS
|
39
|
+
require 'calabash'
|
40
|
+
# Hide from documentation
|
41
|
+
send(:include, Calabash)
|
42
|
+
|
43
|
+
# @!visibility private
|
44
|
+
def self.extended(base)
|
45
|
+
Calabash.send(:extended, base)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @!visibility private
|
49
|
+
def self.included(base)
|
50
|
+
Calabash.send(:included, base)
|
51
|
+
end
|
52
|
+
|
53
|
+
include ::Calabash::IOSInternal
|
54
|
+
|
55
|
+
require 'calabash/ios/defaults'
|
56
|
+
extend Calabash::IOS::Defaults
|
46
57
|
|
47
58
|
require 'calabash/ios/legacy'
|
48
59
|
end
|
49
60
|
end
|
61
|
+
|
62
|
+
# @!visibility private
|
63
|
+
class CalabashIOSMethodsInternal
|
64
|
+
include ::Calabash::IOS
|
65
|
+
end
|
66
|
+
|
67
|
+
# @!visibility private
|
68
|
+
class CalabashIOSMethods < BasicObject
|
69
|
+
include ::Calabash::IOSInternal
|
70
|
+
|
71
|
+
instance_methods.each do |method_name|
|
72
|
+
define_method(method_name) do |*args, &block|
|
73
|
+
::CalabashIOSMethodsInternal.new.send(method_name, *args, &block)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a object that exposes all of the public Calabash iOS API.
|
79
|
+
# This method should *always* be used to access the Calabash API. By default,
|
80
|
+
# all methods are executed using the default device and the default
|
81
|
+
# application.
|
82
|
+
#
|
83
|
+
# For iOS specific methods use {cal_android}. For cross-platform methods use
|
84
|
+
# {cal}.
|
85
|
+
#
|
86
|
+
# All iOS API methods are available with documentation in {Calabash::IOS}
|
87
|
+
#
|
88
|
+
# @see Calabash::IOS
|
89
|
+
#
|
90
|
+
# @return [Object] Instance responding to all Calabash iOS methods
|
91
|
+
# in the API.
|
92
|
+
def cal_ios
|
93
|
+
CalabashIOSMethods.new
|
94
|
+
end
|
95
|
+
|
96
|
+
# We also want to patch `cal` to invoke the iOS implementations
|
97
|
+
class CalabashMethodsInternal
|
98
|
+
include ::Calabash::IOS
|
99
|
+
|
100
|
+
instance_methods.each do |method_name|
|
101
|
+
define_method(method_name) do |*args, &block|
|
102
|
+
::CalabashIOSMethodsInternal.new.send(method_name, *args, &block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if defined?(::Calabash::AndroidInternal)
|
108
|
+
raise Calabash::RequiredBothPlatformsError, "Cannot require both calabash/android and calabash/ios"
|
109
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module Calabash
|
2
|
+
module IOS
|
3
|
+
# @!visibility private
|
4
|
+
module Automator
|
5
|
+
# @!visibility private
|
6
|
+
class Automator
|
7
|
+
include Utility
|
8
|
+
|
9
|
+
# @!visibility private
|
10
|
+
def initialize(*args)
|
11
|
+
abstract_method!
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!visibility private
|
15
|
+
def name
|
16
|
+
abstract_method!
|
17
|
+
end
|
18
|
+
|
19
|
+
# @!visibility private
|
20
|
+
def stop
|
21
|
+
abstract_method!
|
22
|
+
end
|
23
|
+
|
24
|
+
# @!visibility private
|
25
|
+
def running?
|
26
|
+
abstract_method!
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!visibility private
|
30
|
+
def client
|
31
|
+
abstract_method!
|
32
|
+
end
|
33
|
+
|
34
|
+
# @!visibility private
|
35
|
+
def touch(options)
|
36
|
+
abstract_method!
|
37
|
+
end
|
38
|
+
|
39
|
+
# @!visibility private
|
40
|
+
def double_tap(options)
|
41
|
+
abstract_method!
|
42
|
+
end
|
43
|
+
|
44
|
+
# @!visibility private
|
45
|
+
def two_finger_tap(options)
|
46
|
+
abstract_method!
|
47
|
+
end
|
48
|
+
|
49
|
+
# @!visibility private
|
50
|
+
def touch_hold(options)
|
51
|
+
abstract_method!
|
52
|
+
end
|
53
|
+
|
54
|
+
# @!visibility private
|
55
|
+
def flick(options)
|
56
|
+
abstract_method!
|
57
|
+
end
|
58
|
+
|
59
|
+
# @!visibility private
|
60
|
+
def pan(options={})
|
61
|
+
abstract_method!
|
62
|
+
end
|
63
|
+
|
64
|
+
# @!visibility private
|
65
|
+
#
|
66
|
+
# Callers must validate the options.
|
67
|
+
def pan_coordinates(from_point, to_point, options={})
|
68
|
+
abstract_method!
|
69
|
+
end
|
70
|
+
|
71
|
+
# @!visibility private
|
72
|
+
#
|
73
|
+
# Callers must validate the options.
|
74
|
+
def pinch(in_or_out, options)
|
75
|
+
abstract_method!
|
76
|
+
end
|
77
|
+
|
78
|
+
# @!visibility private
|
79
|
+
def send_app_to_background(seconds)
|
80
|
+
abstract_method!
|
81
|
+
end
|
82
|
+
|
83
|
+
# @!visibility private
|
84
|
+
#
|
85
|
+
# It is the caller's responsibility to:
|
86
|
+
# 1. expect the keyboard is visible
|
87
|
+
# 2. escape the existing text
|
88
|
+
def enter_text_with_keyboard(string, options={})
|
89
|
+
abstract_method!
|
90
|
+
end
|
91
|
+
|
92
|
+
# @!visibility private
|
93
|
+
#
|
94
|
+
# Respond to keys like 'Delete' or 'Return'.
|
95
|
+
def char_for_keyboard_action(action_key)
|
96
|
+
abstract_method!
|
97
|
+
end
|
98
|
+
|
99
|
+
# @!visibility private
|
100
|
+
# It is the caller's responsibility to ensure the keyboard is visible.
|
101
|
+
def enter_char_with_keyboard(char)
|
102
|
+
abstract_method!
|
103
|
+
end
|
104
|
+
|
105
|
+
# @!visibility private
|
106
|
+
# It is the caller's responsibility to ensure the keyboard is visible.
|
107
|
+
def tap_keyboard_action_key(return_key_type_of_first_responder)
|
108
|
+
abstract_method!
|
109
|
+
end
|
110
|
+
|
111
|
+
# @!visibility private
|
112
|
+
# It is the caller's responsibility to ensure the keyboard is visible.
|
113
|
+
def tap_keyboard_delete_key
|
114
|
+
abstract_method!
|
115
|
+
end
|
116
|
+
|
117
|
+
# @!visibility private
|
118
|
+
#
|
119
|
+
# Legacy API - can we remove this method?
|
120
|
+
#
|
121
|
+
# It is the caller's responsibility to ensure the keyboard is visible.
|
122
|
+
def fast_enter_text(text)
|
123
|
+
abstract_method!
|
124
|
+
end
|
125
|
+
|
126
|
+
# @!visibility private
|
127
|
+
#
|
128
|
+
# Caller is responsible for limiting calls to iPads and waiting for the
|
129
|
+
# keyboard to disappear.
|
130
|
+
def dismiss_ipad_keyboard
|
131
|
+
abstract_method!
|
132
|
+
end
|
133
|
+
|
134
|
+
# @!visibility private
|
135
|
+
#
|
136
|
+
# Caller is responsible for providing a valid direction.
|
137
|
+
def rotate(direction, status_bar_orientation)
|
138
|
+
abstract_method!
|
139
|
+
end
|
140
|
+
|
141
|
+
# @!visibility private
|
142
|
+
#
|
143
|
+
# Caller is responsible for normalizing and validating the position.
|
144
|
+
def rotate_home_button_to(position, status_bar_orientation)
|
145
|
+
abstract_method!
|
146
|
+
end
|
147
|
+
|
148
|
+
# @! visibility private
|
149
|
+
#
|
150
|
+
# It is important to remember that the current orientation is the
|
151
|
+
# position of the home button:
|
152
|
+
#
|
153
|
+
# :up => home button on the top => upside_down
|
154
|
+
# :bottom => home button on the bottom => portrait
|
155
|
+
# :left => home button on the left => landscape_right
|
156
|
+
# :right => home button on the right => landscape_left
|
157
|
+
#
|
158
|
+
# Notice how :left and :right are mapped.
|
159
|
+
def self.orientation_key(direction, current_orientation)
|
160
|
+
key = nil
|
161
|
+
case direction
|
162
|
+
when :left then
|
163
|
+
if current_orientation == :down
|
164
|
+
key = :landscape_left
|
165
|
+
elsif current_orientation == :right
|
166
|
+
key = :upside_down
|
167
|
+
elsif current_orientation == :left
|
168
|
+
key = :portrait
|
169
|
+
elsif current_orientation == :up
|
170
|
+
key = :landscape_right
|
171
|
+
end
|
172
|
+
when :right then
|
173
|
+
if current_orientation == :down
|
174
|
+
key = :landscape_right
|
175
|
+
elsif current_orientation == :right
|
176
|
+
key = :portrait
|
177
|
+
elsif current_orientation == :left
|
178
|
+
key = :upside_down
|
179
|
+
elsif current_orientation == :up
|
180
|
+
key = :landscape_left
|
181
|
+
end
|
182
|
+
else
|
183
|
+
raise ArgumentError,
|
184
|
+
"Expected '#{direction}' to be :left or :right"
|
185
|
+
end
|
186
|
+
|
187
|
+
key
|
188
|
+
end
|
189
|
+
|
190
|
+
# @!visibility private
|
191
|
+
def self.orientation_for_key(key)
|
192
|
+
DEVICE_ORIENTATION[key]
|
193
|
+
end
|
194
|
+
|
195
|
+
# @! visibility private
|
196
|
+
#
|
197
|
+
# It is important to remember that the current orientation is the
|
198
|
+
# position of the home button:
|
199
|
+
#
|
200
|
+
# :up => home button on the top => upside_down
|
201
|
+
# :bottom => home button on the bottom => portrait
|
202
|
+
# :left => home button on the left => landscape_right
|
203
|
+
# :right => home button on the right => landscape_left
|
204
|
+
#
|
205
|
+
# Notice how :left and :right are mapped to their logical opposite.
|
206
|
+
# @!visibility private
|
207
|
+
# @! visibility private
|
208
|
+
DEVICE_ORIENTATION = {
|
209
|
+
:portrait => 1,
|
210
|
+
:upside_down => 2,
|
211
|
+
:landscape_left => 3, # Home button on the right
|
212
|
+
:landscape_right => 4 # Home button on the left
|
213
|
+
}.freeze
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|