appium_lib_core 4.1.0 → 5.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/unittest.yml +2 -2
  4. data/CHANGELOG.md +51 -277
  5. data/README.md +2 -1
  6. data/Rakefile +4 -0
  7. data/appium_lib_core.gemspec +4 -4
  8. data/ci-jobs/functional/run_appium.yml +2 -2
  9. data/ci-jobs/functional_test.yml +2 -2
  10. data/docs/mobile_command.md +3 -2
  11. data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
  12. data/lib/appium_lib_core/android/device.rb +4 -4
  13. data/lib/appium_lib_core/common/base/bridge.rb +300 -89
  14. data/lib/appium_lib_core/common/base/capabilities.rb +10 -3
  15. data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
  16. data/lib/appium_lib_core/common/base/driver.rb +150 -112
  17. data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
  18. data/lib/appium_lib_core/common/base/has_location.rb +80 -0
  19. data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
  20. data/lib/appium_lib_core/common/base/http_default.rb +1 -3
  21. data/lib/appium_lib_core/common/base/remote_status.rb +31 -0
  22. data/lib/appium_lib_core/common/base/rotable.rb +54 -0
  23. data/lib/appium_lib_core/common/base/screenshot.rb +5 -4
  24. data/lib/appium_lib_core/common/base/search_context.rb +11 -4
  25. data/lib/appium_lib_core/common/base.rb +1 -3
  26. data/lib/appium_lib_core/common/command.rb +259 -4
  27. data/lib/appium_lib_core/common/device/image_comparison.rb +12 -4
  28. data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
  29. data/lib/appium_lib_core/common/{command/mjsonwp.rb → device/orientation.rb} +14 -11
  30. data/lib/appium_lib_core/common/device/value.rb +4 -4
  31. data/lib/appium_lib_core/common/error.rb +4 -1
  32. data/lib/appium_lib_core/common/log.rb +4 -1
  33. data/lib/appium_lib_core/common/touch_action/touch_actions.rb +4 -1
  34. data/lib/appium_lib_core/device.rb +1 -5
  35. data/lib/appium_lib_core/driver.rb +23 -27
  36. data/lib/appium_lib_core/{patch.rb → element.rb} +57 -9
  37. data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
  38. data/lib/appium_lib_core/{common/base/command.rb → mac2/bridge.rb} +9 -8
  39. data/lib/appium_lib_core/mac2/device/screen.rb +48 -0
  40. data/lib/appium_lib_core/mac2/device.rb +92 -0
  41. data/lib/appium_lib_core/mac2.rb +17 -0
  42. data/lib/appium_lib_core/version.rb +2 -2
  43. data/lib/appium_lib_core.rb +2 -5
  44. data/release_notes.md +82 -0
  45. data/script/commands.rb +3 -37
  46. metadata +30 -30
  47. data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
  48. data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -252
  49. data/lib/appium_lib_core/common/command/common.rb +0 -110
  50. data/lib/appium_lib_core/common/command/w3c.rb +0 -56
@@ -0,0 +1,49 @@
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
+ class DeviceIME
22
+ # @private this class is private
23
+ def initialize(bridge)
24
+ @bridge = bridge
25
+ end
26
+
27
+ def activate(ime_name)
28
+ @bridge.ime_activate(ime_name)
29
+ end
30
+
31
+ def available_engines
32
+ @bridge.ime_available_engines
33
+ end
34
+
35
+ def active_engine
36
+ @bridge.ime_active_engine
37
+ end
38
+
39
+ def activated?
40
+ @bridge.ime_activated
41
+ end
42
+
43
+ def deactivate
44
+ @bridge.ime_deactivate
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -13,8 +13,14 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'base64'
16
+ require_relative 'device_ime'
17
+ require_relative 'driver_settings'
16
18
  require_relative 'search_context'
17
19
  require_relative 'screenshot'
20
+ require_relative 'rotable'
21
+ require_relative 'remote_status'
22
+ require_relative 'has_location'
23
+ require_relative 'has_network_connection'
18
24
 
