appium_lib_core 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 816965726811ed0e4814ff74f562f821a1d02a96
4
- data.tar.gz: 48de6d03d02f08681e80b2f830e415016016b57f
3
+ metadata.gz: 1f5dd97d1cbe46c9a3de56622d0235855c17d5fa
4
+ data.tar.gz: 8ae9a77dd25ac92e3c6c2028f2e2366f770d4b7c
5
5
  SHA512:
6
- metadata.gz: fe453c38eee0cdf8405c19580f48de596338054bd4208e245a81825da5d229c65732c62327047f0da48169e2522dacbd8181ffe70c357abd25f6f2f938a70a80
7
- data.tar.gz: da619b8b509db626f9dfbadc38048d9673e632bd505cb343750b3f6153b8871fd59c3d20d426656e3b741e320b498bfa4f94548ced25d145a0fb595df9087f1b
6
+ metadata.gz: d6239c7d4e68eb97e9f9bb55cd727f585a671baee664d89fb8f08f7ff86f40fc7bc68753575154709ce5ee963d1a90bc3a02a3234c182b49051ef08cab4fe635
7
+ data.tar.gz: 66925a81fe4e906508ac090bc606053ebc0fcb05a870fdbbc7cd81b9cad56229b2301b7d8109c6618d8dfe259275713c9eacfc5306b89170c65d314159bde129
@@ -11,9 +11,9 @@ Metrics/ClassLength:
11
11
  Metrics/AbcSize:
12
12
  Enabled: false
13
13
  Metrics/CyclomaticComplexity:
14
- Max: 8
14
+ Max: 9
15
15
  Metrics/PerceivedComplexity:
16
- Max: 8
16
+ Max: 9
17
17
  Style/Documentation:
18
18
  Enabled: false
19
19
  Style/CommentedKeyword:
@@ -8,6 +8,17 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  ### Deprecations
10
10
 
11
+ ## [1.4.1] - 2018-04-22
12
+ ### Enhancements
13
+ - add base image comparison
14
+ - `match_images_features`, `find_image_occurrence`, `get_images_similarity`, `compare_images`
15
+ - [internal] No longer have dependency for Selenium's wait
16
+ - [internal] Separate mjsonwp commands module and w3c commands module from one command module
17
+
18
+ ### Bug fixes
19
+
20
+ ### Deprecations
21
+
11
22
  ## [1.4.0] - 2018-04-15
12
23
  ### Enhancements
