Class: Capybara::Selenium::Node

Inherits:
Driver::Node show all
Includes:
Node::WhitespaceNormalizer, Find, Scroll
Defined in:
lib/capybara/selenium/node.rb,
lib/capybara/selenium/extensions/html5_drag.rb,
lib/capybara/selenium/extensions/modifier_keys_stack.rb,
lib/capybara/selenium/extensions/file_input_click_emulation.rb

Direct Known Subclasses

ChromeNode, EdgeNode, FirefoxNode, IENode, SafariNode

Defined Under Namespace

Modules: FileInputClickEmulation, Html5Drag Classes: ModifierKeysStack

Constant Summary

Constants included from Node::WhitespaceNormalizer

Node::WhitespaceNormalizer::BREAKING_SPACES, Node::WhitespaceNormalizer::EMPTY_LINES, Node::WhitespaceNormalizer::LEADING_SPACES, Node::WhitespaceNormalizer::LEFT_TO_RIGHT_MARK, Node::WhitespaceNormalizer::LINE_SEPERATOR, Node::WhitespaceNormalizer::NON_BREAKING_SPACE, Node::WhitespaceNormalizer::PARAGRAPH_SEPERATOR, Node::WhitespaceNormalizer::REMOVED_CHARACTERS, Node::WhitespaceNormalizer::RIGHT_TO_LEFT_MARK, Node::WhitespaceNormalizer::SQUEEZED_SPACES, Node::WhitespaceNormalizer::TRAILING_SPACES, Node::WhitespaceNormalizer::ZERO_WIDTH_SPACE

Instance Attribute Summary

Attributes inherited from Driver::Node

#driver, #initial_cache, #native

Instance Method Summary collapse

Methods included from Scroll

#scroll_by, #scroll_to

Methods included from Find

#find_css, #find_xpath

Methods included from Node::WhitespaceNormalizer

#normalize_spacing, #normalize_visible_spacing

Methods inherited from Driver::Node

#==, #initialize, #inspect, #scroll_by, #scroll_to, #trigger

Constructor Details

This class inherits a constructor from Capybara::Driver::Node

Instance Method Details

#[](name) ⇒ Object

 25 26 27 28 29
# File 'lib/capybara/selenium/node.rb', line 25 def [](name) native.attribute(name.to_s) rescue Selenium::WebDriver::Error::WebDriverError nil end 

#all_textObject

 20 21 22 23
# File 'lib/capybara/selenium/node.rb', line 20 def all_text text = driver.evaluate_script('arguments[0].textContent', self) || '' normalize_spacing(text) end 

#click(keys = [], **options) ⇒ Object

 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
# File 'lib/capybara/selenium/node.rb', line 106 def click(keys = [], **options) click_options = ClickOptions.new(keys, options) return native.click if click_options.empty? perform_with_options(click_options) do |action| target = click_options.coords? ? nil : native if click_options.delay.zero? action.click(target) else action.click_and_hold(target) action_pause(action, click_options.delay) action.release end end rescue StandardError => e if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) || e.message.include?('Other element would receive the click') scroll_to_center end raise e end 

#content_editable?Boolean

Returns:

  • (Boolean)
 200 201 202
# File 'lib/capybara/selenium/node.rb', line 200 def content_editable? native.attribute('isContentEditable') == 'true' end 

#disabled?Boolean

Returns:

  • (Boolean)
 193 194 195 196 197 198
# File 'lib/capybara/selenium/node.rb', line 193 def disabled? return true unless native.enabled? # WebDriver only defines `disabled?` for form controls but fieldset makes sense too find_xpath('self::fieldset/ancestor-or-self::fieldset[@disabled]').any? end 

#double_click(keys = [], **options) ⇒ Object

Raises:

  • (ArgumentError)
 144 145 146 147 148 149 150 151
# File 'lib/capybara/selenium/node.rb', line 144 def double_click(keys = [], **options) click_options = ClickOptions.new(keys, options) raise ArgumentError, "double_click doesn't support a delay option" unless click_options.delay.zero? perform_with_options(click_options) do |action| click_options.coords? ? action.double_click : action.double_click(native) end end 

#drag_to(element, drop_modifiers: []) ⇒ Object

 161 162 163 164 165 166 167 168 169 170 171 172
# File 'lib/capybara/selenium/node.rb', line 161 def drag_to(element, drop_modifiers: [], **) drop_modifiers = Array(drop_modifiers) # Due to W3C spec compliance - The Actions API no longer scrolls to elements when necessary # which means Seleniums `drag_and_drop` is now broken - do it manually scroll_if_needed { browser_action.click_and_hold(native).perform } # element.scroll_if_needed { browser_action.move_to(element.native).release.perform } element.scroll_if_needed do keys_down = modifiers_down(browser_action, drop_modifiers) keys_up = modifiers_up(keys_down.move_to(element.native).release, drop_modifiers) keys_up.perform end end 

#drop(*_) ⇒ Object

Raises:

  • (NotImplementedError)
 174 175 176
# File 'lib/capybara/selenium/node.rb', line 174 def drop(*_) raise NotImplementedError, 'Out of browser drop emulation is not implemented for the current browser' end 

