appium_lib_core 4.1.0 → 5.0.0.beta2
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 +2 -2
- data/CHANGELOG.md +40 -275
- data/appium_lib_core.gemspec +4 -4
- data/ci-jobs/functional/run_appium.yml +2 -2
- data/ci-jobs/functional_test.yml +1 -1
- data/lib/appium_lib_core/android/device.rb +4 -4
- data/lib/appium_lib_core/common/base/bridge.rb +263 -88
- data/lib/appium_lib_core/common/base/capabilities.rb +3 -3
- data/lib/appium_lib_core/common/base/driver.rb +92 -37
- data/lib/appium_lib_core/common/base/has_location.rb +73 -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 +1 -1
- data/lib/appium_lib_core/common/base/search_context.rb +2 -0
- 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/{command/mjsonwp.rb → device/orientation.rb} +14 -11
- data/lib/appium_lib_core/device.rb +1 -5
- data/lib/appium_lib_core/driver.rb +18 -13
- data/lib/appium_lib_core/{patch.rb → element.rb} +53 -5
- 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 +1 -4
- data/release_notes.md +59 -0
- data/script/commands.rb +3 -37
- metadata +24 -26
- 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
@@ -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.
|
@@ -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
|
@@ -79,11 +79,7 @@ module Appium
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def create_bridge_command(method, &block)
|
82
|
-
::Appium::Core::Base::Bridge
|
83
|
-
undef_method method if method_defined? method
|
84
|
-
block_given? ? class_eval(&block) : define_method(method) { execute method }
|
85
|
-
end
|
86
|
-
::Appium::Core::Base::Bridge::W3C.class_eval do
|
82
|
+
::Appium::Core::Base::Bridge.class_eval do
|
87
83
|
undef_method method if method_defined? method
|
88
84
|
block_given? ? class_eval(&block) : define_method(method) { execute method }
|
89
85
|
end
|
@@ -27,6 +27,8 @@ module Appium
|
|
27
27
|
autoload :Xcuitest, 'appium_lib_core/ios_xcuitest'
|
28
28
|
end
|
29
29
|
|
30
|
+
autoload :Mac2, 'appium_lib_core/mac2'
|
31
|
+
|
30
32
|
autoload :Windows, 'appium_lib_core/windows'
|
31
33
|
|
32
34
|
# This options affects only client side as <code>:appium_lib</code> key.<br>
|
@@ -45,7 +47,7 @@ module Appium
|
|
45
47
|
@export_session = appium_lib_opts.fetch :export_session, false
|
46
48
|
@export_session_path = appium_lib_opts.fetch :export_session_path, default_tmp_appium_lib_session
|
47
49
|
|
48
|
-
@direct_connect = appium_lib_opts.fetch :direct_connect,
|
50
|
+
@direct_connect = appium_lib_opts.fetch :direct_connect, true
|
49
51
|
|
50
52
|
@port = appium_lib_opts.fetch :port, Driver::DEFAULT_APPIUM_PORT
|
51
53
|
|
@@ -175,7 +177,7 @@ module Appium
|
|
175
177
|
# - <code>directConnectPort</code>
|
176
178
|
# - <code>directConnectPath</code>
|
177
179
|
#
|
178
|
-
# Ignore them if this parameter is <code>false</code>. Defaults to
|
180
|
+
# Ignore them if this parameter is <code>false</code>. Defaults to true.
|
179
181
|
#
|
180
182
|
# @return [Bool]
|
181
183
|
attr_reader :direct_connect
|
@@ -366,10 +368,10 @@ module Appium
|
|
366
368
|
|
367
369
|
begin
|
368
370
|
# included https://github.com/SeleniumHQ/selenium/blob/43f8b3f66e7e01124eff6a5805269ee441f65707/rb/lib/selenium/webdriver/remote/driver.rb#L29
|
369
|
-
@driver = ::Appium::Core::Base::Driver.new(
|
370
|
-
|
371
|
-
|
372
|
-
|
371
|
+
@driver = ::Appium::Core::Base::Driver.new(listener: @listener,
|
372
|
+
http_client: @http_client,
|
373
|
+
desired_capabilities: @caps,
|
374
|
+
url: @custom_url)
|
373
375
|
|
374
376
|
if @direct_connect
|
375
377
|
d_c = DirectConnections.new(@driver.capabilities)
|
@@ -435,7 +437,8 @@ module Appium
|
|
435
437
|
nil
|
436
438
|
end
|
437
439
|
|
438
|
-
# Returns the server's version info
|
440
|
+
# Returns the server's version info. This method calls +driver.remote_status+ internally
|
441
|
+
#
|
439
442
|
# @return [Hash]
|
440
443
|
#
|
441
444
|
# @example
|
@@ -449,18 +452,20 @@ module Appium
|
|
449
452
|
# }
|
450
453
|
# }
|
451
454
|
#
|
452
|
-
# Returns blank hash
|
455
|
+
# Returns blank hash in a case +driver.remote_status+ got an error
|
456
|
+
# such as Selenium Grid. It returns 500 error against 'remote_status'.
|
453
457
|
#
|
454
458
|
# @example
|
455
459
|
#
|
456
460
|
# @core.appium_server_version #=> {}
|
457
461
|
#
|
458
462
|
def appium_server_version
|
459
|
-
@driver.
|
460
|
-
rescue Selenium::WebDriver::Error::ServerError => e
|
461
|
-
raise ::Appium::Core::Error::ServerError unless e.message.include?('status code 500')
|
463
|
+
return {} if @driver.nil?
|
462
464
|
|
463
|
-
|
465
|
+
@driver.remote_status
|
466
|
+
rescue StandardError
|
467
|
+
# Ignore error case in a case the target appium server
|
468
|
+
# does not support `/status` API.
|
464
469
|
{}
|
465
470
|
end
|
466
471
|
|
@@ -526,7 +531,7 @@ module Appium
|
|
526
531
|
when :gecko
|
527
532
|
::Appium::Logger.debug('Gecko Driver for macOS')
|
528
533
|
when :mac2
|
529
|
-
::Appium::
|
534
|
+
::Appium::Core::Mac2::Bridge.for self
|
530
535
|
else
|
531
536
|
# no Mac specific extentions
|
532
537
|
::Appium::Logger.debug('macOS Native')
|
@@ -12,14 +12,13 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# rubocop:disable Style/ClassAndModuleChildren
|
16
15
|
module Appium
|
17
16
|
module Core
|
18
17
|
# Implement useful features for element.
|
19
18
|
# Patch for Selenium Webdriver.
|
20
|
-
class Selenium::WebDriver::Element
|
21
|
-
# To extend Appium related SearchContext into ::Selenium::WebDriver::Element
|
19
|
+
class Element < ::Selenium::WebDriver::Element
|
22
20
|
include ::Appium::Core::Base::SearchContext
|
21
|
+
include ::Appium::Core::Base::TakesScreenshot
|
23
22
|
|
24
23
|
# Returns the value of attributes like below. Read each platform to know more details.
|
25
24
|
#
|
@@ -99,7 +98,56 @@ module Appium
|
|
99
98
|
w = driver.window_size
|
100
99
|
::Selenium::WebDriver::Point.new "#{center_x} / #{w.width.to_f}", "#{center_y} / #{w.height.to_f}"
|
101
100
|
end
|
102
|
-
|
101
|
+
|
102
|
+
# Return an element screenshot as base64
|
103
|
+
#
|
104
|
+
# @return String Base 64 encoded string
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
#
|
108
|
+
# element.screenshot #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
|
109
|
+
#
|
110
|
+
def screenshot
|
111
|
+
bridge.take_element_screenshot(self)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return an element screenshot in the given format
|
115
|
+
#
|
116
|
+
# @param [:base64, :png] format
|
117
|
+
# @return String screenshot
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
#
|
121
|
+
# element.screenshot_as :base64 #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
|
122
|
+
#
|
123
|
+
def screenshot_as(format)
|
124
|
+
case format
|
125
|
+
when :base64
|
126
|
+
bridge.take_element_screenshot(self)
|
127
|
+
when :png
|
128
|
+
bridge.take_element_screenshot(self).unpack('m')[0]
|
129
|
+
else
|
130
|
+
raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Save an element screenshot to the given path
|
135
|
+
#
|
136
|
+
# @param [String] png_path A path to save the screenshot
|
137
|
+
# @return [File] Path to the element screenshot.
|
138
|
+
#
|
139
|
+
# @example
|
140
|
+
#
|
141
|
+
# element.save_screenshot("fine_name.png")
|
142
|
+
#
|
143
|
+
def save_screenshot(png_path)
|
144
|
+
extension = File.extname(png_path).downcase
|
145
|
+
if extension != '.png'
|
146
|
+
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
|
147
|
+
'It should end with .png extension'
|
148
|
+
end
|
149
|
+
File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
|
150
|
+
end
|
151
|
+
end # class Element
|
103
152
|
end # module Core
|
104
153
|
end # module Appium
|
105
|
-
# rubocop:enable Style/ClassAndModuleChildren
|
@@ -21,7 +21,7 @@ module Appium
|
|
21
21
|
# will trigger as soon as the file is required. in contrast a method
|
22
22
|
# will trigger only when invoked.
|
23
23
|
def self.patch_webdriver_element
|
24
|
-
::
|
24
|
+
::Appium::Core::Element.class_eval do
|
25
25
|
# Cross platform way of entering text into a textfield
|
26
26
|
def type(text, driver)
|
27
27
|
driver.execute_script %(au.getElement('#{ref}').setValue('#{text}');)
|
@@ -14,11 +14,12 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
|
18
|
-
module
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
17
|
+
module Mac2
|
18
|
+
module Bridge
|
19
|
+
def self.for(target)
|
20
|
+
target.extend Appium::Core::Mac2::Device
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
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
|
+
module Mac2
|
18
|
+
module Device
|
19
|
+
module Screen
|
20
|
+
def self.add_methods
|
21
|
+
::Appium::Core::Device.add_endpoint_method(:start_recording_screen) do
|
22
|
+
def start_recording_screen(remote_path: nil, user: nil, pass: nil, method: 'PUT',
|
23
|
+
file_field_name: nil, form_fields: nil, headers: nil, force_restart: nil,
|
24
|
+
fps: nil, preset: nil, video_filter: nil, time_limit: nil,
|
25
|
+
enable_capture_clicks: nil, enable_cursor_capture: nil, device_id: nil)
|
26
|
+
option = ::Appium::Core::Base::Device::ScreenRecord.new(
|
27
|
+
remote_path: remote_path, user: user, pass: pass, method: method,
|
28
|
+
file_field_name: file_field_name, form_fields: form_fields, headers: headers,
|
29
|
+
force_restart: force_restart
|
30
|
+
).upload_option
|
31
|
+
|
32
|
+
option[:fps] = fps unless fps.nil?
|
33
|
+
option[:preset] = preset unless preset.nil?
|
34
|
+
option[:videoFilter] = video_filter unless video_filter.nil?
|
35
|
+
option[:captureClicks] = enable_capture_clicks unless enable_capture_clicks.nil?
|
36
|
+
option[:captureCursor] = enable_cursor_capture unless enable_cursor_capture.nil?
|
37
|
+
option[:deviceId] = device_id unless device_id.nil?
|
38
|
+
option[:timeLimit] = time_limit unless time_limit.nil?
|
39
|
+
|
40
|
+
execute(:start_recording_screen, {}, { options: option })
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end # module Screen
|
45
|
+
end # module Device
|
46
|
+
end # module Mac2
|
47
|
+
end # module Core
|
48
|
+
end # module Appium
|