1
0
Fork 0
mirror of https://github.com/teamcapybara/capybara.git synced 2022-11-09 12:08:07 -05:00

Moved waiting back into session where it belongs

Also expose the new wait_for method
As an added bonus, find and all now accept XPath
instances and handle them correctly
This commit is contained in:
Jonas Nicklas 2009-12-12 21:46:08 +01:00
parent c33e17f326
commit 9c9f3684a9
8 changed files with 117 additions and 42 deletions

View file

@ -11,10 +11,7 @@ class Capybara::Driver::Base
raise "Not implemented"
end
def fetch(*paths)
paths.find do |path|
result = find(path).first
return result if result
end
def wait?
false
end
end

View file

@ -70,14 +70,7 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
end
def fetch(*paths)
8.times do
result = super
return result if result
sleep(0.1)
end
nil
end
def wait?; true; end
private

View file

@ -83,15 +83,8 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
def find(selector)
driver.find_elements(:xpath, selector).map { |node| Node.new(self, node) }
end
def fetch(*paths)
8.times do
result = super
return result if result
sleep(0.1)
end
nil
end
def wait?; true; end
private

View file

@ -50,7 +50,7 @@ module Capybara
:visit, :body, :click_link, :click_button, :fill_in, :choose, :has_xpath?, :has_css?,
:check, :uncheck, :attach_file, :select, :has_content?, :within, :within_fieldset,
:within_table, :save_and_open_page, :find, :find_field, :find_link, :find_button,
:field_labeled, :all
:field_labeled, :all, :wait_for
]
SESSION_METHODS.each do |method|
class_eval <<-RUBY, __FILE__, __LINE__+1

View file

@ -26,49 +26,49 @@ module Capybara
end
def click_link(locator)
link = find_link(locator)
link = wait_for(XPath.link(locator))
raise Capybara::ElementNotFound, "no link with title, id or text '#{locator}' found" unless link
link.click
end
def click_button(locator)
button = find_button(locator)
button = wait_for(XPath.button(locator))
raise Capybara::ElementNotFound, "no button with value or id or text '#{locator}' found" unless button
button.click
end
def fill_in(locator, options={})
field = fetch_xpath(XPath.fillable_field(locator))
field = wait_for(XPath.fillable_field(locator))
raise Capybara::ElementNotFound, "cannot fill in, no text field, text area or password field with id or label '#{locator}' found" unless field
field.set(options[:with])
end
def choose(locator)
field = fetch_xpath(XPath.radio_button(locator))
field = wait_for(XPath.radio_button(locator))
raise Capybara::ElementNotFound, "cannot choose field, no radio button with id or label '#{locator}' found" unless field
field.set(true)
end
def check(locator)
field = fetch_xpath(XPath.checkbox(locator))
field = wait_for(XPath.checkbox(locator))
raise Capybara::ElementNotFound, "cannot check field, no checkbox with id or label '#{locator}' found" unless field
field.set(true)
end
def uncheck(locator)
field = fetch_xpath(XPath.checkbox(locator))
field = wait_for(XPath.checkbox(locator))
raise Capybara::ElementNotFound, "cannot uncheck field, no checkbox with id or label '#{locator}' found" unless field
field.set(false)
end
def select(value, options={})
field = fetch_xpath(XPath.select(options[:from]))
field = wait_for(XPath.select(options[:from]))
raise Capybara::ElementNotFound, "cannot select option, no select box with id or label '#{options[:from]}' found" unless field
field.select(value)
end
def attach_file(locator, path)
field = fetch_xpath(XPath.file_field(locator))
field = wait_for(XPath.file_field(locator))
raise Capybara::ElementNotFound, "cannot attach file, no file field with id or label '#{locator}' found" unless field
field.set(path)
end
@ -100,7 +100,7 @@ module Capybara
def within(kind, scope=nil)
kind, scope = Capybara.default_selector, kind unless scope
scope = css_to_xpath(scope) if kind == :css
raise Capybara::ElementNotFound, "scope '#{scope}' not found on page" unless find(scope)
raise Capybara::ElementNotFound, "scope '#{scope}' not found on page" unless wait_for(scope)
scopes.push(scope)
yield
scopes.pop
@ -124,32 +124,39 @@ module Capybara
end
def all(locator)
locator = current_scope.to_s + locator
driver.find(locator)
XPath.wrap(locator).scope(current_scope).paths.map do |path|
driver.find(path)
end.flatten
end
def find(locator)
all(locator.to_s).first
all(locator).first
end
def wait_for(locator)
return find(locator) unless driver.wait?
8.times do
result = find(locator)
return result if result
sleep(0.1)
end
nil
end
def find_field(locator)
fetch_xpath(XPath.field(locator))
find(XPath.field(locator))
end
alias_method :field_labeled, :find_field
def find_link(locator)
fetch_xpath(XPath.link(locator))
find(XPath.link(locator))
end
def find_button(locator)
fetch_xpath(XPath.button(locator))
find(XPath.button(locator))
end
private
def fetch_xpath(xpath)
driver.fetch(*xpath.paths.map { |path| current_scope.to_s + path })
end
def css_to_xpath(css)
Nokogiri::CSS.xpath_for(css).first

