-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2180 from teamcapybara/split_selectors
Move selector definitions to their own files
- Loading branch information
Showing
26 changed files
with
835 additions
and
781 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:button, locator_type: [String, Symbol]) do | ||
xpath(:value, :title, :type, :name) do |locator, **options| | ||
input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')] | ||
btn_xpath = XPath.descendant(:button) | ||
image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image'] | ||
|
||
unless locator.nil? | ||
locator = locator.to_s | ||
locator_matchers = XPath.attr(:id).equals(locator) | | ||
XPath.attr(:name).equals(locator) | | ||
XPath.attr(:value).is(locator) | | ||
XPath.attr(:title).is(locator) | ||
locator_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label | ||
locator_matchers |= XPath.attr(test_id) == locator if test_id | ||
|
||
input_btn_xpath = input_btn_xpath[locator_matchers] | ||
|
||
btn_xpath = btn_xpath[locator_matchers | | ||
XPath.string.n.is(locator) | | ||
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]] | ||
|
||
alt_matches = XPath.attr(:alt).is(locator) | ||
alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label | ||
image_btn_xpath = image_btn_xpath[alt_matches] | ||
end | ||
|
||
%i[value title type name].inject(input_btn_xpath.union(btn_xpath).union(image_btn_xpath)) do |memo, ef| | ||
memo[find_by_attr(ef, options[ef])] | ||
end | ||
end | ||
|
||
node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) } | ||
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] } | ||
|
||
describe_expression_filters do |disabled: nil, **options| | ||
desc = +'' | ||
desc << ' that is not disabled' if disabled == false | ||
desc << describe_all_expression_filters(options) | ||
end | ||
|
||
describe_node_filters do |disabled: nil, **| | ||
' that is disabled' if disabled == true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:checkbox, locator_type: [String, Symbol]) do | ||
xpath do |locator, allow_self: nil, **options| | ||
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input)[ | ||
XPath.attr(:type) == 'checkbox' | ||
] | ||
locate_field(xpath, locator, options) | ||
end | ||
|
||
filter_set(:_field, %i[checked unchecked disabled name]) | ||
|
||
node_filter(:option) do |node, value| | ||
val = node.value | ||
(val == value.to_s).tap do |res| | ||
add_error("Expected option value to be #{value.inspect} but it was #{val.inspect}") unless res | ||
end | ||
end | ||
|
||
describe_node_filters do |option: nil, **| | ||
" with value #{option.inspect}" if option | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:css, locator_type: [String, Symbol], raw_locator: true) do | ||
css { |css| css } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:datalist_input, locator_type: [String, Symbol]) do | ||
label 'input box with datalist completion' | ||
|
||
xpath do |locator, **options| | ||
xpath = XPath.descendant(:input)[XPath.attr(:list)] | ||
locate_field(xpath, locator, options) | ||
end | ||
|
||
filter_set(:_field, %i[disabled name placeholder]) | ||
|
||
node_filter(:options) do |node, options| | ||
actual = node.find("//datalist[@id=#{node[:list]}]", visible: :all).all(:datalist_option, wait: false).map(&:value) | ||
(options.sort == actual.sort).tap do |res| | ||
add_error("Expected #{options.inspect} options found #{actual.inspect}") unless res | ||
end | ||
end | ||
|
||
expression_filter(:with_options) do |expr, options| | ||
options.inject(expr) do |xpath, option| | ||
xpath[XPath.attr(:list) == XPath.anywhere(:datalist)[expression_for(:datalist_option, option)].attr(:id)] | ||
end | ||
end | ||
|
||
describe_expression_filters do |with_options: nil, **| | ||
desc = +'' | ||
desc << " with at least options #{with_options.inspect}" if with_options | ||
desc | ||
end | ||
|
||
describe_node_filters do |options: nil, **| | ||
" with options #{options.inspect}" if options | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:datalist_option, locator_type: [String, Symbol]) do | ||
label 'datalist option' | ||
visible(:all) | ||
|
||
xpath do |locator| | ||
xpath = XPath.descendant(:option) | ||
xpath = xpath[XPath.string.n.is(locator.to_s) | (XPath.attr(:value) == locator.to_s)] unless locator.nil? | ||
xpath | ||
end | ||
|
||
node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) } | ||
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] } | ||
|
||
describe_expression_filters do |disabled: nil, **options| | ||
desc = +'' | ||
desc << ' that is not disabled' if disabled == false | ||
desc << describe_all_expression_filters(options) | ||
end | ||
|
||
describe_node_filters do |**options| | ||
' that is disabled' if options[:disabled] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:element, locator_type: [String, Symbol]) do | ||
xpath do |locator, **| | ||
XPath.descendant.where(locator ? XPath.local_name == locator.to_s : nil) | ||
end | ||
|
||
expression_filter(:attributes, matcher: /.+/) do |xpath, name, val| | ||
builder(xpath).add_attribute_conditions(name => val) | ||
end | ||
|
||
node_filter(:attributes, matcher: /.+/) do |node, name, val| | ||
next true unless val.is_a?(Regexp) | ||
|
||
(val.match? node[name]).tap do |res| | ||
add_error("Expected #{name} to match #{val.inspect} but it was #{node[name]}") unless res | ||
end | ||
end | ||
|
||
describe_expression_filters do |**options| | ||
booleans, values = options.partition { |_k, v| [true, false].include? v }.map(&:to_h) | ||
desc = describe_all_expression_filters(values) | ||
desc + booleans.map do |k, v| | ||
v ? " with #{k} attribute" : "without #{k} attribute" | ||
end.join | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:field, locator_type: [String, Symbol]) do | ||
visible { |options| :hidden if options[:type].to_s == 'hidden' } | ||
|
||
xpath do |locator, **options| | ||
invalid_types = %w[submit image] | ||
invalid_types << 'hidden' unless options[:type].to_s == 'hidden' | ||
xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of(*invalid_types)] | ||
locate_field(xpath, locator, options) | ||
end | ||
|
||
expression_filter(:type) do |expr, type| | ||
type = type.to_s | ||
if %w[textarea select].include?(type) | ||
expr.self(type.to_sym) | ||
else | ||
expr[XPath.attr(:type) == type] | ||
end | ||
end | ||
|
||
filter_set(:_field) # checked/unchecked/disabled/multiple/name/placeholder | ||
|
||
node_filter(:readonly, :boolean) { |node, value| !(value ^ node.readonly?) } | ||
|
||
node_filter(:with) do |node, with| | ||
val = node.value | ||
(with.is_a?(Regexp) ? with.match?(val) : val == with.to_s).tap do |res| | ||
add_error("Expected value to be #{with.inspect} but was #{val.inspect}") unless res | ||
end | ||
end | ||
|
||
describe_expression_filters do |type: nil, **| | ||
" of type #{type.inspect}" if type | ||
end | ||
|
||
describe_node_filters do |**options| | ||
" with value #{options[:with].to_s.inspect}" if options.key?(:with) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:fieldset, locator_type: [String, Symbol]) do | ||
xpath do |locator, legend: nil, **| | ||
locator_matchers = (XPath.attr(:id) == locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)] | ||
locator_matchers |= XPath.attr(test_id) == locator.to_s if test_id | ||
xpath = XPath.descendant(:fieldset)[locator && locator_matchers] | ||
xpath = xpath[XPath.child(:legend)[XPath.string.n.is(legend)]] if legend | ||
xpath | ||
end | ||
|
||
node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) } | ||
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:file_field, locator_type: [String, Symbol]) do | ||
label 'file field' | ||
xpath do |locator, allow_self: nil, **options| | ||
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input)[ | ||
XPath.attr(:type) == 'file' | ||
] | ||
locate_field(xpath, locator, options) | ||
end | ||
|
||
filter_set(:_field, %i[disabled multiple name]) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:fillable_field, locator_type: [String, Symbol]) do | ||
label 'field' | ||
xpath do |locator, allow_self: nil, **options| | ||
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input, :textarea)[ | ||
!XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file') | ||
] | ||
locate_field(xpath, locator, options) | ||
end | ||
|
||
expression_filter(:type) do |expr, type| | ||
type = type.to_s | ||
if type == 'textarea' | ||
expr.self(type.to_sym) | ||
else | ||
expr[XPath.attr(:type) == type] | ||
end | ||
end | ||
|
||
filter_set(:_field, %i[disabled multiple name placeholder]) | ||
|
||
node_filter(:with) do |node, with| | ||
val = node.value | ||
(with.is_a?(Regexp) ? with.match?(val) : val == with.to_s).tap do |res| | ||
add_error("Expected value to be #{with.inspect} but was #{val.inspect}") unless res | ||
end | ||
end | ||
|
||
describe_node_filters do |**options| | ||
" with value #{options[:with].to_s.inspect}" if options.key?(:with) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:frame, locator_type: [String, Symbol]) do | ||
xpath do |locator, name: nil, **| | ||
xpath = XPath.descendant(:iframe).union(XPath.descendant(:frame)) | ||
unless locator.nil? | ||
locator_matchers = (XPath.attr(:id) == locator.to_s) | (XPath.attr(:name) == locator.to_s) | ||
locator_matchers |= XPath.attr(test_id) == locator if test_id | ||
xpath = xpath[locator_matchers] | ||
end | ||
xpath[find_by_attr(:name, name)] | ||
end | ||
|
||
describe_expression_filters do |name: nil, **| | ||
" with name #{name}" if name | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:id, locator_type: [String, Symbol, Regexp]) do | ||
xpath { |id| builder(XPath.descendant).add_attribute_conditions(id: id) } | ||
locator_filter { |node, id| id.is_a?(Regexp) ? id.match?(node[:id]) : true } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# frozen_string_literal: true | ||
|
||
Capybara.add_selector(:label, locator_type: [String, Symbol]) do | ||
label 'label' | ||
xpath(:for) do |locator, options| | ||
xpath = XPath.descendant(:label) | ||
unless locator.nil? | ||
locator_matchers = XPath.string.n.is(locator.to_s) | (XPath.attr(:id) == locator.to_s) | ||
locator_matchers |= XPath.attr(test_id) == locator if test_id | ||
xpath = xpath[locator_matchers] | ||
end | ||
if options.key?(:for) | ||
if (for_option = options[:for].is_a?(Capybara::Node::Element) ? options[:for][:id] : options[:for]) | ||
with_attr = XPath.attr(:for) == for_option.to_s | ||
labelable_elements = %i[button input keygen meter output progress select textarea] | ||
wrapped = !XPath.attr(:for) & | ||
XPath.descendant(*labelable_elements)[XPath.attr(:id) == for_option.to_s] | ||
xpath = xpath[with_attr | wrapped] | ||
end | ||
end | ||
xpath | ||
end | ||
|
||
node_filter(:for) do |node, field_or_value| | ||
# Non element values were handled through the expression filter | ||
next true unless field_or_value.is_a? Capybara::Node::Element | ||
|
||
if (for_val = node[:for]) | ||
field_or_value[:id] == for_val | ||
else | ||
field_or_value.find_xpath('./ancestor::label[1]').include? node.base | ||
end | ||
end | ||
|
||
describe_expression_filters do |**options| | ||
next unless options.key?(:for) && !options[:for].is_a?(Capybara::Node::Element) | ||
|
||
" for element with id of \"#{options[:for]}\"" | ||
end | ||
describe_node_filters do |**options| | ||
" for element #{options[:for]}" if options[:for]&.is_a?(Capybara::Node::Element) | ||
end | ||
end |
Oops, something went wrong.