13
24
  - Add a support for WebSocket client based on Faye::WebSocket::Client [#74](https://github.com/appium/ruby_lib_core/pull/74)
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ['lib']
24
24
 
25
25
  spec.add_runtime_dependency 'selenium-webdriver', '~> 3.5'
26
- spec.add_runtime_dependency 'json', '>= 1.8'
27
26
  spec.add_runtime_dependency 'faye-websocket', '~> 0.10.0'
28
27
 
29
28
  spec.add_development_dependency 'bundler', '~> 1.14'
@@ -5,12 +5,7 @@ require_relative 'appium_lib_core/common'
5
5
  require_relative 'appium_lib_core/patch'
6
6
  require_relative 'appium_lib_core/driver'
7
7
 
8
- # for multi touch related methods
9
- require_relative 'appium_lib_core/device/touch_actions'
10
- require_relative 'appium_lib_core/device/multi_touch'
11
- require_relative 'appium_lib_core/device/screen_record'
12
- require_relative 'appium_lib_core/device/app_state'
13
- require_relative 'appium_lib_core/device/clipboard_content_type'
8
+ require_relative 'appium_lib_core/device'
14
9
 
15
10
  require_relative 'appium_lib_core/android'
16
11
  require_relative 'appium_lib_core/android_uiautomator2'
@@ -2,6 +2,6 @@ require_relative 'common/logger'
2
2
  require_relative 'common/error'
3
3
  require_relative 'common/log'
4
4
  require_relative 'common/command'
5
- require_relative 'common/device'
6
5
  require_relative 'common/base'
6
+ require_relative 'common/wait'
7
7
  require_relative 'common/ws/websocket'
@@ -1,10 +1,9 @@
1
1
  # The following files have selenium-webdriver related stuff.
2
2
  require_relative 'base/driver'
3
3
  require_relative 'base/bridge'
4
- require_relative 'base/bridge/msjsonwp'
4
+ require_relative 'base/bridge/mjsonwp'
5
5
  require_relative 'base/bridge/w3c'
6
6
  require_relative 'base/capabilities'
7
7
  require_relative 'base/http_default'
8
8
  require_relative 'base/search_context'
9
9
  require_relative 'base/command'
10
- require_relative 'base/wait'
@@ -4,7 +4,7 @@ module Appium
4
4
  class Bridge
5
5
  class MJSONWP < ::Selenium::WebDriver::Remote::OSS::Bridge
6
6
  def commands(command)
7
- ::Appium::Core::Commands::COMMANDS_EXTEND_MJSONWP[command]
7
+ ::Appium::Core::Commands::MJSONWP::COMMANDS[command]
8
8
  end
9
9
  end # class MJSONWP
10
10
  end # class Bridge
@@ -8,7 +8,7 @@ module Appium
8
8
  ::Selenium::WebDriver::PointerActions::DEFAULT_MOVE_DURATION = 0.05
9
9
 
10
10
  def commands(command)
11
- ::Appium::Core::Commands::COMMANDS_EXTEND_W3C[command]
11
+ ::Appium::Core::Commands::W3C::COMMANDS[command]
12
12
  end
13
13
 
14
14
  # Perform touch actions for W3C module.
@@ -1,132 +1,4 @@
1
1
  require_relative 'base/command'
2
-
3
- module Appium
4
- module Core
5
- # ref: https://github.com/appium/appium-base-driver/blob/master/lib/mjsonwp/routes.js
6
- module Commands
7
- # Some commands differ for each driver.
8
- COMMAND = {
9
- # common
10
- available_contexts: [:get, 'session/:session_id/contexts'.freeze],
11
- set_context: [:post, 'session/:session_id/context'.freeze],
12
- current_context: [:get, 'session/:session_id/context'.freeze],
13
-
14
- touch_actions: [:post, 'session/:session_id/touch/perform'.freeze],
15
- multi_touch: [:post, 'session/:session_id/touch/multi/perform'.freeze],
16
-
17
- set_immediate_value: [:post, 'session/:session_id/appium/element/:id/value'.freeze],
18
- replace_value: [:post, 'session/:session_id/appium/element/:id/replace_value'.freeze],
19
-
20
- launch_app: [:post, 'session/:session_id/appium/app/launch'.freeze],
21
- close_app: [:post, 'session/:session_id/appium/app/close'.freeze],
22
- reset: [:post, 'session/:session_id/appium/app/reset'.freeze],
23
- background_app: [:post, 'session/:session_id/appium/app/background'.freeze],
24
- app_strings: [:post, 'session/:session_id/appium/app/strings'.freeze],
25
-
26
- device_locked?: [:post, 'session/:session_id/appium/device/is_locked'.freeze],
27
- unlock: [:post, 'session/:session_id/appium/device/unlock'.freeze],
28
- lock: [:post, 'session/:session_id/appium/device/lock'.freeze],
29
- device_time: [:get, 'session/:session_id/appium/device/system_time'.freeze],
30
- install_app: [:post, 'session/:session_id/appium/device/install_app'.freeze],
31
- remove_app: [:post, 'session/:session_id/appium/device/remove_app'.freeze],
32
- app_installed?: [:post, 'session/:session_id/appium/device/app_installed'.freeze],
33
- activate_app: [:post, 'session/:session_id/appium/device/activate_app'.freeze],
34
- terminate_app: [:post, 'session/:session_id/appium/device/terminate_app'.freeze],
35
- app_state: [:post, 'session/:session_id/appium/device/app_state'.freeze],
36
- shake: [:post, 'session/:session_id/appium/device/shake'.freeze],
37
- hide_keyboard: [:post, 'session/:session_id/appium/device/hide_keyboard'.freeze],
38
- press_keycode: [:post, 'session/:session_id/appium/device/press_keycode'.freeze],
39
- long_press_keycode: [:post, 'session/:session_id/appium/device/long_press_keycode'.freeze],
40
- # keyevent is only for Selendroid
41
- keyevent: [:post, 'session/:session_id/appium/device/keyevent'.freeze],
42
- push_file: [:post, 'session/:session_id/appium/device/push_file'.freeze],
43
- pull_file: [:post, 'session/:session_id/appium/device/pull_file'.freeze],
44
- pull_folder: [:post, 'session/:session_id/appium/device/pull_folder'.freeze],
45
- get_clipboard: [:post, 'session/:session_id/appium/device/get_clipboard'.freeze],
46
- set_clipboard: [:post, 'session/:session_id/appium/device/set_clipboard'.freeze],
47
- get_settings: [:get, 'session/:session_id/appium/settings'.freeze],
48
- update_settings: [:post, 'session/:session_id/appium/settings'.freeze],
49
- stop_recording_screen: [:post, 'session/:session_id/appium/stop_recording_screen'.freeze],
50
- start_recording_screen: [:post, 'session/:session_id/appium/start_recording_screen'.freeze]
51
- }.freeze
52
-
53
- COMMAND_ANDROID = {
54
- open_notifications: [:post, 'session/:session_id/appium/device/open_notifications'.freeze],
55
- toggle_airplane_mode: [:post, 'session/:session_id/appium/device/toggle_airplane_mode'.freeze],
56
- start_activity: [:post, 'session/:session_id/appium/device/start_activity'.freeze],
57
- current_activity: [:get, 'session/:session_id/appium/device/current_activity'.freeze],
58
- current_package: [:get, 'session/:session_id/appium/device/current_package'.freeze],
59
- get_system_bars: [:get, 'session/:session_id/appium/device/system_bars'.freeze],
60
- get_display_density: [:get, 'session/:session_id/appium/device/display_density'.freeze],
61
- is_keyboard_shown: [:get, 'session/:session_id/appium/device/is_keyboard_shown'.freeze],
62
- toggle_wifi: [:post, 'session/:session_id/appium/device/toggle_wifi'.freeze],
63
- toggle_data: [:post, 'session/:session_id/appium/device/toggle_data'.freeze],
64
- toggle_location_services: [:post, 'session/:session_id/appium/device/toggle_location_services'.freeze],
65
- end_coverage: [:post, 'session/:session_id/appium/app/end_test_coverage'.freeze],
66
- get_performance_data_types: [:post, 'session/:session_id/appium/performanceData/types'.freeze],
67
- get_performance_data: [:post, 'session/:session_id/appium/getPerformanceData'.freeze],
68
- get_network_connection: [:get, 'session/:session_id/network_connection'.freeze], # defined also in OSS
69
- set_network_connection: [:post, 'session/:session_id/network_connection'.freeze], # defined also in OSS
70
-
71
- # only emulator
72
- send_sms: [:post, 'session/:session_id/appium/device/send_sms'.freeze],
73
- gsm_call: [:post, 'session/:session_id/appium/device/gsm_call'.freeze],
74
- gsm_signal: [:post, 'session/:session_id/appium/device/gsm_signal'.freeze],
75
- gsm_voice: [:post, 'session/:session_id/appium/device/gsm_voice'.freeze],
76
- set_network_speed: [:post, 'session/:session_id/appium/device/network_speed'.freeze],
77
- set_power_capacity: [:post, 'session/:session_id/appium/device/power_capacity'.freeze],
78
- set_power_ac: [:post, 'session/:session_id/appium/device/power_ac'.freeze]
79
- }.freeze
80
-
81
- COMMAND_IOS = {
82
- touch_id: [:post, 'session/:session_id/appium/simulator/touch_id'.freeze],
83
- toggle_touch_id_enrollment: [:post, 'session/:session_id/appium/simulator/toggle_touch_id_enrollment'.freeze]
84
- }.freeze
85
-
86
- COMMANDS = {}.merge(COMMAND).merge(COMMAND_ANDROID).merge(COMMAND_IOS).freeze
87
-
88
- COMMANDS_EXTEND_MJSONWP = COMMANDS.merge(::Appium::Core::Base::Commands::OSS).merge(
89
- {
90
- # W3C already has.
91
- take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'.freeze]
92
- }
93
- ).freeze
94
- COMMANDS_EXTEND_W3C = COMMANDS.merge(::Appium::Core::Base::Commands::W3C).merge(
95
- {
96
- # ::Appium::Core::Base::Commands::OSS has the following commands and Appium also use them.
97
- # Delegated to ::Appium::Core::Base::Commands::OSS commands
98
- status: [:get, 'status'.freeze],
99
- is_element_displayed: [:get, 'session/:session_id/element/:id/displayed'.freeze],
100
-
101
- # FIXME: remove after apply https://github.com/SeleniumHQ/selenium/pull/5249
102
- # The fix will be included in selenium-3.8.2
103
- get_page_source: [:get, 'session/:session_id/source'.freeze],
104
-
105
- get_timeouts: [:get, 'session/:session_id/timeouts'.freeze],
106
-
107
- ## Add OSS commands to W3C commands. We can remove them if we would like to remove them from W3C module.
108
- ### Session capability
109
- get_capabilities: [:get, 'session/:session_id'.freeze],
110
-
111
- ### rotatable
112
- get_screen_orientation: [:get, 'session/:session_id/orientation'.freeze],
113
- set_screen_orientation: [:post, 'session/:session_id/orientation'.freeze],
114
-
115
- get_location: [:get, 'session/:session_id/location'.freeze],
116
- set_location: [:post, 'session/:session_id/location'.freeze],
117
-
118
- ### For IME
119
- ime_get_available_engines: [:get, 'session/:session_id/ime/available_engines'.freeze],
120
- ime_get_active_engine: [:get, 'session/:session_id/ime/active_engine'.freeze],
121
- ime_is_activated: [:get, 'session/:session_id/ime/activated'.freeze],
122
- ime_deactivate: [:post, 'session/:session_id/ime/deactivate'.freeze],
123
- ime_activate_engine: [:post, 'session/:session_id/ime/activate'.freeze],
124
-
125
- ### Logs
126
- get_available_log_types: [:get, 'session/:session_id/log/types'.freeze],
127
- get_log: [:post, 'session/:session_id/log'.freeze]
128
- }
129
- ).freeze
130
- end
131
- end
132
- end
2
+ require_relative 'command/common'
3
+ require_relative 'command/mjsonwp'
4
+ require_relative 'command/w3c'
@@ -0,0 +1,88 @@
1
+ module Appium
2
+ module Core
3
+ # ref: https://github.com/appium/appium-base-driver/blob/master/lib/mjsonwp/routes.js
4
+ module Commands
5
+ # Some commands differ for each driver.
6
+ COMMAND = {
7
+ # common
8
+ available_contexts: [:get, 'session/:session_id/contexts'.freeze],
9
+ set_context: [:post, 'session/:session_id/context'.freeze],
10
+ current_context: [:get, 'session/:session_id/context'.freeze],
11
+
12
+ touch_actions: [:post, 'session/:session_id/touch/perform'.freeze],
13
+ multi_touch: [:post, 'session/:session_id/touch/multi/perform'.freeze],
14
+
15
+ set_immediate_value: [:post, 'session/:session_id/appium/element/:id/value'.freeze],
16
+ replace_value: [:post, 'session/:session_id/appium/element/:id/replace_value'.freeze],
17
+
18
+ launch_app: [:post, 'session/:session_id/appium/app/launch'.freeze],
19
+ close_app: [:post, 'session/:session_id/appium/app/close'.freeze],
20
+ reset: [:post, 'session/:session_id/appium/app/reset'.freeze],
21
+ background_app: [:post, 'session/:session_id/appium/app/background'.freeze],
22
+ app_strings: [:post, 'session/:session_id/appium/app/strings'.freeze],
23
+
24
+ device_locked?: [:post, 'session/:session_id/appium/device/is_locked'.freeze],
25
+ unlock: [:post, 'session/:session_id/appium/device/unlock'.freeze],
26
+ lock: [:post, 'session/:session_id/appium/device/lock'.freeze],
27
+ device_time: [:get, 'session/:session_id/appium/device/system_time'.freeze],
28
+ install_app: [:post, 'session/:session_id/appium/device/install_app'.freeze],
29
+ remove_app: [:post, 'session/:session_id/appium/device/remove_app'.freeze],
30
+ app_installed?: [:post, 'session/:session_id/appium/device/app_installed'.freeze],
31
+ activate_app: [:post, 'session/:session_id/appium/device/activate_app'.freeze],
32
+ terminate_app: [:post, 'session/:session_id/appium/device/terminate_app'.freeze],
33
+ app_state: [:post, 'session/:session_id/appium/device/app_state'.freeze],
34
+ shake: [:post, 'session/:session_id/appium/device/shake'.freeze],
35
+ hide_keyboard: [:post, 'session/:session_id/appium/device/hide_keyboard'.freeze],
36
+ press_keycode: [:post, 'session/:session_id/appium/device/press_keycode'.freeze],
37
+ long_press_keycode: [:post, 'session/:session_id/appium/device/long_press_keycode'.freeze],
38
+ # keyevent is only for Selendroid
39
+ keyevent: [:post, 'session/:session_id/appium/device/keyevent'.freeze],
40
+ push_file: [:post, 'session/:session_id/appium/device/push_file'.freeze],
41
+ pull_file: [:post, 'session/:session_id/appium/device/pull_file'.freeze],
42
+ pull_folder: [:post, 'session/:session_id/appium/device/pull_folder'.freeze],
43
+ get_clipboard: [:post, 'session/:session_id/appium/device/get_clipboard'.freeze],
44
+ set_clipboard: [:post, 'session/:session_id/appium/device/set_clipboard'.freeze],
45
+ get_settings: [:get, 'session/:session_id/appium/settings'.freeze],
46
+ update_settings: [:post, 'session/:session_id/appium/settings'.freeze],
47
+ stop_recording_screen: [:post, 'session/:session_id/appium/stop_recording_screen'.freeze],
48
+ start_recording_screen: [:post, 'session/:session_id/appium/start_recording_screen'.freeze],
49
+ compare_images: [:post, 'session/:session_id/appium/compare_images'.freeze]
50
+ }.freeze
51
+
52
+ COMMAND_ANDROID = {
53
+ open_notifications: [:post, 'session/:session_id/appium/device/open_notifications'.freeze],
54
+ toggle_airplane_mode: [:post, 'session/:session_id/appium/device/toggle_airplane_mode'.freeze],
55
+ start_activity: [:post, 'session/:session_id/appium/device/start_activity'.freeze],
56
+ current_activity: [:get, 'session/:session_id/appium/device/current_activity'.freeze],
57
+ current_package: [:get, 'session/:session_id/appium/device/current_package'.freeze],
58
+ get_system_bars: [:get, 'session/:session_id/appium/device/system_bars'.freeze],
59
+ get_display_density: [:get, 'session/:session_id/appium/device/display_density'.freeze],
60
+ is_keyboard_shown: [:get, 'session/:session_id/appium/device/is_keyboard_shown'.freeze],
61
+ toggle_wifi: [:post, 'session/:session_id/appium/device/toggle_wifi'.freeze],
62
+ toggle_data: [:post, 'session/:session_id/appium/device/toggle_data'.freeze],
63
+ toggle_location_services: [:post, 'session/:session_id/appium/device/toggle_location_services'.freeze],
64
+ end_coverage: [:post, 'session/:session_id/appium/app/end_test_coverage'.freeze],
65
+ get_performance_data_types: [:post, 'session/:session_id/appium/performanceData/types'.freeze],
66
+ get_performance_data: [:post, 'session/:session_id/appium/getPerformanceData'.freeze],
67
+ get_network_connection: [:get, 'session/:session_id/network_connection'.freeze], # defined also in OSS
68
+ set_network_connection: [:post, 'session/:session_id/network_connection'.freeze], # defined also in OSS
69
+
70
+ # only emulator
71
+ send_sms: [:post, 'session/:session_id/appium/device/send_sms'.freeze],
72
+ gsm_call: [:post, 'session/:session_id/appium/device/gsm_call'.freeze],
73
+ gsm_signal: [:post, 'session/:session_id/appium/device/gsm_signal'.freeze],
74
+ gsm_voice: [:post, 'session/:session_id/appium/device/gsm_voice'.freeze],
75
+ set_network_speed: [:post, 'session/:session_id/appium/device/network_speed'.freeze],
76
+ set_power_capacity: [:post, 'session/:session_id/appium/device/power_capacity'.freeze],
77
+ set_power_ac: [:post, 'session/:session_id/appium/device/power_ac'.freeze]
78
+ }.freeze
79
+
80
+ COMMAND_IOS = {
81
+ touch_id: [:post, 'session/:session_id/appium/simulator/touch_id'.freeze],
82
+ toggle_touch_id_enrollment: [:post, 'session/:session_id/appium/simulator/toggle_touch_id_enrollment'.freeze]
83
+ }.freeze
84
+
85
+ COMMANDS = {}.merge(COMMAND).merge(COMMAND_ANDROID).merge(COMMAND_IOS).freeze
86
+ end # module Commands
87
+ end # module Core
88
+ end # module Appium
@@ -0,0 +1,14 @@
1
+ module Appium
2
+ module Core
3
+ module Commands
4
+ module MJSONWP
5
+ COMMANDS = ::Appium::Core::Commands::COMMANDS.merge(::Appium::Core::Base::Commands::OSS).merge(
6
+ {
7
+ # W3C already has.
8
+ take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'.freeze]
9
+ }
10
+ ).freeze
11
+ end # module MJSONWP
12
+ end # module Commands
13
+ end # module Core
14
+ end # Appium
@@ -0,0 +1,44 @@
1
+ module Appium
2
+ module Core
3
+ module Commands
4
+ module W3C
5
+ COMMANDS = ::Appium::Core::Commands::COMMANDS.merge(::Appium::Core::Base::Commands::W3C).merge(
6
+ {
7
+ # ::Appium::Core::Base::Commands::OSS has the following commands and Appium also use them.
8
+ # Delegated to ::Appium::Core::Base::Commands::OSS commands
9
+ status: [:get, 'status'.freeze],
10
+ is_element_displayed: [:get, 'session/:session_id/element/:id/displayed'.freeze],
11
+
12
+ # FIXME: remove after apply https://github.com/SeleniumHQ/selenium/pull/5249
13
+ # The fix will be included in selenium-3.8.2
14
+ get_page_source: [:get, 'session/:session_id/source'.freeze],
15
+
16
+ get_timeouts: [:get, 'session/:session_id/timeouts'.freeze],
17
+
18
+ ## Add OSS commands to W3C commands. We can remove them if we would like to remove them from W3C module.
19
+ ### Session capability
20
+ get_capabilities: [:get, 'session/:session_id'.freeze],
21
+
22
+ ### rotatable
23
+ get_screen_orientation: [:get, 'session/:session_id/orientation'.freeze],
24
+ set_screen_orientation: [:post, 'session/:session_id/orientation'.freeze],
25
+
26
+ get_location: [:get, 'session/:session_id/location'.freeze],
27
+ set_location: [:post, 'session/:session_id/location'.freeze],
28
+
29
+ ### For IME
30
+ ime_get_available_engines: [:get, 'session/:session_id/ime/available_engines'.freeze],
31
+ ime_get_active_engine: [:get, 'session/:session_id/ime/active_engine'.freeze],
32
+ ime_is_activated: [:get, 'session/:session_id/ime/activated'.freeze],
33
+ ime_deactivate: [:post, 'session/:session_id/ime/deactivate'.freeze],
34
+ ime_activate_engine: [:post, 'session/:session_id/ime/activate'.freeze],
35
+
36
+ ### Logs
37
+ get_available_log_types: [:get, 'session/:session_id/log/types'.freeze],
38
+ get_log: [:post, 'session/:session_id/log'.freeze]
39
+ }
40
+ ).freeze
41
+ end # module W3C
42
+ end # module Commands
43
+ end # module Core
44
+ end # module Appium
@@ -0,0 +1,162 @@
1
+ require_relative 'wait/timer'
2
+
3
+ module Appium
4
+ module Core
5
+ module Wait
6
+ class TimeoutError < StandardError; end
7
+
8
+ DEFAULT_TIMEOUT = 30
9
+ DEFAULT_INTERVAL = 0.5
10
+
11
+ class << self
12
+ # Check every interval seconds to see if yield doesn't raise an exception.
13
+ # Give up after timeout seconds.
14
+ #
15
+ # If only a number is provided then it's treated as the timeout value.
16
+ #
17
+ # @param [Integer] timeout: Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
18
+ # @param [Integer] interval: Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
19
+ # @param [String] message: Exception message if timed out.
20
+ # @param [Array, Exception] ignored: Exceptions to ignore while polling (default: Exception)
21
+ # @param [Object, NilClass] object: Object to evaluate block against
22
+ #
23
+ # @example
24
+ #
25
+ # result = Appium::Core::Wait.until { @driver.find_element(:id, 'something') }
26
+ #
27
+ # result = Appium::Core::Wait.until(object: 'some object') { |object|
28
+ # @driver.find_element(:id, object)
29
+ # }
30
+ #
31
+ def until(timeout: DEFAULT_TIMEOUT, interval: DEFAULT_INTERVAL, message: nil, ignored: nil, object: nil)
32
+ ignored = Array(ignored || ::Exception)
33
+
34
+ last_error = nil
35
+
36
+ begin
37
+ run_with_timer(timeout, interval) { return yield(object) }
38
+ rescue ::Errno::ECONNREFUSED => e
39
+ raise e
40
+ rescue *ignored => last_error # rubocop:disable Lint/HandleExceptions
41
+ # swallowed
42
+ end
43
+
44
+ msg = message_for timeout, message
45
+ msg << " (#{last_error.message})" if last_error
46
+
47
+ raise TimeoutError, msg
48
+ end
49
+
50
+ # Check every interval seconds to see if yield returns a truthy value.
51
+ # Note this isn't a strict boolean true, any truthy value is accepted.
52
+ # false and nil are considered failures.
53
+ # Give up after timeout seconds.
54
+ #
55
+ # If only a number is provided then it's treated as the timeout value.
56
+ #
57
+ # @param [Integer] timeout: Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
58
+ # @param [Integer] interval: Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
59
+ # @param [String] message: Exception message if timed out.
60
+ # @param [Array, Exception] ignored: Exceptions to ignore while polling (default: Exception)
61
+ # @param [Object, NilClass] object: Object to evaluate block against
62
+ #
63
+ # @example
64
+ #
65
+ # Appium::Core::Wait.until_true { @driver.find_element(:id, 'something') }
66
+ #
67
+ # Appium::Core::Wait.until_true(object: 'some object') { |object|
68
+ # @driver.find_element(:id, object)
69
+ # }
70
+ #
71
+ def until_true(timeout: DEFAULT_TIMEOUT, interval: DEFAULT_INTERVAL, message: nil, ignored: nil, object: nil)
72
+ ignored = Array(ignored || ::Exception)
73
+
74
+ last_error = nil
75
+
76
+ begin
77
+ run_with_timer(timeout, interval) do
78
+ result = yield(object)
79
+ return result if result
80
+ end
81
+ rescue ::Errno::ECONNREFUSED => e
82
+ raise e
83
+ rescue *ignored => last_error # rubocop:disable Lint/HandleExceptions
84
+ # swallowed
85
+ end
86
+
87
+ msg = message_for timeout, message
88
+ msg << " (#{last_error.message})" if last_error
89
+
90
+ raise TimeoutError, msg
91
+ end
92
+
93
+ private
94
+
95
+ def message_for(timeout, message)
96
+ msg = "timed out after #{timeout} seconds"
97
+ msg << ", #{message}" if message
98
+ msg
99
+ end
100
+
101
+ def run_with_timer(timeout, interval, &block)
102
+ if timeout.zero?
103
+ block.call # rubocop:disable Performance/RedundantBlockCall
104
+ else
105
+ Timer.wait timeout do
106
+ block.call # rubocop:disable Performance/RedundantBlockCall
107
+ sleep interval
108
+ end
109
+ end
110
+ end
111
+ end # self
112
+ end # module Wait
113
+
114
+ module Waitable
115
+ # Check every interval seconds to see if yield returns a truthy value.
116
+ # Note this isn't a strict boolean true, any truthy value is accepted.
117
+ # false and nil are considered failures.
118
+ # Give up after timeout seconds.
119
+ #
120
+ # If only a number is provided then it's treated as the timeout value.
121
+ #
122
+ # @param [Integer] timeout: Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
123
+ # @param [Integer] interval: Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
124
+ # @param [String] message: Exception message if timed out.
125
+ # @param [Array, Exception] ignored: Exceptions to ignore while polling (default: Exception)
126
+ #
127
+ # @example
128
+ #
129
+ # @core.wait_true { @driver.find_element :accessibility_id, 'something' }
130
+ #
131
+ def wait_true(timeout: nil, interval: nil, message: nil, ignored: nil)
132
+ Wait.until_true(timeout: timeout || @wait_timeout,
133
+ interval: interval || @wait_interval,
134
+ message: message,
135
+ ignored: ignored,
136
+ object: self) { yield }
137
+ end
138
+
139
+ # Check every interval seconds to see if yield doesn't raise an exception.
140
+ # Give up after timeout seconds.
141
+ #
142
+ # If only a number is provided then it's treated as the timeout value.
143
+ #
144
+ # @param [Integer] timeout: Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
145
+ # @param [Integer] interval: Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
146
+ # @param [String] message: Exception message if timed out.
147
+ # @param [Array, Exception] ignored: Exceptions to ignore while polling (default: Exception)
148
+ #
149
+ # @example
150
+ #
151
+ # @core.wait { @driver.find_element :accessibility_id, 'something' }
152
+ #
153
+ def wait(timeout: nil, interval: nil, message: nil, ignored: nil)
154
+ Wait.until(timeout: timeout || @wait_timeout,
155
+ interval: interval || @wait_interval,
156
+ message: message,
157
+ ignored: ignored,
158
+ object: self) { yield }
159
+ end
160
+ end
161
+ end # module Core
162
+ end # module Appium
@@ -0,0 +1,30 @@
1
+ module Appium
2
+ module Core
3
+ module Wait
4
+ module Timer
5
+ class << self
6
+ # @private
7
+ def wait(timeout, &block)
8
+ end_time = current_time + timeout
9
+ loop do
10
+ yield(block)
11
+ break if current_time > end_time
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ if defined?(Process::CLOCK_MONOTONIC)
18
+ def current_time
19
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
20
+ end
21
+ else
22
+ def current_time
23
+ ::Time.now.to_f
24
+ end
25
+ end
26
+ end
27
+ end # module Timer
28
+ end # module Wait
29
+ end # module Core
30
+ end # module Appium
@@ -1,3 +1,10 @@
1
+ require_relative 'device/touch_actions'
2
+ require_relative 'device/multi_touch'
3
+ require_relative 'device/screen_record'
4
+ require_relative 'device/app_state'
5
+ require_relative 'device/clipboard_content_type'
6
+ require_relative 'device/image_comparison'
7
+
1
8
  require 'base64'
2
9
 
3
10
  module Appium
@@ -513,6 +520,7 @@ module Appium
513
520
  add_app_management
514
521
  add_device_lock
515
522
  add_file_management
523
+ Core::Device::ImageComparison.extended
516
524
  end
517
525
 
518
526
  # def extended
@@ -522,7 +530,6 @@ module Appium
522
530
  block_given? ? create_bridge_command(method, &Proc.new) : create_bridge_command(method)
523
531
 
524
532
  delegate_driver_method method
525
- delegate_from_appium_driver method
526
533
  end
527
534
 
528
535
  # @private CoreBridge
@@ -539,11 +546,6 @@ module Appium
539
546
  ::Appium::Core::Base::Driver.class_eval { def_delegator :@bridge, method }
540
547
  end
541
548
 
542
- # @private
543
- def delegate_from_appium_driver(method, delegation_target = :driver)
544
- def_delegator delegation_target, method
545
- end
546
-
547
549
  # @private
548
550
  def create_bridge_command(method)
549
551
  ::Appium::Core::Base::Bridge::MJSONWP.class_eval do
@@ -0,0 +1,178 @@
1
+ require 'base64'
2
+
3
+ module Appium
4
+ module Core
5
+ module Device
6
+ module ImageComparison
7
+ extend Forwardable
8
+
9
+ MODE = [:matchFeatures, :getSimilarity, :matchTemplate].freeze
10
+
11
+ MATCH_FEATURES = {
12
+ detector_name: %w(AKAZE AGAST BRISK FAST GFTT KAZE MSER SIFT ORB),
13
+ match_func: %w(FlannBased BruteForce BruteForceL1 BruteForceHamming BruteForceHammingLut BruteForceSL2),
14
+ goodMatchesFactor: nil, # Integer
15
+ visualize: [true, false]
16
+ }.freeze
17
+
18
+ MATCH_TEMPLATE = {
19
+ visualize: [true, false]
20
+ }.freeze
21
+
22
+ GET_SIMILARITY = {
23
+ visualize: [true, false]
24
+ }.freeze
25
+
26
+ # @!method match_images_features(first_image:, second_image:, detector_name: 'ORB',
27
+ # match_func: 'BruteForce', good_matches_factor: 100, visualize: false)
28
+ # Performs images matching by features with default options. Read https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html
29
+ # for more details on this topic.
30
+ #
31
+ # @param [String] first_image An image data. All image formats, that OpenCV library itself accepts, are supported.
32
+ # @param [String] second_image An image data. All image formats, that OpenCV library itself accepts, are supported.
33
+ # @param [String] detector_name Sets the detector name for features matching
34
+ # algorithm. Some of these detectors (FAST, AGAST, GFTT, FAST, SIFT and MSER) are
35
+ # not available in the default OpenCV installation and have to be enabled manually
36
+ # before library compilation. The default detector name is 'ORB'.
37
+ # @param [String] match_func The name of the matching function. The default one is 'BruteForce'.
38
+ # @param [String] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
39
+ # The default one is nil.
40
+ # @param [Bool] visualise Makes the endpoint to return an image, which contains the visualized result of
41
+ # the corresponding picture matching operation. This option is disabled by default.
42
+ #
43
+ # @example
44
+ # @driver.match_images_features first_image: "image data 1", second_image: "image data 2"
45
+ #
46
+ # visual = @@driver.match_images_features first_image: image1, second_image: image2, visualize: true
47
+ # File.write 'match_images_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
48
+ #
49
+
50
+ # @!method find_image_occurrence(full_image:, partial_image:, detector_name: 'ORB', visualize: false)
51
+ # Performs images matching by template to find possible occurrence of the partial image
52
+ # in the full image with default options. Read https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
53
+ # for more details on this topic.
54
+ #
55
+ # @param [String] full_image: A full image data.
56
+ # @param [String] partial_image: A partial image data. All image formats, that OpenCV library itself accepts,
57
+ # are supported.
58
+ # @param [Bool] visualise: Makes the endpoint to return an image, which contains the visualized result of
59
+ # the corresponding picture matching operation. This option is disabled by default.
60
+ #
61
+ # @example
62
+ # @driver.find_image_occurrence full_image: "image data 1", partial_image: "image data 2"
63
+ #
64
+ # visual = @@driver.find_image_occurrence full_image: image1, partial_image: image2, visualize: true
65
+ # File.write 'find_result_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
66
+ #
67
+
68
+ # @!method get_images_similarity(first_image:, second_image:, detector_name: 'ORB', visualize: false)
69
+ # Performs images matching to calculate the similarity score between them
70
+ # with default options. The flow there is similar to the one used in `find_image_occurrence`
71
+ # but it is mandatory that both images are of equal size.
72
+ #
73
+ # @param [String] first_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
74
+ # @param [String] second_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
75
+ # @param [Bool] visualise: Makes the endpoint to return an image, which contains the visualized result of
76
+ # the corresponding picture matching operation. This option is disabled by default.
77
+ #
78
+ # @example
79
+ # @driver.get_images_similarity first_image: "image data 1", second_image: "image data 2"
80
+ #
81
+ # visual = @@driver.get_images_similarity first_image: image1, second_image: image2, visualize: true
82
+ # File.write 'images_similarity_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
83
+ #
84
+
85
+ # @!method compare_images(mode:, first_image:, second_image:, options:)
86
+ #
87
+ # Performs images comparison using OpenCV framework features.
88
+ # It is expected that both OpenCV framework and opencv4nodejs
89
+ # module are installed on the machine where Appium server is running.
90
+ #
91
+ # @param [Symbol] mode: One of possible comparison modes: `:matchFeatures`, `:getSimilarity`, `:matchTemplate`.
92
+ # `:matchFeatures is by default.
93
+ # @param [String] first_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
94
+ # @param [String] second_image: An image data. All image formats, that OpenCV library itself accepts, are supported.
95
+ # @param [Hash] options: The content of this dictionary depends on the actual `mode` value.
96
+ # See the documentation on `appium-support` module for more details.
97
+ # @returns [Hash] The content of the resulting dictionary depends on the actual `mode` and `options` values.
98
+ # See the documentation on `appium-support` module for more details.
99
+ #
100
+
101
+ ####
102
+ ## class << self
103
+ ####
104
+
105
+ def self.extended
106
+ ::Appium::Core::Device.add_endpoint_method(:match_images_features) do
107
+ def match_images_features(first_image:, # rubocop:disable Metrics/ParameterLists
108
+ second_image:,
109
+ detector_name: 'ORB',
110
+ match_func: 'BruteForce',
111
+ good_matches_factor: nil,
112
+ visualize: false)
113
+ unless ::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:detector_name].member?(detector_name.to_s)
114
+ raise "detector_name should be #{::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:detector_name]}"
115
+ end
116
+ unless ::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:match_func].member?(match_func.to_s)
117
+ raise "match_func should be #{::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:match_func]}"
118
+ end
119
+ unless ::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:visualize].member?(visualize)
120
+ raise "visualize should be #{::Appium::Core::Device::ImageComparison::MATCH_FEATURES[:visualize]}"
121
+ end
122
+
123
+ options = {}
124
+ options[:detectorName] = detector_name.to_s.upcase
125
+ options[:matchFunc] = match_func.to_s
126
+ options[:goodMatchesFactor] = good_matches_factor.to_i unless good_matches_factor.nil?
127
+ options[:visualize] = visualize
128
+
129
+ compare_images(mode: :matchFeatures, first_image: first_image, second_image: second_image, options: options)
130
+ end
131
+ end
132
+
133
+ ::Appium::Core::Device.add_endpoint_method(:find_image_occurrence) do
134
+ def find_image_occurrence(full_image:, partial_image:, visualize: false)
135
+ unless ::Appium::Core::Device::ImageComparison::MATCH_TEMPLATE[:visualize].member?(visualize)
136
+ raise "visualize should be #{::Appium::Core::Device::ImageComparison::MATCH_TEMPLATE[:visualize]}"
137
+ end
138
+
139
+ options = {}
140
+ options[:visualize] = visualize
141
+
142
+ compare_images(mode: :matchTemplate, first_image: full_image, second_image: partial_image, options: options)
143
+ end
144
+ end
145
+
146
+ ::Appium::Core::Device.add_endpoint_method(:get_images_similarity) do
147
+ def get_images_similarity(first_image:, second_image:, visualize: false)
148
+ unless ::Appium::Core::Device::ImageComparison::GET_SIMILARITY[:visualize].member?(visualize)
149
+ raise "visualize should be #{::Appium::Core::Device::ImageComparison::GET_SIMILARITY[:visualize]}"
150
+ end
151
+
152
+ options = {}
153
+ options[:visualize] = visualize
154
+
155
+ compare_images(mode: :getSimilarity, first_image: first_image, second_image: second_image, options: options)
156
+ end
157
+ end
158
+
159
+ ::Appium::Core::Device.add_endpoint_method(:compare_images) do
160
+ def compare_images(mode: :matchFeatures, first_image:, second_image:, options: nil)
161
+ unless ::Appium::Core::Device::ImageComparison::MODE.member?(mode)
162
+ raise "content_type should be #{::Appium::Core::Device::ImageComparison::MODE}"
163
+ end
164
+
165
+ params = {}
166
+ params[:mode] = mode
167
+ params[:firstImage] = Base64.encode64 first_image
168
+ params[:secondImage] = Base64.encode64 second_image
169
+ params[:options] = options if options
170
+
171
+ execute(:compare_images, {}, params)
172
+ end
173
+ end
174
+ end # self
175
+ end # module ImageComparison
176
+ end # module Device
177
+ end # module Core
178
+ end # module Appium
@@ -1,6 +1,7 @@
1
1
  module Appium
2
2
  module Core
3
3
  class Driver
4
+ include Waitable
4
5
  # Selenium webdriver capabilities
5
6
  # @return [Core::Base::Capabilities]
6
7
  attr_reader :caps
@@ -278,73 +279,8 @@ module Appium
278
279
  @driver.save_screenshot png_save_path
279
280
  end
280
281
 
281
- # Check every interval seconds to see if yield returns a truthy value.
282
- # Note this isn't a strict boolean true, any truthy value is accepted.
283
- # false and nil are considered failures.
284
- # Give up after timeout seconds.
285
- #
286
- # Wait code from the selenium Ruby gem
287
- # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
288
- #
289
- # If only a number is provided then it's treated as the timeout value.
290
- #
291
- # @param [Hash] opts Options
292
- # @option opts [Numeric] :timeout Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
293
- # @option opts [Numeric] :interval Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
294
- # @option opts [String] :message Exception message if timed out.
295
- # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
296
- #
297
- # @example
298
- #
299
- # @core.wait_true { @driver.find_element :accessibility_id, 'something' }
300
- #
301
- def wait_true(opts = {})
302
- opts = process_wait_opts(opts).merge(return_if_true: true)
303
-
304
- opts[:timeout] ||= @wait_timeout
305
- opts[:interval] ||= @wait_interval
306
-
307
- wait = ::Appium::Core::Base::Wait.new opts
308
- wait.until { yield }
309
- end
310
-
311
- # Check every interval seconds to see if yield doesn't raise an exception.
312
- # Give up after timeout seconds.
313
- #
314
- # Wait code from the selenium Ruby gem
315
- # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
316
- #
317
- # If only a number is provided then it's treated as the timeout value.
318
- #
319
- # @param [Hash] opts Options
320
- # @option opts [Numeric] :timeout Seconds to wait before timing out. Set default by `appium_wait_timeout` (30).
321
- # @option opts [Numeric] :interval Seconds to sleep between polls. Set default by `appium_wait_interval` (0.5).
322
- # @option opts [String] :message Exception message if timed out.
323
- # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
324
- #
325
- # @example
326
- #
327
- # @core.wait { @driver.find_element :accessibility_id, 'something' }
328
- #
329
- def wait(opts = {})
330
- opts = process_wait_opts(opts).merge(return_if_true: false)
331
-
332
- opts[:timeout] ||= @wait_timeout
333
- opts[:interval] ||= @wait_interval
334
-
335
- wait = ::Appium::Core::Base::Wait.new opts
336
- wait.until { yield }
337
- end
338
-
339
282
  private
340
283
 
341
- # @private
342
- def process_wait_opts(opts)
343
- opts = { timeout: opts } if opts.is_a?(Numeric)
344
- raise 'opts must be a hash' unless opts.is_a? Hash
345
- opts
346
- end
347
-
348
284
  # @private
349
285
  def extend_for(device:, automation_name:, target:)
350
286
  target.extend Appium::Core
@@ -432,8 +368,8 @@ module Appium
432
368
  @port = appium_lib_opts.fetch :port, DEFAULT_APPIUM_PORT
433
369
 
434
370
  # timeout and interval used in ::Appium::Comm.wait/wait_true
435
- @wait_timeout = appium_lib_opts.fetch :wait_timeout, 30
436
- @wait_interval = appium_lib_opts.fetch :wait_interval, 0.5
371
+ @wait_timeout = appium_lib_opts.fetch :wait_timeout, ::Appium::Core::Wait::DEFAULT_TIMEOUT
372
+ @wait_interval = appium_lib_opts.fetch :wait_interval, ::Appium::Core::Wait::DEFAULT_INTERVAL
437
373
 
438
374
  # to pass it in Selenium.new.
439
375
  # `listener = opts.delete(:listener)` is called in Selenium::Driver.new
@@ -467,7 +403,7 @@ module Appium
467
403
 
