module Capybara::Node::Actions

def _check_with_label(selector, checked, locator,

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
    el = find(selector, locator, **options)
    el.set(checked)
  rescue StandardError => e
    raise unless allow_label_click && catch_error?(e)
    begin
      el ||= find(selector, locator, **options.merge(visible: :all))
      unless el.checked? == checked
        el.session
          .find(:label, for: el, visible: true, match: :first)
          .click(**(Hash.try_convert(allow_label_click) || {}))
      end
    rescue StandardError # swallow extra errors - raise original
      raise e
    end
  end
end

def _reset_style(element)

def _reset_style(element)
  element.execute_script(RESET_STYLE_SCRIPT)
rescue StandardError # rubocop:disable Lint/SuppressedException 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

Other tags:
    Yield: - Block whose actions will trigger the system file chooser to be shown

Parameters:
  • paths (String, Array) -- The path(s) of the file(s) that will be attached
  • 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(paths, &blk)
  • attach_file([locator], paths, **options)

Options Hash: (**options)
  • make_visible (true, Hash) --
  • class (String, Array, Regexp) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String, Regexp) -- Match fields that match the id attribute
  • multiple (Boolean) -- Match field which allows multiple file selection
  • exact (Boolean) --
  • match (Symbol) --
def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
  if locator && block_given?
    raise ArgumentError, '`#attach_file` does not support passing both a locator and a block'
  end
  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?
  if block_given?
    begin
      execute_script CAPTURE_FILE_ELEMENT_SCRIPT
      yield
      file_field = evaluate_script 'window._capybara_clicked_file_input'
      raise ArgumentError, "Capybara was unable to determine the file input you're attaching to" unless file_field
    rescue ::Capybara::NotSupportedByDriverError
      warn 'Block mode of `#attach_file` is not supported by the current driver - ignoring.'
    end
  end
  # Allow user to update the CSS style of the file input since they are so often hidden on a page
  if make_visible
    ff = file_field || find(:file_field, locator, **options.merge(visible: :all))
    while_visible(ff, make_visible) { |el| el.set(paths) }
  else
    (file_field || 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, Regexp) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String, Regexp) -- 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, Regexp) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String, Regexp) -- 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 (Hash) -- 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 (Hash) -- See {Capybara::Node::Finders#find_link}
  • locator (String) -- text, id, {Capybara.configure 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 {#click_button} and {#click_link}

Overloads:
  • click_link_or_button([locator], **options)
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.configure default_set_options})
  • class (String, Array, Regexp) -- 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, Regexp) -- 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
    find(:select, from, **options)
  rescue Capybara::ElementNotFound => select_error # rubocop:disable Naming/RescuedExceptionsVariableName
    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

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

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

Parameters:
  • from (String) -- The id, {Capybara.configure test_id} attribute, name or label of the select box
  • value (String) -- Which option to select

Overloads:
  • select(value = nil, from: nil, **options)
def select(value = nil, from: nil, **options)
  raise ArgumentError, 'The :from option does not take an element' if from.is_a? Capybara::Node::Element
  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, Regexp) -- Match fields that match the class(es) provided
  • name (String) -- Match fields that match the name attribute
  • id (String, Regexp) -- 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.configure test_id} attribute, name or label of the select box
  • value (String) -- Which option to unselect

Overloads:
  • unselect(value = nil, from: nil, **options)
def unselect(value = nil, from: nil, **options)
  raise ArgumentError, 'The :from option does not take an element' if from.is_a? Capybara::Node::Element
  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)
  if visible_css == true
    visible_css = { opacity: 1, display: 'block', visibility: 'visible', width: 'auto', height: 'auto' }
  end
  _update_style(element, visible_css)
  unless element.visible?
    raise ExpectationNotMet, 'The style changes in :make_visible did not make the file input visible'
  end
  begin
    yield element
  ensure
    _reset_style(element)
  end
end