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.
@@ -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