appium_lib_core 4.3.0 → 5.0.0.beta1
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 +20 -2
- 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/common/base.rb +0 -1
- data/lib/appium_lib_core/common/base/bridge.rb +17 -102
- data/lib/appium_lib_core/common/base/bridge/w3c.rb +108 -13
- data/lib/appium_lib_core/common/base/capabilities.rb +3 -3
- data/lib/appium_lib_core/common/base/command.rb +123 -2
- data/lib/appium_lib_core/common/base/driver.rb +67 -21
- 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 -1
- data/lib/appium_lib_core/common/{command/mjsonwp.rb → base/remote_status.rb} +15 -12
- data/lib/appium_lib_core/common/command.rb +0 -1
- data/lib/appium_lib_core/common/device/image_comparison.rb +9 -1
- data/lib/appium_lib_core/device.rb +0 -4
- data/lib/appium_lib_core/driver.rb +13 -10
- data/lib/appium_lib_core/version.rb +2 -2
- data/release_notes.md +27 -0
- data/script/commands.rb +2 -25
- metadata +17 -21
- data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
@@ -19,10 +19,10 @@ module Appium
|
|
19
19
|
# @private
|
20
20
|
# @param [Hash] opts_caps Capabilities for Appium server. All capability keys are converted to lowerCamelCase when
|
21
21
|
# this client sends capabilities to Appium server as JSON format.
|
22
|
-
# @return [::Selenium::WebDriver::Remote::
|
23
|
-
# inherited ::Selenium::WebDriver::Remote::
|
22
|
+
# @return [::Selenium::WebDriver::Remote::Capabilities] Return instance of Appium::Core::Base::Capabilities
|
23
|
+
# inherited ::Selenium::WebDriver::Remote::Capabilities
|
24
24
|
def self.create_capabilities(opts_caps = {})
|
25
|
-
::Selenium::WebDriver::Remote::
|
25
|
+
::Selenium::WebDriver::Remote::Capabilities.new(opts_caps)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -16,8 +16,129 @@ module Appium
|
|
16
16
|
module Core
|
17
17
|
class Base
|
18
18
|
module Commands
|
19
|
-
|
20
|
-
|
19
|
+
W3C = {
|
20
|
+
status: [:get, 'status'],
|
21
|
+
|
22
|
+
#
|
23
|
+
# session handling
|
24
|
+
#
|
25
|
+
|
26
|
+
new_session: [:post, 'session'],
|
27
|
+
delete_session: [:delete, 'session/:session_id'],
|
28
|
+
|
29
|
+
#
|
30
|
+
# basic driver
|
31
|
+
#
|
32
|
+
|
33
|
+
get: [:post, 'session/:session_id/url'],
|
34
|
+
get_current_url: [:get, 'session/:session_id/url'],
|
35
|
+
back: [:post, 'session/:session_id/back'],
|
36
|
+
forward: [:post, 'session/:session_id/forward'],
|
37
|
+
refresh: [:post, 'session/:session_id/refresh'],
|
38
|
+
get_title: [:get, 'session/:session_id/title'],
|
39
|
+
|
40
|
+
#
|
41
|
+
# window and Frame handling
|
42
|
+
#
|
43
|
+
|
44
|
+
get_window_handle: [:get, 'session/:session_id/window'],
|
45
|
+
new_window: [:post, 'session/:session_id/window/new'],
|
46
|
+
close_window: [:delete, 'session/:session_id/window'],
|
47
|
+
switch_to_window: [:post, 'session/:session_id/window'],
|
48
|
+
get_window_handles: [:get, 'session/:session_id/window/handles'],
|
49
|
+
fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
|
50
|
+
minimize_window: [:post, 'session/:session_id/window/minimize'],
|
51
|
+
maximize_window: [:post, 'session/:session_id/window/maximize'],
|
52
|
+
set_window_size: [:post, 'session/:session_id/window/size'],
|
53
|
+
get_window_size: [:get, 'session/:session_id/window/size'],
|
54
|
+
set_window_position: [:post, 'session/:session_id/window/position'],
|
55
|
+
get_window_position: [:get, 'session/:session_id/window/position'],
|
56
|
+
set_window_rect: [:post, 'session/:session_id/window/rect'],
|
57
|
+
get_window_rect: [:get, 'session/:session_id/window/rect'],
|
58
|
+
switch_to_frame: [:post, 'session/:session_id/frame'],
|
59
|
+
switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'],
|
60
|
+
|
61
|
+
#
|
62
|
+
# element
|
63
|
+
#
|
64
|
+
|
65
|
+
find_element: [:post, 'session/:session_id/element'],
|
66
|
+
find_elements: [:post, 'session/:session_id/elements'],
|
67
|
+
find_child_element: [:post, 'session/:session_id/element/:id/element'],
|
68
|
+
find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
|
69
|
+
get_active_element: [:get, 'session/:session_id/element/active'],
|
70
|
+
is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
|
71
|
+
get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
|
72
|
+
get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
|
73
|
+
get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
|
74
|
+
get_element_text: [:get, 'session/:session_id/element/:id/text'],
|
75
|
+
get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
|
76
|
+
get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
|
77
|
+
is_element_enabled: [:get, 'session/:session_id/element/:id/enabled'],
|
78
|
+
|
79
|
+
#
|
80
|
+
# document handling
|
81
|
+
#
|
82
|
+
|
83
|
+
get_page_source: [:get, 'session/:session_id/source'],
|
84
|
+
execute_script: [:post, 'session/:session_id/execute/sync'],
|
85
|
+
execute_async_script: [:post, 'session/:session_id/execute/async'],
|
86
|
+
|
87
|
+
#
|
88
|
+
# cookies
|
89
|
+
#
|
90
|
+
|
91
|
+
get_all_cookies: [:get, 'session/:session_id/cookie'],
|
92
|
+
get_cookie: [:get, 'session/:session_id/cookie/:name'],
|
93
|
+
add_cookie: [:post, 'session/:session_id/cookie'],
|
94
|
+
delete_cookie: [:delete, 'session/:session_id/cookie/:name'],
|
95
|
+
delete_all_cookies: [:delete, 'session/:session_id/cookie'],
|
96
|
+
|
97
|
+
#
|
98
|
+
# timeouts
|
99
|
+
#
|
100
|
+
|
101
|
+
set_timeout: [:post, 'session/:session_id/timeouts'],
|
102
|
+
|
103
|
+
#
|
104
|
+
# actions
|
105
|
+
#
|
106
|
+
|
107
|
+
actions: [:post, 'session/:session_id/actions'],
|
108
|
+
release_actions: [:delete, 'session/:session_id/actions'],
|
109
|
+
print_page: [:post, 'session/:session_id/print'],
|
110
|
+
|
111
|
+
#
|
112
|
+
# Element Operations
|
113
|
+
#
|
114
|
+
|
115
|
+
element_click: [:post, 'session/:session_id/element/:id/click'],
|
116
|
+
element_tap: [:post, 'session/:session_id/element/:id/tap'],
|
117
|
+
element_clear: [:post, 'session/:session_id/element/:id/clear'],
|
118
|
+
element_send_keys: [:post, 'session/:session_id/element/:id/value'],
|
119
|
+
|
120
|
+
#
|
121
|
+
# alerts
|
122
|
+
#
|
123
|
+
|
124
|
+
dismiss_alert: [:post, 'session/:session_id/alert/dismiss'],
|
125
|
+
accept_alert: [:post, 'session/:session_id/alert/accept'],
|
126
|
+
get_alert_text: [:get, 'session/:session_id/alert/text'],
|
127
|
+
send_alert_text: [:post, 'session/:session_id/alert/text'],
|
128
|
+
|
129
|
+
#
|
130
|
+
# screenshot
|
131
|
+
#
|
132
|
+
|
133
|
+
take_screenshot: [:get, 'session/:session_id/screenshot'],
|
134
|
+
take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
|
135
|
+
|
136
|
+
#
|
137
|
+
# server extensions
|
138
|
+
#
|
139
|
+
|
140
|
+
upload_file: [:post, 'session/:session_id/se/file']
|
141
|
+
}.freeze
|
21
142
|
end # module Commands
|
22
143
|
end # module Base
|
23
144
|
end # module Core
|
@@ -16,6 +16,9 @@ require 'base64'
|
|
16
16
|
require_relative 'search_context'
|
17
17
|
require_relative 'screenshot'
|
18
18
|
require_relative 'rotable'
|
19
|
+
require_relative 'remote_status'
|
20
|
+
require_relative 'has_location'
|
21
|
+
require_relative 'has_network_connection'
|
19
22
|
|
20
23
|
module Appium
|
21
24
|
module Core
|
@@ -29,25 +32,51 @@ module Appium
|
|
29
32
|
include ::Appium::Core::Base::Rotatable
|
30
33
|
include ::Appium::Core::Base::SearchContext
|
31
34
|
include ::Appium::Core::Base::TakesScreenshot
|
35
|
+
include ::Appium::Core::Base::HasRemoteStatus
|
36
|
+
include ::Appium::Core::Base::HasLocation
|
37
|
+
include ::Appium::Core::Base::HasNetworkConnection
|
32
38
|
|
33
39
|
# Private API.
|
34
40
|
# Do not use this for general use. Used by flutter driver to get bridge for creating a new element
|
35
41
|
attr_reader :bridge
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
# Almost same as self.handshake in ::Selenium::WebDriver::Remote::Bridge
|
44
|
+
#
|
45
|
+
# Implements protocol handshake which:
|
46
|
+
#
|
47
|
+
# 1. Creates session with driver.
|
48
|
+
# 2. Sniffs response.
|
49
|
+
# 3. Based on the response, understands which dialect we should use.
|
50
|
+
#
|
51
|
+
# @return [Bridge::W3C]
|
52
|
+
#
|
53
|
+
# TODO: Fixme
|
54
|
+
def create_bridge(**opts)
|
55
|
+
opts[:url] ||= service_url(opts)
|
56
|
+
caps = opts.delete(:capabilities)
|
57
|
+
# NOTE: This is deprecated
|
58
|
+
cap_array = caps.is_a?(Hash) ? [caps] : Array(caps)
|
59
|
+
|
60
|
+
desired_capabilities = opts.delete(:desired_capabilities)
|
61
|
+
if desired_capabilities
|
62
|
+
if desired_capabilities.is_a?(Hash)
|
63
|
+
desired_capabilities = ::Selenium::WebDriver::Remote::Capabilities(desired_capabilities)
|
64
|
+
end
|
65
|
+
cap_array << desired_capabilities
|
49
66
|
end
|
50
|
-
|
67
|
+
|
68
|
+
options = opts.delete(:options)
|
69
|
+
cap_array << options if options
|
70
|
+
|
71
|
+
capabilities = generate_capabilities(cap_array)
|
72
|
+
|
73
|
+
bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }
|
74
|
+
raise ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
75
|
+
|
76
|
+
bridge = ::Appium::Core::Base::Bridge::W3C.new(**bridge_opts)
|
77
|
+
|
78
|
+
bridge.create_session(capabilities)
|
79
|
+
bridge
|
51
80
|
end
|
52
81
|
|
53
82
|
# Get the dialect value
|
@@ -69,7 +98,7 @@ module Appium
|
|
69
98
|
#
|
70
99
|
def update_sending_request_to(protocol:, host:, port:, path:)
|
71
100
|
unless @bridge.http&.class&.method_defined? :update_sending_request_to
|
72
|
-
::Appium::Logger.
|
101
|
+
::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
|
73
102
|
'It keeps current connection target.'
|
74
103
|
return
|
75
104
|
end
|
@@ -168,10 +197,24 @@ module Appium
|
|
168
197
|
@bridge = bridge
|
169
198
|
end
|
170
199
|
|
200
|
+
# Get appium Settings for current test session.
|
201
|
+
#
|
202
|
+
# @example
|
203
|
+
#
|
204
|
+
# @driver.settings.get
|
205
|
+
#
|
171
206
|
def get
|
172
207
|
@bridge.get_settings
|
173
208
|
end
|
174
209
|
|
210
|
+
# Update Appium Settings for current test session
|
211
|
+
#
|
212
|
+
# @param [Hash] settings Settings to update, keys are settings, values to value to set each setting to
|
213
|
+
#
|
214
|
+
# @example
|
215
|
+
#
|
216
|
+
# @driver.settings.update({'allowInvisibleElements': true})
|
217
|
+
#
|
175
218
|
def update(settings)
|
176
219
|
@bridge.update_settings(settings)
|
177
220
|
end
|
@@ -208,8 +251,8 @@ module Appium
|
|
208
251
|
#
|
209
252
|
# @example
|
210
253
|
#
|
211
|
-
# @driver.update_settings('allowInvisibleElements': true)
|
212
|
-
# @driver.settings.update('allowInvisibleElements': true)
|
254
|
+
# @driver.update_settings({ 'allowInvisibleElements': true })
|
255
|
+
# @driver.settings.update({ 'allowInvisibleElements': true })
|
213
256
|
# @driver.settings = { 'allowInvisibleElements': true }
|
214
257
|
#
|
215
258
|
def settings=(value)
|
@@ -891,13 +934,13 @@ module Appium
|
|
891
934
|
# Retrieve the capabilities of the specified session.
|
892
935
|
# It's almost same as +@driver.capabilities+ but you can get more details.
|
893
936
|
#
|
894
|
-
# @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::
|
937
|
+
# @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::Capabilities]
|
895
938
|
#
|
896
939
|
# @example
|
897
940
|
# @driver.session_capabilities
|
898
941
|
#
|
899
942
|
# #=> uiautomator2
|
900
|
-
# # <Selenium::WebDriver::Remote::
|
943
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
|
901
944
|
# # @capabilities=
|
902
945
|
# # {:proxy=>nil,
|
903
946
|
# # :browser_name=>nil,
|
@@ -947,7 +990,7 @@ module Appium
|
|
947
990
|
# # "viewportRect"=>{"left"=>0, "top"=>63, "width"=>1080, "height"=>1731}}>
|
948
991
|
# #
|
949
992
|
# #=> XCUITest
|
950
|
-
# # <Selenium::WebDriver::Remote::
|
993
|
+
# # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
|
951
994
|
# # @capabilities=
|
952
995
|
# # {:proxy=>nil,
|
953
996
|
# # :browser_name=>"UICatalog",
|
@@ -1004,11 +1047,14 @@ module Appium
|
|
1004
1047
|
visualize: visualize)
|
1005
1048
|
end
|
1006
1049
|
|
1007
|
-
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil
|
1050
|
+
def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
|
1051
|
+
multiple: nil, match_neighbour_threshold: nil)
|
1008
1052
|
@bridge.find_image_occurrence(full_image: full_image,
|
1009
1053
|
partial_image: partial_image,
|
1010
1054
|
visualize: visualize,
|
1011
|
-
threshold: threshold
|
1055
|
+
threshold: threshold,
|
1056
|
+
multiple: multiple,
|
1057
|
+
match_neighbour_threshold: match_neighbour_threshold)
|
1012
1058
|
end
|
1013
1059
|
|
1014
1060
|
def get_images_similarity(first_image:, second_image:, visualize: false)
|
@@ -0,0 +1,73 @@
|
|
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
|
+
module HasLocation
|
22
|
+
# Get the location of the device.
|
23
|
+
#
|
24
|
+
# @return [::Selenium::WebDriver::Location]
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
#
|
28
|
+
# driver.location #=> ::Selenium::WebDriver::Location.new(10, 10, 10)
|
29
|
+
#
|
30
|
+
def location
|
31
|
+
@bridge.location
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set the location of the device.
|
35
|
+
#
|
36
|
+
# @param [::Selenium::WebDriver::Location] location Set the location.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
#
|
40
|
+
# driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
|
41
|
+
#
|
42
|
+
def location=(location)
|
43
|
+
unless location.is_a?(::Selenium::WebDriver::Location)
|
44
|
+
raise TypeError, "expected #{::Selenium::WebDriver::Location}, got #{location.inspect}:#{location.class}"
|
45
|
+
end
|
46
|
+
|
47
|
+
@bridge.set_location location.latitude, location.longitude, location.altitude
|
48
|
+
end
|
49
|
+
|
50
|
+
# Set the location of the device.
|
51
|
+
#
|
52
|
+
# @param [String, Number] latitude Set the latitude.
|
53
|
+
# @param [String, Number] longitude Set the longitude.
|
54
|
+
# @param [String, Number] altitude Set the altitude.
|
55
|
+
# @param [String, Number] speed Set the speed to apply the location on Android real devices @since Appium 1.21.0.
|
56
|
+
# @param [::Selenium::WebDriver::Location]
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
#
|
60
|
+
# driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
|
61
|
+
#
|
62
|
+
def set_location(latitude, longitude, altitude, speed: nil)
|
63
|
+
if speed.nil?
|
64
|
+
self.location = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
|
65
|
+
else
|
66
|
+
loc = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
|
67
|
+
@bridge.set_location loc.latitude, loc.longitude, loc.altitude, speed: Float(speed)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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
|
+
module HasNetworkConnection
|
22
|
+
def network_connection_type
|
23
|
+
connection_value = @bridge.network_connection
|
24
|
+
|
25
|
+
connection_type = values_to_type[connection_value]
|
26
|
+
|
27
|
+
# In case the connection type is not recognized return the
|
28
|
+
# connection value.
|
29
|
+
connection_type || connection_value
|
30
|
+
end
|
31
|
+
|
32
|
+
def network_connection_type=(connection_type)
|
33
|
+
raise ArgumentError, 'Invalid connection type' unless valid_type? connection_type
|
34
|
+
|
35
|
+
connection_value = type_to_values[connection_type]
|
36
|
+
|
37
|
+
@bridge.network_connection = connection_value
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def type_to_values
|
43
|
+
{ airplane_mode: 1, wifi: 2, data: 4, all: 6, none: 0 }
|
44
|
+
end
|
45
|
+
|
46
|
+
def values_to_type
|
47
|
+
type_to_values.invert
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_type?(type)
|
51
|
+
type_to_values.keys.include? type
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -69,7 +69,7 @@ module Appium
|
|
69
69
|
return true unless [scheme, host, port, path].include?(nil)
|
70
70
|
|
71
71
|
message = "Given parameters are scheme: '#{scheme}', host: '#{host}', port: '#{port}', path: '#{path}'"
|
72
|
-
::Appium::Logger.
|
72
|
+
::Appium::Logger.debug(message)
|
73
73
|
false
|
74
74
|
end
|
75
75
|
|
@@ -14,15 +14,18 @@
|
|
14
14
|
|
15
15
|
module Appium
|
16
16
|
module Core
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
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
|