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

Automatically wait for asynchonous loading

This commit is contained in:
Jonas Nicklas 2009-12-09 21:43:40 +01:00
parent cd2b411ea2
commit 364affa757
10 changed files with 97 additions and 21 deletions

View file

@ -21,12 +21,13 @@ module Capybara
end end
end end
autoload :Server, 'capybara/server' autoload :Server, 'capybara/server'
autoload :Session, 'capybara/session' autoload :Session, 'capybara/session'
autoload :Node, 'capybara/node' autoload :Node, 'capybara/node'
autoload :XPath, 'capybara/xpath' autoload :XPath, 'capybara/xpath'
module Driver module Driver
autoload :Base, 'capybara/driver/base'
autoload :RackTest, 'capybara/driver/rack_test_driver' autoload :RackTest, 'capybara/driver/rack_test_driver'
autoload :Culerity, 'capybara/driver/culerity_driver' autoload :Culerity, 'capybara/driver/culerity_driver'
autoload :Selenium, 'capybara/driver/selenium_driver' autoload :Selenium, 'capybara/driver/selenium_driver'

View file

@ -0,0 +1,20 @@
class Capybara::Driver::Base
def visit(path)
raise "Not implemented"
end
def find(query)
raise "Not implemented"
end
def body
raise "Not implemented"
end
def fetch(*paths)
paths.find do |path|
result = find(path).first
return result if result
end
end
end

View file

@ -1,6 +1,6 @@
require 'culerity' require 'culerity'
class Capybara::Driver::Culerity class Capybara::Driver::Culerity < Capybara::Driver::Base
class Node < Capybara::Node class Node < Capybara::Node
def text def text
node.text node.text
@ -69,6 +69,15 @@ class Capybara::Driver::Culerity
def find(selector) def find(selector)
browser.elements_by_xpath(selector).map { |node| Node.new(self, node) } browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
end end
def fetch(*paths)
8.times do
result = super
return result if result
sleep(0.1)
end
nil
end
private private

View file

@ -2,7 +2,7 @@ require 'rack/test'
require 'nokogiri' require 'nokogiri'
require 'cgi' require 'cgi'
class Capybara::Driver::RackTest class Capybara::Driver::RackTest < Capybara::Driver::Base
class Node < Capybara::Node class Node < Capybara::Node
def text def text
node.text node.text

View file

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

View file

@ -38,37 +38,37 @@ module Capybara
end end
def fill_in(locator, options={}) def fill_in(locator, options={})
field = get(XPath.fillable_field(locator)) field = fetch(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 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]) field.set(options[:with])
end end
def choose(locator) def choose(locator)
field = get(XPath.radio_button(locator)) field = fetch(XPath.radio_button(locator))
raise Capybara::ElementNotFound, "cannot choose field, no radio button with id or label '#{locator}' found" unless field raise Capybara::ElementNotFound, "cannot choose field, no radio button with id or label '#{locator}' found" unless field
field.set(true) field.set(true)
end end
def check(locator) def check(locator)
field = get(XPath.checkbox(locator)) field = fetch(XPath.checkbox(locator))
raise Capybara::ElementNotFound, "cannot check field, no checkbox with id or label '#{locator}' found" unless field raise Capybara::ElementNotFound, "cannot check field, no checkbox with id or label '#{locator}' found" unless field
field.set(true) field.set(true)
end end
def uncheck(locator) def uncheck(locator)
field = get(XPath.checkbox(locator)) field = fetch(XPath.checkbox(locator))
raise Capybara::ElementNotFound, "cannot uncheck field, no checkbox with id or label '#{locator}' found" unless field raise Capybara::ElementNotFound, "cannot uncheck field, no checkbox with id or label '#{locator}' found" unless field
field.set(false) field.set(false)
end end
def select(value, options={}) def select(value, options={})
field = get(XPath.select(options[:from])) field = fetch(XPath.select(options[:from]))
raise Capybara::ElementNotFound, "cannot select option, no select box with id or label '#{options[:from]}' found" unless field raise Capybara::ElementNotFound, "cannot select option, no select box with id or label '#{options[:from]}' found" unless field
field.select(value) field.select(value)
end end
def attach_file(locator, path) def attach_file(locator, path)
field = get(XPath.file_field(locator)) field = fetch(XPath.file_field(locator))
raise Capybara::ElementNotFound, "cannot attach file, no file field with id or label '#{locator}' found" unless field raise Capybara::ElementNotFound, "cannot attach file, no file field with id or label '#{locator}' found" unless field
field.set(path) field.set(path)
end end
@ -133,25 +133,22 @@ module Capybara
end end
def find_field(locator) def find_field(locator)
get(XPath.field(locator)) fetch(XPath.field(locator))
end end
alias_method :field_labeled, :find_field alias_method :field_labeled, :find_field
def find_link(locator) def find_link(locator)
get(XPath.link(locator)) fetch(XPath.link(locator))
end end
def find_button(locator) def find_button(locator)
get(XPath.button(locator)) fetch(XPath.button(locator))
end end
private private
def get(xpath) def fetch(xpath)
xpath.paths.find do |path| driver.fetch(*xpath.paths.map { |path| current_scope.to_s + path })
path = all(path).first
return path if path
end
end end
def css_to_xpath(css) def css_to_xpath(css)

View file

@ -19,5 +19,6 @@ describe Capybara::Session do
end end
it_should_behave_like "session" it_should_behave_like "session"
it_should_behave_like "session with javascript support"
end end
end end

View file

@ -19,5 +19,6 @@ describe Capybara::Session do
end end
it_should_behave_like "session" it_should_behave_like "session"
it_should_behave_like "session with javascript support"
end end
end end

View file

@ -790,6 +790,33 @@ shared_examples_for "session" do
end end
end end
shared_examples_for "session with javascript support" do
describe '#click_link' do
it "should wait for asynchronous load" do
@session.visit('/with_js')
@session.click_link('Click me')
@session.click_link('Has been clicked')
end
end
describe '#click_button' do
it "should wait for asynchronous load" do
@session.visit('/with_js')
@session.click_link('Click me')
@session.click_button('New Here')
end
end
describe '#fill_in' do
it "should wait for asynchronous load" do
@session.visit('/with_js')
@session.click_link('Click me')
@session.fill_in('new_field', :with => 'Testing...')
end
end
end
describe Capybara::Session do describe Capybara::Session do
context 'with non-existant driver' do context 'with non-existant driver' do
it "should raise an error" do it "should raise an error" do

View file

@ -11,10 +11,19 @@
$('#drag').draggable(); $('#drag').draggable();
$('#drop').droppable({ $('#drop').droppable({
drop: function(event, ui) { drop: function(event, ui) {
ui.draggable.remove() ui.draggable.remove();
$(this).html('Dropped!'); $(this).html('Dropped!');
} }
}); });
$('#clickable').click(function() {
var link = $(this);
setTimeout(function() {
$(link).after('<a href="#">Has been clicked</a>');
$(link).after('<input type="submit" value="New Here">');
$(link).after('<input type="text" id="new_field">');
}, 500);
return false;
});
}); });
//]]> //]]>
</script> </script>
@ -30,5 +39,7 @@
<div id="drop"> <div id="drop">
<p>It should be dropped here.</p> <p>It should be dropped here.</p>
</div> </div>
<p><a href="#" id="clickable">Click me</a></p>
</body> </body>
</html> </html>