changed Selector API. Now more like RSpec matchers

This commit is contained in:
Jonas Nicklas 2010-10-22 13:29:08 +02:00
parent 8b4857da81
commit b13e4d3887
4 changed files with 57 additions and 21 deletions

View File

@ -382,19 +382,28 @@ Alternatively you can set the default selector to XPath:
Capybara allows you to add custom selectors, which can be very useful if you
find yourself using the same kinds of selectors very often:
Capybara::Selector.add(:id) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
Capybara::Selector.add(:row) { |num| ".//tbody/tr[#{num}]" }
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
end
These must always return an XPath expression as a String, or an XPath expression
generated through the XPath gem. You can now use these selectors like this:
Capybara.add_selector(:row) do
xpath { |num| ".//tbody/tr[#{num}]" }
end
The block given to xpath must always return an XPath expression as a String, or
an XPath expression generated through the XPath gem. You can now use these
selectors like this:
find(:id, 'post_123')
find(:row, 3)
You can specify an optional :for option which will automatically use the
selector if it matches the argument to find using ===:
You can specify an optional match option which will automatically use the
selector if it matches the argument:
Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
match { |value| value.is_a?(Symbol) }
end
Now use it like this:

View File

@ -64,6 +64,10 @@ module Capybara
drivers[name] = block
end
def add_selector(name, &block)
Capybara::Selector.add(name, &block)
end
def drivers
@drivers ||= {}
end

View File

@ -1,14 +1,14 @@
module Capybara
class Selector
attr_reader :name, :options, :block
attr_reader :name
class << self
def all
@selectors ||= {}
end
def add(name, options={}, &block)
all[name.to_sym] = Capybara::Selector.new(name.to_sym, options, &block)
def add(name, &block)
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
end
def remove(name)
@ -31,22 +31,40 @@ module Capybara
end
end
def initialize(name, options={}, &block)
def initialize(name, &block)
@name = name
@options = options
@block = block
instance_eval(&block)
end
def xpath(&block)
@xpath = block if block
@xpath
end
def match(&block)
@match = block if block
@match
end
def call(locator)
@block.call(locator)
@xpath.call(locator)
end
def match?(locator)
@options[:for] and @options[:for] === locator
@match and @match.call(locator)
end
end
end
Capybara::Selector.add(:xpath) { |xpath| xpath }
Capybara::Selector.add(:css) { |css| XPath.css(css) }
Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
Capybara.add_selector(:xpath) do
xpath { |xpath| xpath }
end
Capybara.add_selector(:css) do
xpath { |css| XPath.css(css) }
end
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
match { |value| value.is_a?(Symbol) }
end

View File

@ -64,7 +64,9 @@ shared_examples_for "find" do
context "with custom selector" do
it "should use the custom selector" do
Capybara::Selector.add(:monkey) { |name| ".//*[@id='#{name}_monkey']" }
Capybara.add_selector(:monkey) do
xpath { |name| ".//*[@id='#{name}_monkey']" }
end
@session.find(:monkey, 'john').text.should == 'Monkey John'
@session.find(:monkey, 'paul').text.should == 'Monkey Paul'
end
@ -72,7 +74,10 @@ shared_examples_for "find" do
context "with custom selector with :for option" do
it "should use the selector when it matches the :for option" do
Capybara::Selector.add(:monkey, :for => Fixnum) { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
Capybara.add_selector(:monkey) do
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
match { |value| value.is_a?(Fixnum) }
end
@session.find(:monkey, '2').text.should == 'Monkey Paul'
@session.find(1).text.should == 'Monkey John'
@session.find(2).text.should == 'Monkey Paul'
@ -115,7 +120,7 @@ shared_examples_for "find" do
it "should find the first element using the given locator" do
@session.within(:xpath, "//div[@id='for_bar']") do
@session.find('.//li').text.should =~ /With Simple HTML/
end
end
end
end
end