#hoverObject

 157 158 159
# File 'lib/capybara/selenium/node.rb', line 157 def hover scroll_if_needed { browser_action.move_to(native).perform } end 

#multiple?Boolean

Returns:

  • (Boolean)
 189
# File 'lib/capybara/selenium/node.rb', line 189 def multiple?; boolean_attr(self[:multiple]); end 

#obscured?(x: nil, y: nil) ⇒ Boolean

Returns:

  • (Boolean)
 208 209 210 211 212 213
# File 'lib/capybara/selenium/node.rb', line 208 def obscured?(x: nil, y: nil) res = driver.evaluate_script(OBSCURED_OR_OFFSET_SCRIPT, self, x, y) return true if res == true driver.frame_obscured_at?(x: res['x'], y: res['y']) end 

#pathObject

 204 205 206
# File 'lib/capybara/selenium/node.rb', line 204 def path driver.evaluate_script GET_XPATH_SCRIPT, self end 

#readonly?Boolean

Returns:

  • (Boolean)
 188
# File 'lib/capybara/selenium/node.rb', line 188 def readonly?; boolean_attr(self[:readonly]); end 

#rectObject

 215 216 217
# File 'lib/capybara/selenium/node.rb', line 215 def rect native.rect end 

#right_click(keys = [], **options) ⇒ Object

 129 130 131 132 133 134 135 136 137 138 139 140 141 142
# File 'lib/capybara/selenium/node.rb', line 129 def right_click(keys = [], **options) click_options = ClickOptions.new(keys, options) perform_with_options(click_options) do |action| target = click_options.coords? ? nil : native if click_options.delay.zero? action.context_click(target) else action.move_to(target) if target action.pointer_down(:right).then do |act| action_pause(act, click_options.delay) end.pointer_up(:right) end end end 

#select_optionObject

 96 97 98
# File 'lib/capybara/selenium/node.rb', line 96 def select_option click unless selected? || disabled? end 

#selected?Boolean Also known as: checked?

Returns:

  • (Boolean)
 190
# File 'lib/capybara/selenium/node.rb', line 190 def selected?; boolean_attr(native.selected?); end 

#send_keys(*args) ⇒ Object

 153 154 155
# File 'lib/capybara/selenium/node.rb', line 153 def send_keys(*args) native.send_keys(*args) end 

#set(value, **options) ⇒ Object

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

Parameters:

  • value (String)

    The new value

  • options (Hash{})

    Driver specific options for how to set the value

Options Hash (**options):

  • :clear (Symbol, Array) — default: nil

    The method used to clear the previous value
    nil => clear via javascript
    :none => append the new value to the existing value
    :backspace => send backspace keystrokes to clear the field
    Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]

  • :rapid (Boolean) — default: nil

    Whether setting text inputs should use a faster "rapid" mode
    nil => Text inputs with length greater than 30 characters will be set using a faster driver script mode
    true => Rapid mode will be used regardless of input length
    false => Sends keys via conventional mode. This may be required to avoid losing key-presses if you have certain Javascript interactions on form inputs

 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
# File 'lib/capybara/selenium/node.rb', line 59 def set(value, **options) if value.is_a?(Array) && !multiple? raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" end tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase } @tag_name ||= tag_name case tag_name when 'input' case type when 'radio' click when 'checkbox' click if value ^ checked? when 'file' set_file(value) 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, **options) end when 'textarea' set_text(value, **options) else set_content_editable(value) end end 

#shadow_rootObject

 219 220 221 222
# File 'lib/capybara/selenium/node.rb', line 219 def shadow_root root = native.shadow_root root && build_node(native.shadow_root) end 

#style(styles) ⇒ Object

 39 40 41
# File 'lib/capybara/selenium/node.rb', line 39 def style(styles) styles.to_h { |style| [style, native.css_value(style)] } end 

#tag_nameObject

 178 179 180 181 182 183 184 185
# File 'lib/capybara/selenium/node.rb', line 178 def tag_name @tag_name ||= if native.respond_to? :tag_name native.tag_name.downcase else shadow_root? ? 'ShadowRoot' : 'Unknown' end end 

#unselect_optionObject

 100 101 102 103 104
# File 'lib/capybara/selenium/node.rb', line 100 def unselect_option raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select_node.multiple? click if selected? end 

#valueObject

 31 32 33 34 35 36 37
# File 'lib/capybara/selenium/node.rb', line 31 def value if tag_name == 'select' && multiple? native.find_elements(:css, 'option:checked').map { |el| el[:value] || el.text } else native[:value] end end 

#visible?Boolean

Returns:

  • (Boolean)
 187
# File 'lib/capybara/selenium/node.rb', line 187 def visible?; boolean_attr(native.displayed?); end 

#visible_textObject

Raises:

  • (NotImplementedError)
 14 15 16 17 18
# File 'lib/capybara/selenium/node.rb', line 14 def visible_text raise NotImplementedError, 'Getting visible text is not currently supported directly on shadow roots' if shadow_root? native.text end