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
Source
# 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
Capybara::Node::Base::new
Public Instance Methods
Source
# File lib/capybara/node/element.rb, line 73 def [](attribute) synchronize { base[attribute] } end
Retrieve the given attribute.
element[:title] # => HTML title attribute
@param [Symbol] attribute The attribute to retrieve @return [String] The value of the attribute
Source
# File lib/capybara/node/element.rb, line 33 def allow_reload!(idx = nil) @query_idx = idx @allow_reload = true end
Source
# File lib/capybara/node/element.rb, line 326 def checked? synchronize { base.checked? } end
Whether or not the element is checked.
@return [Boolean] Whether the element is checked
Source
# 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
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
Source
# File lib/capybara/node/element.rb, line 346 def disabled? synchronize { base.disabled? } end
Whether or not the element is disabled.
@return [Boolean] Whether the element is disabled
Source
# 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
Double Click the Element
.
@macro action_waiting_behavior @macro click_modifiers @return [Capybara::Node::Element] The element
Source
# File lib/capybara/node/element.rb, line 418 def drag_to(node, **options) synchronize { base.drag_to(node.base, **options) } self end
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
Source
# 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
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
Source
# File lib/capybara/node/element.rb, line 529 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 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)
Source
# File lib/capybara/node/element.rb, line 512 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
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)
Source
# File lib/capybara/node/element.rb, line 495 def execute_script(script, *args) session.execute_script(<<~JS, self, *args) (function (){ #{script} }).apply(arguments[0], Array.prototype.slice.call(arguments,1)); JS end
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
Source
# File lib/capybara/node/element.rb, line 542 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
Toggle the elements background color between white and black for a period of time.
@return [Capybara::Node::Element] The element
Source
# File lib/capybara/node/element.rb, line 284 def hover synchronize { base.hover } self end
Hover on the Element
.
@return [Capybara::Node::Element] The element
Source
# File lib/capybara/node/element.rb, line 586 def initial_cache base.respond_to?(:initial_cache) ? base.initial_cache : {} end
@api private
Source
# File lib/capybara/node/element.rb, line 577 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
A human-readable representation of the element.
@return [String] A string representation
Source
# File lib/capybara/node/element.rb, line 366 def multiple? synchronize { base.multiple? } end
Whether or not the element supports multiple results.
@return [Boolean] Whether the element supports multiple results.
Source
# File lib/capybara/node/element.rb, line 42 def native synchronize { base.native } end
@return [Object] The native element from the driver, this allows access to driver specific methods
Source
# File lib/capybara/node/element.rb, line 316 def obscured? synchronize { base.obscured? } end
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.
Source
Source
# File lib/capybara/node/element.rb, line 356 def readonly? synchronize { base.readonly? } end
Whether or not the element is readonly.
@return [Boolean] Whether the element is readonly
Source
# File lib/capybara/node/element.rb, line 560 def reload return self unless @allow_reload begin reloaded = @query.resolve_for(query_scope ? query_scope.reload : session)[@query_idx.to_i] @base = reloaded.base if reloaded rescue StandardError => e raise e unless catch_error?(e) end self end
@api private
Source
# 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
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
Source
# 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
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
Source
# File lib/capybara/node/element.rb, line 139 def select_option(wait: nil) synchronize(wait) { base.select_option } self end
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
Source
# File lib/capybara/node/element.rb, line 336 def selected? synchronize { base.selected? } end
Whether or not the element is selected.
@return [Boolean] Whether the element is selected
Source
# File lib/capybara/node/element.rb, line 274 def send_keys(*args) synchronize { base.send_keys(*args) } self end
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
Source
# File lib/capybara/node/element.rb, line 117 def set(value, **options) if ENV.fetch('CAPYBARA_THOROUGH', nil) && 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
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
Source
# File lib/capybara/node/element.rb, line 481 def shadow_root root = synchronize { base.shadow_root } root && Capybara::Node::Element.new(session, root, nil, nil) end
Return the shadow_root
for the current element
@return [Capybara::Node::Element] The shadow root
Source
# 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
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
Source
# 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
@return [String] The tag name of the element
Source
# 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
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
Source
# File lib/capybara/node/element.rb, line 394 def trigger(event) synchronize { base.trigger(event) } self end
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
Source
# File lib/capybara/node/element.rb, line 150 def unselect_option(wait: nil) synchronize(wait) { base.unselect_option } self end
Unselect this node if it is an option element inside a multiple select tag.
@macro action_waiting_behavior @return [Capybara::Node::Element] The element
Source
# File lib/capybara/node/element.rb, line 105 def value synchronize { base.value } end
@return [String] The value of the form element
Source
# File lib/capybara/node/element.rb, line 305 def visible? synchronize { base.visible? } end
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
Private Instance Methods
Source
# File lib/capybara/node/element.rb, line 604 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