Skip to content

Commit aaf307d

Browse files
authored
refactor: loading xcuitest related methods only for XCUITest case (#631)
* make global driver arguments of several methods * use $ instead of @ * use $ instead of @ * fix rubocop * separate xcuitest related methos in the xcuitest directory * reduce global driver in multu touch * separate some added endpoint method
1 parent 20bc86a commit aaf307d

File tree

9 files changed

+177
-55
lines changed

9 files changed

+177
-55
lines changed

lib/appium_lib/android/device.rb

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
require 'base64'
2+
3+
module Appium
4+
module Android
5+
module Device
6+
extend Forwardable
7+
8+
# @!method hide_keyboard
9+
# Hide the onscreen keyboard
10+
# @param [String] close_key The name of the key which closes the keyboard.
11+
# Defaults to 'Done' for iOS(except for XCUITest).
12+
# @param [Symbol] strategy The symbol of the strategy which closes the keyboard.
13+
# XCUITest ignore this argument.
14+
# Default for iOS is `:pressKey`. Default for Android is `:tapOutside`.
15+
# ```ruby
16+
# hide_keyboard # Close a keyboard with the 'Done' button
17+
# hide_keyboard('Finished') # Close a keyboard with the 'Finished' button
18+
# hide_keyboard(nil, :tapOutside) # Close a keyboard with tapping out side of keyboard
19+
# ```
20+
21+
class << self
22+
def extended(_mod)
23+
::Appium::Device.extend_webdriver_with_forwardable
24+
25+
::Appium::Device.add_endpoint_method(:hide_keyboard) do
26+
def hide_keyboard(close_key = nil, strategy = nil)
27+
option = {}
28+
29+
option[:key] = close_key if close_key
30+
option[:strategy] = strategy || :tapOutside # default to pressKey
31+
32+
execute :hide_keyboard, {}, option
33+
end
34+
end
35+
end
36+
end # class << self
37+
end # module Device
38+
end # module Android
39+
end # module Appium

lib/appium_lib/device/device.rb

+6-20
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,8 @@ def app_installed?(app_id)
253253
end
254254

255255
add_endpoint_method(:background_app) do
256-
def background_app(duration = 0, driver = $driver)
257-
# https://github.com/appium/ruby_lib/issues/500, https://github.com/appium/appium/issues/7741
258-
# `execute :background_app, {}, seconds: { timeout: duration_milli_sec }` works over Appium 1.6.4
259-
if driver.automation_name_is_xcuitest?
260-
duration_milli_sec = duration.nil? ? nil : duration * 1000
261-
execute :background_app, {}, seconds: { timeout: duration_milli_sec }
262-
else
263-
execute :background_app, {}, seconds: duration
264-
end
256+
def background_app(duration = 0)
257+
execute :background_app, {}, seconds: duration
265258
end
266259
end
267260

@@ -292,19 +285,12 @@ def set_context(context = null)
292285
end
293286

294287
add_endpoint_method(:hide_keyboard) do
295-
def hide_keyboard(close_key = nil, strategy = nil, driver = $driver)
288+
def hide_keyboard(close_key = nil, strategy = nil)
296289
option = {}
297290

298-
if driver.device_is_android? # Android can only tapOutside.
299-
option[:key] = close_key if close_key
300-
option[:strategy] = strategy || :tapOutside # default to pressKey
301-
elsif driver.automation_name_is_xcuitest?
302-
option[:key] = close_key if close_key
303-
option[:strategy] = strategy if strategy
304-
else
305-
option[:key] = close_key || 'Done' # default to Done key.
306-
option[:strategy] = strategy || :pressKey # default to pressKey
307-
end
291+
option[:key] = close_key || 'Done' # default to Done key.
292+
option[:strategy] = strategy || :pressKey # default to pressKey
293+
308294
execute :hide_keyboard, {}, option
309295
end
310296
end

lib/appium_lib/device/multi_touch.rb

+14-13
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ def pinch(percentage = 25, auto_perform = true, driver = $driver)
2929
raise ArgumentError("Can't pinch to greater than screen size.") if percentage > 100
3030

3131
rate = Float(percentage) / 100
32+
pinch = MultiTouch.new(driver)
3233

33-
if driver.automation_name_is_xcuitest?
34-
top, bottom = pinch_for_xcuitest(rate, driver)
35-
elsif driver.device_is_android?
34+
if pinch.driver.automation_name_is_xcuitest?
35+
top, bottom = pinch_for_xcuitest(rate, pinch.driver)
36+
elsif pinch.driver.device_is_android?
3637
top, bottom = pinch_android(rate)
3738
else
3839
top, bottom = pinch_ios(rate)
3940
end
4041

41-
pinch = MultiTouch.new
4242
pinch.add top
4343
pinch.add bottom
4444
return pinch unless auto_perform
@@ -58,16 +58,16 @@ def zoom(percentage = 200, auto_perform = true, driver = $driver)
5858
raise ArgumentError("Can't zoom to smaller then screen size.") if percentage < 100
5959

6060
rate = 100 / Float(percentage)
61+
zoom = MultiTouch.new(driver)
6162

62-
if driver.automation_name_is_xcuitest?
63-
top, bottom = zoom_for_xcuitest(rate, driver)
64-
elsif driver.device_is_android?
63+
if zoom.driver.automation_name_is_xcuitest?
64+
top, bottom = zoom_for_xcuitest(rate, zoom.driver)
65+
elsif zoom.driver.device_is_android?
6566
top, bottom = zoom_android(rate)
6667
else
6768
top, bottom = zoom_ios(rate)
6869
end
6970

70-
zoom = MultiTouch.new
7171
zoom.add top
7272
zoom.add bottom
7373
return zoom unless auto_perform
@@ -163,11 +163,12 @@ def zoom_ios(rate)
163163
end
164164
end # self
165165

166-
attr_reader :actions
166+
attr_reader :actions, :driver
167167

168-
# Create a new multi-action
169-
def initialize
168+
# Create a new multi-action with Driver
169+
def initialize(driver = $driver)
170170
@actions = []
171+
@driver = driver
171172
end
172173

173174
# Add a touch_action to be performed
@@ -177,8 +178,8 @@ def add(chain)
177178
end
178179

179180
# Ask Appium to perform the actions
180-
def perform(driver = $driver)
181-
driver.multi_touch @actions
181+
def perform
182+
@driver.multi_touch @actions
182183
@actions.clear
183184
end
184185
end # class MultiTouch

lib/appium_lib/driver.rb

+12-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@
2424
require_relative 'ios/element/textfield'
2525
require_relative 'ios/element/text'
2626
require_relative 'ios/mobile_methods'
27-
require_relative 'ios/xcuitest_gestures'
27+
28+
# ios - xcuitest
29+
require_relative 'ios/xcuitest/element'
30+
require_relative 'ios/xcuitest/gestures'
31+
require_relative 'ios/xcuitest/mobile_methods'
32+
require_relative 'ios/xcuitest/device'
2833

2934
# android
3035
require_relative 'android/helper'
@@ -37,6 +42,8 @@
3742
require_relative 'android/element/text'
3843
require_relative 'android/mobile_methods'
3944

45+
require_relative 'android/device'
46+
4047
# device methods
4148
require_relative 'device/device'
4249
require_relative 'device/touch_actions'
@@ -391,11 +398,14 @@ def initialize(opts = {}, driver = $driver)
391398

392399
if device_is_android?
393400
extend Appium::Android
401+
extend Appium::Android::Device
394402
else
395403
extend Appium::Ios
396-
if automation_name_is_xcuitest? # Override touch actions
404+
if automation_name_is_xcuitest?
405+
# Override touch actions and patch_webdriver_element
397406
extend Appium::Ios::Xcuitest
398407
extend Appium::Ios::Xcuitest::Gesture
408+
extend Appium::Ios::Xcuitest::Device
399409
end
400410
end
401411

lib/appium_lib/ios/mobile_methods.rb

-20
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,5 @@ def extended(_mod)
2121
::Appium::Driver::SearchContext::FINDERS[:predicate] = '-ios predicate string'
2222
end
2323
end # class << self
24-
25-
module Xcuitest
26-
class << self
27-
# @!method ios_class_chain_find
28-
# Only for XCUITest(WebDriverAgent)
29-
# find_element/s can be used with a [class chain]( https://github.com/facebook/WebDriverAgent/wiki/Queries)
30-
#
31-
# ```ruby
32-
# # select the third child button of the first child window element
33-
# find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]'
34-
# # select all the children windows
35-
# find_elements :class_chain, 'XCUIElementTypeWindow'
36-
# # select the second last child of the second child window
37-
# find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]'
38-
# ```
39-
def extended(_mod)
40-
::Appium::Driver::SearchContext::FINDERS[:class_chain] = '-ios class chain'
41-
end
42-
end
43-
end
4424
end # module Ios
4525
end # module Appium

lib/appium_lib/ios/xcuitest/device.rb

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require 'base64'
2+
3+
module Appium
4+
module Ios
5+
module Xcuitest
6+
module Device
7+
extend Forwardable
8+
9+
# @!method hide_keyboard
10+
# Hide the onscreen keyboard
11+
# @param [String] close_key The name of the key which closes the keyboard.
12+
# @param [Symbol] strategy The symbol of the strategy which closes the keyboard.
13+
# XCUITest ignore this argument.
14+
# Default for iOS is `:pressKey`. Default for Android is `:tapOutside`.
15+
# ```ruby
16+
# hide_keyboard # Close a keyboard with the 'Done' button
17+
# hide_keyboard('Finished') # Close a keyboard with the 'Finished' button
18+
# ```
19+
20+
# @!method background_app
21+
# Backgrounds the app for a set number of seconds.
22+
# This is a blocking application
23+
# @param [Integer] seconds How many seconds to background the app for.
24+
#
25+
# ```ruby
26+
# background_app
27+
# background_app(5)
28+
# background_app(-1) #=> the app never come back. https://github.com/appium/appium/issues/7741
29+
# ```
30+
31+
class << self
32+
def extended(_mod)
33+
::Appium::Device.extend_webdriver_with_forwardable
34+
35+
::Appium::Device.add_endpoint_method(:hide_keyboard) do
36+
def hide_keyboard(close_key = nil, strategy = nil)
37+
option = {}
38+
39+
option[:key] = close_key if close_key
40+
option[:strategy] = strategy if strategy
41+
42+
execute :hide_keyboard, {}, option
43+
end
44+
end
45+
46+
::Appium::Device.add_endpoint_method(:background_app) do
47+
def background_app(duration = 0)
48+
# https://github.com/appium/ruby_lib/issues/500, https://github.com/appium/appium/issues/7741
49+
# `execute :background_app, {}, seconds: { timeout: duration_milli_sec }` works over Appium 1.6.4
50+
duration_milli_sec = duration.nil? ? nil : duration * 1000
51+
execute :background_app, {}, seconds: { timeout: duration_milli_sec }
52+
end
53+
end
54+
end
55+
end # class << self
56+
end # module Device
57+
end # module Xcuitest
58+
end # module Ios
59+
end # module Appium
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module Appium
2+
module Ios
3+
module Xcuitest
4+
# @private
5+
# class_eval inside a method because class Selenium::WebDriver::Element
6+
# will trigger as soon as the file is required. in contrast a method
7+
# will trigger only when invoked.
8+
def patch_webdriver_element
9+
Selenium::WebDriver::Element.class_eval do
10+
# Enable access to iOS accessibility label
11+
# accessibility identifier is supported as 'name'
12+
def label
13+
attribute('label')
14+
end
15+
16+
# Cross platform way of entering text into a textfield
17+
def type(text)
18+
send_keys text
19+
end # def type
20+
end # Selenium::WebDriver::Element.class_eval
21+
end # def patch_webdriver_element
22+
end # module Xcuitest
23+
end # module Ios
24+
end # module Appium
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Appium
2+
module Ios
3+
module Xcuitest
4+
class << self
5+
# @!method ios_class_chain_find
6+
# Only for XCUITest(WebDriverAgent)
7+
# find_element/s can be used with a [class chain]( https://github.com/facebook/WebDriverAgent/wiki/Queries)
8+
#
9+
# ```ruby
10+
# # select the third child button of the first child window element
11+
# find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]'
12+
# # select all the children windows
13+
# find_elements :class_chain, 'XCUIElementTypeWindow'
14+
# # select the second last child of the second child window
15+
# find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]'
16+
# ```
17+
def extended(_mod)
18+
::Appium::Driver::SearchContext::FINDERS[:class_chain] = '-ios class chain'
19+
end
20+
end
21+
end
22+
end # module Ios
23+
end # module Appium

0 commit comments

Comments
 (0)