appium_lib_core 4.1.0 → 5.0.0.rc6
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 +4 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/unittest.yml +8 -9
- data/.rubocop.yml +89 -1
- data/CHANGELOG.md +64 -277
- data/README.md +7 -6
- data/Rakefile +4 -0
- data/appium_lib_core.gemspec +4 -4
- data/ci-jobs/functional/run_appium.yml +3 -3
- data/ci-jobs/functional_test.yml +3 -3
- data/docs/mobile_command.md +2 -2
- data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
- data/lib/appium_lib_core/android/device.rb +4 -4
- data/lib/appium_lib_core/common/base/bridge.rb +297 -90
- data/lib/appium_lib_core/common/base/capabilities.rb +10 -3
- data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
- data/lib/appium_lib_core/common/base/driver.rb +148 -128
- data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
- data/lib/appium_lib_core/common/base/has_location.rb +80 -0
- data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
- data/lib/appium_lib_core/common/base/http_default.rb +1 -3
- data/lib/appium_lib_core/common/base/remote_status.rb +31 -0
- data/lib/appium_lib_core/common/base/rotable.rb +54 -0
- data/lib/appium_lib_core/common/base/screenshot.rb +6 -6
- data/lib/appium_lib_core/common/base/search_context.rb +11 -4
- data/lib/appium_lib_core/common/base.rb +1 -3
- data/lib/appium_lib_core/common/command.rb +259 -4
- data/lib/appium_lib_core/common/device/image_comparison.rb +12 -4
- data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
- data/lib/appium_lib_core/common/{command/mjsonwp.rb → device/orientation.rb} +14 -11
- data/lib/appium_lib_core/common/device/value.rb +6 -6
- data/lib/appium_lib_core/common/error.rb +4 -1
- data/lib/appium_lib_core/common/log.rb +4 -1
- data/lib/appium_lib_core/common/touch_action/touch_actions.rb +1 -1
- data/lib/appium_lib_core/common/wait.rb +42 -10
- data/lib/appium_lib_core/device.rb +1 -5
- data/lib/appium_lib_core/driver.rb +27 -46
- data/lib/appium_lib_core/{patch.rb → element.rb} +66 -9
- data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
- data/lib/appium_lib_core/{common/base/command.rb → mac2/bridge.rb} +9 -8
- data/lib/appium_lib_core/mac2/device/screen.rb +48 -0
- data/lib/appium_lib_core/mac2/device.rb +92 -0
- data/lib/appium_lib_core/mac2.rb +17 -0
- data/lib/appium_lib_core/version.rb +2 -2
- data/lib/appium_lib_core.rb +2 -5
- data/release_notes.md +92 -0
- data/script/commands.rb +3 -37
- metadata +28 -28
- data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
- data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -252
- data/lib/appium_lib_core/common/command/common.rb +0 -110
- data/lib/appium_lib_core/common/command/w3c.rb +0 -56
@@ -55,8 +55,6 @@ module Appium
|
|
55
55
|
def update_sending_request_to(scheme:, host:, port:, path:)
|
56
56
|
return @server_url unless validate_url_param(scheme, host, port, path)
|
57
57
|
|
58
|
-
::Appium::Logger.debug("[experimental] This feature, #{__method__}, is an experimental")
|
59
|
-
|
60
58
|
# Add / if 'path' does not have it
|
61
59
|
path = path.start_with?('/') ? path : "/#{path}"
|
62
60
|
path = path.end_with?('/') ? path : "#{path}/"
|
@@ -71,7 +69,7 @@ module Appium
|
|
71
69
|
return true unless [scheme, host, port, path].include?(nil)
|
72
70
|
|
73
71
|
message = "Given parameters are scheme: '#{scheme}', host: '#{host}', port: '#{port}', path: '#{path}'"
|
74
|
-
::Appium::Logger.
|
72
|
+
::Appium::Logger.debug(message)
|
75
73
|
false
|
76
74
|
end
|
77
75
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
|
22
|
+
module HasRemoteStatus
|
23
|
+
# Selenium binding has this ability only in Remote Binding,
|
24
|
+
# so this library has this method by own for safe.
|
25
|
+
def remote_status
|
26
|
+
bridge.status
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
class Base
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
|
22
|
+
module Rotatable
|
23
|
+
ORIENTATIONS = %i[landscape portrait].freeze
|
24
|
+
|
25
|
+
#
|
26
|
+
# Change the screen orientation
|
27
|
+
#
|
28
|
+
# @param [:landscape, :portrait] orientation
|
29
|
+
#
|
30
|
+
#
|
31
|
+
def rotation=(orientation)
|
32
|
+
unless ORIENTATIONS.include?(orientation)
|
33
|
+
raise ::Appium::Core::Error::ArgumentError, "expected #{ORIENTATIONS.inspect}, got #{orientation.inspect}"
|
34
|
+
end
|
35
|
+
|
36
|
+
bridge.screen_orientation = orientation.to_s.upcase
|
37
|
+
end
|
38
|
+
alias rotate rotation=
|
39
|
+
|
40
|
+
#
|
41
|
+
# Get the current screen orientation
|
42
|
+
#
|
43
|
+
# @return [:landscape, :portrait] orientation
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
#
|
47
|
+
|
48
|
+
def orientation
|
49
|
+
bridge.screen_orientation.to_sym.downcase
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -15,7 +15,7 @@
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
17
|
class Base
|
18
|
-
module
|
18
|
+
module TakesScreenshot
|
19
19
|
#
|
20
20
|
# Save a PNG screenshot to the given path
|
21
21
|
#
|
@@ -63,8 +63,8 @@ module Appium
|
|
63
63
|
def save_element_screenshot(element, png_path)
|
64
64
|
extension = File.extname(png_path).downcase
|
65
65
|
if extension != '.png'
|
66
|
-
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
|
67
|
-
|
66
|
+
::Appium::Logger.warn 'name used for saved screenshot does not match file type. ' \
|
67
|
+
'It should end with .png extension'
|
68
68
|
end
|
69
69
|
File.open(png_path, 'wb') { |f| f << element_screenshot_as(element, :png) }
|
70
70
|
end
|
@@ -84,9 +84,9 @@ module Appium
|
|
84
84
|
def element_screenshot_as(element, format)
|
85
85
|
case format
|
86
86
|
when :base64
|
87
|
-
bridge.
|
87
|
+
bridge.element_screenshot element.id
|
88
88
|
when :png
|
89
|
-
bridge.
|
89
|
+
bridge.element_screenshot(element.id).unpack('m')[0]
|
90
90
|
else
|
91
91
|
raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
|
92
92
|
end
|
@@ -106,7 +106,7 @@ module Appium
|
|
106
106
|
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
|
107
107
|
'It should end with .png extension'
|
108
108
|
end
|
109
|
-
viewport_screenshot_encode64 = bridge.
|
109
|
+
viewport_screenshot_encode64 = bridge.viewport_screenshot
|
110
110
|
File.open(png_path, 'wb') { |f| f << viewport_screenshot_encode64.unpack('m')[0] }
|
111
111
|
end
|
112
112
|
end
|
@@ -141,6 +141,8 @@ module Appium
|
|
141
141
|
#
|
142
142
|
# Find all elements matching the given arguments
|
143
143
|
#
|
144
|
+
# @return [Array<Selenium::WebDriver::Element>]
|
145
|
+
#
|
144
146
|
# @see SearchContext#find_elements
|
145
147
|
#
|
146
148
|
def find_elements(*args)
|
@@ -157,7 +159,10 @@ module Appium
|
|
157
159
|
|
158
160
|
def _set_by_from_finders(how)
|
159
161
|
by = FINDERS[how.to_sym]
|
160
|
-
|
162
|
+
unless by
|
163
|
+
raise ::Appium::Core::Error::ArgumentError,
|
164
|
+
"cannot find element by #{how.inspect}. Available finders are #{FINDERS.keys}."
|
165
|
+
end
|
161
166
|
|
162
167
|
by
|
163
168
|
end
|
@@ -169,16 +174,18 @@ module Appium
|
|
169
174
|
when 1
|
170
175
|
arg = args.first
|
171
176
|
|
172
|
-
|
177
|
+
unless arg.respond_to?(:shift)
|
178
|
+
raise ::Appium::Core::Error::ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
|
179
|
+
end
|
173
180
|
|
174
181
|
# this will be a single-entry hash, so use #shift over #first or #[]
|
175
182
|
arr = arg.dup.shift
|
176
183
|
|
177
|
-
raise ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
|
184
|
+
raise ::Appium::Core::Error::ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
|
178
185
|
|
179
186
|
arr
|
180
187
|
else
|
181
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
|
188
|
+
raise ::Appium::Core::Error::ArgumentError, "wrong number of arguments (#{args.size} for 2)"
|
182
189
|
end
|
183
190
|
end
|
184
191
|
end # module SearchContext
|
@@ -29,14 +29,12 @@ require_relative 'device/clipboard_content_type'
|
|
29
29
|
require_relative 'device/device'
|
30
30
|
require_relative 'device/touch_actions'
|
31
31
|
require_relative 'device/execute_driver'
|
32
|
+
require_relative 'device/orientation'
|
32
33
|
|
33
34
|
# The following files have selenium-webdriver related stuff.
|
34
35
|
require_relative 'base/driver'
|
35
36
|
require_relative 'base/bridge'
|
36
|
-
require_relative 'base/bridge/mjsonwp'
|
37
|
-
require_relative 'base/bridge/w3c'
|
38
37
|
require_relative 'base/capabilities'
|
39
38
|
require_relative 'base/http_default'
|
40
39
|
require_relative 'base/search_context'
|
41
|
-
require_relative 'base/command'
|
42
40
|
require_relative 'base/platform'
|
@@ -12,7 +12,262 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
module Appium
|
16
|
+
module Core
|
17
|
+
# ref: https://github.com/appium/appium-base-driver/blob/master/lib/mjsonwp/routes.js
|
18
|
+
module Commands
|
19
|
+
# Some commands differ for each driver.
|
20
|
+
COMMAND = {
|
21
|
+
###
|
22
|
+
# W3C
|
23
|
+
###
|
24
|
+
status: [:get, 'status'],
|
25
|
+
|
26
|
+
#
|
27
|
+
# session handling
|
28
|
+
#
|
29
|
+
|
30
|
+
new_session: [:post, 'session'],
|
31
|
+
delete_session: [:delete, 'session/:session_id'],
|
32
|
+
|
33
|
+
#
|
34
|
+
# basic driver
|
35
|
+
#
|
36
|
+
|
37
|
+
get: [:post, 'session/:session_id/url'],
|
38
|
+
get_current_url: [:get, 'session/:session_id/url'],
|
39
|
+
back: [:post, 'session/:session_id/back'],
|
40
|
+
forward: [:post, 'session/:session_id/forward'],
|
41
|
+
refresh: [:post, 'session/:session_id/refresh'],
|
42
|
+
get_title: [:get, 'session/:session_id/title'],
|
43
|
+
|
44
|
+
#
|
45
|
+
# window and Frame handling
|
46
|
+
#
|
47
|
+
|
48
|
+
get_window_handle: [:get, 'session/:session_id/window'],
|
49
|
+
new_window: [:post, 'session/:session_id/window/new'],
|
50
|
+
close_window: [:delete, 'session/:session_id/window'],
|
51
|
+
switch_to_window: [:post, 'session/:session_id/window'],
|
52
|
+
get_window_handles: [:get, 'session/:session_id/window/handles'],
|
53
|
+
fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
|
54
|
+
minimize_window: [:post, 'session/:session_id/window/minimize'],
|
55
|
+
maximize_window: [:post, 'session/:session_id/window/maximize'],
|
56
|
+
set_window_size: [:post, 'session/:session_id/window/size'],
|
57
|
+
get_window_size: [:get, 'session/:session_id/window/size'],
|
58
|
+
set_window_position: [:post, 'session/:session_id/window/position'],
|
59
|
+
get_window_position: [:get, 'session/:session_id/window/position'],
|
60
|
+
set_window_rect: [:post, 'session/:session_id/window/rect'],
|
61
|
+
get_window_rect: [:get, 'session/:session_id/window/rect'],
|
62
|
+
switch_to_frame: [:post, 'session/:session_id/frame'],
|
63
|
+
switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'],
|
64
|
+
|
65
|
+
#
|
66
|
+
# element
|
67
|
+
#
|
68
|
+
|
69
|
+
find_element: [:post, 'session/:session_id/element'],
|
70
|
+
find_elements: [:post, 'session/:session_id/elements'],
|
71
|
+
find_child_element: [:post, 'session/:session_id/element/:id/element'],
|
72
|
+
find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
|
73
|
+
get_active_element: [:get, 'session/:session_id/element/active'],
|
74
|
+
is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
|
75
|
+
get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
|
76
|
+
get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
|
77
|
+
get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
|
78
|
+
get_element_text: [:get, 'session/:session_id/element/:id/text'],
|
79
|
+
get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
|
80
|
+
get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
|
81
|
+
is_element_enabled: [:get, 'session/:session_id/element/:id/enabled'],
|
82
|
+
|
83
|
+
#
|
84
|
+
# document handling
|
85
|
+
#
|
86
|
+
|
87
|
+
get_page_source: [:get, 'session/:session_id/source'],
|
88
|
+
execute_script: [:post, 'session/:session_id/execute/sync'],
|
89
|
+
execute_async_script: [:post, 'session/:session_id/execute/async'],
|
90
|
+
|
91
|
+
#
|
92
|
+
# cookies
|
93
|
+
#
|
94
|
+
|
95
|
+
get_all_cookies: [:get, 'session/:session_id/cookie'],
|
96
|
+
get_cookie: [:get, 'session/:session_id/cookie/:name'],
|
97
|
+
add_cookie: [:post, 'session/:session_id/cookie'],
|
98
|
+
delete_cookie: [:delete, 'session/:session_id/cookie/:name'],
|
99
|
+
delete_all_cookies: [:delete, 'session/:session_id/cookie'],
|
100
|
+
|
101
|
+
#
|
102
|
+
# timeouts
|
103
|
+
#
|
104
|
+
|
105
|
+
set_timeout: [:post, 'session/:session_id/timeouts'],
|
106
|
+
|
107
|
+
#
|
108
|
+
# actions
|
109
|
+
#
|
110
|
+
|
111
|
+
actions: [:post, 'session/:session_id/actions'],
|
112
|
+
release_actions: [:delete, 'session/:session_id/actions'],
|
113
|
+
print_page: [:post, 'session/:session_id/print'],
|
114
|
+
|
115
|
+
#
|
116
|
+
# Element Operations
|
117
|
+
#
|
118
|
+
|
119
|
+
element_click: [:post, 'session/:session_id/element/:id/click'],
|
120
|
+
element_tap: [:post, 'session/:session_id/element/:id/tap'],
|
121
|
+
element_clear: [:post, 'session/:session_id/element/:id/clear'],
|
122
|
+
element_send_keys: [:post, 'session/:session_id/element/:id/value'],
|
123
|
+
|
124
|
+
#
|
125
|
+
# alerts
|
126
|
+
#
|
127
|
+
|
128
|
+
dismiss_alert: [:post, 'session/:session_id/alert/dismiss'],
|
129
|
+
accept_alert: [:post, 'session/:session_id/alert/accept'],
|
130
|
+
get_alert_text: [:get, 'session/:session_id/alert/text'],
|
131
|
+
send_alert_text: [:post, 'session/:session_id/alert/text'],
|
132
|
+
|
133
|
+
#
|
134
|
+
# screenshot
|
135
|
+
#
|
136
|
+
|
137
|
+
take_screenshot: [:get, 'session/:session_id/screenshot'],
|
138
|
+
take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
|
139
|
+
|
140
|
+
#
|
141
|
+
# server extensions
|
142
|
+
#
|
143
|
+
|
144
|
+
upload_file: [:post, 'session/:session_id/se/file'],
|
145
|
+
|
146
|
+
###
|
147
|
+
# Used by Appium, but no in W3C
|
148
|
+
###
|
149
|
+
|
150
|
+
# ::Appium::Core::Base::Commands::OSS has the following commands and Appium also use them.
|
151
|
+
# Delegated to ::Appium::Core::Base::Commands::OSS commands
|
152
|
+
is_element_displayed: [:get, 'session/:session_id/element/:id/displayed'], # hint: https://w3c.github.io/webdriver/#element-displayedness
|
153
|
+
|
154
|
+
get_timeouts: [:get, 'session/:session_id/timeouts'], # https://w3c.github.io/webdriver/#get-timeouts
|
155
|
+
|
156
|
+
# Add OSS commands to W3C commands. We can remove them if we would like to remove them from W3C module.
|
157
|
+
### Session capability
|
158
|
+
get_capabilities: [:get, 'session/:session_id'],
|
159
|
+
|
160
|
+
### rotatable
|
161
|
+
get_screen_orientation: [:get, 'session/:session_id/orientation'],
|
162
|
+
set_screen_orientation: [:post, 'session/:session_id/orientation'],
|
163
|
+
|
164
|
+
get_location: [:get, 'session/:session_id/location'],
|
165
|
+
set_location: [:post, 'session/:session_id/location'],
|
166
|
+
|
167
|
+
### For IME
|
168
|
+
ime_get_available_engines: [:get, 'session/:session_id/ime/available_engines'],
|
169
|
+
ime_get_active_engine: [:get, 'session/:session_id/ime/active_engine'],
|
170
|
+
ime_is_activated: [:get, 'session/:session_id/ime/activated'],
|
171
|
+
ime_deactivate: [:post, 'session/:session_id/ime/deactivate'],
|
172
|
+
ime_activate_engine: [:post, 'session/:session_id/ime/activate'],
|
173
|
+
|
174
|
+
send_keys_to_active_element: [:post, 'session/:session_id/keys'],
|
175
|
+
|
176
|
+
### Logs
|
177
|
+
get_available_log_types: [:get, 'session/:session_id/log/types'],
|
178
|
+
get_log: [:post, 'session/:session_id/log'],
|
179
|
+
|
180
|
+
###
|
181
|
+
# Appium own
|
182
|
+
###
|
183
|
+
|
184
|
+
# common
|
185
|
+
get_all_sessions: [:get, 'sessions'],
|
186
|
+
available_contexts: [:get, 'session/:session_id/contexts'],
|
187
|
+
set_context: [:post, 'session/:session_id/context'],
|
188
|
+
current_context: [:get, 'session/:session_id/context'],
|
189
|
+
|
190
|
+
touch_actions: [:post, 'session/:session_id/touch/perform'],
|
191
|
+
multi_touch: [:post, 'session/:session_id/touch/multi/perform'],
|
192
|
+
|
193
|
+
set_immediate_value: [:post, 'session/:session_id/appium/element/:id/value'],
|
194
|
+
replace_value: [:post, 'session/:session_id/appium/element/:id/replace_value'],
|
195
|
+
|
196
|
+
launch_app: [:post, 'session/:session_id/appium/app/launch'],
|
197
|
+
close_app: [:post, 'session/:session_id/appium/app/close'],
|
198
|
+
reset: [:post, 'session/:session_id/appium/app/reset'],
|
199
|
+
background_app: [:post, 'session/:session_id/appium/app/background'],
|
200
|
+
app_strings: [:post, 'session/:session_id/appium/app/strings'],
|
201
|
+
|
202
|
+
device_locked?: [:post, 'session/:session_id/appium/device/is_locked'],
|
203
|
+
unlock: [:post, 'session/:session_id/appium/device/unlock'],
|
204
|
+
lock: [:post, 'session/:session_id/appium/device/lock'],
|
205
|
+
device_time: [:get, 'session/:session_id/appium/device/system_time'],
|
206
|
+
install_app: [:post, 'session/:session_id/appium/device/install_app'],
|
207
|
+
remove_app: [:post, 'session/:session_id/appium/device/remove_app'],
|
208
|
+
app_installed?: [:post, 'session/:session_id/appium/device/app_installed'],
|
209
|
+
activate_app: [:post, 'session/:session_id/appium/device/activate_app'],
|
210
|
+
terminate_app: [:post, 'session/:session_id/appium/device/terminate_app'],
|
211
|
+
app_state: [:post, 'session/:session_id/appium/device/app_state'],
|
212
|
+
shake: [:post, 'session/:session_id/appium/device/shake'],
|
213
|
+
hide_keyboard: [:post, 'session/:session_id/appium/device/hide_keyboard'],
|
214
|
+
press_keycode: [:post, 'session/:session_id/appium/device/press_keycode'],
|
215
|
+
long_press_keycode: [:post, 'session/:session_id/appium/device/long_press_keycode'],
|
216
|
+
# keyevent is only for Selendroid
|
217
|
+
keyevent: [:post, 'session/:session_id/appium/device/keyevent'],
|
218
|
+
push_file: [:post, 'session/:session_id/appium/device/push_file'],
|
219
|
+
pull_file: [:post, 'session/:session_id/appium/device/pull_file'],
|
220
|
+
pull_folder: [:post, 'session/:session_id/appium/device/pull_folder'],
|
221
|
+
get_clipboard: [:post, 'session/:session_id/appium/device/get_clipboard'],
|
222
|
+
set_clipboard: [:post, 'session/:session_id/appium/device/set_clipboard'],
|
223
|
+
finger_print: [:post, 'session/:session_id/appium/device/finger_print'],
|
224
|
+
get_settings: [:get, 'session/:session_id/appium/settings'],
|
225
|
+
update_settings: [:post, 'session/:session_id/appium/settings'],
|
226
|
+
stop_recording_screen: [:post, 'session/:session_id/appium/stop_recording_screen'],
|
227
|
+
start_recording_screen: [:post, 'session/:session_id/appium/start_recording_screen'],
|
228
|
+
compare_images: [:post, 'session/:session_id/appium/compare_images'],
|
229
|
+
is_keyboard_shown: [:get, 'session/:session_id/appium/device/is_keyboard_shown'],
|
230
|
+
execute_driver: [:post, 'session/:session_id/appium/execute_driver'],
|
231
|
+
post_log_event: [:post, 'session/:session_id/appium/log_event'],
|
232
|
+
get_log_events: [:post, 'session/:session_id/appium/events']
|
233
|
+
}.freeze
|
234
|
+
|
235
|
+
COMMAND_ANDROID = {
|
236
|
+
open_notifications: [:post, 'session/:session_id/appium/device/open_notifications'],
|
237
|
+
toggle_airplane_mode: [:post, 'session/:session_id/appium/device/toggle_airplane_mode'],
|
238
|
+
start_activity: [:post, 'session/:session_id/appium/device/start_activity'],
|
239
|
+
current_activity: [:get, 'session/:session_id/appium/device/current_activity'],
|
240
|
+
current_package: [:get, 'session/:session_id/appium/device/current_package'],
|
241
|
+
get_system_bars: [:get, 'session/:session_id/appium/device/system_bars'],
|
242
|
+
get_display_density: [:get, 'session/:session_id/appium/device/display_density'],
|
243
|
+
toggle_wifi: [:post, 'session/:session_id/appium/device/toggle_wifi'],
|
244
|
+
toggle_data: [:post, 'session/:session_id/appium/device/toggle_data'],
|
245
|
+
toggle_location_services: [:post, 'session/:session_id/appium/device/toggle_location_services'],
|
246
|
+
end_coverage: [:post, 'session/:session_id/appium/app/end_test_coverage'],
|
247
|
+
get_performance_data_types: [:post, 'session/:session_id/appium/performanceData/types'],
|
248
|
+
get_performance_data: [:post, 'session/:session_id/appium/getPerformanceData'],
|
249
|
+
get_network_connection: [:get, 'session/:session_id/network_connection'], # defined also in OSS
|
250
|
+
set_network_connection: [:post, 'session/:session_id/network_connection'], # defined also in OSS
|
251
|
+
|
252
|
+
# only emulator
|
253
|
+
send_sms: [:post, 'session/:session_id/appium/device/send_sms'],
|
254
|
+
gsm_call: [:post, 'session/:session_id/appium/device/gsm_call'],
|
255
|
+
gsm_signal: [:post, 'session/:session_id/appium/device/gsm_signal'],
|
256
|
+
gsm_voice: [:post, 'session/:session_id/appium/device/gsm_voice'],
|
257
|
+
set_network_speed: [:post, 'session/:session_id/appium/device/network_speed'],
|
258
|
+
set_power_capacity: [:post, 'session/:session_id/appium/device/power_capacity'],
|
259
|
+
set_power_ac: [:post, 'session/:session_id/appium/device/power_ac'],
|
260
|
+
|
261
|
+
# For chromium: https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/server/http_handler.cc
|
262
|
+
chrome_send_command: [:post, 'session/:session_id/goog/cdp/execute']
|
263
|
+
}.freeze
|
264
|
+
|
265
|
+
COMMAND_IOS = {
|
266
|
+
touch_id: [:post, 'session/:session_id/appium/simulator/touch_id'],
|
267
|
+
toggle_touch_id_enrollment: [:post, 'session/:session_id/appium/simulator/toggle_touch_id_enrollment']
|
268
|
+
}.freeze
|
269
|
+
|
270
|
+
COMMANDS = {}.merge(COMMAND).merge(COMMAND_ANDROID).merge(COMMAND_IOS).freeze
|
271
|
+
end # module Commands
|
272
|
+
end # module Core
|
273
|
+
end # module Appium
|
@@ -47,7 +47,7 @@ module Appium
|
|
47
47
|
# not available in the default OpenCV installation and have to be enabled manually
|
48
48
|
# before library compilation. The default detector name is 'ORB'.
|
49
49
|
# @param [String] match_func The name of the matching function. The default one is 'BruteForce'.
|
50
|
-
# @param [String] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
|
50
|
+
# @param [String, nil] good_matches_factor The maximum count of "good" matches (e. g. with minimal distances).
|
51
51
|
# The default one is nil.
|
52
52
|
# @param [Bool] visualize Makes the endpoint to return an image, which contains the visualized result of
|
53
53
|
# the corresponding picture matching operation. This option is disabled by default.
|
@@ -94,7 +94,12 @@ module Appium
|
|
94
94
|
# are supported.
|
95
95
|
# @param [Bool] visualize Makes the endpoint to return an image, which contains the visualized result of
|
96
96
|
# the corresponding picture matching operation. This option is disabled by default.
|
97
|
-
# @param [Float] threshold [0.5] At what normalized threshold to reject
|
97
|
+
# @param [Float, nil] threshold [0.5] At what normalized threshold to reject
|
98
|
+
# @param [bool, nil] multiple Whether to enable the support of multiple image occurrences @since Appium 1.21.0.
|
99
|
+
# @param [integer, nil] match_neighbour_threshold The pixel distance between matches we consider to be part of
|
100
|
+
# the same template match @since Appium 1.21.0.
|
101
|
+
# This option is only considered if multiple matches mode is enabled.
|
102
|
+
# 10 pixels by default.
|
98
103
|
#
|
99
104
|
# @example
|
100
105
|
# @driver.find_image_occurrence full_image: "image data 1", partial_image: "image data 2"
|
@@ -102,12 +107,15 @@ module Appium
|
|
102
107
|
# visual = @@driver.find_image_occurrence full_image: image1, partial_image: image2, visualize: true
|
103
108
|
# File.write 'find_result_visual.png', Base64.decode64(visual['visualization']) # if the image is PNG
|
104
109
|
#
|
105
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
110
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
111
|
+
multiple: nil, match_neighbour_threshold: nil)
|
106
112
|
raise "visualize should be #{MATCH_TEMPLATE[:visualize]}" unless MATCH_TEMPLATE[:visualize].member?(visualize)
|
107
113
|
|
108
114
|
options = {}
|
109
115
|
options[:visualize] = visualize
|
110
116
|
options[:threshold] = threshold unless threshold.nil?
|
117
|
+
options[:multiple] = multiple unless multiple.nil?
|
118
|
+
options[:matchNeighbourThreshold] = match_neighbour_threshold unless match_neighbour_threshold.nil?
|
111
119
|
|
112
120
|
compare_images(mode: :matchTemplate, first_image: full_image, second_image: partial_image, options: options)
|
113
121
|
end
|
@@ -144,7 +152,7 @@ module Appium
|
|
144
152
|
# +:matchFeatures is by default.
|
145
153
|
# @param [String] first_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
146
154
|
# @param [String] second_image An image data. All image formats, that OpenCV library itself accepts, are supported.
|
147
|
-
# @param [Hash] options The content of this dictionary depends on the actual +mode+ value.
|
155
|
+
# @param [Hash, nil] options The content of this dictionary depends on the actual +mode+ value.
|
148
156
|
# See the documentation on +appium-support+ module for more details.
|
149
157
|
# @return [Hash] The content of the resulting dictionary depends on the actual +mode+ and +options+ values.
|
150
158
|
# See the documentation on +appium-support+ module for more details.
|
@@ -25,8 +25,8 @@ module Appium
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def press_keycode(key, metastate: [], flags: [])
|
28
|
-
raise ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
29
|
-
raise ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
28
|
+
raise ::Appium::Core::Error::ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
29
|
+
raise ::Appium::Core::Error::ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
30
30
|
|
31
31
|
args = { keycode: key }
|
32
32
|
args[:metastate] = metastate.reduce(0) { |acc, meta| acc | meta } unless metastate.empty?
|
@@ -36,8 +36,8 @@ module Appium
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def long_press_keycode(key, metastate: [], flags: [])
|
39
|
-
raise ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
40
|
-
raise ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
39
|
+
raise ::Appium::Core::Error::ArgumentError, 'flags should be Array' unless flags.is_a? Array
|
40
|
+
raise ::Appium::Core::Error::ArgumentError, 'metastates should be Array' unless metastate.is_a? Array
|
41
41
|
|
42
42
|
args = { keycode: key }
|
43
43
|
args[:metastate] = metastate.reduce(0) { |acc, meta| acc | meta } unless metastate.empty?
|
@@ -14,15 +14,18 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
|
18
|
-
module
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
class Base
|
18
|
+
module Device
|
19
|
+
module Orientation
|
20
|
+
def screen_orientation=(orientation)
|
21
|
+
execute :set_screen_orientation, {}, { orientation: orientation }
|
22
|
+
end
|
23
|
+
|
24
|
+
def screen_orientation
|
25
|
+
execute :get_screen_orientation
|
26
|
+
end
|
27
|
+
end # module Orientation
|
28
|
+
end # module Device
|
29
|
+
end # class Base
|
27
30
|
end # module Core
|
28
|
-
end # Appium
|
31
|
+
end # module Appium
|
@@ -17,12 +17,12 @@ module Appium
|
|
17
17
|
class Base
|
18
18
|
module Device
|
19
19
|
module Value
|
20
|
-
def set_immediate_value(
|
21
|
-
execute :set_immediate_value, { id:
|
20
|
+
def set_immediate_value(element_id, *value)
|
21
|
+
execute :set_immediate_value, { id: element_id }, generate_value_and_text(value)
|
22
22
|
end
|
23
23
|
|
24
|
-
def replace_value(
|
25
|
-
execute :replace_value, { id:
|
24
|
+
def replace_value(element_id, *value)
|
25
|
+
execute :replace_value, { id: element_id }, generate_value_and_text(value)
|
26
26
|
end
|
27
27
|
|
28
28
|
private
|
@@ -39,11 +39,11 @@ module Appium
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# Keep .split(//) for backward compatibility for now
|
42
|
-
text = keys.join
|
42
|
+
text = keys.join
|
43
43
|
|
44
44
|
# FIXME: further work for W3C. Over appium 1.15.0 or later
|
45
45
|
# { value: text.split(//), text: text }
|
46
|
-
{ value: text.
|
46
|
+
{ value: text.chars }
|
47
47
|
end
|
48
48
|
end # module Value
|
49
49
|
end # module Device
|
@@ -27,8 +27,11 @@ module Appium
|
|
27
27
|
|
28
28
|
class UnsupportedOperationError < CoreError; end
|
29
29
|
|
30
|
-
# Server side
|
30
|
+
# Server side errors
|
31
31
|
class ServerError < CoreError; end
|
32
|
+
|
33
|
+
# ruby_lib_core library specific errors
|
34
|
+
class ArgumentError < CoreError; end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
@@ -65,7 +65,10 @@ module Appium
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def event=(log_event)
|
68
|
-
|
68
|
+
unless log_event.is_a?(Hash)
|
69
|
+
raise ::Appium::Core::Error::ArgumentError,
|
70
|
+
'log_event should be Hash like { vendor: "appium", event: "funEvent"}'
|
71
|
+
end
|
69
72
|
|
70
73
|
event vendor: log_event[:vendor], event: log_event[:event]
|
71
74
|
end
|