appium_lib_core 1.7.2 → 1.8.0

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.
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)