From fb01cfaf21ba2b1856ae62c0e5e0ed3bf3fcd210 Mon Sep 17 00:00:00 2001 From: Jonas Nicklas Date: Mon, 2 Jan 2012 12:46:04 +0100 Subject: [PATCH] Allow custom filters --- lib/capybara/selector.rb | 10 +++++++++- lib/capybara/spec/session/find_spec.rb | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/capybara/selector.rb b/lib/capybara/selector.rb index 652d58f7..ef1e14d8 100644 --- a/lib/capybara/selector.rb +++ b/lib/capybara/selector.rb @@ -2,7 +2,7 @@ module Capybara class Selector PROPERTY_OPTION_KEYS = [:text, :visible, :with, :checked, :unchecked, :selected] - attr_reader :name + attr_reader :name, :custom_filters class Normalized attr_accessor :selector, :locator, :options, :xpath_options, :property_options, :xpaths @@ -17,6 +17,9 @@ module Capybara return false if property_options[:checked] and not node.checked? return false if property_options[:unchecked] and node.checked? return false if property_options[:selected] and not has_selected_options?(node, property_options[:selected]) + selector.custom_filters.each do |name, block| + return false if options.has_key?(name) and not block.call(node, options[name]) + end true end @@ -79,6 +82,7 @@ module Capybara def initialize(name, &block) @name = name + @custom_filters = {} instance_eval(&block) end @@ -112,6 +116,10 @@ module Capybara def match?(locator) @match and @match.call(locator) end + + def filter(name, &block) + @custom_filters[name] = block + end end end diff --git a/lib/capybara/spec/session/find_spec.rb b/lib/capybara/spec/session/find_spec.rb index 2e4bfc52..7cfd3250 100644 --- a/lib/capybara/spec/session/find_spec.rb +++ b/lib/capybara/spec/session/find_spec.rb @@ -107,6 +107,25 @@ shared_examples_for "find" do end end + context "with custom selector with custom filter", :focus => true do + before do + Capybara.add_selector(:monkey) do + xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" } + filter(:name) { |node, name| node.text == name } + end + end + + it "should find elements that match the filter" do + @session.find(:monkey, '1', :name => 'Monkey John').text.should == 'Monkey John' + @session.find(:monkey, '2', :name => 'Monkey Paul').text.should == 'Monkey Paul' + end + + it "should not find elements that don't match the filter" do + expect { @session.find(:monkey, '2', :name => 'Monkey John') }.to raise_error(Capybara::ElementNotFound) + expect { @session.find(:monkey, '1', :name => 'Monkey Paul') }.to raise_error(Capybara::ElementNotFound) + end + end + context "with css as default selector" do before { Capybara.default_selector = :css } it "should find the first element using the given locator" do