lib/capybara/node/actions.rb in capybara-2.11.0 vs lib/capybara/node/actions.rb in capybara-2.12.0

- old
+ new

@@ -73,10 +73,11 @@ # @param [String] locator Which field to fill in # @param [Hash] options # @macro waiting_behavior # @option options [String] :with The value to fill in - required # @option options [Hash] :fill_options Driver specific options regarding how to fill fields + # @option options [String] :currently_with The current value property of the field to fill in # @option options [Boolean] :multiple Match fields that can have multiple values? # @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] :placeholder Match fields that match the placeholder attribute # @option options [String, Array<String>] :class Match links that match the class(es) provided @@ -85,10 +86,11 @@ def fill_in(locator, options={}) locator, options = nil, locator if locator.is_a? Hash raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with) with = options.delete(:with) fill_options = options.delete(:fill_options) + options[:with] = options.delete(:currently_with) if options.has_key?(:currently_with) find(:fillable_field, locator, options).set(with, fill_options) end # @!macro label_click # @option options [Boolean] :allow_label_click (Capybara.automatic_label_click) Attempt to click the label to toggle state if element is non-visible. @@ -226,20 +228,69 @@ # @option options [Boolean] exact (Capybara.exact) Match the exact label name/contents or accept a partial match. # @option options [Boolean] multiple Match field which allows multiple file selection # @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<String>] :class Match links that match the class(es) provided + # @option options [true, Hash] make_visible A Hash of CSS styles to change before attempting to attach the file, if `true` { opacity: 1, display: 'block', visibility: 'visible' } is used (may not be supported by all drivers) # # @return [Capybara::Node::Element] The file field element def attach_file(locator, path, options={}) locator, path, options = nil, locator, path if path.is_a? Hash Array(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, options).set(path) + # Allow user to update the CSS style of the file input since they are so often hidden on a page + if style = options.delete(:make_visible) + style = { opacity: 1, display: 'block', visibility: 'visible' } if style == true + ff = find(:file_field, locator, options.merge({visible: :all})) + _update_style(ff, style) + if ff.visible? + begin + ff.set(path) + ensure + _reset_style(ff) + end + else + raise ExpectationNotMet, "The style changes in :make_visible did not make the file input visible" + end + else + find(:file_field, locator, options).set(path) + end end private + def _update_style(element, style) + script = <<-JS + var el = arguments[0]; + el.capybara_style_cache = el.style.cssText; + 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 :make_visible option is not supported by the current driver - ignoring" + end + end + + def _reset_style(element) + script = <<-JS + var el = arguments[0]; + if (el.hasOwnProperty('capybara_style_cache')) { + el.style.cssText = el.capybara_style_cache; + delete el.capybara_style_cache; + } + JS + begin + session.execute_script(script, element) + rescue + end + end + def _check_with_label(selector, checked, locator, options) locator, options = nil, locator if locator.is_a? Hash allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }