diff --git a/lib/webrat.rb b/lib/webrat.rb index 4401f1a..26c8dde 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -35,7 +35,7 @@ module ActionController current_page.save_and_open end - [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| + [:reloads, :fills_in, :clicks_button, :selects, :attaches_file, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| define_method(method_name) do |*args| current_page.send(method_name, *args) end diff --git a/lib/webrat/field.rb b/lib/webrat/field.rb index f6b1a1e..e45a192 100644 --- a/lib/webrat/field.rb +++ b/lib/webrat/field.rb @@ -97,6 +97,21 @@ module Webrat end end + def replace_param_value(params, oval, nval) + output = Hash.new + params.each do |key, value| + case value + when Hash + value = replace_param_value(value, oval, nval) + when Array + value = value.map { |o| o == oval ? nval : oval } + when oval + value = nval + end + output[key] = value + end + output + end end class ButtonField < Field @@ -221,6 +236,15 @@ module Webrat end class FileField < Field + + def to_param + if @value.nil? + super + else + replace_param_value(super, @value, ActionController::TestUploadedFile.new(@value)) + end + end + end class TextField < Field diff --git a/lib/webrat/page.rb b/lib/webrat/page.rb index 65e5056..17fcd0e 100644 --- a/lib/webrat/page.rb +++ b/lib/webrat/page.rb @@ -88,6 +88,17 @@ module Webrat option.choose end + # Verifies that an input file field exists on the current page and sets + # its value to the given +file+, so that the file will be uploaded + # along with the form. + # + # Example: + # attaches_file "Photo", "/path/to/the/photo.jpg" + def attaches_file(id_or_name_or_label, path) + field = find_field(id_or_name_or_label, FileField) + field.set(path) + end + # Saves the currently loaded page out to RAILS_ROOT/tmp/ and opens it in the default # web browser if on OS X. Useful for debugging. # diff --git a/spec/attaches_file_spec.rb b/spec/attaches_file_spec.rb new file mode 100644 index 0000000..30111c1 --- /dev/null +++ b/spec/attaches_file_spec.rb @@ -0,0 +1,62 @@ +require File.expand_path(File.dirname(__FILE__) + "/spec_helper") + +describe "attaches_file" do + before do + @session = ActionController::Integration::Session.new + @session.stubs(:assert_response) + @session.stubs(:get_via_redirect) + @session.stubs(:response).returns(@response=mock) + + @filename = __FILE__ + @uploaded_file = mock + ActionController::TestUploadedFile.stubs(:new).returns(@uploaded_file) + end + + it "should fail if no file field found" do + @response.stubs(:body).returns(<<-EOS) +
+
+ EOS + lambda { @session.attaches_file("Doc", "/some/path") }.should raise_error + end + + it "should submit empty strings for blank file fields" do + @response.stubs(:body).returns(<<-EOS) +
+ + +
+ EOS + @session.expects(:post_via_redirect).with("/widgets", { "widget" => { "file" => "" } }) + @session.clicks_button + end + + it "should submit the attached file" do + @response.stubs(:body).returns(<<-EOS) +
+ + + +
+ EOS + @session.expects(:post_via_redirect).with("/widgets", { "widget" => { "file" => @uploaded_file } }) + @session.attaches_file "Document", @filename + @session.clicks_button + end + + it "should support collections" do + @response.stubs(:body).returns(<<-EOS) +
+ + + + + +
+ EOS + @session.expects(:post_via_redirect).with("/widgets", { "widget" => { "files" => [@uploaded_file, @uploaded_file] } }) + @session.attaches_file "Document", @filename + @session.attaches_file "Spreadsheet", @filename + @session.clicks_button + end +end