appium_lib_core 9.0.0 → 9.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccf2b5c0df2ae8489c0c9b3382d260f2464c20828b02484888c7f1c738a42084
4
- data.tar.gz: 6aa81ba96bd097f6075a947656533fd20476de3199855827d4278e71449b842e
3
+ metadata.gz: 8679d6bb72c4130e216ac363eaed0c49f13b6d8818db2cba0b44c8f5b9dcef7b
4
+ data.tar.gz: d226eeb911201d9afd12117bb73871afa95e4b0d7f3844f2df2e4efdb45563ed
5
5
  SHA512:
6
- metadata.gz: 7b7c967d705ffd0034af99c930ed6840e272a064cda6dd461710ac8990413b1ee7de7bbb577e9a3231113ec77c5007b737beb82811600c5d2061d21add41b129
7
- data.tar.gz: 24405ae6731acb21cc504d0867410523a63943244d718700b0c24504bdf9cecae0ae54b7e5a647660cd8aec7e5bd9bd6391e160e1796246250e6dfecd78ca2ec
6
+ metadata.gz: 5ad279ca22ef8f33ad8634fbfcaffaac1f6b16a8904a90f45a39427ed060c444fec5e1130589cac30fd35cdff74df0626e9768e9f1a819f49db678ab6044d2d3
7
+ data.tar.gz: 2f6c31b0718f6155db25a647832d68d370c4dee839fe962f5b99bc6f4d082bdc0d96fdde807f5e89192f814815e998752ab9f2fb772f0a01d823425c7b90ad09
data/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@ Read `release_notes.md` for commit level details.
10
10
 
11
11
  ### Deprecations
12
12
 
13
+ ## [9.1.0] - 2024-05-18
14
+
15
+ ### Enhancements
16
+ - Require Selenium 4.21.0+
17
+ - Simplify internal code with Selenium 4.21.0. Now it requires selenium webdriver v4.21.0.
18
+
13
19
  ## [9.0.0] - 2024-05-14
14
20
 
15
21
  ### Deprecations
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_runtime_dependency 'selenium-webdriver', '~> 4.2'
25
+ spec.add_runtime_dependency 'selenium-webdriver', '~> 4.21'
26
26
  spec.add_runtime_dependency 'faye-websocket', '~> 0.11.0'
27
27
 
28
28
  spec.add_development_dependency 'rake', '~> 13.0'
@@ -15,6 +15,12 @@
15
15
  module Appium
16
16
  module Core
17
17
  class Base
18
+ class LocatorConverter
19
+ def convert(how, what)
20
+ [how, what]
21
+ end
22
+ end # LocatorConverter
23
+
18
24
  class Bridge < ::Selenium::WebDriver::Remote::Bridge
19
25
  include Device::DeviceLock
20
26
  include Device::Keyboard
@@ -31,6 +37,8 @@ module Appium
31
37
  include Device::ExecuteDriver
32
38
  include Device::Orientation
33
39
 
40
+ Bridge.locator_converter = LocatorConverter.new
41
+
34
42
  # Prefix for extra capability defined by W3C
35
43
  APPIUM_PREFIX = 'appium:'
36
44
 
@@ -153,6 +161,18 @@ module Appium
153
161
  public
154
162
 
155
163
  # command for Appium 2.0.
164
+
165
+ # Example:
166
+ # driver.add_command(name: :available_contexts, method: :get, url: 'session/:session_id/contexts') do
167
+ # execute(:available_contexts, {}) || []
168
+ # end
169
+ # Then,
170
+ # driver.available_contexts #=> ["NATIVE_APP"]
171
+
172
+ # def add_command(method:, url:, name:, &block)
173
+ # Bridge.add_command name, method, url, &block
174
+ # end
175
+
156
176
  def add_command(method:, url:, name:, &block)
157
177
  ::Appium::Logger.info "Overriding the method '#{name}' for '#{url}'" if @available_commands.key? name
158
178
 
@@ -162,7 +182,7 @@ module Appium
162
182
  end
163
183
 
164
184
  def commands(command)
165
- @available_commands[command]
185
+ @available_commands[command] || Bridge.extra_commands[command]
166
186
  end
167
187
 
168
188
  def status
@@ -216,52 +236,8 @@ module Appium
216
236
  end
217
237
 
218
238
  # For Appium
