Add support for :disabled as a filter, instead of being harcoded, closes #982

This commit is contained in:
Jonas Nicklas 2013-03-08 14:18:56 +01:00
parent 8971237512
commit 9f516cfd7a
6 changed files with 86 additions and 6 deletions

View File

@ -45,8 +45,12 @@ module Capybara
when :visible then return false unless node.visible?
when :hidden then return false if node.visible?
end
selector.custom_filters.each do |name, block|
return false if options.has_key?(name) and not block.call(node, options[name])
selector.custom_filters.each do |name, filter|
if options.has_key?(name)
return false unless filter.matches?(node, options[name])
elsif filter.default?
return false unless filter.matches?(node, filter.default)
end
end
true
end

View File

@ -1,7 +1,26 @@
module Capybara
class Selector
attr_reader :name, :custom_filters, :format
class Filter
def initialize(name, block, options={})
@name = name
@block = block
@options = options
end
def default?
@options.has_key?(:default)
end
def default
@options[:default]
end
def matches?(node, value)
@block.call(node, value)
end
end
attr_reader :name, :custom_filters, :format
class << self
def all
@ -61,8 +80,8 @@ module Capybara
@match and @match.call(locator)
end
def filter(name, &block)
@custom_filters[name] = block
def filter(name, options={}, &block)
@custom_filters[name] = Filter.new(name, block, options)
end
end
end
@ -83,6 +102,7 @@ Capybara.add_selector(:field) do
xpath { |locator| XPath::HTML.field(locator) }
filter(:checked) { |node, value| not(value ^ node.checked?) }
filter(:unchecked) { |node, value| (value ^ node.checked?) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
filter(:with) { |node, with| node.value == with }
filter(:type) do |node, type|
if ['textarea', 'select'].include?(type)
@ -100,6 +120,7 @@ end
Capybara.add_selector(:link_or_button) do
label "link or button"
xpath { |locator| XPath::HTML.link_or_button(locator) }
filter(:disabled, :default => false) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
end
Capybara.add_selector(:link) do
@ -111,11 +132,13 @@ end
Capybara.add_selector(:button) do
xpath { |locator| XPath::HTML.button(locator) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:fillable_field) do
label "field"
xpath { |locator| XPath::HTML.fillable_field(locator) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:radio_button) do
@ -123,12 +146,14 @@ Capybara.add_selector(:radio_button) do
xpath { |locator| XPath::HTML.radio_button(locator) }
filter(:checked) { |node, value| not(value ^ node.checked?) }
filter(:unchecked) { |node, value| (value ^ node.checked?) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:checkbox) do
xpath { |locator| XPath::HTML.checkbox(locator) }
filter(:checked) { |node, value| not(value ^ node.checked?) }
filter(:unchecked) { |node, value| (value ^ node.checked?) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:select) do
@ -143,6 +168,7 @@ Capybara.add_selector(:select) do
actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text }
[selected].flatten.sort == actual.sort
end
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:option) do
@ -152,6 +178,7 @@ end
Capybara.add_selector(:file_field) do
label "file field"
xpath { |locator| XPath::HTML.file_field(locator) }
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
end
Capybara.add_selector(:table) do

View File

@ -79,4 +79,34 @@ Capybara::SpecHelper.spec '#click_link_or_button' do
end.to raise_error(Capybara::ElementNotFound, msg)
end
end
context "with :disabled option" do
it "ignores disabled buttons when false" do
@session.visit('/form')
expect do
@session.click_link_or_button('Disabled button', :disabled => false)
end.to raise_error(Capybara::ElementNotFound)
end
it "ignores disabled buttons by default" do
@session.visit('/form')
expect do
@session.click_link_or_button('Disabled button')
end.to raise_error(Capybara::ElementNotFound)
end
it "happily clicks on links which incorrectly have the disabled attribute" do
@session.visit('/with_html')
@session.click_link_or_button('Disabled link')
@session.should have_content("Bar")
end
it "does nothing when button is disabled" do
@session.visit('/form')
expect do
@session.click_link_or_button('Disabled button', :disabled => false)
end.to raise_error(Capybara::ElementNotFound)
end
end
end

View File

@ -37,4 +37,22 @@ Capybara::SpecHelper.spec '#find_field' do
end.to raise_error(Capybara::ElementNotFound)
end
end
context "with :disabled option" do
it "should find disabled fields when true" do
@session.find_field("Disabled Checkbox", :disabled => true)[:name].should == "form[disabled_checkbox]"
end
it "should not find disabled fields when false" do
expect do
@session.find_field("Disabled Checkbox", :disabled => false)
end.to raise_error(Capybara::ElementNotFound)
end
it "should not find disabled fields by default" do
expect do
@session.find_field("Disabled Checkbox")
end.to raise_error(Capybara::ElementNotFound)
end
end
end

View File

@ -49,6 +49,7 @@ banana</textarea>
<input type="text" checked="checked" id="checked_field">
<a href="/redirect"><img width="20" height="20" alt="very fine image" /></a>
<a href="/with_simple_html"><img width="20" height="20" alt="fine image" /></a>
<a href="/with_simple_html" disabled="disabled">Disabled link</a>
<a href="?query_string=true">Naked Query String</a>
<% if params[:query_string] %>

2
xpath

@ -1 +1 @@
Subproject commit 4c7c3351f970f14635e670239e11f81fffb07717
Subproject commit 6429e5a84a7893d514be1cb04d3ff250b74ab1f8