module Capybara::Node::Actions

def _check_with_label(selector, checked, locator, allow_label_click: session_options.automatic_label_click, **options)

def _check_with_label(selector, checked, locator, allow_label_click: session_options.automatic_label_click, **options)
  options[:allow_self] = true if locator.nil?
  synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
    begin
      el = find(selector, locator, options)
      el.set(checked)
    rescue StandardError => err
      raise unless allow_label_click && catch_error?(err)
      begin
        el ||= find(selector, locator, options.merge(visible: :all))
        el.session.find(:label, for: el, visible: true).click unless el.checked? == checked
      rescue StandardError # swallow extra errors - raise original
        raise err
      end
    end
  end
end

def _reset_style(element)

def _reset_style(element)
  element.execute_script(RESET_STYLE_SCRIPT)
rescue StandardError # rubocop:disable Lint/HandleExceptions swallow extra errors
end

def _update_style(element, style)

def _update_style(element, style)
  element.execute_script(UPDATE_STYLE_SCRIPT, style)
rescue Capybara::NotSupportedByDriverError
  warn 'The :make_visible option is not supported by the current driver - ignoring'
end

def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments

Returns:
  • (Capybara::Node::Element) - The file field element

Options Hash: (**options)
  • make_visible (true, Hash) -- 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)
  • class (String, Array) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String) -- Match fields that match the id attribute
  • multiple (Boolean) -- Match field which allows multiple file selection
  • exact (Boolean) -- Match the exact label name/contents or accept a partial match.
  • match (Symbol) -- The matching strategy to use (:one, :first, :prefer_exact, :smart).

Parameters:
  • paths (String, Array) -- The path(s) of the file(s) that will be attached
  • locator (String) -- Which field to attach the file to

Overloads:
  • attach_file([locator], paths, **options)
def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
  Array(paths).each do |path|
    raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
  end
  options[:allow_self] = true if locator.nil?
  # Allow user to update the CSS style of the file input since they are so often hidden on a page
  if make_visible
    ff = find(:file_field, locator, options.merge(visible: :all))
    while_visible(ff, make_visible) { |el| el.set(paths) }
  else
    find(:file_field, locator, options).set(paths)
  end
end

def check(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element checked or the label clicked

Options Hash: (**options)
  • class (String, Array) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String) -- Match fields that match the id attribute
  • option (String) -- Value of the checkbox to select

Parameters:
  • locator (String) -- Which check box to check

Overloads:
  • check([locator], **options)
def check(locator = nil, **options)
  _check_with_label(:checkbox, true, locator, options)
end

def choose(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element chosen or the label clicked

Options Hash: (**options)
  • class (String, Array) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String) -- Match fields that match the id attribute
  • option (String) -- Value of the radio_button to choose

Parameters:
  • locator (String) -- Which radio button to choose

Overloads:
  • choose([locator], **options)
def choose(locator = nil, **options)
  _check_with_label(:radio_button, true, locator, options)
end

def click_button(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element clicked

Parameters:
  • options () -- See {Capybara::Node::Finders#find_button}
  • locator (String) -- Which button to find

Overloads:
  • click_button([locator], **options)
def click_button(locator = nil, **options)
  find(:button, locator, options).click
end

def click_link(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element clicked

Parameters:
  • options () -- See {Capybara::Node::Finders#find_link}
  • locator (String) -- text, id, Capybara.test_id attribute, title or nested image's alt attribute

Overloads:
  • click_link([locator], options)
def click_link(locator = nil, **options)
  find(:link, locator, options).click
end

def click_link_or_button(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element clicked

Parameters:
  • locator (String) -- See {Capybara::Node::Actions#click_button} and {Capybara::Node::Actions#click_link}

Overloads:
  • click_link_or_button([locator], options)

Options Hash: (**options)
  • wait (false, Numeric) -- Maximum time to wait for matching element to appear.
def click_link_or_button(locator = nil, **options)
  find(:link_or_button, locator, options).click
end

def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)

Returns:
  • (Capybara::Node::Element) - The element filled_in

Options Hash: (**options)
  • fill_options (Hash) -- Driver specific options regarding how to fill fields (Defaults come from Capybara.default_set_options)
  • class (String, Array) -- Match fields that match the class(es) provided
  • placeholder (String) -- Match fields that match the placeholder attribute
  • name (String) -- Match fields that match the name attribute
  • id (String) -- Match fields that match the id attribute
  • multiple (Boolean) -- Match fields that can have multiple values?
  • currently_with (String) -- The current value property of the field to fill in

Parameters:
  • with: (String) -- The value to fill_in
  • options (Hash) --
  • locator (String) -- Which field to fill in

Overloads:
  • fill_in([locator], with:, **options)
def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
  find_options[:with] = currently_with if currently_with
  find_options[:allow_self] = true if locator.nil?
  find(:fillable_field, locator, find_options).set(with, fill_options)
end

def find_select_or_datalist_input(from, options)

def find_select_or_datalist_input(from, options)
  synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
    begin
      find(:select, from, options)
    rescue Capybara::ElementNotFound => select_error
      raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }
      begin
        find(:datalist_input, from, options)
      rescue Capybara::ElementNotFound => dlinput_error
        raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
      end
    end
  end
end

def select(value = nil, from: nil, **options)

Returns:
  • (Capybara::Node::Element) - The option element selected

Parameters:
  • from (String) -- The id, Capybara.test_id atrtribute, name or label of the select box
  • value (String) -- Which option to select
def select(value = nil, from: nil, **options)
  el = from ? find_select_or_datalist_input(from, options) : self
  if el.respond_to?(:tag_name) && (el.tag_name == 'input')
    select_datalist_option(el, value)
  else
    el.find(:option, value, options).select_option
  end
end

def select_datalist_option(input, value)

def select_datalist_option(input, value)
  datalist_options = input.evaluate_script(DATALIST_OPTIONS_SCRIPT)
  option = datalist_options.find { |opt| opt.values_at('value', 'label').include?(value) }
  raise ::Capybara::ElementNotFound, %(Unable to find datalist option "#{value}") unless option
  input.set(option['value'])
rescue ::Capybara::NotSupportedByDriverError
  # Implement for drivers that don't support JS
  datalist = find(:xpath, XPath.descendant(:datalist)[XPath.attr(:id) == input[:list]], visible: false)
  option = datalist.find(:datalist_option, value, disabled: false)
  input.set(option.value)
end

def uncheck(locator = nil, **options)

Returns:
  • (Capybara::Node::Element) - The element unchecked or the label clicked

Options Hash: (**options)
  • class (String, Array) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String) -- Match fields that match the id attribute
  • option (String) -- Value of the checkbox to deselect

Parameters:
  • locator (String) -- Which check box to uncheck

Overloads:
  • uncheck([locator], **options)
def uncheck(locator = nil, **options)
  _check_with_label(:checkbox, false, locator, options)
end

def unselect(value = nil, from: nil, **options)

Returns:
  • (Capybara::Node::Element) - The option element unselected

Parameters:
  • from (String) -- The id, Capybara.test_id attribute, name or label of the select box
  • value (String) -- Which option to unselect
def unselect(value = nil, from: nil, **options)
  scope = from ? find(:select, from, options) : self
  scope.find(:option, value, options).unselect_option
end

def while_visible(element, visible_css)

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
    yield element
  ensure
    _reset_style(element)
  end
end