219
- # override
220
- def active_element
221
- ::Appium::Core::Element.new self, element_id_from(execute(:get_active_element))
222
- end
223
239
  alias switch_to_active_element active_element
224
240
 
225
- # For Appium
226
- # override
227
- def find_element_by(how, what, parent_ref = [])
228
- how, what = convert_locator(how, what)
229
-
230
- return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative'
231
-
232
- parent_type, parent_id = parent_ref
233
- id = case parent_type
234
- when :element
235
- execute :find_child_element, { id: parent_id }, { using: how, value: what.to_s }
236
- when :shadow_root
237
- execute :find_shadow_child_element, { id: parent_id }, { using: how, value: what.to_s }
238
- else
239
- execute :find_element, {}, { using: how, value: what.to_s }
240
- end
241
-
242
- ::Appium::Core::Element.new self, element_id_from(id)
243
- end
244
-
245
- # For Appium
246
- # override
247
- def find_elements_by(how, what, parent_ref = [])
248
- how, what = convert_locator(how, what)
249
-
250
- return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative'
251
-
252
- parent_type, parent_id = parent_ref
253
- ids = case parent_type
254
- when :element
255
- execute :find_child_elements, { id: parent_id }, { using: how, value: what.to_s }
256
- when :shadow_root
257
- execute :find_shadow_child_elements, { id: parent_id }, { using: how, value: what.to_s }
258
- else
259
- execute :find_elements, {}, { using: how, value: what.to_s }
260
- end
261
-
262
- ids.map { |id| ::Appium::Core::Element.new self, element_id_from(id) }
263
- end
264
-
265
241
  # For Appium
266
242
  # @param [Hash] id The id which can get as a response from server
267
243
  # @return [::Appium::Core::Element]
@@ -370,36 +346,6 @@ module Appium
370
346
  arg
371
347
  end
372
348
  end
373
-
374
- def element_id_from(id)
375
- id['ELEMENT'] || id['element-6066-11e4-a52e-4f735466cecf']
376
- end
377
-
378
- # Don't convert locators for Appium in native context
379
- def convert_locator(how, what)
380
- # case how
381
- # when 'class name'
382
- # how = 'css selector'
383
- # what = ".#{escape_css(what)}"
384
- # when 'id'
385
- # how = 'css selector'
386
- # what = "##{escape_css(what)}"
387
- # when 'name'
388
- # how = 'css selector'
389
- # what = "*[name='#{escape_css(what)}']"
390
- # when 'tag name'
391
- # how = 'css selector'
392
- # end
393
- #
394
- # if what.is_a?(Hash)
395
- # what = what.each_with_object({}) do |(h, w), hash|
396
- # h, w = convert_locator(h.to_s, w)
397
- # hash[h] = w
398
- # end
399
- # end
400
-
401
- [how, what]
402
- end
403
349
  end # class Bridge
404
350
  end # class Base
405
351
  end # module Core
@@ -32,7 +32,6 @@ module Appium
32
32
  include ::Selenium::WebDriver::DriverExtensions::HasWebStorage
33
33
 
34
34
  include ::Appium::Core::Base::Rotatable
35
- include ::Appium::Core::Base::SearchContext
36
35
  include ::Appium::Core::Base::TakesScreenshot
37
36
  include ::Appium::Core::Base::HasRemoteStatus
38
37
  include ::Appium::Core::Base::HasLocation
@@ -40,6 +39,8 @@ module Appium
40
39
 
41
40
  include ::Appium::Core::Waitable
42
41
 
42
+ ::Selenium::WebDriver::SearchContext.extra_finders = APPIUM_EXTRA_FINDERS
43
+
43
44
  # Private API.
44
45
  # Do not use this for general use. Used by flutter driver to get bridge for creating a new element
45
46
  attr_reader :bridge
@@ -57,6 +58,7 @@ module Appium
57
58
  @bidi = nil
58
59
 
59
60
  # in the selenium webdriver as well
61
+ ::Selenium::WebDriver::Remote::Bridge.element_class = ::Appium::Core::Element
60
62
  bridge ||= create_bridge(**opts)
61
63
  add_extensions(bridge.browser)
62
64
  @bridge = listener ? ::Appium::Support::EventFiringBridge.new(bridge, listener, **original_opts) : bridge
@@ -1023,8 +1025,8 @@ module Appium
1023
1025
  # ele = @driver.convert_to_element(response) #=> ::Appium::Core::Element
1024
1026
  # ele.rect #=> Can get the rect of the element
