class Capybara::Node::Element

A {Capybara::Node::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)

bar = session.find('#bar')              # from Capybara::Node::Finders
bar.select('Baz', from: 'Quox')      # from Capybara::Node::Actions

{Capybara::Node::Element} also has access to HTML attributes and other properties of the element:

bar.value
bar.text
bar[:title]

@see Capybara::Node

Constants

STYLE_SCRIPT

Public Class Methods

new(session, base, query_scope, query) click to toggle source
Calls superclass method Capybara::Node::Base::new
# 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
  @query_idx = nil
end

Public Instance Methods

[](attribute) click to toggle source

Retrieve the given attribute.

element[:title] # => HTML title attribute

@param [Symbol] attribute The attribute to retrieve @return [String] The value of the attribute

# File lib/capybara/node/element.rb, line 73
def [](attribute)
  synchronize { base[attribute] }
end
allow_reload!(idx = nil) click to toggle source
# File lib/capybara/node/element.rb, line 33
def allow_reload!(idx = nil)
  @query_idx = idx
  @allow_reload = true
end
checked?() click to toggle source

Whether or not the element is checked.

@return [Boolean] Whether the element is checked

# File lib/capybara/node/element.rb, line 326
def checked?
  synchronize { base.checked? }
end
click(*keys, **options) click to toggle source

Click the Element.

@macro action_waiting_behavior @!macro click_modifiers

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.
@overload $0(*modifier_keys, wait: nil, **offset)
  @param *modifier_keys [:alt, :control, :meta, :shift] ([]) Keys to be held down when clicking
  @option options [Integer] x  X coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the
    offset will be from the element center, otherwise it will be from the top left corner of the element
  @option options [Integer] y  Y coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the
    offset will be from the element center, otherwise it will be from the top left corner of the element

@option options [Float] delay Delay between the mouse down and mouse up events in seconds (0) @return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 170
def click(*keys, **options)
  perform_click_action(keys, **options) do |k, opts|
    base.click(k, **opts)
  end
end
disabled?() click to toggle source

Whether or not the element is disabled.

@return [Boolean] Whether the element is disabled

# File lib/capybara/node/element.rb, line 346
def disabled?
  synchronize { base.disabled? }
end
double_click(*keys, **options) click to toggle source

Double Click the Element.

@macro action_waiting_behavior @macro click_modifiers @return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 197
def double_click(*keys, **options)
  perform_click_action(keys, **options) do |k, opts|
    base.double_click(k, **opts)
  end
end
drag_to(node, **options) click to toggle source

Drag the element to the given other element.

source = page.find('#foo')
target = page.find('#bar')
source.drag_to(target)

@param [Capybara::Node::Element] node The element to drag to @param [Hash] options Driver specific options for dragging. May not be supported by all drivers. @option options [Numeric] :delay (0.05) When using Chrome/Firefox with Selenium and HTML5 dragging this is the number

of seconds between each stage of the drag.

@option options [Boolean] :html5 When using Chrome/Firefox with Selenium enables to force the use of HTML5

(true) or legacy (false) dragging. If not specified the driver will attempt to
detect the correct method to use.

@option options [Array<Symbol>,Symbol] :drop_modifiers Modifier keys which should be held while the dragged element is dropped.

@return [Capybara::Node::Element] The dragged element

# File lib/capybara/node/element.rb, line 418
def drag_to(node, **options)
  synchronize { base.drag_to(node.base, **options) }
  self
end
drop(*args) click to toggle source

Drop items on the current element.

target = page.find('#foo')
target.drop('/some/path/file.csv')

@overload drop(path, …)

@param [String, #to_path] path Location of the file to drop on the element

@overload drop(strings, …)

@param [Hash] strings A hash of type to data to be dropped - `{ "text/url" => "https://www.google.com" }`

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 437
def drop(*args)
  options = args.map { |arg| arg.respond_to?(:to_path) ? arg.to_path : arg }
  synchronize { base.drop(*options) }
  self
end
evaluate_async_script(script, *args) click to toggle source

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.

@param [String] script A string of JavaScript to evaluate @return [Object] The result of the evaluated JavaScript (may be driver specific)

# File lib/capybara/node/element.rb, line 518
      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) click to toggle source

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.

