lib/capybara/node/actions.rb in capybara-2.18.0 vs lib/capybara/node/actions.rb in capybara-3.0.0.rc1

- old
+ new

@@ -1,10 +1,10 @@ # frozen_string_literal: true + module Capybara module Node module Actions - ## # # Finds a button or link and clicks it. See {Capybara::Node::Actions#click_button} and # {Capybara::Node::Actions#click_link} for what locator will match against for each type of element # @!macro waiting_behavior @@ -18,12 +18,11 @@ # # @param [String] locator See {Capybara::Node::Actions#click_button} and {Capybara::Node::Actions#click_link} # # @return [Capybara::Node::Element] The element clicked # - def click_link_or_button(locator=nil, options={}) - locator, options = nil, locator if locator.is_a? Hash + def click_link_or_button(locator = nil, **options) find(:link_or_button, locator, options).click end alias_method :click_on, :click_link_or_button ## @@ -36,12 +35,11 @@ # @overload click_link([locator], options) # @param [String] locator text, id, title or nested image's alt attribute # @param options See {Capybara::Node::Finders#find_link} # # @return [Capybara::Node::Element] The element clicked - def click_link(locator=nil, options={}) - locator, options = nil, locator if locator.is_a? Hash + def click_link(locator = nil, **options) find(:link, locator, options).click end ## # @@ -54,12 +52,11 @@ # # @overload click_button([locator], options) # @param [String] locator Which button to find # @param options See {Capybara::Node::Finders#find_button} # @return [Capybara::Node::Element] The element clicked - def click_button(locator=nil, options={}) - locator, options = nil, locator if locator.is_a? Hash + def click_button(locator = nil, **options) find(:button, locator, options).click end ## # @@ -81,16 +78,12 @@ # @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 fields that match the class(es) provided # # @return [Capybara::Node::Element] The element filled_in - 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) + def fill_in(locator = nil, with:, fill_options: {}, **options) + options[:with] = options.delete(:currently_with) if options.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. @@ -111,12 +104,12 @@ # @option options [String, Array<String>] :class Match fields that match the class(es) provided # @macro waiting_behavior # @macro label_click # # @return [Capybara::Node::Element] The element chosen or the label clicked - def choose(locator, options={}) - _check_with_label(:radio_button, true, locator, options) + def choose(locator = nil, **options) + _check_with_label(:radio_button, true, locator, **options) end ## # # Find a check box and mark it as checked. The check box can be found @@ -134,12 +127,12 @@ # @option options [String, Array<String>] :class Match fields that match the class(es) provided # @macro label_click # @macro waiting_behavior # # @return [Capybara::Node::Element] The element checked or the label clicked - def check(locator, options={}) - _check_with_label(:checkbox, true, locator, options) + def check(locator, **options) + _check_with_label(:checkbox, true, locator, **options) end ## # # Find a check box and mark uncheck it. The check box can be found @@ -157,12 +150,12 @@ # @option options [String, Array<String>] :class Match fields that match the class(es) provided # @macro label_click # @macro waiting_behavior # # @return [Capybara::Node::Element] The element unchecked or the label clicked - def uncheck(locator, options={}) - _check_with_label(:checkbox, false, locator, options) + def uncheck(locator = nil, **options) + _check_with_label(:checkbox, false, locator, **options) end ## # # If `:from` option is present, `select` finds a select box on the page @@ -178,17 +171,13 @@ # # @param [String] value Which option to select # @option options [String] :from The id, name or label of the select box # # @return [Capybara::Node::Element] The option element selected - def select(value, options={}) - if options.has_key?(:from) - from = options.delete(:from) - find(:select, from, options).find(:option, value, options).select_option - else - find(:option, value, options).select_option - end + def select(value = nil, from: nil, **options) + scope = from ? find(:select, from, options) : self + scope.find(:option, value, options).select_option end ## # # Find a select box on the page and unselect a particular option from it. If the select @@ -201,17 +190,13 @@ # # @param [String] value Which option to unselect # @param [Hash{:from => String}] options The id, name or label of the select box # # @return [Capybara::Node::Element] The option element unselected - def unselect(value, options={}) - if options.has_key?(:from) - from = options.delete(:from) - find(:select, from, options).find(:option, value, options).unselect_option - else - find(:option, value, options).unselect_option - end + def unselect(value = nil, from: nil, **options) + scope = from ? find(:select, from, options) : self + scope.find(:option, value, options).unselect_option end ## # # Find a file field on the page and attach a file given its path. The file field can @@ -231,87 +216,80 @@ # @option options [String] name Match fields that match the name attribute # @option options [String, Array<String>] :class Match fields 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 + def attach_file(locator = nil, path, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments 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(: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 + if make_visible + ff = find(:file_field, locator, options.merge(visible: :all)) + while_visible(ff, make_visible) { |el| el.set(path) } 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 + + def while_visible(element, visible_css) + visible_css = { opacity: 1, display: 'block', visibility: 'visible' } if visible_css == true + _update_style(element, visible_css) + raise ExpectationNotMet, "The style changes in :make_visible did not make the file input visible" unless element.visible? begin - session.execute_script(script, element, style) - rescue Capybara::NotSupportedByDriverError - warn "The :make_visible option is not supported by the current driver - ignoring" + yield element + ensure + _reset_style(element) end end + def _update_style(element, style) + session.execute_script(UPDATE_STYLE_SCRIPT, element, style) + rescue Capybara::NotSupportedByDriverError + warn "The :make_visible option is not supported by the current driver - ignoring" + 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 + session.execute_script(RESET_STYLE_SCRIPT, element) + rescue # swallow extra errors 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) { session_options.automatic_label_click } - + def _check_with_label(selector, checked, locator, allow_label_click: session_options.automatic_label_click, **options) synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do begin el = find(selector, locator, options) el.set(checked) rescue => e raise unless allow_label_click && catch_error?(e) begin el ||= find(selector, locator, options.merge(visible: :all)) - label = find(:label, for: el, visible: true) - label.click unless (el.checked? == checked) - rescue + find(:label, for: el, visible: true).click unless el.checked? == checked + rescue # swallow extra errors - raise original raise e end end end end + UPDATE_STYLE_SCRIPT = <<-'JS'.freeze + 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 + + RESET_STYLE_SCRIPT = <<-'JS'.freeze + var el = arguments[0]; + if (el.hasOwnProperty('capybara_style_cache')) { + el.style.cssText = el.capybara_style_cache; + delete el.capybara_style_cache; + } + JS end end end