1025
1027
  #
1026
- def convert_to_element(id)
1027
- @bridge.convert_to_element id
1028
+ def convert_to_element(response_id)
1029
+ @bridge.convert_to_element response_id
1028
1030
  end
1029
1031
  end # class Driver
1030
1032
  end # class Base
@@ -31,6 +31,9 @@ module Appium
31
31
  class Default < ::Selenium::WebDriver::Remote::Http::Default
32
32
  attr_reader :additional_headers
33
33
 
34
+ ::Selenium::WebDriver::Remote::Http::Common.user_agent = \
35
+ "appium/ruby_lib_core/#{VERSION} (#{::Selenium::WebDriver::Remote::Http::Common.user_agent})"
36
+
34
37
  # override
35
38
  def initialize(open_timeout: nil, read_timeout: nil)
36
39
  @open_timeout = open_timeout
@@ -39,6 +42,17 @@ module Appium
39
42
  super
40
43
  end
41
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
54
+ end
55
+
42
56
  # Update <code>server_url</code> provided when ruby_lib _core created a default http client.
43
57
  # Set <code>@http</code> as nil to re-create http client for the <code>server_url</code>
44
58
  #
@@ -59,13 +73,6 @@ module Appium
59
73
  @server_url = URI.parse "#{scheme}://#{host}:#{port}#{path}"
60
74
  end
61
75
 
62
- def request(verb, url, headers, payload, redirects = 0)
63
- headers['User-Agent'] = "appium/ruby_lib_core/#{VERSION} (#{headers['User-Agent']})"
64
- headers = headers.merge @additional_headers unless @additional_headers.empty?
65
-
66
- super(verb, url, headers, payload, redirects)
67
- end
68
-
69
76
  private
70
77
 
71
78
  def validate_url_param(scheme, host, port, path)
