appium_lib_core 4.1.0 → 9.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +357 -270
  3. data/README.md +68 -16
  4. data/Rakefile +8 -20
  5. data/Steepfile +11 -0
  6. data/appium_lib_core.gemspec +13 -15
  7. data/bin/console +0 -4
  8. data/lib/appium_lib_core/android/device/auth_finger_print.rb +4 -1
  9. data/lib/appium_lib_core/android/device/clipboard.rb +4 -2
  10. data/lib/appium_lib_core/android/device/emulator.rb +11 -5
  11. data/lib/appium_lib_core/android/device/network.rb +10 -0
  12. data/lib/appium_lib_core/android/device/performance.rb +3 -0
  13. data/lib/appium_lib_core/android/device/screen.rb +5 -1
  14. data/lib/appium_lib_core/android/device.rb +83 -20
  15. data/lib/appium_lib_core/common/base/bridge.rb +238 -95
  16. data/lib/appium_lib_core/common/base/capabilities.rb +21 -8
  17. data/lib/appium_lib_core/common/{command/mjsonwp.rb → base/device_ime.rb} +33 -12
  18. data/lib/appium_lib_core/common/base/driver.rb +260 -334
  19. data/lib/appium_lib_core/common/base/driver_settings.rb +51 -0
  20. data/lib/appium_lib_core/common/base/has_location.rb +80 -0
  21. data/lib/appium_lib_core/common/base/has_network_connection.rb +56 -0
  22. data/lib/appium_lib_core/common/base/http_default.rb +22 -38
  23. data/lib/appium_lib_core/{ios/uiautomation/bridge.rb → common/base/remote_status.rb} +9 -8
  24. data/lib/appium_lib_core/common/base/rotable.rb +62 -0
  25. data/lib/appium_lib_core/common/base/screenshot.rb +10 -10
  26. data/lib/appium_lib_core/common/base/search_context.rb +98 -172
  27. data/lib/appium_lib_core/common/base.rb +1 -5
  28. data/lib/appium_lib_core/common/command.rb +244 -4
  29. data/lib/appium_lib_core/common/device/app_management.rb +2 -26
  30. data/lib/appium_lib_core/common/device/context.rb +1 -5
  31. data/lib/appium_lib_core/common/device/image_comparison.rb +27 -10
  32. data/lib/appium_lib_core/common/device/keyevent.rb +4 -4
  33. data/lib/appium_lib_core/common/device/{touch_actions.rb → orientation.rb} +6 -10
  34. data/lib/appium_lib_core/common/device/screen_record.rb +8 -2
  35. data/lib/appium_lib_core/common/error.rb +5 -5
  36. data/lib/appium_lib_core/common/log.rb +5 -4
  37. data/lib/appium_lib_core/common/wait.rb +38 -6
  38. data/lib/appium_lib_core/device.rb +3 -9
  39. data/lib/appium_lib_core/driver.rb +193 -182
  40. data/lib/appium_lib_core/{patch.rb → element.rb} +64 -26
  41. data/lib/appium_lib_core/ios/device/clipboard.rb +4 -2
  42. data/lib/appium_lib_core/ios/xcuitest/device.rb +2 -0
  43. data/lib/appium_lib_core/{common/base/command.rb → mac2/bridge.rb} +9 -8
  44. data/lib/appium_lib_core/mac2/device/screen.rb +48 -0
  45. data/lib/appium_lib_core/mac2/device.rb +92 -0
  46. data/lib/appium_lib_core/{ios.rb → mac2.rb} +2 -5
  47. data/lib/appium_lib_core/support/event_firing_bridge.rb +57 -0
  48. data/lib/appium_lib_core/version.rb +2 -2
  49. data/lib/appium_lib_core.rb +23 -10
  50. data/rbs_collection.lock.yaml +252 -0
  51. data/rbs_collection.yaml +15 -0
  52. data/sig/gems/selenium/abstract_event_listener.rbs +8 -0
  53. data/sig/gems/selenium/capabilities.rbs +8 -0
  54. data/sig/gems/selenium/common.rbs +10 -0
  55. data/sig/gems/selenium/default.rbs +10 -0
  56. data/sig/gems/selenium/driver.rbs +7 -0
  57. data/sig/gems/selenium/has_session_id.rbs +8 -0
  58. data/sig/gems/selenium/has_web_storage.rbs +8 -0
  59. data/sig/gems/selenium/uploads_files.rbs +8 -0
  60. data/sig/lib/appium_lib_core/common/base/capabilities.rbs +9 -0
  61. data/sig/lib/appium_lib_core/common/base/driver.rbs +167 -0
  62. data/sig/lib/appium_lib_core/common/base/driver_settings.rbs +15 -0
  63. data/sig/lib/appium_lib_core/common/base/has_location.rbs +13 -0
  64. data/sig/lib/appium_lib_core/common/base/has_network_connection.rbs +19 -0
  65. data/sig/lib/appium_lib_core/common/base/http_default.rbs +38 -0
  66. data/sig/lib/appium_lib_core/common/base/platform.rbs +7 -0
  67. data/sig/lib/appium_lib_core/common/base/remote_status.rbs +9 -0
  68. data/sig/lib/appium_lib_core/common/base/rotable.rbs +17 -0
  69. data/sig/lib/appium_lib_core/common/base/screenshot.rbs +19 -0
  70. data/sig/lib/appium_lib_core/common/device/battery_status.rbs +13 -0
  71. data/sig/lib/appium_lib_core/common/wait.rbs +31 -0
  72. data/sig/lib/appium_lib_core/device.rbs +21 -0
  73. data/sig/lib/appium_lib_core/driver.rbs +196 -0
  74. data/sig/lib/appium_lib_core/ios/xcuitest/device/battery.rbs +15 -0
  75. data/sig/lib/appium_lib_core/version.rbs +7 -0
  76. data/sig/lib/appium_lib_core.rbs +8 -0
  77. metadata +88 -111
  78. data/.github/ISSUE_TEMPLATE/issue-report.md +0 -29
  79. data/.github/contributing.md +0 -26
  80. data/.github/issue_template.md +0 -20
  81. data/.github/workflows/unittest.yml +0 -68
  82. data/.gitignore +0 -18
  83. data/.rubocop.yml +0 -58
  84. data/azure-pipelines.yml +0 -15
  85. data/ci-jobs/functional/android_setup.yml +0 -3
  86. data/ci-jobs/functional/ios_setup.yml +0 -7
  87. data/ci-jobs/functional/publish_test_result.yml +0 -18
  88. data/ci-jobs/functional/run_appium.yml +0 -25
  89. data/ci-jobs/functional/start-emulator.sh +0 -26
  90. data/ci-jobs/functional_test.yml +0 -298
  91. data/docs/mobile_command.md +0 -34
  92. data/lib/appium_lib_core/common/base/bridge/mjsonwp.rb +0 -81
  93. data/lib/appium_lib_core/common/base/bridge/w3c.rb +0 -252
  94. data/lib/appium_lib_core/common/command/common.rb +0 -110
  95. data/lib/appium_lib_core/common/command/w3c.rb +0 -56
  96. data/lib/appium_lib_core/common/device/value.rb +0 -52
  97. data/lib/appium_lib_core/common/touch_action/multi_touch.rb +0 -56
  98. data/lib/appium_lib_core/common/touch_action/touch_actions.rb +0 -203
  99. data/lib/appium_lib_core/ios/uiautomation/device.rb +0 -44
  100. data/lib/appium_lib_core/ios/uiautomation/patch.rb +0 -34
  101. data/release_notes.md +0 -816
  102. data/script/commands.rb +0 -200
