appium_lib_core 1.7.2 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/CHANGELOG.md +11 -0
  4. data/lib/appium_lib_core/android/device/clipboard.rb +4 -4
  5. data/lib/appium_lib_core/android/device/screen.rb +1 -1
  6. data/lib/appium_lib_core/android/uiautomator2/device/battery.rb +2 -2
  7. data/lib/appium_lib_core/common/base.rb +17 -0
  8. data/lib/appium_lib_core/common/base/bridge.rb +1 -0
  9. data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +15 -0
  10. data/lib/appium_lib_core/common/base/bridge/w3c.rb +19 -0
  11. data/lib/appium_lib_core/common/base/driver.rb +599 -1
  12. data/lib/appium_lib_core/common/base/screenshot.rb +18 -0
  13. data/lib/appium_lib_core/common/device/app_management.rb +87 -0
  14. data/lib/appium_lib_core/common/device/app_state.rb +30 -0
  15. data/lib/appium_lib_core/common/device/battery_status.rb +25 -0
  16. data/lib/appium_lib_core/common/device/clipboard_content_type.rb +11 -0
  17. data/lib/appium_lib_core/common/device/context.rb +38 -0
  18. data/lib/appium_lib_core/common/device/device.rb +19 -0
  19. data/lib/appium_lib_core/common/device/device_lock.rb +22 -0
  20. data/lib/appium_lib_core/common/device/file_management.rb +26 -0
  21. data/lib/appium_lib_core/common/device/image_comparison.rb +168 -0
  22. data/lib/appium_lib_core/common/device/ime_actions.rb +29 -0
  23. data/lib/appium_lib_core/common/device/keyboard.rb +22 -0
  24. data/lib/appium_lib_core/common/device/keyevent.rb +38 -0
  25. data/lib/appium_lib_core/common/device/screen_record.rb +54 -0
  26. data/lib/appium_lib_core/common/device/setting.rb +17 -0
  27. data/lib/appium_lib_core/common/device/touch_actions.rb +21 -0
  28. data/lib/appium_lib_core/common/device/value.rb +19 -0
  29. data/lib/appium_lib_core/device.rb +24 -547
  30. data/lib/appium_lib_core/driver.rb +14 -9
  31. data/lib/appium_lib_core/element/image.rb +1 -1
  32. data/lib/appium_lib_core/ios/device/clipboard.rb +4 -4
  33. data/lib/appium_lib_core/ios/xcuitest/device/battery.rb +2 -2
  34. data/lib/appium_lib_core/ios/xcuitest/device/performance.rb +1 -3
  35. data/lib/appium_lib_core/ios/xcuitest/device/screen.rb +1 -1
  36. data/lib/appium_lib_core/ios_xcuitest.rb +0 -2
  37. data/lib/appium_lib_core/version.rb +2 -2
  38. data/release_notes.md +10 -0
  39. metadata +18 -17
  40. data/lib/appium_lib_core/device/app_management.rb +0 -113
  41. data/lib/appium_lib_core/device/app_state.rb +0 -32
  42. data/lib/appium_lib_core/device/battery_status.rb +0 -23
  43. data/lib/appium_lib_core/device/clipboard_content_type.rb +0 -9
  44. data/lib/appium_lib_core/device/context.rb +0 -48
  45. data/lib/appium_lib_core/device/device_lock.rb +0 -28
  46. data/lib/appium_lib_core/device/file_management.rb +0 -32
  47. data/lib/appium_lib_core/device/image_comparison.rb +0 -178
  48. data/lib/appium_lib_core/device/ime_actions.rb +0 -43
  49. data/lib/appium_lib_core/device/keyboard.rb +0 -26
  50. data/lib/appium_lib_core/device/keyevent.rb +0 -44
  51. data/lib/appium_lib_core/device/screen_record.rb +0 -56
  52. data/lib/appium_lib_core/device/setting.rb +0 -21
  53. data/lib/appium_lib_core/device/touch_actions.rb +0 -22
  54. data/lib/appium_lib_core/device/value.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4396bf8502f02909fc45492b5f205554cd367f2
4
- data.tar.gz: ece56ca4022cef888da977917121a403df721b47
3
+ metadata.gz: '0973ef5a6046f3de9ee41ce9fc1d4d3d66529335'
4
+ data.tar.gz: e26a62a0620e8e79a493b47e972dc6d13c3e7cfb
5
5
  SHA512:
6
- metadata.gz: 261082f3a1f085f18d549ad837d0b93dac630886ddcd24e4c40420744efac7f9ef0490ab94c32d171ba58816cb2607bd476988513a558435723eb7448ed212cc
7
- data.tar.gz: f46ec6897d884275faa9260ef48c550c479e5173986e9464035e03d7af50e29ea576b97d2e33560e55ef0422c27990e5cb8b61dfe9d5761674ce3fd99cfbba51
6
+ metadata.gz: 067eda5fda5a52d0d3f3197b3228172d38144a5b9a92e8672fd0f2297eebb7d7f8469e3880e83870421c2b420956979c2e48e99d2d2b5c3f78b06eb48d539f42
7
+ data.tar.gz: bd9e058c3c294a68b575ae5732db43c743a17f9e79e05d878d9e4128a6c9f8da50acb63654088320a47dece2f71801b3f3dafd397a89d7334f6daafca9c8138b
data/.rubocop.yml CHANGED
@@ -14,6 +14,8 @@ Metrics/CyclomaticComplexity:
14
14
  Max: 10
15
15
  Metrics/PerceivedComplexity:
16
16
  Max: 10
17
+ Metrics/ParameterLists:
18
+ Max: 6
17
19
  Style/Documentation:
18
20
  Enabled: false
19
21
  Style/CommentedKeyword:
data/CHANGELOG.md CHANGED
@@ -8,8 +8,19 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  ### Deprecations
10
10
 
11
+ ## [1.8.0] - 2018-07-07
12
+ ### Enhancements
13
+ - Add Tizen case
14
+ - [Internal] reduce method definition by `add_endpoint_method`
15
+
16
+ ### Bug fixes
17
+
18
+ ### Deprecations
19
+
11
20
  ## [1.7.2] - 2018-06-23
12
21
  ### Enhancements
