appium_lib_core 5.0.0.beta1 → 5.0.0.rc1

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -6
  3. data/README.md +2 -1
  4. data/Rakefile +4 -0
  5. data/appium_lib_core.gemspec +3 -3
  6. data/ci-jobs/functional_test.yml +1 -1
  7. data/docs/mobile_command.md +3 -2
  8. data/lib/appium_lib_core/android/device/auth_finger_print.rb +2 -1
  9. data/lib/appium_lib_core/common/base/bridge.rb +303 -7
  10. data/lib/appium_lib_core/common/base/device_ime.rb +49 -0
  11. data/lib/appium_lib_core/common/base/driver.rb +101 -105
  12. data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
  13. data/lib/appium_lib_core/common/base/has_location.rb +11 -4
  14. data/lib/appium_lib_core/common/base/has_network_connection.rb +1 -1
  15. data/lib/appium_lib_core/common/base/rotable.rb +1 -1
  16. data/lib/appium_lib_core/common/base/screenshot.rb +4 -3
  17. data/lib/appium_lib_core/common/base/search_context.rb +9 -4
  18. data/lib/appium_lib_core/common/base.rb +0 -2
  19. data/lib/appium_lib_core/common/command.rb +259 -3
  20. data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
  21. data/lib/appium_lib_core/common/device/value.rb +4 -4
  22. data/lib/appium_lib_core/common/error.rb +4 -1
  23. data/lib/appium_lib_core/common/log.rb +4 -1
  24. data/lib/appium_lib_core/common/touch_action/touch_actions.rb +4 -1
  25. data/lib/appium_lib_core/device.rb +1 -1
  26. data/lib/appium_lib_core/driver.rb +3 -4
  27. data/lib/appium_lib_core/{patch.rb → element.rb} +9 -14
  28. data/lib/appium_lib_core/ios/uiautomation/patch.rb +1 -1
  29. data/lib/appium_lib_core/version.rb +2 -2
  30. data/lib/appium_lib_core.rb +2 -5
  31. data/release_notes.md +23 -0
  32. data/script/commands.rb +1 -12
  33. metadata +15 -17
  34. data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -348
  35. data/lib/appium_lib_core/common/base/command.rb +0 -145
  36. data/lib/appium_lib_core/common/command/common.rb +0 -110
  37. 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,6 +13,8 @@
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'
18
20
  require_relative 'rotable'
@@ -36,23 +38,25 @@ module Appium
36
38
  include ::Appium::Core::Base::HasLocation
37
39
  include ::Appium::Core::Base::HasNetworkConnection
38
40
 
41
+ private
42
+
39
43
  # Private API.
40
44
  # Do not use this for general use. Used by flutter driver to get bridge for creating a new element
41
45
  attr_reader :bridge
42
46
 
43
- # Almost same as self.handshake in ::Selenium::WebDriver::Remote::Bridge
44
- #
47
+ def initialize(bridge: nil, listener: nil, **opts)
48
+ super
49
+ end
50
+
45
51
  # Implements protocol handshake which:
46
52
  #
47
53
  # 1. Creates session with driver.
48
54
  # 2. Sniffs response.
49
55
  # 3. Based on the response, understands which dialect we should use.
50
56
  #
51
- # @return [Bridge::W3C]
57
+ # @return [::Appium::Core::Base::Bridge]
52
58
  #
53
- # TODO: Fixme
54
59
  def create_bridge(**opts)
55
- opts[:url] ||= service_url(opts)
56
60
  caps = opts.delete(:capabilities)
57
61
  # NOTE: This is deprecated
58
62
  cap_array = caps.is_a?(Hash) ? [caps] : Array(caps)
@@ -71,19 +75,15 @@ module Appium
71
75
  capabilities = generate_capabilities(cap_array)
72
76
 
73
77
  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?
78
+ raise ::Appium::Core::Error::ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
75
79
 
76
- bridge = ::Appium::Core::Base::Bridge::W3C.new(**bridge_opts)
80
+ bridge = ::Appium::Core::Base::Bridge.new(**bridge_opts)
77
81
 