@@ -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 [::Appium::Location]
25
+ #
26
+ # @example
27
+ #
28
+ # driver.location #=> ::Appium::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 [::Appium::Location] location Set the location.
37
+ #
38
+ # @example
39
+ #
40
+ # driver.location = ::Appium::Location.new(10, 10, 10)
41
+ #
42
+ def location=(location)
43
+ unless location.is_a?(::Appium::Location)
44
+ raise TypeError, "expected #{::Appium::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 [::Appium::Location]
60
+ #
61
+ # @example
62
+ #
63
+ # driver.location = ::Appium::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 = ::Appium::Location.new(Float(latitude), Float(longitude), Float(altitude))
68
+ else
69
+ loc = ::Appium::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
@@ -13,6 +13,8 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'securerandom'
16
+ # to avoid mysterious resolution error 'uninitialized constant Selenium::WebDriver::Remote::Http::Default::Net (NameError)'
17
+ require 'net/http'
16
18
 
17
19
  require_relative '../../version'
18
20
 
@@ -26,21 +28,29 @@ module Appium
26
28
  }.freeze
27
29
  end
28
30
 
29
- class Default < Selenium::WebDriver::Remote::Http::Default
30
- DEFAULT_HEADERS = {
31
- 'Accept' => CONTENT_TYPE,
32
- 'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8",
33
- 'User-Agent' =>
34
- "appium/ruby_lib_core/#{VERSION} (#{::Selenium::WebDriver::Remote::Http::Common::DEFAULT_HEADERS['User-Agent']})"
35
- }.freeze
36
-
31
+ class Default < ::Selenium::WebDriver::Remote::Http::Default
37
32
  attr_reader :additional_headers
