appium_lib_core 5.0.0.beta1 → 5.0.0.rc1

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