@@ -12,172 +12,102 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- module Appium
16
- module Core
17
- class Base
18
- module SearchContext
19
- # referenced: ::Selenium::WebDriver::SearchContext
20
-
21
- FINDERS = ::Selenium::WebDriver::SearchContext::FINDERS.merge(
22
- accessibility_id: 'accessibility id',
23
- image: '-image',
24
- custom: '-custom',
25
- # Android
26
- uiautomator: '-android uiautomator', # Unavailable in Espresso
27
- viewtag: '-android viewtag', # Available in Espresso
28
- data_matcher: '-android datamatcher', # Available in Espresso
29
- view_matcher: '-android viewmatcher', # Available in Espresso
30
- # iOS
31
- predicate: '-ios predicate string',
32
- class_chain: '-ios class chain'
33
- )
34
-
35
- # rubocop:disable Layout/LineLength
36
- #
37
- # Find the first element matching the given arguments
38
- #
39
- # - Android can find with uiautomator like a {http://developer.android.com/tools/help/uiautomator/UiSelector.html UISelector}.
40
- # - iOS can find with a {https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930 UIAutomation command}.
41
- # - iOS, only for XCUITest(WebDriverAgent), can find with a {https://github.com/facebook/WebDriverAgent/wiki/Queries class chain}
42
- #
43
- # == Find with image
44
- # Return an element if current view has a partial image. The logic depends on template matching by OpenCV.
45
- # {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
46
- #
47
- # You can handle settings for the comparision following {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 here}
48
- #
49
- # == Espresso viewmatcher and datamatcher
50
- # Espresso has {https://developer.android.com/training/testing/espresso/basics _onView_ matcher}
51
- # and {https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf _onData_ matcher} for more reference
52
- # that allows you to target adapters instead of Views. This method find methods based on reflections
53
- #
54
- # This is a selector strategy that allows users to pass a selector of the form:
55
- #
56
- # <code>{ name: '<name>', args: ['arg1', 'arg2', '...'], class: '<optional class>' }</code>
57
- #
58
- # - _name_: The name of a method to invoke. The method must return
59
- # a Hamcrest {http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html Matcher}
60
- # - _args_: The args provided to the method
61
- # - _class_: The class name that the method is part of (defaults to <code>org.hamcrest.Matchers</code>).
62
- # Can be fully qualified, or simple, and simple defaults to <code>androidx.test.espresso.matcher</code> package
63
- # (e.g.: <code>class=CursorMatchers</code> fully qualified is <code>class=androidx.test.espresso.matcher.CursorMatchers</code>
64
- #
65
- # See example how to send viewmatcher and datamatcher in Ruby client
66
- #
67
- #
68
- # @overload find_element(how, what)
69
- # @param [Symbol, String] how The method to find the element by
70
- # @param [String] what The locator to use
71
- #
72
- # @overload find_element(opts)
73
- # @param [Hash] opts Find options
74
- # @option opts [Symbol] :how Key named after the method to find the element by, containing the locator
75
- # @return [Element]
76
- # @raise [Error::NoSuchElementError] if the element doesn't exist
77
- #
78
- # @example Find element with each keys
79
- #
80
- # # with accessibility id. All platforms.
81
- # @driver.find_elements :accessibility_id, 'Animation'
82
- # @driver.find_elements :accessibility_id, 'Animation'
83
- #
84
- # # with base64 encoded template image. All platforms.
85
- # @driver.find_elements :image, Base64.strict_encode64(File.read(file_path))
86
- #
87
- # # For Android
88
- # ## With uiautomator
89
- # @driver.find_elements :uiautomator, 'new UiSelector().clickable(true)'
90
- # ## With viewtag, but only for Espresso
91
- # ## 'setTag'/'getTag' in https://developer.android.com/reference/android/view/View
92
- # @driver.find_elements :viewtag, 'new UiSelector().clickable(true)'
93
- # # With data_matcher. The argument should be JSON format.
94
- # @driver.find_elements :data_matcher, { name: 'hasEntry', args: %w(title Animation) }.to_json
95
- #
96
- # # For iOS
97
- # ## With :predicate
98
- # @driver.find_elements :predicate, "isWDVisible == 1"
99
- # @driver.find_elements :predicate, 'wdName == "Buttons"'
100
- # @driver.find_elements :predicate, 'wdValue == "SearchBar" AND isWDDivisible == 1'
101
- #
102
- # ## With Class Chain
103
- # ### select the third child button of the first child window element
104
- # @driver.find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]'
105
- # ### select all the children windows
106
- # @driver.find_elements :class_chain, 'XCUIElementTypeWindow'
107
- # ### select the second last child of the second child window
108
- # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]'
109
- # ### matching predicate. <code>'</code> is the mark.
110
- # @driver.find_elements :class_chain, 'XCUIElementTypeWindow['visible = 1]['name = "bla"']'
111
- # ### containing predicate. '$' is the mark.
112
- # ### Require appium-xcuitest-driver 2.54.0+. PR: https://github.com/facebook/WebDriverAgent/pull/707/files
113
- # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[$name = \"bla$$$bla\"$]'
114
- # e = find_element :class_chain, "**/XCUIElementTypeWindow[$name == 'Buttons'$]"
115
- # e.tag_name #=> "XCUIElementTypeWindow"
116
- # e = find_element :class_chain, "**/XCUIElementTypeStaticText[$name == 'Buttons'$]"
117
- # e.tag_name #=> "XCUIElementTypeStaticText"
118
- #
119
- # rubocop:enable Layout/LineLength
120
- def find_element(*args)
121
- how, what = extract_args(args)
122
- by = _set_by_from_finders(how)
123
- begin
124
- bridge.find_element_by by, what.to_s, ref
125
- rescue Selenium::WebDriver::Error::TimeoutError
126
- raise Selenium::WebDriver::Error::NoSuchElementError
127
- end
128
- end
129
-
130
- #
131
- # Find all elements matching the given arguments
132
- #
133
- # @return [Array<Selenium::WebDriver::Element>]
134
- #
135
- # @see SearchContext#find_elements
136
- #
137
- def find_elements(*args)
138
- how, what = extract_args(args)
139
- by = _set_by_from_finders(how)
140
- begin
141
- bridge.find_elements_by by, what.to_s, ref
142
- rescue Selenium::WebDriver::Error::TimeoutError
143
- []
144
- end
145
- end
146
-
147
- private
148
-
149
- def _set_by_from_finders(how)
150
- by = FINDERS[how.to_sym]
151
- unless by
152
- raise ::Appium::Core::Error::ArgumentError,
153
- "cannot find element by #{how.inspect}. Available finders are #{FINDERS.keys}."
154
- end
155
-
156
- by
157
- end
158
-
159
- def extract_args(args)
160
- case args.size
161
- when 2
162
- args
163
- when 1
164
- arg = args.first
165
-
166
- unless arg.respond_to?(:shift)
167
- raise ::Appium::Core::Error::ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
168
- end
169
-
170
- # this will be a single-entry hash, so use #shift over #first or #[]
171
- arr = arg.dup.shift
172
-
173
- raise ::Appium::Core::Error::ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
15
+ # rubocop:disable Layout/LineLength
16
+ #
17
+ # Find the first element matching the given arguments
18
+ #
19
+ # - Android can find with uiautomator like a {http://developer.android.com/tools/help/uiautomator/UiSelector.html UISelector}.
20
+ # - iOS can find with a {https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930 UIAutomation command}.
21
+ # - iOS, only for XCUITest(WebDriverAgent), can find with a {https://github.com/facebook/WebDriverAgent/wiki/Queries class chain}
22
+ #
23
+ # == Find with image
24
+ # Return an element if current view has a partial image. The logic depends on template matching by OpenCV.
25
+ # {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison}
26
+ #
27
+ # You can handle settings for the comparision following {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 here}
28
+ #
29
+ # == Espresso viewmatcher and datamatcher
30
+ # Espresso has {https://developer.android.com/training/testing/espresso/basics _onView_ matcher}
31
+ # and {https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf _onData_ matcher} for more reference
32
+ # that allows you to target adapters instead of Views. This method find methods based on reflections
33
+ #
34
+ # This is a selector strategy that allows users to pass a selector of the form:
35
+ #
36
+ # <code>{ name: '<name>', args: ['arg1', 'arg2', '...'], class: '<optional class>' }</code>
37
+ #
38
+ # - _name_: The name of a method to invoke. The method must return
39
+ # a Hamcrest {http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html Matcher}
40
+ # - _args_: The args provided to the method
41
+ # - _class_: The class name that the method is part of (defaults to <code>org.hamcrest.Matchers</code>).
42
+ # Can be fully qualified, or simple, and simple defaults to <code>androidx.test.espresso.matcher</code> package
43
+ # (e.g.: <code>class=CursorMatchers</code> fully qualified is <code>class=androidx.test.espresso.matcher.CursorMatchers</code>
44
+ #
45
+ # See example how to send viewmatcher and datamatcher in Ruby client
46
+ #
47
+ #
48
+ # @overload find_element(how, what)
49
+ # @param [Symbol, String] how The method to find the element by
50
+ # @param [String] what The locator to use
51
+ #
52
+ # @overload find_element(opts)
53
+ # @param [Hash] opts Find options
54
+ # @option opts [Symbol] :how Key named after the method to find the element by, containing the locator
55
+ # @return [Element]
56
+ # @raise [Error::NoSuchElementError] if the element doesn't exist
57
+ #
58
+ # @example Find element with each keys
59
+ #
60
+ # # with accessibility id. All platforms.
61
+ # @driver.find_elements :accessibility_id, 'Animation'
62
+ # @driver.find_elements :accessibility_id, 'Animation'
63
+ #
64
+ # # with base64 encoded template image. All platforms.
65
+ # @driver.find_elements :image, Base64.strict_encode64(File.read(file_path))
66
+ #
67
+ # # For Android
68
+ # ## With uiautomator
69
+ # @driver.find_elements :uiautomator, 'new UiSelector().clickable(true)'
70
+ # ## With viewtag, but only for Espresso
71
+ # ## 'setTag'/'getTag' in https://developer.android.com/reference/android/view/View
72
+ # @driver.find_elements :viewtag, 'new UiSelector().clickable(true)'
73
+ # # With data_matcher. The argument should be JSON format.
74
+ # @driver.find_elements :data_matcher, { name: 'hasEntry', args: %w(title Animation) }.to_json
75
+ #
76
+ # # For iOS
77
+ # ## With :predicate
78
+ # @driver.find_elements :predicate, "isWDVisible == 1"
79
+ # @driver.find_elements :predicate, 'wdName == "Buttons"'
80
+ # @driver.find_elements :predicate, 'wdValue == "SearchBar" AND isWDDivisible == 1'
81
+ #
82
+ # ## With Class Chain
83
+ # ### select the third child button of the first child window element
84
+ # @driver.find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]'
85
+ # ### select all the children windows
86
+ # @driver.find_elements :class_chain, 'XCUIElementTypeWindow'
87
+ # ### select the second last child of the second child window
88
+ # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]'
89
+ # ### matching predicate. <code>'</code> is the mark.
90
+ # @driver.find_elements :class_chain, 'XCUIElementTypeWindow['visible = 1]['name = "bla"']'
91
+ # ### containing predicate. '$' is the mark.
92
+ # ### Require appium-xcuitest-driver 2.54.0+. PR: https://github.com/facebook/WebDriverAgent/pull/707/files
93
+ # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[$name = \"bla$$$bla\"$]'
94
+ # e = find_element :class_chain, "**/XCUIElementTypeWindow[$name == 'Buttons'$]"
95
+ # e.tag_name #=> "XCUIElementTypeWindow"
96
+ # e = find_element :class_chain, "**/XCUIElementTypeStaticText[$name == 'Buttons'$]"
97
+ # e.tag_name #=> "XCUIElementTypeStaticText"
98
+ #
99
+ # rubocop:enable Layout/LineLength
174
100
 
