Manually document built-in selectors rather than using yard extension due to non-support for extension on rubydoc.info

This commit is contained in:
Thomas Walpole 2018-05-29 16:02:53 -07:00
parent 88e3ac2d2c
commit cc9629645d
6 changed files with 159 additions and 314 deletions

View File

@ -1,38 +0,0 @@
<div id="selectors">
<h2>Built-in Selectors</h2>
<ul>
<% @selectors.each do |name, selector| %>
<li>
<h3>:<%= name %></h3>
<div class="docstring">
<div class="discussion">
<p><%= h(selector.docstring) %></p>
</div>
</div>
<div class="tags">
<p class="inline">Locator:</p>
<% if locator=selector.tag('locator') %>
<p class="inline"><%= h locator.text %></p>
<% end %>
<% if selector.has_tag?('filter') %>
<p>Filters:</p>
<ul class="param">
<% selector.tags('filter').each do |filter| %>
<li>
<span class="name"><%= filter.name %></span>
<% if filter.types %>
<span class="type">(<tt><%= h(filter.types.join(', ')) %></tt>)</span>
<% end %>
<% if filter.text %>
<div class="inline"><p><%= h filter.text %></p></div>
<% end %>
</li>
<% end %>
</ul>
<% end %>
</div
</li>
<% end %>
</ul>
</div>

View File

@ -1,17 +0,0 @@
def init
super
sections.place(:builtins).before(:subclasses)
end
def builtins
return if object.path != "Capybara::Selector" # only show built-in selectors for Selector class
@selectors = Registry.all(:selector)
return if @selectors.nil? || @selectors.empty?
@selectors = @selectors.map do |selector|
[selector.name, selector]
end
erb(:selectors)
end

View File

@ -1,78 +0,0 @@
YARD::Templates::Engine.register_template_path Pathname.new('./.yard/templates_custom')
YARD::Tags::Library.define_tag "Locator", :locator
YARD::Tags::Library.define_tag "Filter", :filter, :with_types_and_name
class SelectorObject < YARD::CodeObjects::Base
def path
"__Capybara" + sep + super
end
end
class AddSelectorHandler < YARD::Handlers::Ruby::Base
handles method_call(:add_selector)
namespace_only
process do
name = statement.parameters.first.jump(:tstring_content, :ident).source
# object = YARD::CodeObjects::MethodObject.new(namespace, name.to_sym)
# object = SelectorObject.new(YARD::Registry.resolve(P("Capybara"), "#add_selector", false, true), name.to_sym)
object = SelectorObject.new(namespace, name)
register(object)
parse_block(statement.last.last, :owner => object)
# modify the object
object.dynamic = true
end
end
class AddExpressionFilterHandler < YARD::Handlers::Ruby::Base
handles method_call(:xpath)
handles method_call(:css)
process do
return unless owner.is_a?(SelectorObject)
return if statement.parameters.empty?
# names = statement.parameters.children.map { |p| p.jump(:tstring_content, :ident).source.sub(/^:/, '') }
names = statement.parameters.children.map &:source
current_names = owner.tags(:filter).map(&:name)
(names-current_names).each do |name|
owner.add_tag(YARD::Tags::Tag.new(:filter, nil, nil, name))
end
end
end
class AddFilterHandler < YARD::Handlers::Ruby::Base
handles method_call(:filter)
process do
return unless owner.is_a?(SelectorObject)
return if statement.parameters.empty?
name = statement.parameters.first.source
type = if statement.parameters[1] && statement.parameters[1].source == ':boolean'
'Boolean'
else
nil
end
if owner.tags(:filter).none? {|tag| tag.name == name }
filter_tag = YARD::Tags::Tag.new(:filter, nil, type, name)
owner.add_tag(filter_tag)
end
end
end
class FilterSetHandler < YARD::Handlers::Ruby::Base
handles method_call(:filter_set)
process do
return unless owner.is_a?(SelectorObject)
return if statement.parameters.empty? || !statement.parameters[1]
names = statement.parameters[1].flatten.map { |name| ":#{name}" }
names.each do |name|
if owner.tags(:filter).none? {|tag| tag.name == name }
filter_tag = YARD::Tags::Tag.new(:filter, nil, nil, name)
owner.add_tag(filter_tag)
end
end
end
end

