From 4d6773811e1eb461c0b8e114b7f0c0d05ef5e08a Mon Sep 17 00:00:00 2001 From: Thomas Walpole Date: Fri, 30 Dec 2016 12:33:57 -0800 Subject: [PATCH] Add an option for attach_file to allow modifying the elements style since they are so often hidden on the page --- lib/capybara/node/actions.rb | 22 +++++++++++++++++++ lib/capybara/spec/session/attach_file_spec.rb | 8 +++++++ .../spec/session/evaluate_script_spec.rb | 4 ++-- .../spec/session/execute_script_spec.rb | 4 ++-- lib/capybara/spec/views/with_js.erb | 5 +++++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/capybara/node/actions.rb b/lib/capybara/node/actions.rb index afbcbfe3..610741be 100644 --- a/lib/capybara/node/actions.rb +++ b/lib/capybara/node/actions.rb @@ -230,6 +230,7 @@ module Capybara # @option options [String] id Match fields that match the id attribute # @option options [String] name Match fields that match the name attribute # @option options [String, Array] :class Match links that match the class(es) provided + # @option options [Hash] style A Hash of CSS styles to change before attempting to attach the file # # @return [Capybara::Node::Element] The file field element def attach_file(locator, path, options={}) @@ -237,10 +238,31 @@ module Capybara Array(path).each do |p| raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s) end + # Allow user to update the CSS style of the file input since they are so often hidden on a page + if style = options.delete(:style) + ff = find(:file_field, locator, options.merge({visible: :all})) + _update_style(ff, style) + end find(:file_field, locator, options).set(path) end private + def _update_style(element, style) + script = <<-JS + var el = arguments[0]; + var css = arguments[1]; + for (var prop in css){ + if (css.hasOwnProperty(prop)) { + el.style[prop] = css[prop] + } + } + JS + begin + session.execute_script(script, element, style) + rescue Capybara::NotSupportedByDriverError + warn "The :style option is not supported by the current driver - ignoring" + end + end def _check_with_label(selector, checked, locator, options) locator, options = nil, locator if locator.is_a? Hash diff --git a/lib/capybara/spec/session/attach_file_spec.rb b/lib/capybara/spec/session/attach_file_spec.rb index 7e69b6c8..3a0df5a5 100644 --- a/lib/capybara/spec/session/attach_file_spec.rb +++ b/lib/capybara/spec/session/attach_file_spec.rb @@ -107,4 +107,12 @@ Capybara::SpecHelper.spec "#attach_file" do end.to raise_error(Capybara::ElementNotFound) end end + + context "with :style option", requires: [:js, :es_args] do + it "can change the CSS style of the file input field" do + @session.visit('/with_js') + expect { @session.attach_file("hidden_file", __FILE__) }.to raise_error Capybara::ElementNotFound + @session.attach_file("hidden_file", __FILE__, style: { opacity: 1, display: 'block' }) + end + end end diff --git a/lib/capybara/spec/session/evaluate_script_spec.rb b/lib/capybara/spec/session/evaluate_script_spec.rb index 296bf7d3..fdf4be60 100644 --- a/lib/capybara/spec/session/evaluate_script_spec.rb +++ b/lib/capybara/spec/session/evaluate_script_spec.rb @@ -5,13 +5,13 @@ Capybara::SpecHelper.spec "#evaluate_script", requires: [:js] do expect(@session.evaluate_script("1+3")).to eq(4) end - it "should pass arguments to the script" do + it "should pass arguments to the script", requires: [:js, :es_args] do @session.visit('/with_js') @session.evaluate_script("document.getElementById('change').textContent = arguments[0]", "Doodle Funk") expect(@session).to have_css('#change', text: 'Doodle Funk') end - it "should support passing elements as arguments to the script" do + it "should support passing elements as arguments to the script", requires: [:js, :es_args] do @session.visit('/with_js') el = @session.find(:css, '#change') @session.evaluate_script("arguments[0].textContent = arguments[1]", el, "Doodle Funk") diff --git a/lib/capybara/spec/session/execute_script_spec.rb b/lib/capybara/spec/session/execute_script_spec.rb index dd4a0aa6..9f0491e8 100644 --- a/lib/capybara/spec/session/execute_script_spec.rb +++ b/lib/capybara/spec/session/execute_script_spec.rb @@ -11,13 +11,13 @@ Capybara::SpecHelper.spec "#execute_script", requires: [:js] do expect{ @session.execute_script("$('#change').text('Funky Doodle')") }.not_to raise_error end - it "should pass arguments to the script" do + it "should pass arguments to the script", requires: [:js, :es_args] do @session.visit('/with_js') @session.execute_script("document.getElementById('change').textContent = arguments[0]", "Doodle Funk") expect(@session).to have_css('#change', text: 'Doodle Funk') end - it "should support passing elements as arguments to the script" do + it "should support passing elements as arguments to the script", requires: [:js, :es_args] do @session.visit('/with_js') el = @session.find(:css, '#change') @session.execute_script("arguments[1].textContent = arguments[0]", "Doodle Funk", el) diff --git a/lib/capybara/spec/views/with_js.erb b/lib/capybara/spec/views/with_js.erb index 779a6b36..5f50d17a 100644 --- a/lib/capybara/spec/views/with_js.erb +++ b/lib/capybara/spec/views/with_js.erb @@ -110,6 +110,11 @@

+ +

+ +

+