Class: TestaAppiumDriver::Driver
- Inherits:
-
Object
- Object
- TestaAppiumDriver::Driver
- Includes:
- ClassSelectors, Helpers, TypeSelectors
- Defined in:
- lib/testa_appium_driver/driver.rb,
lib/testa_appium_driver/ios/driver.rb,
lib/testa_appium_driver/android/driver.rb
Instance Attribute Summary collapse
-
#automation_name ⇒ String
readonly
Driver automation name (uiautomator2 or xcuitest).
-
#device ⇒ String
readonly
IOS or Android.
-
#driver ⇒ ::Appium::Core::Base::Driver
The ruby_lib_core appium driver.
Instance Method Summary collapse
- #android? ⇒ Boolean
- #back ⇒ Object
- #click(x, y, double: false) ⇒ Object
-
#current_package ⇒ Object
@@return [String] current package under test.
-
#disable_implicit_wait ⇒ Object
disables implicit wait.
-
#disable_wait_for_idle ⇒ Object
disables wait for idle, only executed for android devices.
- #double_click(x, y) ⇒ Object
- #dpad_down_key ⇒ Object
- #dpad_left_key ⇒ Object
- #dpad_right_key ⇒ Object
- #dpad_up_key ⇒ Object
- #enter_key ⇒ Object
-
#execute(from_element, single, strategies_and_selectors, skip_cache: false, ignore_implicit_wait: false) ⇒ Selenium::WebDriver::Element, Array
Executes the find_element with the resolved locator strategy and selector.
- #first_and_last_child(from_element = @driver) ⇒ Object
-
#first_and_last_leaf(from_element = @driver) ⇒ Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page.
- #hide_keyboard ⇒ Object
- #home_key ⇒ Object
-
#initialize(opts = {}) ⇒ Driver
constructor
custom options - default_find_strategy: default strategy to be used for finding elements.
-
#invalidate_cache ⇒ Object
invalidates current find_element cache.
- #ios? ⇒ Boolean
- #is_keyboard_shown? ⇒ Boolean
- #long_press_keycode(code) ⇒ Object
-
#method_missing(method, *args, &block) ⇒ Object
method missing is used to forward methods to the actual appium driver after the method is executed, find element cache is invalidated.
- #press_keycode(code) ⇒ Object
- #restore_set_by_image_settings ⇒ Object
-
#scrollable ⇒ TestaAppiumDriver::Locator
First scrollable element.
-
#scrollables ⇒ TestaAppiumDriver::Locator
First scrollable element.
- #set_find_by_image_settings(settings) ⇒ Object
-
#shell(command, args: nil, timeout: nil, includeStderr: true) ⇒ Object
executes shell command.
- #tab_key ⇒ Object
- #window_size ⇒ Object
Methods included from ClassSelectors
#add_selector, #button, #buttons, #card_view, #card_views, #check_box, #check_boxes, #edit_text, #edit_texts, #element, #elements, #frame_layout, #frame_layouts, #horizontal_scroll_view, #horizontal_scroll_views, #image_button, #image_buttons, #image_view, #image_views, #linear_layout, #linear_layouts, #list_view, #list_views, #progress_bar, #progress_bars, #radio_button, #radio_buttons, #radio_group, #radio_groups, #recycler_view, #recycler_views, #relative_layout, #relative_layouts, #scroll_view, #scroll_views, #search_view, #search_views, #spinner, #spinners, #switch, #switches, #text_view, #text_views, #toast, #toasts, #toolbar, #toolbars, #view, #view_group, #view_groups, #view_pager, #view_pagers, #views, #web_view, #web_views
Methods included from TypeSelectors
#add_selector, #button, #buttons, #cell, #cells, #collection_view, #collection_views, #element, #elements, #image, #images, #navigation_bar, #navigation_bars, #other, #others, #scroll_view, #scroll_views, #secure_text_field, #secure_text_fields, #static_text, #static_texts, #table, #tables, #text_field, #text_fields, #window, #windows
Methods included from Helpers
#extract_selectors_from_params, #hash_to_class_chain, #hash_to_uiautomator, #hash_to_xpath, #is_scrollable_selector?, #resolve_id
Constructor Details
#initialize(opts = {}) ⇒ Driver
custom options
-
default_find_strategy: default strategy to be used for finding elements. Available strategies :uiautomator or :xpath
-
default_scroll_strategy: default strategy to be used for scrolling. Available strategies: :uiautomator(android only), :w3c
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/testa_appium_driver/driver.rb', line 29 def initialize(opts = {}) @testa_opts = opts[:testa_appium_driver] || {} core = Appium::Core.for(opts) @driver = core.start_driver @automation_name = @driver.capabilities["automationName"].downcase.to_sym @device = @driver.capabilities.platform_name.downcase.to_sym extend_for(@device, @automation_name) handle_testa_opts invalidate_cache #disable_wait_for_idle #disable_implicit_wait ::Appium::Core::Element.set_driver(self, @driver.capabilities["udid"]) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
method missing is used to forward methods to the actual appium driver after the method is executed, find element cache is invalidated
145 146 147 148 149 |
# File 'lib/testa_appium_driver/driver.rb', line 145 def method_missing(method, *args, &block) r = @driver.send(method, *args, &block) invalidate_cache r end |
Instance Attribute Details
#automation_name ⇒ String (readonly)
Returns driver automation name (uiautomator2 or xcuitest).
24 25 26 |
# File 'lib/testa_appium_driver/driver.rb', line 24 def automation_name @automation_name end |
#device ⇒ String (readonly)
Returns iOS or Android.
21 22 23 |
# File 'lib/testa_appium_driver/driver.rb', line 21 def device @device end |
#driver ⇒ ::Appium::Core::Base::Driver
Returns the ruby_lib_core appium driver.
18 19 20 |
# File 'lib/testa_appium_driver/driver.rb', line 18 def driver @driver end |
Instance Method Details
#android? ⇒ Boolean
308 309 310 |
# File 'lib/testa_appium_driver/driver.rb', line 308 def android? device == :android end |
#back ⇒ Object
201 202 203 |
# File 'lib/testa_appium_driver/driver.rb', line 201 def back @driver.back end |
#click(x, y, double: false) ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/testa_appium_driver/driver.rb', line 250 def click(x, y, double: false) ws = driver.window_size window_width = ws.width.to_i window_height = ws.height.to_i if x.kind_of?(Integer) if x < 0 x = window_width + x end elsif x.kind_of?(Float) && x <= 1.0 && x >= 0 x = window_width*x else raise "x value #{x} not supported. Use integer as pixel or float (0..1) as percentage of screen" end if y.kind_of?(Integer) if y < 0 y = window_height + y end elsif y.kind_of?(Float) && y <= 1.0 && y >= 0 y = window_height*y else raise "y value #{x} not supported. Use integer as pixel or float (0..1) as percentage of screen" end action_builder = @driver.action f1 = action_builder.add_pointer_input(:touch, "finger1") f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT) f1.create_pointer_down(:left) f1.create_pointer_up(:left) if double f1.create_pause(0.1) f1.create_pointer_down(:left) f1.create_pointer_up(:left) end @driver.perform_actions [f1] end |
#current_package ⇒ Object
@@return [String] current package under test
192 193 194 |
# File 'lib/testa_appium_driver/driver.rb', line 192 def current_package @driver.current_package end |
#disable_implicit_wait ⇒ Object
disables implicit wait
152 153 154 155 156 157 158 |
# File 'lib/testa_appium_driver/driver.rb', line 152 def disable_implicit_wait @implicit_wait_ms = @driver.get_timeouts["implicit"].to_i @implicit_wait_ms = @implicit_wait_ms/1000 if @implicit_wait_ms > 100000 @implicit_wait_uiautomator_ms = @driver.get_settings["waitForSelectorTimeout"] @driver.manage.timeouts.implicit_wait = 0 @driver.update_settings({waitForSelectorTimeout: 0}) end |
#disable_wait_for_idle ⇒ Object
disables wait for idle, only executed for android devices
161 162 163 164 165 166 |
# File 'lib/testa_appium_driver/driver.rb', line 161 def disable_wait_for_idle if @device == :android @wait_for_idle_timeout = @driver.settings.get["waitForIdleTimeout"] @driver.update_settings({waitForIdleTimeout: 0}) end end |
#double_click(x, y) ⇒ Object
288 289 290 |
# File 'lib/testa_appium_driver/driver.rb', line 288 def double_click(x,y) click(x,y, double: true) end |
#dpad_down_key ⇒ Object
226 227 228 |
# File 'lib/testa_appium_driver/driver.rb', line 226 def dpad_down_key @driver.press_keycode(20) end |
#dpad_left_key ⇒ Object
234 235 236 |
# File 'lib/testa_appium_driver/driver.rb', line 234 def dpad_left_key @driver.press_keycode(23) end |
#dpad_right_key ⇒ Object
230 231 232 |
# File 'lib/testa_appium_driver/driver.rb', line 230 def dpad_right_key @driver.press_keycode(22) end |
#dpad_up_key ⇒ Object
222 223 224 |
# File 'lib/testa_appium_driver/driver.rb', line 222 def dpad_up_key @driver.press_keycode(19) end |
#enter_key ⇒ Object
238 239 240 |
# File 'lib/testa_appium_driver/driver.rb', line 238 def enter_key @driver.press_keycode(66) end |
#execute(from_element, single, strategies_and_selectors, skip_cache: false, ignore_implicit_wait: false) ⇒ Selenium::WebDriver::Element, Array
Executes the find_element with the resolved locator strategy and selector. Find_element might be skipped if cache is hit. Cache stores last executed find_element with given selector, strategy and from_element. If given values are the same within last 5 seconds element is retrieved from cache.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/testa_appium_driver/driver.rb', line 72 def execute(from_element, single, strategies_and_selectors, skip_cache: false, ignore_implicit_wait: false) # if user wants to wait for element to exist, he can use wait_until_present start_time = Time.now.to_f ss_index = 0 # resolve from_element unique id, so that we can cache it properly from_element_id = from_element.instance_of?(TestaAppiumDriver::Locator) ? from_element.strategies_and_selectors : nil begin begin ss = strategies_and_selectors[ss_index % strategies_and_selectors.count] rescue ZeroDivisionError puts "aa" end ss_index +=1 puts "Executing #{from_element_id ? "from #{from_element.strategy}: #{from_element.strategies_and_selectors} => " : ""}#{ss.keys[0]}: #{ss.values[0]}" if @cache[:selector] != ss.values[0] || # cache miss, selector is different @cache[:time] + 5 <= Time.now || # cache miss, older than 5 seconds @cache[:strategy] != ss.keys[0] || # cache miss, different find strategy @cache[:from_element_id] != from_element_id || # cache miss, search is started from different element skip_cache # cache is skipped if ss.keys[0] == FIND_STRATEGY_IMAGE set_find_by_image_settings(ss.values[0].dup) if single execute_result = from_element.find_element_by_image(ss.values[0][:image]) else execute_result = from_element.find_elements_by_image(ss.values[0][:image]) end restore_set_by_image_settings else if single execute_result = from_element.find_element(ss) else execute_result = from_element.find_elements(ss) end end unless skip_cache @cache[:selector] = ss.values[0] @cache[:strategy] = ss.keys[0] @cache[:time] = Time.now @cache[:from_element_id] = from_element_id @cache[:element] = execute_result end else # this is a cache hit, use the element from cache execute_result = @cache[:element] puts "Using cache from #{@cache[:time].strftime("%H:%M:%S.%L")}, strategy: #{@cache[:strategy]}" end rescue => e #if (start_time + @implicit_wait_ms/1000 < Time.now.to_f && !ignore_implicit_wait) || ss_index < strategies_and_selectors.count if ss_index < strategies_and_selectors.count sleep EXISTS_WAIT if ss_index >= strategies_and_selectors.count retry else raise e end end execute_result end |
#first_and_last_child(from_element = @driver) ⇒ Object
301 302 303 304 305 306 |
# File 'lib/testa_appium_driver/driver.rb', line 301 def first_and_last_child(from_element = @driver) elements = from_element.find_elements(xpath: "./*") return nil if elements.count == 0 [elements[0], elements[-1]] end |
#first_and_last_leaf(from_element = @driver) ⇒ Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
Returns Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page.
295 296 297 298 299 |
# File 'lib/testa_appium_driver/driver.rb', line 295 def first_and_last_leaf(from_element = @driver) elements = from_element.find_elements(xpath: ".//*[not(*)]") return nil if elements.count == 0 [elements[0], elements[-1]] end |
#hide_keyboard ⇒ Object
210 211 212 |
# File 'lib/testa_appium_driver/driver.rb', line 210 def hide_keyboard @driver.hide_keyboard end |
#home_key ⇒ Object
214 215 216 |
# File 'lib/testa_appium_driver/driver.rb', line 214 def home_key @driver.press_keycode(3) end |
#invalidate_cache ⇒ Object
invalidates current find_element cache
51 52 53 54 55 56 57 58 59 |
# File 'lib/testa_appium_driver/driver.rb', line 51 def invalidate_cache @cache = { strategy: nil, selector: nil, element: nil, from_element: nil, time: Time.at(0) } end |
#ios? ⇒ Boolean
312 313 314 |
# File 'lib/testa_appium_driver/driver.rb', line 312 def ios? device == :ios end |
#is_keyboard_shown? ⇒ Boolean
206 207 208 |
# File 'lib/testa_appium_driver/driver.rb', line 206 def is_keyboard_shown? @driver.is_keyboard_shown end |
#long_press_keycode(code) ⇒ Object
246 247 248 |
# File 'lib/testa_appium_driver/driver.rb', line 246 def long_press_keycode(code) @driver.long_press_keycode(code) end |
#press_keycode(code) ⇒ Object
242 243 244 |
# File 'lib/testa_appium_driver/driver.rb', line 242 def press_keycode(code) @driver.press_keycode(code) end |
#restore_set_by_image_settings ⇒ Object
186 187 188 |
# File 'lib/testa_appium_driver/driver.rb', line 186 def restore_set_by_image_settings @driver.update_settings(@default_find_image_settings) if @default_find_image_settings end |
#scrollable ⇒ TestaAppiumDriver::Locator
Returns first scrollable element.
13 14 15 |
# File 'lib/testa_appium_driver/ios/driver.rb', line 13 def scrollable(params = {}) scroll_view(params) end |
#scrollables ⇒ TestaAppiumDriver::Locator
Returns first scrollable element.
19 20 21 |
# File 'lib/testa_appium_driver/ios/driver.rb', line 19 def scrollables(params = {}) scroll_views(params) end |
#set_find_by_image_settings(settings) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/testa_appium_driver/driver.rb', line 169 def set_find_by_image_settings(settings) settings.delete(:image) @default_find_image_settings = {} old_settings = @driver.get_settings @default_find_image_settings[:imageMatchThreshold] = old_settings["imageMatchThreshold"] @default_find_image_settings[:fixImageFindScreenshotDims] = old_settings["fixImageFindScreenshotDims"] @default_find_image_settings[:fixImageTemplateSize] = old_settings["fixImageTemplateSize"] @default_find_image_settings[:fixImageTemplateScale] = old_settings["fixImageTemplateScale"] @default_find_image_settings[:defaultImageTemplateScale] = old_settings["defaultImageTemplateScale"] @default_find_image_settings[:checkForImageElementStaleness] = old_settings["checkForImageElementStaleness"] @default_find_image_settings[:autoUpdateImageElementPosition] = old_settings["autoUpdateImageElementPosition"] @default_find_image_settings[:imageElementTapStrategy] = old_settings["imageElementTapStrategy"] @default_find_image_settings[:getMatchedImageResult] = old_settings["getMatchedImageResult"] @driver.update_settings(settings) end |
#shell(command, args: nil, timeout: nil, includeStderr: true) ⇒ Object
executes shell command
15 16 17 18 19 20 21 22 23 |
# File 'lib/testa_appium_driver/android/driver.rb', line 15 def shell(command, args: nil, timeout: nil, includeStderr: true) params = { command: command, includeStderr: includeStderr, } params[:args] = args unless args.nil? params[:timeout] = timeout unless timeout.nil? @driver.execute_script("mobile: shell", params) end |
#tab_key ⇒ Object
218 219 220 |
# File 'lib/testa_appium_driver/driver.rb', line 218 def tab_key @driver.press_keycode(61) end |
#window_size ⇒ Object
197 198 199 |
# File 'lib/testa_appium_driver/driver.rb', line 197 def window_size @driver.window_size end |