Added attaching files and file uploads

This commit is contained in:
Jonas Nicklas 2009-11-12 17:07:43 +01:00
parent 48993cf7bb
commit c344a92387
5 changed files with 84 additions and 26 deletions

View File

@ -13,7 +13,7 @@ class Webcat::Driver::RackTest
end
def set(value)
if tag_name == 'input' and %w(text password hidden).include?(type)
if tag_name == 'input' and %w(text password hidden file).include?(type)
node['value'] = value.to_s
elsif tag_name == 'input' and type == 'radio'
session.html.xpath("//input[@name='#{self[:name]}']").each { |node| node.remove_attribute("checked") }
@ -60,40 +60,50 @@ class Webcat::Driver::RackTest
class Form < Node
def params(button)
params = []
params << node.xpath(".//input[@type='text']", ".//input[@type='hidden']", ".//input[@type='password']").inject([]) do |agg, input|
agg << param(input['name'].to_s, input['value'].to_s)
params += node.xpath(".//input[@type='text']", ".//input[@type='hidden']", ".//input[@type='password']").inject([]) do |agg, input|
agg << [input['name'].to_s, input['value'].to_s]
agg
end
params << node.xpath(".//textarea").inject([]) do |agg, textarea|
agg << param(textarea['name'].to_s, textarea.text.to_s)
params += node.xpath(".//textarea").inject([]) do |agg, textarea|
agg << [textarea['name'].to_s, textarea.text.to_s]
agg
end
params << node.xpath(".//input[@type='radio']").inject([]) do |agg, input|
agg << param(input['name'].to_s, input['value'].to_s) if input['checked']
params += node.xpath(".//input[@type='radio']").inject([]) do |agg, input|
agg << [input['name'].to_s, input['value'].to_s] if input['checked']
agg
end
params << node.xpath(".//input[@type='checkbox']").inject([]) do |agg, input|
agg << param(input['name'].to_s, input['value'].to_s) if input['checked']
params += node.xpath(".//input[@type='checkbox']").inject([]) do |agg, input|
agg << [input['name'].to_s, input['value'].to_s] if input['checked']
agg
end
params << node.xpath(".//select").inject([]) do |agg, select|
params += node.xpath(".//select").inject([]) do |agg, select|
option = select.xpath(".//option[@selected]").first
option ||= select.xpath('.//option').first
agg << param(select['name'].to_s, (option['value'] || option.text).to_s) if option
agg << [select['name'].to_s, (option['value'] || option.text).to_s] if option
agg
end
params << param(button[:name], button[:value]) if button[:name]
params.join('&')
params += node.xpath(".//input[@type='file']").inject([]) do |agg, input|
if multipart?
agg << [input['name'].to_s, Rack::Test::UploadedFile.new(input['value'].to_s)]
else
agg << [input['name'].to_s, File.basename(input['value'].to_s)]
end
agg
end
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
end
def submit(button)
session.submit(node['action'].to_s, params(button))
end
private
def param(key, value)
"#{key}=#{value}"
def multipart?
self[:enctype] == "multipart/form-data"
end
end

View File

@ -52,6 +52,10 @@ class Webcat::Session
def select(value, options={})
find_field(options[:from], :select).select(value)
end
def attach_file(locator, path)
find_field(locator, :file_field).set(path)
end
def body
driver.body
@ -78,7 +82,8 @@ private
:radio => proc { |id| "//input[@type='radio'][@id='#{id}']" },
:hidden_field => proc { |id| "//input[@type='hidden'][@id='#{id}']" },
:checkbox => proc { |id| "//input[@type='checkbox'][@id='#{id}']" },
:select => proc { |id| "//select[@id='#{id}']" }
:select => proc { |id| "//select[@id='#{id}']" },
:file_field => proc { |id| "//input[@type='file'][@id='#{id}']" }
}
def find_field_by_id(locator, *kinds)

View File

@ -111,14 +111,6 @@ shared_examples_for "session" do
it "should not serialize a select tag without options" do
@results['tendency'].should be_nil
end
context "with multipart form" do
it "should attach the file"
end
context "with normal form" do
it "should serialize the file path"
end
end
context "with id given" do
@ -264,6 +256,37 @@ shared_examples_for "session" do
end
describe "#attach_file" do
before do
@session.visit('/form')
end
context "with normal form" do
it "should set a file path by id" do
@session.attach_file "form_image", __FILE__
@session.click_button('awesome')
YAML.load(@session.body)['image'].should == File.basename(__FILE__)
end
it "should set a file path by label" do
@session.attach_file "Image", __FILE__
@session.click_button('awesome')
YAML.load(@session.body)['image'].should == File.basename(__FILE__)
end
end
context "with multipart form" do
it "should set a file path by id" do
@session.attach_file "form_document", __FILE__
@session.click_button('Upload')
@session.body.should == File.read(__FILE__)
end
it "should set a file path by label" do
@session.attach_file "Document", __FILE__
@session.click_button('Upload')
@session.body.should == File.read(__FILE__)
end
end
end
end

View File

@ -32,6 +32,10 @@ class TestApp < Sinatra::Base
post '/form' do
params[:form].to_yaml
end
post '/upload' do
params[:form][:document][:tempfile].read
end
end
if __FILE__ == $0

View File

@ -16,6 +16,11 @@
<input type="password" name="form[password]" value="seeekrit" id="form_password"/>
</p>
<p>
<label for="form_image">Image</label>
<input type="file" name="form[image]" id="form_image"/>
</p>
<p>
<input type="hidden" name="form[token]" value="12345" id="form_token"/>
</p>
@ -92,3 +97,14 @@
<input type="submit" name="form[mediocre]" id="mediocre" value="med"/>
<p>
</form>
<form action="/upload" method="post" enctype="multipart/form-data">
<p>
<label for="form_document">Document</label>
<input type="file" name="form[document]" id="form_document"/>
</p>
<p>
<input type="submit" value="Upload"/>
<p>
</form>