38
33
 
34
+ ::Selenium::WebDriver::Remote::Http::Common.user_agent = \
35
+ "appium/ruby_lib_core/#{VERSION} (#{::Selenium::WebDriver::Remote::Http::Common.user_agent})"
36
+
39
37
  # override
40
- def initialize(open_timeout: nil, read_timeout: nil) # rubocop:disable Lint/MissingSuper
38
+ def initialize(open_timeout: nil, read_timeout: nil)
41
39
  @open_timeout = open_timeout
42
40
  @read_timeout = read_timeout
43
41
  @additional_headers = {}
42
+ super
43
+ end
44
+
45
+ def set_additional_header(key, value)
46
+ @additional_headers[key] = value
47
+ ::Selenium::WebDriver::Remote::Http::Common.extra_headers = @additional_headers
48
+ end
49
+
50
+ def delete_additional_header(key)
51
+ @additional_headers.delete key
52
+ ::Selenium::WebDriver::Remote::Http::Common.extra_headers = @additional_headers
53
+ @common_headers.delete key if defined? @common_headers
44
54
  end
45
55
 
46
56
  # Update <code>server_url</code> provided when ruby_lib _core created a default http client.
@@ -55,11 +65,9 @@ module Appium
55
65
  def update_sending_request_to(scheme:, host:, port:, path:)
56
66
  return @server_url unless validate_url_param(scheme, host, port, path)
57
67
 
58
- ::Appium::Logger.debug("[experimental] This feature, #{__method__}, is an experimental")
59
-
60
68
  # Add / if 'path' does not have it
61
- path = path.start_with?('/') ? path : "/#{path}"
62
- path = path.end_with?('/') ? path : "#{path}/"
69
+ path = "/#{path}" unless path.start_with?('/')
70
+ path = "#{path}/" unless path.end_with?('/')
63
71
 
64
72
  @http = nil
65
73
  @server_url = URI.parse "#{scheme}://#{host}:#{port}#{path}"
@@ -71,33 +79,9 @@ module Appium
71
79
  return true unless [scheme, host, port, path].include?(nil)
72
80
 
73
81
  message = "Given parameters are scheme: '#{scheme}', host: '#{host}', port: '#{port}', path: '#{path}'"
74
- ::Appium::Logger.warn(message)
82
+ ::Appium::Logger.debug(message)
75
83
  false
76
84
  end
77
-
78
- public
79
-
80
- # override to use default header
81
- # https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/remote/http/common.rb#L46
82
- def call(verb, url, command_hash)
83
- url = server_url.merge(url) unless url.is_a?(URI)
84
- headers = DEFAULT_HEADERS.dup
85
- headers = headers.merge @additional_headers unless @additional_headers.empty?
86
- headers['Cache-Control'] = 'no-cache' if verb == :get
87
-
88
- if command_hash
89
- payload = JSON.generate(command_hash)
90
- headers['Content-Length'] = payload.bytesize.to_s if [:post, :put].include?(verb)
91
- elsif verb == :post
92
- payload = '{}'
93
- headers['Content-Length'] = '2'
94
- end
95
-
96
- ::Appium::Logger.info(" >>> #{url} | #{payload}")
97
- ::Appium::Logger.info(" > #{headers.inspect}")
98
-
99
- request verb, url, headers, payload
100
- end
101
85
  end
102
86
  end
103
87
  end
@@ -14,15 +14,16 @@
14
14
 
15
15
  module Appium
16
16
  module Core
