mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Support negated classes in the :class filter option
This commit is contained in:
parent
cc9629645d
commit
6995982268
3 changed files with 26 additions and 5 deletions
|
@ -202,7 +202,11 @@ module Capybara
|
||||||
XPath.attr(:class)[options[:class]]
|
XPath.attr(:class)[options[:class]]
|
||||||
else
|
else
|
||||||
Array(options[:class]).map do |klass|
|
Array(options[:class]).map do |klass|
|
||||||
XPath.attr(:class).contains_word(klass)
|
if klass.start_with?('!')
|
||||||
|
!XPath.attr(:class).contains_word(klass.slice(1))
|
||||||
|
else
|
||||||
|
XPath.attr(:class).contains_word(klass)
|
||||||
|
end
|
||||||
end.reduce(:&)
|
end.reduce(:&)
|
||||||
end
|
end
|
||||||
expr = "(#{expr})[#{class_xpath}]"
|
expr = "(#{expr})[#{class_xpath}]"
|
||||||
|
@ -224,12 +228,18 @@ module Capybara
|
||||||
css_selectors = expr.split(',').map(&:rstrip)
|
css_selectors = expr.split(',').map(&:rstrip)
|
||||||
expr = css_selectors.map do |sel|
|
expr = css_selectors.map do |sel|
|
||||||
sel += "##{Capybara::Selector::CSS.escape(options[:id])}" if process_id
|
sel += "##{Capybara::Selector::CSS.escape(options[:id])}" if process_id
|
||||||
sel += Array(options[:class]).map { |k| ".#{Capybara::Selector::CSS.escape(k)}" }.join if process_class
|
sel += css_from_classes(Array(options[:class])) if process_class
|
||||||
sel
|
sel
|
||||||
end.join(", ")
|
end.join(", ")
|
||||||
expr
|
expr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def css_from_classes(classes)
|
||||||
|
classes = classes.group_by { |c| c.start_with? '!' }
|
||||||
|
(classes[false].to_a.map { |c| ".#{Capybara::Selector::CSS.escape(c)}" } +
|
||||||
|
classes[true].to_a.map { |c| ":not(.#{Capybara::Selector::CSS.escape(c.slice(1))})" }).join
|
||||||
|
end
|
||||||
|
|
||||||
def apply_expression_filters(expr)
|
def apply_expression_filters(expr)
|
||||||
unapplied_options = options.keys - valid_keys
|
unapplied_options = options.keys - valid_keys
|
||||||
expression_filters.inject(expr) do |memo, (name, ef)|
|
expression_filters.inject(expr) do |memo, (name, ef)|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# rubocop:disable Style/AsciiComments
|
||||||
|
|
||||||
require 'capybara/selector/filter_set'
|
require 'capybara/selector/filter_set'
|
||||||
require 'capybara/selector/css'
|
require 'capybara/selector/css'
|
||||||
|
|
||||||
|
@ -426,3 +428,5 @@ module Capybara
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# rubocop:enable Style/AsciiComments
|
||||||
|
|
|
@ -16,8 +16,8 @@ RSpec.describe Capybara do
|
||||||
<h1 class="a">Totally awesome</h1>
|
<h1 class="a">Totally awesome</h1>
|
||||||
<p>Yes it is</p>
|
<p>Yes it is</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="b">Some Content</p>
|
<p class="b c">Some Content</p>
|
||||||
<p class="b"></p>
|
<p class="b d"></p>
|
||||||
</div>
|
</div>
|
||||||
<div id="#special">
|
<div id="#special">
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,7 +64,7 @@ RSpec.describe Capybara do
|
||||||
it "supports `filter` as an alias for `node_filter`" do
|
it "supports `filter` as an alias for `node_filter`" do
|
||||||
expect do
|
expect do
|
||||||
Capybara.add_selector :filter_alias_selector do
|
Capybara.add_selector :filter_alias_selector do
|
||||||
css { |_unused| "div"}
|
css { |_unused| "div" }
|
||||||
filter(:something) { |_node, _value| true }
|
filter(:something) { |_node, _value| true }
|
||||||
end
|
end
|
||||||
end.not_to raise_error
|
end.not_to raise_error
|
||||||
|
@ -155,6 +155,13 @@ RSpec.describe Capybara do
|
||||||
expect(string.all(:custom_css_selector, "h1, div", class: 'a').size).to eq 2
|
expect(string.all(:custom_css_selector, "h1, div", class: 'a').size).to eq 2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "handles negated classes" do
|
||||||
|
expect(string.all(:custom_css_selector, "div, p", class: ['b', '!c']).size).to eq 2
|
||||||
|
expect(string.all(:custom_css_selector, "div, p", class: ['!c', '!d', 'b']).size).to eq 1
|
||||||
|
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['b', '!c']).size).to eq 2
|
||||||
|
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!c', '!d', 'b']).size).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
it "works with 'special' characters" do
|
it "works with 'special' characters" do
|
||||||
expect(string.find(:custom_css_selector, "input", class: ".special")[:id]).to eq 'file'
|
expect(string.find(:custom_css_selector, "input", class: ".special")[:id]).to eq 'file'
|
||||||
expect(string.find(:custom_css_selector, "input", class: "2checkbox")[:id]).to eq '2checkbox'
|
expect(string.find(:custom_css_selector, "input", class: "2checkbox")[:id]).to eq '2checkbox'
|
||||||
|
|
Loading…
Reference in a new issue