175
- arr
176
- else
177
- raise ::Appium::Core::Error::ArgumentError, "wrong number of arguments (#{args.size} for 2)"
178
- end
179
- end
180
- end # module SearchContext
181
- end # class Base
182
- end # module Core
183
- end # module Appium
101
+ APPIUM_EXTRA_FINDERS = {
102
+ accessibility_id: 'accessibility id',
103
+ image: '-image',
104
+ custom: '-custom',
105
+ # Android
106
+ uiautomator: '-android uiautomator', # Unavailable in Espresso
107
+ viewtag: '-android viewtag', # Available in Espresso
108
+ data_matcher: '-android datamatcher', # Available in Espresso
109
+ view_matcher: '-android viewmatcher', # Available in Espresso
110
+ # iOS
111
+ predicate: '-ios predicate string',
112
+ class_chain: '-ios class chain'
113
+ }.freeze
@@ -402,7 +402,7 @@ module Appium
402
402
 
403
403
  if @enable_idempotency_header
404
404
  if @http_client.instance_variable_defined? :@additional_headers
405
- @http_client.additional_headers[Appium::Core::Base::Http::RequestHeaders::KEYS[:idempotency]] = SecureRandom.uuid
405
+ @http_client.set_additional_header Appium::Core::Base::Http::RequestHeaders::KEYS[:idempotency], SecureRandom.uuid
406
406
  else