78
82
  bridge.create_session(capabilities)
79
83
  bridge
80
84
  end
81
85
 
82
- # Get the dialect value
83
- # @return [:oss|:w3c]
84
- def dialect
85
- @bridge.dialect
86
- end
86
+ public
87
87
 
88
88
  # Update +server_url+ and HTTP clients following this arguments, protocol, host, port and path.
89
89
  # After this method, +@bridge.http+ will be a new instance following them instead of +server_url+ which is
@@ -109,6 +109,86 @@ module Appium
109
109
  path: path)
110
110
  end
111
111
 
112
+ AVAILABLE_METHODS = [
113
+ :get, :head, :post, :put, :delete,
114
+ :connect, :options, :trace, :patch
115
+ ].freeze
116
+ # Define a new custom method to the driver so that you can define your own method for
117
+ # drivers/plugins in Appium 2.0. Appium 2.0 and its custom drivers/plugins allow you
118
+ # to define custom commands that are not part of W3C spec.
119
+ #
120
+ # @param [Symbol] method HTTP request method as https://www.w3.org/TR/webdriver/#endpoints
121
+ # @param [string] url The url to URL template as https://www.w3.org/TR/webdriver/#endpoints.
122
+ # +:session_id+ is the placeholder of 'session id'.
123
+ # Other place holders can be specified with +:+ prefix like +:id+.
124
+ # Then, the +:id+ will be replaced with a given value as the seconds argument of +execute+
125
+ # @param [Symbol] name The name of method that is called as the driver instance method.
126
+ # @param [Proc] block The block to involve as the method.
127
+ # Please define a method that has the same +name+ with arguments you want.
128
+ # The method must has +execute+ method. tHe +execute+ is calls the +url+
129
+ # with the given parameters.
130
+ # The first argument should be +name+ as symbol.
131
+ # The second argument should be hash. If keys in the hash matches +:+ prefix
132
+ # string in the given url, the matched string in the given url will be
133
+ # values in the hash.
134
+ # The third argument should be hash. The hash will be the request body.
135
+ # Please read examples below for more details.
136
+ # @raise [ArgumentError] If the given +method+ is invalid value.
137
+ #
138
+ # @example
139
+ #
140
+ # @driver.add_command(
141
+ # method: :get,
142
+ # url: 'session/:session_id/path/to/custom/url',
143
+ # name: :test_command
144
+ # )
145
+ # # Send a GET request to 'session/<session id>/path/to/custom/url'
146
+ # @driver.test_command
147
+ #
148
+ #
149
+ # @driver.add_command(
150
+ # method: :post,
151
+ # url: 'session/:session_id/path/to/custom/url',
152
+ # name: :test_command
153
+ # ) do
154
+ # def test_command(argument)
155
+ # execute(:test_command, {}, { dummy: argument })
156
+ # end
157
+ # end
158
+ # # Send a POST request to 'session/<session id>/path/to/custom/url'
159
+ # # with body "{ dummy: 1 }" as JSON object. "1" is the argument.
160
+ # # ':session_id' in the given 'url' is replaced with current 'session id'.
161
+ # @driver.test_command(1)
162
+ #
163
+ #
164
+ # @driver.add_command(
165
+ # method: :post,
166
+ # url: 'session/:session_id/element/:id/custom/action',
167
+ # name: :test_action_command
168
+ # ) do
169
+ # def test_action_command(element_id, action)
170
+ # execute(:test_action_command, {id: element_id}, { dummy_action: action })
171
+ # end
172
+ # end
173
+ # # Send a POST request to 'session/<session id>/element/<element id>/custom/action'
174
+ # # with body "{ dummy_action: #{action} }" as JSON object. "action" is the seconds argument.
175
+ # # ':session_id' in the given url is replaced with current 'session id'.
176
+ # # ':id' in the given url is replaced with the given 'element_id'.
177
+ # e = @driver.find_element :accessibility_id, 'an element'
178
+ # _, element_id = e.ref
179
+ # @driver.test_action_command(element_id, 'action')
180
+ #
181
+ def add_command(method:, url:, name:, &block)
182
+ unless AVAILABLE_METHODS.include? method
183
+ raise ::Appium::Core::Error::ArgumentError, "Available method is either #{AVAILABLE_METHODS}"
184
+ end
185
+
186
+ # TODO: Remove this logger before Appium 2.0 release
187
+ ::Appium::Logger.info '[Experimental] this method is experimental for Appium 2.0. This interface may change.'
188
+
189
+ @bridge.add_command method: method, url: url, name: name, &block
190
+ end
191
+
112
192
  ### Methods for Appium
