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:
parent
cd2b411ea2
commit
364affa757
10 changed files with 97 additions and 21 deletions
|
@ -21,12 +21,13 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
autoload :Server, 'capybara/server'
|
||||
autoload :Server, 'capybara/server'
|
||||
autoload :Session, 'capybara/session'
|
||||
autoload :Node, 'capybara/node'
|
||||
autoload :XPath, 'capybara/xpath'
|
||||
autoload :Node, 'capybara/node'
|
||||
autoload :XPath, 'capybara/xpath'
|
||||
|
||||
module Driver
|
||||
autoload :Base, 'capybara/driver/base'
|
||||
autoload :RackTest, 'capybara/driver/rack_test_driver'
|
||||
autoload :Culerity, 'capybara/driver/culerity_driver'
|
||||
autoload :Selenium, 'capybara/driver/selenium_driver'
|
||||
|
|
20
lib/capybara/driver/base.rb
Normal file
20
lib/capybara/driver/base.rb
Normal 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
|
|
@ -1,6 +1,6 @@
|
|||
require 'culerity'
|
||||
|
||||
class Capybara::Driver::Culerity
|
||||
class Capybara::Driver::Culerity < Capybara::Driver::Base
|
||||
class Node < Capybara::Node
|
||||
def text
|
||||
node.text
|
||||
|
@ -69,6 +69,15 @@ class Capybara::Driver::Culerity
|
|||
def find(selector)
|
||||
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
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'rack/test'
|
|||
require 'nokogiri'
|
||||
require 'cgi'
|
||||
|
||||
class Capybara::Driver::RackTest
|
||||
class Capybara::Driver::RackTest < Capybara::Driver::Base
|
||||
class Node < Capybara::Node
|
||||
def text
|
||||
node.text
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'selenium-webdriver'
|
||||
|
||||
class Capybara::Driver::Selenium
|
||||
class Capybara::Driver::Selenium < Capybara::Driver::Base
|
||||
class Node < Capybara::Node
|
||||
def text
|
||||
node.text
|
||||
|
@ -83,6 +83,15 @@ class Capybara::Driver::Selenium
|
|||
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
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -38,37 +38,37 @@ module Capybara
|
|||
end
|
||||
|
||||
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
|
||||
field.set(options[:with])
|
||||
end
|
||||
|
||||
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
|
||||
field.set(true)
|
||||
end
|
||||
|
||||
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
|
||||
field.set(true)
|
||||
end
|
||||
|
||||
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
|
||||
field.set(false)
|
||||
end
|
||||
|
||||
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
|
||||
field.select(value)
|
||||
end
|
||||
|
||||
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
|
||||
field.set(path)
|
||||
end
|
||||
|
@ -133,25 +133,22 @@ module Capybara
|
|||
end
|
||||
|
||||
def find_field(locator)
|
||||
get(XPath.field(locator))
|
||||
fetch(XPath.field(locator))
|
||||
end
|
||||
alias_method :field_labeled, :find_field
|
||||
|
||||
def find_link(locator)
|
||||
get(XPath.link(locator))
|
||||
fetch(XPath.link(locator))
|
||||
end
|
||||
|
||||
def find_button(locator)
|
||||
get(XPath.button(locator))
|
||||
fetch(XPath.button(locator))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get(xpath)
|
||||
xpath.paths.find do |path|
|
||||
path = all(path).first
|
||||
return path if path
|
||||
end
|
||||
def fetch(xpath)
|
||||
driver.fetch(*xpath.paths.map { |path| current_scope.to_s + path })
|
||||
end
|
||||
|
||||
def css_to_xpath(css)
|
||||
|
|
|
@ -19,5 +19,6 @@ describe Capybara::Session do
|
|||
end
|
||||
|
||||
it_should_behave_like "session"
|
||||
it_should_behave_like "session with javascript support"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,5 +19,6 @@ describe Capybara::Session do
|
|||
end
|
||||
|
||||
it_should_behave_like "session"
|
||||
it_should_behave_like "session with javascript support"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -790,6 +790,33 @@ shared_examples_for "session" do
|
|||
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
|
||||
context 'with non-existant driver' do
|
||||
it "should raise an error" do
|
||||
|
|
|
@ -11,10 +11,19 @@
|
|||
$('#drag').draggable();
|
||||
$('#drop').droppable({
|
||||
drop: function(event, ui) {
|
||||
ui.draggable.remove()
|
||||
ui.draggable.remove();
|
||||
$(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>
|
||||
|
@ -30,5 +39,7 @@
|
|||
<div id="drop">
|
||||
<p>It should be dropped here.</p>
|
||||
</div>
|
||||
|
||||
<p><a href="#" id="clickable">Click me</a></p>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue