Merge branch 'master' of git://github.com/robholland/capybara

This commit is contained in:
Aslak Hellesøy 2009-12-07 10:38:00 +01:00
commit 76bda6e558
10 changed files with 153 additions and 49 deletions

View File

@ -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...

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

35
spec/public/jquery-ui.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@ -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')

View File

@ -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>

View File

@ -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>