113
193
 
114
194
  # Lock the device
@@ -191,36 +271,6 @@ module Appium
191
271
  end
192
272
  alias type send_keys
193
273
 
194
- class DriverSettings
195
- # @private this class is private
196
- def initialize(bridge)
197
- @bridge = bridge
198
- end
199
-
200
- # Get appium Settings for current test session.
201
- #
202
- # @example
203
- #
204
- # @driver.settings.get
205
- #
206
- def get
207
- @bridge.get_settings
208
- end
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
- #
218
- def update(settings)
219
- @bridge.update_settings(settings)
220
- end
221
- end
222
- private_constant :DriverSettings
223
-
224
274
  # Returns an instance of DriverSettings to call get/update.
225
275
  #
226
276
  # @example
@@ -229,7 +279,7 @@ module Appium
229
279
  # @driver.settings.update('allowInvisibleElements': true)
230
280
  #
231
281
  def settings
232
- @driver_settings ||= DriverSettings.new(@bridge) # rubocop:disable Naming/MemoizedInstanceVariableName
282
+ @settings ||= DriverSettings.new(@bridge)
233
283
  end
234
284
 
235
285
  # Get appium Settings for current test session.
@@ -260,34 +310,6 @@ module Appium
260
310
  end
261
311
  alias update_settings settings=
262
312
 
263
- class DeviceIME
264
- # @private this class is private
265
- def initialize(bridge)
266
- @bridge = bridge
267
- end
268
-
269
- def activate(ime_name)
270
- @bridge.ime_activate(ime_name)
271
- end
272
-
273
- def available_engines
274
- @bridge.ime_available_engines
275
- end
276
-
277
- def active_engine
278
- @bridge.ime_active_engine
279
- end
280
-
281
- def activated?
282
- @bridge.ime_activated
283
- end
284
-
285
- def deactivate
286
- @bridge.ime_deactivate
287
- end
288
- end
289
- private_constant :DeviceIME
290
-
291
313
  # Returns an instance of DeviceIME
292
314
  #
293
315
  # @return [Appium::Core::Base::Driver::DeviceIME]
@@ -301,7 +323,7 @@ module Appium
301
323
  # @driver.ime.deactivate #=> Deactivate current IME engine
302
324
  #
303
325
  def ime
304
- @device_ime ||= DeviceIME.new(@bridge) # rubocop:disable Naming/MemoizedInstanceVariableName
326
+ @ime ||= DeviceIME.new(@bridge)
305
327
  end
306
328
 
307
329
  # Android only. Make an engine that is available active.
@@ -421,30 +443,6 @@ module Appium
421
443
  end
422
444
  alias set_context context=
423
445
 
424
- # Set the value to element directly
425
- #
426
- # @example
427
- #
428
- # @driver.set_immediate_value element, 'hello'
429
- #
430
- def set_immediate_value(element, *value)
431
- ::Appium::Logger.warn '[DEPRECATION] driver#set_immediate_value(element, *value) is deprecated. ' \
432
- 'Use Element#immediate_value(*value) instead'
433
- @bridge.set_immediate_value(element, *value)
434
- end
435
-
436
- # Replace the value to element directly
437
- #
438
- # @example
439
- #
440
- # @driver.replace_value element, 'hello'
441
- #
442
- def replace_value(element, *value)
443
- ::Appium::Logger.warn '[DEPRECATION] driver#replace_value(element, *value) is deprecated. ' \
444
- 'Use Element#replace_value(*value) instead'
445
- @bridge.replace_value(element, *value)
446
- end
447
-
448
446
  # Place a file in a specific location on the device.