19
25
  module Appium
20
26
  module Core
@@ -22,42 +28,51 @@ module Appium
22
28
  class Driver < ::Selenium::WebDriver::Driver
23
29
  include ::Selenium::WebDriver::DriverExtensions::UploadsFiles
24
30
  include ::Selenium::WebDriver::DriverExtensions::HasSessionId
25
- include ::Selenium::WebDriver::DriverExtensions::Rotatable
26
31
  include ::Selenium::WebDriver::DriverExtensions::HasRemoteStatus
27
32
  include ::Selenium::WebDriver::DriverExtensions::HasWebStorage
28
33
 
34
+ include ::Appium::Core::Base::Rotatable
29
35
  include ::Appium::Core::Base::SearchContext
30
- include ::Appium::Core::Base::TakeScreenshot
36
+ include ::Appium::Core::Base::TakesScreenshot
37
+ include ::Appium::Core::Base::HasRemoteStatus
38
+ include ::Appium::Core::Base::HasLocation
39
+ include ::Appium::Core::Base::HasNetworkConnection
40
+
41
+ private
31
42
 
32
43
  # Private API.
33
44
  # Do not use this for general use. Used by flutter driver to get bridge for creating a new element
34
45
  attr_reader :bridge
35
46
 
36
- def initialize(opts = {})
37
- listener = opts.delete(:listener)
38
- @bridge = ::Appium::Core::Base::Bridge.handshake(**opts)
39
- if @bridge.dialect == :oss # MJSONWP
40
- extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
41
- extend ::Selenium::WebDriver::DriverExtensions::HasLocation
42
- extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
43
- elsif @bridge.dialect == :w3c
44
- # TODO: Only for Appium. Ideally, we'd like to remove the below like selenium-webdriver
45
- extend ::Selenium::WebDriver::DriverExtensions::HasTouchScreen
46
- extend ::Selenium::WebDriver::DriverExtensions::HasLocation
47
- extend ::Selenium::WebDriver::DriverExtensions::HasNetworkConnection
48
- end
49
- super(@bridge, listener: listener)
47
+ def initialize(bridge: nil, listener: nil, **opts)
48
+ super
50
49
  end
51
50
 
52
- # Get the dialect value
53
- # @return [:oss|:w3c]
54
- def dialect
55
- @bridge.dialect
51
+ # Implements protocol handshake which:
52
+ #
53
+ # 1. Creates session with driver.
54
+ # 2. Sniffs response.
55
+ # 3. Based on the response, understands which dialect we should use.
56
+ #
57
+ # @return [::Appium::Core::Base::Bridge]
58
+ #
59
+ def create_bridge(**opts)
60
+ capabilities = opts.delete(:capabilities)
61
+ bridge_opts = { http_client: opts.delete(:http_client), url: opts.delete(:url) }
62
+ raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
63
+
64
+ bridge = ::Appium::Core::Base::Bridge.new(**bridge_opts)
65
+
66
+ bridge.create_session(capabilities)
67
+ bridge
56
68
  end
57
69
 
70
+ public
71
+
58
72
  # Update +server_url+ and HTTP clients following this arguments, protocol, host, port and path.
59
73
  # After this method, +@bridge.http+ will be a new instance following them instead of +server_url+ which is
60
74
  # set before creating session.
75
+ # If +@bridge.http+ did not have +update_sending_request_to+ method, this method returns immediately.
61
76
  #
62
77
  # @example
63
78
  #
@@ -66,10 +81,96 @@ module Appium
66
81
  # driver.manage.timeouts.implicit_wait = 10 # @bridge.http is for 'https://example2.com:9000/wd/hub/'
67
82
  #
68
83
  def update_sending_request_to(protocol:, host:, port:, path:)
69
- @bridge.http.update_sending_request_to(scheme: protocol,
70
- host: host,
71
- port: port,
72
- path: path)
84
+ unless @bridge.http&.class&.method_defined? :update_sending_request_to
85
+ ::Appium::Logger.warn "#{@bridge.http&.class} has no 'update_sending_request_to'. " \
86
+ 'It keeps current connection target.'
87
+ return
88
+ end
89
+
90
+ @bridge.http&.update_sending_request_to(scheme: protocol,
91
+ host: host,
92
+ port: port,
93
+ path: path)
94
+ end
95
+
96
+ AVAILABLE_METHODS = [
97
+ :get, :head, :post, :put, :delete,
98
+ :connect, :options, :trace, :patch
99
+ ].freeze
100
+ # Define a new custom method to the driver so that you can define your own method for
101
+ # drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you
102
+ # to define custom commands that are not part of W3C spec.
103
+ #
104
+ # @param [Symbol] method HTTP request method as https://www.w3.org/TR/webdriver/#endpoints
105
+ # @param [string] url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints.
106
+ # +:session_id+ is the placeholder of 'session id'.
107
+ # Other place holders can be specified with +:+ prefix like +:id+.
108
+ # Then, the +:id+ will be replaced with a given value as the seconds argument of +execute+
109
+ # @param [Symbol] name The name of method that is called as the driver instance method.
110
+ # @param [Proc] block The block to involve as the method.
111
+ # Please define a method that has the same +name+ with arguments you want.
112
+ # The method must has +execute+ method. tHe +execute+ is calls the +url+
113
+ # with the given parameters.
114
+ # The first argument should be +name+ as symbol.
115
+ # The second argument should be hash. If keys in the hash matches +:+ prefix
116
+ # string in the given url, the matched string in the given url will be
117
+ # values in the hash.
118
+ # The third argument should be hash. The hash will be the request body.
119
+ # Please read examples below for more details.
120
+ # @raise [ArgumentError] If the given +method+ is invalid value.
121
+ #
122
+ # @example
123
+ #
124
+ # @driver.add_command(
125
+ # method: :get,
126
+ # url: 'session/:session_id/path/to/custom/url',
127
+ # name: :test_command
128
+ # )
129
+ # # Send a GET request to 'session/<session id>/path/to/custom/url'
130
+ # @driver.test_command
131
+ #
132
+ #
133
+ # @driver.add_command(
134
+ # method: :post,
135
+ # url: 'session/:session_id/path/to/custom/url',
136
+ # name: :test_command
137
+ # ) do
138
+ # def test_command(argument)
139
+ # execute(:test_command, {}, { dummy: argument })
140
+ # end
141
+ # end
142
+ # # Send a POST request to 'session/<session id>/path/to/custom/url'
143
+ # # with body "{ dummy: 1 }" as JSON object. "1" is the argument.
144
+ # # ':session_id' in the given 'url' is replaced with current 'session id'.
145
+ # @driver.test_command(1)
146
+ #
147
+ #
148
+ # @driver.add_command(
149
+ # method: :post,
150
+ # url: 'session/:session_id/element/:id/custom/action',
151
+ # name: :test_action_command
152
+ # ) do
153
+ # def test_action_command(element_id, action)
154
+ # execute(:test_action_command, {id: element_id}, { dummy_action: action })
155
+ # end
156
+ # end
157
+ # # Send a POST request to 'session/<session id>/element/<element id>/custom/action'
158
+ # # with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
159
+ # # ':session_id' in the given url is replaced with current 'session id'.
160
+ # # ':id' in the given url is replaced with the given 'element_id'.
161
+ # e = @driver.find_element :accessibility_id, 'an element'
162
+ # _, element_id = e.ref
163
+ # @driver.test_action_command(element_id, 'action')
164
+ #
165
+ def add_command(method:, url:, name:, &block)
166
+ unless AVAILABLE_METHODS.include? method
167
+ raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}"
168
+ end
169
+
170
+ # TODO: Remove this logger before Appium 2.0 release
171
+ ::Appium::Logger.info '[Experimental] this method is experimental for Appium 2.0. This interface may change.'
172
+
173
+ @bridge.add_command method: method, url: url, name: name, &block
73
174
  end
74
175
 
75
176
  ### Methods for Appium
@@ -154,22 +255,6 @@ module Appium
154
255
  end
155
256
  alias type send_keys
156
257
 
157
- class DriverSettings
158
- # @private this class is private
159
- def initialize(bridge)
160
- @bridge = bridge
161
- end
162
-
163
- def get
164
- @bridge.get_settings
165
- end
166
-
167
- def update(settings)
168
- @bridge.update_settings(settings)
169
- end
170
- end
171
- private_constant :DriverSettings
172
-
173
258
  # Returns an instance of DriverSettings to call get/update.
174
259
  #
175
260
  # @example
@@ -178,7 +263,7 @@ module Appium
178
263
  # @driver.settings.update('allowInvisibleElements': true)
179
264
  #
180
265
  def settings
181
- @driver_settings ||= DriverSettings.new(@bridge) # rubocop:disable Naming/MemoizedInstanceVariableName
266
+ @settings ||= DriverSettings.new(@bridge)
182
267
  end
183
268
 
184
269
  # Get appium Settings for current test session.
@@ -200,8 +285,8 @@ module Appium
200
285
  #
201
286
  # @example
202
287
  #
203
- # @driver.update_settings('allowInvisibleElements': true)
204
- # @driver.settings.update('allowInvisibleElements': true)
288
+ # @driver.update_settings({ 'allowInvisibleElements': true })
289
+ # @driver.settings.update({ 'allowInvisibleElements': true })
205
290
  # @driver.settings = { 'allowInvisibleElements': true }
206
291
  #
207
292
  def settings=(value)
@@ -209,36 +294,10 @@ module Appium
209
294
  end
210
295
  alias update_settings settings=
211
296
 
212
- class DeviceIME
213
- # @private this class is private
214
- def initialize(bridge)
215
- @bridge = bridge
216
- end
217
-
218
- def activate(ime_name)
219
- @bridge.ime_activate(ime_name)
220
- end
221
-
222
- def available_engines
223
- @bridge.ime_available_engines
224
- end
225
-
226
- def active_engine
227
- @bridge.ime_active_engine
228
- end
229
-
230
- def activated?
231
- @bridge.ime_activated
232
- end
233
-
234
- def deactivate
235
- @bridge.ime_deactivate
236
- end
237
- end
238
- private_constant :DeviceIME
239
-
240
297
  # Returns an instance of DeviceIME
241
298
  #
299
+ # @return [Appium::Core::Base::Driver::DeviceIME]
300
+ #
242
301
  # @example
243
302
  #
244
303
  # @driver.ime.activate engine: 'com.android.inputmethod.latin/.LatinIME'
@@ -248,7 +307,7 @@ module Appium
248
307
  # @driver.ime.deactivate #=> Deactivate current IME engine
249
308
  #
250
309
  def ime
251
- @device_ime ||= DeviceIME.new(@bridge) # rubocop:disable Naming/MemoizedInstanceVariableName
310
+ @ime ||= DeviceIME.new(@bridge)
252
311
  end
253
312
 
254
313
  # Android only. Make an engine that is available active.
@@ -289,6 +348,8 @@ module Appium
289
348
  # @!method ime_activated
290
349
  # Android only. Indicates whether IME input is active at the moment (not if it is available).
291
350
  #
351
+ # @return [Boolean]
352
+ #
292
353
  # @example
293
354
  #
294
355
  # @driver.ime_activated #=> True if IME is activated
@@ -366,30 +427,6 @@ module Appium
366
427
  end
367
428
  alias set_context context=
368
429
 
369
- # Set the value to element directly
370
- #
371
- # @example
372
- #
373
- # @driver.set_immediate_value element, 'hello'
374
- #
375
- def set_immediate_value(element, *value)
376
- ::Appium::Logger.warn '[DEPRECATION] driver#set_immediate_value(element, *value) is deprecated. ' \
377
- 'Use Element#immediate_value(*value) instead'
378
- @bridge.set_immediate_value(element, *value)
379
- end
380
-
381
- # Replace the value to element directly
382
- #
383
- # @example
384
- #
385
- # @driver.replace_value element, 'hello'
386
- #
387
- def replace_value(element, *value)
388
- ::Appium::Logger.warn '[DEPRECATION] driver#replace_value(element, *value) is deprecated. ' \
389
- 'Use Element#replace_value(*value) instead'
390
- @bridge.replace_value(element, *value)
391
- end
392
-
393
430
  # Place a file in a specific location on the device.
394
431
  # On iOS, the server should have ifuse libraries installed and configured properly for this feature to work on
395
432
  # real devices.
@@ -809,7 +846,7 @@ module Appium
809
846
  # @driver.perform_actions [f1, f2] #=> 'nil' if the action succeed
810
847
  #
811
848
  def perform_actions(data)
812
- raise ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
849
+ raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
813
850
 
814
851
  @bridge.send_actions data.map(&:encode).compact
815
852
  data.each(&:clear_actions)
@@ -853,7 +890,7 @@ module Appium
853
890
  end
854
891
 
855
892
  # Get the device window's logs.
856
- # @return [String]
893
+ # @return [Appium::Core::Logs]
857
894
  #
858
895
  # @example
859
896
  #
@@ -879,16 +916,15 @@ module Appium
879
916
  # Retrieve the capabilities of the specified session.
880
917
  # It's almost same as +@driver.capabilities+ but you can get more details.
881
918
  #
882
- # @return [Selenium::WebDriver::Remote::Capabilities]
919
+ # @return [Selenium::WebDriver::Remote::Capabilities, Selenium::WebDriver::Remote::Capabilities]
883
920
  #
884
921
  # @example
885
922
  # @driver.session_capabilities
886
923
  #
887
924
  # #=> uiautomator2
888
- # # <Selenium::WebDriver::Remote::W3C::Capabilities:0x007fa38dae1360
925
+ # # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
889
926
  # # @capabilities=
890
- # # {:proxy=>nil,
891
- # # :browser_name=>nil,
927
+ # # {:browser_name=>nil,
892
928
  # # :browser_version=>nil,
893
929
  # # :platform_name=>"android",
894
930
  # # :page_load_strategy=>nil,
@@ -935,10 +971,9 @@ module Appium
935
971
  # # "viewportRect"=>{"left"=>0, "top"=>63, "width"=>1080, "height"=>1731}}>
936
972
  # #
937
973
  # #=> XCUITest
938
- # # <Selenium::WebDriver::Remote::W3C::Capabilities:0x007fb15dc01370
974
+ # # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
939
975
  # # @capabilities=
940
- # # {:proxy=>nil,
941
- # # :browser_name=>"UICatalog",
976
+ # # {:browser_name=>"UICatalog",
942
977
  # # :browser_version=>nil,
943
978
  # # :platform_name=>"ios",
944
979
  # # :page_load_strategy=>nil,
@@ -992,11 +1027,14 @@ module Appium
992
1027
  visualize: visualize)
993
1028
  end
994
1029
 
995
- def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil)
1030
+ def find_image_occurrence(full_image:, partial_image:, visualize: false, threshold: nil,
1031
+ multiple: nil, match_neighbour_threshold: nil)
996
1032
  @bridge.find_image_occurrence(full_image: full_image,
997
1033
  partial_image: partial_image,
998
1034
  visualize: visualize,
999
- threshold: threshold)
1035
+ threshold: threshold,
1036
+ multiple: multiple,
1037
+ match_neighbour_threshold: match_neighbour_threshold)
1000
1038
  end
1001
1039
 
1002
1040
  def get_images_similarity(first_image:, second_image:, visualize: false)
@@ -1016,7 +1054,7 @@ module Appium
1016
1054
  #
1017
1055
  # @param [String] img_path A path to a partial image you'd like to find
1018
1056
  #
1019
- # @return [::Selenium::WebDriver::Element]
1057
+ # @return [::Appium::Core::Element]
1020
1058
  #
1021
1059
  # @example
1022
1060
  #
@@ -1038,7 +1076,7 @@ module Appium
1038
1076
  #
1039
1077
  # @param [String] img_path A path to a partial image you'd like to find
1040
1078
  #
1041
- # @return [::Selenium::WebDriver::Element]
1079
+ # @return [Array<Selenium::WebDriver::Element>]
1042
1080
  #
1043
1081
  # @example
1044
1082
  #
@@ -1086,14 +1124,14 @@ module Appium
1086
1124
  @bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
1087
1125
  end
1088
1126
 
1089
- # Convert vanilla element response to ::Selenium::WebDriver::Element
1127
+ # Convert vanilla element response to ::Appium::Core::Element
1090
1128
  #
1091
1129
  # @param [Hash] id The id which can get as a response from server
1092
- # @return [::Selenium::WebDriver::Element]
1130
+ # @return [::Appium::Core::Element]
1093
1131
  #
1094
1132
  # @example
1095
1133
  # response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
1096
- # ele = @driver.convert_to_element(response) #=> ::Selenium::WebDriver::Element
1134
+ # ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
1097
1135
  # ele.rect #=> Can get the rect of the element
1098
1136
  #
1099
1137
  def convert_to_element(id)
@@ -0,0 +1,51 @@
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
+ class DriverSettings
22
+ # @private this class is private
23
+ def initialize(bridge)
24
+ @bridge = bridge
25
+ end
26
+
27
+ # Get appium Settings for current test session.
28
+ #
29
+ # @example
30
+ #
31
+ # @driver.settings.get
32
+ #
33
+ def get
34
+ @bridge.get_settings
35
+ end
36
+
37
+ # Update Appium Settings for current test session
38
+ #
39
+ # @param [Hash] settings Settings to update, keys are settings, values to value to set each setting to
40
+ #
41
+ # @example
42
+ #
43
+ # @driver.settings.update({'allowInvisibleElements': true})
44
+ #
45
+ def update(settings)
46
+ @bridge.update_settings(settings)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,80 @@
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
56
+ # in meters/second @since Appium 1.21.0 and in knots for emulators @since Appium 1.22.0.
57
+ # @param [String, Number] satellites Sets the count of geo satellites being tracked in range 1..12 @since Appium 1.22.0.
58
+ # This number is respected on Emulators.
59
+ # @param [::Selenium::WebDriver::Location]
60
+ #
61
+ # @example
62
+ #
63
+ # driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
64
+ #
65
+ def set_location(latitude, longitude, altitude, speed: nil, satellites: nil)
66
+ if speed.nil? && satellites.nil?
67
+ self.location = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
68
+ else
69
+ loc = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
70
+
71
+ speed = Float(speed) unless speed.nil?
72
+ satellites = Integer(satellites) unless satellites.nil?
73
+
74
+ @bridge.set_location loc.latitude, loc.longitude, loc.altitude, speed: speed, satellites: satellites
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ 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 ::Appium::Core::Error::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
@@ -55,8 +55,6 @@ module Appium
55
55
  def update_sending_request_to(scheme:, host:, port:, path:)
56
56
  return @server_url unless validate_url_param(scheme, host, port, path)
57
57
 
58
- ::Appium::Logger.debug("[experimental] This feature, #{__method__}, is an experimental")
59
-
60
58
  # Add / if 'path' does not have it
61
59
  path = path.start_with?('/') ? path : "/#{path}"
62
60
  path = path.end_with?('/') ? path : "#{path}/"
@@ -71,7 +69,7 @@ module Appium
71
69
  return true unless [scheme, host, port, path].include?(nil)
72
70
 
73
71
  message = "Given parameters are scheme: '#{scheme}', host: '#{host}', port: '#{port}', path: '#{path}'"
74
- ::Appium::Logger.warn(message)
72
+ ::Appium::Logger.debug(message)
75
73
  false
76
74
  end
77
75