@param [String] script A string of JavaScript to evaluate @return [Object] The result of the evaluated JavaScript (may be driver specific)

# File lib/capybara/node/element.rb, line 501
      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) click to toggle source

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 a result is not expected or needed. `this` in the script will refer to the element this is called on.

@param [String] script A string of JavaScript to execute @param args Optional arguments that will be passed to the script. Driver support for this is optional and types of objects supported may differ between drivers

# File lib/capybara/node/element.rb, line 484
      def execute_script(script, *args)
        session.execute_script(<<~JS, self, *args)
          (function (){
            #{script}
          }).apply(arguments[0], Array.prototype.slice.call(arguments,1));
        JS
      end
flash() click to toggle source

Toggle the elements background color between white and black for a period of time.

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 531
      def flash
        execute_script(<<~JS, 100)
          async function flash(el, delay){
            var old_bg = el.style.backgroundColor;
            var colors = ["black", "white"];
            for(var i=0; i<20; i++){
              el.style.backgroundColor = colors[i % colors.length];
              await new Promise(resolve => setTimeout(resolve, delay));
            }
            el.style.backgroundColor = old_bg;
          }
          flash(this, arguments[0]);
        JS

        self
      end
hover() click to toggle source

Hover on the Element.

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 284
def hover
  synchronize { base.hover }
  self
end
initial_cache() click to toggle source

@api private

# File lib/capybara/node/element.rb, line 575
def initial_cache
  base.respond_to?(:initial_cache) ? base.initial_cache : {}
end
inspect() click to toggle source

A human-readable representation of the element.

@return [String] A string representation

