Class: Capybara::Selenium::Node

Inherits:
Driver::Node show all
Includes:
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

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 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

#==(other) ⇒ Object


169
170
171
# File 'lib/capybara/selenium/node.rb', line 169

def ==(other)
  native == other.native
end

#[](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


16
17
18
19
20
21
22
23
# File 'lib/capybara/selenium/node.rb', line 16

def all_text
  text = driver.evaluate_script('arguments[0].textContent', self)
  text.gsub(/[\u200b\u200e\u200f]/, '')
      .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
      .gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
      .gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
      .tr("\u00a0", ' ')
end

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


101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/capybara/selenium/node.rb', line 101

def click(keys = [], **options)
  click_options = ClickOptions.new(keys, options)
  return native.click if click_options.empty?

  click_with_options(click_options)
rescue StandardError => e
  if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||
     e.message.match?(/Other element would receive the click/)
    scroll_to_center
  end

  raise e
end

#content_editable?Boolean

Returns:

  • (Boolean)

165
166
167
# File 'lib/capybara/selenium/node.rb', line 165

def content_editable?
  native.attribute('isContentEditable') == 'true'
end

#disabled?Boolean

Returns:

  • (Boolean)

158
159
160
161
162
163
# File 'lib/capybara/selenium/node.rb', line 158

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


122
123
124
125
126
127
# File 'lib/capybara/selenium/node.rb', line 122

def double_click(keys = [], **options)
  click_options = ClickOptions.new(keys, options)
  click_with_options(click_options) do |action|
    click_options.coords? ? action.double_click : action.double_click(native)
  end
end

#drag_to(element) ⇒ Object


137
138
139
140
141
142
# File 'lib/capybara/selenium/node.rb', line 137

def drag_to(element, **)
  # 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 }
end

#drop(*_) ⇒ Object

Raises:

  • (NotImplementedError)

144
145
146
# File 'lib/capybara/selenium/node.rb', line 144

def drop(*_)
  raise NotImplementedError, 'Out of browser drop emulation is not implemented for the current browser'
end

#hoverObject


133
134
135
# File 'lib/capybara/selenium/node.rb', line 133

def hover
  scroll_if_needed { browser_action.move_to(native).perform }
end

#multiple?Boolean

Returns:

  • (Boolean)

154
# File 'lib/capybara/selenium/node.rb', line 154

def multiple?; boolean_attr(self[:multiple]); end

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

Returns:

  • (Boolean)

177
178
179
180
181
182
# File 'lib/capybara/selenium/node.rb', line 177

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


173
174
175
# File 'lib/capybara/selenium/node.rb', line 173

def path
  driver.evaluate_script GET_XPATH_SCRIPT, self
end

#readonly?Boolean

Returns:

  • (Boolean)

153
# File 'lib/capybara/selenium/node.rb', line 153

def readonly?; boolean_attr(self[:readonly]); end

#rectObject


184
185
186
# File 'lib/capybara/selenium/node.rb', line 184

def rect
  native.rect
end

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


115
116
117
118
119
120
# File 'lib/capybara/selenium/node.rb', line 115

def right_click(keys = [], **options)
  click_options = ClickOptions.new(keys, options)
  click_with_options(click_options) do |action|
    click_options.coords? ? action.context_click : action.context_click(native)
  end
end

#select_optionObject


91
92
93
# File 'lib/capybara/selenium/node.rb', line 91

def select_option
  click unless selected? || disabled?
end

#selected?Boolean Also known as: checked?

Returns:

  • (Boolean)

155
# File 'lib/capybara/selenium/node.rb', line 155

def selected?; boolean_attr(native.selected?); end

#send_keys(*args) ⇒ Object


129
130
131
# File 'lib/capybara/selenium/node.rb', line 129

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]


56
57
58
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
# File 'lib/capybara/selenium/node.rb', line 56

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)
    else
      set_text(value, options)
    end
  when 'textarea'
    set_text(value, options)
  else
    set_content_editable(value)
  end
end

#style(styles) ⇒ Object


39
40
41
42
43
# File 'lib/capybara/selenium/node.rb', line 39

def style(styles)
  styles.each_with_object({}) do |style, result|
    result[style] = native.css_value(style)
  end
end

#tag_nameObject


148
149
150
# File 'lib/capybara/selenium/node.rb', line 148

def tag_name
  @tag_name ||= native.tag_name.downcase
end

#unselect_optionObject


95
96
97
98
99
# File 'lib/capybara/selenium/node.rb', line 95

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)

152
# File 'lib/capybara/selenium/node.rb', line 152

def visible?; boolean_attr(native.displayed?); end

#visible_textObject


12
13
14
# File 'lib/capybara/selenium/node.rb', line 12

def visible_text
  native.text
end