diff --git a/lib/capybara/driver/node.rb b/lib/capybara/driver/node.rb index 713dff6a..ceaa1f27 100644 --- a/lib/capybara/driver/node.rb +++ b/lib/capybara/driver/node.rb @@ -20,6 +20,7 @@ module Capybara raise NotImplementedError end + # @param value String or Array. Array is only allowed if node has 'multiple' attribute def set(value) raise NotImplementedError end diff --git a/lib/capybara/node/actions.rb b/lib/capybara/node/actions.rb index d3b04b0e..028ae413 100644 --- a/lib/capybara/node/actions.rb +++ b/lib/capybara/node/actions.rb @@ -135,10 +135,12 @@ module Capybara # page.attach_file(locator, '/path/to/file.png') # # @param [String] locator Which field to attach the file to - # @param [String] path The path of the file that will be attached + # @param [String] path The path of the file that will be attached, or an array of paths # def attach_file(locator, path) - raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s) + (String === path ? [path] : path).each do |p| + raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s) + end find(:file_field, locator).set(path) end end diff --git a/lib/capybara/rack_test/node.rb b/lib/capybara/rack_test/node.rb index 8e4209ca..afe5725a 100644 --- a/lib/capybara/rack_test/node.rb +++ b/lib/capybara/rack_test/node.rb @@ -12,6 +12,9 @@ class Capybara::RackTest::Node < Capybara::Driver::Node end def set(value) + if (Array === value) && !self[:multiple] + raise ArgumentError.new "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" + end if tag_name == 'input' and type == 'radio' other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s driver.dom.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") } @@ -29,7 +32,17 @@ class Capybara::RackTest::Node < Capybara::Driver::Node # Firefox, allowing no input value = value[0...self[:maxlength].to_i] end - native['value'] = value.to_s + if Array === value #Assert multiple attribute is present + value.each do |v| + new_native = native.clone + new_native.remove_attribute('value') + native.add_next_sibling(new_native) + new_native['value'] = v.to_s + end + native.remove + else + native['value'] = value.to_s + end elsif tag_name == "textarea" native.content = value.to_s end diff --git a/lib/capybara/selenium/node.rb b/lib/capybara/selenium/node.rb index 866c2b50..85e32195 100644 --- a/lib/capybara/selenium/node.rb +++ b/lib/capybara/selenium/node.rb @@ -19,12 +19,16 @@ class Capybara::Selenium::Node < Capybara::Driver::Node end def set(value) + if (Array === value) && !self[:multiple] + raise ArgumentError.new "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" + end if tag_name == 'input' and type == 'radio' click elsif tag_name == 'input' and type == 'checkbox' click if value ^ native.attribute('checked').to_s.eql?("true") elsif tag_name == 'input' and type == 'file' - native.send_keys(value.to_s) + path_names = value.to_s.empty? ? [] : value + native.send_keys(*path_names) elsif tag_name == 'textarea' or tag_name == 'input' native.send_keys(("\b" * native[:value].size) + value.to_s) end diff --git a/lib/capybara/spec/fixtures/another_test_file.txt b/lib/capybara/spec/fixtures/another_test_file.txt new file mode 100644 index 00000000..ba7f2270 --- /dev/null +++ b/lib/capybara/spec/fixtures/another_test_file.txt @@ -0,0 +1 @@ +ThisIsTheOtherTestFile diff --git a/lib/capybara/spec/session/attach_file_spec.rb b/lib/capybara/spec/session/attach_file_spec.rb index 16d52f2c..e27ae71a 100644 --- a/lib/capybara/spec/session/attach_file_spec.rb +++ b/lib/capybara/spec/session/attach_file_spec.rb @@ -1,6 +1,7 @@ Capybara::SpecHelper.spec "#attach_file" do before do @test_file_path = File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__)) + @another_test_file_path = File.expand_path('../fixtures/another_test_file.txt', File.dirname(__FILE__)) @test_jpg_file_path = File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__)) @session.visit('/form') end @@ -11,7 +12,7 @@ Capybara::SpecHelper.spec "#attach_file" do @session.click_button('awesome') extract_results(@session)['image'].should == File.basename(__FILE__) end - + it "should set a file path by label" do @session.attach_file "Image", __FILE__ @session.click_button('awesome') @@ -54,12 +55,22 @@ Capybara::SpecHelper.spec "#attach_file" do @session.click_button 'Upload Single' @session.should have_content('image/jpeg') end - - it "should not break when using HTML5 multiple file input" do + + it "should not break when using HTML5 multiple file input" do @session.attach_file "Multiple Documents", @test_file_path @session.click_button('Upload Multiple') + @session.body.should include("1 | ")#number of files @session.should have_content(File.read(@test_file_path)) end + + it "should not break when using HTML5 multiple file input uploading multiple files" do + pending "Selenium is buggy on this, see http://code.google.com/p/selenium/issues/detail?id=2239" if @session.respond_to?(:mode) && @session.mode == :selenium + @session.attach_file "Multiple Documents", [@test_file_path, @another_test_file_path] + @session.click_button('Upload Multiple') + @session.body.should include("2 | ")#number of files + @session.body.should include(File.read(@test_file_path)) + @session.body.should include(File.read(@another_test_file_path)) + end end context "with a locator that doesn't exist" do diff --git a/lib/capybara/spec/test_app.rb b/lib/capybara/spec/test_app.rb index 02d2717b..0f3e7d3b 100644 --- a/lib/capybara/spec/test_app.rb +++ b/lib/capybara/spec/test_app.rb @@ -151,9 +151,11 @@ class TestApp < Sinatra::Base post '/upload_multiple' do begin - buffer = [] - buffer << "Content-type: #{params[:form][:multiple_documents][0][:type]}" - buffer << "File content: #{params[:form][:multiple_documents][0][:tempfile].read}" + buffer = ["#{params[:form][:multiple_documents].size}"] + params[:form][:multiple_documents].each do |doc| + buffer << "Content-type: #{doc[:type]}" + buffer << "File content: #{doc[:tempfile].read}" + end buffer.join(' | ') rescue 'No files uploaded'