module Watir class Select < HTMLElement include Watir::Exception # # Clears all selected options. # def clear raise Error, "you can only clear multi-selects" unless multiple? options.each do |o| click_option(o) if o.selected? end end # # Gets all the options in the select list # # @return [Watir::OptionCollection] # def options(*) element_call(:wait_for_exists) { super } end # # 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] # def include?(str_or_rx) element_call do @element.find_elements(:tag_name, 'option').any? do |e| str_or_rx === e.text || str_or_rx === e.attribute(:label) end end end # # Select the option(s) whose text or label matches the given string. # If this is a multi-select and several options match the value given, all will be selected. # # @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. # def select(str_or_rx) select_by :text, str_or_rx end # # 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 # def select_value(str_or_rx) select_by :value, str_or_rx end # # 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] # def selected?(str_or_rx) match_found = false element_call do @element.find_elements(:tag_name, 'option').each do |e| matched = str_or_rx === e.text || str_or_rx === e.attribute(:label) if matched return true if e.selected? match_found = true end end end raise(UnknownObjectException, "Unable to locate option matching #{str_or_rx.inspect}") unless match_found false end # # Returns the value of the first selected option in the select list. # Returns nil if no option is selected. # # @return [String, nil] # def value option = selected_options.first option && option.value end # # Returns the text of the first selected option in the select list. # Returns nil if no option is selected. # # @return [String, nil] # def text option = selected_options.first option && option.text end # Returns an array of currently selected options. # # @return [Array] # def selected_options element_call do script = <<-SCRIPT var result = []; var options = arguments[0].options; for (var i = 0; i < options.length; i++) { var option = options[i]; if (option.selected) { result.push(option) } } return result; SCRIPT @query_scope.execute_script(script, self) end end private def select_by(how, str_or_rx) found = nil begin Wait.until do case str_or_rx when String, Numeric, Regexp found = options(how => str_or_rx) found = options(label: str_or_rx) if found.to_a.empty? else raise TypeError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}" end !found.to_a.empty? end rescue Wait::TimeoutError no_value_found(str_or_rx) end select_matching(found) end def select_matching(elements) elements = [elements.first] unless multiple? elements.each { |e| click_option(e) unless e.selected? } elements.first.exist? ? elements.first.text : '' end def matches_regexp?(how, element, exp) case how when :text element.text =~ exp || element.label =~ exp when :value element.value =~ exp else raise Error, "unknown how: #{how.inspect}" end end def click_option(element) element = Option.new(self, element: element) unless element.is_a?(Option) element.click end def no_value_found(arg, msg = nil) raise NoValueFoundException, msg || "#{arg.inspect} not found in select list" end end # Select module Container alias_method :select_list, :select alias_method :select_lists, :selects Watir.tag_to_class[:select_list] = Select end # Container end # Watir