Class: Capybara::Simulated::Node
- Inherits:
-
Driver::Node
- Object
- Driver::Node
- Capybara::Simulated::Node
show all
- Includes:
- WhitespaceNormalizer
- Defined in:
- lib/capybara/simulated/node.rb
Constant Summary
WhitespaceNormalizer::BREAKING_SPACES, WhitespaceNormalizer::EMPTY_LINES, WhitespaceNormalizer::LEADING_SPACES, WhitespaceNormalizer::LEFT_TO_RIGHT_MARK, WhitespaceNormalizer::LINE_SEPERATOR, WhitespaceNormalizer::NON_BREAKING_SPACE, WhitespaceNormalizer::PARAGRAPH_SEPERATOR, WhitespaceNormalizer::REMOVED_CHARACTERS, WhitespaceNormalizer::RIGHT_TO_LEFT_MARK, WhitespaceNormalizer::SQUEEZED_SPACES, WhitespaceNormalizer::TRAILING_SPACES, WhitespaceNormalizer::ZERO_WIDTH_SPACE
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#==(other) ⇒ Object
Both handle_id and context_gen are part of identity: after a cross-page reload the new element can land on the same handle id (JS-side counter resets per ctx) but a different generation.
-
#[](name) ⇒ Object
-
#all_text ⇒ Object
Tick the virtual clock unconditionally on the text path.
-
#checked? ⇒ Boolean
-
#click(keys = [], **opts) ⇒ Object
-
#disabled? ⇒ Boolean
-
#double_click(keys = [], **opts) ⇒ Object
-
#drag_to(target_node, **opts) ⇒ Object
-
#drop(*args) ⇒ Object
-
#find_css(query) ⇒ Object
-
#find_xpath(query) ⇒ Object
-
#hover(**_opts) ⇒ Object
-
#initialize(driver, handle) ⇒ Node
constructor
-
#inner_html ⇒ Object
Convenience accessors mirroring real browser nodes — Discourse tests reach for .native.inner_html (e.g. reviewables XSS checks); without this method .native (= self) raised NoMethodError.
-
#obscured? ⇒ Boolean
-
#outer_html ⇒ Object
-
#path ⇒ Object
-
#readonly? ⇒ Boolean
-
#rect ⇒ Object
Capybara's standard rect API.
-
#right_click(keys = [], **opts) ⇒ Object
-
#scroll_by(dx, dy) ⇒ Object
Capybara's Element#scroll_to(:current, offset: [dx, dy]) calls this after the position handling above — a relative scroll from wherever the element is now.
-
#scroll_to(target = nil, arg = nil, coords = nil) ⇒ Object
Capybara's driver scroll_to contract (from Element#scroll_to): a target element + align symbol, a position symbol (:top/:bottom/:center), or an [x, y] coordinate pair.
-
#select_option ⇒ Object
-
#selected? ⇒ Boolean
-
#send_keys(*keys) ⇒ Object
-
#set(value, **_) ⇒ Object
-
#shadow_root ⇒ Object
-
#style(names = []) ⇒ Object
-
#submit(*_) ⇒ Object
-
#synchronize ⇒ Object
-
#tag_name ⇒ Object
-
#trigger(event) ⇒ Object
-
#unselect_option ⇒ Object
-
#value ⇒ Object
-
#visible? ⇒ Boolean
-
#visible_text ⇒ Object
#normalize_spacing, #normalize_visible_spacing
Constructor Details
#initialize(driver, handle) ⇒ Node
Returns a new instance of Node.
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# File 'lib/capybara/simulated/node.rb', line 12
def initialize(driver, handle)
super(driver, self)
@handle_id = handle
@browser = driver.current_browser
@initial_node = @browser.lookup_node(handle)
@context_gen = @browser.context_gen
@realm_id = @browser.current_realm_id
end
|
Instance Attribute Details
#context_gen ⇒ Object
Returns the value of attribute context_gen.
26
27
28
|
# File 'lib/capybara/simulated/node.rb', line 26
def context_gen
@context_gen
end
|
#handle_id ⇒ Object
Returns the value of attribute handle_id.
26
27
28
|
# File 'lib/capybara/simulated/node.rb', line 26
def handle_id
@handle_id
end
|
#realm_id ⇒ Object
Returns the value of attribute realm_id.
26
27
28
|
# File 'lib/capybara/simulated/node.rb', line 26
def realm_id
@realm_id
end
|
Instance Method Details
#==(other) ⇒ Object
Both handle_id and context_gen are part of identity: after a
cross-page reload the new element can land on the same handle
id (JS-side counter resets per ctx) but a different generation.
Capybara's synchronize uses old_base == @base to decide
whether reload made progress, so id-only equality would mark
a successful reload as a no-op and raise the original error.
241
242
243
244
245
246
|
# File 'lib/capybara/simulated/node.rb', line 241
def ==(other)
other.is_a?(Node) &&
other.handle_id == @handle_id &&
other.context_gen == @context_gen &&
other.realm_id == @realm_id
end
|
#[](name) ⇒ Object
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# File 'lib/capybara/simulated/node.rb', line 77
def [](name)
browser.tick_real_time if browser.timer_wait_elapsed? || browser.async_io_pending?
check_stale
browser.attr(handle_id, name.to_s)
end
|
#all_text ⇒ Object
Tick the virtual clock unconditionally on the text path. Unlike
Node#[] (attribute reads), the text readers are NOT preceded by
a find_css that ticks under the wall throttle: have_text /
assert_text polls .text directly against an already-found,
cached scope node, so the find loop short-circuits without
re-ticking. Gating these behind timer_wait_elapsed? therefore
stalls a pure text-poll loop's virtual clock and scheduled
setTimeouts never fire (smoke_spec virtual-clock contract).
They run ~once per poll-scope (not once per matched result like
the attribute filters the audit targeted), so they are not the
O(N) hot path and are safe to tick every call.
39
40
41
42
43
|
# File 'lib/capybara/simulated/node.rb', line 39
def all_text
browser.tick_real_time
check_stale
normalize_spacing(browser.all_text(handle_id))
end
|
#checked? ⇒ Boolean
219
|
# File 'lib/capybara/simulated/node.rb', line 219
def checked? = !!self['checked']
|
#click(keys = [], **opts) ⇒ Object
104
105
106
107
|
# File 'lib/capybara/simulated/node.rb', line 104
def click(keys = [], **opts)
check_stale
browser.click(handle_id, keys, **opts)
end
|
#disabled? ⇒ Boolean
217
|
# File 'lib/capybara/simulated/node.rb', line 217
def disabled? = browser.disabled?(handle_id)
|
#double_click(keys = [], **opts) ⇒ Object
114
115
116
117
|
# File 'lib/capybara/simulated/node.rb', line 114
def double_click(keys = [], **opts)
check_stale
browser.double_click(handle_id, keys, **opts)
end
|
#drag_to(target_node, **opts) ⇒ Object
177
178
179
180
181
182
183
|
# File 'lib/capybara/simulated/node.rb', line 177
def drag_to(target_node, **opts)
check_stale
target_node.check_stale if target_node.respond_to?(:check_stale)
target_handle = target_node.respond_to?(:handle_id) ? target_node.handle_id : target_node.native
browser.drag_to(handle_id, target_handle, **opts)
self
end
|
#drop(*args) ⇒ Object
171
172
173
174
175
|
# File 'lib/capybara/simulated/node.rb', line 171
def drop(*args)
check_stale
browser.drop(handle_id, args)
true
end
|
#find_css(query) ⇒ Object
208
209
210
|
# File 'lib/capybara/simulated/node.rb', line 208
def find_css(query)
browser.find_css(query, handle_id).map {|id| self.class.new(driver, id) }
end
|
#find_xpath(query) ⇒ Object
204
205
206
|
# File 'lib/capybara/simulated/node.rb', line 204
def find_xpath(query)
browser.find_xpath(query, handle_id).map {|id| self.class.new(driver, id) }
end
|
#hover(**_opts) ⇒ Object
119
120
121
122
123
|
# File 'lib/capybara/simulated/node.rb', line 119
def hover(**_opts)
check_stale
browser.hover(handle_id)
self
end
|
#inner_html ⇒ Object
Convenience accessors mirroring real browser nodes — Discourse
tests reach for .native.inner_html (e.g. reviewables XSS
checks); without this method .native (= self) raised
NoMethodError.
67
68
69
70
|
# File 'lib/capybara/simulated/node.rb', line 67
def inner_html
check_stale
browser.inner_html(handle_id)
end
|
#obscured? ⇒ Boolean
221
222
223
224
|
# File 'lib/capybara/simulated/node.rb', line 221
def obscured?(*)
check_stale
browser.obscured?(handle_id)
end
|
#outer_html ⇒ Object
72
73
74
75
|
# File 'lib/capybara/simulated/node.rb', line 72
def outer_html
check_stale
browser.outer_html(handle_id)
end
|
#path ⇒ Object
230
231
232
233
|
# File 'lib/capybara/simulated/node.rb', line 230
def path
check_stale
browser.node_path(handle_id)
end
|
#readonly? ⇒ Boolean
220
|
# File 'lib/capybara/simulated/node.rb', line 220
def readonly? = !!self['readonly']
|
#rect ⇒ Object
Capybara's standard rect API. No layout engine — but
The element's coarse border-box (viewport-relative), from the layout engine — backs the
spatial selectors (:above/:below/:near) and coordinate drag. Deterministic per layout
generation (memoised; only a DOM/style mutation changes it), so Discourse's
wait_for_animation — which polls element.rect[:x] twice and waits for it to stabilise —
still settles immediately when nothing is animating.
155
156
157
158
|
# File 'lib/capybara/simulated/node.rb', line 155
def rect
check_stale
browser.rect(handle_id)
end
|
#right_click(keys = [], **opts) ⇒ Object
109
110
111
112
|
# File 'lib/capybara/simulated/node.rb', line 109
def right_click(keys = [], **opts)
check_stale
browser.right_click(handle_id, keys, **opts)
end
|
Capybara's Element#scroll_to(:current, offset: [dx, dy]) calls this after the position
handling above — a relative scroll from wherever the element is now.
143
144
145
146
147
|
# File 'lib/capybara/simulated/node.rb', line 143
def scroll_by(dx, dy)
check_stale
browser.scroll_by(handle_id, dx, dy)
self
end
|
Capybara's driver scroll_to contract (from Element#scroll_to): a target element + align
symbol, a position symbol (:top/:bottom/:center), or an [x, y] coordinate pair.
self is the element it was called on — the document root for a session-level scroll (routed
via find('/html')), else an element. Drives a real scroll offset in the layout engine.
129
130
131
132
133
134
135
136
137
138
139
|
# File 'lib/capybara/simulated/node.rb', line 129
def scroll_to(target = nil, arg = nil, coords = nil)
check_stale
if target
browser.scroll_to(handle_id, target.handle_id, arg)
elsif coords
browser.scroll_to(handle_id, nil, nil, coords[0], coords[1])
elsif arg
browser.scroll_to(handle_id, nil, arg)
end
self
end
|
#select_option ⇒ Object
189
190
191
192
|
# File 'lib/capybara/simulated/node.rb', line 189
def select_option
check_stale
browser.select_option(handle_id)
end
|
#selected? ⇒ Boolean
218
|
# File 'lib/capybara/simulated/node.rb', line 218
def selected? = browser.option_selected?(handle_id)
|
#send_keys(*keys) ⇒ Object
160
161
162
163
164
|
# File 'lib/capybara/simulated/node.rb', line 160
def send_keys(*keys)
check_stale
browser.send_keys(handle_id, keys)
true
end
|
#set(value, **_) ⇒ Object
184
185
186
187
|
# File 'lib/capybara/simulated/node.rb', line 184
def set(value, **_)
check_stale
browser.set_value_with_events(handle_id, value)
end
|
#shadow_root ⇒ Object
212
213
214
215
216
|
# File 'lib/capybara/simulated/node.rb', line 212
def shadow_root
check_stale
h = browser.shadow_root_handle(handle_id)
h && self.class.new(driver, h)
end
|
#style(names = []) ⇒ Object
226
227
228
229
|
# File 'lib/capybara/simulated/node.rb', line 226
def style(names = [])
check_stale
browser.computed_style(handle_id, Array(names))
end
|
#submit(*_) ⇒ Object
199
200
201
202
|
# File 'lib/capybara/simulated/node.rb', line 199
def submit(*_)
check_stale
browser.submit_form(handle_id)
end
|
#synchronize ⇒ Object
225
|
# File 'lib/capybara/simulated/node.rb', line 225
def synchronize(*) = yield
|
#tag_name ⇒ Object
61
|
# File 'lib/capybara/simulated/node.rb', line 61
def tag_name = browser.tag_name(handle_id)
|
#trigger(event) ⇒ Object
166
167
168
169
170
|
# File 'lib/capybara/simulated/node.rb', line 166
def trigger(event)
check_stale
browser.dispatch_event(handle_id, event.to_s)
true
end
|
#unselect_option ⇒ Object
194
195
196
197
|
# File 'lib/capybara/simulated/node.rb', line 194
def unselect_option
check_stale
browser.unselect_option(handle_id)
end
|
#value ⇒ Object
51
52
53
54
|
# File 'lib/capybara/simulated/node.rb', line 51
def value
check_stale
browser.value(handle_id)
end
|
#visible? ⇒ Boolean
56
57
58
59
|
# File 'lib/capybara/simulated/node.rb', line 56
def visible?
check_stale
browser.visible?(handle_id)
end
|
#visible_text ⇒ Object
45
46
47
48
49
|
# File 'lib/capybara/simulated/node.rb', line 45
def visible_text
browser.tick_real_time
check_stale
normalize_visible_spacing(browser.visible_text(handle_id))
end
|