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

Direct Known Subclasses

ChromeNode, FirefoxNode, IENode, SafariNode

Defined Under Namespace

Modules: Html5Drag

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



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

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



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/capybara/selenium/node.rb', line 97

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)


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

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

#disabled?Boolean

Returns:

  • (Boolean)


154
155
156
157
158
159
# File 'lib/capybara/selenium/node.rb', line 154

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



118
119
120
121
122
123
# File 'lib/capybara/selenium/node.rb', line 118

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



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

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)


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

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

#hoverObject



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

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

#multiple?Boolean

Returns:

  • (Boolean)


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

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

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

Returns:

  • (Boolean)


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

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



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

def path
  driver.evaluate_script GET_XPATH_SCRIPT, self
end

#readonly?Boolean

Returns:

  • (Boolean)


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

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

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



111
112
113
114
115
116
# File 'lib/capybara/selenium/node.rb', line 111

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



87
88
89
# File 'lib/capybara/selenium/node.rb', line 87

def select_option
  click unless selected? || disabled?
end

#selected?Boolean Also known as: checked?

Returns:

  • (Boolean)


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

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

#send_keys(*args) ⇒ Object



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

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]

Raises:

  • (ArgumentError)


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

def set(value, **options)
  raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" if value.is_a?(Array) && !multiple?

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



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

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

#unselect_optionObject



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

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)


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

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