mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Support alternated id and class regexps when using CSS
This commit is contained in:
parent
c0704c38e0
commit
1384e00bd1
6 changed files with 58 additions and 8 deletions
|
@ -240,10 +240,15 @@ module Capybara
|
|||
end
|
||||
|
||||
def filtered_css(expr)
|
||||
id_conditions = conditions_from_id if use_default_id_filter?
|
||||
id_conditions = [''] unless id_conditions&.any?
|
||||
|
||||
class_conditions = conditions_from_classes if use_default_class_filter?
|
||||
class_conditions = [''] unless class_conditions&.any?
|
||||
|
||||
conditions = id_conditions.product(class_conditions)
|
||||
::Capybara::Selector::CSS.split(expr).map do |sel|
|
||||
sel += conditions_from_id if use_default_id_filter?
|
||||
sel += conditions_from_classes if use_default_class_filter?
|
||||
sel
|
||||
conditions.map { |(id_cond, class_cond)| sel + id_cond + class_cond }.join(', ')
|
||||
end.join(', ')
|
||||
end
|
||||
|
||||
|
@ -260,7 +265,7 @@ module Capybara
|
|||
end
|
||||
|
||||
def conditions_from_id
|
||||
builder.attribute_conditions(id: options[:id])
|
||||
builder.id_conditions(options[:id])
|
||||
end
|
||||
|
||||
def apply_expression_filters(expression)
|
||||
|
|
|
@ -34,7 +34,7 @@ Capybara.add_selector(:css) do
|
|||
end
|
||||
|
||||
Capybara.add_selector(:id) do
|
||||
xpath { |id| XPath.descendant[builder.attribute_conditions(id: id)] }
|
||||
xpath { |id| XPath.descendant[builder.id_conditions(id)] }
|
||||
locator_filter { |node, id| id.is_a?(Regexp) ? node[:id] =~ id : true }
|
||||
end
|
||||
|
||||
|
|
|
@ -35,11 +35,28 @@ module Capybara
|
|||
when XPath::Expression
|
||||
raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'
|
||||
when Regexp
|
||||
attribute_conditions(class: classes)
|
||||
Selector::RegexpDisassembler.new(classes).alternated_substrings.map do |strs|
|
||||
strs.map do |str|
|
||||
"[class*='#{str}'#{' i' if classes.casefold?}]"
|
||||
end.join
|
||||
end
|
||||
else
|
||||
cls = Array(classes).group_by { |cl| cl.start_with?('!') && !cl.start_with?('!!!') }
|
||||
(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
|
||||
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..-1))})" }).join
|
||||
[(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
|
||||
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..-1))})" }).join]
|
||||
end
|
||||
end
|
||||
|
||||
def id_conditions(id)
|
||||
case id
|
||||
when Regexp
|
||||
Selector::RegexpDisassembler.new(id).alternated_substrings.map do |id_strs|
|
||||
id_strs.map do |str|
|
||||
"[id*='#{str}'#{' i' if id.casefold?}]"
|
||||
end.join
|
||||
end
|
||||
else
|
||||
[attribute_conditions(id: id)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,6 +39,10 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
def id_conditions(id)
|
||||
attribute_conditions(id: id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def regexp_to_xpath_conditions(regexp)
|
||||
|
|
|
@ -27,11 +27,15 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|||
expect(@session).to have_css('h2', id: 'h2one')
|
||||
expect(@session).to have_css('h2')
|
||||
expect(@session).to have_css('h2', id: /h2o/)
|
||||
expect(@session).to have_css('li', id: /john|paul/)
|
||||
end
|
||||
|
||||
it 'should support :class option' do
|
||||
expect(@session).to have_css('li', class: 'guitarist')
|
||||
expect(@session).to have_css('li', class: /guitar/)
|
||||
expect(@session).to have_css('li', class: /guitar|drummer/)
|
||||
expect(@session).to have_css('li', class: %w[beatle guitarist])
|
||||
expect(@session).to have_css('li', class: /.*/)
|
||||
end
|
||||
|
||||
it 'should support case insensitive :class and :id options' do
|
||||
|
@ -111,6 +115,9 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|||
expect(@session).to have_css('p', count: 3)
|
||||
expect(@session).to have_css('p a#foo', count: 1)
|
||||
expect(@session).to have_css('p a.doesnotexist', count: 0)
|
||||
expect(@session).to have_css('li', class: /guitar|drummer/, count: 4)
|
||||
expect(@session).to have_css('li', id: /john|paul/, class: /guitar|drummer/, count: 2)
|
||||
expect(@session).to have_css('li', class: %w[beatle guitarist], count: 2)
|
||||
end
|
||||
|
||||
it 'should be false if the content occurs a different number of times than the given' do
|
||||
|
|
|
@ -11,6 +11,20 @@ Capybara::SpecHelper.spec '#has_xpath?' do
|
|||
expect(@session).to have_xpath("//p[contains(.,'est')]")
|
||||
end
|
||||
|
||||
it 'should support :id option' do
|
||||
expect(@session).to have_xpath('//h2', id: 'h2one')
|
||||
expect(@session).to have_xpath('//h2')
|
||||
expect(@session).to have_xpath('//h2', id: /h2o/)
|
||||
end
|
||||
|
||||
it 'should support :class option' do
|
||||
expect(@session).to have_xpath('//li', class: 'guitarist')
|
||||
expect(@session).to have_xpath('//li', class: /guitar/)
|
||||
expect(@session).to have_xpath('//li', class: /guitar|drummer/)
|
||||
expect(@session).to have_xpath('//li', class: %w[beatle guitarist])
|
||||
expect(@session).to have_xpath('//li', class: /.*/)
|
||||
end
|
||||
|
||||
it 'should be false if the given selector is not on the page' do
|
||||
expect(@session).not_to have_xpath('//abbr')
|
||||
expect(@session).not_to have_xpath("//p//a[@id='doesnotexist']")
|
||||
|
@ -43,6 +57,9 @@ Capybara::SpecHelper.spec '#has_xpath?' do
|
|||
expect(@session).to have_xpath("//p//a[@id='foo']", count: 1)
|
||||
expect(@session).to have_xpath("//p[contains(.,'est')]", count: 1)
|
||||
expect(@session).to have_xpath("//p//a[@id='doesnotexist']", count: 0)
|
||||
expect(@session).to have_xpath('//li', class: /guitar|drummer/, count: 4)
|
||||
expect(@session).to have_xpath('//li', id: /john|paul/, class: /guitar|drummer/, count: 2)
|
||||
expect(@session).to have_xpath('//li', class: %w[beatle guitarist], count: 2)
|
||||
end
|
||||
|
||||
it 'should be false if the content occurs a different number of times than the given' do
|
||||
|
|
Loading…
Reference in a new issue