如何为select定义自定义策略

时间:2015-06-24 14:02:23

标签: ruby gwt watir page-object-gem

我正在寻找一种正确的方法来重新定义/扩展Gwt app中select标签的定位策略。 从html代码段中,您可以看到select标记不可见。 因此,要从列表中选择选项,我需要点击button代码,然后从下拉列表中选择所需的li代码。

<div class="form-group">
  <select class="bootstrap-select form-control" style="display: none; locator='gender">
    <div class="btn-group">
    <button class="dropdown-toggle" type="button" title="Male">
      <div class="dropdown-menu open">
        <ul class="dropdown-menu inner selectpicker" role="menu">
          <li data-original-index="1"> (contains a>span with option text)
            .....more options
      </ul>
    </div>
  </div>
</div>

我看到脏解决方案:在BasePage类中实现方法。这种方法很好的page_object糖(选项,获取值等):

def set_nationality(country, nationality='Nationality')
  select = button_element(xpath: "//button[@title='#{nationality}']")
  select.click
  option = span_element(xpath: "//span[.='#{country}']")
  option.when_visible
  option.click
end

还有其他更明确的方法吗?使用`PageObject :: Widgets可能?

UPD:这是我期望得到的:

def bool_list(name, identifier={:index => 0}, &block)
  define_method("#{name}_btn_element") do
    platform.send('button_for', identifier.clone + "//button")
  end
  define_method("#{name}?") do
    platform.send('button_for', identifier.clone + "//button").exists?
  end
  define_method(name) do
    return platform.select_list_value_for identifier.clone + '/select' unless block_given?
    self.send("#{name}_element").value
  end
  define_method("#{name}=") do |value|
    return platform.select_list_value_set(identifier.clone + '/select', value) unless block_given?
    self.send("#{name}_element").select(value)
  end
  define_method("#{name}_options") do
    element = self.send("#{name}_element")
    (element && element.options) ? element.options.collect(&:text) : []
  end
end 

1 个答案:

答案 0 :(得分:1)

选择列表似乎具有最多的标识属性,因此我将其用作窗口小部件的基本元素。所有其他元素,即按钮和列表项,都需要相对于选择列表定位。在这种情况下,它们都共享相同的div.form-group祖先。

小部件可以定义为:

class BoolList < PageObject::Elements::SelectList
  def select(value)
    dropdown_toggle_element.click
    option = span_element(xpath: "./..//span[.='#{value}']")
    option.when_visible
    option.click
  end

  def dropdown_toggle_element
    button_element(xpath: './../div/button')
  end

  def self.accessor_methods(widget, name)
    widget.send('define_method', "#{name}_btn_element") do
      self.send("#{name}_element").dropdown_toggle_element
    end

    widget.send('define_method', "#{name}?") do
      self.send("#{name}_btn_element").exists?
    end

    widget.send('define_method', name) do
      self.send("#{name}_element").value
    end

    widget.send('define_method', "#{name}=") do |value|
      self.send("#{name}_element").select(value)
    end

    widget.send('define_method', "#{name}_options") do
      # Since the element is not displayed, we need to check the inner HTML
      element = self.send("#{name}_element")
      (element && element.options) ? element.options.map { |o| o.element.inner_html } : []
    end
  end
end
PageObject.register_widget :bool_list, BoolList, :select

请注意,所有定位器都与选择列表有关。同样,请注意我们使用accessor_methods将额外的方法添加到页面对象。

然后,页面对象将使用bool_list访问器方法。请注意,标识符用于定位select元素,我们说这将是小部件的基本元素。

class MyPage
  include PageObject

  bool_list(:gender, title: 'Gender')
  bool_list(:nationality, title: 'Nationality')
end

该页面现在可以调用以下方法:

page.gender_btn_element.click
page.gender_btn_element.exists?
page.gender
page.gender = 'Female'
page.gender_options

page.nationality_btn_element.click
page.nationality_btn_element.exists?
page.nationality
page.nationality = 'Barbados'
page.nationality_options