2016-03-07 19:52:19 -05:00
# frozen_string_literal: true
2011-04-05 11:42:12 -04:00
class Capybara :: RackTest :: Node < Capybara :: Driver :: Node
2013-02-17 08:46:37 -05:00
def all_text
Capybara :: Helpers . normalize_whitespace ( native . text )
end
def visible_text
2012-08-01 07:24:43 -04:00
Capybara :: Helpers . normalize_whitespace ( unnormalized_text )
2011-04-05 11:42:12 -04:00
end
def [] ( name )
string_node [ name ]
end
def value
string_node . value
end
def set ( value )
2016-06-11 15:09:23 -04:00
if ( Array === value ) && ! multiple?
2016-12-28 19:49:45 -05:00
raise TypeError . new " Value cannot be an Array when 'multiple' attribute is not present. Not a #{ value . class } "
2012-09-17 08:48:13 -04:00
end
2013-01-09 21:19:36 -05:00
if radio?
set_radio ( value )
elsif checkbox?
set_checkbox ( value )
elsif input_field?
set_input ( value )
elsif textarea?
2014-06-11 20:14:31 -04:00
if self [ :readonly ]
warn " Attempt to set readonly element with value: #{ value } \n * This will raise an exception in a future version of Capybara "
else
native . content = value . to_s
end
2011-04-05 11:42:12 -04:00
end
end
def select_option
2015-06-05 13:59:26 -04:00
return if disabled?
2011-04-05 11:42:12 -04:00
if select_node [ 'multiple' ] != 'multiple'
2013-02-19 12:03:26 -05:00
select_node . find_xpath ( " .//option[@selected] " ) . each { | node | node . native . remove_attribute ( " selected " ) }
2011-04-05 11:42:12 -04:00
end
native [ " selected " ] = 'selected'
end
def unselect_option
if select_node [ 'multiple' ] != 'multiple'
raise Capybara :: UnselectNotAllowed , " Cannot unselect option from single select box. "
end
native . remove_attribute ( 'selected' )
end
def click
2014-06-02 19:25:53 -04:00
if tag_name == 'a' && ! self [ :href ] . nil?
2011-08-30 05:20:29 -04:00
method = self [ " data-method " ] if driver . options [ :respect_data_method ]
method || = :get
2011-04-05 11:42:12 -04:00
driver . follow ( method , self [ :href ] . to_s )
elsif ( tag_name == 'input' and %w( submit image ) . include? ( type ) ) or
( ( tag_name == 'button' ) and type . nil? or type == " submit " )
2013-04-22 12:12:35 -04:00
associated_form = form
Capybara :: RackTest :: Form . new ( driver , associated_form ) . submit ( self ) if associated_form
2016-04-21 17:25:14 -04:00
elsif ( tag_name == 'label' )
labelled_control = if native [ :for ]
find_xpath ( " //input[@id=' #{ native [ :for ] } '] " ) . first
else
find_xpath ( " .//input " ) . first
end
if labelled_control && ( labelled_control . checkbox? || labelled_control . radio? )
labelled_control . set ( ! labelled_control . checked? )
end
2011-04-05 11:42:12 -04:00
end
end
def tag_name
2011-05-17 15:21:51 -04:00
native . node_name
2011-04-05 11:42:12 -04:00
end
def visible?
string_node . visible?
end
def checked?
string_node . checked?
end
def selected?
string_node . selected?
end
2013-01-29 04:35:23 -05:00
def disabled?
2013-03-15 15:11:12 -04:00
if %w( option optgroup ) . include? tag_name
2017-01-03 16:45:49 -05:00
string_node . disabled? || find_xpath ( " parent::*[self::optgroup or self::select] " ) [ 0 ] . disabled?
2013-03-15 15:11:12 -04:00
else
2017-01-03 16:45:49 -05:00
string_node . disabled? || ! find_xpath ( " parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]] " ) . empty?
2013-03-15 15:11:12 -04:00
end
2013-01-29 04:35:23 -05:00
end
2013-03-26 16:29:25 -04:00
2011-04-05 11:42:12 -04:00
def path
native . path
end
2013-02-19 12:03:26 -05:00
def find_xpath ( locator )
2011-04-05 11:42:12 -04:00
native . xpath ( locator ) . map { | n | self . class . new ( driver , n ) }
end
2013-03-26 16:29:25 -04:00
def find_css ( locator )
2013-02-19 12:03:26 -05:00
native . css ( locator , Capybara :: RackTest :: CSSHandlers . new ) . map { | n | self . class . new ( driver , n ) }
end
2013-03-26 16:29:25 -04:00
2012-11-19 21:57:09 -05:00
def == ( other )
native == other . native
end
2012-01-06 16:22:41 -05:00
protected
2014-05-19 14:16:54 -04:00
def unnormalized_text ( check_ancestor_visibility = true )
if ! string_node . visible? ( check_ancestor_visibility )
2012-01-06 16:22:41 -05:00
''
elsif native . text?
native . text
elsif native . element?
native . children . map do | child |
2014-05-19 14:16:54 -04:00
Capybara :: RackTest :: Node . new ( driver , child ) . unnormalized_text ( false )
2012-01-06 16:22:41 -05:00
end . join
else
''
end
end
2011-04-05 11:42:12 -04:00
private
def string_node
@string_node || = Capybara :: Node :: Simple . new ( native )
end
# a reference to the select node if this is an option node
def select_node
2013-02-19 12:03:26 -05:00
find_xpath ( './ancestor::select' ) . first
2011-04-05 11:42:12 -04:00
end
def type
native [ :type ]
end
def form
2013-02-08 15:12:41 -05:00
if native [ :form ]
native . xpath ( " //form[@id=' #{ native [ :form ] } '] " ) . first
else
native . ancestors ( 'form' ) . first
end
2011-04-05 11:42:12 -04:00
end
2013-01-09 21:19:36 -05:00
2016-11-21 19:28:45 -05:00
def set_radio ( _value )
2013-01-09 21:19:36 -05:00
other_radios_xpath = XPath . generate { | x | x . anywhere ( :input ) [ x . attr ( :name ) . equals ( self [ :name ] ) ] } . to_s
driver . dom . xpath ( other_radios_xpath ) . each { | node | node . remove_attribute ( " checked " ) }
native [ 'checked' ] = 'checked'
end
def set_checkbox ( value )
if value && ! native [ 'checked' ]
native [ 'checked' ] = 'checked'
elsif ! value && native [ 'checked' ]
native . remove_attribute ( 'checked' )
end
end
def set_input ( value )
if text_or_password? && attribute_is_not_blank? ( :maxlength )
# Browser behavior for maxlength="0" is inconsistent, so we stick with
# Firefox, allowing no input
2013-03-26 16:29:25 -04:00
value = value . to_s [ 0 ... self [ :maxlength ] . to_i ]
2013-01-09 21:19:36 -05:00
end
if Array === value #Assert multiple attribute is present
value . each do | v |
new_native = native . clone
new_native . remove_attribute ( 'value' )
native . add_next_sibling ( new_native )
new_native [ 'value' ] = v . to_s
end
native . remove
else
2014-06-11 20:14:31 -04:00
if self [ :readonly ]
warn " Attempt to set readonly element with value: #{ value } \n *This will raise an exception in a future version of Capybara "
else
native [ 'value' ] = value . to_s
end
2013-01-09 21:19:36 -05:00
end
end
def attribute_is_not_blank? ( attribute )
self [ attribute ] && ! self [ attribute ] . empty?
end
2016-04-21 17:25:14 -04:00
protected
2013-01-09 21:19:36 -05:00
def checkbox?
input_field? && type == 'checkbox'
end
def input_field?
tag_name == 'input'
end
def radio?
input_field? && type == 'radio'
end
def textarea?
tag_name == " textarea "
end
def text_or_password?
input_field? && ( type == 'text' || type == 'password' )
end
2011-04-05 11:42:12 -04:00
end