class Watir::Select

Public Instance Methods

clear() click to toggle source

Clears all selected options.

# File lib/watir/elements/select.rb, line 7
def clear
  raise Exception::Error, 'you can only clear multi-selects' unless multiple?

  selected_options.each(&:click)
end
include?(str_or_rx) click to toggle source

Returns true if the select list has one or more options where text or label matches the given value.

@param [String, Regexp] str_or_rx @return [Boolean]

# File lib/watir/elements/select.rb, line 20
def include?(str_or_rx)
  option(text: str_or_rx).exist? || option(label: str_or_rx).exist?
end
select(*str_or_rx) click to toggle source

Select the option whose text or label matches the given string.

@param [String, Regexp] str_or_rx @raise [Watir::Exception::NoValueFoundException] if the value does not exist. @return [String] The text of the option selected. If multiple options match, returns the first match.

# File lib/watir/elements/select.rb, line 32
def select(*str_or_rx)
  if str_or_rx.size > 1 || str_or_rx.first.is_a?(Array)
    str_or_rx.flatten.map { |v| select_all_by v }.first
  else
    str_or_rx.flatten.map { |v| select_by v }.first
  end
end
select!(*str_or_rx) click to toggle source

Uses JavaScript to select the option whose text matches the given string.

@param [String, Regexp] str_or_rx @raise [Watir::Exception::NoValueFoundException] if the value does not exist.

# File lib/watir/elements/select.rb, line 64
def select!(*str_or_rx)
  if str_or_rx.size > 1 || str_or_rx.first.is_a?(Array)
    str_or_rx.flatten.map { |v| select_by! v, :multiple }.first
  else
    str_or_rx.flatten.map { |v| select_by! v, :single }.first
  end
end
select_all(*str_or_rx) click to toggle source

Select all options whose text or label matches the given string.

@param [String, Regexp] str_or_rx @raise [Watir::Exception::NoValueFoundException] if the value does not exist. @return [String] The text of the first option selected.

# File lib/watir/elements/select.rb, line 48
def select_all(*str_or_rx)
  Watir.logger.deprecate('#select_all',
                         '#select with an Array instance',
                         ids: [:select_all])

  results = str_or_rx.flatten.map { |v| select_all_by v }
  results.first
end
select_all!(*str_or_rx) click to toggle source

Uses JavaScript to select all options whose text matches the given string.

@param [String, Regexp] str_or_rx @raise [Watir::Exception::NoValueFoundException] if the value does not exist.

# File lib/watir/elements/select.rb, line 79
def select_all!(*str_or_rx)
  Watir.logger.deprecate('#select_all!',
                         '#select! with an Array instance',
                         ids: [:select_all])

  results = str_or_rx.flatten.map { |v| select_by!(v, :multiple) }
  results.first
end
select_value(str_or_rx) click to toggle source

Selects the option(s) whose value attribute matches the given string.

@see select

@param [String, Regexp] str_or_rx @raise [Watir::Exception::NoValueFoundException] if the value does not exist. @return [String] The option selected. If multiple options match, returns the first match

# File lib/watir/elements/select.rb, line 98
def select_value(str_or_rx)
  Watir.logger.deprecate '#select_value', '#select', ids: [:select_value]
  select_by str_or_rx
end
selected?(str_or_rx) click to toggle source

Returns true if any of the selected options' text or label matches the given value.

@param [String, Regexp] str_or_rx @raise [Watir::Exception::UnknownObjectException] if the options do not exist @return [Boolean]

# File lib/watir/elements/select.rb, line 111
def selected?(str_or_rx)
  by_text = options(text: str_or_rx)
  return true if by_text.find(&:selected?)

  by_label = options(label: str_or_rx)
  return true if by_label.find(&:selected?)

  return false unless (by_text.size + by_label.size).zero?

  raise(UnknownObjectException, "Unable to locate option matching #{str_or_rx.inspect}")
end
selected_options() click to toggle source

Returns an array of currently selected options.

@return [Array<Watir::Option>]