# File lib/capybara/node/element.rb, line 566
def inspect
  %(#<Capybara::Node::Element tag="#{base.tag_name}" path="#{base.path}">)
rescue NotSupportedByDriverError
  %(#<Capybara::Node::Element tag="#{base.tag_name}">)
rescue *session.driver.invalid_element_errors
  %(Obsolete #<Capybara::Node::Element>)
end
multiple?() click to toggle source

Whether or not the element supports multiple results.

@return [Boolean] Whether the element supports multiple results.

# File lib/capybara/node/element.rb, line 366
def multiple?
  synchronize { base.multiple? }
end
native() click to toggle source

@return [Object] The native element from the driver, this allows access to driver specific methods

# File lib/capybara/node/element.rb, line 42
def native
  synchronize { base.native }
end
obscured?() click to toggle source

Whether or not the element is currently in the viewport and it (or descendants) would be considered clickable at the elements center point.

@return [Boolean] Whether the elements center is obscured.

# File lib/capybara/node/element.rb, line 316
def obscured?
  synchronize { base.obscured? }
end
path() click to toggle source

An XPath expression describing where on the page the element can be found.

@return [String] An XPath expression

# File lib/capybara/node/element.rb, line 376
def path
  synchronize { base.path }
end
readonly?() click to toggle source

Whether or not the element is readonly.

@return [Boolean] Whether the element is readonly

# File lib/capybara/node/element.rb, line 356
def readonly?
  synchronize { base.readonly? }
end
rect() click to toggle source
# File lib/capybara/node/element.rb, line 380
def rect
  synchronize { base.rect }
end
reload() click to toggle source

@api private

# File lib/capybara/node/element.rb, line 549
def reload
  return self unless @allow_reload

  begin
    reloaded = @query.resolve_for(query_scope.reload)[@query_idx.to_i]
    @base = reloaded.base if reloaded
  rescue StandardError => e
    raise e unless catch_error?(e)
  end
  self
end
right_click(*keys, **options) click to toggle source

Right Click the Element.

@macro action_waiting_behavior @macro click_modifiers @option options [Float] delay Delay between the mouse down and mouse up events in seconds (0) @return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 184
def right_click(*keys, **options)
  perform_click_action(keys, **options) do |k, opts|
    base.right_click(k, **opts)
  end
end
scroll_to(pos_or_el_or_x, y = nil, align: :top, offset: nil) click to toggle source

Scroll the page or element.

@overload scroll_to(position, offset: [0,0])

Scroll the page or element to its top, bottom or middle.
@param [:top, :bottom, :center, :current] position
@param [[Integer, Integer]] offset

@overload scroll_to(element, align: :top)

Scroll the page or current element until the given element is aligned at the top, bottom, or center of it.
@param [Capybara::Node::Element] element   The element to be scrolled into view
@param [:top, :bottom, :center] align Where to align the element being scrolled into view with relation to the current page/element if possible

@overload scroll_to(x,y)

@param [Integer] x    Horizontal scroll offset
@param [Integer] y    Vertical scroll offset

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 462
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) click to toggle source

Select this node if it is an option element inside a select tag.

@!macro action_waiting_behavior

If the driver dynamic pages (JS) and the element is currently non-interactable, this method will
continuously retry the action until either the element becomes interactable or the maximum
wait time expires.

@param [false, Numeric] wait
  Maximum time to wait for the action to succeed. Defaults to {Capybara.configure default_max_wait_time}.

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 139
def select_option(wait: nil)
  synchronize(wait) { base.select_option }
  self
end
selected?() click to toggle source

Whether or not the element is selected.

@return [Boolean] Whether the element is selected

# File lib/capybara/node/element.rb, line 336
def selected?
  synchronize { base.selected? }
end
send_keys(*args) click to toggle source

Send Keystrokes to the Element.

@overload send_keys(keys, …)

@param keys [String, Symbol, Array<String,Symbol>]

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

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 274
def send_keys(*args)
  synchronize { base.send_keys(*args) }
  self
end
set(value, **options) click to toggle source

Set the value of the form element to the given value.

@param [String] value The new value @param [Hash] options Driver specific options for how to set the value. Take default values from {Capybara.configure default_set_options}.

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 117
def set(value, **options)
  if ENV['CAPYBARA_THOROUGH'] && readonly?
    raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}"
  end

  options = session_options.default_set_options.to_h.merge(options)
  synchronize { base.set(value, **options) }
  self
end
style(*styles) click to toggle source

Retrieve the given CSS styles.

element.style('color', 'font-size') # => Computed values of CSS 'color' and 'font-size' styles

@param [Array<String>] styles Names of the desired CSS properties @return [Hash] Hash of the CSS property names to computed values

# File lib/capybara/node/element.rb, line 86
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() click to toggle source

@return [String] The tag name of the element

# File lib/capybara/node/element.rb, line 293
def tag_name
  # Element type is immutable so cache it
  @tag_name ||= initial_cache[:tag_name] || synchronize { base.tag_name }
end
text(type = nil, normalize_ws: false) click to toggle source

Retrieve the text of the element. If {Capybara.configure 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.

@param type [:all, :visible] Whether to return only visible or all text @return [String] The text of the element

# File lib/capybara/node/element.rb, line 58
def text(type = nil, normalize_ws: false)
  type ||= :all unless session_options.ignore_hidden_elements || session_options.visible_text_only
  txt = synchronize { type == :all ? base.all_text : base.visible_text }
  normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt
end
trigger(event) click to toggle source

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.

@param [String] event The name of the event to trigger

@return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 394
def trigger(event)
  synchronize { base.trigger(event) }
  self
end
unselect_option(wait: nil) click to toggle source

Unselect this node if it is an option element inside a multiple select tag.

@macro action_waiting_behavior @return [Capybara::Node::Element] The element

# File lib/capybara/node/element.rb, line 150
def unselect_option(wait: nil)
  synchronize(wait) { base.unselect_option }
  self
end
value() click to toggle source

@return [String] The value of the form element

# File lib/capybara/node/element.rb, line 105
def value
  synchronize { base.value }
end
visible?() click to toggle source

Whether or not the element is visible. Not all drivers support CSS, so the result may be inaccurate.

@return [Boolean] Whether the element is visible

# File lib/capybara/node/element.rb, line 305
def visible?
  synchronize { base.visible? }
end

Private Instance Methods

perform_click_action(keys, wait: nil, **options) { |keys, options| ... } click to toggle source
# File lib/capybara/node/element.rb, line 593
def perform_click_action(keys, wait: nil, **options)
  raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ options[:x] ^ options[:y]

  options[:offset] ||= :center if session_options.w3c_click_offset
  synchronize(wait) { yield keys, options }
  self
end