View File

@ -1 +0,0 @@
--load ./.yard/yard_extensions.rb

View File

@ -26,52 +26,18 @@ end
# rubocop:disable Metrics/BlockLength
# rubocop:disable Metrics/ParameterLists
##
#
# Select elements by XPath expression
#
# @locator An XPath expression
#
Capybara.add_selector(:xpath) do
xpath { |xpath| xpath }
end
##
#
# Select elements by CSS selector
#
# @locator A CSS selector
#
Capybara.add_selector(:css) do
css { |css| css }
end
##
#
# Select element by id
#
# @locator The id of the element to match
#
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
end
##
#
# Select field elements (input [not of type submit, image, or hidden], textarea, select)
#
# @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
Capybara.add_selector(:field) do
xpath do |locator, **options|
xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of('submit', 'image', 'hidden')]
@ -102,16 +68,6 @@ Capybara.add_selector(:field) do
end
end
##
#
# Select fieldset elements
#
# @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
#
Capybara.add_selector(:fieldset) do
xpath(:legend) do |locator, legend: nil, **_options|
xpath = XPath.descendant(:fieldset)
@ -121,18 +77,6 @@ Capybara.add_selector(:fieldset) do
end
end
##
#
# Find links ( <a> elements with an href attribute )
#
# @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
# @filter [String, Regexp,nil] :href Matches the normalized href of the link, if nil will find <a> elements with no href attribute
#
Capybara.add_selector(:link) do
xpath(:title, :alt) do |locator, href: true, enable_aria_label: false, alt: nil, title: nil, **_options|
xpath = XPath.descendant(:a)
@ -176,17 +120,6 @@ Capybara.add_selector(:link) do
end
end
##
#
# Find buttons ( input [of type submit, reset, image, button] or button elements )
#
# @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
#
# @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
#
Capybara.add_selector(:button) do
xpath(:value, :title, :type) do |locator, enable_aria_label: false, **options|
input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
@ -224,10 +157,6 @@ Capybara.add_selector(:button) do
end
end
##
#
# Find links or buttons
#
Capybara.add_selector(:link_or_button) do
label "link or button"
xpath do |locator, **options|
@ -239,20 +168,6 @@ Capybara.add_selector(:link_or_button) do
describe { |disabled: nil, **_options| " that is disabled" if disabled == true }
end
##
#
# Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
#
# @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
# @filter [String] :type Matches the type attribute of the field or element type for 'textarea'
# @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
#
Capybara.add_selector(:fillable_field) do
label "field"
@ -284,19 +199,6 @@ Capybara.add_selector(:fillable_field) do
end
end
##
#
# Find radio buttons
#
# @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
#
Capybara.add_selector(:radio_button) do
label "radio button"
@ -317,19 +219,6 @@ Capybara.add_selector(:radio_button) do
end
end
##
#
# Find checkboxes
#
# @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
#
Capybara.add_selector(:checkbox) do
xpath do |locator, **options|
xpath = XPath.descendant(:input)[XPath.attr(:type) == 'checkbox']
@ -348,22 +237,6 @@ Capybara.add_selector(:checkbox) do
end
end
##
#
# Find select elements
#
# @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)
# @filter [String, Array<String>] :with_selected Partial match the selection(s)
#
Capybara.add_selector(:select) do
label "select box"
@ -440,14 +313,6 @@ Capybara.add_selector(:datalist_input) do
end
end
##
#
# Find option elements
#
# @locator Match text of option
# @filter [Boolean] :disabled Match disabled option
# @filter [Boolean] :selected Match selected option
#
Capybara.add_selector(:option) do
xpath do |locator|
xpath = XPath.descendant(:option)
@ -485,17 +350,6 @@ Capybara.add_selector(:datalist_option) do
end
end
##
#
# Find file input elements
#
# @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
#
Capybara.add_selector(:file_field) do
label "file field"
xpath do |locator, options|
@ -512,13 +366,6 @@ Capybara.add_selector(:file_field) do
end
end
##
#
# Find label elements
#
# @locator Match id or text contents
# @filter [Element, String] :for The element or id of the element associated with the label
#
Capybara.add_selector(:label) do
label "label"
xpath(:for) do |locator, options|
@ -553,15 +400,6 @@ Capybara.add_selector(:label) do
end
end
##
#
# Find table elements
#
# @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
#
Capybara.add_selector(:table) do
xpath(:caption) do |locator, caption: nil, **_options|
xpath = XPath.descendant(:table)
@ -577,15 +415,6 @@ Capybara.add_selector(:table) do
end
end
##
#
# Find frame/iframe elements
#
# @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
#
Capybara.add_selector(:frame) do
xpath(:name) do |locator, **options|
xpath = XPath.descendant(:iframe).union(XPath.descendant(:frame))

