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