Class: Capybara::Apparition::Node
- Inherits:
-
Driver::Node
- Object
- Driver::Node
- Capybara::Apparition::Node
- Extended by:
- Forwardable
- Includes:
- Drag
- Defined in:
- lib/capybara/apparition/node.rb
Constant Summary collapse
- EVENTS =
{ blur: ['FocusEvent'], focus: ['FocusEvent'], focusin: ['FocusEvent', { bubbles: true }], focusout: ['FocusEvent', { bubbles: true }], click: ['MouseEvent', { bubbles: true, cancelable: true }], dblckick: ['MouseEvent', { bubbles: true, cancelable: true }], mousedown: ['MouseEvent', { bubbles: true, cancelable: true }], mouseup: ['MouseEvent', { bubbles: true, cancelable: true }], mouseenter: ['MouseEvent'], mouseleave: ['MouseEvent'], mousemove: ['MouseEvent', { bubbles: true, cancelable: true }], mouseover: ['MouseEvent', { bubbles: true, cancelable: true }], mouseout: ['MouseEvent', { bubbles: true, cancelable: true }], context_menu: ['MouseEvent', { bubble: true, cancelable: true }], submit: ['Event', { bubbles: true, cancelable: true }], change: ['Event', { bubbles: true, cacnelable: false }], input: ['InputEvent', { bubbles: true, cacnelable: false }], wheel: ['WheelEvent', { bubbles: true, cancelable: true }] }.freeze
Constants included from Drag
Drag::ATTACH_FILE, Drag::DROP_FILE, Drag::DROP_STRING, Drag::HTML5_DRAG_DROP_SCRIPT, Drag::LEGACY_DRAG_CHECK, Drag::MOUSEDOWN_TRACKER
Instance Attribute Summary collapse
-
#page_id ⇒ Object
readonly
Returns the value of attribute page_id.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #[](name) ⇒ Object
- #all_text ⇒ Object
- #attribute(name) ⇒ Object
- #attributes ⇒ Object
- #checked? ⇒ Boolean
- #click(keys = [], button: 'left', count: 1, **options) ⇒ Object
- #disabled? ⇒ Boolean
- #double_click(keys = [], **options) ⇒ Object
- #element_click_pos(x: nil, y: nil, offset: nil) ⇒ Object
- #find(method, selector) ⇒ Object
- #find_css(selector) ⇒ Object
- #find_xpath(selector) ⇒ Object
- #hover ⇒ Object
- #id ⇒ Object
-
#initialize(driver, page, remote_object, initial_cache) ⇒ Node
constructor
A new instance of Node.
-
#inner_html ⇒ Object
capybara-webkit method.
-
#inner_html=(value) ⇒ Object
capybara-webkit method.
- #obscured? ⇒ Boolean
- #parents ⇒ Object
- #path ⇒ Object
- #property(name) ⇒ Object
- #rect ⇒ Object
- #right_click(keys = [], **options) ⇒ Object
- #scroll_by(x, y) ⇒ Object
- #scroll_to(element, location, position = nil) ⇒ Object
- #select_option ⇒ Object
- #selected? ⇒ Boolean
- #send_keys(*keys, delay: 0, **opts) ⇒ Object (also: #send_key)
- #set(value, **options) ⇒ Object
- #style(styles) ⇒ Object
- #submit ⇒ Object
- #tag_name ⇒ Object
-
#text ⇒ Object
capybara-webkit method.
- #top_left ⇒ Object
- #trigger(name, event_type = nil, **options) ⇒ Object
- #unselect_option ⇒ Object
- #value ⇒ Object
- #visible? ⇒ Boolean
- #visible_center(allow_scroll: true) ⇒ Object
- #visible_text ⇒ Object
- #visible_top_left ⇒ Object
Methods included from Drag
Constructor Details
#initialize(driver, page, remote_object, initial_cache) ⇒ Node
Returns a new instance of Node.
14 15 16 17 18 |
# File 'lib/capybara/apparition/node.rb', line 14 def initialize(driver, page, remote_object, initial_cache) super(driver, self, initial_cache) @page = page @remote_object = remote_object end |
Instance Attribute Details
#page_id ⇒ Object (readonly)
Returns the value of attribute page_id.
12 13 14 |
# File 'lib/capybara/apparition/node.rb', line 12 def page_id @page_id end |
Instance Method Details
#==(other) ⇒ Object
272 273 274 275 276 |
# File 'lib/capybara/apparition/node.rb', line 272 def ==(other) evaluate_on('el => this == el', objectId: other.id) rescue ObsoleteNode false end |
#[](name) ⇒ Object
99 100 101 102 103 |
# File 'lib/capybara/apparition/node.rb', line 99 def [](name) # Although the attribute matters, the property is consistent. Return that in # preference to the attribute for links and images. evaluate_on ELEMENT_PROP_OR_ATTR_JS, value: name end |
#all_text ⇒ Object
50 51 52 53 54 55 56 57 |
# File 'lib/capybara/apparition/node.rb', line 50 def all_text text = evaluate_on('() => this.textContent') text.to_s.gsub(/[\u200b\u200e\u200f]/, '') .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ') .gsub(/\A[[:space:]&&[^\u00a0]]+/, '') .gsub(/[[:space:]&&[^\u00a0]]+\z/, '') .tr("\u00a0", ' ') end |
#attribute(name) ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/capybara/apparition/node.rb', line 91 def attribute(name) if %w[checked selected].include?(name.to_s) property(name) else evaluate_on('name => this.getAttribute(name)', value: name) end end |
#attributes ⇒ Object
105 106 107 |
# File 'lib/capybara/apparition/node.rb', line 105 def attributes evaluate_on GET_ATTRIBUTES_JS end |
#checked? ⇒ Boolean
188 189 190 |
# File 'lib/capybara/apparition/node.rb', line 188 def checked? self[:checked] end |
#click(keys = [], button: 'left', count: 1, **options) ⇒ Object
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/capybara/apparition/node.rb', line 200 def click(keys = [], button: 'left', count: 1, **) pos = element_click_pos(**) raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if pos.nil? test = mouse_event_test(**pos) raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if test.nil? unless [:x] && [:y] raise ::Capybara::Apparition::MouseEventFailed.new(self, 'args' => ['click', test.selector, pos]) unless test.success end @page.mouse.click_at(**pos.merge(button: , count: count, modifiers: keys)) if ENV['DEBUG'] begin new_pos = element_click_pos(**) puts "Element moved from #{pos} to #{new_pos}" unless pos == new_pos rescue WrongWorld # rubocop:disable Lint/SuppressedException end end # Wait a short time to see if click triggers page load sleep 0.05 @page.wait_for_loaded(allow_obsolete: true) end |
#disabled? ⇒ Boolean
196 197 198 |
# File 'lib/capybara/apparition/node.rb', line 196 def disabled? evaluate_on ELEMENT_DISABLED_JS end |
#double_click(keys = [], **options) ⇒ Object
228 229 230 |
# File 'lib/capybara/apparition/node.rb', line 228 def double_click(keys = [], **) click(keys, count: 2, **) end |
#element_click_pos(x: nil, y: nil, offset: nil) ⇒ Object
288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/capybara/apparition/node.rb', line 288 def element_click_pos(x: nil, y: nil, offset: nil, **) if x && y if offset == :center visible_center else visible_top_left end.tap do |p| p[:x] += x p[:y] += y end else visible_center end end |
#find(method, selector) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/capybara/apparition/node.rb', line 30 def find(method, selector) js = method == :css ? FIND_CSS_JS : FIND_XPATH_JS evaluate_on(js, value: selector).map do |r_o| tag_name = r_o['description'].split(/[\.#]/, 2)[0] Capybara::Apparition::Node.new(driver, @page, r_o['objectId'], tag_name: tag_name) end rescue ::Capybara::Apparition::BrowserError => e raise unless /is not a valid (XPath expression|selector)/.match? e.name raise Capybara::Apparition::InvalidSelector, 'args' => [method, selector] end |
#find_css(selector) ⇒ Object
46 47 48 |
# File 'lib/capybara/apparition/node.rb', line 46 def find_css(selector) find :css, selector end |
#find_xpath(selector) ⇒ Object
42 43 44 |
# File 'lib/capybara/apparition/node.rb', line 42 def find_xpath(selector) find :xpath, selector end |
#hover ⇒ Object
232 233 234 235 236 237 |
# File 'lib/capybara/apparition/node.rb', line 232 def hover pos = visible_center raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['hover']) if pos.nil? @page.mouse.move_to(**pos) end |
#id ⇒ Object
22 23 24 |
# File 'lib/capybara/apparition/node.rb', line 22 def id @remote_object end |
#inner_html ⇒ Object
capybara-webkit method
76 77 78 |
# File 'lib/capybara/apparition/node.rb', line 76 def inner_html self[:innerHTML] end |
#inner_html=(value) ⇒ Object
capybara-webkit method
81 82 83 84 85 |
# File 'lib/capybara/apparition/node.rb', line 81 def inner_html=(value) driver.execute_script <<~JS, self, value arguments[0].innerHTML = arguments[1] JS end |
#obscured? ⇒ Boolean
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/capybara/apparition/node.rb', line 173 def obscured?(**) pos = visible_center(allow_scroll: false) return true if pos.nil? hit_node = @page.element_from_point(**pos) return true if hit_node.nil? begin return evaluate_on('el => !this.contains(el)', objectId: hit_node['objectId']) rescue WrongWorld # rubocop:disable Lint/SuppressedException end true end |
#parents ⇒ Object
26 27 28 |
# File 'lib/capybara/apparition/node.rb', line 26 def parents find('xpath', 'ancestor::*').reverse end |
#path ⇒ Object
284 285 286 |
# File 'lib/capybara/apparition/node.rb', line 284 def path evaluate_on GET_PATH_JS end |
#property(name) ⇒ Object
87 88 89 |
# File 'lib/capybara/apparition/node.rb', line 87 def property(name) evaluate_on('name => this[name]', value: name) end |
#rect ⇒ Object
387 388 389 |
# File 'lib/capybara/apparition/node.rb', line 387 def rect evaluate_on GET_CLIENT_RECT_JS end |
#right_click(keys = [], **options) ⇒ Object
224 225 226 |
# File 'lib/capybara/apparition/node.rb', line 224 def right_click(keys = [], **) click(keys, button: 'right', **) end |
#scroll_by(x, y) ⇒ Object
391 392 393 394 395 396 |
# File 'lib/capybara/apparition/node.rb', line 391 def scroll_by(x, y) evaluate_on <<~JS, { value: x }, value: y (x, y) => this.scrollBy(x,y) JS self end |
#scroll_to(element, location, position = nil) ⇒ Object
398 399 400 401 402 403 404 405 406 407 |
# File 'lib/capybara/apparition/node.rb', line 398 def scroll_to(element, location, position = nil) if element.is_a? Capybara::Apparition::Node scroll_element_to_location(element, location) elsif location.is_a? Symbol scroll_to_location(location) else scroll_to_coords(*position) end self end |
#select_option ⇒ Object
151 152 153 154 155 156 |
# File 'lib/capybara/apparition/node.rb', line 151 def select_option return false if disabled? evaluate_on SELECT_OPTION_JS true end |
#selected? ⇒ Boolean
192 193 194 |
# File 'lib/capybara/apparition/node.rb', line 192 def selected? !!self[:selected] end |
#send_keys(*keys, delay: 0, **opts) ⇒ Object Also known as: send_key
278 279 280 281 |
# File 'lib/capybara/apparition/node.rb', line 278 def send_keys(*keys, delay: 0, **opts) click unless evaluate_on CURRENT_NODE_SELECTED_JS _send_keys(*keys, delay: delay, **opts) end |
#set(value, **options) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/capybara/apparition/node.rb', line 117 def set(value, **) if tag_name == 'input' case self[:type] when 'radio' click when 'checkbox' click if value != checked? when 'file' files = value.respond_to?(:to_ary) ? value.to_ary.map(&:to_s) : value.to_s set_files(files) when 'date' set_date(value) when 'time' set_time(value) when 'datetime-local' set_datetime_local(value) when 'color' set_color(value) when 'range' set_range(value) else set_text(value.to_s, **{ delay: 0 }.merge()) end elsif tag_name == 'textarea' set_text(value.to_s) elsif tag_name == 'select' warn "Setting the value of a select element via 'set' is deprecated, please use 'select' or 'select_option'." evaluate_on '()=>{ this.value = arguments[0] }', value: value.to_s elsif self[:isContentEditable] delete_text send_keys(value.to_s, delay: .fetch(:delay, 0)) end end |
#style(styles) ⇒ Object
113 114 115 |
# File 'lib/capybara/apparition/node.rb', line 113 def style(styles) evaluate_on GET_STYLES_JS, value: styles end |
#submit ⇒ Object
268 269 270 |
# File 'lib/capybara/apparition/node.rb', line 268 def submit evaluate_on '()=>{ this.submit() }' end |
#tag_name ⇒ Object
165 166 167 |
# File 'lib/capybara/apparition/node.rb', line 165 def tag_name @tag_name ||= evaluate_on('() => this.tagName').downcase end |
#text ⇒ Object
capybara-webkit method
70 71 72 73 |
# File 'lib/capybara/apparition/node.rb', line 70 def text warn 'Node#text is deprecated, please use Node#visible_text instead' visible_text end |
#top_left ⇒ Object
380 381 382 383 384 385 |
# File 'lib/capybara/apparition/node.rb', line 380 def top_left result = evaluate_on GET_CLIENT_RECT_JS return nil if result.nil? { x: result['x'], y: result['y'] } end |
#trigger(name, event_type = nil, **options) ⇒ Object
260 261 262 263 264 265 266 |
# File 'lib/capybara/apparition/node.rb', line 260 def trigger(name, event_type = nil, **) raise ArgumentError, 'Unknown event' unless EVENTS.key?(name.to_sym) || event_type event_type, opts = *EVENTS[name.to_sym], {} if event_type.nil? evaluate_on DISPATCH_EVENT_JS, { value: event_type }, { value: name }, value: opts.merge() end |
#unselect_option ⇒ Object
158 159 160 161 162 163 |
# File 'lib/capybara/apparition/node.rb', line 158 def unselect_option return false if disabled? evaluate_on(UNSELECT_OPTION_JS) || raise(Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.') end |
#value ⇒ Object
109 110 111 |
# File 'lib/capybara/apparition/node.rb', line 109 def value evaluate_on GET_VALUE_JS end |
#visible? ⇒ Boolean
169 170 171 |
# File 'lib/capybara/apparition/node.rb', line 169 def visible? evaluate_on VISIBLE_JS end |
#visible_center(allow_scroll: true) ⇒ Object
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
# File 'lib/capybara/apparition/node.rb', line 337 def visible_center(allow_scroll: true) rect = in_view_client_rect(allow_scroll: allow_scroll) return nil if rect.nil? frame_offset = @page.current_frame_offset if rect['width'].zero? || rect['height'].zero? return nil unless tag_name == 'area' map = find('xpath', 'ancestor::map').first img = find('xpath', "//img[@usemap='##{map[:name]}']").first return nil unless img.visible? img_pos = img.top_left coords = self[:coords].split(',').map(&:to_i) offset_pos = case self[:shape] when 'rect' { x: (coords[0] + coords[2]) / 2, y: (coords[1] + coords[2]) / 2 } when 'circle' { x: coords[0], y: coords[1] } when 'poly' raise 'TODO: Poly not implemented' else raise 'Unknown Shape' end { x: img_pos[:x] + offset_pos[:x] + frame_offset[:x], y: img_pos[:y] + offset_pos[:y] + frame_offset[:y] } else lm = @page.command('Page.getLayoutMetrics') x_extents = [rect['left'], rect['right']].minmax y_extents = [rect['top'], rect['bottom']].minmax x_extents[1] = [x_extents[1], lm['layoutViewport']['clientWidth']].min y_extents[1] = [y_extents[1], lm['layoutViewport']['clientHeight']].min { x: (x_extents.sum / 2) + frame_offset[:x], y: (y_extents.sum / 2) + frame_offset[:y] } end end |
#visible_text ⇒ Object
59 60 61 62 63 64 65 66 67 |
# File 'lib/capybara/apparition/node.rb', line 59 def visible_text return '' unless visible? text = evaluate_on ELEMENT_VISIBLE_TEXT_JS text.to_s.gsub(/\A[[:space:]&&[^\u00a0]]+/, '') .gsub(/[[:space:]&&[^\u00a0]]+\z/, '') .gsub(/\n+/, "\n") .tr("\u00a0", ' ') end |
#visible_top_left ⇒ Object
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/capybara/apparition/node.rb', line 303 def visible_top_left rect = in_view_client_rect return nil if rect.nil? frame_offset = @page.current_frame_offset if rect['width'].zero? || rect['height'].zero? return nil unless tag_name == 'area' map = find('xpath', 'ancestor::map').first img = find('xpath', "//img[@usemap='##{map[:name]}']").first return nil unless img.visible? img_pos = img.top_left coords = self[:coords].split(',').map(&:to_i) offset_pos = case self[:shape] when 'rect' { x: coords[0], y: coords[1] } when 'circle' { x: coords[0], y: coords[1] } when 'poly' raise 'TODO: Poly not implemented' else raise 'Unknown Shape' end { x: img_pos[:x] + offset_pos[:x] + frame_offset[:x], y: img_pos[:y] + offset_pos[:y] + frame_offset[:y] } else { x: rect['left'] + frame_offset[:x], y: rect['top'] + frame_offset[:y] } end end |