Class: Capybara::Node::Element
- Defined in:
- lib/capybara/node/element.rb
Overview
A Element represents a single element on the page. It is possible to interact with the contents of this element the same as with a document:
session = Capybara::Session.new(:rack_test, my_app)
= session.find('#bar') # from Capybara::Node::Finders
.select('Baz', from: 'Quox') # from Capybara::Node::Actions
Element also has access to HTML attributes and other properties of the element:
.value
.text
[:title]
Constant Summary collapse
- STYLE_SCRIPT =
<<~JS (function(){ var s = window.getComputedStyle(this); var result = {}; for (var i = arguments.length; i--; ) { var property_name = arguments[i]; result[property_name] = s.getPropertyValue(property_name); } return result; }).apply(this, arguments) JS
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#[](attribute) ⇒ String
Retrieve the given attribute.
- #allow_reload! ⇒ Object
-
#checked? ⇒ Boolean
Whether or not the element is checked.
-
#click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Click the Element.
-
#disabled? ⇒ Boolean
Whether or not the element is disabled.
-
#double_click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Double Click the Element.
-
#drag_to(node) ⇒ Capybara::Node::Element
Drag the element to the given other element.
-
#evaluate_async_script(script, *args) ⇒ Object
Evaluate the given JavaScript in the context of the element and obtain the result from a callback function which will be passed as the last argument to the script.
-
#evaluate_script(script, *args) ⇒ Object
Evaluate the given JS in the context of the element and return the result.
-
#execute_script(script, *args) ⇒ Object
Execute the given JS in the context of the element not returning a result.
-
#hover ⇒ Capybara::Node::Element
Hover on the Element.
- #initial_cache ⇒ Object private
-
#initialize(session, base, query_scope, query) ⇒ Element
constructor
A new instance of Element.
- #inspect ⇒ Object
-
#multiple? ⇒ Boolean
Whether or not the element supports multiple results.
-
#native ⇒ Object
The native element from the driver, this allows access to driver specific methods.
-
#path ⇒ String
An XPath expression describing where on the page the element can be found.
-
#readonly? ⇒ Boolean
Whether or not the element is readonly.
- #reload ⇒ Object
-
#right_click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Right Click the Element.
-
#scroll_to(pos_or_el_or_x, y = nil, align: :top, offset: nil) ⇒ Capybara::Node::Element
Scroll the page or element.
-
#select_option(wait: nil) ⇒ Capybara::Node::Element
Select this node if is an option element inside a select tag.
-
#selected? ⇒ Boolean
Whether or not the element is selected.
-
#send_keys(keys, ...) ⇒ Capybara::Node::Element
Send Keystrokes to the Element.
-
#set(value, **options) ⇒ Capybara::Node::Element
Set the value of the form element to the given value.
-
#style(*styles) ⇒ Hash
Retrieve the given CSS styles.
-
#tag_name ⇒ String
The tag name of the element.
-
#text(type = nil, normalize_ws: false) ⇒ String
Retrieve the text of the element.
-
#trigger(event) ⇒ Capybara::Node::Element
Trigger any event on the current element, for example mouseover or focus events.
-
#unselect_option(wait: nil) ⇒ Capybara::Node::Element
Unselect this node if is an option element inside a multiple select tag.
-
#value ⇒ String
The value of the form element.
-
#visible? ⇒ Boolean
Whether or not the element is visible.
Methods inherited from Base
#find_css, #find_xpath, #session_options, #synchronize, #to_capybara_node
Methods included from Minitest::Expectations
Methods included from Matchers
#==, #assert_all_of_selectors, #assert_any_of_selectors, #assert_matches_selector, #assert_matches_style, #assert_no_selector, #assert_no_text, #assert_none_of_selectors, #assert_not_matches_selector, #assert_selector, #assert_style, #assert_text, #has_button?, #has_checked_field?, #has_css?, #has_field?, #has_link?, #has_no_button?, #has_no_checked_field?, #has_no_css?, #has_no_field?, #has_no_link?, #has_no_select?, #has_no_selector?, #has_no_table?, #has_no_text?, #has_no_unchecked_field?, #has_no_xpath?, #has_select?, #has_selector?, #has_style?, #has_table?, #has_text?, #has_unchecked_field?, #has_xpath?, #matches_css?, #matches_selector?, #matches_style?, #matches_xpath?, #not_matches_css?, #not_matches_selector?, #not_matches_xpath?
Methods included from Actions
#attach_file, #check, #choose, #click_button, #click_link, #click_link_or_button, #fill_in, #select, #uncheck, #unselect
Methods included from Finders
#all, #ancestor, #find, #find_button, #find_by_id, #find_field, #find_link, #first, #sibling
Constructor Details
#initialize(session, base, query_scope, query) ⇒ Element
Returns a new instance of Element.
25 26 27 28 29 30 |
# File 'lib/capybara/node/element.rb', line 25 def initialize(session, base, query_scope, query) super(session, base) @query_scope = query_scope @query = query @allow_reload = false end |
Instance Method Details
#[](attribute) ⇒ String
Retrieve the given attribute
element[:title] # => HTML title attribute
71 72 73 |
# File 'lib/capybara/node/element.rb', line 71 def [](attribute) synchronize { base[attribute] } end |
#allow_reload! ⇒ Object
32 33 34 |
# File 'lib/capybara/node/element.rb', line 32 def allow_reload! @allow_reload = true end |
#checked? ⇒ Boolean
Whether or not the element is checked.
299 300 301 |
# File 'lib/capybara/node/element.rb', line 299 def checked? synchronize { base.checked? } end |
#click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Click the Element
Both x: and y: must be specified if an offset is wanted, if not specified the click will occur at the middle of the element
155 156 157 158 159 160 |
# File 'lib/capybara/node/element.rb', line 155 def click(*keys, wait: nil, **offset) raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ offset[:x] ^ offset[:y] synchronize(wait) { base.click(Array(keys), offset) } self end |
#disabled? ⇒ Boolean
Whether or not the element is disabled.
319 320 321 |
# File 'lib/capybara/node/element.rb', line 319 def disabled? synchronize { base.disabled? } end |
#double_click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Double Click the Element
Both x: and y: must be specified if an offset is wanted, if not specified the click will occur at the middle of the element
181 182 183 184 185 186 |
# File 'lib/capybara/node/element.rb', line 181 def double_click(*keys, wait: nil, **offset) raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ offset[:x] ^ offset[:y] synchronize(wait) { base.double_click(keys, offset) } self end |
#drag_to(node) ⇒ Capybara::Node::Element
Drag the element to the given other element.
source = page.find('#foo')
target = page.find('#bar')
source.drag_to(target)
379 380 381 382 |
# File 'lib/capybara/node/element.rb', line 379 def drag_to(node) synchronize { base.drag_to(node.base) } self end |
#evaluate_async_script(script, *args) ⇒ Object
Evaluate the given JavaScript in the context of the element and obtain the result from a callback function which will be passed as the last argument to the script. ‘this` in the script will refer to the element this is called on
459 460 461 462 463 464 465 |
# File 'lib/capybara/node/element.rb', line 459 def evaluate_async_script(script, *args) session.evaluate_async_script(<<~JS, self, *args) (function (){ #{script} }).apply(arguments[0], Array.prototype.slice.call(arguments,1)); JS end |
#evaluate_script(script, *args) ⇒ Object
Evaluate the given JS in the context of the element and return the result. Be careful when using this with scripts that return complex objects, such as jQuery statements. execute_script might be a better alternative. ‘this` in the script will refer to the element this is called on.
442 443 444 445 446 447 448 |
# File 'lib/capybara/node/element.rb', line 442 def evaluate_script(script, *args) session.evaluate_script(<<~JS, self, *args) (function(){ return #{script.strip} }).apply(arguments[0], Array.prototype.slice.call(arguments,1)); JS end |
#execute_script(script, *args) ⇒ Object
Execute the given JS in the context of the element not returning a result. This is useful for scripts that return complex objects, such as jQuery statements. execute_script should be used over evaluate_script whenever possible. ‘this` in the script will refer to the element this is called on.
425 426 427 428 429 430 431 |
# File 'lib/capybara/node/element.rb', line 425 def execute_script(script, *args) session.execute_script(<<~JS, self, *args) (function (){ #{script} }).apply(arguments[0], Array.prototype.slice.call(arguments,1)); JS end |
#hover ⇒ Capybara::Node::Element
Hover on the Element
269 270 271 272 |
# File 'lib/capybara/node/element.rb', line 269 def hover synchronize { base.hover } self end |
#initial_cache ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
490 491 492 |
# File 'lib/capybara/node/element.rb', line 490 def initial_cache base.respond_to?(:initial_cache) ? base.initial_cache : {} end |
#inspect ⇒ Object
479 480 481 482 483 484 485 486 487 |
# File 'lib/capybara/node/element.rb', line 479 def inspect %(#<Capybara::Node::Element tag="#{base.tag_name}" path="#{base.path}">) rescue NotSupportedByDriverError %(#<Capybara::Node::Element tag="#{base.tag_name}">) rescue StandardError => err raise unless session.driver.invalid_element_errors.any? { |et| err.is_a?(et) } %(Obsolete #<Capybara::Node::Element>) end |
#multiple? ⇒ Boolean
Whether or not the element supports multiple results.
339 340 341 |
# File 'lib/capybara/node/element.rb', line 339 def multiple? synchronize { base.multiple? } end |
#native ⇒ Object
Returns The native element from the driver, this allows access to driver specific methods.
40 41 42 |
# File 'lib/capybara/node/element.rb', line 40 def native synchronize { base.native } end |
#path ⇒ String
An XPath expression describing where on the page the element can be found
349 350 351 |
# File 'lib/capybara/node/element.rb', line 349 def path synchronize { base.path } end |
#readonly? ⇒ Boolean
Whether or not the element is readonly.
329 330 331 |
# File 'lib/capybara/node/element.rb', line 329 def readonly? synchronize { base.readonly? } end |
#reload ⇒ Object
467 468 469 470 471 472 473 474 475 476 477 |
# File 'lib/capybara/node/element.rb', line 467 def reload if @allow_reload begin reloaded = query_scope.reload.first(@query.name, @query.locator, @query.) @base = reloaded.base if reloaded rescue StandardError => e raise e unless catch_error?(e) end end self end |
#right_click(*modifier_keys, **offset) ⇒ Capybara::Node::Element
Right Click the Element
Both x: and y: must be specified if an offset is wanted, if not specified the click will occur at the middle of the element
168 169 170 171 172 173 |
# File 'lib/capybara/node/element.rb', line 168 def right_click(*keys, wait: nil, **offset) raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ offset[:x] ^ offset[:y] synchronize(wait) { base.right_click(keys, offset) } self end |
#scroll_to(position, offset: [0,0]) ⇒ Capybara::Node::Element #scroll_to(element, align: :top) ⇒ Capybara::Node::Element #scroll_to(x, y) ⇒ Capybara::Node::Element
Scroll the page or element
Scroll the page or element to its top, bottom or middle Scroll the page or current element until the given element is aligned at the top, bottom, or center of it
403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/capybara/node/element.rb', line 403 def scroll_to(pos_or_el_or_x, y = nil, align: :top, offset: nil) case pos_or_el_or_x when Symbol synchronize { base.scroll_to(nil, pos_or_el_or_x) } unless pos_or_el_or_x == :current when Capybara::Node::Element synchronize { base.scroll_to(pos_or_el_or_x.base, align) } else synchronize { base.scroll_to(nil, nil, [pos_or_el_or_x, y]) } end synchronize { base.scroll_by(*offset) } unless offset.nil? self end |
#select_option(wait: nil) ⇒ Capybara::Node::Element
Select this node if is an option element inside a select tag
128 129 130 131 132 |
# File 'lib/capybara/node/element.rb', line 128 def select_option(wait: nil) warn "Attempt to select disabled option: #{value || text}" if disabled? synchronize(wait) { base.select_option } self end |
#selected? ⇒ Boolean
Whether or not the element is selected.
309 310 311 |
# File 'lib/capybara/node/element.rb', line 309 def selected? synchronize { base.selected? } end |
#send_keys(keys, ...) ⇒ Capybara::Node::Element
Send Keystrokes to the Element
Examples:
element.send_keys "foo" #=> value: 'foo'
element.send_keys "tet", :left, "s" #=> value: 'test'
element.send_keys [:control, 'a'], :space #=> value: ' ' - assuming ctrl-a selects all contents
Symbols supported for keys :cancel :help :backspace :tab :clear :return :enter :shift :control :alt :pause :escape :space :page_up :page_down :end :home :left :up :right :down :insert :delete :semicolon :equals :numpad0 :numpad1 :numpad2 :numpad3 :numpad4 :numpad5 :numpad6 :numpad7 :numpad8 :numpad9 :multiply - numeric keypad * :add - numeric keypad + :separator - numeric keypad ‘separator’ key ?? :subtract - numeric keypad - :decimal - numeric keypad . :divide - numeric keypad / :f1 :f2 :f3 :f4 :f5 :f6 :f7 :f8 :f9 :f10 :f11 :f12 :meta :command - alias of :meta
259 260 261 262 |
# File 'lib/capybara/node/element.rb', line 259 def send_keys(*args) synchronize { base.send_keys(*args) } self end |
#set(value, **options) ⇒ Capybara::Node::Element
Set the value of the form element to the given value.
115 116 117 118 119 120 121 |
# File 'lib/capybara/node/element.rb', line 115 def set(value, **) raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}" if ENV['CAPYBARA_THOROUGH'] && readonly? = ..to_h.merge() synchronize { base.set(value, ) } self end |
#style(*styles) ⇒ Hash
Retrieve the given CSS styles
element.style('color', 'font-size') # => Computed values of CSS 'color' and 'font-size' styles
84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/capybara/node/element.rb', line 84 def style(*styles) styles = styles.flatten.map(&:to_s) raise ArgumentError, 'You must specify at least one CSS style' if styles.empty? begin synchronize { base.style(styles) } rescue NotImplementedError => e begin evaluate_script(STYLE_SCRIPT, *styles) rescue Capybara::NotSupportedByDriverError raise e end end end |
#tag_name ⇒ String
Returns The tag name of the element.
278 279 280 |
# File 'lib/capybara/node/element.rb', line 278 def tag_name synchronize { base.tag_name } end |
#text(type = nil, normalize_ws: false) ⇒ String
Retrieve the text of the element. If ‘Capybara.ignore_hidden_elements` is `true`, which it is by default, then this will return only text which is visible. The exact semantics of this may differ between drivers, but generally any text within elements with `display:none` is ignored. This behaviour can be overridden by passing `:all` to this method.
56 57 58 59 60 |
# File 'lib/capybara/node/element.rb', line 56 def text(type = nil, normalize_ws: false) type ||= :all unless .ignore_hidden_elements || .visible_text_only txt = synchronize { type == :all ? base.all_text : base.visible_text } normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt end |
#trigger(event) ⇒ Capybara::Node::Element
Trigger any event on the current element, for example mouseover or focus events. Not supported with the Selenium driver, and SHOULDN’T BE USED IN TESTING unless you fully understand why you’re using it, that it can allow actions a user could never perform, and that it may completely invalidate your test.
363 364 365 366 |
# File 'lib/capybara/node/element.rb', line 363 def trigger(event) synchronize { base.trigger(event) } self end |
#unselect_option(wait: nil) ⇒ Capybara::Node::Element
Unselect this node if is an option element inside a multiple select tag
139 140 141 142 |
# File 'lib/capybara/node/element.rb', line 139 def unselect_option(wait: nil) synchronize(wait) { base.unselect_option } self end |
#value ⇒ String
Returns The value of the form element.
103 104 105 |
# File 'lib/capybara/node/element.rb', line 103 def value synchronize { base.value } end |
#visible? ⇒ Boolean
Whether or not the element is visible. Not all drivers support CSS, so the result may be inaccurate.
289 290 291 |
# File 'lib/capybara/node/element.rb', line 289 def visible? synchronize { base.visible? } end |