appium_lib_core 9.0.0 → 9.1.1
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 +4 -4
- data/CHANGELOG.md +12 -0
- data/appium_lib_core.gemspec +10 -10
- data/lib/appium_lib_core/common/base/bridge.rb +21 -94
- data/lib/appium_lib_core/common/base/driver.rb +5 -3
- data/lib/appium_lib_core/common/base/http_default.rb +14 -7
- data/lib/appium_lib_core/common/base/search_context.rb +98 -168
- data/lib/appium_lib_core/driver.rb +2 -2
- data/lib/appium_lib_core/element.rb +2 -1
- data/lib/appium_lib_core/version.rb +2 -2
- metadata +43 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66d04f7356959668f0eb58b68869126add5dc0e4abfdc79c2aedcb24e8e8dd6f
|
4
|
+
data.tar.gz: f49ba5759a02d29a88a2c470f65e5c30277660838fe4aadcc024db77092b6f0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbee76c3700eda2c8a4214644f9de866a8957e4d25d0aa20e10fffe245e1c3d7208863004c4c16d7e32b0bbf79d22a65cfca6999e5783361178e104000b7847a
|
7
|
+
data.tar.gz: 3c0fce31f001303602d99a1feec396e51061a2b57f1ce8155dad771d4167dadaf2ef263a579833eba4f7466fbe2ce8055776b0dbd4de3c7c8fb293465570dc43
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,18 @@ Read `release_notes.md` for commit level details.
|
|
10
10
|
|
11
11
|
### Deprecations
|
12
12
|
|
13
|
+
## [9.1.1] - 2024-05-19
|
14
|
+
|
15
|
+
### Enhancements
|
16
|
+
- Simplify internal code with Selenium 4.21.0 further.
|
17
|
+
|
18
|
+
|
19
|
+
## [9.1.0] - 2024-05-18
|
20
|
+
|
21
|
+
### Enhancements
|
22
|
+
- Require Selenium 4.21.0+
|
23
|
+
- Simplify internal code with Selenium 4.21.0. Now it requires selenium webdriver v4.21.0.
|
24
|
+
|
13
25
|
## [9.0.0] - 2024-05-14
|
14
26
|
|
15
27
|
### Deprecations
|
data/appium_lib_core.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'appium_lib_core/version'
|
5
4
|
|
@@ -11,8 +10,8 @@ Gem::Specification.new do |spec|
|
|
11
10
|
spec.authors = ['Kazuaki MATSUO']
|
12
11
|
spec.email = ['fly.49.89.over@gmail.com']
|
13
12
|
|
14
|
-
spec.summary =
|
15
|
-
spec.description =
|
13
|
+
spec.summary = 'Minimal Ruby library for Appium.'
|
14
|
+
spec.description = 'Minimal Ruby library for Appium.'
|
16
15
|
spec.homepage = 'https://github.com/appium/ruby_lib_core/'
|
17
16
|
spec.license = 'Apache-2.0'
|
18
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -22,16 +21,17 @@ Gem::Specification.new do |spec|
|
|
22
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
22
|
spec.require_paths = ['lib']
|
24
23
|
|
25
|
-
spec.add_runtime_dependency 'selenium-webdriver', '~> 4.2'
|
26
24
|
spec.add_runtime_dependency 'faye-websocket', '~> 0.11.0'
|
25
|
+
spec.add_runtime_dependency 'selenium-webdriver', '~> 4.21'
|
27
26
|
|
28
|
-
spec.add_development_dependency '
|
29
|
-
spec.add_development_dependency 'yard', '~> 0.9.11'
|
27
|
+
spec.add_development_dependency 'appium_thor', '~> 2.0'
|
30
28
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
31
29
|
spec.add_development_dependency 'minitest-reporters', '~> 1.1'
|
32
|
-
spec.add_development_dependency 'webmock', '~> 3.23.0'
|
33
|
-
spec.add_development_dependency 'rubocop', '1.63.5'
|
34
|
-
spec.add_development_dependency 'appium_thor', '~> 2.0'
|
35
30
|
spec.add_development_dependency 'parallel_tests'
|
31
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
32
|
+
spec.add_development_dependency 'rubocop', '1.63.5'
|
36
33
|
spec.add_development_dependency 'simplecov'
|
34
|
+
spec.add_development_dependency 'webmock', '~> 3.23.0'
|
35
|
+
spec.add_development_dependency 'yard', '~> 0.9.11'
|
36
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
37
37
|
end
|
@@ -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]
|
@@ -351,55 +327,6 @@ module Appium
|
|
351
327
|
def send_command(command_params)
|
352
328
|
execute :chrome_send_command, {}, command_params
|
353
329
|
end
|
354
|
-
|
355
|
-
private
|
356
|
-
|
357
|
-
def unwrap_script_result(arg)
|
358
|
-
case arg
|
359
|
-
when Array
|
360
|
-
arg.map { |e| unwrap_script_result(e) }
|
361
|
-
when Hash
|
362
|
-
element_id = element_id_from(arg)
|
363
|
-
return ::Appium::Core::Element.new(self, element_id) if element_id
|
364
|
-
|
365
|
-
shadow_root_id = shadow_root_id_from(arg)
|
366
|
-
return ::Selenium::WebDriver::Remote::ShadowRoot.new self, shadow_root_id if shadow_root_id
|
367
|
-
|
368
|
-
arg.each { |k, v| arg[k] = unwrap_script_result(v) }
|
369
|
-
else
|
370
|
-
arg
|
371
|
-
end
|
372
|
-
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
330
|
end # class Bridge
|
404
331
|
end # class Base
|
405
332
|
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(
|
1027
|
-
@bridge.convert_to_element
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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.
|
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.
|
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.
|
18
|
-
DATE = '2024-05-
|
17
|
+
VERSION = '9.1.1' unless defined? ::Appium::Core::VERSION
|
18
|
+
DATE = '2024-05-19' unless defined? ::Appium::Core::DATE
|
19
19
|
end
|
20
20
|
end
|
metadata
CHANGED
@@ -1,113 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appium_lib_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.
|
4
|
+
version: 9.1.1
|
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-
|
11
|
+
date: 2024-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: faye-websocket
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.11.0
|
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:
|
26
|
+
version: 0.11.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: selenium-webdriver
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '4.21'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '4.21'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: appium_thor
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0
|
61
|
+
version: '5.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0
|
68
|
+
version: '5.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
70
|
+
name: minitest-reporters
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '1.1'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '1.1'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: parallel_tests
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: '13.0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: '13.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rubocop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,47 +123,47 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 1.63.5
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: simplecov
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: webmock
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- - "
|
143
|
+
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 3.23.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- - "
|
150
|
+
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 3.23.0
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: yard
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- - "
|
157
|
+
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
159
|
+
version: 0.9.11
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- - "
|
164
|
+
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
166
|
+
version: 0.9.11
|
167
167
|
description: Minimal Ruby library for Appium.
|
168
168
|
email:
|
169
169
|
- fly.49.89.over@gmail.com
|
@@ -258,7 +258,8 @@ files:
|
|
258
258
|
homepage: https://github.com/appium/ruby_lib_core/
|
259
259
|
licenses:
|
260
260
|
- Apache-2.0
|
261
|
-
metadata:
|
261
|
+
metadata:
|
262
|
+
rubygems_mfa_required: 'true'
|
262
263
|
post_install_message:
|
263
264
|
rdoc_options: []
|
264
265
|
require_paths:
|
@@ -274,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
274
275
|
- !ruby/object:Gem::Version
|
275
276
|
version: '0'
|
276
277
|
requirements: []
|
277
|
-
rubygems_version: 3.
|
278
|
+
rubygems_version: 3.5.9
|
278
279
|
signing_key:
|
279
280
|
specification_version: 4
|
280
281
|
summary: Minimal Ruby library for Appium.
|