17
- module Ios
18
- module Uiautomation
19
- module Bridge
20
- def self.for(target)
21
- target.extend Appium::Core::Ios::Device
17
+ class Base
18
+ #
19
+ # @api private
20
+ #
22
21
 
23
- Core::Ios::Uiautomation.patch_webdriver_element
24
- Core::Ios::Uiautomation::Device.add_methods
25
- end
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
26
27
  end
27
28
  end
28
29
  end
@@ -0,0 +1,62 @@
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
+
22
+ module Rotatable
23
+ ORIENTATIONS = %i[
24
+ landscape
25
+ portrait
26
+ uia_device_orientation_landscaperight
27
+ uia_device_orientation_portrait_upsidedown
28
+ ].freeze
29
+
30
+ #
31
+ # Change the screen orientation
32
+ #
33
+ # @param [:landscape, :portrait,
34
+ # :uia_device_orientation_landscaperight, :uia_device_orientation_portrait_upsidedown] orientation
35
+ #
36
+ #
37
+ def rotation=(orientation)
38
+ unless ORIENTATIONS.include?(orientation)
39
+ raise ::Appium::Core::Error::ArgumentError, "expected #{ORIENTATIONS.inspect}, got #{orientation.inspect}"
40
+ end
41
+
42
+ bridge.screen_orientation = orientation.to_s.upcase
43
+ end
44
+ alias rotate rotation=
45
+ alias orientation= rotation=
46
+
47
+ #
48
+ # Get the current screen orientation
49
+ #
50
+ # @return [:landscape, :portrait,
51
+ # :uia_device_orientation_landscaperight, :uia_device_orientation_portrait_upsidedown] orientation
52
+ #
53
+ # @api public
54
+ #
55
+
56
+ def orientation
57
+ bridge.screen_orientation.to_sym.downcase
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -15,7 +15,7 @@
15
15
  module Appium
16
16
  module Core
17
17
  class Base
18
- module TakeScreenshot
18
+ module TakesScreenshot
19
19
  #
20
20
  # Save a PNG screenshot to the given path
21
21
  #
@@ -24,7 +24,7 @@ module Appium
24
24
  def save_screenshot(png_path)
25
25
  extension = File.extname(png_path).downcase
26
26
  if extension != '.png'
27
- ::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
27
+ ::Appium::Logger.warn 'name used for saved screenshot does not match file type. ' \
28
28
  'It should end with .png extension'
29
29
  end
30
30
  File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
@@ -48,7 +48,7 @@ module Appium
48
48
  when :png
49
49
  bridge.screenshot.unpack('m')[0]
50
50
  else
51
- raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
51
+ raise ::Appium::Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
52
52
  end
53
53
  end
54
54
 
@@ -63,8 +63,8 @@ module Appium
63
63
  def save_element_screenshot(element, png_path)
64
64
  extension = File.extname(png_path).downcase
65
65
  if extension != '.png'
66
- ::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
67
- 'It should end with .png extension'
66
+ ::Appium::Logger.warn 'name used for saved screenshot does not match file type. ' \
67
+ 'It should end with .png extension'
68
68
  end
69
69
  File.open(png_path, 'wb') { |f| f << element_screenshot_as(element, :png) }
70
70
  end
@@ -84,11 +84,11 @@ module Appium
84
84
  def element_screenshot_as(element, format)
85
85
  case format
86
86
  when :base64
87
- bridge.take_element_screenshot(element)
87
+ bridge.element_screenshot element.id
88
88
  when :png
89
- bridge.take_element_screenshot(element).unpack('m')[0]
89
+ bridge.element_screenshot(element.id).unpack('m')[0]
90
90
  else
91
- raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
91
+ raise ::Appium::Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
92
92
  end
93
93
  end
94
94
 
@@ -103,10 +103,10 @@ module Appium
103
103
  def save_viewport_screenshot(png_path)
104
104
  extension = File.extname(png_path).downcase
105
105
  if extension != '.png'
106
- ::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
106
+ ::Appium::Logger.warn 'name used for saved screenshot does not match file type. ' \
107
107
  'It should end with .png extension'
108
108
  end
109
- viewport_screenshot_encode64 = bridge.take_viewport_screenshot
109
+ viewport_screenshot_encode64 = bridge.viewport_screenshot
110
110
  File.open(png_path, 'wb') { |f| f << viewport_screenshot_encode64.unpack('m')[0] }
111
111
  end
112
112
  end