449
447
  # On iOS, the server should have ifuse libraries installed and configured properly for this feature to work on
450
448
  # real devices.
@@ -864,7 +862,7 @@ module Appium
864
862
  # @driver.perform_actions [f1, f2] #=> 'nil' if the action succeed
865
863
  #
866
864
  def perform_actions(data)
867
- raise ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
865
+ raise ::Appium::Core::Error::ArgumentError, "'#{data}' must be Array" unless data.is_a? Array
868
866
 
869
867
  @bridge.send_actions data.map(&:encode).compact
870
868
  data.each(&:clear_actions)
@@ -942,8 +940,7 @@ module Appium
942
940
  # #=> uiautomator2
943
941
  # # <Selenium::WebDriver::Remote::Capabilities:0x007fa38dae1360
944
942
  # # @capabilities=
945
- # # {:proxy=>nil,
946
- # # :browser_name=>nil,
943
+ # # {:browser_name=>nil,
947
944
  # # :browser_version=>nil,
948
945
  # # :platform_name=>"android",
949
946
  # # :page_load_strategy=>nil,
@@ -992,8 +989,7 @@ module Appium
992
989
  # #=> XCUITest
993
990
  # # <Selenium::WebDriver::Remote::Capabilities:0x007fb15dc01370
994
991
  # # @capabilities=
995
- # # {:proxy=>nil,
996
- # # :browser_name=>"UICatalog",
992
+ # # {:browser_name=>"UICatalog",
997
993
  # # :browser_version=>nil,
998
994
  # # :platform_name=>"ios",
999
995
  # # :page_load_strategy=>nil,
@@ -1074,7 +1070,7 @@ module Appium
1074
1070
  #
1075
1071
  # @param [String] img_path A path to a partial image you'd like to find
1076
1072
  #
1077
- # @return [::Selenium::WebDriver::Element]
1073
+ # @return [::Appium::Core::Element]
1078
1074
  #
1079
1075
  # @example
1080
1076
  #
@@ -1144,14 +1140,14 @@ module Appium
1144
1140
  @bridge.execute_driver(script: script, type: type, timeout_ms: timeout_ms)
1145
1141
  end
1146
1142
 
1147
- # Convert vanilla element response to ::Selenium::WebDriver::Element
1143
+ # Convert vanilla element response to ::Appium::Core::Element
1148
1144
  #
1149
1145
  # @param [Hash] id The id which can get as a response from server
1150
- # @return [::Selenium::WebDriver::Element]
1146
+ # @return [::Appium::Core::Element]
1151
1147
  #
1152
1148
  # @example
1153
1149
  # response = {"element-6066-11e4-a52e-4f735466cecf"=>"xxxx", "ELEMENT"=>"xxxx"}
1154
- # ele = @driver.convert_to_element(response) #=> ::Selenium::WebDriver::Element
1150
+ # ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
1155
1151
  # ele.rect #=> Can get the rect of the element
1156
1152
  #
1157
1153
  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
@@ -52,19 +52,26 @@ module Appium
52
52
  # @param [String, Number] latitude Set the latitude.
53
53
  # @param [String, Number] longitude Set the longitude.
54
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.
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.
56
59
  # @param [::Selenium::WebDriver::Location]
57
60
  #
58
61
  # @example
59
62
  #
60
63
  # driver.location = ::Selenium::WebDriver::Location.new(10, 10, 10)
61
64
  #
62
- def set_location(latitude, longitude, altitude, speed: nil)
63
- if speed.nil?
65
+ def set_location(latitude, longitude, altitude, speed: nil, satellites: nil)
66
+ if speed.nil? && satellites.nil?
64
67
  self.location = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
65
68
  else
66
69
  loc = ::Selenium::WebDriver::Location.new(Float(latitude), Float(longitude), Float(altitude))
67
- @bridge.set_location loc.latitude, loc.longitude, loc.altitude, speed: Float(speed)
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
68
75
  end
69
76
  end
70
77
  end