2016-03-08 00:52:19 +00:00
# frozen_string_literal: true
2018-01-08 20:23:54 +00:00
2016-08-18 20:27:35 +00:00
require 'capybara/selector/selector'
2016-04-27 05:44:48 +00:00
Capybara :: Selector :: FilterSet . add ( :_field ) do
2018-01-09 22:05:50 +00:00
filter ( :checked , :boolean ) { | node , value | ! ( value ^ node . checked? ) }
2016-08-29 18:40:53 +00:00
filter ( :unchecked , :boolean ) { | node , value | ( value ^ node . checked? ) }
2018-01-09 22:05:50 +00:00
filter ( :disabled , :boolean , default : false , skip_if : :all ) { | node , value | ! ( value ^ node . disabled? ) }
2016-08-29 18:40:53 +00:00
filter ( :multiple , :boolean ) { | node , value | ! ( value ^ node . multiple? ) }
2016-04-27 05:44:48 +00:00
2018-01-03 01:46:41 +00:00
expression_filter ( :name ) { | xpath , val | xpath [ XPath . attr ( :name ) == val ] }
2018-01-09 22:05:50 +00:00
expression_filter ( :placeholder ) { | xpath , val | xpath [ XPath . attr ( :placeholder ) == val ] }
2016-10-05 22:16:00 +00:00
2017-11-13 21:04:47 +00:00
describe do | checked : nil , unchecked : nil , disabled : nil , multiple : nil , ** _options |
2018-01-09 22:05:50 +00:00
desc , states = " " . dup , [ ]
2017-05-02 01:39:08 +00:00
states << 'checked' if checked || ( unchecked == false )
states << 'not checked' if unchecked || ( checked == false )
states << 'disabled' if disabled == true
states << 'not disabled' if disabled == false
2016-04-27 05:44:48 +00:00
desc << " that is #{ states . join ( ' and ' ) } " unless states . empty?
2017-05-02 01:39:08 +00:00
desc << " with the multiple attribute " if multiple == true
desc << " without the multiple attribute " if multiple == false
2016-04-27 05:44:48 +00:00
desc
end
end
2018-01-08 20:23:54 +00:00
# rubocop:disable Metrics/BlockLength
# rubocop:disable Metrics/ParameterLists
2016-09-09 23:44:32 +00:00
##
#
# Select elements by XPath expression
2016-09-08 18:01:22 +00:00
#
# @locator An XPath expression
#
2016-08-18 20:27:35 +00:00
Capybara . add_selector ( :xpath ) do
xpath { | xpath | xpath }
end
2016-09-09 23:44:32 +00:00
##
#
# Select elements by CSS selector
2016-09-08 18:01:22 +00:00
#
# @locator A CSS selector
#
2016-08-18 20:27:35 +00:00
Capybara . add_selector ( :css ) do
css { | css | css }
end
2016-09-09 23:44:32 +00:00
##
#
# Select element by id
2016-09-08 18:01:22 +00:00
#
# @locator The id of the element to match
#
2016-08-18 20:27:35 +00:00
Capybara . add_selector ( :id ) do
xpath { | id | XPath . descendant [ XPath . attr ( :id ) == id . to_s ] }
end
2016-09-19 21:47:41 +00:00
2016-09-09 23:44:32 +00:00
##
#
# Select field elements (input [not of type submit, image, or hidden], textarea, select)
2016-09-08 18:01:22 +00:00
#
# @locator Matches against the id, name, or placeholder
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String] :placeholder Matches the placeholder attribute
# @filter [String] :type Matches the type attribute of the field or element type for 'textarea' and 'select'
# @filter [Boolean] :readonly
# @filter [String] :with Matches the current value of the field
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :checked Match checked fields?
# @filter [Boolean] :unchecked Match unchecked fields?
# @filter [Boolean] :disabled Match disabled field?
# @filter [Boolean] :multiple Match fields that accept multiple values
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :field ) do
2016-11-14 02:32:23 +00:00
xpath do | locator , ** options |
2018-01-03 01:46:41 +00:00
xpath = XPath . descendant ( :input , :textarea , :select ) [ ! XPath . attr ( :type ) . one_of ( 'submit' , 'image' , 'hidden' ) ]
2016-10-05 22:16:00 +00:00
locate_field ( xpath , locator , options )
end
expression_filter ( :type ) do | expr , type |
type = type . to_s
2018-01-09 22:05:50 +00:00
if %w[ textarea select ] . include? ( type )
2017-05-25 22:55:34 +00:00
expr . self ( type . to_sym )
2016-10-05 22:16:00 +00:00
else
2018-01-03 01:46:41 +00:00
expr [ XPath . attr ( :type ) == type ]
2016-08-18 20:27:35 +00:00
end
2016-03-24 18:18:12 +00:00
end
2016-04-26 15:51:22 +00:00
2016-10-05 22:16:00 +00:00
filter_set ( :_field ) # checked/unchecked/disabled/multiple/name/placeholder
2016-04-26 15:51:22 +00:00
2018-01-09 22:05:50 +00:00
filter ( :readonly , :boolean ) { | node , value | ! ( value ^ node . readonly? ) }
2016-07-28 08:25:24 +00:00
filter ( :with ) do | node , with |
with . is_a? ( Regexp ) ? node . value =~ with : node . value == with . to_s
end
2017-05-02 01:39:08 +00:00
describe do | type : nil , ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
( expression_filters . keys - [ :type ] ) . each { | ef | desc << " with #{ ef } #{ options [ ef ] } " if options . key? ( ef ) }
2017-05-02 01:39:08 +00:00
desc << " of type #{ type . inspect } " if type
2018-01-09 22:05:50 +00:00
desc << " with value #{ options [ :with ] . to_s . inspect } " if options . key? ( :with )
2014-07-02 18:17:53 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Select fieldset elements
2016-09-08 18:01:22 +00:00
#
# @locator Matches id or contents of wrapped legend
#
# @filter [String] :id Matches id attribute
# @filter [String] :legend Matches contents of wrapped legend
# @filter [String, Array<String>] :class Matches the class(es) provided
#
2011-08-27 21:57:12 +00:00
Capybara . add_selector ( :fieldset ) do
2017-11-13 21:04:47 +00:00
xpath ( :legend ) do | locator , legend : nil , ** _options |
2016-03-24 18:18:12 +00:00
xpath = XPath . descendant ( :fieldset )
2018-01-03 01:46:41 +00:00
xpath = xpath [ ( XPath . attr ( :id ) == locator . to_s ) | XPath . child ( :legend ) [ XPath . string . n . is ( locator . to_s ) ] ] unless locator . nil?
2016-11-14 02:32:23 +00:00
xpath = xpath [ XPath . child ( :legend ) [ XPath . string . n . is ( legend ) ] ] if legend
2016-03-24 18:18:12 +00:00
xpath
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find links ( <a> elements with an href attribute )
2016-09-08 18:01:22 +00:00
#
# @locator Matches the id or title attributes, or the string content of the link, or the alt attribute of a contained img element
#
# @filter [String] :id Matches the id attribute
# @filter [String] :title Matches the title attribute
# @filter [String] :alt Matches the alt attribute of a contained img element
# @filter [String] :class Matches the class(es) provided
2016-12-15 18:59:01 +00:00
# @filter [String, Regexp,nil] :href Matches the normalized href of the link, if nil will find <a> elements with no href attribute
2016-09-08 18:01:22 +00:00
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :link ) do
2017-11-13 21:04:47 +00:00
xpath ( :title , :alt ) do | locator , href : true , enable_aria_label : false , alt : nil , title : nil , ** _options |
2016-12-15 18:59:01 +00:00
xpath = XPath . descendant ( :a )
2016-11-14 02:32:23 +00:00
xpath = if href . nil?
2018-01-03 01:46:41 +00:00
xpath [ ! XPath . attr ( :href ) ]
2016-12-15 18:59:01 +00:00
else
xpath [ XPath . attr ( :href ) ]
end
2016-03-24 18:18:12 +00:00
unless locator . nil?
locator = locator . to_s
2018-01-12 00:45:50 +00:00
matchers = [ XPath . attr ( :id ) == locator ,
2018-01-08 20:23:54 +00:00
XPath . string . n . is ( locator ) ,
XPath . attr ( :title ) . is ( locator ) ,
XPath . descendant ( :img ) [ XPath . attr ( :alt ) . is ( locator ) ] ] . reduce ( :| )
2018-01-12 00:45:50 +00:00
matchers |= XPath . attr ( :'aria-label' ) . is ( locator ) if enable_aria_label
2016-08-03 20:16:30 +00:00
xpath = xpath [ matchers ]
2016-03-24 18:18:12 +00:00
end
2017-05-02 01:39:08 +00:00
xpath = xpath [ find_by_attr ( :title , title ) ]
2018-01-03 01:46:41 +00:00
xpath = xpath [ XPath . descendant ( :img ) [ XPath . attr ( :alt ) == alt ] ] if alt
2016-03-24 18:18:12 +00:00
xpath
end
2015-08-25 21:25:42 +00:00
filter ( :href ) do | node , href |
2016-12-15 18:59:01 +00:00
case href
when nil
true
when Regexp
2015-04-28 00:33:39 +00:00
node [ :href ] . match href
else
2018-01-03 01:46:41 +00:00
node . first ( :xpath , XPath . self [ XPath . attr ( :href ) == href . to_s ] , minimum : 0 )
2015-04-28 00:33:39 +00:00
end
2012-01-03 08:43:11 +00:00
end
2016-03-24 18:18:12 +00:00
2017-05-02 01:39:08 +00:00
describe do | ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2016-12-15 18:59:01 +00:00
desc << " with href #{ options [ :href ] . inspect } " if options [ :href ]
desc << " with no href attribute " if options . fetch ( :href , true ) . nil?
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find buttons ( input [of type submit, reset, image, button] or button elements )
#
2016-09-30 03:23:05 +00:00
# @locator Matches the id, value, or title attributes, string content of a button, or the alt attribute of an image type button or of a descendant image of a button
2016-09-19 21:47:41 +00:00
#
# @filter [String] :id Matches the id attribute
# @filter [String] :title Matches the title attribute
# @filter [String] :class Matches the class(es) provided
# @filter [String] :value Matches the value of an input button
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :button ) do
2016-11-14 02:32:23 +00:00
xpath ( :value , :title ) do | locator , ** options |
2016-03-24 18:18:12 +00:00
input_btn_xpath = XPath . descendant ( :input ) [ XPath . attr ( :type ) . one_of ( 'submit' , 'reset' , 'image' , 'button' ) ]
btn_xpath = XPath . descendant ( :button )
2018-01-03 01:46:41 +00:00
image_btn_xpath = XPath . descendant ( :input ) [ XPath . attr ( :type ) == 'image' ]
2016-03-24 18:18:12 +00:00
unless locator . nil?
locator = locator . to_s
2018-01-03 01:46:41 +00:00
locator_matches = XPath . attr ( :id ) . equals ( locator ) | XPath . attr ( :value ) . is ( locator ) | XPath . attr ( :title ) . is ( locator )
2018-01-12 00:45:50 +00:00
locator_matches |= XPath . attr ( :'aria-label' ) . is ( locator ) if options [ :enable_aria_label ]
2016-08-03 20:16:30 +00:00
input_btn_xpath = input_btn_xpath [ locator_matches ]
2018-01-03 01:46:41 +00:00
btn_xpath = btn_xpath [ locator_matches | XPath . string . n . is ( locator ) | XPath . descendant ( :img ) [ XPath . attr ( :alt ) . is ( locator ) ] ]
2016-08-03 20:16:30 +00:00
alt_matches = XPath . attr ( :alt ) . is ( locator )
2018-01-12 00:45:50 +00:00
alt_matches |= XPath . attr ( :'aria-label' ) . is ( locator ) if options [ :enable_aria_label ]
2016-08-03 20:16:30 +00:00
image_btn_xpath = image_btn_xpath [ alt_matches ]
2016-03-24 18:18:12 +00:00
end
2017-05-30 22:51:15 +00:00
res_xpath = input_btn_xpath . union ( btn_xpath ) . union ( image_btn_xpath )
2016-08-18 20:27:35 +00:00
2016-10-05 22:16:00 +00:00
res_xpath = expression_filters . keys . inject ( res_xpath ) { | memo , ef | memo [ find_by_attr ( ef , options [ ef ] ) ] }
2016-08-18 20:27:35 +00:00
res_xpath
2016-03-24 18:18:12 +00:00
end
2018-01-09 22:05:50 +00:00
filter ( :disabled , :boolean , default : false , skip_if : :all ) { | node , value | ! ( value ^ node . disabled? ) }
2016-03-24 18:18:12 +00:00
2017-05-02 01:39:08 +00:00
describe do | disabled : nil , ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " that is disabled " if disabled == true
2016-11-22 00:28:45 +00:00
desc << describe_all_expression_filters ( options )
2016-08-18 20:27:35 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find links or buttons
#
2016-03-24 18:18:12 +00:00
Capybara . add_selector ( :link_or_button ) do
label " link or button "
2017-05-02 01:39:08 +00:00
xpath do | locator , ** options |
2018-01-09 22:05:50 +00:00
self . class . all . values_at ( :link , :button ) . map { | selector | selector . xpath . call ( locator , options ) } . reduce ( :union )
2016-03-24 18:18:12 +00:00
end
2018-01-09 22:05:50 +00:00
filter ( :disabled , :boolean , default : false , skip_if : :all ) { | node , value | node . tag_name == " a " or ! ( value ^ node . disabled? ) }
2016-03-24 18:18:12 +00:00
2017-11-13 21:04:47 +00:00
describe { | disabled : nil , ** _options | " that is disabled " if disabled == true }
2016-03-24 18:18:12 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
#
2016-09-19 21:47:41 +00:00
# @locator Matches against the id, name, or placeholder
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String] :placeholder Matches the placeholder attribute
# @filter [String] :with Matches the current value of the field
2017-04-25 01:50:14 +00:00
# @filter [String] :type Matches the type attribute of the field or element type for 'textarea'
2016-09-19 21:47:41 +00:00
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :disabled Match disabled field?
# @filter [Boolean] :multiple Match fields that accept multiple values
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :fillable_field ) do
2012-06-08 15:07:12 +00:00
label " field "
2017-05-02 01:39:08 +00:00
xpath do | locator , ** options |
2018-01-03 01:46:41 +00:00
xpath = XPath . descendant ( :input , :textarea ) [ ! XPath . attr ( :type ) . one_of ( 'submit' , 'image' , 'radio' , 'checkbox' , 'hidden' , 'file' ) ]
2016-08-18 20:27:35 +00:00
locate_field ( xpath , locator , options )
2016-03-24 18:18:12 +00:00
end
2016-10-05 22:16:00 +00:00
expression_filter ( :type ) do | expr , type |
type = type . to_s
if [ 'textarea' ] . include? ( type )
2017-05-25 22:55:34 +00:00
expr . self ( type . to_sym )
2016-10-05 22:16:00 +00:00
else
2018-01-03 01:46:41 +00:00
expr [ XPath . attr ( :type ) == type ]
2016-10-05 22:16:00 +00:00
end
end
2018-01-08 20:23:54 +00:00
filter_set ( :_field , % i [ disabled multiple name placeholder ] )
2016-08-18 20:27:35 +00:00
2016-09-19 21:47:41 +00:00
filter ( :with ) do | node , with |
with . is_a? ( Regexp ) ? node . value =~ with : node . value == with . to_s
end
2016-08-18 20:27:35 +00:00
describe do | options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2016-11-22 00:28:45 +00:00
desc << describe_all_expression_filters ( options )
2018-01-09 22:05:50 +00:00
desc << " with value #{ options [ :with ] . to_s . inspect } " if options . key? ( :with )
2016-08-18 20:27:35 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find radio buttons
#
2016-09-19 21:47:41 +00:00
# @locator Match id, name, or associated label text
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :checked Match checked fields?
# @filter [Boolean] :unchecked Match unchecked fields?
# @filter [Boolean] :disabled Match disabled field?
# @filter [String] :option Match the value
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :radio_button ) do
2012-06-08 15:07:12 +00:00
label " radio button "
2017-05-02 01:39:08 +00:00
xpath do | locator , ** options |
2018-01-03 01:46:41 +00:00
xpath = XPath . descendant ( :input ) [ XPath . attr ( :type ) == 'radio' ]
2016-08-18 20:27:35 +00:00
locate_field ( xpath , locator , options )
2016-03-24 18:18:12 +00:00
end
2018-01-08 20:23:54 +00:00
filter_set ( :_field , % i [ checked unchecked disabled name ] )
2016-04-26 15:51:22 +00:00
2018-01-09 22:05:50 +00:00
filter ( :option ) { | node , value | node . value == value . to_s }
2016-03-24 18:18:12 +00:00
2017-09-21 17:28:03 +00:00
describe do | option : nil , ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " with value #{ option . inspect } " if option
2016-11-22 00:28:45 +00:00
desc << describe_all_expression_filters ( options )
2014-07-02 18:17:53 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find checkboxes
#
2016-09-19 21:47:41 +00:00
# @locator Match id, name, or associated label text
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :checked Match checked fields?
# @filter [Boolean] :unchecked Match unchecked fields?
# @filter [Boolean] :disabled Match disabled field?
# @filter [String] :option Match the value
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :checkbox ) do
2017-05-02 01:39:08 +00:00
xpath do | locator , ** options |
2018-01-03 01:46:41 +00:00
xpath = XPath . descendant ( :input ) [ XPath . attr ( :type ) == 'checkbox' ]
2016-08-18 20:27:35 +00:00
locate_field ( xpath , locator , options )
2016-03-24 18:18:12 +00:00
end
2018-01-08 20:23:54 +00:00
filter_set ( :_field , % i [ checked unchecked disabled name ] )
2016-04-26 15:51:22 +00:00
2018-01-09 22:05:50 +00:00
filter ( :option ) { | node , value | node . value == value . to_s }
2016-03-24 18:18:12 +00:00
2017-05-02 01:39:08 +00:00
describe do | option : nil , ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " with value #{ option . inspect } " if option
2016-11-22 00:28:45 +00:00
desc << describe_all_expression_filters ( options )
2014-07-02 18:17:53 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find select elements
#
2016-09-19 21:47:41 +00:00
# @locator Match id, name, placeholder, or associated label text
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String] :placeholder Matches the placeholder attribute
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :disabled Match disabled field?
# @filter [Boolean] :multiple Match fields that accept multiple values
# @filter [Array<String>] :options Exact match options
# @filter [Array<String>] :with_options Partial match options
# @filter [String, Array<String>] :selected Match the selection(s)
2017-06-04 13:51:29 +00:00
# @filter [String, Array<String>] :with_selected Partial match the selection(s)
2016-09-19 21:47:41 +00:00
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :select ) do
2012-06-08 15:07:12 +00:00
label " select box "
2017-05-02 01:39:08 +00:00
xpath do | locator , ** options |
2016-03-24 18:18:12 +00:00
xpath = XPath . descendant ( :select )
2016-08-18 20:27:35 +00:00
locate_field ( xpath , locator , options )
2016-03-24 18:18:12 +00:00
end
2018-01-08 20:23:54 +00:00
filter_set ( :_field , % i [ disabled multiple name placeholder ] )
2016-04-26 15:51:22 +00:00
2012-03-16 03:14:47 +00:00
filter ( :options ) do | node , options |
2018-01-08 20:23:54 +00:00
actual = if node . visible?
2018-01-09 22:05:50 +00:00
node . all ( :xpath , './/option' , wait : false ) . map ( & :text )
2015-10-06 20:42:45 +00:00
else
2018-01-08 20:23:54 +00:00
node . all ( :xpath , './/option' , visible : false , wait : false ) . map { | option | option . text ( :all ) }
2015-10-06 20:42:45 +00:00
end
2012-03-16 03:14:47 +00:00
options . sort == actual . sort
end
2016-10-07 01:04:14 +00:00
2015-10-06 20:42:45 +00:00
filter ( :with_options ) do | node , options |
finder_settings = { minimum : 0 }
2018-01-09 22:05:50 +00:00
finder_settings [ :visible ] = false unless node . visible?
2015-10-06 20:42:45 +00:00
options . all? { | option | node . first ( :option , option , finder_settings ) }
end
2016-10-07 01:04:14 +00:00
2012-01-02 16:12:21 +00:00
filter ( :selected ) do | node , selected |
2017-11-14 20:14:24 +00:00
actual = node . all ( :xpath , './/option' , visible : false , wait : false ) . select ( & :selected? ) . map { | option | option . text ( :all ) }
2017-06-04 13:51:29 +00:00
Array ( selected ) . sort == actual . sort
end
filter ( :with_selected ) do | node , selected |
2017-11-14 20:14:24 +00:00
actual = node . all ( :xpath , './/option' , visible : false , wait : false ) . select ( & :selected? ) . map { | option | option . text ( :all ) }
2017-06-04 13:51:29 +00:00
( Array ( selected ) - actual ) . empty?
2012-01-02 16:12:21 +00:00
end
2016-03-24 18:18:12 +00:00
2017-05-02 01:39:08 +00:00
describe do | options : nil , with_options : nil , selected : nil , with_selected : nil , ** opts |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " with options #{ options . inspect } " if options
desc << " with at least options #{ with_options . inspect } " if with_options
desc << " with #{ selected . inspect } selected " if selected
desc << " with at least #{ with_selected . inspect } selected " if with_selected
desc << describe_all_expression_filters ( opts )
2014-07-02 18:17:53 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find option elements
#
2016-09-19 21:47:41 +00:00
# @locator Match text of option
# @filter [Boolean] :disabled Match disabled option
# @filter [Boolean] :selected Match selected option
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :option ) do
2016-03-24 18:18:12 +00:00
xpath do | locator |
xpath = XPath . descendant ( :option )
xpath = xpath [ XPath . string . n . is ( locator . to_s ) ] unless locator . nil?
xpath
end
2016-03-24 21:50:42 +00:00
2018-01-09 22:05:50 +00:00
filter ( :disabled , :boolean ) { | node , value | ! ( value ^ node . disabled? ) }
filter ( :selected , :boolean ) { | node , value | ! ( value ^ node . selected? ) }
2016-03-24 21:50:42 +00:00
2017-05-02 01:39:08 +00:00
describe do | ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
desc << " that is #{ ' not' unless options [ :disabled ] } disabled " if options . key? ( :disabled )
desc << " that is #{ ' not' unless options [ :selected ] } selected " if options . key? ( :selected )
2016-03-24 21:50:42 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find file input elements
#
2016-09-19 21:47:41 +00:00
# @locator Match id, name, or associated label text
# @filter [String] :id Matches the id attribute
# @filter [String] :name Matches the name attribute
# @filter [String, Array<String>] :class Matches the class(es) provided
# @filter [Boolean] :disabled Match disabled field?
# @filter [Boolean] :multiple Match field that accepts multiple values
#
2011-08-27 02:16:15 +00:00
Capybara . add_selector ( :file_field ) do
2012-06-08 15:07:12 +00:00
label " file field "
2016-10-05 22:16:00 +00:00
xpath do | locator , options |
2018-01-03 01:46:41 +00:00
xpath = XPath . descendant ( :input ) [ XPath . attr ( :type ) == 'file' ]
2016-08-18 20:27:35 +00:00
locate_field ( xpath , locator , options )
2016-03-24 18:18:12 +00:00
end
2018-01-08 20:23:54 +00:00
filter_set ( :_field , % i [ disabled multiple name ] )
2016-08-18 20:27:35 +00:00
2017-05-02 01:39:08 +00:00
describe do | ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2016-11-22 00:28:45 +00:00
desc << describe_all_expression_filters ( options )
2016-08-18 20:27:35 +00:00
desc
end
2011-08-27 02:16:15 +00:00
end
2011-08-27 21:54:55 +00:00
2016-09-09 23:44:32 +00:00
##
#
# Find label elements
#
2016-09-19 21:47:41 +00:00
# @locator Match id or text contents
# @filter [Element, String] :for The element or id of the element associated with the label
#
2016-04-06 17:59:11 +00:00
Capybara . add_selector ( :label ) do
label " label "
2016-09-28 18:49:08 +00:00
xpath ( :for ) do | locator , options |
2016-04-06 17:59:11 +00:00
xpath = XPath . descendant ( :label )
2018-01-03 01:46:41 +00:00
xpath = xpath [ XPath . string . n . is ( locator . to_s ) | ( XPath . attr ( :id ) == locator . to_s ) ] unless locator . nil?
2018-01-09 22:05:50 +00:00
if options . key? ( :for ) && ! options [ :for ] . is_a? ( Capybara :: Node :: Element )
2018-01-12 00:45:50 +00:00
with_attr = XPath . attr ( :for ) == options [ :for ] . to_s
2018-01-09 22:05:50 +00:00
labelable_elements = % i [ button input keygen meter output progress select textarea ]
2018-01-03 01:46:41 +00:00
wrapped = ! XPath . attr ( :for ) &
XPath . descendant ( * labelable_elements ) [ XPath . attr ( :id ) == options [ :for ] . to_s ]
xpath = xpath [ with_attr | wrapped ]
2016-09-28 18:49:08 +00:00
end
2016-04-06 17:59:11 +00:00
xpath
end
filter ( :for ) do | node , field_or_value |
if field_or_value . is_a? Capybara :: Node :: Element
2016-09-28 18:49:08 +00:00
if node [ :for ]
field_or_value [ :id ] == node [ :for ]
2016-04-06 17:59:11 +00:00
else
2016-04-06 21:20:23 +00:00
field_or_value . find_xpath ( './ancestor::label[1]' ) . include? node . base
2016-04-06 17:59:11 +00:00
end
else
2018-01-09 22:05:50 +00:00
# Non element values were handled through the expression filter
2016-09-28 18:49:08 +00:00
true
2016-04-06 17:59:11 +00:00
end
end
2016-04-21 21:25:14 +00:00
2017-05-02 01:39:08 +00:00
describe do | ** options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2016-04-21 21:25:14 +00:00
desc << " for #{ options [ :for ] } " if options [ :for ]
2016-04-27 05:44:48 +00:00
desc
2016-04-21 21:25:14 +00:00
end
2016-04-06 17:59:11 +00:00
end
2016-09-09 23:44:32 +00:00
##
#
# Find table elements
#
2016-09-19 21:47:41 +00:00
# @locator id or caption text of table
# @filter [String] :id Match id attribute of table
# @filter [String] :caption Match text of associated caption
# @filter [String, Array<String>] :class Matches the class(es) provided
#
2011-08-27 21:54:55 +00:00
Capybara . add_selector ( :table ) do
2016-09-22 23:55:54 +00:00
xpath ( :caption ) do | locator , options |
2016-03-24 18:18:12 +00:00
xpath = XPath . descendant ( :table )
2018-01-03 01:46:41 +00:00
xpath = xpath [ ( XPath . attr ( :id ) == locator . to_s ) | XPath . descendant ( :caption ) . is ( locator . to_s ) ] unless locator . nil?
xpath = xpath [ XPath . descendant ( :caption ) == options [ :caption ] ] if options [ :caption ]
2016-03-24 18:18:12 +00:00
xpath
end
2016-08-18 20:27:35 +00:00
2017-11-13 21:04:47 +00:00
describe do | caption : nil , ** _options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " with caption #{ caption } " if caption
2016-08-18 20:27:35 +00:00
desc
end
2011-08-27 21:54:55 +00:00
end
2016-07-18 20:17:22 +00:00
2016-09-09 23:44:32 +00:00
##
#
# Find frame/iframe elements
#
2016-09-19 21:47:41 +00:00
# @locator Match id or name
# @filter [String] :id Match id attribute
# @filter [String] :name Match name attribute
# @filter [String, Array<String>] :class Matches the class(es) provided
#
2016-07-18 20:17:22 +00:00
Capybara . add_selector ( :frame ) do
2017-05-02 01:39:08 +00:00
xpath ( :name ) do | locator , ** options |
2017-05-30 22:51:15 +00:00
xpath = XPath . descendant ( :iframe ) . union ( XPath . descendant ( :frame ) )
2018-01-03 01:46:41 +00:00
xpath = xpath [ ( XPath . attr ( :id ) == locator . to_s ) | ( XPath . attr ( :name ) == locator . to_s ) ] unless locator . nil?
2016-10-05 22:16:00 +00:00
xpath = expression_filters . keys . inject ( xpath ) { | memo , ef | memo [ find_by_attr ( ef , options [ ef ] ) ] }
2016-07-18 20:17:22 +00:00
xpath
end
2016-08-18 20:27:35 +00:00
2017-11-13 21:04:47 +00:00
describe do | name : nil , ** _options |
2018-01-09 22:05:50 +00:00
desc = " " . dup
2017-05-02 01:39:08 +00:00
desc << " with name #{ name } " if name
2016-08-18 20:27:35 +00:00
desc
end
2016-07-28 08:25:24 +00:00
end
2018-01-08 20:23:54 +00:00
# rubocop:enable Metrics/BlockLength
# rubocop:enable Metrics/ParameterLists