Merge branch 'master' of git://github.com/robholland/capybara
This commit is contained in:
commit
76bda6e558
|
@ -27,6 +27,12 @@ class Capybara::Driver::Culerity
|
|||
node.click
|
||||
end
|
||||
|
||||
def drag_to(element)
|
||||
node.fire_event('mousedown')
|
||||
element.node.fire_event('mousemove')
|
||||
element.node.fire_event('mouseup')
|
||||
end
|
||||
|
||||
def tag_name
|
||||
# FIXME: this might be the dumbest way ever of getting the tag name
|
||||
# there has to be something better...
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'rack/test'
|
||||
require 'nokogiri'
|
||||
require 'cgi'
|
||||
|
||||
class Capybara::Driver::RackTest
|
||||
class Node < Capybara::Node
|
||||
|
@ -59,53 +60,39 @@ class Capybara::Driver::RackTest
|
|||
|
||||
class Form < Node
|
||||
def params(button)
|
||||
params = []
|
||||
inputs = node.xpath(".//input[@type='text']", ".//input[@type='hidden']", ".//input[@type='password']").map do |input|
|
||||
[input['name'].to_s, input['value'].to_s]
|
||||
params = {}
|
||||
node.xpath(".//input[@type='text' or @type='hidden' or @type='password']").map do |input|
|
||||
merge_param!(params, input['name'].to_s, input['value'].to_s)
|
||||
end
|
||||
params.concat(inputs)
|
||||
inputs = node.xpath(".//textarea").map do |textarea|
|
||||
[textarea['name'].to_s, textarea.text.to_s]
|
||||
node.xpath(".//textarea").map do |textarea|
|
||||
merge_param!(params, textarea['name'].to_s, textarea.text.to_s)
|
||||
end
|
||||
params.concat(inputs)
|
||||
inputs = node.xpath(".//input[@type='radio']").map do |input|
|
||||
[input['name'].to_s, input['value'].to_s] if input['checked']
|
||||
node.xpath(".//input[@type='radio' or @type='checkbox']").map do |input|
|
||||
merge_param!(params, input['name'].to_s, input['value'].to_s) if input['checked']
|
||||
end
|
||||
params.concat(inputs)
|
||||
inputs = node.xpath(".//input[@type='checkbox']").map do |input|
|
||||
[input['name'].to_s, input['value'].to_s] if input['checked']
|
||||
end
|
||||
params.concat(inputs)
|
||||
inputs = node.xpath(".//select").map do |select|
|
||||
node.xpath(".//select").map do |select|
|
||||
option = select.xpath(".//option[@selected]").first
|
||||
option ||= select.xpath('.//option').first
|
||||
option ? [select['name'].to_s, (option['value'] || option.text).to_s] : nil
|
||||
merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option
|
||||
end
|
||||
params.concat(inputs)
|
||||
inputs = node.xpath(".//input[@type='file']").map do |input|
|
||||
node.xpath(".//input[@type='file']").map do |input|
|
||||
if input['value'].to_s.any?
|
||||
if multipart?
|
||||
[input['name'].to_s, Rack::Test::UploadedFile.new(input['value'].to_s)]
|
||||
merge_param!(params, input['name'].to_s, Rack::Test::UploadedFile.new(input['value'].to_s))
|
||||
else
|
||||
[input['name'].to_s, File.basename(input['value'].to_s)]
|
||||
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
|
||||
end
|
||||
end
|
||||
end
|
||||
params.concat(inputs)
|
||||
params.compact!
|
||||
params.push [button[:name], button[:value]] if button[:name]
|
||||
if multipart?
|
||||
params.inject({}) { |agg, (key, value)| agg[key] = value; agg }
|
||||
else
|
||||
params.map { |key, value| "#{key}=#{value}" }.join('&')
|
||||
end
|
||||
merge_param!(params, button[:name], button[:value]) if button[:name]
|
||||
params
|
||||
end
|
||||
|
||||
def submit(button)
|
||||
if post?
|
||||
driver.submit(node['action'].to_s, params(button))
|
||||
driver.submit(node['action'].to_s, params(button))
|
||||
else
|
||||
driver.visit(node['action'].to_s.split('?').first + '?' + params(button))
|
||||
driver.visit(node['action'].to_s, params(button))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -116,6 +103,21 @@ class Capybara::Driver::RackTest
|
|||
def post?
|
||||
self[:method] =~ /post/i
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def merge_param!(params, key, value)
|
||||
collection = key.sub!(/\[\]$/, '')
|
||||
if collection
|
||||
if params[key]
|
||||
params[key] << value
|
||||
else
|
||||
params[key] = [value]
|
||||
end
|
||||
else
|
||||
params[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include ::Rack::Test::Methods
|
||||
|
@ -128,8 +130,8 @@ class Capybara::Driver::RackTest
|
|||
@app = app
|
||||
end
|
||||
|
||||
def visit(path)
|
||||
get(path)
|
||||
def visit(path, attributes = {})
|
||||
get(path, attributes)
|
||||
follow_redirect! while response.redirect?
|
||||
cache_body
|
||||
end
|
||||
|
@ -137,9 +139,9 @@ class Capybara::Driver::RackTest
|
|||
def submit(path, attributes)
|
||||
post(path, attributes)
|
||||
follow_redirect! while response.redirect?
|
||||
cache_body
|
||||
cache_body
|
||||
end
|
||||
|
||||
|
||||
def find(selector)
|
||||
html.xpath(selector).map { |node| Node.new(self, node) }
|
||||
end
|
||||
|
|
|
@ -38,6 +38,10 @@ class Capybara::Driver::Selenium
|
|||
node.click
|
||||
end
|
||||
|
||||
def drag_to(element)
|
||||
node.drag_and_drop_on(element.node)
|
||||
end
|
||||
|
||||
def tag_name
|
||||
node.tag_name
|
||||
end
|
||||
|
|
|
@ -30,6 +30,10 @@ class Capybara::Node
|
|||
raise "Not implemented"
|
||||
end
|
||||
|
||||
def drag_to(element)
|
||||
raise "Not implemented"
|
||||
end
|
||||
|
||||
def tag_name
|
||||
raise "Not implemented"
|
||||
end
|
||||
|
|
|
@ -165,21 +165,16 @@ module Capybara
|
|||
end
|
||||
|
||||
def find_field_by_id(locator, *kinds)
|
||||
kinds.each do |kind|
|
||||
path = FIELDS_PATHS[kind]
|
||||
element = find(path.call(locator)).first
|
||||
return element if element
|
||||
end
|
||||
return nil
|
||||
field_locator = kinds.map { |kind| FIELDS_PATHS[kind].call(locator) }.join("|")
|
||||
element = find(field_locator).first
|
||||
return element
|
||||
end
|
||||
|
||||
def find_field_by_label(locator, *kinds)
|
||||
kinds.each do |kind|
|
||||
label = find("//label[contains(.,'#{locator}')]").first
|
||||
if label
|
||||
element = find_field_by_id(label[:for], kind)
|
||||
return element if element
|
||||
end
|
||||
label = find("//label[text()='#{locator}']").first || find("//label[contains(.,'#{locator}')]").first
|
||||
if label
|
||||
element = find_field_by_id(label[:for], *kinds)
|
||||
return element if element
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
|
|
@ -69,4 +69,14 @@ shared_examples_for "driver with javascript support" do
|
|||
@driver.find('//p').first.text.should == 'I changed it'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#drag_to' do
|
||||
it "should drag and drop an object" do
|
||||
@driver.visit('/with_js')
|
||||
draggable = @driver.find('//div[@id="drag"]').first
|
||||
droppable = @driver.find('//div[@id="drop"]').first
|
||||
draggable.drag_to(droppable)
|
||||
@driver.find('//div[contains(., "Dropped!")]').should_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -67,6 +67,14 @@ shared_examples_for "session" do
|
|||
@session.visit('/form')
|
||||
end
|
||||
|
||||
context "with multiple values with the same name" do
|
||||
it "should use the latest given value" do
|
||||
@session.check('Terms of Use')
|
||||
@session.click_button('awesome')
|
||||
extract_results(@session)['terms_of_use'].should == '1'
|
||||
end
|
||||
end
|
||||
|
||||
context "with value given on a submit button" do
|
||||
before do
|
||||
@session.click_button('awesome')
|
||||
|
@ -77,6 +85,10 @@ shared_examples_for "session" do
|
|||
@results['first_name'].should == 'John'
|
||||
end
|
||||
|
||||
it "should escape fields when submitting" do
|
||||
@results['phone'].should == '+1 555 7021'
|
||||
end
|
||||
|
||||
it "should serialize and submit password fields" do
|
||||
@results['password'].should == 'seeekrit'
|
||||
end
|
||||
|
@ -205,6 +217,12 @@ shared_examples_for "session" do
|
|||
extract_results(@session)['first_name'].should == 'Harry'
|
||||
end
|
||||
|
||||
it "should favour exact label matches over partial matches" do
|
||||
@session.fill_in('Name', :with => 'Harry Jones')
|
||||
@session.click_button('awesome')
|
||||
extract_results(@session)['name'].should == 'Harry Jones'
|
||||
end
|
||||
|
||||
it "should fill in a textarea by id" do
|
||||
@session.fill_in('form_description', :with => 'Texty text')
|
||||
@session.click_button('awesome')
|
||||
|
|
|
@ -11,11 +11,27 @@
|
|||
<input type="text" name="form[last_name]" value="Smith" id="form_last_name"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="form_name">Name</label>
|
||||
<input type="text" name="form[name]" value="John Smith" id="form_name"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="form_phone">Phone</label>
|
||||
<input type="text" name="form[phone]" value="+1 555 7021" id="form_phone"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="form_password">Password</label>
|
||||
<input type="password" name="form[password]" value="seeekrit" id="form_password"/>
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<label for="form_terms_of_use">Terms of Use</label>
|
||||
<input type="hidden" name="form[terms_of_use]" value="0" id="form_terms_of_use_default">
|
||||
<input type="checkbox" name="form[terms_of_use]" value="1" id="form_terms_of_use">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="form_image">Image</label>
|
||||
<input type="file" name="form[image]" id="form_image"/>
|
||||
|
@ -102,8 +118,8 @@
|
|||
|
||||
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<label for="form_name">Name</label>
|
||||
<input type="file" name="form[name]" id="form_name"/>
|
||||
<label for="form_file_name">File Name</label>
|
||||
<input type="file" name="form[file_name]" id="form_file_name"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -3,10 +3,18 @@
|
|||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||
<title>with_js</title>
|
||||
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="/jquery-ui.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
//<![CDATA[
|
||||
$(function() {
|
||||
$('#change').text('I changed it');
|
||||
$('#drag').draggable();
|
||||
$('#drop').droppable({
|
||||
drop: function(event, ui) {
|
||||
ui.draggable.remove()
|
||||
$(this).html('Dropped!');
|
||||
}
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
|
@ -16,5 +24,11 @@
|
|||
<h1>FooBar</h1>
|
||||
|
||||
<p id="change">This is text</p>
|
||||
<div id="drag">
|
||||
<p>This is a draggable element.</p>
|
||||
</div>
|
||||
<div id="drop">
|
||||
<p>It should be dropped here.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue