appium_lib_core 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
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