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 @@