# File lib/watir/elements/select.rb, line 152
def selected_options
  element_call { execute_js :selectedOptions, self }
end
text() click to toggle source

Returns the text of the first selected option in the select list. Returns nil if no option is selected.

@return [String, nil]

# File lib/watir/elements/select.rb, line 142
def text
  option = selected_options.first
  option&.text
end
value() click to toggle source

Returns the value of the first selected option in the select list. Returns nil if no option is selected.

@return [String, nil]

# File lib/watir/elements/select.rb, line 130
def value
  option = selected_options.first
  option&.value
end

Private Instance Methods

find_options(how, str_or_rx) click to toggle source
# File lib/watir/elements/select.rb, line 216
def find_options(how, str_or_rx)
  wait_while do
    case str_or_rx
    when String, Numeric, Regexp
      @found = how == :value ? options(value: str_or_rx) : []
      @found = options(text: str_or_rx) if @found.empty?
      @found = options(label: str_or_rx) if @found.empty?
      @found.empty? && Watir.relaxed_locate?
    else
      raise TypeError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
    end
  end
  # TODO: Remove conditional when remove relaxed_locate toggle
  return @found unless @found.empty?

  raise_no_value_found(str_or_rx)
rescue Wait::TimeoutError
  raise_no_value_found(str_or_rx)
end
matching_option?(how, what) click to toggle source
# File lib/watir/elements/select.rb, line 197
def matching_option?(how, what)
  selected_options.each do |opt|
    value = opt.send(how)
    next unless what.is_a?(String) ? value == what : value =~ what
    return true if opt.enabled?

    raise ObjectDisabledException, "option matching #{what} by #{how} on #{inspect} is disabled"
  end
  false
end
process_str_or_rx(str_or_rx) click to toggle source
# File lib/watir/elements/select.rb, line 180
def process_str_or_rx(str_or_rx)
  case str_or_rx
  when String
    "^#{str_or_rx}$"
  when Regexp
    str_or_rx.inspect.sub('\\A', '^')
             .sub('\\Z', '$')
             .sub('\\z', '$')
             .sub(%r{^/}, '')
             .sub(%r{/[a-z]*$}, '')
             .gsub(/\(\?#.+\)/, '')
             .gsub(/\(\?-\w+:/, '(')
  else
    raise TypeError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
  end
end
raise_no_value_found(str_or_rx) click to toggle source

TODO: Consider locating the Select List before throwing the exception

# File lib/watir/elements/select.rb, line 237
def raise_no_value_found(str_or_rx)
  raise NoValueFoundException, "#{str_or_rx.inspect} not found in #{inspect}"
end
select_all_by(str_or_rx) click to toggle source
# File lib/watir/elements/select.rb, line 208
def select_all_by(str_or_rx)
  raise Error, 'you can only use #select_all on multi-selects' unless multiple?

  found = find_options :text, str_or_rx

  select_matching(found)
end
select_by(str_or_rx) click to toggle source
# File lib/watir/elements/select.rb, line 158
def select_by(str_or_rx)
  found = find_options(:value, str_or_rx)

  if found.size > 1
    Watir.logger.deprecate 'Selecting multiple options with #select using a String or Regexp value',
                           '#select with the desired values in an Array instance',
                           ids: [:select_by]
  end
  select_matching(found)
end
select_by!(str_or_rx, number) click to toggle source
# File lib/watir/elements/select.rb, line 169
def select_by!(str_or_rx, number)
  js_rx = process_str_or_rx(str_or_rx)

  %w[Text Label Value].each do |approach|
    element_call { execute_js("selectOptions#{approach}", self, js_rx, number.to_s) }
    return selected_options.first.text if matching_option?(approach.downcase, str_or_rx)
  end

  raise_no_value_found(str_or_rx)
end
select_matching(elements) click to toggle source
# File lib/watir/elements/select.rb, line 241
def select_matching(elements)
  elements = [elements.first] unless multiple?
  elements.each { |e| e.click unless e.selected? }
  # TODO: this can go back to #exist? after `:stale_exists` deprecation removed
  elements.first.stale? ? '' : elements.first.text
end