468
404
  # @private
469
405
  def write_session_id(session_id, export_path = '/tmp/appium_lib_session')
470
- File.open(export_path, 'w') { |f| f.puts session_id }
406
+ File.write(export_path, session_id)
471
407
  rescue IOError => e
472
408
  ::Appium::Logger.warn e
473
409
  nil
@@ -1,6 +1,6 @@
1
1
  module Appium
2
2
  module Core
3
- VERSION = '1.4.0'.freeze unless defined? ::Appium::Core::VERSION
4
- DATE = '2018-04-15'.freeze unless defined? ::Appium::Core::DATE
3
+ VERSION = '1.4.1'.freeze unless defined? ::Appium::Core::VERSION
4
+ DATE = '2018-04-22'.freeze unless defined? ::Appium::Core::DATE
5
5
  end
6
6
  end
@@ -1,3 +1,12 @@
1
+ #### v1.4.1 2018-04-22
2
+
3
+ - [afb5d33](https://github.com/appium/ruby_lib_core/commit/afb5d334a786a12bd407848312ddd35c8c9ad308) Release 1.4.1
4
+ - [7fd0ccc](https://github.com/appium/ruby_lib_core/commit/7fd0ccca947e742f03ac41022d0670bf809d3969) add base image comparison (#80)
5
+ - [0b10980](https://github.com/appium/ruby_lib_core/commit/0b10980cbbb48cfba0352fa0ef4e15b2fd16d086) split timer loop from wait
6
+ - [009f679](https://github.com/appium/ruby_lib_core/commit/009f679c08fd4c019b4876454d758ef5cf30daae) Refactor commands (#79)
7
+ - [4b1c086](https://github.com/appium/ruby_lib_core/commit/4b1c0868c6258106faae24978be324b79785fc5b) Extract wait (#78)
8
+
9
+
1
10
  #### v1.4.0 2018-04-15
2
11
 
3
12
  - [5cc89aa](https://github.com/appium/ruby_lib_core/commit/5cc89aa4a9533e174527db5b805b96cf2b45a9ac) Release 1.4.0
@@ -16,8 +16,8 @@ module Script
16
16
  # - webdriver_w3c_commands: ::Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS
17
17
  #
18
18
  def initialize
19
- @implemented_mjsonwp_commands = convert_driver_commands Appium::Core::Commands::COMMANDS_EXTEND_MJSONWP
20
- @implemented_w3c_commands = convert_driver_commands Appium::Core::Commands::COMMANDS_EXTEND_W3C
19
+ @implemented_mjsonwp_commands = convert_driver_commands Appium::Core::Commands::MJSONWP::COMMANDS
20
+ @implemented_w3c_commands = convert_driver_commands Appium::Core::Commands::W3C::COMMANDS
21
21
  @implemented_core_commands = convert_driver_commands Appium::Core::Commands::COMMANDS
22
22
 
23
23
  @webdriver_oss_commands = convert_driver_commands Appium::Core::Base::Commands::OSS
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_lib_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuaki MATSUO
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-15 00:00:00.000000000 Z
11
+ date: 2018-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.5'
27
- - !ruby/object:Gem::Dependency
28
- name: json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '1.8'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '1.8'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: faye-websocket
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -247,22 +233,27 @@ files:
247
233
  - lib/appium_lib_core/common.rb
248
234
  - lib/appium_lib_core/common/base.rb
249
235
  - lib/appium_lib_core/common/base/bridge.rb
250
- - lib/appium_lib_core/common/base/bridge/msjsonwp.rb
236
+ - lib/appium_lib_core/common/base/bridge/mjsonwp.rb
251
237
  - lib/appium_lib_core/common/base/bridge/w3c.rb
252
238
  - lib/appium_lib_core/common/base/capabilities.rb
253
239
  - lib/appium_lib_core/common/base/command.rb
254
240
  - lib/appium_lib_core/common/base/driver.rb
255
241
  - lib/appium_lib_core/common/base/http_default.rb
256
242
  - lib/appium_lib_core/common/base/search_context.rb
257
- - lib/appium_lib_core/common/base/wait.rb
258
243
  - lib/appium_lib_core/common/command.rb
259
- - lib/appium_lib_core/common/device.rb
244
+ - lib/appium_lib_core/common/command/common.rb
245
+ - lib/appium_lib_core/common/command/mjsonwp.rb
246
+ - lib/appium_lib_core/common/command/w3c.rb
260
247
  - lib/appium_lib_core/common/error.rb
261
248
  - lib/appium_lib_core/common/log.rb
262
249
  - lib/appium_lib_core/common/logger.rb
250
+ - lib/appium_lib_core/common/wait.rb
251
+ - lib/appium_lib_core/common/wait/timer.rb
263
252
  - lib/appium_lib_core/common/ws/websocket.rb
253
+ - lib/appium_lib_core/device.rb
264
254
  - lib/appium_lib_core/device/app_state.rb
265
255
  - lib/appium_lib_core/device/clipboard_content_type.rb
256
+ - lib/appium_lib_core/device/image_comparison.rb
266
257
  - lib/appium_lib_core/device/multi_touch.rb
267
258
  - lib/appium_lib_core/device/screen_record.rb
268
259
  - lib/appium_lib_core/device/touch_actions.rb
@@ -1,56 +0,0 @@
1
- # rubocop:disable Lint/HandleExceptions
2
- module Appium
3
- module Core
4
- class Base
5
- class Wait < ::Selenium::WebDriver::Wait
6
- require 'timeout' # for wait
7
-
8
- def initialize(opts = {})
9
- valid_keys = %i(timeout interval message ignore return_if_true)
10
- invalid_keys = []
11
- opts.each_key { |key| invalid_keys << key unless valid_keys.include?(key) }
12
- # [:one, :two] => :one, :two
13
- unless invalid_keys.empty?
14
- raise "Invalid keys #{invalid_keys.to_s[1..-2]}. Valid keys are #{valid_keys.to_s[1..-2]}"
15
- end
16
-
17
- @timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT)
18
- @interval = opts.fetch(:interval, DEFAULT_INTERVAL)
19
- @message = opts[:message]
20
- @ignored = Array(opts[:ignore] || ::Exception)
21
- @return_if_true = opts[:return_if_true]
22
-
23
- super(timeout: @timeout, interval: @interval, message: @message, ignore: @ignored)
24
- end
25
-
26
- # Wait code from the selenium Ruby gem
27
- # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
28
- def until
29
- end_time = Time.now + @timeout
30
- last_error = nil
31
-
32
- until Time.now > end_time
33
- begin
34
- return yield unless @return_if_true
35
-
36
- result = yield
37
- return result if result
38
- rescue ::Errno::ECONNREFUSED => e
39
- raise e
40
- rescue *@ignored => last_error
41
- # swallowed
42
- end
43
-
44
- sleep @interval
45
- end
46
-
47
- msg = @message ? @message.dup : "timed out after #{@timeout} seconds"
48
-
49
- msg << " (#{last_error.message})" if last_error
50
-
51
- raise Selenium::WebDriver::Error::TimeOutError, msg
52
- end
53
- end # module Wait
54
- end # module Base
55
- end # module Core
56
- end # module Appium