Class: Capybara::Selector
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
SimpleDelegator
|
|
Instance Chain:
self,
SimpleDelegator
|
|
Inherits: |
SimpleDelegator
|
Defined in: | lib/capybara/selector.rb, lib/capybara/selector/css.rb, lib/capybara/selector/definition.rb, lib/capybara/selector/filter_set.rb, lib/capybara/selector/regexp_disassembler.rb, lib/capybara/selector/selector.rb, lib/capybara/selector/builders/css_builder.rb, lib/capybara/selector/builders/xpath_builder.rb, lib/capybara/selector/filters/base.rb, lib/capybara/selector/filters/expression_filter.rb, lib/capybara/selector/filters/locator_filter.rb, lib/capybara/selector/filters/node_filter.rb |
Overview
All Selectors below support the listed selector specific filters in addition to the following system-wide filters
* :id (String, Regexp, XPath::Expression) - Matches the id attribute
* :class (String, Array<String | Regexp>, Regexp, XPath::Expression) - Matches the class(es) provided
* :style (String, Regexp, Hash<String, String>) - Match on elements style
* :above (Element) - Match elements above the passed element on the page
* :below (Element) - Match elements below the passed element on the page
* :left_of (Element) - Match elements left of the passed element on the page
* :right_of (Element) - Match elements right of the passed element on the page
* :near (Element) - Match elements near (within 50px) the passed element on the page
* :focused (Boolean) - Match elements with focus (requires driver support)
Built-in Selectors
-
:xpath - Select elements by
::XPath
expression-
Locator: An XPath expression
“‘ruby page.html # => ’<input>‘
page.find :xpath, ‘.//input’ “‘
-
-
:css - Select elements by
CSS
selector-
Locator: A CSS selector
“‘ruby page.html # => ’<input>‘
page.find :css, ‘input’ “‘
-
-
:id - Select element by id
-
Locator: (String, Regexp, XPath::Expression) The id of the element to match
“‘ruby page.html # => ’<input id=“field”>‘
page.find :id, ‘field’ “‘
-
-
:field - Select field elements (input [not of type submit, image, or hidden], textarea, select)
-
Locator: Matches against the id, test_id attribute, name, placeholder, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :placeholder (String, Regexp) - Matches the placeholder attribute * :type (String) - Matches the type attribute of the field or element type for 'textarea' and 'select' * :readonly (Boolean) - Match on the element being readonly * :with (String, Regexp) - Matches the current value of the field * :checked (Boolean) - Match checked fields? * :unchecked (Boolean) - Match unchecked fields? * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :multiple (Boolean) - Match fields that accept multiple values * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation * : (String, Regexp) - Matches the elements current validationMessage
“‘ruby page.html # => ’<label for=“article_title”>Title</label>
# <input id="article_title" name="article[title]" value="Hello world">'
page.find :field, ‘article_title’ page.find :field, ‘article’ page.find :field, ‘Title’ page.find :field, ‘Title’, type: ‘text’, with: ‘Hello world’ “‘
-
-
:fieldset - Select fieldset elements
-
Locator: Matches id, test_id, or contents of wrapped legend
-
Filters:
* :legend (String) - Matches contents of wrapped legend * :disabled (Boolean) - Match disabled fieldset?
“‘ruby page.html # => ’<fieldset disabled>
# <legend>Fields (disabled)</legend> # </fieldset>'
page.find :fieldset, ‘Fields (disabled)’, disabled: true “‘
-
-
:link - Find links (‘<a>` elements with an href attribute)
-
Locator: Matches the id, test_id, or title attributes, or the string content of the link, or the alt attribute of a contained img element. By default this selector requires a link to have an href attribute.
-
Filters:
* :title (String) - Matches the title attribute * :alt (String) - Matches the alt attribute of a contained img element * :href (String, Regexp, nil, false) - Matches the normalized href of the link, if nil will find `<a>` elements with no href attribute, if false ignores href presence
“‘ruby page.html # => ’<a href=“/”>Home</a>‘
page.find :link, ‘Home’, href: ‘/’
page.html # => ‘<a href=“/”><img src=“/logo.png” alt=“The logo”></a>’
page.find :link, ‘The logo’, href: ‘/’ page.find :link, alt: ‘The logo’, href: ‘/’ “‘
-
-
:button - Find buttons ( input [of type submit, reset, image, button] or button elements )
-
Locator: Matches the id, test_id attribute, name, 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
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :title (String) - Matches the title attribute * :value (String) - Matches the value of an input * :type (String) - Matches the type attribute * :disabled (Boolean, :all) - Match disabled (Default: false)
“‘ruby page.html # => ’<button>Submit</button>‘
page.find :button, ‘Submit’
page.html # => ‘<button name=“article” value=“draft”>Save as draft</button>’
page.find :button, ‘Save as draft’, name: ‘article’, value: ‘draft’ “‘
-
-
:link_or_button - Find links or buttons
-
Locator: See :link and :button selectors
-
Filters:
* :disabled (Boolean, :all) - Match disabled (Default: false)
“‘ruby page.html # => ’<a href=“/”>Home</a>‘
page.find :link_or_button, ‘Home’
page.html # => ‘<button>Submit</button>’
page.find :link_or_button, ‘Submit’ “‘
-
-
:fillable_field - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
-
Locator: Matches against the id, test_id attribute, name, placeholder, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :placeholder (String, Regexp) - Matches the placeholder attribute * :with (String, Regexp) - Matches the current value of the field * :type (String) - Matches the type attribute of the field or element type for 'textarea' * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :multiple (Boolean) - Match fields that accept multiple values * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation * : (String, Regexp) - Matches the elements current validationMessage
“‘ruby page.html # => ’<label for=“article_body”>Body</label>
# <textarea id="article_body" name="article[body]"></textarea>'
page.find :fillable_field, ‘article_body’ page.find :fillable_field, ‘article’ page.find :fillable_field, ‘Body’ page.find :field, ‘Body’, type: ‘textarea’ “‘
-
-
:radio_button - Find radio buttons
-
Locator: Match id, test_id attribute, name, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :checked (Boolean) - Match checked fields? * :unchecked (Boolean) - Match unchecked fields? * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :option (String, Regexp) - Match the current value * :with - Alias of :option
“‘ruby page.html # => ’<input type=“radio” id=“article_state_published” name=“article” value=“published” checked>
# <label for="article_state_published">Published</label> # <input type="radio" id="article_state_draft" name="article[state]" value="draft"> # <label for="article_state_draft">Draft</label>'
page.find :radio_button, ‘article_state_published’ page.find :radio_button, ‘article’, option: ‘published’ page.find :radio_button, ‘Published’, checked: true page.find :radio_button, ‘Draft’, unchecked: true “‘
-
-
:checkbox - Find checkboxes
-
Locator: Match id, test_id attribute, name, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :checked (Boolean) - Match checked fields? * :unchecked (Boolean) - Match unchecked fields? * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :with (String, Regexp) - Match the current value * :option - Alias of :with
“‘ruby page.html # => ’<input type=“checkbox” id=“registration_terms” name=“registration” value=“true”>
# <label for="registration_terms">I agree to terms and conditions</label>'
page.find :checkbox, ‘registration_terms’ page.find :checkbox, ‘registration’ page.find :checkbox, ‘I agree to terms and conditions’, unchecked: true “‘
-
-
:select - Find select elements
-
Locator: Match id, test_id attribute, name, placeholder, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :placeholder (String, Placeholder) - Matches the placeholder attribute * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :multiple (Boolean) - Match fields that accept multiple values * : (Array<String>) - Exact match * : (Array<String>) - Exact match enabled * : (Array<String>) - Exact match disabled * : (Array<String>) - Partial match * :selected (String, Array<String>) - Match the selection(s) * :with_selected (String, Array<String>) - Partial match the selection(s)
“‘ruby page.html # => ’<label for=“article_category”>Category</label>
# <select id="article_category" name="article[category]"> # <option value="General" checked></option> # <option value="Other"></option> # </select>'
page.find :select, ‘article_category’ page.find :select, ‘article’ page.find :select, ‘Category’ page.find :select, ‘Category’, selected: ‘General’ page.find :select, with_options: [‘General’] page.find :select, with_options: [‘Other’] page.find :select, options: [‘General’, ‘Other’] page.find :select, options: [‘General’] # => raises Capybara::ElementNotFound “‘
-
-
:option - Find option elements
-
Locator: Match text of option
-
Filters:
* :disabled (Boolean) - Match disabled option * :selected (Boolean) - Match selected option
“‘ruby page.html # => ’<option value=“General” checked></option>
# <option value="Disabled" disabled></option> # <option value="Other"></option>'
page.find :option, ‘General’ page.find :option, ‘General’, selected: true page.find :option, ‘Disabled’, disabled: true page.find :option, ‘Other’, selected: false “‘
-
-
:datalist_input - Find input field with datalist completion
-
Locator: Matches against the id, test_id attribute, name, placeholder, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :placeholder (String, Regexp) - Matches the placeholder attribute * :disabled (Boolean, :all) - Match disabled field? (Default: false) * : (Array<String>) - Exact match * : (Array<String>) - Partial match
“‘ruby page.html # => ’<label for=“ice_cream_flavor”>Flavor</label>
# <input list="ice_cream_flavors" id="ice_cream_flavor" name="ice_cream[flavor]"> # <datalist id="ice_cream_flavors"> # <option value="Chocolate"></option> # <option value="Strawberry"></option> # <option value="Vanilla"></option> # </datalist>'
page.find :datalist_input, ‘ice_cream_flavor’ page.find :datalist_input, ‘ice_cream’ page.find :datalist_input, ‘Flavor’ page.find :datalist_input, with_options: [‘Chocolate’, ‘Strawberry’] page.find :datalist_input, options: [‘Chocolate’, ‘Strawberry’, ‘Vanilla’] page.find :datalist_input, options: [‘Chocolate’] # => raises Capybara::ElementNotFound “‘
-
-
:datalist_option - Find datalist option
-
Locator: Match text or value of option
-
Filters:
* :disabled (Boolean) - Match disabled option
“‘ruby page.html # => ’<datalist>
# <option value="Chocolate"></option> # <option value="Strawberry"></option> # <option value="Vanilla"></option> # <option value="Forbidden" disabled></option> # </datalist>'
page.find :datalist_option, ‘Chocolate’ page.find :datalist_option, ‘Strawberry’ page.find :datalist_option, ‘Vanilla’ page.find :datalist_option, ‘Forbidden’, disabled: true “‘
-
-
:file_field - Find file input elements
-
Locator: Match id, test_id attribute, name, or associated label text
-
Filters:
* :name (String, Regexp) - Matches the name attribute * :disabled (Boolean, :all) - Match disabled field? (Default: false) * :multiple (Boolean) - Match field that accepts multiple values
“‘ruby page.html # => ’<label for=“article_banner_image”>Banner Image</label>
# <input type="file" id="article_banner_image" name="article[banner_image]">'
page.find :file_field, ‘article_banner_image’ page.find :file_field, ‘article’ page.find :file_field, ‘Banner Image’ page.find :file_field, ‘Banner Image’, name: ‘article’ page.find :field, ‘Banner Image’, type: ‘file’ “‘
-
-
:label - Find label elements
-
Locator: Match id, test_id, or text contents
-
Filters:
* :for (Element, String, Regexp) - The element or id of the element associated with the label
“‘ruby page.html # => ’<label for=“article_title”>Title</label>
# <input id="article_title" name="article[title]">'
page.find :label, ‘Title’ page.find :label, ‘Title’, for: ‘article_title’ page.find :label, ‘Title’, for: page.find(‘article’) “‘
-
-
:table - Find table elements
-
Locator: id, test_id, or caption text of table
-
Filters:
* : (String) - Match text of associated * :with_rows (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered * :rows (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered * :with_cols (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered * :cols (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered
“‘ruby page.html # => ’<table>
# <caption>A table</caption> # <tr> # <th>A</th> # <th>B</th> # </tr> # <tr> # <td>1</td> # <td>2</td> # </tr> # <tr> # <td>3</td> # <td>4</td> # </tr> # </table>'
page.find :table, ‘A table’ page.find :table, with_rows: [
{ 'A' => '1', 'B' => '2' }, { 'A' => '3', 'B' => '4' },
] page.find :table, with_rows: [
['1', '2'], ['3', '4'],
] page.find :table, rows: [
{ 'A' => '1', 'B' => '2' }, { 'A' => '3', 'B' => '4' },
] page.find :table, rows: [
['1', '2'], ['3', '4'],
] page.find :table, rows: [ [‘1’, ‘2’] ] # => raises Capybara::ElementNotFound “‘
-
-
:table_row - Find table row
-
Locator: Array<String>, Hash<String, String> table row ‘<td>` contents - visibility of
elements is not considered “‘ruby page.html # => ’<table>
# <tr> # <th>A</th> # <th>B</th> # </tr> # <tr> # <td>1</td> # <td>2</td> # </tr> # <tr> # <td>3</td> # <td>4</td> # </tr> # </table>'
page.find :table_row, ‘A’ => ‘1’, ‘B’ => ‘2’ page.find :table_row, ‘A’ => ‘3’, ‘B’ => ‘4’ “‘
:frame - Find frame/iframe elements
-
Locator: Match id, test_id attribute, or name
-
Filters:
* :name (String) - Match name attribute
“‘ruby page.html # => ’<iframe id=“embed_frame” name=“embed” src=“example.com/embed”></iframe>‘
page.find :frame, ‘embed_frame’ page.find :frame, ‘embed’ page.find :frame, name: ‘embed’ “‘
:element
-
Locator: Type of element (‘div’, ‘a’, etc) - if not specified defaults to ‘*’
-
Filters:
* :\<any> (String, Regexp) - Match on any specified element attribute
“‘ruby page.html # => ’<button type=“button” role=“menuitemcheckbox” aria-checked=“true”>Check me</button>
page.find :element, ‘button’ page.find :element, type: ‘button’, text: ‘Check me’ page.find :element, role: ‘menuitemcheckbox’ page.find :element, role: /checkbox/, ‘aria-checked’: ‘true’ “‘
Class Method Summary
Instance Attribute Summary
- #errors readonly
Instance Method Summary
- #add_error(error_msg)
- #call(locator, **options)
-
#current_format
Alias for #format.
- #enable_aria_label
- #enable_aria_role
- #expression_for(name, locator, config: @config, format: current_format, **options)
- #format (also: #current_format)
- #test_id
- #find_by_attr(attribute, value) private
- #find_by_class_attr(classes) private
- #locate_field(xpath, locator, **_options) private
- #locate_label(locator) private
- #locator_description private
- #locator_valid?(locator) ⇒ Boolean private
- #builder(expr = nil) Internal use only Internal use only
- #with_filter_errors(errors) Internal use only Internal use only
Constructor Details
.new(definition, config:, format:) ⇒
Selector
# File 'lib/capybara/selector/selector.rb', line 33
def initialize(definition, config:, format:) definition = self.class[definition] unless definition.is_a? Definition super(definition) @definition = definition @config = config @format = format @errors = [] end
Class Method Details
.[](name)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 10
def [](name) all.fetch(name.to_sym) { |sel_type| raise ArgumentError, "Unknown selector type (:#{sel_type})" } end
.add(name, **options, &block)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 14
def add(name, **, &block) all[name.to_sym] = Definition.new(name.to_sym, **, &block) end
.all
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 6
def all @definitions ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName end
.for(locator)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 26
def for(locator) all.values.find { |sel| sel.match?(locator) } end
.remove(name)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 22
def remove(name) all.delete(name.to_sym) end
.update(name, &block)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 18
def update(name, &block) self[name].instance_eval(&block) end
Instance Attribute Details
#errors (readonly)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 31
attr_reader :errors
Instance Method Details
#add_error(error_msg)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 77
def add_error(error_msg) errors << error_msg end
#builder(expr = nil)
This method is for internal use only.[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 95
def builder(expr = nil) case format when :css Capybara::Selector::CSSBuilder when :xpath Capybara::Selector::XPathBuilder else raise NotImplementedError, "No builder exists for selector of type #{default_format}" end.new(expr) end
#call(locator, **options)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 59
def call(locator, ** ) if format raise ArgumentError, "Selector #{@name} does not support #{format}" unless expressions.key?(format) instance_exec(locator, **, &expressions[format]) else warn 'Selector has no format' end ensure unless locator_valid?(locator) Capybara::Helpers.warn( "Locator #{locator.class}:#{locator.inspect} for selector #{name.inspect} must #{locator_description}. " \ 'This will raise an error in a future version of Capybara. ' \ "Called from: #{Capybara::Helpers.filter_backtrace(caller)}" ) end end
#current_format
Alias for #format.
# File 'lib/capybara/selector/selector.rb', line 45
alias_method :current_format, :format
#enable_aria_label
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 47
def enable_aria_label @config[:enable_aria_label] end
#enable_aria_role
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 51
def enable_aria_role @config[:enable_aria_role] end
#expression_for(name, locator, config: @config, format: current_format, **options)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 81
def expression_for(name, locator, config: @config, format: current_format, ** ) Selector.new(name, config: config, format: format).call(locator, ** ) end
#find_by_attr(attribute, value) (private)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 146
def find_by_attr(attribute, value) finder_name = "find_by_#{attribute}_attr" if respond_to?(finder_name, true) send(finder_name, value) else value ? XPath.attr(attribute) == value : nil end end
#find_by_class_attr(classes) (private)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 155
def find_by_class_attr(classes) Array(classes).map { |klass| XPath.attr(:class).contains_word(klass) }.reduce(:&) end
#format Also known as: #current_format
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 42
def format @format || @definition.default_format end
#locate_field(xpath, locator, **_options) (private)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 126
def locate_field(xpath, locator, ** ) return xpath if locator.nil? locate_xpath = xpath # Need to save original xpath for the label wrap locator = locator.to_s attr_matchers = [XPath.attr(:id) == locator, XPath.attr(:name) == locator, XPath.attr(:placeholder) == locator, XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)].reduce(:|) attr_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label attr_matchers |= XPath.attr(test_id) == locator if test_id locate_xpath = locate_xpath[attr_matchers] locate_xpath + locate_label(locator).descendant(xpath) end
#locate_label(locator) (private)
[ GitHub ]#locator_description (private)
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 108
def locator_description locator_types.group_by { |lt| lt.is_a? Symbol }.map do |symbol, types_or_methods| if symbol "respond to #{types_or_methods.join(' or ')}" else "be an instance of #{types_or_methods.join(' or ')}" end end.join(' or ') end
#locator_valid?(locator) ⇒
Boolean
(private)# File 'lib/capybara/selector/selector.rb', line 118
def locator_valid?(locator) return true unless locator && locator_types locator_types&.any? do |type_or_method| type_or_method.is_a?(Symbol) ? locator.respond_to?(type_or_method) : type_or_method === locator # rubocop:disable Style/CaseEquality end end
#test_id
[ GitHub ]# File 'lib/capybara/selector/selector.rb', line 55
def test_id @config[:test_id] end
#with_filter_errors(errors)
This method is for internal use only.[ GitHub ]
-