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
The text readers advance the virtual clock, unlike Node#[] (attribute reads) which sit behind a find_css that already ticked: have_text / assert_text polls .text directly against an already-found, cached scope node, so the find loop short-circuits without re-ticking and a page waiting on a timer would never make progress.
-
#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.
238
239
240
241
242
243
|
# File 'lib/capybara/simulated/node.rb', line 238
def ==(other)
other.is_a?(Node) &&
other.handle_id == @handle_id &&
other.context_gen == @context_gen &&
other.realm_id == @realm_id
end
|
#[](name) ⇒ Object
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
|
# File 'lib/capybara/simulated/node.rb', line 74
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
The text readers advance the virtual clock, unlike Node#[]
(attribute reads) which sit behind a find_css that already
ticked: have_text / assert_text polls .text directly against
an already-found, cached scope node, so the find loop
short-circuits without re-ticking and a page waiting on a timer
would never make progress. tick_for_read decides WHEN: a read
leaves the clock where it is and the next query pays the step, so
a walk over one query's results can't be stranded mid-way.
36
37
38
39
40
|
# File 'lib/capybara/simulated/node.rb', line 36
def all_text
browser.tick_for_read(handle_id)
check_stale
normalize_spacing(browser.all_text(handle_id))
end
|
#checked? ⇒ Boolean
216
|
# File 'lib/capybara/simulated/node.rb', line 216
def checked? = !!self['checked']
|
#click(keys = [], **opts) ⇒ Object
101
102
103
104
|
# File 'lib/capybara/simulated/node.rb', line 101
def click(keys = [], **opts)
check_stale
browser.click(handle_id, keys, **opts)
end
|
#disabled? ⇒ Boolean
214
|
# File 'lib/capybara/simulated/node.rb', line 214
def disabled? = browser.disabled?(handle_id)
|
#double_click(keys = [], **opts) ⇒ Object
111
112
113
114
|
# File 'lib/capybara/simulated/node.rb', line 111
def double_click(keys = [], **opts)
check_stale
browser.double_click(handle_id, keys, **opts)
end
|
#drag_to(target_node, **opts) ⇒ Object
174
175
176
177
178
179
180
|
# File 'lib/capybara/simulated/node.rb', line 174
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
168
169
170
171
172
|
# File 'lib/capybara/simulated/node.rb', line 168
def drop(*args)
check_stale
browser.drop(handle_id, args)
true
end
|
#find_css(query) ⇒ Object
205
206
207
|
# File 'lib/capybara/simulated/node.rb', line 205
def find_css(query)
browser.find_css(query, handle_id).map {|id| self.class.new(driver, id) }
end
|
#find_xpath(query) ⇒ Object
201
202
203
|
# File 'lib/capybara/simulated/node.rb', line 201
def find_xpath(query)
browser.find_xpath(query, handle_id).map {|id| self.class.new(driver, id) }
end
|
#hover(**_opts) ⇒ Object
116
117
118
119
120
|
# File 'lib/capybara/simulated/node.rb', line 116
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.
64
65
66
67
|
# File 'lib/capybara/simulated/node.rb', line 64
def inner_html
check_stale
browser.inner_html(handle_id)
end
|
#obscured? ⇒ Boolean
218
219
220
221
|
# File 'lib/capybara/simulated/node.rb', line 218
def obscured?(*)
check_stale
browser.obscured?(handle_id)
end
|
#outer_html ⇒ Object
69
70
71
72
|
# File 'lib/capybara/simulated/node.rb', line 69
def outer_html
check_stale
browser.outer_html(handle_id)
end
|
#path ⇒ Object
227
228
229
230
|
# File 'lib/capybara/simulated/node.rb', line 227
def path
check_stale
browser.node_path(handle_id)
end
|
#readonly? ⇒ Boolean
217
|
# File 'lib/capybara/simulated/node.rb', line 217
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.
152
153
154
155
|
# File 'lib/capybara/simulated/node.rb', line 152
def rect
check_stale
browser.rect(handle_id)
end
|
#right_click(keys = [], **opts) ⇒ Object
106
107
108
109
|
# File 'lib/capybara/simulated/node.rb', line 106
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.
140
141
142
143
144
|
# File 'lib/capybara/simulated/node.rb', line 140
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.
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/capybara/simulated/node.rb', line 126
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
186
187
188
189
|
# File 'lib/capybara/simulated/node.rb', line 186
def select_option
check_stale
browser.select_option(handle_id)
end
|
#selected? ⇒ Boolean
215
|
# File 'lib/capybara/simulated/node.rb', line 215
def selected? = browser.option_selected?(handle_id)
|
#send_keys(*keys) ⇒ Object
157
158
159
160
161
|
# File 'lib/capybara/simulated/node.rb', line 157
def send_keys(*keys)
check_stale
browser.send_keys(handle_id, keys)
true
end
|
#set(value, **_) ⇒ Object
181
182
183
184
|
# File 'lib/capybara/simulated/node.rb', line 181
def set(value, **_)
check_stale
browser.set_value_with_events(handle_id, value)
end
|
#shadow_root ⇒ Object
209
210
211
212
213
|
# File 'lib/capybara/simulated/node.rb', line 209
def shadow_root
check_stale
h = browser.shadow_root_handle(handle_id)
h && self.class.new(driver, h)
end
|
#style(names = []) ⇒ Object
223
224
225
226
|
# File 'lib/capybara/simulated/node.rb', line 223
def style(names = [])
check_stale
browser.computed_style(handle_id, Array(names))
end
|
#submit(*_) ⇒ Object
196
197
198
199
|
# File 'lib/capybara/simulated/node.rb', line 196
def submit(*_)
check_stale
browser.submit_form(handle_id)
end
|
#synchronize ⇒ Object
222
|
# File 'lib/capybara/simulated/node.rb', line 222
def synchronize(*) = yield
|
#tag_name ⇒ Object
58
|
# File 'lib/capybara/simulated/node.rb', line 58
def tag_name = browser.tag_name(handle_id)
|
#trigger(event) ⇒ Object
163
164
165
166
167
|
# File 'lib/capybara/simulated/node.rb', line 163
def trigger(event)
check_stale
browser.dispatch_event(handle_id, event.to_s)
true
end
|
#unselect_option ⇒ Object
191
192
193
194
|
# File 'lib/capybara/simulated/node.rb', line 191
def unselect_option
check_stale
browser.unselect_option(handle_id)
end
|
#value ⇒ Object
48
49
50
51
|
# File 'lib/capybara/simulated/node.rb', line 48
def value
check_stale
browser.value(handle_id)
end
|
#visible? ⇒ Boolean
53
54
55
56
|
# File 'lib/capybara/simulated/node.rb', line 53
def visible?
check_stale
browser.visible?(handle_id)
end
|
#visible_text ⇒ Object
42
43
44
45
46
|
# File 'lib/capybara/simulated/node.rb', line 42
def visible_text
browser.tick_for_read(handle_id)
check_stale
normalize_visible_spacing(browser.visible_text(handle_id))
end
|