diff --git a/lib/capybara/driver/node.rb b/lib/capybara/driver/node.rb index 330b0e6e..41b9f8d5 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 6ce907f0..35dec47d 100644 --- a/lib/capybara/node/actions.rb +++ b/lib/capybara/node/actions.rb @@ -153,12 +153,11 @@ module Capybara # @param [String] path The path of the file that will be attached, or an array of paths # def attach_file(locator, path) - path = [path] if String === path - path.each do |p| + (String === path ? [path] : path).each do |p| raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s) end msg = "cannot attach file, no file field with id, name, or label '#{locator}' found" - find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path.to_yaml) + find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path) end end end diff --git a/lib/capybara/rack_test/form.rb b/lib/capybara/rack_test/form.rb index 765cc7ef..ecd02f6f 100644 --- a/lib/capybara/rack_test/form.rb +++ b/lib/capybara/rack_test/form.rb @@ -26,30 +26,17 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node # TO DO identify the click button here (in document order, rather # than leaving until the end of the params) elsif field['type'] =='file' - value = field['value'] - path_names = value.to_s.empty? ? [] : YAML::load(value.to_s) if multipart? - files = \ - if path_names.empty? - [NilUploadedFile.new] + file = \ + if (value = field['value']).to_s.empty? + NilUploadedFile.new else - if field['multiple'] - path_names.map do |path_name| - content_type = MIME::Types.type_for(path_name).first.to_s - Rack::Test::UploadedFile.new(path_name, content_type) - end - else - content_type = MIME::Types.type_for(path_names.last).first.to_s - [Rack::Test::UploadedFile.new(path_names.last, content_type)] - end + content_type = MIME::Types.type_for(value).first.to_s + Rack::Test::UploadedFile.new(value, content_type) end - files.each do |file| - merge_param!(params, field['name'].to_s, file) - end + merge_param!(params, field['name'].to_s, file) else - path_names.each do |path_name| - merge_param!(params, field['name'].to_s, File.basename(path_name)) - end + merge_param!(params, field['name'].to_s, File.basename(field['value'].to_s)) end else merge_param!(params, field['name'].to_s, field['value'].to_s) diff --git a/lib/capybara/rack_test/node.rb b/lib/capybara/rack_test/node.rb index 9f71334a..10e02dac 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 f7629deb..c87d2c09 100644 --- a/lib/capybara/selenium/node.rb +++ b/lib/capybara/selenium/node.rb @@ -18,12 +18,15 @@ 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' - path_names = value.to_s.empty? ? [] : YAML::load(value.to_s) + path_names = value.to_s.empty? ? [] : value resynchronize do native.send_keys(*path_names) end