View file

@ -4,6 +4,14 @@ module Capybara
# this will generate an XPath that matches either a text field or a link
class XPath
class << self
def wrap(path)
if path.is_a?(self)
path
else
new(path.to_s)
end
end
def respond_to?(method)
new.respond_to?(method)
end
@ -75,6 +83,10 @@ module Capybara
def file_field(locator)
add_field(locator) { |id| "//input[@type='file'][@id=#{id}]" }
end
def scope(scope)
XPath.new(*paths.map { |p| scope + p })
end
def to_s
@paths.join(' | ')

View file

@ -607,6 +607,13 @@ shared_examples_for "session" do
@session.all('//div').should be_empty
end
it "should accept an XPath instance" do
@session.visit('/form')
@xpath = Capybara::XPath.text_field('Name')
@result = @session.all(@xpath)
@result.map(&:value).should include('Smith', 'John', 'John Smith')
end
context "within a scope" do
before do
@session.visit('/with_scope')
@ -634,6 +641,12 @@ shared_examples_for "session" do
@session.find('//div').should be_nil
end
it "should accept an XPath instance and respect the order of paths" do
@session.visit('/form')
@xpath = Capybara::XPath.text_field('Name')
@session.find(@xpath).value.should == 'John Smith'
end
context "within a scope" do
before do
@session.visit('/with_scope')
@ -646,6 +659,39 @@ shared_examples_for "session" do
end
end
end
describe '#wait_for' do
before do
@session.visit('/with_html')
end
it "should find the first element using the given locator" do
@session.wait_for('//h1').text.should == 'This is a test'
@session.wait_for("//input[@id='test_field']")[:value].should == 'monkey'
end
it "should return nil when nothing was found" do
@session.wait_for('//div').should be_nil
end
it "should accept an XPath instance and respect the order of paths" do
@session.visit('/form')
@xpath = Capybara::XPath.text_field('Name')
@session.wait_for(@xpath).value.should == 'John Smith'
end
context "within a scope" do
before do
@session.visit('/with_scope')
end
it "should find the first element using the given locator" do
@session.within(:xpath, "//div[@id='for_bar']") do
@session.wait_for('//li').text.should =~ /With Simple HTML/
end
end
end
end
describe '#within' do
before do
@ -791,6 +837,14 @@ shared_examples_for "session" do
end
shared_examples_for "session with javascript support" do
describe '#wait_for' do
it "should wait for asynchronous load" do
@session.visit('/with_js')
@session.click_link('Click me')
@session.wait_for("//a[contains(.,'Has been clicked')]")[:href].should == '#'
end
end
describe '#click_link' do
it "should wait for asynchronous load" do
@session.visit('/with_js')

View file

@ -16,6 +16,25 @@ describe Capybara::XPath do
it "should respond to instance methods at the class level" do
Capybara::XPath.should respond_to(:fillable_field)
end
describe '.wrap' do
it "should return an XPath unmodified" do
Capybara::XPath.wrap(@xpath).should == @xpath
end
it "should wrap a string in an xpath object" do
@xpath = Capybara::XPath.wrap('//foo/bar')
@xpath.should be_an_instance_of(Capybara::XPath)
@xpath.paths.should == ['//foo/bar']
end
end
describe '#scope' do
it "should prepend the given scope to all paths" do
@xpath = Capybara::XPath.new('//foo/bar', '//test[@blah=foo]').scope('//quox')
@xpath.paths.should include('//quox//foo/bar', '//quox//test[@blah=foo]')
end
end
describe '#field' do
it "should find any field by id or label" do