appium_lib_core 13.1.3 → 13.2.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +25 -0
- data/lib/appium_lib_core/common/base/bridge.rb +7 -0
- data/lib/appium_lib_core/driver.rb +1 -1
- data/lib/appium_lib_core/element.rb +98 -0
- data/lib/appium_lib_core/support/event_firing_bridge.rb +2 -2
- data/lib/appium_lib_core/version.rb +2 -2
- data/sig/gems/selenium/common/element.rbs +2 -0
- data/sig/lib/appium_lib_core/common/base/bridge.rbs +2 -0
- data/sig/lib/appium_lib_core/driver.rbs +12 -0
- data/sig/lib/appium_lib_core/element.rbs +29 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f58df4e5db1afd7bdaf68fdcb87493c51d2c0807bbcaa91b031c15bcefdc509
|
|
4
|
+
data.tar.gz: c597388ecf32f065053c5098f52ddf91cad376af02d9996518d31c1962d41c76
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f8afcd5b9d81aae9e7ea0ca51d5a98e184534b906793a358823956512a39e32caa1c24983c2ded9ba1ecccb2e16f6971974bec0f5541887a0bac0f25225be24
|
|
7
|
+
data.tar.gz: f82582b27f5520d4992565cac86a86e2b1b8d465f30f8867646e090e2f4588786e5bb869bf83cc1d7df28710e3c03eb59a1cb6a8a41b99998d63b9600e38584d
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
New entries are generated by Release Please. Historical commit-level details through 13.1.0 remain in `release_notes.md`.
|
|
4
4
|
|
|
5
|
+
## [13.2.0](https://github.com/appium/ruby_lib_core/compare/v13.1.4...v13.2.0) (2026-10-26)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* Implement Cached Element for shouldUseCompactResponses and elementResponseAttributes ([#727](https://github.com/appium/ruby_lib_core/issues/727)) ([a0b22c5](https://github.com/appium/ruby_lib_core/commit/a0b22c5d8d757b787b44ba0468e6a216a7c46725))
|
|
11
|
+
|
|
12
|
+
## [13.1.4](https://github.com/appium/ruby_lib_core/compare/v13.1.3...v13.1.4) (2026-10-03)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* add missing RBS for direct connect DNS constants ([#718](https://github.com/appium/ruby_lib_core/issues/718)) ([f288cf2](https://github.com/appium/ruby_lib_core/commit/f288cf23de843bef7af97562d37d01a356ee0a3e))
|
|
18
|
+
|
|
5
19
|
## [13.1.3](https://github.com/appium/ruby_lib_core/compare/v13.1.2...v13.1.3) (2026-09-13)
|
|
6
20
|
|
|
7
21
|
|
data/README.md
CHANGED
|
@@ -151,6 +151,31 @@ assert attached_driver.session_id == @driver.session_id
|
|
|
151
151
|
attached_driver.page_source
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
+
### Element response attributes
|
|
155
|
+
|
|
156
|
+
When the server is configured with `shouldUseCompactResponses: false` and
|
|
157
|
+
`elementResponseAttributes`, returned attributes are available through `element.cached`:
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
element = @driver.find_element(:accessibility_id, 'some accessibility')
|
|
161
|
+
element.cached.text # text returned with this element
|
|
162
|
+
element.cached['content-desc'] # also accepts attribute/content-desc
|
|
163
|
+
element.cached.attributes # returned attributes, excluding element IDs
|
|
164
|
+
element.text # fetches current text; does not update cached
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`cached` only reads the response snapshot. It cannot find elements or send commands.
|
|
168
|
+
Standard boolean fields (`enabled`, `displayed`, `selected`) normalize `"true"` and
|
|
169
|
+
`"false"` to booleans. `cached.rect`, `cached.location`, and `cached.size` return
|
|
170
|
+
Selenium Rectangle, Point, and Dimension objects; `cached.tag_name` reads `name`.
|
|
171
|
+
These conversions also apply to `cached[name]`. Explicit `cached['attribute/...']`
|
|
172
|
+
lookups and custom attributes retain their server types. `cached.attributes`
|
|
173
|
+
exposes the original server values.
|
|
174
|
+
Use `cached[name]` for optional attributes; it returns `nil` when absent. Dynamic
|
|
175
|
+
methods such as `cached.text` are available only for attributes in the response.
|
|
176
|
+
Standard accessors such as `cached.enabled?` and `cached.rect` return `nil` when
|
|
177
|
+
their data is absent.
|
|
178
|
+
|
|
154
179
|
### Capabilities
|
|
155
180
|
|
|
156
181
|
Read [Appium/Core/Driver](https://rubydoc.info/github/appium/ruby_lib_core/Appium/Core/Driver) to catch up with available capabilities.
|
|
@@ -148,6 +148,13 @@ module Appium
|
|
|
148
148
|
|
|
149
149
|
private
|
|
150
150
|
|
|
151
|
+
# Preserve the response until Element initialization, including for script results.
|
|
152
|
+
# Selenium calls this immediately before constructing an element. Keep nil for
|
|
153
|
+
# non-element hashes so ordinary script results and shadow roots stay intact.
|
|
154
|
+
def element_id_from(response)
|
|
155
|
+
response if super
|
|
156
|
+
end
|
|
157
|
+
|
|
151
158
|
def selenium_bridge_accepts_url?
|
|
152
159
|
::Selenium::WebDriver::Remote::Bridge.instance_method(:initialize).parameters.any? do |_, name|
|
|
153
160
|
name == :url
|
|
@@ -134,7 +134,7 @@ module Appium
|
|
|
134
134
|
return [normalized_host] if ip_literal?(normalized_host)
|
|
135
135
|
|
|
136
136
|
Timeout.timeout(DNS_RESOLVE_TIMEOUT_SECONDS) do
|
|
137
|
-
Socket.getaddrinfo(normalized_host, nil).map { |entry| entry[3] }.uniq
|
|
137
|
+
Socket.getaddrinfo(normalized_host, nil).map { |entry| entry[3].to_s }.uniq
|
|
138
138
|
end
|
|
139
139
|
rescue Timeout::Error
|
|
140
140
|
::Appium::Logger.warn("DNS resolution for '#{host}' timed out after #{DNS_RESOLVE_TIMEOUT_SECONDS}s")
|
|
@@ -17,6 +17,86 @@ module Appium
|
|
|
17
17
|
# Implement useful features for element.
|
|
18
18
|
# Patch for Selenium Webdriver.
|
|
19
19
|
class Element < ::Selenium::WebDriver::Element
|
|
20
|
+
# Attributes returned with an element response. This object has no bridge:
|
|
21
|
+
# reading it never sends a command or refreshes the returned values.
|
|
22
|
+
class Cache
|
|
23
|
+
attr_reader :attributes
|
|
24
|
+
|
|
25
|
+
def initialize(attributes = {})
|
|
26
|
+
@attributes = attributes.dup.freeze
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Normalize standard response fields; arbitrary attribute/... values stay raw.
|
|
30
|
+
# Missing attributes return nil. The original values remain in attributes.
|
|
31
|
+
def attribute(name)
|
|
32
|
+
key = attribute_key(name)
|
|
33
|
+
value = @attributes[key]
|
|
34
|
+
case name.to_s
|
|
35
|
+
when 'enabled', 'displayed', 'selected'
|
|
36
|
+
return true if value == 'true'
|
|
37
|
+
return false if value == 'false'
|
|
38
|
+
when 'rect'
|
|
39
|
+
return ::Selenium::WebDriver::Rectangle.new(value['x'], value['y'], value['width'], value['height']) if value.is_a?(Hash)
|
|
40
|
+
end
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
alias [] attribute
|
|
45
|
+
|
|
46
|
+
def enabled?
|
|
47
|
+
attribute('enabled')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
alias enabled enabled?
|
|
51
|
+
|
|
52
|
+
def displayed?
|
|
53
|
+
attribute('displayed')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
alias displayed displayed?
|
|
57
|
+
|
|
58
|
+
def selected?
|
|
59
|
+
attribute('selected')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
alias selected selected?
|
|
63
|
+
|
|
64
|
+
def rect
|
|
65
|
+
attribute('rect')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def location
|
|
69
|
+
rectangle = rect
|
|
70
|
+
::Selenium::WebDriver::Point.new(rectangle.x, rectangle.y) if rectangle
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def size
|
|
74
|
+
rectangle = rect
|
|
75
|
+
::Selenium::WebDriver::Dimension.new(rectangle.width, rectangle.height) if rectangle
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def tag_name
|
|
79
|
+
attribute('name')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def method_missing(name, *args, &block)
|
|
83
|
+
return super unless args.empty? && block.nil? && respond_to_missing?(name)
|
|
84
|
+
|
|
85
|
+
attribute(name.to_s.delete_suffix('?').tr('_', '-'))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def respond_to_missing?(name, include_private = false)
|
|
89
|
+
@attributes.key?(attribute_key(name.to_s.delete_suffix('?').tr('_', '-'))) || super
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def attribute_key(name)
|
|
95
|
+
key = name.to_s
|
|
96
|
+
@attributes.key?("attribute/#{key}") ? "attribute/#{key}" : key
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
20
100
|
include ::Appium::Core::Base::TakesScreenshot
|
|
21
101
|
|
|
22
102
|
# steep:ignore:start
|
|
@@ -32,6 +112,24 @@ module Appium
|
|
|
32
112
|
#
|
|
33
113
|
attr_reader :id
|
|
34
114
|
|
|
115
|
+
def initialize(bridge, id, cached = nil)
|
|
116
|
+
if id.is_a?(Hash)
|
|
117
|
+
# Preserve any extra attributes included in the element response.
|
|
118
|
+
cached = Cache.new(id.except('ELEMENT', ELEMENT_KEY))
|
|
119
|
+
id = id['ELEMENT'] || id[ELEMENT_KEY]
|
|
120
|
+
end
|
|
121
|
+
super(bridge, id)
|
|
122
|
+
@cached = cached
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Snapshot from elementResponseAttributes with shouldUseCompactResponses=false.
|
|
126
|
+
# Normal element calls still query the server and do not update this snapshot.
|
|
127
|
+
# Standard fields use Element API types; cached.attributes holds server values.
|
|
128
|
+
# @return [Appium::Core::Element::Cache]
|
|
129
|
+
def cached
|
|
130
|
+
@cached ||= Cache.new
|
|
131
|
+
end
|
|
132
|
+
|
|
35
133
|
# Returns the value of attributes like below. Read each platform to know more details.
|
|
36
134
|
#
|
|
37
135
|
# uiautomator2: https://github.com/appium/appium-uiautomator2-server/blob/203cc7e57ce477f3cff5d95b135d1b3450a6033a/app/src/main/java/io/appium/uiautomator2/utils/Attribute.java#L19
|
|
@@ -29,7 +29,7 @@ module Appium
|
|
|
29
29
|
@delegate.find_element_by how, what, parent
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
::Appium::Core::Element.new self, e.ref.last
|
|
32
|
+
::Appium::Core::Element.new self, e.ref.last, e.cached
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def find_elements_by(how, what, parent = nil)
|
|
@@ -37,7 +37,7 @@ module Appium
|
|
|
37
37
|
@delegate.find_elements_by(how, what, parent)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
es.map { |e| ::Appium::Core::Element.new self, e.ref.last }
|
|
40
|
+
es.map { |e| ::Appium::Core::Element.new self, e.ref.last, e.cached }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
private
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
module Appium
|
|
16
16
|
module Core
|
|
17
|
-
VERSION = '13.
|
|
18
|
-
DATE = '2026-
|
|
17
|
+
VERSION = '13.2.0' unless defined? ::Appium::Core::VERSION
|
|
18
|
+
DATE = '2026-10-26' unless defined? ::Appium::Core::DATE # x-release-please-date
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -70,6 +70,18 @@ module Appium
|
|
|
70
70
|
|
|
71
71
|
W3C_KEYS: Hash[String | Symbol, String]
|
|
72
72
|
|
|
73
|
+
DNS_RESOLVE_TIMEOUT_SECONDS: Integer
|
|
74
|
+
|
|
75
|
+
LOOPBACK_RANGES: Array[IPAddr]
|
|
76
|
+
|
|
77
|
+
LINK_LOCAL_RANGES: Array[IPAddr]
|
|
78
|
+
|
|
79
|
+
UNSPECIFIED_RANGES: Array[IPAddr]
|
|
80
|
+
|
|
81
|
+
MULTICAST_RANGES: Array[IPAddr]
|
|
82
|
+
|
|
83
|
+
DISALLOWED_RANGES: Array[IPAddr]
|
|
84
|
+
|
|
73
85
|
attr_reader protocol: String
|
|
74
86
|
|
|
75
87
|
attr_reader host: String
|
|
@@ -2,9 +2,37 @@ module Appium
|
|
|
2
2
|
module Core
|
|
3
3
|
# Element class inheriting from Selenium::WebDriver::Element
|
|
4
4
|
class Element < ::Selenium::WebDriver::Element
|
|
5
|
+
class Cache
|
|
6
|
+
attr_reader attributes: Hash[String, untyped]
|
|
7
|
+
|
|
8
|
+
def initialize: (?Hash[String, untyped] attributes) -> void
|
|
9
|
+
def attribute: (String | Symbol name) -> untyped
|
|
10
|
+
alias [] attribute
|
|
11
|
+
def enabled?: () -> bool?
|
|
12
|
+
alias enabled enabled?
|
|
13
|
+
def displayed?: () -> bool?
|
|
14
|
+
alias displayed displayed?
|
|
15
|
+
def selected?: () -> bool?
|
|
16
|
+
alias selected selected?
|
|
17
|
+
def rect: () -> untyped
|
|
18
|
+
def location: () -> untyped
|
|
19
|
+
def size: () -> untyped
|
|
20
|
+
def tag_name: () -> String?
|
|
21
|
+
def method_missing: (Symbol name, *untyped args) ?{ (?) -> untyped } -> untyped
|
|
22
|
+
def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def attribute_key: (String | Symbol name) -> String
|
|
27
|
+
end
|
|
28
|
+
|
|
5
29
|
include ::Appium::Core::Base::TakesScreenshot
|
|
6
30
|
|
|
7
|
-
|
|
31
|
+
@cached: Cache?
|
|
32
|
+
|
|
33
|
+
def initialize: (untyped bridge, untyped id, ?Cache? cached) -> void
|
|
34
|
+
|
|
35
|
+
def cached: () -> Cache
|
|
8
36
|
|
|
9
37
|
attr_reader id: Array[untyped]
|
|
10
38
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appium_lib_core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 13.
|
|
4
|
+
version: 13.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kazuaki MATSUO
|
|
@@ -251,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
251
251
|
- !ruby/object:Gem::Version
|
|
252
252
|
version: '0'
|
|
253
253
|
requirements: []
|
|
254
|
-
rubygems_version: 4.0.
|
|
254
|
+
rubygems_version: 4.0.20
|
|
255
255
|
specification_version: 4
|
|
256
256
|
summary: Minimal Ruby library for Appium.
|
|
257
257
|
test_files: []
|