407
407
  ::Appium::Logger.warn 'No additional_headers attribute in this http client instance'
408
408
  end
@@ -426,7 +426,7 @@ module Appium
426
426
 
427
427
  if @http_client.instance_variable_defined? :@additional_headers
428
428
  # We only need the key for a new session request. Should remove it for other following commands.
429
- @http_client.additional_headers.delete Appium::Core::Base::Http::RequestHeaders::KEYS[:idempotency]
429
+ @http_client.delete_additional_header Appium::Core::Base::Http::RequestHeaders::KEYS[:idempotency]
430
430
  end
431
431
 
432
432
  # TODO: this method can be removed after releasing Appium 2.0, and after a while
@@ -17,9 +17,10 @@ module Appium
17
17
  # Implement useful features for element.
18
18
  # Patch for Selenium Webdriver.
19
19
  class Element < ::Selenium::WebDriver::Element
20
- include ::Appium::Core::Base::SearchContext
21
20
  include ::Appium::Core::Base::TakesScreenshot
22
21
 
22
+ ::Selenium::WebDriver::SearchContext.extra_finders = APPIUM_EXTRA_FINDERS
23
+
23
24
  # Retuns the element id.
24
25
  #
25
26
  # @return [String]
@@ -14,7 +14,7 @@
14
14
 
15
15
  module Appium
16
16
  module Core
17
- VERSION = '9.0.0' unless defined? ::Appium::Core::VERSION
18
- DATE = '2024-05-14' unless defined? ::Appium::Core::DATE
17
+ VERSION = '9.1.0' unless defined? ::Appium::Core::VERSION
18
+ DATE = '2024-05-18' unless defined? ::Appium::Core::DATE
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_lib_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.0.0
4
+ version: 9.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuaki MATSUO
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-14 00:00:00.000000000 Z
11
+ date: 2024-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '4.21'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '4.2'
26
+ version: '4.21'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: faye-websocket
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -274,7 +274,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
274
274
  - !ruby/object:Gem::Version
275
275
  version: '0'
276
276
  requirements: []
277
- rubygems_version: 3.4.10
277
+ rubygems_version: 3.5.9
278
278
  signing_key:
279
279
  specification_version: 4
280
280
  summary: Minimal Ruby library for Appium.