22
+ - Add `find_element_by_image` and `find_elements_by_image` to handle `ImageElement`
23
+ - Read [here](https://github.com/appium/ruby_lib_core/blob/a08c7c769d12316f3a410b28f93799682a111ed8/lib/appium_lib_core/common/base/driver.rb#L191-L257) for more details
13
24
  - Add a `ImageElement` to handle images as elements by `matchTemplate`
14
25
  - Experimental feature
15
26
  - [Internal] Define screenshot methods in appium_lib_core instead of Selenium's one
@@ -8,8 +8,8 @@ module Appium
8
8
  def self.add_methods
9
9
  ::Appium::Core::Device.add_endpoint_method(:get_clipboard) do
10
10
  def get_clipboard(content_type: :plaintext)
11
- unless ::Appium::Core::Device::Clipboard::CONTENT_TYPE.member?(content_type)
12
- raise "content_type should be #{::Appium::Core::Device::Clipboard::CONTENT_TYPE}"
11
+ unless ::Appium::Core::Base::Device::Clipboard::CONTENT_TYPE.member?(content_type)
12
+ raise "content_type should be #{::Appium::Core::Base::Device::Clipboard::CONTENT_TYPE}"
13
13
  end
14
14
 
15
15
  params = { contentType: content_type }
@@ -21,8 +21,8 @@ module Appium
21
21
 
22
22
  ::Appium::Core::Device.add_endpoint_method(:set_clipboard) do
23
23
  def set_clipboard(content:, content_type: :plaintext, label: nil)
24
- unless ::Appium::Core::Device::Clipboard::CONTENT_TYPE.member?(content_type)
25
- raise "content_type should be #{::Appium::Core::Device::Clipboard::CONTENT_TYPE}"
24
+ unless ::Appium::Core::Base::Device::Clipboard::CONTENT_TYPE.member?(content_type)
25
+ raise "content_type should be #{::Appium::Core::Base::Device::Clipboard::CONTENT_TYPE}"
26
26
  end
27
27
 
28
28
  params = {
@@ -14,7 +14,7 @@ module Appium
14
14
  # rubocop:disable Metrics/ParameterLists
15
15
  def start_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT', force_restart: nil,
16
16
  video_size: nil, time_limit: '180', bit_rate: nil, bug_report: nil)
17
- option = ::Appium::Core::Device::ScreenRecord.new(
17
+ option = ::Appium::Core::Base::Device::ScreenRecord.new(
18
18
  remote_path: remote_path, user: user, pass: pass, method: method, force_restart: force_restart
19
19
  ).upload_option
20
20
 
@@ -11,10 +11,10 @@ module Appium
11
11
 
12
12
  state = case response['state']
13
13
  when 2, 3, 4, 5
14
- ::Appium::Core::Device::BatteryStatus::ANDROID[response['state']]
14
+ ::Appium::Core::Base::Device::BatteryStatus::ANDROID[response['state']]
15
15
  else
16
16
  ::Appium::Logger.warn("The state is unknown or undefined: #{response['state']}")
17
- ::Appium::Core::Device::BatteryStatus::ANDROID[1] # :unknown
17
+ ::Appium::Core::Base::Device::BatteryStatus::ANDROID[1] # :unknown
18
18
  end
19
19
  { state: state, level: response['level'] }
20
20
  end
@@ -1,3 +1,20 @@
1
+ require_relative 'device/device_lock'
2
+ require_relative 'device/keyboard'
3
+ require_relative 'device/ime_actions'
4
+ require_relative 'device/setting'
5
+ require_relative 'device/context'
6
+ require_relative 'device/value'
7
+ require_relative 'device/file_management'
8
+ require_relative 'device/keyevent'
9
+ require_relative 'device/image_comparison'
10
+ require_relative 'device/app_management'
11
+ require_relative 'device/app_state'
12
+ require_relative 'device/screen_record'
13
+ require_relative 'device/battery_status'
14
+ require_relative 'device/clipboard_content_type'
15
+ require_relative 'device/device'
16
+ require_relative 'device/touch_actions'
17
+
1
18
  # The following files have selenium-webdriver related stuff.
2
19
  require_relative 'base/driver'
3
20
  require_relative 'base/bridge'
@@ -5,6 +5,7 @@ module Appium
5
5
  # Prefix for extra capability defined by W3C
6
6
  APPIUM_PREFIX = 'appium:'.freeze
7
7
 
8
+ # TODO: Remove the forceMjsonwp after Appium server won't need it
8
9
  FORCE_MJSONWP = :forceMjsonwp
9
10
 
10
11
  # Almost same as self.handshake in ::Selenium::WebDriver::Remote::Bridge
@@ -3,6 +3,21 @@ module Appium
3
3
  class Base
4
4
  class Bridge
5
5
  class MJSONWP < ::Selenium::WebDriver::Remote::OSS::Bridge
6
+ include Device::DeviceLock
7
+ include Device::Keyboard
8
+ include Device::ImeActions
9
+ include Device::Setting
10
+ include Device::Context
11
+ include Device::Value
12
+ include Device::FileManagement
13
+ include Device::KeyEvent
14
+ include Device::ImageComparison
15
+ include Device::AppManagement
16
+ include Device::AppState
17
+ include Device::ScreenRecord::Command
18
+ include Device::Device
19
+ include Device::TouchActions
20
+
6
21
  def commands(command)
7
22
  ::Appium::Core::Commands::MJSONWP::COMMANDS[command]
8
23
  end
@@ -5,6 +5,21 @@ module Appium
5
5
  class Base
6
6
  class Bridge
7
7
  class W3C < ::Selenium::WebDriver::Remote::W3C::Bridge
8
+ include Device::DeviceLock
9
+ include Device::Keyboard
10
+ include Device::ImeActions
11
+ include Device::Setting
12
+ include Device::Context
13
+ include Device::Value
14
+ include Device::FileManagement
15
+ include Device::KeyEvent
16
+ include Device::ImageComparison
17
+ include Device::AppManagement
18
+ include Device::AppState
19
+ include Device::ScreenRecord::Command
20
+ include Device::Device
21
+ include Device::TouchActions
22
+
8
23
  # Used for default duration of each touch actions
9
24
  # Override from 250 milliseconds to 50 milliseconds
10
25
  ::Selenium::WebDriver::PointerActions::DEFAULT_MOVE_DURATION = 0.05
@@ -204,6 +219,10 @@ module Appium
204
219
  end
205
220
  end
206
221
 
222
+ def take_viewport_screenshot
223
+ execute_script('mobile: viewportScreenshot')
224
+ end
225
+
207
226
  def take_element_screenshot(element)
208
227
  execute :take_element_screenshot, id: element.ref
209
228
  end
@@ -37,6 +37,574 @@ module Appium
37
37
  @bridge.dialect
38
38
  end
39
39
 
40
+ ### Methods for Appium
41
+
42
+ # Lock the device
43
+ # @return [String]
44
+ #
45
+ # @example
46
+ #
47
+ # @driver.lock #=> Lock the device
48
+ # @driver.lock(5) #=> Lock the device in 5 sec and unlock the device after 5 sec.
49
+ # # Block other commands during locking the device.
50
+ #
51
+ def lock(duration = nil)
52
+ @bridge.lock(duration)
53
+ end
54
+
55
+ # Check current device status is weather locked or not
56
+ #
57
+ # @example
58
+ #
59
+ # @driver.device_locked?
60
+ #
61
+ def device_locked?
62
+ @bridge.device_locked?
63
+ end
64
+
65
+ # Unlock the device
66
+ #
67
+ # @example
68
+ #
69
+ # @driver.unlock
70
+ #
71
+ def unlock
72
+ @bridge.unlock
73
+ end
74
+
75
+ # Hide the onscreen keyboard
76
+ # @param [String] close_key The name of the key which closes the keyboard.
77
+ # Defaults to 'Done' for iOS(except for XCUITest).
78
+ # @param [Symbol] strategy The symbol of the strategy which closes the keyboard.
79
+ # XCUITest ignore this argument.
80
+ # Default for iOS is `:pressKey`. Default for Android is `:tapOutside`.
81
+ #
82
+ # @example
83
+ #
84
+ # @driver.hide_keyboard # Close a keyboard with the 'Done' button
85
+ # @driver.hide_keyboard('Finished') # Close a keyboard with the 'Finished' button
86
+ # @driver.hide_keyboard(nil, :tapOutside) # Close a keyboard with tapping out side of keyboard
87
+ #
88
+ def hide_keyboard(close_key = nil, strategy = nil)
89
+ @bridge.hide_keyboard close_key, strategy
90
+ end
91
+
92
+ # Get whether keyboard is displayed or not.
93
+ # @return [Boolean] Return true if keyboard is shown. Return false if keyboard is hidden.
94
+ #
95
+ # @example
96
+ # @driver.is_keyboard_shown # false
97
+ #
98
+ def is_keyboard_shown # rubocop:disable Naming/PredicateName
99
+ @bridge.is_keyboard_shown
100
+ end
101
+
102
+ # Get appium Settings for current test session
103
+ #
104
+ # @example
105
+ #
106
+ # @driver.pull_folder '/data/local/tmp' #=> Get the folder at that path
107
+ #
108
+ def get_settings
109
+ @bridge.get_settings
110
+ end
111
+
112
+ # Update Appium Settings for current test session
113
+ # @param [Hash] settings Settings to update, keys are settings, values to value to set each setting to
114
+ #
115
+ # @example
116
+ #
117
+ # @driver.update_settings('allowInvisibleElements': true)
118
+ #
119
+ def update_settings(settings)
120
+ @bridge.update_settings(settings)
121
+ end
122
+
123
+ # Android only. Make an engine that is available active.
124
+ # @param [String] ime_name The IME owning the activity [required]
125
+ #
126
+ # @example
127
+ #
128
+ # ime_activate engine: 'com.android.inputmethod.latin/.LatinIME'
129
+ #
130
+ def ime_activate(ime_name)
131
+ @bridge.ime_activate(ime_name)
132
+ end
133
+
134
+ # Android only. List all available input engines on the machine.
135
+ #
136
+ # @example
137
+ #
138
+ # ime_available_engines #=> Get the list of IME installed in the target device
139
+ #
140
+ def ime_available_engines
141
+ @bridge.ime_available_engines
142
+ end
143
+
144
+ # Android only. Get the name of the active IME engine.
145
+ #
146
+ # @example
147
+ #
148
+ # ime_active_engine #=> Get the current active IME such as 'com.android.inputmethod.latin/.LatinIME'
149
+ #
150
+ def ime_active_engine
151
+ @bridge.ime_active_engine
152
+ end
153
+
154
+ # @!method ime_activated
155
+ # Android only. Indicates whether IME input is active at the moment (not if it is available).
156
+ #
157
+ # @example
158
+ #
159
+ # ime_activated #=> True if IME is activated
160
+ #
161
+ def ime_activated
162
+ @bridge.ime_activated
163
+ end
164
+
165
+ # Android only. De-activates the currently-active IME engine.
166
+ #
167
+ # @example
168
+ #
169
+ # ime_deactivate #=> Deactivate current IME engine
170
+ #
171
+ def ime_deactivate
172
+ @bridge.ime_deactivate
173
+ end
174
+
175
+ # Perform a block within the given context, then switch back to the starting context.
176
+ # @param [String] context The context to switch to for the duration of the block.
177
+ #
178
+ # @example
179
+ #
180
+ # result = @driver.within_context('NATIVE_APP') do
181
+ # @driver.find_element :tag, "button"
182
+ # end # The result of `find_element :tag, "button"`
183
+ #
184
+ def within_context(context)
185
+ @bridge.within_context(context)
186
+ end
187
+
188
+ # Change to the default context. This is equivalent to `set_context nil`.
189
+ #
190
+ # @example
191
+ #
192
+ # @driver.switch_to_default_context
193
+ #
194
+ def switch_to_default_context
195
+ @bridge.switch_to_default_context
196
+ end
197
+
198
+ # @return [String] The context currently being used.
199
+ #
200
+ # @example
201
+ #
202
+ # @driver.current_context
203
+ #
204
+ def current_context
205
+ @bridge.current_context
206
+ end
207
+
208
+ # @return [Array<String>] All usable contexts, as an array of strings.
209
+ #
210
+ # @example
211
+ #
212
+ # @driver.available_contexts
213
+ #
214
+ def available_contexts
215
+ @bridge.available_contexts
216
+ end
217
+
218
+ # Change the context to the given context.
219
+ # @param [String] context The context to change to
220
+ #
221
+ # @example
222
+ #
223
+ # @driver.set_context "NATIVE_APP"
224
+ #
225
+ def set_context(context = null)
226
+ @bridge.set_context(context)
227
+ end
228
+
229
+ # Set the value to element directly
230
+ #
231
+ # @example
232
+ #
233
+ # set_immediate_value element, 'hello'
234
+ #
235
+ def set_immediate_value(element, *value)
236
+ @bridge.set_immediate_value(element, *value)
237
+ end
238
+
239
+ # Replace the value to element directly
240
+ #
241
+ # @example
242
+ #
243
+ # replace_value element, 'hello'
244
+ #
245
+ def replace_value(element, *value)
246
+ @bridge.replace_value(element, *value)
247
+ end
248
+
249
+ # Place a file in a specific location on the device.
250
+ # On iOS, the server should have ifuse libraries installed and configured properly for this feature to work on
251
+ # real devices.
252
+ # On Android, the application under test should be built with debuggable flag enabled in order to get access to
253
+ # its container on the internal file system.
254
+ #
255
+ # @see https://github.com/libimobiledevice/ifuse iFuse GitHub page6
256
+ # @see https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ
257
+ # @see https://developer.android.com/studio/debug/ 'Debug Your App' developer article
258
+ #
259
+ # @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
260
+ # If the path starts with application id prefix, then the file will be pushed to the root of
261
+ # the corresponding application container.
262
+ # @param [String] filedata Raw file data to be sent to the device. Converted to base64 in the method.
263
+ #
264
+ # @example
265
+ #
266
+ # @driver.push_file "/file/to/path", "data"
267
+ #
268
+ def push_file(path, filedata)
269
+ @bridge.push_file(path, filedata)
270
+ end
271
+
272
+ # Pull a file from the simulator/device.
273
+ # On iOS the server should have ifuse
274
+ # libraries installed and configured properly for this feature to work on real devices.
275
+ # On Android the application under test should be built with debuggable flag enabled in order to get access
276
+ # to its container on the internal file system.
277
+ #
278
+ # @see https://github.com/libimobiledevice/ifuse iFuse GitHub page6
279
+ # @see https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ
280
+ # @see https://developer.android.com/studio/debug/ 'Debug Your App' developer article
281
+ #
282
+ # @param [String] path Either an absolute path OR, for iOS devices, a path relative to the app, as described.
283
+ # If the path starts with application id prefix, then the file will be pulled from the root
284
+ # of the corresponding application container.
285
+ # Otherwise the root folder is considered as / on Android and on iOS it is a media folder root
286
+ # (real devices only).
287
+ # @return [Base64-decoded] Base64 decoded data
288
+ #
289
+ # @example
290
+ #
291
+ # @driver.pull_file '/local/data/some/path' #=> Get the file at that path
292
+ # @driver.pull_file 'Shenanigans.app/some/file' #=> Get 'some/file' from the install location of Shenanigans.app
293
+ #
294
+ def pull_file(path)
295
+ @bridge.pull_file(path)
296
+ end
297
+
298
+ # Pull a folder content from the simulator/device.
299
+ # On iOS the server should have ifuse libraries installed and configured properly for this feature to work
300
+ # on real devices.
301
+ # On Android the application under test should be built with debuggable flag enabled in order to get access to
302
+ # its container on the internal file system.
303
+ #
304
+ # @see https://github.com/libimobiledevice/ifuse iFuse GitHub page6
305
+ # @see https://github.com/osxfuse/osxfuse/wiki/FAQ osxFuse FAQ
306
+ # @see https://developer.android.com/studio/debug/ 'Debug Your App' developer article
307
+ #
308
+ # @param [String] path Absolute path to the folder.
309
+ # If the path starts with <em>@applicationId/</em> prefix, then the folder will be pulled
310
+ # from the root of the corresponding application container.
311
+ # Otherwise the root folder is considered as / on Android and on iOS it is a media folder root
312
+ # (real devices only).
313
+ #
314
+ # @return [Base64-decoded] Base64 decoded data which is zip archived
315
+ #
316
+ # @example
317
+ #
318
+ # @driver.pull_folder '/data/local/tmp' #=> Get the folder at that path
319
+ #
320
+ def pull_folder(path)
321
+ @bridge.pull_folder(path)
322
+ end
323
+
324
+ # Send keyevent on the device.(Only for Selendroid)
325
+ # http://developer.android.com/reference/android/view/KeyEvent.html
326
+ # @param [integer] key The key to press.
327
+ # @param [String] metastate The state the metakeys should be in when pressing the key.
328
+ #
329
+ # @example
330
+ #
331
+ # @driver.keyevent 82
332
+ #
333
+ def keyevent(key, metastate = nil)
334
+ @bridge.keyevent(key, metastate)
335
+ end
336
+
337
+ # Press keycode on the device.
338
+ # http://developer.android.com/reference/android/view/KeyEvent.html
339
+ # @param [Integer] key The key to press. The values which have `KEYCODE_` prefix in http://developer.android.com/reference/android/view/KeyEvent.html
340
+ # e.g.: KEYCODE_HOME is `3` or `0x00000003`
341
+ # @param [[Integer]] metastate: The state the metakeys should be in when pressing the key. Default is empty Array.
342
+ # Metastate have `META_` prefix in https://developer.android.com/reference/android/view/KeyEvent.html
343
+ # e.g.: META_SHIFT_ON is `1` or `0x00000001`
344
+ # @param [[Integer]] flags: Native Android flag value. Several flags can be combined into a single key event.
345
+ # Default is empty Array. Can set multiple flags as Array.
346
+ # Flags have `FLAG_` prefix in http://developer.android.com/reference/android/view/KeyEvent.html
347
+ # e.g.: FLAG_CANCELED is `32` or `0x00000020`
348
+ #
349
+ # @example
350
+ #
351
+ # @driver.press_keycode 66
352
+ # @driver.press_keycode 66, flags: [0x02]
353
+ # @driver.press_keycode 66, metastate: [1], flags: [32]
354
+ #
355
+ def press_keycode(key, metastate: [], flags: [])
356
+ @bridge.press_keycode(key, metastate: metastate, flags: flags)
357
+ end
358
+
359
+ # Long press keycode on the device.
360
+ # http://developer.android.com/reference/android/view/KeyEvent.html
361
+ # @param [Integer] key The key to long press. The values which have `KEYCODE_` prefix in http://developer.android.com/reference/android/view/KeyEvent.html
362
+ # e.g.: KEYCODE_HOME is `3` or `0x00000003`
363
+ # @param [[Integer]] metastate: The state the metakeys should be in when pressing the key. Default is empty Array.
364
+ # Metastate have `META_` prefix in https://developer.android.com/reference/android/view/KeyEvent.html
365
+ # e.g.: META_SHIFT_ON is `1` or `0x00000001`
366
+ # @param [[Integer]] flags: Native Android flag value. Several flags can be combined into a single key event.
367
+ # Default is empty Array. Can set multiple flags as Array.
368
+ # Flags have `FLAG_` prefix in http://developer.android.com/reference/android/view/KeyEvent.html
369
+ # e.g.: FLAG_CANCELED is `32` or `0x00000020`
370
+ #
371
+ # @example
372
+ #
373
+ # @driver.long_press_keycode 66
374
+ # @driver.long_press_keycode 66, flags: [0x20, 0x2000]
375
+ # @driver.long_press_keycode 66, metastate: [1], flags: [32, 8192]
376
+ #
377
+ def long_press_keycode(key, metastate: [], flags: [])
378
+ @bridge.long_press_keycode(key, metastate: metastate, flags: flags)
379
+ end
380
+
381
+ # Start the simulator and application configured with desired capabilities
382
+ #
383
+ # @example
384
+ #
385
+ # @driver.launch_app
386
+ #
387
+ def launch_app
388
+ @bridge.launch_app
389
+ end
390
+
391
+ # Close an app on device
392
+ #
393
+ # @example
394
+ #
395
+ # @driver.close_app
396
+ #
397
+ def close_app
398
+ @bridge.close_app
399
+ end
400
+
401
+ # Reset the device, relaunching the application.
402
+ #
403
+ # @example
404
+ #
405
+ # @driver.reset
406
+ #
407
+ def reset
408
+ @bridge.reset
409
+ end
410
+
411
+ # Return the hash of all localization strings.
412
+ # @return [Hash]
413
+ #
414
+ # @example
415
+ #
416
+ # @driver.app_strings #=> "TransitionsTitle"=>"Transitions", "WebTitle"=>"Web"
417
+ #
418
+ def app_strings(language = nil)
419
+ @bridge.app_strings(language)
420
+ end
421
+
422
+ # Backgrounds the app for a set number of seconds.
423
+ # This is a blocking application
424
+ # @param [Integer] duration How many seconds to background the app for.
425
+ # @return [String]
426
+ #
427
+ # @example
428
+ #
429
+ # @driver.background_app
430
+ # @driver.background_app(5)
431
+ # @driver.background_app(-1) #=> the app never come back. https://github.com/appium/appium/issues/7741
432
+ #
433
+ def background_app(duration = 0)
434
+ @bridge.background_app(duration)
435
+ end
436
+
437
+ # Install the given app onto the device
438
+ #
439
+ # @param [String] path The absolute local path or remote http URL to an .ipa or .apk file,
440
+ # or a .zip containing one of these.
441
+ # @param [Boolean] replace: Only for Android. Whether to reinstall/upgrade the package if it is already present
442
+ # on the device under test. `true` by default
443
+ # @param [Integer] timeout: Only for Android. How much time to wait for the installation to complete.
444
+ # 60000ms by default.
445
+ # @param [Boolean] allow_test_packages: Only for Android. Whether to allow installation of packages marked as test
446
+ # in the manifest. `false` by default
447
+ # @param [Boolean] use_sdcard: Only for Android. Whether to use the SD card to install the app. `false` by default
448
+ # @param [Boolean] grant_permissions: Only for Android. whether to automatically grant application permissions
449
+ # on Android 6+ after the installation completes. `false` by default
450
+ #
451
+ # @example
452
+ #
453
+ # @driver.install_app("/path/to/test.apk")
454
+ # @driver.install_app("/path/to/test.apk", replace: true, timeout: 20000, allow_test_packages: true,
455
+ # use_sdcard: false, grant_permissions: false)
456
+ #
457
+ def install_app(path,
458
+ replace: nil,
459
+ timeout: nil,
460
+ allow_test_packages: nil,
461
+ use_sdcard: nil,
462
+ grant_permissions: nil)
463
+ @bridge.install_app(path,
464
+ replace: replace,
465
+ timeout: timeout,
466
+ allow_test_packages: allow_test_packages,
467
+ use_sdcard: use_sdcard,
468
+ grant_permissions: grant_permissions)
469
+ end
470
+
471
+ # @param [Strong] app_id BundleId for iOS or package name for Android
472
+ # @param [Boolean] keep_data: Only for Android. Whether to keep application data and caches after it is uninstalled.
473
+ # `false` by default
474
+ # @param [Integer] timeout: Only for Android. How much time to wait for the uninstall to complete. 20000ms by default.
475
+ #
476
+ # @example
477
+ #
478
+ # @driver.remove_app("io.appium.bundle")
479
+ # @driver.remove_app("io.appium.bundle", keep_data: false, timeout, 10000)
480
+ #
481
+ def remove_app(app_id, keep_data: nil, timeout: nil)
482
+ @bridge.remove_app(app_id, keep_data: keep_data, timeout: timeout)
483
+ end
484
+
485
+ # Check whether the specified app is installed on the device
486
+ # @return [Boolean]
487
+ #
488
+ # @example
489
+ #
490
+ # @driver.app_installed?("io.appium.bundle")
491
+ #
492
+ def app_installed?(app_id)
493
+ @bridge.app_installed?(app_id)
494
+ end
495
+
496
+ # Activate(Launch) the specified app.
497
+ # @return [Hash]
498
+ #
499
+ # @example
500
+ #
501
+ # @driver.activate_app("io.appium.bundle") #=> {}
502
+ #
503
+ def activate_app(app_id)
504
+ @bridge.activate_app(app_id)
505
+ end
506
+
507
+ # Terminate the specified app.
508
+ #
509
+ # @param [Strong] app_id BundleId for iOS or package name for Android
510
+ # @param [Integer] timeout: Only for Android. How much time to wait for the application termination to complete.
511
+ # 500ms by default.
512
+ # @return [Boolean]
513
+ #
514
+ # @example
515
+ #
516
+ # @driver.terminate_app("io.appium.bundle") # true
517
+ # @driver.terminate_app("io.appium.bundle", timeout: 500)
518
+ #
519
+ def terminate_app(app_id, timeout: nil)
520
+ @bridge.terminate_app(app_id, timeout: timeout)
521
+ end
522
+
523
+ # Get the status of an existing application on the device.
524
+ # State:
525
+ # :not_installed : The current application state cannot be determined/is unknown
526
+ # :not_running : The application is not running
527
+ # :running_in_background_suspended : The application is running in the background and is suspended
528
+ # :running_in_background : The application is running in the background and is not suspended
529
+ # :running_in_foreground : The application is running in the foreground
530
+ #
531
+ # For more details: https://developer.apple.com/documentation/xctest/xcuiapplicationstate
532
+ #
533
+ # @param [String] app_id A target app's bundle id
534
+ # @return [AppState::STATUS] A number of the state
535
+ #
536
+ # @example
537
+ #
538
+ # @driver.app_state("io.appium.bundle") #=> :not_running
539
+ #
540
+ def app_state(app_id)
541
+ @bridge.app_state(app_id)
542
+ end
543
+
544
+ # @param [String] remote_path: The path to the remote location, where the resulting video should be uploaded.
545
+ # The following protocols are supported: http/https, ftp.
546
+ # Null or empty string value (the default setting) means the content of resulting
547
+ # file should be encoded as Base64 and passed as the endpoint response value.
548
+ # An exception will be thrown if the generated media file is too big to
549
+ # fit into the available process memory.
550
+ # @param [String] user: The name of the user for the remote authentication.
551
+ # @param [String] pass: The password for the remote authentication.
552
+ # @param [String] method: The http multipart upload method name. The 'PUT' one is used by default.
553
+ #
554
+ # @example
555
+ #
556
+ # @driver.stop_recording_screen
557
+ # @driver.stop_recording_screen remote_path: 'https://example.com', user: 'example', pass: 'pass', method: 'POST'
558
+ #
559
+ def stop_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT')
560
+ @bridge.stop_recording_screen(remote_path: remote_path, user: user, pass: pass, method: method)
561
+ end
562
+
563
+ # @param [String] file_path The path to save video decoded from base64 from Appium server.
564
+ #
565
+ # @example
566
+ #
567
+ # @driver.stop_and_save_recording_screen 'example.mp4'
568
+ #
569
+ def stop_and_save_recording_screen(file_path)
570
+ @bridge.stop_and_save_recording_screen(file_path)
571
+ end
572
+
573
+ # Cause the device to shake
574
+ #
575
+ # @example
576
+ #
577
+ # @driver.shake
578
+ #
579
+ def shake
580
+ @bridge.shake
581
+ end
582
+
583
+ # Get the time on the device
584
+ #
585
+ # @param [String] format The set of format specifiers. Read https://momentjs.com/docs/ to get
586
+ # the full list of supported datetime format specifiers.
587
+ # The default format is `YYYY-MM-DDTHH:mm:ssZ`, which complies to ISO-8601
588
+ # @return [String] Formatted datetime string or the raw command output if formatting fails
589
+ #
590
+ # @example
591
+ #
592
+ # @driver.device_time #=> "2018-06-12T11:13:31+02:00"
593
+ # @driver.device_time "YYYY-MM-DD" #=> "2018-06-12"
594
+ #
595
+ def device_time(format = nil)
596
+ @bridge.device_time(format)
597
+ end
598
+
599
+ # touch actions
600
+ def touch_actions(actions)
601
+ @bridge.touch_actions(actions)
602
+ end
603
+
604
+ def multi_touch(actions)
605
+ @bridge.multi_touch(actions)
606
+ end
607
+
40
608
  # Get the device window's size.
41
609
  # @return [Selenium::WebDriver::Dimension]
42
610
  #
@@ -188,6 +756,36 @@ module Appium
188
756
 
189
757
  DEFAULT_MATCH_THRESHOLD = 0.5
190
758
 
759
+ # Image Comparison
760
+ def match_images_features(first_image:,
761
+ second_image:,
762
+ detector_name: 'ORB',
763
+ match_func: 'BruteForce',
764
+ good_matches_factor: nil,
765
+ visualize: false)
766
+ @bridge.match_images_features(first_image: first_image,
767
+ second_image: second_image,
768
+ detector_name: detector_name,
769
+ match_func: match_func,
770
+ good_matches_factor: good_matches_factor,
771
+ visualize: visualize)
772
+ end
773
+
774
+ def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil)
775
+ @bridge.find_image_occurrence(full_image: full_image,
776
+ partial_image: partial_image,
777
+ visualize: visualize,
778
+ threshold: threshold)
779
+ end
780
+
781
+ def get_images_similarity(first_image:, second_image:, visualize: false)
782
+ @bridge.get_images_similarity(first_image: first_image, second_image: second_image, visualize: visualize)
783
+ end
784
+
785
+ def compare_images(mode: :matchFeatures, first_image:, second_image:, options: nil)
786
+ @bridge.compare_images(mode: mode, first_image: first_image, second_image: second_image, options: options)
787
+ end
788
+
191
789
  # Return ImageElement if current view has a partial image
192
790
  #
193
791
  # @param [String] png_img_path A path to a partial image you'd like to find
@@ -234,7 +832,7 @@ module Appium
234
832
  #
235
833
  # @example
236
834
  #
237
- # e = @@driver.find_elements_by_image './test/functional/data/test_element_image.png'
835
+ # e = @@driver.find_elements_by_image ['./test/functional/data/test_element_image.png']
238
836
  # e == [] # if the `e` is empty
239
837
  #
240
838
  def find_elements_by_image(png_img_paths, match_threshold: DEFAULT_MATCH_THRESHOLD, visualize: false)