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.
@@ -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::W3C::Capabilities] Return instance of Appium::Core::Base::Capabilities
23
- # inherited ::Selenium::WebDriver::Remote::W3C::Capabilities
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::W3C::Capabilities.new(opts_caps)
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
- OSS = ::Selenium::WebDriver::Remote::OSS::Bridge::COMMANDS.freeze
20
- W3C = ::Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS.freeze
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
- def initialize(opts = {})
38
- listener = opts.delete(:listener)
39
- @bridge = ::Appium::Core::Base::Bridge.handshake(**opts)
40
- if @bridge.dialect == :oss # MJSONWP
41
- extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
42
- extend ::Selenium::WebDriver::DriverExtensions::HasLocation
43
- extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
44
- elsif @bridge.dialect == :w3c
45
- # TODO: Only for Appium. Ideally, we'd like to remove the below like selenium-webdriver
46
- extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
47
- extend ::Selenium::WebDriver::DriverExtensions::HasLocation
48
- extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
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
- super(@bridge, listener: listener)
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.fatal "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
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::W3C::Capabilities]
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::W3C::Capabilities:0x007fa38dae1360
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::W3C::Capabilities:0x007fb15dc01370
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.warn(message)
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
- module Commands
18
- module MJSONWP
19
- COMMANDS = ::Appium::Core::Commands::COMMANDS.merge(::Appium::Core::Base::Commands::OSS).merge(
20
- {
21
- # W3C already has.
22
- take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot']
23
- }
24
- ).freeze
25
- end # module MJSONWP
26
- end # module Commands
27
- end # module Core
28
- end # Appium
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