View File

@ -4,6 +4,157 @@ require 'capybara/selector/filter_set'
require 'capybara/selector/css'
module Capybara
#
# ## Built-in Selectors
#
# * **:xpath** - Select elements by XPath expression
# * Locator: An XPath expression
#
# * **:css** - Select elements by CSS selector
# * Locator: A CSS selector
#
# * **:id** - Select element by id
# * Locator: The id of the element to match
#
# * **:field** - Select field elements (input [not of type submit, image, or hidden], textarea, select)
# * Locator: Matches against the id, name, or placeholder
# * Filters:
# * :id (String) — Matches the id attribute
# * :name (String) — Matches the name attribute
# * :placeholder (String) — Matches the placeholder attribute
# * :type (String) — Matches the type attribute of the field or element type for 'textarea' and 'select'
# * :readonly (Boolean)
# * :with (String) — Matches the current value of the field
# * :class (String, Array<String>) — Matches the class(es) provided
# * :checked (Boolean) — Match checked fields?
# * :unchecked (Boolean) — Match unchecked fields?
# * :disabled (Boolean) — Match disabled field?
# * :multiple (Boolean) — Match fields that accept multiple values
#
# * **:fieldset** - Select fieldset elements
# * Locator: Matches id or contents of wrapped legend
# * Filters:
# * :id (String) — Matches id attribute
# * :legend (String) — Matches contents of wrapped legend
# * :class (String, Array<String>) — Matches the class(es) provided
#
# * **:link** - Find links ( <a> elements with an href attribute )
# * Locator: Matches the id or title attributes, or the string content of the link, or the alt attribute of a contained img element
# * Filters:
# * :id (String) — Matches the id attribute
# * :title (String) — Matches the title attribute
# * :alt (String) — Matches the alt attribute of a contained img element
# * :class (String) — Matches the class(es) provided
# * :href (String, Regexp, nil) — Matches the normalized href of the link, if nil will find <a> elements with no href attribute
#
# * **:button** - Find buttons ( input [of type submit, reset, image, button] or button elements )
# * 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
# * Filters:
# * :id (String) — Matches the id attribute
# * :title (String) — Matches the title attribute
# * :class (String) — Matches the class(es) provided
# * :value (String) — Matches the value of an input button
# * :type
#
# * **:link_or_button** - Find links or buttons
# * Locator: See :link and :button selectors
#
# * **:fillable_field** - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
# * Locator: Matches against the id, name, or placeholder
# * Filters:
# * :id (String) — Matches the id attribute
# * :name (String) — Matches the name attribute
# * :placeholder (String) — Matches the placeholder attribute
# * :with (String) — Matches the current value of the field
# * :type (String) — Matches the type attribute of the field or element type for 'textarea'
# * :class (String, Array<String>) — Matches the class(es) provided
# * :disabled (Boolean) — Match disabled field?
# * :multiple (Boolean) — Match fields that accept multiple values
#
# * **:radio_button** - Find radio buttons
# * Locator: Match id, name, or associated label text
# * Filters:
# * :id (String) — Matches the id attribute
# * :name (String) — Matches the name attribute
# * :class (String, Array<String>) — Matches the class(es) provided
# * :checked (Boolean) — Match checked fields?
# * :unchecked (Boolean) — Match unchecked fields?
# * :disabled (Boolean) — Match disabled field?
# * :option (String) — Match the value
#
# * **:checkbox** - Find checkboxes
# * Locator: Match id, name, or associated label text
# * Filters:
# * *:id (String) — Matches the id attribute
# * *:name (String) — Matches the name attribute
# * *:class (String, Array<String>) — Matches the class(es) provided
# * *:checked (Boolean) — Match checked fields?
# * *:unchecked (Boolean) — Match unchecked fields?
# * *:disabled (Boolean) — Match disabled field?
# * *:option (String) — Match the value
#
# * **:select** - Find select elements
# * Locator: Match id, name, placeholder, or associated label text
# * Filters:
# * :id (String) — Matches the id attribute
# * :name (String) — Matches the name attribute
# * :placeholder (String) — Matches the placeholder attribute
# * :class (String, Array<String>) — Matches the class(es) provided
# * :disabled (Boolean) — Match disabled field?
# * :multiple (Boolean) — Match fields that accept multiple values
# * :options (Array<String>) — Exact match options
# * :with_options (Array<String>) — Partial match options
# * :selected (String, Array<String>) — Match the selection(s)
# * :with_selected (String, Array<String>) — Partial match the selection(s)
#
# * **:option** - Find option elements
# * Locator: Match text of option
# * Filters:
# * :disabled (Boolean) — Match disabled option
# * :selected (Boolean) — Match selected option
#
# * **:datalist_input**
# * Locator:
# * Filters:
# * :disabled
# * :name
# * :placeholder
#
# * **:datalist_option**
# * Locator:
#
# * **:file_field** - Find file input elements
# * Locator: Match id, name, or associated label text
# * Filters:
# * :id (String) — Matches the id attribute
# * :name (String) — Matches the name attribute
# * :class (String, Array<String>) — Matches the class(es) provided
# * :disabled (Boolean) — Match disabled field?
# * :multiple (Boolean) — Match field that accepts multiple values
#
# * **:label** - Find label elements
# * Locator: Match id or text contents
# * Filters:
# * :for (Element, String) — The element or id of the element associated with the label
#
# * **:table** - Find table elements
# * Locator: id or caption text of table
# * Filters:
# * :id (String) — Match id attribute of table
# * :caption (String) — Match text of associated caption
# * :class (String, Array<String>) — Matches the class(es) provided
#
# * **:frame** - Find frame/iframe elements
# * Locator: Match id or name
# * Filters:
# * :id (String) — Match id attribute
# * :name (String) — Match name attribute
# * :class (String, Array<String>) — Matches the class(es) provided
#
# * **:element**
# * Locator: Type of element ('div', 'a', etc) - if not specified defaults to '*'
# * Filters: Matches on any element attribute
#
class Selector
attr_reader :name, :format
extend Forwardable
@ -129,14 +280,10 @@ module Capybara
#
# Description of the selector
#
# @param [Hash] options The options of the query used to generate the description
# @return [String] Description of the selector when used with the options passed
#
# @!method description(options)
# @param [Hash] options The options of the query used to generate the description
# @return [String] Description of the selector when used with the options passed
def_delegator :@filter_set, :description
def description(**options)
@filter_set.description(options)
end
def call(locator, **options)
if format
@ -163,7 +310,7 @@ module Capybara
#
# Define a node filter for use with this selector
#
# @overload filter(name, *types, options={}, &block)
# @!method node_filter(name, *types, options={}, &block)
# @param [Symbol, Regexp] name The filter name
# @param [Array<Symbol>] types The types of the filter - currently valid types are [:boolean]
# @param [Hash] options ({}) Options of the filter
@ -176,11 +323,14 @@ module Capybara
# is passed for the name the block should accept | node, option_name, option_value |. In either case
# the block should return `true` if the node passes the filer or `false` if it doesn't
# @!method filter
# See {Selector#node_filter}
##
#
# Define an expression filter for use with this selector
#
# @overload expression_filter(name, *types, options={}, &block)
# @!method expression_filter(name, *types, options={}, &block)
# @param [Symbol, Regexp] name The filter name
# @param [Regexp] matcher (nil) A Regexp used to check whether a specific option is handled by this filter
# @param [Array<Symbol>] types The types of the filter - currently valid types are [:boolean]